diff options
Diffstat (limited to 'arch/arm64')
319 files changed, 27334 insertions, 3350 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index bc3f00f586f1..111742126897 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -4,18 +4,19 @@ config ARM64 select ACPI_GENERIC_GSI if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ACPI_MCFG if ACPI + select ACPI_SPCR_TABLE if ACPI + select ARCH_CLOCKSOURCE_DATA select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI - select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_GCOV_PROFILE_ALL + select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_KCOV select ARCH_HAS_SG_CHAIN select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_USE_CMPXCHG_LOCKREF select ARCH_SUPPORTS_ATOMIC_RMW select ARCH_SUPPORTS_NUMA_BALANCING - select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_COMPAT_IPC_PARSE_VERSION select ARCH_WANT_FRAME_POINTERS select ARCH_HAS_UBSAN_SANITIZE_ALL @@ -51,6 +52,7 @@ config ARM64 select GENERIC_TIME_VSYSCALL select HANDLE_DOMAIN_IRQ select HARDIRQS_SW_RESEND + select HAVE_ACPI_APEI if (ACPI && EFI) select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_BITREVERSE @@ -102,14 +104,13 @@ config ARM64 select NO_BOOTMEM select OF select OF_EARLY_FLATTREE - select OF_NUMA if NUMA && OF select OF_RESERVED_MEM select PCI_ECAM if ACPI - select PERF_USE_VMALLOC select POWER_RESET select POWER_SUPPLY select SPARSE_IRQ select SYSCTL_EXCEPTION_TRACE + select THREAD_INFO_IN_TASK help ARM 64-bit (AArch64) Linux support. @@ -122,6 +123,9 @@ config ARCH_PHYS_ADDR_T_64BIT config MMU def_bool y +config DEBUG_RODATA + def_bool y + config ARM64_PAGE_SHIFT int default 16 if ARM64_64K_PAGES @@ -236,6 +240,9 @@ config PGTABLE_LEVELS default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47 default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48 +config ARCH_SUPPORTS_UPROBES + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -415,18 +422,13 @@ config ARM64_ERRATUM_845719 config ARM64_ERRATUM_843419 bool "Cortex-A53: 843419: A load or store might access an incorrect address" - depends on MODULES default y - select ARM64_MODULE_CMODEL_LARGE + select ARM64_MODULE_CMODEL_LARGE if MODULES help - This option builds kernel modules using the large memory model in - order to avoid the use of the ADRP instruction, which can cause - a subsequent memory access to use an incorrect address on Cortex-A53 - parts up to r0p4. - - Note that the kernel itself must be linked with a version of ld - which fixes potentially affected ADRP instructions through the - use of veneers. + This option links the kernel with '--fix-cortex-a53-843419' and + builds modules using the large memory model in order to avoid the use + of the ADRP instruction, which can cause a subsequent memory access + to use an incorrect address on Cortex-A53 parts up to r0p4. If unsure, say Y. @@ -582,7 +584,8 @@ config HOTPLUG_CPU # Common NUMA Features config NUMA bool "Numa Memory Allocation and Scheduler Support" - depends on SMP + select ACPI_NUMA if ACPI + select OF_NUMA help Enable NUMA (Non Uniform Memory Access) support. @@ -603,11 +606,18 @@ config USE_PERCPU_NUMA_NODE_ID def_bool y depends on NUMA +config HAVE_SETUP_PER_CPU_AREA + def_bool y + depends on NUMA + +config NEED_PER_CPU_EMBED_FIRST_CHUNK + def_bool y + depends on NUMA + source kernel/Kconfig.preempt source kernel/Kconfig.hz config ARCH_SUPPORTS_DEBUG_PAGEALLOC - depends on !HIBERNATION def_bool y config ARCH_HAS_HOLES_MEMORYMODEL @@ -785,6 +795,14 @@ config SETEND_EMULATION If unsure, say Y endif +config ARM64_SW_TTBR0_PAN + bool "Emulate Privileged Access Never using TTBR0_EL1 switching" + help + Enabling this option prevents the kernel from accessing + user-space memory directly by pointing TTBR0_EL1 to a reserved + zeroed area and reserved ASID. The user access routines + restore the valid TTBR0_EL1 temporarily. + menu "ARMv8.1 architectural features" config ARM64_HW_AFDBM @@ -910,7 +928,7 @@ config RANDOMIZE_BASE config RANDOMIZE_MODULE_REGION_FULL bool "Randomize the module region independently from the core kernel" - depends on RANDOMIZE_BASE + depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE default y help Randomizes the location of the module region without considering the diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug index 0cc758cdd0dc..d1ebd46872fd 100644 --- a/arch/arm64/Kconfig.debug +++ b/arch/arm64/Kconfig.debug @@ -2,9 +2,13 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config ARM64_PTDUMP +config ARM64_PTDUMP_CORE + def_bool n + +config ARM64_PTDUMP_DEBUGFS bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL + select ARM64_PTDUMP_CORE select DEBUG_FS help Say Y here if you want to show the kernel pagetable layout in a @@ -38,6 +42,35 @@ config ARM64_RANDOMIZE_TEXT_OFFSET of TEXT_OFFSET and platforms must not require a specific value. +config DEBUG_WX + bool "Warn on W+X mappings at boot" + select ARM64_PTDUMP_CORE + ---help--- + Generate a warning if any W+X mappings are found at boot. + + This is useful for discovering cases where the kernel is leaving + W+X mappings after applying NX, as such mappings are a security risk. + This check also includes UXN, which should be set on all kernel + mappings. + + Look for a message in dmesg output like this: + + arm64/mm: Checked W+X mappings: passed, no W+X pages found. + + or like this, if the check failed: + + arm64/mm: Checked W+X mappings: FAILED, <N> W+X pages found. + + Note that even if the check fails, your kernel is possibly + still fine, as W+X mappings are not a security hole in + themselves, what they do is that they make the exploitation + of other unfixed kernel bugs easier. + + There is no runtime or memory usage effect of this option + once the kernel has booted up - it's a one time check. + + If in doubt, say "Y". + config DEBUG_SET_MODULE_RONX bool "Set loadable kernel module data as NX and text as RO" depends on MODULES @@ -49,16 +82,6 @@ config DEBUG_SET_MODULE_RONX If in doubt, say Y. -config DEBUG_RODATA - bool "Make kernel text and rodata read-only" - default y - help - If this is set, kernel text and rodata will be made read-only. This - is to help catch accidental or malicious attempts to change the - kernel's executable code. - - If in doubt, say Y. - config DEBUG_ALIGN_RODATA depends on DEBUG_RODATA bool "Align linker sections up to SECTION_SIZE" diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index be5d824ebdba..715ef1256838 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -3,6 +3,8 @@ menu "Platform selection" config ARCH_SUNXI bool "Allwinner sunxi 64-bit SoC Family" select GENERIC_IRQ_CHIP + select PINCTRL + select PINCTRL_SUN50I_A64 help This enables support for Allwinner sunxi based SoCs like the A64. @@ -15,8 +17,8 @@ config ARCH_ALPINE config ARCH_BCM2835 bool "Broadcom BCM2835 family" - select ARCH_REQUIRE_GPIOLIB select CLKSRC_OF + select GPIOLIB select PINCTRL select PINCTRL_BCM2835 select ARM_AMBA @@ -29,19 +31,26 @@ config ARCH_BCM2835 config ARCH_BCM_IPROC bool "Broadcom iProc SoC Family" select COMMON_CLK_IPROC + select GPIOLIB select PINCTRL - select ARCH_REQUIRE_GPIOLIB help This enables support for Broadcom iProc based SoCs config ARCH_BERLIN bool "Marvell Berlin SoC Family" - select ARCH_REQUIRE_GPIOLIB select DW_APB_ICTL + select GPIOLIB select PINCTRL help This enables support for Marvell Berlin SoC Family +config ARCH_BRCMSTB + bool "Broadcom Set-Top-Box SoCs" + select BRCMSTB_L2_IRQ + select GENERIC_IRQ_CHIP + help + This enables support for Broadcom's ARMv8 Set Top Box SoCs + config ARCH_EXYNOS bool "ARMv8 based Samsung Exynos SoC family" select COMMON_CLK_SAMSUNG @@ -55,6 +64,7 @@ config ARCH_EXYNOS config ARCH_LAYERSCAPE bool "ARMv8 based Freescale Layerscape SoC family" + select EDAC_SUPPORT help This enables support for the Freescale Layerscape SoC family. @@ -67,6 +77,7 @@ config ARCH_HISI bool "Hisilicon SoC Family" select ARM_TIMER_SP804 select HISILICON_IRQ_MBIGEN if PCI + select PINCTRL help This enables support for Hisilicon ARMv8 SoC family @@ -93,6 +104,7 @@ config ARCH_MVEBU select ARMADA_CP110_SYSCON select ARMADA_37XX_CLK select MVEBU_ODMI + select MVEBU_PIC help This enables support for Marvell EBU familly, including: - Armada 3700 SoC Family @@ -101,6 +113,7 @@ config ARCH_MVEBU config ARCH_QCOM bool "Qualcomm Platforms" + select GPIOLIB select PINCTRL help This enables support for the ARMv8 based Qualcomm chipsets. @@ -108,7 +121,7 @@ config ARCH_QCOM config ARCH_ROCKCHIP bool "Rockchip Platforms" select ARCH_HAS_RESET_CONTROLLER - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select PINCTRL select PINCTRL_ROCKCHIP select ROCKCHIP_TIMER @@ -131,6 +144,7 @@ config ARCH_RENESAS select PM select PM_GENERIC_DOMAINS select RENESAS_IRQC + select SOC_BUS help This enables support for the ARMv8 based Renesas SoCs. @@ -154,13 +168,14 @@ config ARCH_STRATIX10 config ARCH_TEGRA bool "NVIDIA Tegra SoC Family" select ARCH_HAS_RESET_CONTROLLER - select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP select CLKSRC_MMIO select CLKSRC_OF select GENERIC_CLOCKEVENTS - select HAVE_CLK + select GPIOLIB select PINCTRL + select PM + select PM_GENERIC_DOMAINS select RESET_CONTROLLER help This enables support for the NVIDIA Tegra SoC family. @@ -177,14 +192,15 @@ config ARCH_THUNDER config ARCH_UNIPHIER bool "Socionext UniPhier SoC Family" + select ARCH_HAS_RESET_CONTROLLER select PINCTRL help This enables support for Socionext UniPhier SoC family. config ARCH_VEXPRESS bool "ARMv8 software model (Versatile Express)" - select ARCH_REQUIRE_GPIOLIB select COMMON_CLK_VERSATILE + select GPIOLIB select PM select PM_GENERIC_DOMAINS select POWER_RESET_VEXPRESS @@ -204,6 +220,11 @@ config ARCH_XGENE help This enables support for AppliedMicro X-Gene SOC Family +config ARCH_ZX + bool "ZTE ZX SoC Family" + help + This enables support for ZTE ZX SoC Family + config ARCH_ZYNQMP bool "Xilinx ZynqMP Family" help diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 5b54f8c021d8..b9a4a934ca05 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -15,7 +15,15 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) GZFLAGS :=-9 ifneq ($(CONFIG_RELOCATABLE),) -LDFLAGS_vmlinux += -pie -Bsymbolic +LDFLAGS_vmlinux += -pie -shared -Bsymbolic +endif + +ifeq ($(CONFIG_ARM64_ERRATUM_843419),y) + ifeq ($(call ld-option, --fix-cortex-a53-843419),) +$(warning ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum) + else +LDFLAGS_vmlinux += --fix-cortex-a53-843419 + endif endif KBUILD_DEFCONFIG := defconfig @@ -29,19 +37,27 @@ $(warning LSE atomics not supported by binutils) endif endif -KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) +brokengasinst := $(call as-instr,1:\n.inst 0\n.rept . - 1b\n\nnop\n.endr\n,,-DCONFIG_BROKEN_GAS_INST=1) + +ifneq ($(brokengasinst),) +$(warning Detected assembler with broken .inst; disassembly will be unreliable) +endif + +KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads) -KBUILD_AFLAGS += $(lseinstr) +KBUILD_AFLAGS += $(lseinstr) $(brokengasinst) ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) KBUILD_CPPFLAGS += -mbig-endian AS += -EB LD += -EB +UTS_MACHINE := aarch64_be else KBUILD_CPPFLAGS += -mlittle-endian AS += -EL LD += -EL +UTS_MACHINE := aarch64 endif CHECKFLAGS += -D__aarch64__ diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 6e199c903676..080232b0270e 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -1,4 +1,5 @@ dts-dirs += al +dts-dirs += allwinner dts-dirs += altera dts-dirs += amd dts-dirs += amlogic @@ -19,6 +20,7 @@ dts-dirs += socionext dts-dirs += sprd dts-dirs += xilinx dts-dirs += lg +dts-dirs += zte subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile new file mode 100644 index 000000000000..1e29a5ae8282 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts new file mode 100644 index 000000000000..790d14daaa6a --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 ARM Ltd. + * + * 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "sun50i-a64-pine64.dts" + +/ { + model = "Pine64+"; + compatible = "pine64,pine64-plus", "allwinner,sun50i-a64"; + + /* TODO: Camera, Ethernet PHY, touchscreen, etc. */ +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts new file mode 100644 index 000000000000..47095909d9d6 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 ARM Ltd. + * + * 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "sun50i-a64.dtsi" + +/ { + model = "Pine64"; + compatible = "pine64,pine64", "allwinner,sun50i-a64"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&i2c1_pins { + bias-pull-up; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi new file mode 100644 index 000000000000..e0dcab8eb035 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2016 ARM Ltd. + * based on the Allwinner H3 dtsi: + * Copyright (C) 2015 Jens Kuske <jenskuske@gmail.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. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/pinctrl/sun4i-a10.h> + +/ { + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + }; + }; + + osc24M: osc24M_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + + osc32k: osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "osc32k"; + }; + + psci { + compatible = "arm,psci-0.2"; + 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)>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + ccu: clock@01c20000 { + compatible = "allwinner,sun50i-a64-ccu"; + reg = <0x01c20000 0x400>; + clocks = <&osc24M>, <&osc32k>; + clock-names = "hosc", "losc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pio: pinctrl@1c20800 { + compatible = "allwinner,sun50i-a64-pinctrl"; + reg = <0x01c20800 0x400>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu 58>; + gpio-controller; + #gpio-cells = <3>; + interrupt-controller; + #interrupt-cells = <3>; + + i2c1_pins: i2c1_pins { + pins = "PH2", "PH3"; + function = "i2c1"; + }; + + uart0_pins_a: uart0@0 { + pins = "PB8", "PB9"; + function = "uart0"; + }; + }; + + uart0: serial@1c28000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28000 0x400>; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&ccu 67>; + resets = <&ccu 46>; + status = "disabled"; + }; + + uart1: serial@1c28400 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28400 0x400>; + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&ccu 68>; + resets = <&ccu 47>; + status = "disabled"; + }; + + uart2: serial@1c28800 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28800 0x400>; + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&ccu 69>; + resets = <&ccu 48>; + status = "disabled"; + }; + + uart3: serial@1c28c00 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28c00 0x400>; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&ccu 70>; + resets = <&ccu 49>; + status = "disabled"; + }; + + uart4: serial@1c29000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c29000 0x400>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&ccu 71>; + resets = <&ccu 50>; + status = "disabled"; + }; + + i2c0: i2c@1c2ac00 { + compatible = "allwinner,sun6i-a31-i2c"; + reg = <0x01c2ac00 0x400>; + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu 63>; + resets = <&ccu 42>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c@1c2b000 { + compatible = "allwinner,sun6i-a31-i2c"; + reg = <0x01c2b000 0x400>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu 64>; + resets = <&ccu 43>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c@1c2b400 { + compatible = "allwinner,sun6i-a31-i2c"; + reg = <0x01c2b400 0x400>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu 65>; + resets = <&ccu 44>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + gic: interrupt-controller@1c81000 { + compatible = "arm,gic-400"; + reg = <0x01c81000 0x1000>, + <0x01c82000 0x2000>, + <0x01c84000 0x2000>, + <0x01c86000 0x2000>; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + rtc: rtc@1f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile index 47ec703cb230..0d7bfbf7d922 100644 --- a/arch/arm64/boot/dts/amlogic/Makefile +++ b/arch/arm64/boot/dts/amlogic/Makefile @@ -1,9 +1,17 @@ +dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p200.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxl-nexbox-a95x.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-q200.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-q201.dtb +dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi new file mode 100644 index 000000000000..7a078bef04cd --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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. + */ + +/* Common DTSI for same Amlogic Q200/Q201 and P230/P231 boards using either + * the pin-compatible S912 (GXM) or S905D (GXL) SoCs. + */ + +/ { + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + vddio_boot: regulator-vddio_boot { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddao_3v3: regulator-vddao_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; +}; + +/* This UART is brought out to the DB9 connector */ +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +/* Wireless SDIO Module */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_FCLK_DIV4>; + clock-names = "clkin0"; +}; + +ðmac { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi new file mode 100644 index 000000000000..eada0b58ba1c --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2016 Andreas Färber + * + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + 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"; + }; + }; + + 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-0.2"; + method = "smc"; + }; + + 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>; + }; + + firmware { + sm: secure-monitor { + compatible = "amlogic,meson-gx-sm", "amlogic,meson-gxbb-sm"; + }; + }; + + efuse: efuse { + compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse"; + #address-cells = <1>; + #size-cells = <1>; + + sn: sn@14 { + reg = <0x14 0x10>; + }; + + eth_mac: eth_mac@34 { + reg = <0x34 0x10>; + }; + + bid: bid@46 { + reg = <0x46 0x30>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cbus: cbus@c1100000 { + compatible = "simple-bus"; + reg = <0x0 0xc1100000 0x0 0x100000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>; + + reset: reset-controller@4404 { + compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset"; + reg = <0x0 0x04404 0x0 0x20>; + #reset-cells = <1>; + }; + + uart_A: serial@84c0 { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x84c0 0x0 0x14>; + interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>; + status = "disabled"; + }; + + uart_B: serial@84dc { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x84dc 0x0 0x14>; + interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>; + status = "disabled"; + }; + + i2c_A: i2c@8500 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x08500 0x0 0x20>; + interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + pwm_ab: pwm@8550 { + compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm"; + reg = <0x0 0x08550 0x0 0x10>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_cd: pwm@8650 { + compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm"; + reg = <0x0 0x08650 0x0 0x10>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ef: pwm@86c0 { + compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm"; + reg = <0x0 0x086c0 0x0 0x10>; + #pwm-cells = <3>; + status = "disabled"; + }; + + uart_C: serial@8700 { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x8700 0x0 0x14>; + interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>; + status = "disabled"; + }; + + i2c_B: i2c@87c0 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x087c0 0x0 0x20>; + interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c_C: i2c@87e0 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x087e0 0x0 0x20>; + interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + watchdog@98d0 { + compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt"; + reg = <0x0 0x098d0 0x0 0x10>; + clocks = <&xtal>; + }; + }; + + gic: interrupt-controller@c4301000 { + compatible = "arm,gic-400"; + reg = <0x0 0xc4301000 0 0x1000>, + <0x0 0xc4302000 0 0x2000>, + <0x0 0xc4304000 0 0x2000>, + <0x0 0xc4306000 0 0x2000>; + interrupt-controller; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; + #interrupt-cells = <3>; + #address-cells = <0>; + }; + + aobus: aobus@c8100000 { + compatible = "simple-bus"; + reg = <0x0 0xc8100000 0x0 0x100000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>; + + uart_AO: serial@4c0 { + compatible = "amlogic,meson-uart"; + reg = <0x0 0x004c0 0x0 0x14>; + interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>; + clocks = <&xtal>; + status = "disabled"; + }; + + ir: ir@580 { + compatible = "amlogic,meson-gxbb-ir"; + reg = <0x0 0x00580 0x0 0x40>; + interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + }; + }; + + periphs: periphs@c8834000 { + compatible = "simple-bus"; + reg = <0x0 0xc8834000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>; + + rng { + compatible = "amlogic,meson-rng"; + reg = <0x0 0x0 0x0 0x4>; + }; + }; + + + hiubus: hiubus@c883c000 { + compatible = "simple-bus"; + reg = <0x0 0xc883c000 0x0 0x2000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>; + + mailbox: mailbox@404 { + compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu"; + reg = <0 0x404 0 0x4c>; + interrupts = <0 208 IRQ_TYPE_EDGE_RISING>, + <0 209 IRQ_TYPE_EDGE_RISING>, + <0 210 IRQ_TYPE_EDGE_RISING>; + #mbox-cells = <1>; + }; + }; + + ethmac: ethernet@c9410000 { + compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac"; + reg = <0x0 0xc9410000 0x0 0x10000 + 0x0 0xc8834540 0x0 0x4>; + interrupts = <0 8 1>; + interrupt-names = "macirq"; + phy-mode = "rgmii"; + status = "disabled"; + }; + + apb: apb@d0000000 { + compatible = "simple-bus"; + reg = <0x0 0xd0000000 0x0 0x200000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>; + + sd_emmc_a: mmc@70000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x70000 0x0 0x2000>; + interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + }; + + sd_emmc_b: mmc@72000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x72000 0x0 0x2000>; + interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + }; + + sd_emmc_c: mmc@74000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x74000 0x0 0x2000>; + interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; + }; + }; + + vpu: vpu@d0100000 { + compatible = "amlogic,meson-gx-vpu"; + reg = <0x0 0xd0100000 0x0 0x100000>, + <0x0 0xc883c000 0x0 0x1000>, + <0x0 0xc8838000 0x0 0x1000>; + reg-names = "vpu", "hhi", "dmc"; + interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + + /* CVBS VDAC output port */ + cvbs_vdac_port: port@0 { + reg = <0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts new file mode 100644 index 000000000000..4cbd626a9e88 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Neil Armstrong <narmstrong@kernel.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxbb.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + compatible = "nexbox,a95x", "amlogic,meson-gxbb"; + model = "NEXBOX A95X"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; + }; + + leds { + compatible = "gpio-leds"; + blue { + label = "a95x:system-status"; + gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + button@0 { + label = "reset"; + linux,code = <KEY_RESTART>; + gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>; + }; + }; + + vddio_card: gpio-regulator { + compatible = "regulator-gpio"; + + regulator-name = "VDDIO_CARD"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + + /* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */ + states = <1800000 0 + 3300000 1>; + }; + + vddio_boot: regulator-vddio_boot { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddao_3v3: regulator-vddao_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; + + cvbs-connector { + compatible = "composite-video-connector"; + + port { + cvbs_connector_in: endpoint { + remote-endpoint = <&cvbs_vdac_out>; + }; + }; + }; +}; + +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +ðmac { + status = "okay"; + pinctrl-0 = <ð_rmii_pins>; + pinctrl-names = "default"; + phy-mode = "rmii"; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +/* Wireless SDIO Module */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_card>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_FCLK_DIV4>; + clock-names = "clkin0"; +}; + +&cvbs_vdac_port { + cvbs_vdac_out: endpoint { + remote-endpoint = <&cvbs_connector_in>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts index 90a84c514d3d..238fbeacd330 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts @@ -64,6 +64,18 @@ reg = <0x0 0x0 0x0 0x80000000>; }; + usb_otg_pwr: regulator-usb-pwrs { + compatible = "regulator-fixed"; + + regulator-name = "USB_OTG_PWR"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + leds { compatible = "gpio-leds"; blue { @@ -73,6 +85,56 @@ default-state = "off"; }; }; + + tflash_vdd: regulator-tflash_vdd { + /* + * signal name from schematics: TFLASH_VDD_EN + */ + compatible = "regulator-fixed"; + + regulator-name = "TFLASH_VDD"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + tf_io: gpio-regulator-tf_io { + compatible = "regulator-gpio"; + + regulator-name = "TF_IO"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + /* + * signal name from schematics: TF_3V3N_1V8_EN + */ + gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; + gpios-states = <0>; + + states = <3300000 0 + 1800000 1>; + }; + + vcc1v8: regulator-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcc3v3: regulator-vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; }; &uart_AO { @@ -83,7 +145,73 @@ ðmac { status = "okay"; - pinctrl-0 = <ð_pins>; + pinctrl-0 = <ð_rgmii_pins>; + pinctrl-names = "default"; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +&i2c_A { + status = "okay"; + pinctrl-0 = <&i2c_a_pins>; + pinctrl-names = "default"; +}; + +&usb0_phy { + status = "okay"; + phy-supply = <&usb_otg_pwr>; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* SD */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&tflash_vdd>; + vqmmc-supply = <&tf_io>; }; +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc3v3>; + vqmmc-supply = <&vcc1v8>; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts index 62979076e250..03e3d76626dd 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts @@ -50,3 +50,9 @@ compatible = "amlogic,p200", "amlogic,meson-gxbb"; model = "Amlogic Meson GXBB P200 Development Board"; }; + +&i2c_B { + status = "okay"; + pinctrl-0 = <&i2c_b_pins>; + pinctrl-names = "default"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi index f4f30f674b4c..4a96e0f6f926 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi @@ -57,6 +57,84 @@ device_type = "memory"; reg = <0x0 0x0 0x0 0x40000000>; }; + + usb_pwr: regulator-usb-pwrs { + compatible = "regulator-fixed"; + + regulator-name = "USB_PWR"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + /* signal name in schematic: USB_PWR_EN */ + gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vddio_card: gpio-regulator { + compatible = "regulator-gpio"; + + regulator-name = "VDDIO_CARD"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + + /* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */ + states = <1800000 0 + 3300000 1>; + }; + + vddio_boot: regulator-vddio_boot { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddao_3v3: regulator-vddao_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; + + cvbs-connector { + compatible = "composite-video-connector"; + + port { + cvbs_connector_in: endpoint { + remote-endpoint = <&cvbs_vdac_out>; + }; + }; + }; }; /* This UART is brought out to the DB9 connector */ @@ -68,7 +146,107 @@ ðmac { status = "okay"; - pinctrl-0 = <ð_pins>; + pinctrl-0 = <ð_rgmii_pins>; + pinctrl-names = "default"; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +&usb0_phy { + status = "okay"; + phy-supply = <&usb_pwr>; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* Wireless SDIO Module */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins>; pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; }; +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_card>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_FCLK_DIV4>; + clock-names = "clkin0"; +}; + +&cvbs_vdac_port { + cvbs_vdac_out: endpoint { + remote-endpoint = <&cvbs_connector_in>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi index 54bb7c739089..e59ad308192f 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi @@ -52,6 +52,52 @@ chosen { stdout-path = "serial0:115200n8"; }; + + usb_vbus: regulator-usb0-vbus { + compatible = "regulator-fixed"; + + regulator-name = "USB0_VBUS"; + + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_1v8: regulator-vcc_1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>, + <&gpio GPIOX_20 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; }; &uart_AO { @@ -60,3 +106,103 @@ pinctrl-names = "default"; }; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +ðmac { + status = "okay"; + pinctrl-0 = <ð_rgmii_pins>; + pinctrl-names = "default"; +}; + +&usb0_phy { + status = "okay"; + phy-supply = <&usb_vbus>; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +/* Wireless SDIO Module */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins &sdio_irq_pins>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vcc_1v8>; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vcc_3v3>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vmmcq-sumpply = <&vcc_1v8>; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_FCLK_DIV4>; + clock-names = "clkin0"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi index bf6c8d051002..596240c38a9c 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi @@ -40,307 +40,473 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/interrupt-controller/irq.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> +#include "meson-gx.dtsi" #include <dt-bindings/gpio/meson-gxbb-gpio.h> #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> +#include <dt-bindings/clock/gxbb-clkc.h> +#include <dt-bindings/clock/gxbb-aoclkc.h> +#include <dt-bindings/reset/gxbb-aoclkc.h> / { compatible = "amlogic,meson-gxbb"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - cpus { - #address-cells = <0x2>; - #size-cells = <0x0>; + scpi { + compatible = "amlogic,meson-gxbb-scpi", "arm,scpi-pre-1.0"; + mboxes = <&mailbox 1 &mailbox 2>; + shmem = <&cpu_scp_lpri &cpu_scp_hpri>; - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x0>; - enable-method = "psci"; + clocks { + compatible = "arm,scpi-clocks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm,scpi-dvfs-clocks"; + #clock-cells = <1>; + clock-indices = <0>; + clock-output-names = "vcpu"; + }; }; - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x1>; - enable-method = "psci"; + scpi_sensors: sensors { + compatible = "arm,scpi-sensors"; + #thermal-sensor-cells = <1>; }; + }; - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x2>; - enable-method = "psci"; + soc { + usb0_phy: phy@c0000000 { + compatible = "amlogic,meson-gxbb-usb2-phy"; + #phy-cells = <0>; + reg = <0x0 0xc0000000 0x0 0x20>; + resets = <&reset RESET_USB_OTG>; + clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>; + clock-names = "usb_general", "usb"; + status = "disabled"; }; - cpu3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a53", "arm,armv8"; - reg = <0x0 0x3>; - enable-method = "psci"; + usb1_phy: phy@c0000020 { + compatible = "amlogic,meson-gxbb-usb2-phy"; + #phy-cells = <0>; + reg = <0x0 0xc0000020 0x0 0x20>; + resets = <&reset RESET_USB_OTG>; + clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>; + clock-names = "usb_general", "usb"; + status = "disabled"; + }; + + sram: sram@c8000000 { + compatible = "amlogic,meson-gxbb-sram", "mmio-sram"; + reg = <0x0 0xc8000000 0x0 0x14000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0xc8000000 0x14000>; + + cpu_scp_lpri: scp-shmem@0 { + compatible = "amlogic,meson-gxbb-scp-shmem"; + reg = <0x13000 0x400>; + }; + + cpu_scp_hpri: scp-shmem@200 { + compatible = "amlogic,meson-gxbb-scp-shmem"; + reg = <0x13400 0x400>; + }; + }; + + usb0: usb@c9000000 { + compatible = "amlogic,meson-gxbb-usb", "snps,dwc2"; + reg = <0x0 0xc9000000 0x0 0x40000>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_USB0_DDR_BRIDGE>; + clock-names = "otg"; + phys = <&usb0_phy>; + phy-names = "usb2-phy"; + dr_mode = "host"; + status = "disabled"; + }; + + usb1: usb@c9100000 { + compatible = "amlogic,meson-gxbb-usb", "snps,dwc2"; + reg = <0x0 0xc9100000 0x0 0x40000>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc CLKID_USB1_DDR_BRIDGE>; + clock-names = "otg"; + phys = <&usb1_phy>; + phy-names = "usb2-phy"; + dr_mode = "host"; + status = "disabled"; }; }; +}; + +&cpu0 { + clocks = <&scpi_dvfs 0>; +}; + +&cpu1 { + clocks = <&scpi_dvfs 0>; +}; + +&cpu2 { + clocks = <&scpi_dvfs 0>; +}; + +&cpu3 { + clocks = <&scpi_dvfs 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>; +&cbus { + spifc: spi@8c80 { + compatible = "amlogic,meson-gxbb-spifc"; + reg = <0x0 0x08c80 0x0 0x80>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkc CLKID_SPI>; + status = "disabled"; }; +}; + +ðmac { + clocks = <&clkc CLKID_ETH>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_MPLL2>; + clock-names = "stmmaceth", "clkin0", "clkin1"; +}; + +&aobus { + pinctrl_aobus: pinctrl@14 { + compatible = "amlogic,meson-gxbb-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: bank@14 { + reg = <0x0 0x00014 0x0 0x8>, + <0x0 0x0002c 0x0 0x4>, + <0x0 0x00024 0x0 0x8>; + reg-names = "mux", "pull", "gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + uart_ao_a_pins: uart_ao_a { + mux { + groups = "uart_tx_ao_a", "uart_rx_ao_a"; + function = "uart_ao"; + }; + }; + + remote_input_ao_pins: remote_input_ao { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; - psci { - compatible = "arm,psci-0.2"; - method = "smc"; + i2c_ao_pins: i2c_ao { + mux { + groups = "i2c_sck_ao", + "i2c_sda_ao"; + function = "i2c_ao"; + }; + }; + + pwm_ao_a_3_pins: pwm_ao_a_3 { + mux { + groups = "pwm_ao_a_3"; + function = "pwm_ao_a_3"; + }; + }; + + pwm_ao_a_6_pins: pwm_ao_a_6 { + mux { + groups = "pwm_ao_a_6"; + function = "pwm_ao_a_6"; + }; + }; + + pwm_ao_a_12_pins: pwm_ao_a_12 { + mux { + groups = "pwm_ao_a_12"; + function = "pwm_ao_a_12"; + }; + }; + + pwm_ao_b_pins: pwm_ao_b { + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + }; + }; }; - 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)>; + clkc_AO: clock-controller@040 { + compatible = "amlogic,gxbb-aoclkc"; + reg = <0x0 0x00040 0x0 0x4>; + #clock-cells = <1>; + #reset-cells = <1>; }; - xtal: xtal-clk { - compatible = "fixed-clock"; - clock-frequency = <24000000>; - clock-output-names = "xtal"; - #clock-cells = <0>; + pwm_ab_AO: pwm@550 { + compatible = "amlogic,meson-gxbb-pwm"; + reg = <0x0 0x0550 0x0 0x10>; + #pwm-cells = <3>; + status = "disabled"; }; - soc { - compatible = "simple-bus"; + i2c_AO: i2c@500 { + compatible = "amlogic,meson-gxbb-i2c"; + reg = <0x0 0x500 0x0 0x20>; + interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkc CLKID_AO_I2C>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; +}; + +&periphs { + pinctrl_periphs: pinctrl@4b0 { + compatible = "amlogic,meson-gxbb-periphs-pinctrl"; #address-cells = <2>; #size-cells = <2>; ranges; - cbus: cbus@c1100000 { - compatible = "simple-bus"; - reg = <0x0 0xc1100000 0x0 0x100000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>; - - reset: reset-controller@4404 { - compatible = "amlogic,meson-gxbb-reset"; - reg = <0x0 0x04404 0x0 0x20>; - #reset-cells = <1>; + gpio: bank@4b0 { + reg = <0x0 0x004b0 0x0 0x28>, + <0x0 0x004e8 0x0 0x14>, + <0x0 0x00120 0x0 0x14>, + <0x0 0x00430 0x0 0x40>; + reg-names = "mux", "pull", "pull-enable", "gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + emmc_pins: emmc { + mux { + groups = "emmc_nand_d07", + "emmc_cmd", + "emmc_clk", + "emmc_ds"; + function = "emmc"; }; + }; - uart_A: serial@84c0 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x84c0 0x0 0x14>; - interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; - clocks = <&xtal>; - status = "disabled"; + nor_pins: nor { + mux { + groups = "nor_d", + "nor_q", + "nor_c", + "nor_cs"; + function = "nor"; }; + }; - uart_B: serial@84dc { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x84dc 0x0 0x14>; - interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; - clocks = <&xtal>; - status = "disabled"; + sdcard_pins: sdcard { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; }; + }; - uart_C: serial@8700 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x8700 0x0 0x14>; - interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>; - clocks = <&xtal>; - status = "disabled"; + sdio_pins: sdio { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_cmd", + "sdio_clk"; + function = "sdio"; }; }; - gic: interrupt-controller@c4301000 { - compatible = "arm,gic-400"; - reg = <0x0 0xc4301000 0 0x1000>, - <0x0 0xc4302000 0 0x2000>, - <0x0 0xc4304000 0 0x2000>, - <0x0 0xc4306000 0 0x2000>; - interrupt-controller; - interrupts = <GIC_PPI 9 - (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; - #interrupt-cells = <3>; - #address-cells = <0>; - }; - - aobus: aobus@c8100000 { - compatible = "simple-bus"; - reg = <0x0 0xc8100000 0x0 0x100000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>; - - pinctrl_aobus: pinctrl@14 { - compatible = "amlogic,meson-gxbb-aobus-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio_ao: bank@14 { - reg = <0x0 0x00014 0x0 0x8>, - <0x0 0x0002c 0x0 0x4>, - <0x0 0x00024 0x0 0x8>; - reg-names = "mux", "pull", "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - - uart_ao_a_pins: uart_ao_a { - mux { - groups = "uart_tx_ao_a", "uart_rx_ao_a"; - function = "uart_ao"; - }; - }; + sdio_irq_pins: sdio_irq { + mux { + groups = "sdio_irq"; + function = "sdio"; }; + }; - uart_AO: serial@4c0 { - compatible = "amlogic,meson-uart"; - reg = <0x0 0x004c0 0x0 0x14>; - interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>; - clocks = <&xtal>; - status = "disabled"; + uart_a_pins: uart_a { + mux { + groups = "uart_tx_a", + "uart_rx_a"; + function = "uart_a"; }; }; - periphs: periphs@c8834000 { - compatible = "simple-bus"; - reg = <0x0 0xc8834000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>; + uart_b_pins: uart_b { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; - rng { - compatible = "amlogic,meson-rng"; - reg = <0x0 0x0 0x0 0x4>; + uart_c_pins: uart_c { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; }; + }; - pinctrl_periphs: pinctrl@4b0 { - compatible = "amlogic,meson-gxbb-periphs-pinctrl"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - - gpio: bank@4b0 { - reg = <0x0 0x004b0 0x0 0x28>, - <0x0 0x004e8 0x0 0x14>, - <0x0 0x00120 0x0 0x14>, - <0x0 0x00430 0x0 0x40>; - reg-names = "mux", "pull", "pull-enable", "gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - - emmc_pins: emmc { - mux { - groups = "emmc_nand_d07", - "emmc_cmd", - "emmc_clk"; - function = "emmc"; - }; - }; - - sdcard_pins: sdcard { - mux { - groups = "sdcard_d0", - "sdcard_d1", - "sdcard_d2", - "sdcard_d3", - "sdcard_cmd", - "sdcard_clk"; - function = "sdcard"; - }; - }; - - uart_a_pins: uart_a { - mux { - groups = "uart_tx_a", - "uart_rx_a"; - function = "uart_a"; - }; - }; - - uart_b_pins: uart_b { - mux { - groups = "uart_tx_b", - "uart_rx_b"; - function = "uart_b"; - }; - }; - - uart_c_pins: uart_c { - mux { - groups = "uart_tx_c", - "uart_rx_c"; - function = "uart_c"; - }; - }; - - eth_pins: eth_c { - mux { - groups = "eth_mdio", - "eth_mdc", - "eth_clk_rx_clk", - "eth_rx_dv", - "eth_rxd0", - "eth_rxd1", - "eth_rxd2", - "eth_rxd3", - "eth_rgmii_tx_clk", - "eth_tx_en", - "eth_txd0", - "eth_txd1", - "eth_txd2", - "eth_txd3"; - function = "eth"; - }; - }; + i2c_a_pins: i2c_a { + mux { + groups = "i2c_sck_a", + "i2c_sda_a"; + function = "i2c_a"; }; }; - hiubus: hiubus@c883c000 { - compatible = "simple-bus"; - reg = <0x0 0xc883c000 0x0 0x2000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>; + i2c_b_pins: i2c_b { + mux { + groups = "i2c_sck_b", + "i2c_sda_b"; + function = "i2c_b"; + }; + }; - clkc: clock-controller@0 { - compatible = "amlogic,gxbb-clkc"; - #clock-cells = <1>; - reg = <0x0 0x0 0x0 0x3db>; + i2c_c_pins: i2c_c { + mux { + groups = "i2c_sck_c", + "i2c_sda_c"; + function = "i2c_c"; }; }; - apb: apb@d0000000 { - compatible = "simple-bus"; - reg = <0x0 0xd0000000 0x0 0x200000>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>; + eth_rgmii_pins: eth-rgmii { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_clk_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2", + "eth_rxd3", + "eth_rgmii_tx_clk", + "eth_tx_en", + "eth_txd0", + "eth_txd1", + "eth_txd2", + "eth_txd3"; + function = "eth"; + }; }; - ethmac: ethernet@c9410000 { - compatible = "amlogic,meson6-dwmac", "snps,dwmac"; - reg = <0x0 0xc9410000 0x0 0x10000 - 0x0 0xc8834540 0x0 0x4>; - interrupts = <0 8 1>; - interrupt-names = "macirq"; - clocks = <&xtal>; - clock-names = "stmmaceth"; - phy-mode = "rgmii"; - status = "disabled"; + eth_rmii_pins: eth-rmii { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_clk_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_tx_en", + "eth_txd0", + "eth_txd1"; + function = "eth"; + }; + }; + + pwm_a_x_pins: pwm_a_x { + mux { + groups = "pwm_a_x"; + function = "pwm_a_x"; + }; }; + + pwm_a_y_pins: pwm_a_y { + mux { + groups = "pwm_a_y"; + function = "pwm_a_y"; + }; + }; + + pwm_b_pins: pwm_b { + mux { + groups = "pwm_b"; + function = "pwm_b"; + }; + }; + + pwm_d_pins: pwm_d { + mux { + groups = "pwm_d"; + function = "pwm_d"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + + pwm_f_x_pins: pwm_f_x { + mux { + groups = "pwm_f_x"; + function = "pwm_f_x"; + }; + }; + + pwm_f_y_pins: pwm_f_y { + mux { + groups = "pwm_f_y"; + function = "pwm_f_y"; + }; + }; + }; +}; + +&hiubus { + clkc: clock-controller@0 { + compatible = "amlogic,gxbb-clkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3db>; }; }; + +&i2c_A { + clocks = <&clkc CLKID_I2C>; +}; + +&i2c_B { + clocks = <&clkc CLKID_I2C>; +}; + +&i2c_C { + clocks = <&clkc CLKID_I2C>; +}; + +&sd_emmc_a { + clocks = <&clkc CLKID_SD_EMMC_A>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&sd_emmc_b { + clocks = <&clkc CLKID_SD_EMMC_B>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&sd_emmc_c { + clocks = <&clkc CLKID_SD_EMMC_C>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&vpu { + compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts new file mode 100644 index 000000000000..cea4a3eded9b --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016 Andreas Färber + * Copyright (c) 2016 BayLibre, Inc. + * Author: Neil Armstrong <narmstrong@kernel.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl-s905x.dtsi" + +/ { + compatible = "nexbox,a95x", "amlogic,s905x", "amlogic,meson-gxl"; + model = "NEXBOX A95X (S905X)"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + vddio_card: gpio-regulator { + compatible = "regulator-gpio"; + + regulator-name = "VDDIO_CARD"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + + /* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */ + states = <1800000 0 + 3300000 1>; + }; + + vddio_boot: regulator-vddio_boot { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddao_3v3: regulator-vddao_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + wifi32k: wifi32k { + compatible = "pwm-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; + clocks = <&wifi32k>; + clock-names = "ext_clock"; + }; + + cvbs-connector { + compatible = "composite-video-connector"; + + port { + cvbs_connector_in: endpoint { + remote-endpoint = <&cvbs_vdac_out>; + }; + }; + }; +}; + +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +ðmac { + status = "okay"; + phy-mode = "rmii"; + phy-handle = <&internal_phy>; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +/* Wireless SDIO Module */ +&sd_emmc_a { + status = "okay"; + pinctrl-0 = <&sdio_pins>; + pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + + non-removable; + disable-wp; + + mmc-pwrseq = <&sdio_pwrseq>; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_card>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +&pwm_ef { + status = "okay"; + pinctrl-0 = <&pwm_e_pins>; + pinctrl-names = "default"; + clocks = <&clkc CLKID_FCLK_DIV4>; + clock-names = "clkin0"; +}; + +&cvbs_vdac_port { + cvbs_vdac_out: endpoint { + remote-endpoint = <&cvbs_connector_in>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts new file mode 100644 index 000000000000..f66939cacd37 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl-s905d.dtsi" +#include "meson-gx-p23x-q20x.dtsi" + +/ { + compatible = "amlogic,p230", "amlogic,s905d", "amlogic,meson-gxl"; + model = "Amlogic Meson GXL (S905D) P230 Development Board"; +}; + +/* P230 has exclusive choice between internal or external PHY */ +ðmac { + pinctrl-0 = <ð_pins>; + pinctrl-names = "default"; + + /* Select external PHY by default */ + phy-handle = <&external_phy>; + + /* External PHY reset is shared with internal PHY Led signals */ + snps,reset-gpio = <&gpio GPIOZ_14 0>; + snps,reset-delays-us = <0 10000 1000000>; + snps,reset-active-low; + + /* External PHY is in RGMII */ + phy-mode = "rgmii"; +}; + +&external_mdio { + external_phy: ethernet-phy@0 { + compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22"; + reg = <0>; + max-speed = <1000>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts new file mode 100644 index 000000000000..95992cf1fe61 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl-s905d.dtsi" +#include "meson-gx-p23x-q20x.dtsi" + +/ { + compatible = "amlogic,p231", "amlogic,s905d", "amlogic,meson-gxl"; + model = "Amlogic Meson GXL (S905D) P231 Development Board"; +}; + +/* P231 has only internal PHY port */ +ðmac { + phy-mode = "rmii"; + phy-handle = <&internal_phy>; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi new file mode 100644 index 000000000000..615308e55576 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl.dtsi" + +/ { + compatible = "amlogic,s905d", "amlogic,meson-gxl"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts new file mode 100644 index 000000000000..9639f012b02b --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl-s905x.dtsi" + +/ { + compatible = "amlogic,p212", "amlogic,s905x", "amlogic,meson-gxl"; + model = "Amlogic Meson GXL (S905X) P212 Development Board"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +/* This UART is brought out to the DB9 connector */ +&uart_AO { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi new file mode 100644 index 000000000000..08237ee1e362 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl.dtsi" + +/ { + compatible = "amlogic,s905x", "amlogic,meson-gxl"; +}; + +/* S905X Only has access to its internal PHY */ +ðmac { + phy-mode = "rmii"; + phy-handle = <&internal_phy>; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi new file mode 100644 index 000000000000..69216246275d --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gx.dtsi" +#include <dt-bindings/clock/gxbb-clkc.h> +#include <dt-bindings/gpio/meson-gxl-gpio.h> + +/ { + compatible = "amlogic,meson-gxl"; +}; + +ðmac { + reg = <0x0 0xc9410000 0x0 0x10000 + 0x0 0xc8834540 0x0 0x4>; + + clocks = <&clkc CLKID_ETH>, + <&clkc CLKID_FCLK_DIV2>, + <&clkc CLKID_MPLL2>; + clock-names = "stmmaceth", "clkin0", "clkin1"; + + mdio0: mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + }; +}; + +&aobus { + pinctrl_aobus: pinctrl@14 { + compatible = "amlogic,meson-gxl-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: bank@14 { + reg = <0x0 0x00014 0x0 0x8>, + <0x0 0x0002c 0x0 0x4>, + <0x0 0x00024 0x0 0x8>; + reg-names = "mux", "pull", "gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + uart_ao_a_pins: uart_ao_a { + mux { + groups = "uart_tx_ao_a", "uart_rx_ao_a"; + function = "uart_ao"; + }; + }; + + remote_input_ao_pins: remote_input_ao { + mux { + groups = "remote_input_ao"; + function = "remote_input_ao"; + }; + }; + }; +}; + +&periphs { + pinctrl_periphs: pinctrl@4b0 { + compatible = "amlogic,meson-gxl-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: bank@4b0 { + reg = <0x0 0x004b0 0x0 0x28>, + <0x0 0x004e8 0x0 0x14>, + <0x0 0x00120 0x0 0x14>, + <0x0 0x00430 0x0 0x40>; + reg-names = "mux", "pull", "pull-enable", "gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + emmc_pins: emmc { + mux { + groups = "emmc_nand_d07", + "emmc_cmd", + "emmc_clk", + "emmc_ds"; + function = "emmc"; + }; + }; + + sdcard_pins: sdcard { + mux { + groups = "sdcard_d0", + "sdcard_d1", + "sdcard_d2", + "sdcard_d3", + "sdcard_cmd", + "sdcard_clk"; + function = "sdcard"; + }; + }; + + sdio_pins: sdio { + mux { + groups = "sdio_d0", + "sdio_d1", + "sdio_d2", + "sdio_d3", + "sdio_cmd", + "sdio_clk"; + function = "sdio"; + }; + }; + + sdio_irq_pins: sdio_irq { + mux { + groups = "sdio_irq"; + function = "sdio"; + }; + }; + + uart_a_pins: uart_a { + mux { + groups = "uart_tx_a", + "uart_rx_a"; + function = "uart_a"; + }; + }; + + uart_b_pins: uart_b { + mux { + groups = "uart_tx_b", + "uart_rx_b"; + function = "uart_b"; + }; + }; + + uart_c_pins: uart_c { + mux { + groups = "uart_tx_c", + "uart_rx_c"; + function = "uart_c"; + }; + }; + + i2c_a_pins: i2c_a { + mux { + groups = "i2c_sck_a", + "i2c_sda_a"; + function = "i2c_a"; + }; + }; + + i2c_b_pins: i2c_b { + mux { + groups = "i2c_sck_b", + "i2c_sda_b"; + function = "i2c_b"; + }; + }; + + i2c_c_pins: i2c_c { + mux { + groups = "i2c_sck_c", + "i2c_sda_c"; + function = "i2c_c"; + }; + }; + + eth_pins: eth_c { + mux { + groups = "eth_mdio", + "eth_mdc", + "eth_clk_rx_clk", + "eth_rx_dv", + "eth_rxd0", + "eth_rxd1", + "eth_rxd2", + "eth_rxd3", + "eth_rgmii_tx_clk", + "eth_tx_en", + "eth_txd0", + "eth_txd1", + "eth_txd2", + "eth_txd3"; + function = "eth"; + }; + }; + + pwm_e_pins: pwm_e { + mux { + groups = "pwm_e"; + function = "pwm_e"; + }; + }; + }; + + eth-phy-mux { + compatible = "mdio-mux-mmioreg", "mdio-mux"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x55c 0x0 0x4>; + mux-mask = <0xffffffff>; + mdio-parent-bus = <&mdio0>; + + internal_mdio: mdio@e40908ff { + reg = <0xe40908ff>; + #address-cells = <1>; + #size-cells = <0>; + + internal_phy: ethernet-phy@8 { + compatible = "ethernet-phy-id0181.4400", "ethernet-phy-ieee802.3-c22"; + reg = <8>; + max-speed = <100>; + }; + }; + + external_mdio: mdio@2009087f { + reg = <0x2009087f>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&hiubus { + clkc: clock-controller@0 { + compatible = "amlogic,gxl-clkc", "amlogic,gxbb-clkc"; + #clock-cells = <1>; + reg = <0x0 0x0 0x0 0x3db>; + }; +}; + +&i2c_A { + clocks = <&clkc CLKID_I2C>; +}; + +&i2c_B { + clocks = <&clkc CLKID_I2C>; +}; + +&i2c_C { + clocks = <&clkc CLKID_I2C>; +}; + +&sd_emmc_a { + clocks = <&clkc CLKID_SD_EMMC_A>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&sd_emmc_b { + clocks = <&clkc CLKID_SD_EMMC_B>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&sd_emmc_c { + clocks = <&clkc CLKID_SD_EMMC_C>, + <&xtal>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "core", "clkin0", "clkin1"; +}; + +&vpu { + compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu"; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts new file mode 100644 index 000000000000..5a337d339df1 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxm.dtsi" + +/ { + compatible = "nexbox,a1", "amlogic,s912", "amlogic,meson-gxm"; + model = "NEXBOX A1"; + + aliases { + serial0 = &uart_AO; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + vddio_boot: regulator-vddio-boot { + compatible = "regulator-fixed"; + regulator-name = "VDDIO_BOOT"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vddao_3v3: regulator-vddao-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc_3v3: regulator-vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; + }; + + cvbs-connector { + compatible = "composite-video-connector"; + + port { + cvbs_connector_in: endpoint { + remote-endpoint = <&cvbs_vdac_out>; + }; + }; + }; +}; + +/* This UART is brought out to the DB9 connector */ +&uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; + pinctrl-names = "default"; +}; + +&ir { + status = "okay"; + pinctrl-0 = <&remote_input_ao_pins>; + pinctrl-names = "default"; +}; + +/* SD card */ +&sd_emmc_b { + status = "okay"; + pinctrl-0 = <&sdcard_pins>; + pinctrl-names = "default"; + + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <100000000>; + disable-wp; + + cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; + cd-inverted; + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +/* eMMC */ +&sd_emmc_c { + status = "okay"; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + + bus-width = <8>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <200000000>; + non-removable; + disable-wp; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + + mmc-pwrseq = <&emmc_pwrseq>; + vmmc-supply = <&vcc_3v3>; + vqmmc-supply = <&vddio_boot>; +}; + +ðmac { + status = "okay"; + + pinctrl-0 = <ð_pins>; + pinctrl-names = "default"; + + /* Select external PHY by default */ + phy-handle = <&external_phy>; + + snps,reset-gpio = <&gpio GPIOZ_14 0>; + snps,reset-delays-us = <0 10000 1000000>; + snps,reset-active-low; + + /* External PHY is in RGMII */ + phy-mode = "rgmii"; +}; + +&external_mdio { + external_phy: ethernet-phy@0 { + compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22"; + reg = <0>; + max-speed = <1000>; + }; +}; + +&cvbs_vdac_port { + cvbs_vdac_out: endpoint { + remote-endpoint = <&cvbs_connector_in>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts new file mode 100644 index 000000000000..5dbc66088355 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxm.dtsi" +#include "meson-gx-p23x-q20x.dtsi" + +/ { + compatible = "amlogic,q200", "amlogic,s912", "amlogic,meson-gxm"; + model = "Amlogic Meson GXM (S912) Q200 Development Board"; +}; + +/* Q200 has exclusive choice between internal or external PHY */ +ðmac { + pinctrl-0 = <ð_pins>; + pinctrl-names = "default"; + + /* Select external PHY by default */ + phy-handle = <&external_phy>; + + /* External PHY reset is shared with internal PHY Led signals */ + snps,reset-gpio = <&gpio GPIOZ_14 0>; + snps,reset-delays-us = <0 10000 1000000>; + snps,reset-active-low; + + /* External PHY is in RGMII */ + phy-mode = "rgmii"; +}; + +&external_mdio { + external_phy: ethernet-phy@0 { + compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22"; + reg = <0>; + max-speed = <1000>; + }; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts new file mode 100644 index 000000000000..95e11d7faab8 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxm.dtsi" +#include "meson-gx-p23x-q20x.dtsi" + +/ { + compatible = "amlogic,q201", "amlogic,s912", "amlogic,meson-gxm"; + model = "Amlogic Meson GXM (S912) Q201 Development Board"; +}; + +/* Q201 has only internal PHY port */ +ðmac { + phy-mode = "rmii"; + phy-handle = <&internal_phy>; +}; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi new file mode 100644 index 000000000000..eb2f0c3e5e53 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Endless Computers, Inc. + * Author: Carlo Caione <carlo@endlessm.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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "meson-gxl.dtsi" + +/ { + compatible = "amlogic,meson-gxm"; + + cpus { + 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>; + }; + }; + }; + + cpu4: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu5: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu6: cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + + cpu7: cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + next-level-cache = <&l2>; + }; + }; +}; + +&vpu { + compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu"; +}; diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts index b7fb5d9295c2..32a961c5e98a 100644 --- a/arch/arm64/boot/dts/apm/apm-mustang.dts +++ b/arch/arm64/boot/dts/apm/apm-mustang.dts @@ -74,6 +74,7 @@ &xgenet { status = "ok"; + rxlos-gpios = <&sbgpio 12 1>; }; &mmc0 { diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi index 1425ed41620c..72720e9132a1 100644 --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi @@ -26,6 +26,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_0>; + #clock-cells = <1>; + clocks = <&pmd0clk 0>; }; cpu@001 { device_type = "cpu"; @@ -34,6 +36,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_0>; + #clock-cells = <1>; + clocks = <&pmd0clk 0>; }; cpu@100 { device_type = "cpu"; @@ -42,6 +46,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_1>; + #clock-cells = <1>; + clocks = <&pmd1clk 0>; }; cpu@101 { device_type = "cpu"; @@ -50,6 +56,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_1>; + #clock-cells = <1>; + clocks = <&pmd1clk 0>; }; cpu@200 { device_type = "cpu"; @@ -58,6 +66,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_2>; + #clock-cells = <1>; + clocks = <&pmd2clk 0>; }; cpu@201 { device_type = "cpu"; @@ -66,6 +76,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_2>; + #clock-cells = <1>; + clocks = <&pmd2clk 0>; }; cpu@300 { device_type = "cpu"; @@ -74,6 +86,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_3>; + #clock-cells = <1>; + clocks = <&pmd3clk 0>; }; cpu@301 { device_type = "cpu"; @@ -82,6 +96,8 @@ enable-method = "spin-table"; cpu-release-addr = <0x1 0x0000fff8>; next-level-cache = <&xgene_L2_3>; + #clock-cells = <1>; + clocks = <&pmd3clk 0>; }; xgene_L2_0: l2-cache-0 { compatible = "cache"; @@ -223,6 +239,46 @@ clock-output-names = "refclk"; }; + pmdpll: pmdpll@170000f0 { + compatible = "apm,xgene-pcppll-v2-clock"; + #clock-cells = <1>; + clocks = <&refclk 0>; + reg = <0x0 0x170000f0 0x0 0x10>; + clock-output-names = "pmdpll"; + }; + + pmd0clk: pmd0clk@7e200200 { + compatible = "apm,xgene-pmd-clock"; + #clock-cells = <1>; + clocks = <&pmdpll 0>; + reg = <0x0 0x7e200200 0x0 0x10>; + clock-output-names = "pmd0clk"; + }; + + pmd1clk: pmd1clk@7e200210 { + compatible = "apm,xgene-pmd-clock"; + #clock-cells = <1>; + clocks = <&pmdpll 0>; + reg = <0x0 0x7e200210 0x0 0x10>; + clock-output-names = "pmd1clk"; + }; + + pmd2clk: pmd2clk@7e200220 { + compatible = "apm,xgene-pmd-clock"; + #clock-cells = <1>; + clocks = <&pmdpll 0>; + reg = <0x0 0x7e200220 0x0 0x10>; + clock-output-names = "pmd2clk"; + }; + + pmd3clk: pmd3clk@7e200230 { + compatible = "apm,xgene-pmd-clock"; + #clock-cells = <1>; + clocks = <&pmdpll 0>; + reg = <0x0 0x7e200230 0x0 0x10>; + clock-output-names = "pmd3clk"; + }; + socpll: socpll@17000120 { compatible = "apm,xgene-socpll-v2-clock"; #clock-cells = <1>; @@ -453,6 +509,64 @@ }; }; + pmu: pmu@78810000 { + compatible = "apm,xgene-pmu-v2"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + regmap-csw = <&csw>; + regmap-mcba = <&mcba>; + regmap-mcbb = <&mcbb>; + reg = <0x0 0x78810000 0x0 0x1000>; + interrupts = <0x0 0x22 0x4>; + + pmul3c@7e610000 { + compatible = "apm,xgene-pmu-l3c"; + reg = <0x0 0x7e610000 0x0 0x1000>; + }; + + pmuiob@7e940000 { + compatible = "apm,xgene-pmu-iob"; + reg = <0x0 0x7e940000 0x0 0x1000>; + }; + + pmucmcb@7e710000 { + compatible = "apm,xgene-pmu-mcb"; + reg = <0x0 0x7e710000 0x0 0x1000>; + enable-bit-index = <0>; + }; + + pmucmcb@7e730000 { + compatible = "apm,xgene-pmu-mcb"; + reg = <0x0 0x7e730000 0x0 0x1000>; + enable-bit-index = <1>; + }; + + pmucmc@7e810000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e810000 0x0 0x1000>; + enable-bit-index = <0>; + }; + + pmucmc@7e850000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e850000 0x0 0x1000>; + enable-bit-index = <1>; + }; + + pmucmc@7e890000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e890000 0x0 0x1000>; + enable-bit-index = <2>; + }; + + pmucmc@7e8d0000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e8d0000 0x0 0x1000>; + enable-bit-index = <3>; + }; + }; + mailbox: mailbox@10540000 { compatible = "apm,xgene-slimpro-mbox"; reg = <0x0 0x10540000 0x0 0x8000>; @@ -472,6 +586,11 @@ mboxes = <&mailbox 0>; }; + hwmonslimpro { + compatible = "apm,xgene-slimpro-hwmon"; + mboxes = <&mailbox 7>; + }; + serial0: serial@10600000 { device_type = "serial"; compatible = "ns16550"; @@ -508,10 +627,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 0x10 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 0x11 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 0x12 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 0x13 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 0x10 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 0x11 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 0x12 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 0x13 0x4>; dma-coherent; clocks = <&pcie0clk 0>; msi-parent = <&v2m0>; @@ -533,10 +652,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 0x16 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 0x17 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 0x18 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 0x19 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0x0 0x0 0x16 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0x0 0x0 0x17 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0x0 0x0 0x18 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0x0 0x0 0x19 0x4>; dma-coherent; clocks = <&pcie1clk 0>; msi-parent = <&v2m0>; diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index c29dab9d1834..63be8e51eaa8 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -553,6 +553,64 @@ }; }; + pmu: pmu@78810000 { + compatible = "apm,xgene-pmu-v2"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + regmap-csw = <&csw>; + regmap-mcba = <&mcba>; + regmap-mcbb = <&mcbb>; + reg = <0x0 0x78810000 0x0 0x1000>; + interrupts = <0x0 0x22 0x4>; + + pmul3c@7e610000 { + compatible = "apm,xgene-pmu-l3c"; + reg = <0x0 0x7e610000 0x0 0x1000>; + }; + + pmuiob@7e940000 { + compatible = "apm,xgene-pmu-iob"; + reg = <0x0 0x7e940000 0x0 0x1000>; + }; + + pmucmcb@7e710000 { + compatible = "apm,xgene-pmu-mcb"; + reg = <0x0 0x7e710000 0x0 0x1000>; + enable-bit-index = <0>; + }; + + pmucmcb@7e730000 { + compatible = "apm,xgene-pmu-mcb"; + reg = <0x0 0x7e730000 0x0 0x1000>; + enable-bit-index = <1>; + }; + + pmucmc@7e810000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e810000 0x0 0x1000>; + enable-bit-index = <0>; + }; + + pmucmc@7e850000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e850000 0x0 0x1000>; + enable-bit-index = <1>; + }; + + pmucmc@7e890000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e890000 0x0 0x1000>; + enable-bit-index = <2>; + }; + + pmucmc@7e8d0000 { + compatible = "apm,xgene-pmu-mc"; + reg = <0x0 0x7e8d0000 0x0 0x1000>; + enable-bit-index = <3>; + }; + }; + pcie0: pcie@1f2b0000 { status = "disabled"; device_type = "pci"; @@ -569,10 +627,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x4>; dma-coherent; clocks = <&pcie0clk 0>; msi-parent = <&msi>; @@ -594,10 +652,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x4>; dma-coherent; clocks = <&pcie1clk 0>; msi-parent = <&msi>; @@ -619,10 +677,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x4>; dma-coherent; clocks = <&pcie2clk 0>; msi-parent = <&msi>; @@ -644,10 +702,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x4>; dma-coherent; clocks = <&pcie3clk 0>; msi-parent = <&msi>; @@ -669,10 +727,10 @@ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1 - 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1 - 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1 - 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>; + interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x4 + 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x4 + 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x4 + 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x4>; dma-coherent; clocks = <&pcie4clk 0>; msi-parent = <&msi>; @@ -697,6 +755,11 @@ mboxes = <&mailbox 0>; }; + hwmonslimpro { + compatible = "apm,xgene-slimpro-hwmon"; + mboxes = <&mailbox 7>; + }; + serial0: serial@1c020000 { status = "disabled"; device_type = "serial"; @@ -923,7 +986,7 @@ /* mac address will be overwritten by the bootloader */ local-mac-address = [00 00 00 00 00 00]; phy-connection-type = "rgmii"; - phy-handle = <&menet0phy>,<&menetphy>; + phy-handle = <&menetphy>,<&menet0phy>; mdio { compatible = "apm,xgene-mdio"; #address-cells = <1>; diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index 334271a25f70..7d832247d0db 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -29,6 +29,28 @@ clock-names = "apb_pclk"; }; + smmu_pcie: iommu@2b500000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x2b500000 0x0 0x10000>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + dma-coherent; + status = "disabled"; + }; + + smmu_etr: iommu@2b600000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x2b600000 0x0 0x10000>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + dma-coherent; + status = "disabled"; + }; + gic: interrupt-controller@2c010000 { compatible = "arm,gic-400", "arm,cortex-a15-gic"; reg = <0x0 0x2c010000 0 0x1000>, @@ -146,6 +168,7 @@ etr@20070000 { compatible = "arm,coresight-tmc", "arm,primecell"; reg = <0 0x20070000 0 0x1000>; + iommus = <&smmu_etr 0>; clocks = <&soc_smc50mhz>; clock-names = "apb_pclk"; @@ -393,7 +416,7 @@ #address-cells = <3>; #size-cells = <2>; dma-coherent; - ranges = <0x01000000 0x00 0x5f800000 0x00 0x5f800000 0x0 0x00800000>, + ranges = <0x01000000 0x00 0x00000000 0x00 0x5f800000 0x0 0x00800000>, <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>, <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>; #interrupt-cells = <1>; @@ -404,6 +427,8 @@ <0 0 0 4 &gic 0 0 0 139 4>; msi-parent = <&v2m_0>; status = "disabled"; + iommu-map-mask = <0x0>; /* RC has no means to output PCI RID */ + iommu-map = <0x0 &smmu_pcie 0x0 0x1>; }; scpi { @@ -484,6 +509,48 @@ /include/ "juno-clocks.dtsi" + smmu_dma: iommu@7fb00000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x7fb00000 0x0 0x10000>; + interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + dma-coherent; + status = "disabled"; + }; + + smmu_hdlcd1: iommu@7fb10000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x7fb10000 0x0 0x10000>; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + status = "disabled"; + }; + + smmu_hdlcd0: iommu@7fb20000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x7fb20000 0x0 0x10000>; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + status = "disabled"; + }; + + smmu_usb: iommu@7fb30000 { + compatible = "arm,mmu-401", "arm,smmu-v1"; + reg = <0x0 0x7fb30000 0x0 0x10000>; + interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + #global-interrupts = <1>; + dma-coherent; + status = "disabled"; + }; + dma@7ff00000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x0 0x7ff00000 0 0x1000>; @@ -499,6 +566,15 @@ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&smmu_dma 0>, + <&smmu_dma 1>, + <&smmu_dma 2>, + <&smmu_dma 3>, + <&smmu_dma 4>, + <&smmu_dma 5>, + <&smmu_dma 6>, + <&smmu_dma 7>, + <&smmu_dma 8>; clocks = <&soc_faxiclk>; clock-names = "apb_pclk"; }; @@ -507,6 +583,7 @@ compatible = "arm,hdlcd"; reg = <0 0x7ff50000 0 0x1000>; interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&smmu_hdlcd1 0>; clocks = <&scpi_clk 3>; clock-names = "pxlclk"; @@ -521,6 +598,7 @@ compatible = "arm,hdlcd"; reg = <0 0x7ff60000 0 0x1000>; interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&smmu_hdlcd0 0>; clocks = <&scpi_clk 3>; clock-names = "pxlclk"; @@ -574,6 +652,7 @@ compatible = "generic-ohci"; reg = <0x0 0x7ffb0000 0x0 0x10000>; interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&smmu_usb 0>; clocks = <&soc_usb48mhz>; }; @@ -581,6 +660,7 @@ compatible = "generic-ehci"; reg = <0x0 0x7ffc0000 0x0 0x10000>; interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&smmu_usb 0>; clocks = <&soc_usb48mhz>; }; diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts index 123a58b29cbd..eec37feee8fc 100644 --- a/arch/arm64/boot/dts/arm/juno-r1.dts +++ b/arch/arm64/boot/dts/arm/juno-r1.dts @@ -76,7 +76,7 @@ compatible = "arm,idle-state"; arm,psci-suspend-param = <0x1010000>; local-timer-stop; - entry-latency-us = <300>; + entry-latency-us = <400>; exit-latency-us = <1200>; min-residency-us = <2500>; }; @@ -90,6 +90,7 @@ next-level-cache = <&A57_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A57_1: cpu@1 { @@ -100,6 +101,7 @@ next-level-cache = <&A57_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A53_0: cpu@100 { @@ -110,6 +112,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_1: cpu@101 { @@ -120,6 +123,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_2: cpu@102 { @@ -130,6 +134,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_3: cpu@103 { @@ -140,6 +145,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A57_L2: l2-cache0 { diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts index 007be826efce..28f40ec44090 100644 --- a/arch/arm64/boot/dts/arm/juno-r2.dts +++ b/arch/arm64/boot/dts/arm/juno-r2.dts @@ -76,7 +76,7 @@ compatible = "arm,idle-state"; arm,psci-suspend-param = <0x1010000>; local-timer-stop; - entry-latency-us = <300>; + entry-latency-us = <400>; exit-latency-us = <1200>; min-residency-us = <2500>; }; @@ -90,6 +90,7 @@ next-level-cache = <&A72_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A72_1: cpu@1 { @@ -100,6 +101,7 @@ next-level-cache = <&A72_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A53_0: cpu@100 { @@ -110,6 +112,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <485>; }; A53_1: cpu@101 { @@ -120,6 +123,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <485>; }; A53_2: cpu@102 { @@ -130,6 +134,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <485>; }; A53_3: cpu@103 { @@ -140,6 +145,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <485>; }; A72_L2: l2-cache0 { diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts index a7270eff6939..ac5ceb73f45f 100644 --- a/arch/arm64/boot/dts/arm/juno.dts +++ b/arch/arm64/boot/dts/arm/juno.dts @@ -76,7 +76,7 @@ compatible = "arm,idle-state"; arm,psci-suspend-param = <0x1010000>; local-timer-stop; - entry-latency-us = <300>; + entry-latency-us = <400>; exit-latency-us = <1200>; min-residency-us = <2500>; }; @@ -90,6 +90,7 @@ next-level-cache = <&A57_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A57_1: cpu@1 { @@ -100,6 +101,7 @@ next-level-cache = <&A57_L2>; clocks = <&scpi_dvfs 0>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; }; A53_0: cpu@100 { @@ -110,6 +112,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_1: cpu@101 { @@ -120,6 +123,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_2: cpu@102 { @@ -130,6 +134,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A53_3: cpu@103 { @@ -140,6 +145,7 @@ next-level-cache = <&A53_L2>; clocks = <&scpi_dvfs 1>; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <578>; }; A57_L2: l2-cache0 { diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts index a852e28a40e1..a83ed2c6bbf7 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts @@ -81,7 +81,7 @@ #address-cells = <0>; interrupt-controller; reg = <0x0 0x2c001000 0 0x1000>, - <0x0 0x2c002000 0 0x1000>, + <0x0 0x2c002000 0 0x2000>, <0x0 0x2c004000 0 0x2000>, <0x0 0x2c006000 0 0x2000>; interrupts = <1 9 0xf04>; diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts index 7841b724e340..c309633a1e87 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts @@ -2,6 +2,7 @@ #include "bcm2837.dtsi" #include "bcm2835-rpi.dtsi" #include "bcm283x-rpi-smsc9514.dtsi" +#include "bcm283x-rpi-usb-host.dtsi" / { compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; @@ -15,13 +16,6 @@ act { gpios = <&gpio 47 0>; }; - - pwr { - label = "PWR"; - gpios = <&gpio 35 0>; - default-state = "keep"; - linux,default-trigger = "default-on"; - }; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi index 8216bbb29fe0..19f2fe620a21 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi @@ -1,7 +1,7 @@ #include "bcm283x.dtsi" / { - compatible = "brcm,bcm2836"; + compatible = "brcm,bcm2837"; soc { ranges = <0x7e000000 0x3f000000 0x1000000>, @@ -74,3 +74,9 @@ interrupt-parent = <&local_intc>; interrupts = <8>; }; + +/* enable thermal sensor with the correct compatible property set */ +&thermal { + compatible = "brcm,bcm2837-thermal"; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcm283x-rpi-usb-host.dtsi b/arch/arm64/boot/dts/broadcom/bcm283x-rpi-usb-host.dtsi new file mode 120000 index 000000000000..cbeebe312ff8 --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/bcm283x-rpi-usb-host.dtsi @@ -0,0 +1 @@ +../../../../arm/boot/dts/bcm283x-rpi-usb-host.dtsi
\ No newline at end of file diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts index 2d7872a36b91..de8d379f44e2 100644 --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts @@ -56,6 +56,10 @@ }; }; +&enet { + status = "ok"; +}; + &pci_phy0 { status = "ok"; }; @@ -157,6 +161,10 @@ status = "ok"; }; +&sdio1 { + status = "ok"; +}; + &nand { nandcs@0 { compatible = "brcm,nandcs"; @@ -164,6 +172,8 @@ nand-ecc-mode = "hw"; nand-ecc-strength = <8>; nand-ecc-step-size = <512>; + nand-bus-width = <16>; + brcm,nand-oob-sector-size = <16>; #address-cells = <1>; #size-cells = <1>; }; @@ -172,6 +182,7 @@ &mdio_mux_iproc { mdio@10 { gphy0: eth-phy@10 { + enet-phy-lane-swap; reg = <0x10>; }; }; @@ -185,3 +196,37 @@ groups = "nand_grp"; }; }; + +&qspi { + bspi-sel = <0>; + flash: m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p80"; + reg = <0x0>; + spi-max-frequency = <12500000>; + m25p,fast-read; + spi-cpol; + spi-cpha; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x000a0000>; + }; + + partition@a0000 { + label = "env"; + reg = <0x000a0000 0x00060000>; + }; + + partition@100000 { + label = "system"; + reg = <0x00100000 0x00600000>; + }; + + partition@700000 { + label = "rootfs"; + reg = <0x00700000 0x01900000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index d4a12fad8afd..4fcdeca3a983 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -133,6 +133,9 @@ status = "disabled"; + phys = <&pci_phy0>; + phy-names = "pcie-phy"; + msi-parent = <&msi0>; msi0: msi@20020000 { compatible = "brcm,iproc-msi"; @@ -171,6 +174,9 @@ status = "disabled"; + phys = <&pci_phy1>; + phy-names = "pcie-phy"; + msi-parent = <&msi4>; msi4: msi@50020000 { compatible = "brcm,iproc-msi"; @@ -191,6 +197,54 @@ #include "ns2-clock.dtsi" + enet: ethernet@61000000 { + compatible = "brcm,ns2-amac"; + reg = <0x61000000 0x1000>, + <0x61090000 0x1000>, + <0x61030000 0x100>; + reg-names = "amac_base", "idm_base", "nicpm_base"; + interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>; + phy-handle = <&gphy0>; + phy-mode = "rgmii"; + status = "disabled"; + }; + + pdc0: iproc-pdc0@612c0000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x612c0000 0x445>; /* PDC FS0 regs */ + interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc1: iproc-pdc1@612e0000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x612e0000 0x445>; /* PDC FS1 regs */ + interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc2: iproc-pdc2@61300000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x61300000 0x445>; /* PDC FS2 regs */ + interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + + pdc3: iproc-pdc3@61320000 { + compatible = "brcm,iproc-pdc-mbox"; + reg = <0x61320000 0x445>; /* PDC FS3 regs */ + interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; + #mbox-cells = <1>; + brcm,rx-status-len = <32>; + brcm,use-bcm-hdr; + }; + dma0: dma@61360000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x61360000 0x1000>; @@ -248,7 +302,7 @@ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>; - mmu-masters; + #iommu-cells = <1>; }; pinctrl: pinctrl@6501d130 { @@ -299,6 +353,14 @@ }; }; + pwm: pwm@66010000 { + compatible = "brcm,iproc-pwm"; + reg = <0x66010000 0x28>; + clocks = <&osc>; + #pwm-cells = <3>; + status = "disabled"; + }; + mdio_mux_iproc: mdio-mux@6602023c { compatible = "brcm,mdio-mux-iproc"; reg = <0x6602023c 0x14>; @@ -557,5 +619,23 @@ brcm,nand-has-wp; }; + + qspi: spi@66470200 { + compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi"; + reg = <0x66470200 0x184>, + <0x66470000 0x124>, + <0x67017408 0x004>, + <0x664703a0 0x01c>; + reg-names = "mspi", "bspi", "intr_regs", + "intr_status_reg"; + interrupts = <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "spi_l1_intr"; + clocks = <&iprocmed>; + clock-names = "iprocmed"; + num-cs = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; }; diff --git a/arch/arm64/boot/dts/exynos/Makefile b/arch/arm64/boot/dts/exynos/Makefile index 50c9b9383cfa..7ddea53769a7 100644 --- a/arch/arm64/boot/dts/exynos/Makefile +++ b/arch/arm64/boot/dts/exynos/Makefile @@ -1,4 +1,7 @@ -dtb-$(CONFIG_ARCH_EXYNOS) += exynos7-espresso.dtb +dtb-$(CONFIG_ARCH_EXYNOS) += \ + exynos5433-tm2.dtb \ + exynos5433-tm2e.dtb \ + exynos7-espresso.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi new file mode 100644 index 000000000000..ad71247b074f --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi @@ -0,0 +1,804 @@ +/* + * Samsung's Exynos5433 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Chanwoo Choi <cw00.choi@samsung.com> + * + * Samsung's Exynos5433 SoC pin-mux and pin-config options are listed as device + * tree nodes are listed in this file. + * + * 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. + */ + +#define PIN_PULL_NONE 0 +#define PIN_PULL_DOWN 1 +#define PIN_PULL_UP 3 + +#define PIN_DRV_LV1 0 +#define PIN_DRV_LV2 2 +#define PIN_DRV_LV3 1 +#define PIN_DRV_LV4 3 + +#define PIN_IN 0 +#define PIN_OUT 1 +#define PIN_FUNC1 2 + +#define PIN(_func, _pin, _pull, _drv) \ + _pin { \ + samsung,pins = #_pin; \ + samsung,pin-function = <PIN_ ##_func>; \ + samsung,pin-pud = <PIN_PULL_ ##_pull>; \ + samsung,pin-drv = <PIN_DRV_ ##_drv>; \ + } + +&pinctrl_alive { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + }; + + gpa2: gpa2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa3: gpa3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf2: gpf2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf3: gpf3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf4: gpf4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf5: gpf5 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_aud { + gpz0: gpz0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpz1: gpz1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + i2s0_bus: i2s0-bus { + samsung,pins = "gpz0-0", "gpz0-1", "gpz0-2", "gpz0-3", + "gpz0-4", "gpz0-5", "gpz0-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + pcm0_bus: pcm0-bus { + samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + uart_aud_bus: uart-aud-bus { + samsung,pins = "gpz1-3", "gpz1-2", "gpz1-1", "gpz1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_cpif { + gpv6: gpv6 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_ese { + gpj2: gpj2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_finger { + gpd5: gpd5 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + spi2_bus: spi2-bus { + samsung,pins = "gpd5-0", "gpd5-2", "gpd5-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c6_bus: hs-i2c6-bus { + samsung,pins = "gpd5-3", "gpd5-2"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_fsys { + gph1: gph1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr4: gpr4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr0: gpr0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr1: gpr1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr2: gpr2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr3: gpr3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd0_clk: sd0-clk { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpr0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_rdqs: sd0-rdqs { + samsung,pins = "gpr0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_qrdy: sd0-qrdy { + samsung,pins = "gpr0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpr1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpr2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpr2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpr3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_bus8: sd1-bus-width8 { + samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + pcie_bus: pcie_bus { + samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpr4-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpr4-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpr4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpr4-4", "gpr4-5", "gpr4-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_clk_output: sd2-clk-output { + samsung,pins = "gpr4-0"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd2_cmd_output: sd2-cmd-output { + samsung,pins = "gpr4-1"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; +}; + +&pinctrl_imem { + gpf0: gpf0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_nfc { + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c4_bus: hs-i2c4-bus { + samsung,pins = "gpj0-1", "gpj0-0"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_peric { + gpv7: gpv7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb0: gpb0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc2: gpc2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc3: gpc3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg0: gpg0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd2: gpd2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd4: gpd4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd8: gpd8 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd6: gpd6 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd7: gpd7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg1: gpg1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg2: gpg2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg3: gpg3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c8_bus: hs-i2c8-bus { + samsung,pins = "gpb0-1", "gpb0-0"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c9_bus: hs-i2c9-bus { + samsung,pins = "gpb0-3", "gpb0-2"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2s1_bus: i2s1-bus { + samsung,pins = "gpd4-0", "gpd4-1", "gpd4-2", + "gpd4-3", "gpd4-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + pcm1_bus: pcm1-bus { + samsung,pins = "gpd4-0", "gpd4-1", "gpd4-2", + "gpd4-3", "gpd4-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + spdif_bus: spdif-bus { + samsung,pins = "gpd4-3", "gpd4-4"; + samsung,pin-function = <4>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + fimc_is_spi_pin0: fimc-is-spi-pin0 { + samsung,pins = "gpc3-3", "gpc3-2", "gpc3-1", "gpc3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_spi_pin1: fimc-is-spi-pin1 { + samsung,pins = "gpc3-7", "gpc3-6", "gpc3-5", "gpc3-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart0_bus: uart0-bus { + samsung,pins = "gpd0-3", "gpd0-2", "gpd0-1", "gpd0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + }; + + hs_i2c2_bus: hs-i2c2-bus { + samsung,pins = "gpd0-3", "gpd0-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart2_bus: uart2-bus { + samsung,pins = "gpd1-5", "gpd1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + }; + + uart1_bus: uart1-bus { + samsung,pins = "gpd1-3", "gpd1-2", "gpd1-1", "gpd1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + }; + + hs_i2c3_bus: hs-i2c3-bus { + samsung,pins = "gpd1-3", "gpd1-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c0_bus: hs-i2c0-bus { + samsung,pins = "gpd2-1", "gpd2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c1_bus: hs-i2c1-bus { + samsung,pins = "gpd2-3", "gpd2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + pwm0_out: pwm0-out { + samsung,pins = "gpd2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm1_out: pwm1-out { + samsung,pins = "gpd2-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm2_out: pwm2-out { + samsung,pins = "gpd2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm3_out: pwm3-out { + samsung,pins = "gpd2-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi1_bus: spi1-bus { + samsung,pins = "gpd6-2", "gpd6-4", "gpd6-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c7_bus: hs-i2c7-bus { + samsung,pins = "gpd2-7", "gpd2-6"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi0_bus: spi0-bus { + samsung,pins = "gpd8-0", "gpd6-0", "gpd6-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c10_bus: hs-i2c10-bus { + samsung,pins = "gpg3-1", "gpg3-0"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c11_bus: hs-i2c11-bus { + samsung,pins = "gpg3-3", "gpg3-2"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi3_bus: spi3-bus { + samsung,pins = "gpg3-4", "gpg3-6", "gpg3-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi4_bus: spi4-bus { + samsung,pins = "gpv7-1", "gpv7-3", "gpv7-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + fimc_is_uart: fimc-is-uart { + samsung,pins = "gpc1-1", "gpc0-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch0_i2c: fimc-is-ch0_i2c { + samsung,pins = "gpc2-1", "gpc2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch0_mclk: fimc-is-ch0_mclk { + samsung,pins = "gpd7-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch1_i2c: fimc-is-ch1-i2c { + samsung,pins = "gpc2-3", "gpc2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch1_mclk: fimc-is-ch1-mclk { + samsung,pins = "gpd7-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch2_i2c: fimc-is-ch2-i2c { + samsung,pins = "gpc2-5", "gpc2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + fimc_is_ch2_mclk: fimc-is-ch2-mclk { + samsung,pins = "gpd7-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_touch { + gpj1: gpj1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c5_bus: hs-i2c5-bus { + samsung,pins = "gpj1-1", "gpj1-0"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts new file mode 100644 index 000000000000..f21bdc2ff834 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts @@ -0,0 +1,1049 @@ +/* + * SAMSUNG Exynos5433 TM2 board device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Device tree source file for Samsung's TM2 board which is based on + * Samsung Exynos5433 SoC. + * + * 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. + */ + +/dts-v1/; +#include "exynos5433.dtsi" +#include <dt-bindings/clock/samsung,s2mps11.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + model = "Samsung TM2 board"; + compatible = "samsung,tm2", "samsung,exynos5433"; + + aliases { + gsc0 = &gsc_0; + gsc1 = &gsc_1; + gsc2 = &gsc_2; + pinctrl0 = &pinctrl_alive; + pinctrl1 = &pinctrl_aud; + pinctrl2 = &pinctrl_cpif; + pinctrl3 = &pinctrl_ese; + pinctrl4 = &pinctrl_finger; + pinctrl5 = &pinctrl_fsys; + pinctrl6 = &pinctrl_imem; + pinctrl7 = &pinctrl_nfc; + pinctrl8 = &pinctrl_peric; + pinctrl9 = &pinctrl_touch; + serial0 = &serial_0; + serial1 = &serial_1; + serial2 = &serial_2; + serial3 = &serial_3; + spi0 = &spi_0; + spi1 = &spi_1; + spi2 = &spi_2; + spi3 = &spi_3; + spi4 = &spi_4; + mshc0 = &mshc_0; + mshc2 = &mshc_2; + }; + + chosen { + stdout-path = &serial_1; + }; + + memory@20000000 { + device_type = "memory"; + reg = <0x0 0x20000000 0x0 0xc0000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power-key { + gpios = <&gpa2 7 GPIO_ACTIVE_LOW>; + linux,code = <KEY_POWER>; + label = "power key"; + debounce-interval = <10>; + }; + + volume-up-key { + gpios = <&gpa2 0 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEUP>; + label = "volume-up key"; + debounce-interval = <10>; + }; + + volume-down-key { + gpios = <&gpa2 1 GPIO_ACTIVE_LOW>; + linux,code = <KEY_VOLUMEDOWN>; + label = "volume-down key"; + debounce-interval = <10>; + }; + + homepage-key { + gpios = <&gpa0 3 GPIO_ACTIVE_LOW>; + linux,code = <KEY_MENU>; + label = "homepage key"; + debounce-interval = <10>; + }; + }; + + i2c_max98504: i2c-gpio-0 { + compatible = "i2c-gpio"; + gpios = <&gpd0 1 GPIO_ACTIVE_HIGH /* SPK_AMP_SDA */ + &gpd0 0 GPIO_ACTIVE_HIGH /* SPK_AMP_SCL */ >; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + max98504: max98504@31 { + compatible = "maxim,max98504"; + reg = <0x31>; + maxim,rx-path = <1>; + maxim,tx-path = <1>; + maxim,tx-channel-mask = <3>; + maxim,tx-channel-source = <2>; + }; + }; + + sound { + compatible = "samsung,tm2-audio"; + audio-codec = <&wm5110>; + i2s-controller = <&i2s0>; + audio-amplifier = <&max98504>; + mic-bias-gpios = <&gpr3 2 GPIO_ACTIVE_HIGH>; + model = "wm5110"; + samsung,audio-routing = + /* Headphone */ + "HP", "HPOUT1L", + "HP", "HPOUT1R", + + /* Speaker */ + "SPK", "SPKOUT", + "SPKOUT", "HPOUT2L", + "SPKOUT", "HPOUT2R", + + /* Receiver */ + "RCV", "HPOUT3L", + "RCV", "HPOUT3R"; + status = "okay"; + }; +}; + +&adc { + vdd-supply = <&ldo3_reg>; + status = "okay"; + + thermistor-ap { + compatible = "murata,ncp03wf104"; + pullup-uv = <1800000>; + pullup-ohm = <100000>; + pulldown-ohm = <0>; + io-channels = <&adc 0>; + }; + + thermistor-battery { + compatible = "murata,ncp03wf104"; + pullup-uv = <1800000>; + pullup-ohm = <100000>; + pulldown-ohm = <0>; + io-channels = <&adc 1>; + #thermal-sensor-cells = <0>; + }; + + thermistor-charger { + compatible = "murata,ncp03wf104"; + pullup-uv = <1800000>; + pullup-ohm = <100000>; + pulldown-ohm = <0>; + io-channels = <&adc 2>; + }; +}; + +&cmu_aud { + assigned-clocks = <&cmu_aud CLK_MOUT_AUD_PLL_USER>; + assigned-clock-parents = <&cmu_top CLK_FOUT_AUD_PLL>; +}; + +&cmu_fsys { + assigned-clocks = <&cmu_top CLK_MOUT_SCLK_USBDRD30>, + <&cmu_top CLK_MOUT_SCLK_USBHOST30>, + <&cmu_fsys CLK_MOUT_SCLK_USBDRD30_USER>, + <&cmu_fsys CLK_MOUT_SCLK_USBHOST30_USER>, + <&cmu_fsys CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_USER>, + <&cmu_fsys CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_USER>, + <&cmu_fsys CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_USER>, + <&cmu_fsys CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_USER>, + <&cmu_top CLK_DIV_SCLK_USBDRD30>, + <&cmu_top CLK_DIV_SCLK_USBHOST30>; + assigned-clock-parents = <&cmu_top CLK_MOUT_BUS_PLL_USER>, + <&cmu_top CLK_MOUT_BUS_PLL_USER>, + <&cmu_top CLK_SCLK_USBDRD30_FSYS>, + <&cmu_top CLK_SCLK_USBHOST30_FSYS>, + <&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_PHY>, + <&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_PHY>, + <&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY>, + <&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_PHY>; + assigned-clock-rates = <0>, <0>, <0>, <0>, <0>, <0>, <0>, <0>, + <66700000>, <66700000>; +}; + +&cmu_gscl { + assigned-clocks = <&cmu_gscl CLK_MOUT_ACLK_GSCL_111_USER>, + <&cmu_gscl CLK_MOUT_ACLK_GSCL_333_USER>; + assigned-clock-parents = <&cmu_top CLK_ACLK_GSCL_111>, + <&cmu_top CLK_ACLK_GSCL_333>; +}; + +&cmu_mfc { + assigned-clocks = <&cmu_mfc CLK_MOUT_ACLK_MFC_400_USER>; + assigned-clock-parents = <&cmu_top CLK_ACLK_MFC_400>; +}; + +&cmu_mscl { + assigned-clocks = <&cmu_mscl CLK_MOUT_ACLK_MSCL_400_USER>, + <&cmu_mscl CLK_MOUT_SCLK_JPEG_USER>, + <&cmu_mscl CLK_MOUT_SCLK_JPEG>, + <&cmu_top CLK_MOUT_SCLK_JPEG_A>; + assigned-clock-parents = <&cmu_top CLK_ACLK_MSCL_400>, + <&cmu_top CLK_SCLK_JPEG_MSCL>, + <&cmu_mscl CLK_MOUT_SCLK_JPEG_USER>, + <&cmu_top CLK_MOUT_BUS_PLL_USER>; +}; + +&cpu0 { + cpu-supply = <&buck3_reg>; +}; + +&cpu4 { + cpu-supply = <&buck2_reg>; +}; + +&decon { + status = "okay"; + + i80-if-timings { + }; +}; + +&dsi { + status = "okay"; + vddcore-supply = <&ldo6_reg>; + vddio-supply = <&ldo7_reg>; + samsung,pll-clock-frequency = <24000000>; + pinctrl-names = "default"; + pinctrl-0 = <&te_irq>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + dsi_out: endpoint { + samsung,burst-clock-frequency = <512000000>; + samsung,esc-clock-frequency = <16000000>; + }; + }; + }; +}; + +&hsi2c_0 { + status = "okay"; + clock-frequency = <2500000>; + + s2mps13-pmic@66 { + compatible = "samsung,s2mps13-pmic"; + interrupt-parent = <&gpa0>; + interrupts = <7 IRQ_TYPE_NONE>; + reg = <0x66>; + samsung,s2mps11-wrstbi-ground; + + s2mps13_osc: clocks { + compatible = "samsung,s2mps13-clk"; + #clock-cells = <1>; + clock-output-names = "s2mps13_ap", "s2mps13_cp", + "s2mps13_bt"; + }; + + regulators { + ldo1_reg: LDO1 { + regulator-name = "VDD_ALIVE_0.9V_AP"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-always-on; + }; + + ldo2_reg: LDO2 { + regulator-name = "VDDQ_MMC2_2.8V_AP"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo3_reg: LDO3 { + regulator-name = "VDD1_E_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo4_reg: LDO4 { + regulator-name = "VDD10_MIF_PLL_1.0V_AP"; + regulator-min-microvolt = <1300000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo5_reg: LDO5 { + regulator-name = "VDD10_DPLL_1.0V_AP"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo6_reg: LDO6 { + regulator-name = "VDD10_MIPI2L_1.0V_AP"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo7_reg: LDO7 { + regulator-name = "VDD18_MIPI2L_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo8_reg: LDO8 { + regulator-name = "VDD18_LLI_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo9_reg: LDO9 { + regulator-name = "VDD18_ABB_ETC_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo10_reg: LDO10 { + regulator-name = "VDD33_USB30_3.0V_AP"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo11_reg: LDO11 { + regulator-name = "VDD_INT_M_1.0V_AP"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo12_reg: LDO12 { + regulator-name = "VDD_KFC_M_1.1V_AP"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + + ldo13_reg: LDO13 { + regulator-name = "VDD_G3D_M_0.95V_AP"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <950000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo14_reg: LDO14 { + regulator-name = "VDDQ_M1_LDO_1.2V_AP"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo15_reg: LDO15 { + regulator-name = "VDDQ_M2_LDO_1.2V_AP"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + ldo16_reg: LDO16 { + regulator-name = "VDDQ_EFUSE"; + regulator-min-microvolt = <1400000>; + regulator-max-microvolt = <3400000>; + regulator-always-on; + }; + + ldo17_reg: LDO17 { + regulator-name = "V_TFLASH_2.8V_AP"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo18_reg: LDO18 { + regulator-name = "V_CODEC_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo19_reg: LDO19 { + regulator-name = "VDDA_1.8V_COMP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo20_reg: LDO20 { + regulator-name = "VCC_2.8V_AP"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + ldo21_reg: LDO21 { + regulator-name = "VT_CAM_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo22_reg: LDO22 { + regulator-name = "CAM_IO_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo23_reg: LDO23 { + regulator-name = "CAM_SEN_CORE_1.2V_AP"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1200000>; + }; + + ldo24_reg: LDO24 { + regulator-name = "VT_CAM_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo25_reg: LDO25 { + regulator-name = "CAM_SEN_A2.8V_AP"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo26_reg: LDO26 { + regulator-name = "CAM_AF_2.8V_AP"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo27_reg: LDO27 { + regulator-name = "VCC_3.0V_LCD_AP"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo28_reg: LDO28 { + regulator-name = "VCC_1.8V_LCD_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo29_reg: LDO29 { + regulator-name = "VT_CAM_2.8V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo30_reg: LDO30 { + regulator-name = "TSP_AVDD_3.3V_AP"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo31_reg: LDO31 { + regulator-name = "TSP_VDD_1.85V_AP"; + regulator-min-microvolt = <1850000>; + regulator-max-microvolt = <1850000>; + }; + + ldo32_reg: LDO32 { + regulator-name = "VTOUCH_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo33_reg: LDO33 { + regulator-name = "VTOUCH_LED_3.3V"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + }; + + ldo34_reg: LDO34 { + regulator-name = "VCC_1.8V_MHL_AP"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2100000>; + }; + + ldo35_reg: LDO35 { + regulator-name = "OIS_VM_2.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo36_reg: LDO36 { + regulator-name = "VSIL_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + + ldo37_reg: LDO37 { + regulator-name = "VF_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo38_reg: LDO38 { + regulator-name = "VCC_3.0V_MOTOR_AP"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + ldo39_reg: LDO39 { + regulator-name = "V_HRM_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo40_reg: LDO40 { + regulator-name = "V_HRM_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + buck1_reg: BUCK1 { + regulator-name = "VDD_MIF_0.9V_AP"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck2_reg: BUCK2 { + regulator-name = "VDD_EGL_1.0V_AP"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck3_reg: BUCK3 { + regulator-name = "VDD_KFC_1.0V_AP"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck4_reg: BUCK4 { + regulator-name = "VDD_INT_0.95V_AP"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck5_reg: BUCK5 { + regulator-name = "VDD_DISP_CAM0_0.9V_AP"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck6_reg: BUCK6 { + regulator-name = "VDD_G3D_0.9V_AP"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + buck7_reg: BUCK7 { + regulator-name = "VDD_MEM1_1.2V_AP"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + buck8_reg: BUCK8 { + regulator-name = "VDD_LLDO_1.35V_AP"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + buck9_reg: BUCK9 { + regulator-name = "VDD_MLDO_2.0V_AP"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + buck10_reg: BUCK10 { + regulator-name = "vdd_mem2"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + }; + }; + }; +}; + +&hsi2c_8 { + status = "okay"; + + max77843@66 { + compatible = "maxim,max77843"; + interrupt-parent = <&gpa1>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + reg = <0x66>; + + muic: max77843-muic { + compatible = "maxim,max77843-muic"; + }; + + regulators { + compatible = "maxim,max77843-regulator"; + safeout1_reg: SAFEOUT1 { + regulator-name = "SAFEOUT1"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <4950000>; + }; + + safeout2_reg: SAFEOUT2 { + regulator-name = "SAFEOUT2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <4950000>; + }; + + charger_reg: CHARGER { + regulator-name = "CHARGER"; + regulator-min-microamp = <100000>; + regulator-max-microamp = <3150000>; + }; + }; + + haptic: max77843-haptic { + compatible = "maxim,max77843-haptic"; + haptic-supply = <&ldo38_reg>; + pwms = <&pwm 0 33670 0>; + pwm-names = "haptic"; + }; + }; +}; + +&i2s0 { + status = "okay"; +}; + +&mshc_0 { + status = "okay"; + num-slots = <1>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + cap-mmc-highspeed; + non-removable; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + samsung,dw-mshc-hs400-timing = <0 3>; + samsung,read-strobe-delay = <90>; + fifo-depth = <0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_qrdy &sd0_bus1 &sd0_bus4 + &sd0_bus8 &sd0_rdqs>; + bus-width = <8>; + assigned-clocks = <&cmu_top CLK_SCLK_MMC0_FSYS>; + assigned-clock-rates = <800000000>; +}; + +&mshc_2 { + status = "okay"; + num-slots = <1>; + cap-sd-highspeed; + disable-wp; + cd-gpios = <&gpa2 4 GPIO_ACTIVE_HIGH>; + cd-inverted; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + fifo-depth = <0x80>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>; + bus-width = <4>; +}; + +&pinctrl_alive { + pinctrl-names = "default"; + pinctrl-0 = <&initial_alive>; + + initial_alive: initial-state { + PIN(IN, gpa0-0, DOWN, LV1); + PIN(IN, gpa0-1, NONE, LV1); + PIN(IN, gpa0-2, DOWN, LV1); + PIN(IN, gpa0-3, NONE, LV1); + PIN(IN, gpa0-4, NONE, LV1); + PIN(IN, gpa0-5, DOWN, LV1); + PIN(IN, gpa0-6, NONE, LV1); + PIN(IN, gpa0-7, NONE, LV1); + + PIN(IN, gpa1-0, UP, LV1); + PIN(IN, gpa1-1, NONE, LV1); + PIN(IN, gpa1-2, NONE, LV1); + PIN(IN, gpa1-3, DOWN, LV1); + PIN(IN, gpa1-4, DOWN, LV1); + PIN(IN, gpa1-5, NONE, LV1); + PIN(IN, gpa1-6, NONE, LV1); + PIN(IN, gpa1-7, NONE, LV1); + + PIN(IN, gpa2-0, NONE, LV1); + PIN(IN, gpa2-1, NONE, LV1); + PIN(IN, gpa2-2, NONE, LV1); + PIN(IN, gpa2-3, DOWN, LV1); + PIN(IN, gpa2-4, NONE, LV1); + PIN(IN, gpa2-5, DOWN, LV1); + PIN(IN, gpa2-6, DOWN, LV1); + PIN(IN, gpa2-7, NONE, LV1); + + PIN(IN, gpa3-0, DOWN, LV1); + PIN(IN, gpa3-1, DOWN, LV1); + PIN(IN, gpa3-2, NONE, LV1); + PIN(IN, gpa3-3, DOWN, LV1); + PIN(IN, gpa3-4, NONE, LV1); + PIN(IN, gpa3-5, DOWN, LV1); + PIN(IN, gpa3-6, DOWN, LV1); + PIN(IN, gpa3-7, DOWN, LV1); + + PIN(IN, gpf1-0, NONE, LV1); + PIN(IN, gpf1-1, NONE, LV1); + PIN(IN, gpf1-2, DOWN, LV1); + PIN(IN, gpf1-4, UP, LV1); + PIN(OUT, gpf1-5, NONE, LV1); + PIN(IN, gpf1-6, DOWN, LV1); + PIN(IN, gpf1-7, DOWN, LV1); + + PIN(IN, gpf2-0, DOWN, LV1); + PIN(IN, gpf2-1, DOWN, LV1); + PIN(IN, gpf2-2, DOWN, LV1); + PIN(IN, gpf2-3, DOWN, LV1); + + PIN(IN, gpf3-0, DOWN, LV1); + PIN(IN, gpf3-1, DOWN, LV1); + PIN(IN, gpf3-2, NONE, LV1); + PIN(IN, gpf3-3, DOWN, LV1); + + PIN(IN, gpf4-0, DOWN, LV1); + PIN(IN, gpf4-1, DOWN, LV1); + PIN(IN, gpf4-2, DOWN, LV1); + PIN(IN, gpf4-3, DOWN, LV1); + PIN(IN, gpf4-4, DOWN, LV1); + PIN(IN, gpf4-5, DOWN, LV1); + PIN(IN, gpf4-6, DOWN, LV1); + PIN(IN, gpf4-7, DOWN, LV1); + + PIN(IN, gpf5-0, DOWN, LV1); + PIN(IN, gpf5-1, DOWN, LV1); + PIN(IN, gpf5-2, DOWN, LV1); + PIN(IN, gpf5-3, DOWN, LV1); + PIN(OUT, gpf5-4, NONE, LV1); + PIN(IN, gpf5-5, DOWN, LV1); + PIN(IN, gpf5-6, DOWN, LV1); + PIN(IN, gpf5-7, DOWN, LV1); + }; + + te_irq: te_irq { + samsung,pins = "gpf1-3"; + samsung,pin-function = <0xf>; + }; +}; + +&pinctrl_cpif { + pinctrl-names = "default"; + pinctrl-0 = <&initial_cpif>; + + initial_cpif: initial-state { + PIN(IN, gpv6-0, DOWN, LV1); + PIN(IN, gpv6-1, DOWN, LV1); + }; +}; + +&pinctrl_ese { + pinctrl-names = "default"; + pinctrl-0 = <&initial_ese>; + + initial_ese: initial-state { + PIN(IN, gpj2-0, DOWN, LV1); + PIN(IN, gpj2-1, DOWN, LV1); + PIN(IN, gpj2-2, DOWN, LV1); + }; +}; + +&pinctrl_fsys { + pinctrl-names = "default"; + pinctrl-0 = <&initial_fsys>; + + initial_fsys: initial-state { + PIN(IN, gpr3-0, NONE, LV1); + PIN(IN, gpr3-1, DOWN, LV1); + PIN(IN, gpr3-2, DOWN, LV1); + PIN(IN, gpr3-3, DOWN, LV1); + PIN(IN, gpr3-7, NONE, LV1); + }; +}; + +&pinctrl_imem { + pinctrl-names = "default"; + pinctrl-0 = <&initial_imem>; + + initial_imem: initial-state { + PIN(IN, gpf0-0, UP, LV1); + PIN(IN, gpf0-1, UP, LV1); + PIN(IN, gpf0-2, DOWN, LV1); + PIN(IN, gpf0-3, UP, LV1); + PIN(IN, gpf0-4, DOWN, LV1); + PIN(IN, gpf0-5, NONE, LV1); + PIN(IN, gpf0-6, DOWN, LV1); + PIN(IN, gpf0-7, UP, LV1); + }; +}; + +&pinctrl_nfc { + pinctrl-names = "default"; + pinctrl-0 = <&initial_nfc>; + + initial_nfc: initial-state { + PIN(IN, gpj0-2, DOWN, LV1); + }; +}; + +&pinctrl_peric { + pinctrl-names = "default"; + pinctrl-0 = <&initial_peric>; + + initial_peric: initial-state { + PIN(IN, gpv7-0, DOWN, LV1); + PIN(IN, gpv7-1, DOWN, LV1); + PIN(IN, gpv7-2, NONE, LV1); + PIN(IN, gpv7-3, DOWN, LV1); + PIN(IN, gpv7-4, DOWN, LV1); + PIN(IN, gpv7-5, DOWN, LV1); + + PIN(IN, gpb0-4, DOWN, LV1); + + PIN(IN, gpc0-2, DOWN, LV1); + PIN(IN, gpc0-5, DOWN, LV1); + PIN(IN, gpc0-7, DOWN, LV1); + + PIN(IN, gpc1-1, DOWN, LV1); + + PIN(IN, gpc3-4, NONE, LV1); + PIN(IN, gpc3-5, NONE, LV1); + PIN(IN, gpc3-6, NONE, LV1); + PIN(IN, gpc3-7, NONE, LV1); + + PIN(OUT, gpg0-0, NONE, LV1); + PIN(FUNC1, gpg0-1, DOWN, LV1); + + PIN(IN, gpd2-5, DOWN, LV1); + + PIN(IN, gpd4-0, NONE, LV1); + PIN(IN, gpd4-1, DOWN, LV1); + PIN(IN, gpd4-2, DOWN, LV1); + PIN(IN, gpd4-3, DOWN, LV1); + PIN(IN, gpd4-4, DOWN, LV1); + + PIN(IN, gpd6-3, DOWN, LV1); + + PIN(IN, gpd8-1, UP, LV1); + + PIN(IN, gpg1-0, DOWN, LV1); + PIN(IN, gpg1-1, DOWN, LV1); + PIN(IN, gpg1-2, DOWN, LV1); + PIN(IN, gpg1-3, DOWN, LV1); + PIN(IN, gpg1-4, DOWN, LV1); + + PIN(IN, gpg2-0, DOWN, LV1); + PIN(IN, gpg2-1, DOWN, LV1); + + PIN(IN, gpg3-0, DOWN, LV1); + PIN(IN, gpg3-1, DOWN, LV1); + PIN(IN, gpg3-5, DOWN, LV1); + PIN(IN, gpg3-7, DOWN, LV1); + }; +}; + +&pinctrl_touch { + pinctrl-names = "default"; + pinctrl-0 = <&initial_touch>; + + initial_touch: initial-state { + PIN(IN, gpj1-2, DOWN, LV1); + }; +}; + +&pwm { + pinctrl-0 = <&pwm0_out>; + pinctrl-names = "default"; + status = "okay"; +}; + +&mic { + status = "okay"; + + i80-if-timings { + }; +}; + +&pmu_system_controller { + assigned-clocks = <&pmu_system_controller 0>; + assigned-clock-parents = <&xxti>; +}; + +&serial_1 { + status = "okay"; +}; + +&spi_1 { + cs-gpios = <&gpd6 3 GPIO_ACTIVE_HIGH>; + status = "okay"; + + wm5110: wm5110-codec@0 { + compatible = "wlf,wm5110"; + reg = <0x0>; + spi-max-frequency = <20000000>; + interrupt-parent = <&gpa0>; + interrupts = <4 IRQ_TYPE_NONE>; + clocks = <&pmu_system_controller 0>, + <&s2mps13_osc S2MPS11_CLK_BT>; + clock-names = "mclk1", "mclk2"; + + gpio-controller; + #gpio-cells = <2>; + + wlf,micd-detect-debounce = <300>; + wlf,micd-bias-start-time = <0x1>; + wlf,micd-rate = <0x7>; + wlf,micd-dbtime = <0x1>; + wlf,micd-force-micbias; + wlf,micd-configs = <0x0 1 0>; + wlf,hpdet-channel = <1>; + wlf,gpsw = <0x1>; + wlf,inmode = <2 0 2 0>; + + wlf,reset = <&gpc0 7 GPIO_ACTIVE_HIGH>; + wlf,ldoena = <&gpf0 0 GPIO_ACTIVE_HIGH>; + + /* core supplies */ + AVDD-supply = <&ldo18_reg>; + DBVDD1-supply = <&ldo18_reg>; + CPVDD-supply = <&ldo18_reg>; + DBVDD2-supply = <&ldo18_reg>; + DBVDD3-supply = <&ldo18_reg>; + + controller-data { + samsung,spi-feedback-delay = <0>; + }; + }; +}; + +&timer { + clock-frequency = <24000000>; +}; + +&tmu_atlas0 { + vtmu-supply = <&ldo3_reg>; + status = "okay"; +}; + +&tmu_apollo { + vtmu-supply = <&ldo3_reg>; + status = "okay"; +}; + +&tmu_g3d { + vtmu-supply = <&ldo3_reg>; + status = "okay"; +}; + +&usbdrd30 { + vdd33-supply = <&ldo10_reg>; + vdd10-supply = <&ldo6_reg>; + status = "okay"; +}; + +&usbdrd_dwc3_0 { + dr_mode = "otg"; +}; + +&usbdrd30_phy { + vbus-supply = <&safeout1_reg>; + status = "okay"; +}; + +&xxti { + clock-frequency = <24000000>; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts new file mode 100644 index 000000000000..1db4e7f363a9 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts @@ -0,0 +1,41 @@ +/* + * SAMSUNG Exynos5433 TM2E board device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Device tree source file for Samsung's TM2E(TM2 EDGE) board which is based on + * Samsung Exynos5433 SoC. + * + * 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 "exynos5433-tm2.dts" + +/ { + model = "Samsung TM2E board"; + compatible = "samsung,tm2e", "samsung,exynos5433"; +}; + +&ldo23_reg { + regulator-name = "CAM_SEN_CORE_1.025V_AP"; + regulator-max-microvolt = <1050000>; +}; + +&ldo25_reg { + regulator-name = "UNUSED_LDO25"; + regulator-always-off; +}; + +&ldo31_reg { + regulator-name = "TSP_VDD_1.8V_AP"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +}; + +&ldo38_reg { + regulator-name = "VCC_3.3V_MOTOR_AP"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi new file mode 100644 index 000000000000..9be2978f1b9a --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi @@ -0,0 +1,23 @@ +/* + * Device tree sources for Exynos5433 TMU sensor configuration + * + * Copyright (c) 2016 Jonghwa Lee <jonghwa3.lee@samsung.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/thermal/thermal_exynos.h> + +#thermal-sensor-cells = <0>; +samsung,tmu_gain = <8>; +samsung,tmu_reference_voltage = <23>; +samsung,tmu_noise_cancel_mode = <4>; +samsung,tmu_efuse_value = <75>; +samsung,tmu_min_efuse_value = <40>; +samsung,tmu_max_efuse_value = <150>; +samsung,tmu_first_point_trim = <25>; +samsung,tmu_second_point_trim = <85>; +samsung,tmu_default_temp_offset = <50>; +samsung,tmu_mux_addr = <6>; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi new file mode 100644 index 000000000000..125fe58d77ce --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi @@ -0,0 +1,22 @@ +/* + * Device tree sources for Exynos5433 TMU sensor configuration + * + * Copyright (c) 2016 Chanwoo Choi <cw00.choi@samsung.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/thermal/thermal_exynos.h> + +#thermal-sensor-cells = <0>; +samsung,tmu_gain = <8>; +samsung,tmu_reference_voltage = <16>; +samsung,tmu_noise_cancel_mode = <4>; +samsung,tmu_efuse_value = <75>; +samsung,tmu_min_efuse_value = <40>; +samsung,tmu_max_efuse_value = <150>; +samsung,tmu_first_point_trim = <25>; +samsung,tmu_second_point_trim = <85>; +samsung,tmu_default_temp_offset = <50>; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi new file mode 100644 index 000000000000..ceaa05145b8a --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi @@ -0,0 +1,296 @@ +/* + * Device tree sources for Exynos5433 thermal zone + * + * Copyright (c) 2016 Chanwoo Choi <cw00.choi@samsung.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/thermal/thermal.h> + +/ { +thermal-zones { + atlas0_thermal: atlas0-thermal { + thermal-sensors = <&tmu_atlas0>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + atlas0_alert_0: atlas0-alert-0 { + temperature = <65000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_1: atlas0-alert-1 { + temperature = <70000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_2: atlas0-alert-2 { + temperature = <75000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_3: atlas0-alert-3 { + temperature = <80000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_4: atlas0-alert-4 { + temperature = <85000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_5: atlas0-alert-5 { + temperature = <90000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas0_alert_6: atlas0-alert-6 { + temperature = <95000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + }; + + cooling-maps { + map0 { + /* Set maximum frequency as 1800MHz */ + trip = <&atlas0_alert_0>; + cooling-device = <&cpu4 1 2>; + }; + map1 { + /* Set maximum frequency as 1700MHz */ + trip = <&atlas0_alert_1>; + cooling-device = <&cpu4 2 3>; + }; + map2 { + /* Set maximum frequency as 1600MHz */ + trip = <&atlas0_alert_2>; + cooling-device = <&cpu4 3 4>; + }; + map3 { + /* Set maximum frequency as 1500MHz */ + trip = <&atlas0_alert_3>; + cooling-device = <&cpu4 4 5>; + }; + map4 { + /* Set maximum frequency as 1400MHz */ + trip = <&atlas0_alert_4>; + cooling-device = <&cpu4 5 7>; + }; + map5 { + /* Set maximum frequencyas 1200MHz */ + trip = <&atlas0_alert_5>; + cooling-device = <&cpu4 7 9>; + }; + map6 { + /* Set maximum frequency as 1000MHz */ + trip = <&atlas0_alert_6>; + cooling-device = <&cpu4 9 14>; + }; + }; + }; + + atlas1_thermal: atlas1-thermal { + thermal-sensors = <&tmu_atlas1>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + atlas1_alert_0: atlas1-alert-0 { + temperature = <65000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_1: atlas1-alert-1 { + temperature = <70000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_2: atlas1-alert-2 { + temperature = <75000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_3: atlas1-alert-3 { + temperature = <80000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_4: atlas1-alert-4 { + temperature = <85000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_5: atlas1-alert-5 { + temperature = <90000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + atlas1_alert_6: atlas1-alert-6 { + temperature = <95000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + }; + }; + + g3d_thermal: g3d-thermal { + thermal-sensors = <&tmu_g3d>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + g3d_alert_0: g3d-alert-0 { + temperature = <70000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_1: g3d-alert-1 { + temperature = <75000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_2: g3d-alert-2 { + temperature = <80000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_3: g3d-alert-3 { + temperature = <85000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_4: g3d-alert-4 { + temperature = <90000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_5: g3d-alert-5 { + temperature = <95000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + g3d_alert_6: g3d-alert-6 { + temperature = <100000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + }; + }; + + apollo_thermal: apollo-thermal { + thermal-sensors = <&tmu_apollo>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + apollo_alert_0: apollo-alert-0 { + temperature = <65000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_1: apollo-alert-1 { + temperature = <70000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_2: apollo-alert-2 { + temperature = <75000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_3: apollo-alert-3 { + temperature = <80000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_4: apollo-alert-4 { + temperature = <85000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_5: apollo-alert-5 { + temperature = <90000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + apollo_alert_6: apollo-alert-6 { + temperature = <95000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + }; + + cooling-maps { + map0 { + /* Set maximum frequency as 1200MHz */ + trip = <&apollo_alert_2>; + cooling-device = <&cpu0 1 2>; + }; + map1 { + /* Set maximum frequency as 1100MHz */ + trip = <&apollo_alert_3>; + cooling-device = <&cpu0 2 3>; + }; + map2 { + /* Set maximum frequency as 1000MHz */ + trip = <&apollo_alert_4>; + cooling-device = <&cpu0 3 4>; + }; + map3 { + /* Set maximum frequency as 900MHz */ + trip = <&apollo_alert_5>; + cooling-device = <&cpu0 4 5>; + }; + map4 { + /* Set maximum frequency as 800MHz */ + trip = <&apollo_alert_6>; + cooling-device = <&cpu0 5 9>; + }; + }; + }; + + isp_thermal: isp-thermal { + thermal-sensors = <&tmu_isp>; + polling-delay-passive = <0>; + polling-delay = <0>; + trips { + isp_alert_0: isp-alert-0 { + temperature = <80000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_1: isp-alert-1 { + temperature = <85000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_2: isp-alert-2 { + temperature = <90000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_3: isp-alert-3 { + temperature = <95000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_4: isp-alert-4 { + temperature = <100000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_5: isp-alert-5 { + temperature = <105000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + isp_alert_6: isp-alert-6 { + temperature = <110000>; /* millicelsius */ + hysteresis = <1000>; /* millicelsius */ + type = "active"; + }; + }; + }; +}; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi new file mode 100644 index 000000000000..64226d5ae471 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi @@ -0,0 +1,1462 @@ +/* + * Samsung's Exynos5433 SoC device tree source + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Samsung's Exynos5433 SoC device nodes are listed in this file. + * Exynos5433 based board files can include this file and provide + * values for board specific bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos5433 SoC. As device tree coverage for Exynos5433 increases, + * additional nodes can be added to this file. + * + * 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/clock/exynos5433.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "samsung,exynos5433"; + #address-cells = <2>; + #size-cells = <2>; + + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + enable-method = "psci"; + reg = <0x100>; + clock-frequency = <1300000000>; + clocks = <&cmu_apollo CLK_SCLK_APOLLO>; + clock-names = "apolloclk"; + operating-points-v2 = <&cluster_a53_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + enable-method = "psci"; + reg = <0x101>; + clock-frequency = <1300000000>; + operating-points-v2 = <&cluster_a53_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + enable-method = "psci"; + reg = <0x102>; + clock-frequency = <1300000000>; + operating-points-v2 = <&cluster_a53_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + enable-method = "psci"; + reg = <0x103>; + clock-frequency = <1300000000>; + operating-points-v2 = <&cluster_a53_opp_table>; + #cooling-cells = <2>; + }; + + cpu4: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + enable-method = "psci"; + reg = <0x0>; + clock-frequency = <1900000000>; + clocks = <&cmu_atlas CLK_SCLK_ATLAS>; + clock-names = "atlasclk"; + operating-points-v2 = <&cluster_a57_opp_table>; + #cooling-cells = <2>; + }; + + cpu5: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + enable-method = "psci"; + reg = <0x1>; + clock-frequency = <1900000000>; + operating-points-v2 = <&cluster_a57_opp_table>; + #cooling-cells = <2>; + }; + + cpu6: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + enable-method = "psci"; + reg = <0x2>; + clock-frequency = <1900000000>; + operating-points-v2 = <&cluster_a57_opp_table>; + #cooling-cells = <2>; + }; + + cpu7: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + enable-method = "psci"; + reg = <0x3>; + clock-frequency = <1900000000>; + operating-points-v2 = <&cluster_a57_opp_table>; + #cooling-cells = <2>; + }; + }; + + cluster_a53_opp_table: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp@400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <900000>; + }; + opp@500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <925000>; + }; + opp@600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <950000>; + }; + opp@700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <975000>; + }; + opp@800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1000000>; + }; + opp@900000000 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <1050000>; + }; + opp@1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <1075000>; + }; + opp@1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <1112500>; + }; + opp@1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1112500>; + }; + opp@1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1150000>; + }; + }; + + cluster_a57_opp_table: opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp@500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <900000>; + }; + opp@600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000>; + }; + opp@700000000 { + opp-hz = /bits/ 64 <700000000>; + opp-microvolt = <912500>; + }; + opp@800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <912500>; + }; + opp@900000000 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <937500>; + }; + opp@1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <975000>; + }; + opp@1100000000 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <1012500>; + }; + opp@1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <1037500>; + }; + opp@1300000000 { + opp-hz = /bits/ 64 <1300000000>; + opp-microvolt = <1062500>; + }; + opp@1400000000 { + opp-hz = /bits/ 64 <1400000000>; + opp-microvolt = <1087500>; + }; + opp@1500000000 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <1125000>; + }; + opp@1600000000 { + opp-hz = /bits/ 64 <1600000000>; + opp-microvolt = <1137500>; + }; + opp@1700000000 { + opp-hz = /bits/ 64 <1700000000>; + opp-microvolt = <1175000>; + }; + opp@1800000000 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1212500>; + }; + opp@1900000000 { + opp-hz = /bits/ 64 <1900000000>; + opp-microvolt = <1262500>; + }; + }; + + psci { + compatible = "arm,psci"; + method = "smc"; + cpu_off = <0x84000002>; + cpu_on = <0xC4000003>; + }; + + reboot: syscon-reboot { + compatible = "syscon-reboot"; + regmap = <&pmu_system_controller>; + offset = <0x400>; /* SWRESET */ + mask = <0x1>; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x18000000>; + + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + + xxti: xxti { + compatible = "fixed-clock"; + clock-output-names = "oscclk"; + #clock-cells = <0>; + }; + + cmu_top: clock-controller@10030000 { + compatible = "samsung,exynos5433-cmu-top"; + reg = <0x10030000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_mphy_pll", + "sclk_mfc_pll", + "sclk_bus_pll"; + clocks = <&xxti>, + <&cmu_cpif CLK_SCLK_MPHY_PLL>, + <&cmu_mif CLK_SCLK_MFC_PLL>, + <&cmu_mif CLK_SCLK_BUS_PLL>; + }; + + cmu_cpif: clock-controller@10fc0000 { + compatible = "samsung,exynos5433-cmu-cpif"; + reg = <0x10fc0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk"; + clocks = <&xxti>; + }; + + cmu_mif: clock-controller@105b0000 { + compatible = "samsung,exynos5433-cmu-mif"; + reg = <0x105b0000 0x2000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_mphy_pll"; + clocks = <&xxti>, + <&cmu_cpif CLK_SCLK_MPHY_PLL>; + }; + + cmu_peric: clock-controller@14c80000 { + compatible = "samsung,exynos5433-cmu-peric"; + reg = <0x14c80000 0x1000>; + #clock-cells = <1>; + }; + + cmu_peris: clock-controller@0x10040000 { + compatible = "samsung,exynos5433-cmu-peris"; + reg = <0x10040000 0x1000>; + #clock-cells = <1>; + }; + + cmu_fsys: clock-controller@156e0000 { + compatible = "samsung,exynos5433-cmu-fsys"; + reg = <0x156e0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_ufs_mphy", + "aclk_fsys_200", + "sclk_pcie_100_fsys", + "sclk_ufsunipro_fsys", + "sclk_mmc2_fsys", + "sclk_mmc1_fsys", + "sclk_mmc0_fsys", + "sclk_usbhost30_fsys", + "sclk_usbdrd30_fsys"; + clocks = <&xxti>, + <&cmu_cpif CLK_SCLK_UFS_MPHY>, + <&cmu_top CLK_ACLK_FSYS_200>, + <&cmu_top CLK_SCLK_PCIE_100_FSYS>, + <&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>, + <&cmu_top CLK_SCLK_MMC2_FSYS>, + <&cmu_top CLK_SCLK_MMC1_FSYS>, + <&cmu_top CLK_SCLK_MMC0_FSYS>, + <&cmu_top CLK_SCLK_USBHOST30_FSYS>, + <&cmu_top CLK_SCLK_USBDRD30_FSYS>; + }; + + cmu_g2d: clock-controller@12460000 { + compatible = "samsung,exynos5433-cmu-g2d"; + reg = <0x12460000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "aclk_g2d_266", + "aclk_g2d_400"; + clocks = <&xxti>, + <&cmu_top CLK_ACLK_G2D_266>, + <&cmu_top CLK_ACLK_G2D_400>; + }; + + cmu_disp: clock-controller@13b90000 { + compatible = "samsung,exynos5433-cmu-disp"; + reg = <0x13b90000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_dsim1_disp", + "sclk_dsim0_disp", + "sclk_dsd_disp", + "sclk_decon_tv_eclk_disp", + "sclk_decon_vclk_disp", + "sclk_decon_eclk_disp", + "sclk_decon_tv_vclk_disp", + "aclk_disp_333"; + clocks = <&xxti>, + <&cmu_mif CLK_SCLK_DSIM1_DISP>, + <&cmu_mif CLK_SCLK_DSIM0_DISP>, + <&cmu_mif CLK_SCLK_DSD_DISP>, + <&cmu_mif CLK_SCLK_DECON_TV_ECLK_DISP>, + <&cmu_mif CLK_SCLK_DECON_VCLK_DISP>, + <&cmu_mif CLK_SCLK_DECON_ECLK_DISP>, + <&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>, + <&cmu_mif CLK_ACLK_DISP_333>; + }; + + cmu_aud: clock-controller@114c0000 { + compatible = "samsung,exynos5433-cmu-aud"; + reg = <0x114c0000 0x1000>; + #clock-cells = <1>; + clock-names = "oscclk", "fout_aud_pll"; + clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>; + }; + + cmu_bus0: clock-controller@13600000 { + compatible = "samsung,exynos5433-cmu-bus0"; + reg = <0x13600000 0x1000>; + #clock-cells = <1>; + + clock-names = "aclk_bus0_400"; + clocks = <&cmu_top CLK_ACLK_BUS0_400>; + }; + + cmu_bus1: clock-controller@14800000 { + compatible = "samsung,exynos5433-cmu-bus1"; + reg = <0x14800000 0x1000>; + #clock-cells = <1>; + + clock-names = "aclk_bus1_400"; + clocks = <&cmu_top CLK_ACLK_BUS1_400>; + }; + + cmu_bus2: clock-controller@13400000 { + compatible = "samsung,exynos5433-cmu-bus2"; + reg = <0x13400000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", "aclk_bus2_400"; + clocks = <&xxti>, <&cmu_mif CLK_ACLK_BUS2_400>; + }; + + cmu_g3d: clock-controller@14aa0000 { + compatible = "samsung,exynos5433-cmu-g3d"; + reg = <0x14aa0000 0x2000>; + #clock-cells = <1>; + + clock-names = "oscclk", "aclk_g3d_400"; + clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>; + }; + + cmu_gscl: clock-controller@13cf0000 { + compatible = "samsung,exynos5433-cmu-gscl"; + reg = <0x13cf0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "aclk_gscl_111", + "aclk_gscl_333"; + clocks = <&xxti>, + <&cmu_top CLK_ACLK_GSCL_111>, + <&cmu_top CLK_ACLK_GSCL_333>; + }; + + cmu_apollo: clock-controller@11900000 { + compatible = "samsung,exynos5433-cmu-apollo"; + reg = <0x11900000 0x2000>; + #clock-cells = <1>; + + clock-names = "oscclk", "sclk_bus_pll_apollo"; + clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_APOLLO>; + }; + + cmu_atlas: clock-controller@11800000 { + compatible = "samsung,exynos5433-cmu-atlas"; + reg = <0x11800000 0x2000>; + #clock-cells = <1>; + + clock-names = "oscclk", "sclk_bus_pll_atlas"; + clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_ATLAS>; + }; + + cmu_mscl: clock-controller@105d0000 { + compatible = "samsung,exynos5433-cmu-mscl"; + reg = <0x150d0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_jpeg_mscl", + "aclk_mscl_400"; + clocks = <&xxti>, + <&cmu_top CLK_SCLK_JPEG_MSCL>, + <&cmu_top CLK_ACLK_MSCL_400>; + }; + + cmu_mfc: clock-controller@15280000 { + compatible = "samsung,exynos5433-cmu-mfc"; + reg = <0x15280000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", "aclk_mfc_400"; + clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>; + }; + + cmu_hevc: clock-controller@14f80000 { + compatible = "samsung,exynos5433-cmu-hevc"; + reg = <0x14f80000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", "aclk_hevc_400"; + clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>; + }; + + cmu_isp: clock-controller@146d0000 { + compatible = "samsung,exynos5433-cmu-isp"; + reg = <0x146d0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "aclk_isp_dis_400", + "aclk_isp_400"; + clocks = <&xxti>, + <&cmu_top CLK_ACLK_ISP_DIS_400>, + <&cmu_top CLK_ACLK_ISP_400>; + }; + + cmu_cam0: clock-controller@120d0000 { + compatible = "samsung,exynos5433-cmu-cam0"; + reg = <0x120d0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "aclk_cam0_333", + "aclk_cam0_400", + "aclk_cam0_552"; + clocks = <&xxti>, + <&cmu_top CLK_ACLK_CAM0_333>, + <&cmu_top CLK_ACLK_CAM0_400>, + <&cmu_top CLK_ACLK_CAM0_552>; + }; + + cmu_cam1: clock-controller@145d0000 { + compatible = "samsung,exynos5433-cmu-cam1"; + reg = <0x145d0000 0x1000>; + #clock-cells = <1>; + + clock-names = "oscclk", + "sclk_isp_uart_cam1", + "sclk_isp_spi1_cam1", + "sclk_isp_spi0_cam1", + "aclk_cam1_333", + "aclk_cam1_400", + "aclk_cam1_552"; + clocks = <&xxti>, + <&cmu_top CLK_SCLK_ISP_UART_CAM1>, + <&cmu_top CLK_SCLK_ISP_SPI1_CAM1>, + <&cmu_top CLK_SCLK_ISP_SPI0_CAM1>, + <&cmu_top CLK_ACLK_CAM1_333>, + <&cmu_top CLK_ACLK_CAM1_400>, + <&cmu_top CLK_ACLK_CAM1_552>; + }; + + tmu_atlas0: tmu@10060000 { + compatible = "samsung,exynos5433-tmu"; + reg = <0x10060000 0x200>; + interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>, + <&cmu_peris CLK_SCLK_TMU0>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos5433-tmu-sensor-conf.dtsi" + status = "disabled"; + }; + + tmu_atlas1: tmu@10068000 { + compatible = "samsung,exynos5433-tmu"; + reg = <0x10068000 0x200>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>, + <&cmu_peris CLK_SCLK_TMU0>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos5433-tmu-sensor-conf.dtsi" + status = "disabled"; + }; + + tmu_g3d: tmu@10070000 { + compatible = "samsung,exynos5433-tmu"; + reg = <0x10070000 0x200>; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>, + <&cmu_peris CLK_SCLK_TMU1>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos5433-tmu-g3d-sensor-conf.dtsi" + status = "disabled"; + }; + + tmu_apollo: tmu@10078000 { + compatible = "samsung,exynos5433-tmu"; + reg = <0x10078000 0x200>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>, + <&cmu_peris CLK_SCLK_TMU1>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos5433-tmu-sensor-conf.dtsi" + status = "disabled"; + }; + + tmu_isp: tmu@1007c000 { + compatible = "samsung,exynos5433-tmu"; + reg = <0x1007c000 0x200>; + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>, + <&cmu_peris CLK_SCLK_TMU1>; + clock-names = "tmu_apbif", "tmu_sclk"; + #include "exynos5433-tmu-sensor-conf.dtsi" + status = "disabled"; + }; + + mct@101c0000 { + compatible = "samsung,exynos4210-mct"; + reg = <0x101c0000 0x800>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&xxti>, <&cmu_peris CLK_PCLK_MCT>; + clock-names = "fin_pll", "mct"; + }; + + pinctrl_alive: pinctrl@10580000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x10580000 0x1a20>, <0x11090000 0x100>; + + wakeup-interrupt-controller { + compatible = "samsung,exynos7-wakeup-eint"; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + pinctrl_aud: pinctrl@114b0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x114b0000 0x1000>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_cpif: pinctrl@10fe0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x10fe0000 0x1000>; + interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_ese: pinctrl@14ca0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x14ca0000 0x1000>; + interrupts = <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_finger: pinctrl@14cb0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x14cb0000 0x1000>; + interrupts = <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_fsys: pinctrl@15690000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x15690000 0x1000>; + interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_imem: pinctrl@11090000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x11090000 0x1000>; + interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_nfc: pinctrl@14cd0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x14cd0000 0x1000>; + interrupts = <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_peric: pinctrl@14cc0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x14cc0000 0x1100>; + interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>; + }; + + pinctrl_touch: pinctrl@14ce0000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x14ce0000 0x1100>; + interrupts = <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>; + }; + + pmu_system_controller: system-controller@105c0000 { + compatible = "samsung,exynos5433-pmu", "syscon"; + reg = <0x105c0000 0x5008>; + #clock-cells = <1>; + clock-names = "clkout16"; + clocks = <&xxti>; + }; + + gic: interrupt-controller@11001000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x11001000 0x1000>, + <0x11002000 0x2000>, + <0x11004000 0x2000>, + <0x11006000 0x2000>; + interrupts = <GIC_PPI 9 0xf04>; + }; + + mipi_phy: video-phy@105c0710 { + compatible = "samsung,exynos5433-mipi-video-phy"; + #phy-cells = <1>; + samsung,pmu-syscon = <&pmu_system_controller>; + samsung,cam0-sysreg = <&syscon_cam0>; + samsung,cam1-sysreg = <&syscon_cam1>; + samsung,disp-sysreg = <&syscon_disp>; + }; + + decon: decon@13800000 { + compatible = "samsung,exynos5433-decon"; + reg = <0x13800000 0x2104>; + clocks = <&cmu_disp CLK_PCLK_DECON>, + <&cmu_disp CLK_ACLK_DECON>, + <&cmu_disp CLK_ACLK_SMMU_DECON0X>, + <&cmu_disp CLK_ACLK_XIU_DECON0X>, + <&cmu_disp CLK_PCLK_SMMU_DECON0X>, + <&cmu_disp CLK_SCLK_DECON_VCLK>, + <&cmu_disp CLK_SCLK_DECON_ECLK>; + clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x", + "aclk_xiu_decon0x", "pclk_smmu_decon0x", + "sclk_decon_vclk", "sclk_decon_eclk"; + interrupt-names = "fifo", "vsync", "lcd_sys"; + interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>; + samsung,disp-sysreg = <&syscon_disp>; + status = "disabled"; + iommus = <&sysmmu_decon0x>, <&sysmmu_decon1x>; + iommu-names = "m0", "m1"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + decon_to_mic: endpoint { + remote-endpoint = + <&mic_to_decon>; + }; + }; + }; + }; + + dsi: dsi@13900000 { + compatible = "samsung,exynos5433-mipi-dsi"; + reg = <0x13900000 0xC0>; + interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>; + phys = <&mipi_phy 1>; + phy-names = "dsim"; + clocks = <&cmu_disp CLK_PCLK_DSIM0>, + <&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>, + <&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>, + <&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>, + <&cmu_disp CLK_SCLK_DSIM0>; + clock-names = "bus_clk", + "phyclk_mipidphy0_bitclkdiv8", + "phyclk_mipidphy0_rxclkesc0", + "sclk_rgb_vclk_to_dsim0", + "sclk_mipi"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_to_mic: endpoint { + remote-endpoint = <&mic_to_dsi>; + }; + }; + }; + }; + + mic: mic@13930000 { + compatible = "samsung,exynos5433-mic"; + reg = <0x13930000 0x48>; + clocks = <&cmu_disp CLK_PCLK_MIC0>, + <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>; + clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0"; + samsung,disp-syscon = <&syscon_disp>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mic_to_decon: endpoint { + remote-endpoint = + <&decon_to_mic>; + }; + }; + + port@1 { + reg = <1>; + mic_to_dsi: endpoint { + remote-endpoint = <&dsi_to_mic>; + }; + }; + }; + }; + + syscon_disp: syscon@13b80000 { + compatible = "syscon"; + reg = <0x13b80000 0x1010>; + }; + + syscon_cam0: syscon@120f0000 { + compatible = "syscon"; + reg = <0x120f0000 0x1020>; + }; + + syscon_cam1: syscon@145f0000 { + compatible = "syscon"; + reg = <0x145f0000 0x1038>; + }; + + gsc_0: video-scaler@13C00000 { + compatible = "samsung,exynos5433-gsc"; + reg = <0x13c00000 0x1000>; + interrupts = <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk", "aclk_xiu", + "aclk_gsclbend"; + clocks = <&cmu_gscl CLK_PCLK_GSCL0>, + <&cmu_gscl CLK_ACLK_GSCL0>, + <&cmu_gscl CLK_ACLK_XIU_GSCLX>, + <&cmu_gscl CLK_ACLK_GSCLBEND_333>; + iommus = <&sysmmu_gscl0>; + }; + + gsc_1: video-scaler@13C10000 { + compatible = "samsung,exynos5433-gsc"; + reg = <0x13c10000 0x1000>; + interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk", "aclk_xiu", + "aclk_gsclbend"; + clocks = <&cmu_gscl CLK_PCLK_GSCL1>, + <&cmu_gscl CLK_ACLK_GSCL1>, + <&cmu_gscl CLK_ACLK_XIU_GSCLX>, + <&cmu_gscl CLK_ACLK_GSCLBEND_333>; + iommus = <&sysmmu_gscl1>; + }; + + gsc_2: video-scaler@13C20000 { + compatible = "samsung,exynos5433-gsc"; + reg = <0x13c20000 0x1000>; + interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk", "aclk_xiu", + "aclk_gsclbend"; + clocks = <&cmu_gscl CLK_PCLK_GSCL2>, + <&cmu_gscl CLK_ACLK_GSCL2>, + <&cmu_gscl CLK_ACLK_XIU_GSCLX>, + <&cmu_gscl CLK_ACLK_GSCLBEND_333>; + iommus = <&sysmmu_gscl2>; + }; + + jpeg: codec@15020000 { + compatible = "samsung,exynos5433-jpeg"; + reg = <0x15020000 0x10000>; + interrupts = <GIC_SPI 411 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk", "aclk_xiu", "sclk"; + clocks = <&cmu_mscl CLK_PCLK_JPEG>, + <&cmu_mscl CLK_ACLK_JPEG>, + <&cmu_mscl CLK_ACLK_XIU_MSCLX>, + <&cmu_mscl CLK_SCLK_JPEG>; + iommus = <&sysmmu_jpeg>; + }; + + mfc: codec@152E0000 { + compatible = "samsung,exynos5433-mfc"; + reg = <0x152E0000 0x10000>; + interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk", "aclk_xiu"; + clocks = <&cmu_mfc CLK_PCLK_MFC>, + <&cmu_mfc CLK_ACLK_MFC>, + <&cmu_mfc CLK_ACLK_XIU_MFCX>; + iommus = <&sysmmu_mfc_0>, <&sysmmu_mfc_1>; + iommu-names = "left", "right"; + }; + + sysmmu_decon0x: sysmmu@0x13a00000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x13a00000 0x1000>; + interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk"; + clocks = <&cmu_disp CLK_PCLK_SMMU_DECON0X>, + <&cmu_disp CLK_ACLK_SMMU_DECON0X>; + #iommu-cells = <0>; + }; + + sysmmu_decon1x: sysmmu@0x13a10000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x13a10000 0x1000>; + interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk"; + clocks = <&cmu_disp CLK_PCLK_SMMU_DECON1X>, + <&cmu_disp CLK_ACLK_SMMU_DECON1X>; + #iommu-cells = <0>; + }; + + sysmmu_gscl0: sysmmu@0x13C80000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x13C80000 0x1000>; + interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "aclk", "pclk"; + clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL0>, + <&cmu_gscl CLK_PCLK_SMMU_GSCL0>; + #iommu-cells = <0>; + }; + + sysmmu_gscl1: sysmmu@0x13C90000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x13C90000 0x1000>; + interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "aclk", "pclk"; + clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL1>, + <&cmu_gscl CLK_PCLK_SMMU_GSCL1>; + #iommu-cells = <0>; + }; + + sysmmu_gscl2: sysmmu@0x13CA0000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x13CA0000 0x1000>; + interrupts = <GIC_SPI 292 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "aclk", "pclk"; + clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL2>, + <&cmu_gscl CLK_PCLK_SMMU_GSCL2>; + #iommu-cells = <0>; + }; + + sysmmu_jpeg: sysmmu@0x15060000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x15060000 0x1000>; + interrupts = <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk"; + clocks = <&cmu_mscl CLK_PCLK_SMMU_JPEG>, + <&cmu_mscl CLK_ACLK_SMMU_JPEG>; + #iommu-cells = <0>; + }; + + sysmmu_mfc_0: sysmmu@0x15200000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x15200000 0x1000>; + interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk"; + clocks = <&cmu_mfc CLK_PCLK_SMMU_MFC_0>, + <&cmu_mfc CLK_ACLK_SMMU_MFC_0>; + #iommu-cells = <0>; + }; + + sysmmu_mfc_1: sysmmu@0x15210000 { + compatible = "samsung,exynos-sysmmu"; + reg = <0x15210000 0x1000>; + interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "pclk", "aclk"; + clocks = <&cmu_mfc CLK_PCLK_SMMU_MFC_1>, + <&cmu_mfc CLK_ACLK_SMMU_MFC_1>; + #iommu-cells = <0>; + }; + + serial_0: serial@14c10000 { + compatible = "samsung,exynos5433-uart"; + reg = <0x14c10000 0x100>; + interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peric CLK_PCLK_UART0>, + <&cmu_peric CLK_SCLK_UART0>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_bus>; + status = "disabled"; + }; + + serial_1: serial@14c20000 { + compatible = "samsung,exynos5433-uart"; + reg = <0x14c20000 0x100>; + interrupts = <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peric CLK_PCLK_UART1>, + <&cmu_peric CLK_SCLK_UART1>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_bus>; + status = "disabled"; + }; + + serial_2: serial@14c30000 { + compatible = "samsung,exynos5433-uart"; + reg = <0x14c30000 0x100>; + interrupts = <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_peric CLK_PCLK_UART2>, + <&cmu_peric CLK_SCLK_UART2>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_bus>; + status = "disabled"; + }; + + spi_0: spi@14d20000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d20000 0x100>; + interrupts = <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 9>, <&pdma0 8>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI0>, + <&cmu_peric CLK_SCLK_SPI0>, + <&cmu_peric CLK_SCLK_IOCLK_SPI0>; + clock-names = "spi", "spi_busclk0", "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_bus>; + num-cs = <1>; + status = "disabled"; + }; + + spi_1: spi@14d30000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d30000 0x100>; + interrupts = <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 11>, <&pdma0 10>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI1>, + <&cmu_peric CLK_SCLK_SPI1>, + <&cmu_peric CLK_SCLK_IOCLK_SPI1>; + clock-names = "spi", "spi_busclk0", "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_bus>; + num-cs = <1>; + status = "disabled"; + }; + + spi_2: spi@14d40000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d40000 0x100>; + interrupts = <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 13>, <&pdma0 12>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI2>, + <&cmu_peric CLK_SCLK_SPI2>, + <&cmu_peric CLK_SCLK_IOCLK_SPI2>; + clock-names = "spi", "spi_busclk0", "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2_bus>; + num-cs = <1>; + status = "disabled"; + }; + + spi_3: spi@14d50000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d50000 0x100>; + interrupts = <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 23>, <&pdma0 22>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI3>, + <&cmu_peric CLK_SCLK_SPI3>, + <&cmu_peric CLK_SCLK_IOCLK_SPI3>; + clock-names = "spi", "spi_busclk0", "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi3_bus>; + num-cs = <1>; + status = "disabled"; + }; + + spi_4: spi@14d00000 { + compatible = "samsung,exynos5433-spi"; + reg = <0x14d00000 0x100>; + interrupts = <GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&pdma0 25>, <&pdma0 24>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_peric CLK_PCLK_SPI4>, + <&cmu_peric CLK_SCLK_SPI4>, + <&cmu_peric CLK_SCLK_IOCLK_SPI4>; + clock-names = "spi", "spi_busclk0", "spi_ioclk"; + samsung,spi-src-clk = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&spi4_bus>; + num-cs = <1>; + status = "disabled"; + }; + + adc: adc@14d10000 { + compatible = "samsung,exynos7-adc"; + reg = <0x14d10000 0x100>; + interrupts = <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "adc"; + clocks = <&cmu_peric CLK_PCLK_ADCIF>; + #io-channel-cells = <1>; + io-channel-ranges; + status = "disabled"; + }; + + pwm: pwm@14dd0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x14dd0000 0x100>; + 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>; + samsung,pwm-outputs = <0>, <1>, <2>, <3>; + clocks = <&cmu_peric CLK_PCLK_PWM>; + clock-names = "timers"; + #pwm-cells = <3>; + status = "disabled"; + }; + + hsi2c_0: hsi2c@14e40000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e40000 0x1000>; + interrupts = <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c0_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C0>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_1: hsi2c@14e50000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e50000 0x1000>; + interrupts = <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c1_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C1>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_2: hsi2c@14e60000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e60000 0x1000>; + interrupts = <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c2_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C2>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_3: hsi2c@14e70000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e70000 0x1000>; + interrupts = <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c3_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C3>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_4: hsi2c@14ec0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14ec0000 0x1000>; + interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c4_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C4>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_5: hsi2c@14ed0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14ed0000 0x1000>; + interrupts = <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c5_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C5>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_6: hsi2c@14ee0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14ee0000 0x1000>; + interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c6_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C6>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_7: hsi2c@14ef0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14ef0000 0x1000>; + interrupts = <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c7_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C7>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_8: hsi2c@14d90000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14d90000 0x1000>; + interrupts = <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c8_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C8>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_9: hsi2c@14da0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14da0000 0x1000>; + interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c9_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C9>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_10: hsi2c@14de0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14de0000 0x1000>; + interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c10_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C10>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_11: hsi2c@14df0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14df0000 0x1000>; + interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c11_bus>; + clocks = <&cmu_peric CLK_PCLK_HSI2C11>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + usbdrd30: usb@15400000 { + compatible = "samsung,exynos5250-dwusb3"; + clocks = <&cmu_fsys CLK_ACLK_USBDRD30>, + <&cmu_fsys CLK_SCLK_USBDRD30>; + clock-names = "usbdrd30", "usbdrd30_susp_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + status = "disabled"; + + dwc3@15400000 { + compatible = "snps,dwc3"; + reg = <0x15400000 0x10000>; + interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbdrd30_phy 0>, <&usbdrd30_phy 1>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + usbdrd30_phy: phy@15500000 { + compatible = "samsung,exynos5433-usbdrd-phy"; + reg = <0x15500000 0x100>; + clocks = <&cmu_fsys CLK_ACLK_USBDRD30>, <&xxti>, + <&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK>, + <&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK>, + <&cmu_fsys CLK_SCLK_USBDRD30>; + clock-names = "phy", "ref", "phy_utmi", "phy_pipe", + "itp"; + #phy-cells = <1>; + samsung,pmu-syscon = <&pmu_system_controller>; + status = "disabled"; + }; + + usbhost30_phy: phy@15580000 { + compatible = "samsung,exynos5433-usbdrd-phy"; + reg = <0x15580000 0x100>; + clocks = <&cmu_fsys CLK_ACLK_USBHOST30>, <&xxti>, + <&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK>, + <&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK>, + <&cmu_fsys CLK_SCLK_USBHOST30>; + clock-names = "phy", "ref", "phy_utmi", "phy_pipe", + "itp"; + #phy-cells = <1>; + samsung,pmu-syscon = <&pmu_system_controller>; + status = "disabled"; + }; + + usbhost30: usb@15a00000 { + compatible = "samsung,exynos5250-dwusb3"; + clocks = <&cmu_fsys CLK_ACLK_USBHOST30>, + <&cmu_fsys CLK_SCLK_USBHOST30>; + clock-names = "usbdrd30", "usbdrd30_susp_clk"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + status = "disabled"; + + usbdrd_dwc3_0: dwc3@15a00000 { + compatible = "snps,dwc3"; + reg = <0x15a00000 0x10000>; + interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbhost30_phy 0>, <&usbhost30_phy 1>; + phy-names = "usb2-phy", "usb3-phy"; + }; + }; + + mshc_0: mshc@15540000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15540000 0x2000>; + clocks = <&cmu_fsys CLK_ACLK_MMC0>, + <&cmu_fsys CLK_SCLK_MMC0>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mshc_1: mshc@15550000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15550000 0x2000>; + clocks = <&cmu_fsys CLK_ACLK_MMC1>, + <&cmu_fsys CLK_SCLK_MMC1>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mshc_2: mshc@15560000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15560000 0x2000>; + clocks = <&cmu_fsys CLK_ACLK_MMC2>, + <&cmu_fsys CLK_SCLK_MMC2>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + amba { + compatible = "arm,amba-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pdma0: pdma@15610000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x15610000 0x1000>; + interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_fsys CLK_PDMA0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; + + pdma1: pdma@15600000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x15600000 0x1000>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_fsys CLK_PDMA1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; + }; + + audio-subsystem@11400000 { + compatible = "samsung,exynos5433-lpass"; + reg = <0x11400000 0x100>, <0x11500000 0x08>; + samsung,pmu-syscon = <&pmu_system_controller>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + adma: adma@11420000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x11420000 0x1000>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_aud CLK_ACLK_DMAC>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; + + i2s0: i2s0@11440000 { + compatible = "samsung,exynos7-i2s"; + reg = <0x11440000 0x100>; + dmas = <&adma 0 &adma 2>; + dma-names = "tx", "rx"; + interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&cmu_aud CLK_PCLK_AUD_I2S>, + <&cmu_aud CLK_SCLK_AUD_I2S>, + <&cmu_aud CLK_SCLK_I2S_BCLK>; + clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_bus>; + status = "disabled"; + }; + + serial_3: serial@11460000 { + compatible = "samsung,exynos5433-uart"; + reg = <0x11460000 0x100>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cmu_aud CLK_PCLK_AUD_UART>, + <&cmu_aud CLK_SCLK_AUD_UART>; + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_aud_bus>; + status = "disabled"; + }; + }; + }; + + timer: timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 14 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 11 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 10 + (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; + }; +}; + +#include "exynos5433-pinctrl.dtsi" +#include "exynos5433-tmu.dtsi" diff --git a/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi index f77ddaf21d04..82321984e1fb 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi @@ -20,8 +20,14 @@ interrupt-controller; interrupt-parent = <&gic>; #interrupt-cells = <2>; - interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, - <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>; + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; }; gpa1: gpa1 { @@ -31,8 +37,14 @@ interrupt-controller; interrupt-parent = <&gic>; #interrupt-cells = <2>; - interrupts = <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, - <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; }; gpa2: gpa2 { diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 162831546e18..80aa60e38237 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -10,6 +10,7 @@ */ #include <dt-bindings/clock/exynos7-clk.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> / { compatible = "samsung,exynos7"; @@ -34,28 +35,28 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu_atlas0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0x0>; enable-method = "psci"; }; - cpu@1 { + cpu_atlas1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0x1>; enable-method = "psci"; }; - cpu@2 { + cpu_atlas2: cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0x2>; enable-method = "psci"; }; - cpu@3 { + cpu_atlas3: cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a57", "arm,armv8"; reg = <0x3>; @@ -105,7 +106,7 @@ pdma0: pdma@10E10000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x10E10000 0x1000>; - interrupts = <0 225 0>; + interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_fsys0 ACLK_PDMA0>; clock-names = "apb_pclk"; #dma-cells = <1>; @@ -116,7 +117,7 @@ pdma1: pdma@10EB0000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x10EB0000 0x1000>; - interrupts = <0 226 0>; + interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_fsys0 ACLK_PDMA1>; clock-names = "apb_pclk"; #dma-cells = <1>; @@ -219,7 +220,7 @@ serial_0: serial@13630000 { compatible = "samsung,exynos4210-uart"; reg = <0x13630000 0x100>; - interrupts = <0 440 0>; + interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peric0 PCLK_UART0>, <&clock_peric0 SCLK_UART0>; clock-names = "uart", "clk_uart_baud0"; @@ -229,7 +230,7 @@ serial_1: serial@14c20000 { compatible = "samsung,exynos4210-uart"; reg = <0x14c20000 0x100>; - interrupts = <0 456 0>; + interrupts = <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peric1 PCLK_UART1>, <&clock_peric1 SCLK_UART1>; clock-names = "uart", "clk_uart_baud0"; @@ -239,7 +240,7 @@ serial_2: serial@14c30000 { compatible = "samsung,exynos4210-uart"; reg = <0x14c30000 0x100>; - interrupts = <0 457 0>; + interrupts = <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peric1 PCLK_UART2>, <&clock_peric1 SCLK_UART2>; clock-names = "uart", "clk_uart_baud0"; @@ -249,7 +250,7 @@ serial_3: serial@14c40000 { compatible = "samsung,exynos4210-uart"; reg = <0x14c40000 0x100>; - interrupts = <0 458 0>; + interrupts = <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peric1 PCLK_UART3>, <&clock_peric1 SCLK_UART3>; clock-names = "uart", "clk_uart_baud0"; @@ -263,62 +264,62 @@ wakeup-interrupt-controller { compatible = "samsung,exynos7-wakeup-eint"; interrupt-parent = <&gic>; - interrupts = <0 16 0>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; }; }; pinctrl_bus0: pinctrl@13470000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x13470000 0x1000>; - interrupts = <0 383 0>; + interrupts = <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_nfc: pinctrl@14cd0000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x14cd0000 0x1000>; - interrupts = <0 473 0>; + interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_touch: pinctrl@14ce0000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x14ce0000 0x1000>; - interrupts = <0 474 0>; + interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_ff: pinctrl@14c90000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x14c90000 0x1000>; - interrupts = <0 475 0>; + interrupts = <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_ese: pinctrl@14ca0000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x14ca0000 0x1000>; - interrupts = <0 476 0>; + interrupts = <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_fsys0: pinctrl@10e60000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x10e60000 0x1000>; - interrupts = <0 221 0>; + interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_fsys1: pinctrl@15690000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x15690000 0x1000>; - interrupts = <0 203 0>; + interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>; }; pinctrl_bus1: pinctrl@14870000 { compatible = "samsung,exynos7-pinctrl"; reg = <0x14870000 0x1000>; - interrupts = <0 384 0>; + interrupts = <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>; }; hsi2c_0: hsi2c@13640000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13640000 0x1000>; - interrupts = <0 441 0>; + interrupts = <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -331,7 +332,7 @@ hsi2c_1: hsi2c@13650000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13650000 0x1000>; - interrupts = <0 442 0>; + interrupts = <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -344,7 +345,7 @@ hsi2c_2: hsi2c@14e60000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x14e60000 0x1000>; - interrupts = <0 459 0>; + interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -357,7 +358,7 @@ hsi2c_3: hsi2c@14e70000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x14e70000 0x1000>; - interrupts = <0 460 0>; + interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -370,7 +371,7 @@ hsi2c_4: hsi2c@13660000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13660000 0x1000>; - interrupts = <0 443 0>; + interrupts = <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -383,7 +384,7 @@ hsi2c_5: hsi2c@13670000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13670000 0x1000>; - interrupts = <0 444 0>; + interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -396,7 +397,7 @@ hsi2c_6: hsi2c@14e00000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x14e00000 0x1000>; - interrupts = <0 461 0>; + interrupts = <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -409,7 +410,7 @@ hsi2c_7: hsi2c@13e10000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13e10000 0x1000>; - interrupts = <0 462 0>; + interrupts = <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -422,7 +423,7 @@ hsi2c_8: hsi2c@14e20000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x14e20000 0x1000>; - interrupts = <0 463 0>; + interrupts = <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -435,7 +436,7 @@ hsi2c_9: hsi2c@13680000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13680000 0x1000>; - interrupts = <0 445 0>; + interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -448,7 +449,7 @@ hsi2c_10: hsi2c@13690000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x13690000 0x1000>; - interrupts = <0 446 0>; + interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -461,7 +462,7 @@ hsi2c_11: hsi2c@136a0000 { compatible = "samsung,exynos7-hsi2c"; reg = <0x136a0000 0x1000>; - interrupts = <0 447 0>; + interrupts = <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -471,12 +472,26 @@ status = "disabled"; }; + arm-pmu { + compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3"; + interrupts = <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>; + interrupt-affinity = <&cpu_atlas0>, <&cpu_atlas1>, + <&cpu_atlas2>, <&cpu_atlas3>; + }; + timer { compatible = "arm,armv8-timer"; - interrupts = <1 13 0xff08>, - <1 14 0xff08>, - <1 11 0xff08>, - <1 10 0xff08>; + 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)>; }; pmu_system_controller: system-controller@105c0000 { @@ -494,7 +509,8 @@ rtc: rtc@10590000 { compatible = "samsung,s3c6410-rtc"; reg = <0x10590000 0x100>; - interrupts = <0 355 0>, <0 356 0>; + interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_ccore PCLK_RTC>; clock-names = "rtc"; status = "disabled"; @@ -503,7 +519,7 @@ watchdog: watchdog@101d0000 { compatible = "samsung,exynos7-wdt"; reg = <0x101d0000 0x100>; - interrupts = <0 110 0>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peris PCLK_WDT>; clock-names = "watchdog"; samsung,syscon-phandle = <&pmu_system_controller>; @@ -512,7 +528,7 @@ mmc_0: mmc@15740000 { compatible = "samsung,exynos7-dw-mshc-smu"; - interrupts = <0 201 0>; + interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; reg = <0x15740000 0x2000>; @@ -525,7 +541,7 @@ mmc_1: mmc@15750000 { compatible = "samsung,exynos7-dw-mshc"; - interrupts = <0 202 0>; + interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; reg = <0x15750000 0x2000>; @@ -538,7 +554,7 @@ mmc_2: mmc@15560000 { compatible = "samsung,exynos7-dw-mshc-smu"; - interrupts = <0 216 0>; + interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; reg = <0x15560000 0x2000>; @@ -552,7 +568,7 @@ adc: adc@13620000 { compatible = "samsung,exynos7-adc"; reg = <0x13620000 0x100>; - interrupts = <0 448 0>; + interrupts = <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peric0 PCLK_ADCIF>; clock-names = "adc"; #io-channel-cells = <1>; @@ -572,7 +588,7 @@ tmuctrl_0: tmu@10060000 { compatible = "samsung,exynos7-tmu"; reg = <0x10060000 0x200>; - interrupts = <0 108 0>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clock_peris PCLK_TMU>, <&clock_peris SCLK_TMU>; clock-names = "tmu_apbif", "tmu_sclk"; diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 1b7783db7de4..66027181fba4 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -1,5 +1,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts index 9d3e9fe1c87c..0989d635b558 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts @@ -45,7 +45,7 @@ */ /dts-v1/; -/include/ "fsl-ls1043a.dtsi" +#include "fsl-ls1043a.dtsi" / { model = "LS1043A QDS Board"; @@ -56,12 +56,14 @@ gpio1 = &gpio2; gpio2 = &gpio3; gpio3 = &gpio4; - serial0 = &lpuart0; - serial1 = &lpuart1; - serial2 = &lpuart2; - serial3 = &lpuart3; - serial4 = &lpuart4; - serial5 = &lpuart5; + serial0 = &duart0; + serial1 = &duart1; + serial2 = &duart2; + serial3 = &duart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts index 40846319be69..c37110bc1506 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts @@ -45,13 +45,21 @@ */ /dts-v1/; -/include/ "fsl-ls1043a.dtsi" +#include "fsl-ls1043a.dtsi" / { model = "LS1043A RDB Board"; aliases { crypto = &crypto; + serial0 = &duart0; + serial1 = &duart1; + serial2 = &duart2; + serial3 = &duart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; }; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index a67e210e2019..ec13a6ecb754 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -44,6 +44,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <dt-bindings/thermal/thermal.h> + / { compatible = "fsl,ls1043a"; interrupt-parent = <&gic>; @@ -66,6 +68,7 @@ reg = <0x0>; clocks = <&clockgen 1 0>; next-level-cache = <&l2>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -123,6 +126,7 @@ <1 14 0xf08>, /* Physical Non-Secure PPI */ <1 11 0xf08>, /* Virtual PPI */ <1 10 0xf08>; /* Hypervisor PPI */ + fsl,erratum-a008585; }; pmu { @@ -247,6 +251,88 @@ bus-width = <4>; }; + ddr: memory-controller@1080000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1080000 0x0 0x1000>; + interrupts = <0 144 0x4>; + big-endian; + }; + + tmu: tmu@1f00000 { + compatible = "fsl,qoriq-tmu"; + reg = <0x0 0x1f00000 0x0 0x10000>; + interrupts = <0 33 0x4>; + fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>; + fsl,tmu-calibration = <0x00000000 0x00000026 + 0x00000001 0x0000002d + 0x00000002 0x00000032 + 0x00000003 0x00000039 + 0x00000004 0x0000003f + 0x00000005 0x00000046 + 0x00000006 0x0000004d + 0x00000007 0x00000054 + 0x00000008 0x0000005a + 0x00000009 0x00000061 + 0x0000000a 0x0000006a + 0x0000000b 0x00000071 + + 0x00010000 0x00000025 + 0x00010001 0x0000002c + 0x00010002 0x00000035 + 0x00010003 0x0000003d + 0x00010004 0x00000045 + 0x00010005 0x0000004e + 0x00010006 0x00000057 + 0x00010007 0x00000061 + 0x00010008 0x0000006b + 0x00010009 0x00000076 + + 0x00020000 0x00000029 + 0x00020001 0x00000033 + 0x00020002 0x0000003d + 0x00020003 0x00000049 + 0x00020004 0x00000056 + 0x00020005 0x00000061 + 0x00020006 0x0000006d + + 0x00030000 0x00000021 + 0x00030001 0x0000002a + 0x00030002 0x0000003c + 0x00030003 0x0000004e>; + #thermal-sensor-cells = <1>; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <5000>; + + thermal-sensors = <&tmu 3>; + + trips { + cpu_alert: cpu-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_crit: cpu-crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; + }; + }; + dspi0: dspi@2100000 { compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; @@ -495,10 +581,11 @@ }; sata: sata@3200000 { - compatible = "fsl,ls1043a-ahci", "fsl,ls1021a-ahci"; + compatible = "fsl,ls1043a-ahci"; reg = <0x0 0x3200000 0x0 0x10000>; interrupts = <0 69 0x4>; clocks = <&clockgen 4 0>; + dma-coherent; }; msi1: msi-controller1@1571000 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts new file mode 100644 index 000000000000..290e5b014414 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts @@ -0,0 +1,212 @@ +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016, Freescale Semiconductor, Inc. + * + * Shaohui Xie <Shaohui.Xie@nxp.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "fsl-ls1046a.dtsi" + +/ { + model = "LS1046A QDS Board"; + compatible = "fsl,ls1046a-qds", "fsl,ls1046a"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + serial0 = &duart0; + serial1 = &duart1; + serial2 = &duart2; + serial3 = &duart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&dspi { + bus-num = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a11", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + + flash@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "sst25wf040b", "jedec,spi-nor"; + spi-cpol; + spi-cpha; + reg = <1>; + spi-max-frequency = <10000000>; + }; + + flash@2 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25s64", "jedec,spi-nor"; + spi-cpol; + spi-cpha; + reg = <2>; + spi-max-frequency = <10000000>; + }; +}; + +&duart0 { + status = "okay"; +}; + +&duart1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + pca9547@77 { + compatible = "nxp,pca9547"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + + ina220@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + ina220@41 { + compatible = "ti,ina220"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + rtc@51 { + compatible = "nxp,pcf2129"; + reg = <0x51>; + /* IRQ10_B */ + interrupts = <0 150 0x4>; + }; + + eeprom@56 { + compatible = "atmel,24c512"; + reg = <0x56>; + }; + + eeprom@57 { + compatible = "atmel,24c512"; + reg = <0x57>; + }; + + temp-sensor@4c { + compatible = "adi,adt7461a"; + reg = <0x4c>; + }; + }; + }; +}; + +&ifc { + #address-cells = <2>; + #size-cells = <1>; + /* NOR, NAND Flashes and FPGA on board */ + ranges = <0x0 0x0 0x0 0x60000000 0x08000000 + 0x1 0x0 0x0 0x7e800000 0x00010000 + 0x2 0x0 0x0 0x7fb00000 0x00000100>; + status = "okay"; + + nor@0,0 { + compatible = "cfi-flash"; + reg = <0x0 0x0 0x8000000>; + bank-width = <2>; + device-width = <1>; + }; + + nand@1,0 { + compatible = "fsl,ifc-nand"; + reg = <0x1 0x0 0x10000>; + }; + + fpga: board-control@2,0 { + compatible = "fsl,ls1046aqds-fpga", "fsl,fpga-qixis"; + reg = <0x2 0x0 0x0000100>; + }; +}; + +&lpuart0 { + status = "okay"; +}; + +&qspi { + num-cs = <2>; + bus-num = <0>; + status = "okay"; + + qflash0: s25fl128s@0 { + compatible = "spansion,m25p80"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <20000000>; + reg = <0>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts new file mode 100644 index 000000000000..d1ccc000d05a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts @@ -0,0 +1,150 @@ +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016, Freescale Semiconductor, Inc. + * + * Mingkai Hu <mingkai.hu@nxp.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "fsl-ls1046a.dtsi" + +/ { + model = "LS1046A RDB Board"; + compatible = "fsl,ls1046a-rdb", "fsl,ls1046a"; + + aliases { + serial0 = &duart0; + serial1 = &duart1; + serial2 = &duart2; + serial3 = &duart3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&duart0 { + status = "okay"; +}; + +&duart1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + ina220@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + + temp-sensor@4c { + compatible = "adi,adt7461"; + reg = <0x4c>; + }; + + eeprom@56 { + compatible = "atmel,24c512"; + reg = <0x52>; + }; + + eeprom@57 { + compatible = "atmel,24c512"; + reg = <0x53>; + }; +}; + +&i2c3 { + status = "okay"; + + rtc@51 { + compatible = "nxp,pcf2129"; + reg = <0x51>; + }; +}; + +&ifc { + #address-cells = <2>; + #size-cells = <1>; + /* NAND Flashe and CPLD on board */ + ranges = <0x0 0x0 0x0 0x7e800000 0x00010000 + 0x2 0x0 0x0 0x7fb00000 0x00000100>; + status = "okay"; + + nand@0,0 { + compatible = "fsl,ifc-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x0 0x10000>; + }; + + cpld: board-control@2,0 { + compatible = "fsl,ls1046ardb-cpld"; + reg = <0x2 0x0 0x0000100>; + }; +}; + +&qspi { + num-cs = <2>; + bus-num = <0>; + status = "okay"; + + qflash0: s25fs512s@0 { + compatible = "spansion,m25p80"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <20000000>; + reg = <0>; + }; + + qflash1: s25fs512s@1 { + compatible = "spansion,m25p80"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <20000000>; + reg = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi new file mode 100644 index 000000000000..38806ca53829 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi @@ -0,0 +1,515 @@ +/* + * Device Tree Include file for Freescale Layerscape-1046A family SoC. + * + * Copyright 2016, Freescale Semiconductor, Inc. + * + * Mingkai Hu <mingkai.hu@nxp.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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/interrupt-controller/arm-gic.h> + +/ { + compatible = "fsl,ls1046a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + crypto = &crypto; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x0>; + clocks = <&clockgen 1 0>; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_PH20>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x1>; + clocks = <&clockgen 1 0>; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_PH20>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x2>; + clocks = <&clockgen 1 0>; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_PH20>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x3>; + clocks = <&clockgen 1 0>; + next-level-cache = <&l2>; + cpu-idle-states = <&CPU_PH20>; + }; + + l2: l2-cache { + compatible = "cache"; + }; + }; + + idle-states { + /* + * PSCI node is not added default, U-boot will add missing + * parts if it determines to use PSCI. + */ + entry-method = "arm,psci"; + + CPU_PH20: cpu-ph20 { + compatible = "arm,idle-state"; + idle-state-name = "PH20"; + arm,psci-suspend-param = <0x00010000>; + entry-latency-us = <1000>; + exit-latency-us = <1000>; + min-residency-us = <3000>; + }; + }; + + memory@80000000 { + device_type = "memory"; + }; + + sysclk: sysclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "sysclk"; + }; + + reboot { + compatible ="syscon-reboot"; + regmap = <&dcfg>; + offset = <0xb0>; + mask = <0x02>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xf) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_RAW(0xf) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_RAW(0xf) | + IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_RAW(0xf) | + IRQ_TYPE_LEVEL_LOW)>; + }; + + pmu { + compatible = "arm,cortex-a72-pmu"; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&cpu0>, + <&cpu1>, + <&cpu2>, + <&cpu3>; + }; + + gic: interrupt-controller@1400000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x1410000 0 0x10000>, /* GICD */ + <0x0 0x1420000 0 0x20000>, /* GICC */ + <0x0 0x1440000 0 0x20000>, /* GICH */ + <0x0 0x1460000 0 0x20000>; /* GICV */ + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_RAW(0xf) | + IRQ_TYPE_LEVEL_LOW)>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ddr: memory-controller@1080000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1080000 0x0 0x1000>; + interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; + big-endian; + }; + + ifc: ifc@1530000 { + compatible = "fsl,ifc", "simple-bus"; + reg = <0x0 0x1530000 0x0 0x10000>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; + }; + + qspi: quadspi@1550000 { + compatible = "fsl,ls1021a-qspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x1550000 0x0 0x10000>, + <0x0 0x40000000 0x0 0x10000000>; + reg-names = "QuadSPI", "QuadSPI-memory"; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "qspi_en", "qspi"; + clocks = <&clockgen 4 1>, <&clockgen 4 1>; + big-endian; + fsl,qspi-has-second-chip; + status = "disabled"; + }; + + esdhc: esdhc@1560000 { + compatible = "fsl,esdhc"; + reg = <0x0 0x1560000 0x0 0x10000>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <0>; + voltage-ranges = <1800 1800 3300 3300>; + sdhci,auto-cmd12; + big-endian; + bus-width = <4>; + }; + + scfg: scfg@1570000 { + compatible = "fsl,ls1046a-scfg", "syscon"; + reg = <0x0 0x1570000 0x0 0x10000>; + big-endian; + }; + + crypto: crypto@1700000 { + compatible = "fsl,sec-v5.4", "fsl,sec-v5.0", + "fsl,sec-v4.0"; + fsl,sec-era = <8>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x00 0x1700000 0x100000>; + reg = <0x00 0x1700000 0x0 0x100000>; + interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; + + sec_jr0: jr@10000 { + compatible = "fsl,sec-v5.4-job-ring", + "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x10000 0x10000>; + interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + }; + + sec_jr1: jr@20000 { + compatible = "fsl,sec-v5.4-job-ring", + "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x20000 0x10000>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + }; + + sec_jr2: jr@30000 { + compatible = "fsl,sec-v5.4-job-ring", + "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x30000 0x10000>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + }; + + sec_jr3: jr@40000 { + compatible = "fsl,sec-v5.4-job-ring", + "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x40000 0x10000>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + dcfg: dcfg@1ee0000 { + compatible = "fsl,ls1046a-dcfg", "syscon"; + reg = <0x0 0x1ee0000 0x0 0x10000>; + big-endian; + }; + + clockgen: clocking@1ee1000 { + compatible = "fsl,ls1046a-clockgen"; + reg = <0x0 0x1ee1000 0x0 0x1000>; + #clock-cells = <2>; + clocks = <&sysclk>; + }; + + dspi: dspi@2100000 { + compatible = "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2100000 0x0 0x10000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "dspi"; + clocks = <&clockgen 4 1>; + spi-num-chipselects = <5>; + big-endian; + status = "disabled"; + }; + + i2c0: i2c@2180000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2180000 0x0 0x10000>; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + dmas = <&edma0 1 39>, + <&edma0 1 38>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c1: i2c@2190000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2190000 0x0 0x10000>; + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + status = "disabled"; + }; + + i2c2: i2c@21a0000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x21a0000 0x0 0x10000>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + status = "disabled"; + }; + + i2c3: i2c@21b0000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x21b0000 0x0 0x10000>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + status = "disabled"; + }; + + duart0: serial@21c0500 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x00 0x21c0500 0x0 0x100>; + interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + }; + + duart1: serial@21c0600 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x00 0x21c0600 0x0 0x100>; + interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + }; + + duart2: serial@21d0500 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x0 0x21d0500 0x0 0x100>; + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + }; + + duart3: serial@21d0600 { + compatible = "fsl,ns16550", "ns16550a"; + reg = <0x0 0x21d0600 0x0 0x100>; + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + }; + + gpio0: gpio@2300000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@2310000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2310000 0x0 0x10000>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@2320000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2320000 0x0 0x10000>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@2330000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2330000 0x0 0x10000>; + interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + lpuart0: serial@2950000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x2950000 0x0 0x1000>; + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 0>; + clock-names = "ipg"; + status = "disabled"; + }; + + lpuart1: serial@2960000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x2960000 0x0 0x1000>; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + clock-names = "ipg"; + status = "disabled"; + }; + + lpuart2: serial@2970000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x2970000 0x0 0x1000>; + interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + clock-names = "ipg"; + status = "disabled"; + }; + + lpuart3: serial@2980000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x2980000 0x0 0x1000>; + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + clock-names = "ipg"; + status = "disabled"; + }; + + lpuart4: serial@2990000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x2990000 0x0 0x1000>; + interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + clock-names = "ipg"; + status = "disabled"; + }; + + lpuart5: serial@29a0000 { + compatible = "fsl,ls1021a-lpuart"; + reg = <0x0 0x29a0000 0x0 0x1000>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + clock-names = "ipg"; + status = "disabled"; + }; + + wdog0: watchdog@2ad0000 { + compatible = "fsl,imx21-wdt"; + reg = <0x0 0x2ad0000 0x0 0x10000>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + big-endian; + }; + + edma0: edma@2c00000 { + #dma-cells = <2>; + compatible = "fsl,vf610-edma"; + reg = <0x0 0x2c00000 0x0 0x10000>, + <0x0 0x2c10000 0x0 0x10000>, + <0x0 0x2c20000 0x0 0x10000>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "edma-tx", "edma-err"; + dma-channels = <32>; + big-endian; + clock-names = "dmamux0", "dmamux1"; + clocks = <&clockgen 4 1>, + <&clockgen 4 1>; + }; + + usb0: usb@2f00000 { + compatible = "snps,dwc3"; + reg = <0x0 0x2f00000 0x0 0x10000>; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + }; + + usb1: usb@3000000 { + compatible = "snps,dwc3"; + reg = <0x0 0x3000000 0x0 0x10000>; + interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + }; + + usb2: usb@3100000 { + compatible = "snps,dwc3"; + reg = <0x0 0x3100000 0x0 0x10000>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + }; + + sata: sata@3200000 { + compatible = "fsl,ls1046a-ahci"; + reg = <0x0 0x3200000 0x0 0x10000>; + interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clockgen 4 1>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts index e8801faca996..8bc1f8f6fcfc 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts @@ -46,7 +46,7 @@ /dts-v1/; -/include/ "fsl-ls2080a.dtsi" +#include "fsl-ls2080a.dtsi" / { model = "Freescale Layerscape 2080a QDS Board"; @@ -57,6 +57,9 @@ serial1 = &serial1; }; + chosen { + stdout-path = "serial0:115200n8"; + }; }; &esdhc { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts index e127f0baab19..265e0a8b107b 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts @@ -46,7 +46,7 @@ /dts-v1/; -/include/ "fsl-ls2080a.dtsi" +#include "fsl-ls2080a.dtsi" / { model = "Freescale Layerscape 2080a RDB Board"; @@ -56,6 +56,10 @@ serial0 = &serial0; serial1 = &serial1; }; + + chosen { + stdout-path = "serial1:115200n8"; + }; }; &esdhc { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts index 505d038078a3..290604b0a603 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts @@ -46,7 +46,7 @@ /dts-v1/; -/include/ "fsl-ls2080a.dtsi" +#include "fsl-ls2080a.dtsi" / { model = "Freescale Layerscape 2080a software Simulator model"; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi index e3b6034ea5d9..e5935f28848c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi @@ -44,6 +44,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <dt-bindings/thermal/thermal.h> + / { compatible = "fsl,ls2080a"; interrupt-parent = <&gic>; @@ -62,15 +64,16 @@ */ /* We have 4 clusters having 2 Cortex-A57 cores each */ - cpu@0 { + cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x0>; clocks = <&clockgen 1 0>; next-level-cache = <&cluster0_l2>; + #cooling-cells = <2>; }; - cpu@1 { + cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x1>; @@ -78,15 +81,16 @@ next-level-cache = <&cluster0_l2>; }; - cpu@100 { + cpu2: cpu@100 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x100>; clocks = <&clockgen 1 1>; next-level-cache = <&cluster1_l2>; + #cooling-cells = <2>; }; - cpu@101 { + cpu3: cpu@101 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x101>; @@ -94,15 +98,16 @@ next-level-cache = <&cluster1_l2>; }; - cpu@200 { + cpu4: cpu@200 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x200>; clocks = <&clockgen 1 2>; next-level-cache = <&cluster2_l2>; + #cooling-cells = <2>; }; - cpu@201 { + cpu5: cpu@201 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x201>; @@ -110,15 +115,16 @@ next-level-cache = <&cluster2_l2>; }; - cpu@300 { + cpu6: cpu@300 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x300>; clocks = <&clockgen 1 3>; next-level-cache = <&cluster3_l2>; + #cooling-cells = <2>; }; - cpu@301 { + cpu7: cpu@301 { device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x301>; @@ -195,6 +201,7 @@ <1 14 4>, /* Physical Non-Secure PPI, active-low */ <1 11 4>, /* Virtual PPI, active-low */ <1 10 4>; /* Hypervisor PPI, active-low */ + fsl,erratum-a008585; }; pmu { @@ -215,6 +222,106 @@ clocks = <&sysclk>; }; + dcfg: dcfg@1e00000 { + compatible = "fsl,ls2080a-dcfg", "syscon"; + reg = <0x0 0x1e00000 0x0 0x10000>; + little-endian; + }; + + tmu: tmu@1f80000 { + compatible = "fsl,qoriq-tmu"; + reg = <0x0 0x1f80000 0x0 0x10000>; + interrupts = <0 23 0x4>; + fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>; + fsl,tmu-calibration = <0x00000000 0x00000026 + 0x00000001 0x0000002d + 0x00000002 0x00000032 + 0x00000003 0x00000039 + 0x00000004 0x0000003f + 0x00000005 0x00000046 + 0x00000006 0x0000004d + 0x00000007 0x00000054 + 0x00000008 0x0000005a + 0x00000009 0x00000061 + 0x0000000a 0x0000006a + 0x0000000b 0x00000071 + + 0x00010000 0x00000025 + 0x00010001 0x0000002c + 0x00010002 0x00000035 + 0x00010003 0x0000003d + 0x00010004 0x00000045 + 0x00010005 0x0000004e + 0x00010006 0x00000057 + 0x00010007 0x00000061 + 0x00010008 0x0000006b + 0x00010009 0x00000076 + + 0x00020000 0x00000029 + 0x00020001 0x00000033 + 0x00020002 0x0000003d + 0x00020003 0x00000049 + 0x00020004 0x00000056 + 0x00020005 0x00000061 + 0x00020006 0x0000006d + + 0x00030000 0x00000021 + 0x00030001 0x0000002a + 0x00030002 0x0000003c + 0x00030003 0x0000004e>; + little-endian; + #thermal-sensor-cells = <1>; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <5000>; + + thermal-sensors = <&tmu 4>; + + trips { + cpu_alert: cpu-alert { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_crit: cpu-crit { + temperature = <85000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert>; + cooling-device = + <&cpu0 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + map1 { + trip = <&cpu_alert>; + cooling-device = + <&cpu2 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + map2 { + trip = <&cpu_alert>; + cooling-device = + <&cpu4 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + map3 { + trip = <&cpu_alert>; + cooling-device = + <&cpu6 THERMAL_NO_LIMIT + THERMAL_NO_LIMIT>; + }; + }; + }; + }; + serial0: serial@21c0500 { compatible = "fsl,ns16550", "ns16550a"; reg = <0x0 0x21c0500 0x0 0x100>; @@ -588,6 +695,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + dma-coherent; num-lanes = <4>; bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000 /* downstream I/O */ @@ -612,6 +720,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + dma-coherent; num-lanes = <4>; bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000 /* downstream I/O */ @@ -636,6 +745,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + dma-coherent; num-lanes = <8>; bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000 /* downstream I/O */ @@ -660,6 +770,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + dma-coherent; num-lanes = <4>; bus-range = <0x0 0xff>; ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000 /* downstream I/O */ @@ -679,6 +790,7 @@ reg = <0x0 0x3200000 0x0 0x10000>; interrupts = <0 133 0x4>; /* Level high type */ clocks = <&clockgen 4 3>; + dma-coherent; }; sata1: sata@3210000 { @@ -687,6 +799,7 @@ reg = <0x0 0x3210000 0x0 0x10000>; interrupts = <0 136 0x4>; /* Level high type */ clocks = <&clockgen 4 3>; + dma-coherent; }; usb0: usb3@3100000 { @@ -715,4 +828,18 @@ interrupts = <0 12 4>; }; }; + + ddr1: memory-controller@1080000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1080000 0x0 0x1000>; + interrupts = <0 17 0x4>; + little-endian; + }; + + ddr2: memory-controller@1090000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1090000 0x0 0x1000>; + interrupts = <0 18 0x4>; + little-endian; + }; }; diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile index d5f43a06b1c1..c8b8f803cf90 100644 --- a/arch/arm64/boot/dts/hisilicon/Makefile +++ b/arch/arm64/boot/dts/hisilicon/Makefile @@ -1,6 +1,7 @@ dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb +dtb-$(CONFIG_ARCH_HISI) += hip07-d05.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 593c7e43de79..dba3c131c62c 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -29,16 +29,56 @@ * Reserve below regions from memory node: * * 0x05e0,0000 - 0x05ef,ffff: MCU firmware runtime using + * 0x05f0,1000 - 0x05f0,1fff: Reboot reason * 0x06df,f000 - 0x06df,ffff: Mailbox message data * 0x0740,f000 - 0x0740,ffff: MCU firmware section + * 0x21f0,0000 - 0x21ff,ffff: pstore/ramoops buffer * 0x3e00,0000 - 0x3fff,ffff: OP-TEE */ memory@0 { device_type = "memory"; reg = <0x00000000 0x00000000 0x00000000 0x05e00000>, - <0x00000000 0x05f00000 0x00000000 0x00eff000>, + <0x00000000 0x05f00000 0x00000000 0x00001000>, + <0x00000000 0x05f02000 0x00000000 0x00efd000>, <0x00000000 0x06e00000 0x00000000 0x0060f000>, - <0x00000000 0x07410000 0x00000000 0x36bf0000>; + <0x00000000 0x07410000 0x00000000 0x1aaf0000>, + <0x00000000 0x22000000 0x00000000 0x1c000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ramoops@0x21f00000 { + compatible = "ramoops"; + reg = <0x0 0x21f00000 0x0 0x00100000>; + record-size = <0x00020000>; + console-size = <0x00020000>; + ftrace-size = <0x00020000>; + }; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x00000000 0x08000000>; + linux,cma-default; + }; + }; + + reboot-mode-syscon@5f01000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x05f01000 0x0 0x00001000>; + + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x0>; + + mode-normal = <0x77665501>; + mode-bootloader = <0x77665500>; + mode-recovery = <0x77665502>; + }; }; soc { @@ -55,6 +95,8 @@ }; uart1: uart@f7111000 { + assigned-clocks = <&sys_ctrl HI6220_UART1_SRC>; + assigned-clock-rates = <150000000>; status = "ok"; }; @@ -372,3 +414,43 @@ &uart3 { label = "LS-UART1"; }; + +&ade { + status = "ok"; +}; + +&dsi { + status = "ok"; + + ports { + /* 1 for output port */ + port@1 { + reg = <1>; + + dsi_out0: endpoint@0 { + remote-endpoint = <&adv7533_in>; + }; + }; + }; +}; + +&i2c2 { + #address-cells = <1>; + #size-cells = <0>; + status = "ok"; + + adv7533: adv7533@39 { + compatible = "adi,adv7533"; + reg = <0x39>; + interrupt-parent = <&gpio1>; + interrupts = <1 2>; + pd-gpio = <&gpio0 4 0>; + adi,dsi-lanes = <4>; + + port { + adv7533_in: endpoint { + remote-endpoint = <&dsi_out0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi index 4f270410a5cb..470461ddd427 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi @@ -262,6 +262,11 @@ #clock-cells = <1>; }; + medianoc_ade: medianoc_ade@f4520000 { + compatible = "syscon"; + reg = <0x0 0xf4520000 0x0 0x4000>; + }; + stub_clock: stub_clock { compatible = "hisilicon,hi6220-stub-clk"; hisilicon,hi6220-clk-sram = <&sram>; @@ -359,6 +364,7 @@ reg = <0x0 0xf7010000 0x0 0x27c>; #address-cells = <1>; #size-cells = <1>; + #pinctrl-cells = <1>; #gpio-range-cells = <3>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <7>; @@ -397,6 +403,7 @@ reg = <0x0 0xf7010800 0x0 0x28c>; #address-cells = <1>; #size-cells = <1>; + #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; }; @@ -405,6 +412,7 @@ reg = <0x0 0xf8001800 0x0 0x78>; #address-cells = <1>; #size-cells = <1>; + #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; }; @@ -742,7 +750,6 @@ clocks = <&sys_ctrl HI6220_USBOTG_HCLK>; clock-names = "otg"; dr_mode = "otg"; - g-use-dma; g-rx-fifo-size = <512>; g-np-tx-fifo-size = <128>; g-tx-fifo-size = <128 128 128 128 128 128>; @@ -766,6 +773,7 @@ interrupts = <0x0 0x48 0x4>; clocks = <&sys_ctrl 2>, <&sys_ctrl 1>; clock-names = "ciu", "biu"; + resets = <&sys_ctrl PERIPH_RSTDIS0_MMC0>; bus-width = <0x8>; vmmc-supply = <&ldo19>; pinctrl-names = "default"; @@ -779,12 +787,16 @@ card-detect-delay = <200>; hisilicon,peripheral-syscon = <&ao_ctrl>; cap-sd-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; reg = <0x0 0xf723e000 0x0 0x1000>; interrupts = <0x0 0x49 0x4>; #address-cells = <0x1>; #size-cells = <0x0>; clocks = <&sys_ctrl 4>, <&sys_ctrl 3>; clock-names = "ciu", "biu"; + resets = <&sys_ctrl PERIPH_RSTDIS0_MMC1>; vqmmc-supply = <&ldo7>; vmmc-supply = <&ldo10>; bus-width = <0x4>; @@ -802,6 +814,7 @@ interrupts = <0x0 0x4a 0x4>; clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>; clock-names = "ciu", "biu"; + resets = <&sys_ctrl PERIPH_RSTDIS0_MMC2>; bus-width = <0x4>; broken-cd; pinctrl-names = "default", "idle"; @@ -850,5 +863,55 @@ }; }; }; + + ade: ade@f4100000 { + compatible = "hisilicon,hi6220-ade"; + reg = <0x0 0xf4100000 0x0 0x7800>; + reg-names = "ade_base"; + hisilicon,noc-syscon = <&medianoc_ade>; + resets = <&media_ctrl MEDIA_ADE>; + interrupts = <0 115 4>; /* ldi interrupt */ + + clocks = <&media_ctrl HI6220_ADE_CORE>, + <&media_ctrl HI6220_CODEC_JPEG>, + <&media_ctrl HI6220_ADE_PIX_SRC>; + /*clock name*/ + clock-names = "clk_ade_core", + "clk_codec_jpeg", + "clk_ade_pix"; + + assigned-clocks = <&media_ctrl HI6220_ADE_CORE>, + <&media_ctrl HI6220_CODEC_JPEG>; + assigned-clock-rates = <360000000>, <288000000>; + dma-coherent; + status = "disabled"; + + port { + ade_out: endpoint { + remote-endpoint = <&dsi_in>; + }; + }; + }; + + dsi: dsi@f4107800 { + compatible = "hisilicon,hi6220-dsi"; + reg = <0x0 0xf4107800 0x0 0x100>; + clocks = <&media_ctrl HI6220_DSI_PCLK>; + clock-names = "pclk"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* 0 for input port */ + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <&ade_out>; + }; + }; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi index bf322ed038b8..4b472a302cd8 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -300,11 +300,6 @@ clock-frequency = <200000000>; }; - peri_c_subctrl: syscon@80000000 { - compatible = "hisilicon,hip05-perisubc", "syscon"; - reg = < 0x0 0x80000000 0x0 0x10000>; - }; - uart0: uart@80300000 { compatible = "snps,dw-apb-uart"; reg = <0x0 0x80300000 0x0 0x10000>; diff --git a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi deleted file mode 100644 index b6a130c2e5a4..000000000000 --- a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi +++ /dev/null @@ -1,180 +0,0 @@ -soc0: soc@000000000 { - #address-cells = <2>; - #size-cells = <2>; - device_type = "soc"; - compatible = "simple-bus"; - ranges = <0x0 0x0 0x0 0x0 0x1 0x0>; - chip-id = <0>; - - soc0_mdio0: mdio@803c0000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "hisilicon,hns-mdio"; - reg = <0x0 0x803c0000 0x0 0x10000>; - subctrl-vbase = <&peri_c_subctrl>; - - soc0_phy0: ethernet-phy@0 { - reg = <0x0>; - compatible = "ethernet-phy-ieee802.3-c22"; - }; - soc0_phy1: ethernet-phy@1 { - reg = <0x1>; - compatible = "ethernet-phy-ieee802.3-c22"; - }; - }; - - dsaf0: dsa@c7000000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "hisilicon,hns-dsaf-v1"; - mode = "6port-16rss"; - interrupt-parent = <&mbigen_dsa>; - - reg = <0x0 0xc5000000 0x0 0x890000 - 0x0 0xc7000000 0x0 0x60000 - >; - - reg-names = "ppe-base","dsaf-base"; - subctrl-syscon = <&dsaf_subctrl>; - reset-field-offset = <0>; - interrupts = < - /* [14] ge fifo err 8 / xge 6**/ - 149 0x4 150 0x4 151 0x4 152 0x4 - 153 0x4 154 0x4 26 0x4 27 0x4 - 155 0x4 156 0x4 157 0x4 158 0x4 159 0x4 160 0x4 - /* [12] rcb com 4*3**/ - 0x6 0x4 0x7 0x4 0x8 0x4 0x9 0x4 - 16 0x4 17 0x4 18 0x4 19 0x4 - 22 0x4 23 0x4 24 0x4 25 0x4 - /* [8] ppe tnl 0-7***/ - 0x0 0x4 0x1 0x4 0x2 0x4 0x3 0x4 - 0x4 0x4 0x5 0x4 12 0x4 13 0x4 - /* [21] dsaf event int 3+18**/ - 128 0x4 129 0x4 130 0x4 - 0x83 0x4 0x84 0x4 0x85 0x4 0x86 0x4 0x87 0x4 0x88 0x4 - 0x89 0x4 0x8a 0x4 0x8b 0x4 0x8c 0x4 0x8d 0x4 0x8e 0x4 - 0x8f 0x4 0x90 0x4 0x91 0x4 0x92 0x4 0x93 0x4 0x94 0x4 - /* [4] debug rcb 2*2*/ - 0xe 0x1 0xf 0x1 0x14 0x1 0x15 0x1 - /* [256] sevice rcb 2*128*/ - 0x180 0x1 0x181 0x1 0x182 0x1 0x183 0x1 - 0x184 0x1 0x185 0x1 0x186 0x1 0x187 0x1 - 0x188 0x1 0x189 0x1 0x18a 0x1 0x18b 0x1 - 0x18c 0x1 0x18d 0x1 0x18e 0x1 0x18f 0x1 - 0x190 0x1 0x191 0x1 0x192 0x1 0x193 0x1 - 0x194 0x1 0x195 0x1 0x196 0x1 0x197 0x1 - 0x198 0x1 0x199 0x1 0x19a 0x1 0x19b 0x1 - 0x19c 0x1 0x19d 0x1 0x19e 0x1 0x19f 0x1 - 0x1a0 0x1 0x1a1 0x1 0x1a2 0x1 0x1a3 0x1 - 0x1a4 0x1 0x1a5 0x1 0x1a6 0x1 0x1a7 0x1 - 0x1a8 0x1 0x1a9 0x1 0x1aa 0x1 0x1ab 0x1 - 0x1ac 0x1 0x1ad 0x1 0x1ae 0x1 0x1af 0x1 - 0x1b0 0x1 0x1b1 0x1 0x1b2 0x1 0x1b3 0x1 - 0x1b4 0x1 0x1b5 0x1 0x1b6 0x1 0x1b7 0x1 - 0x1b8 0x1 0x1b9 0x1 0x1ba 0x1 0x1bb 0x1 - 0x1bc 0x1 0x1bd 0x1 0x1be 0x1 0x1bf 0x1 - 0x1c0 0x1 0x1c1 0x1 0x1c2 0x1 0x1c3 0x1 - 0x1c4 0x1 0x1c5 0x1 0x1c6 0x1 0x1c7 0x1 - 0x1c8 0x1 0x1c9 0x1 0x1ca 0x1 0x1cb 0x1 - 0x1cc 0x1 0x1cd 0x1 0x1ce 0x1 0x1cf 0x1 - 0x1d0 0x1 0x1d1 0x1 0x1d2 0x1 0x1d3 0x1 - 0x1d4 0x1 0x1d5 0x1 0x1d6 0x1 0x1d7 0x1 - 0x1d8 0x1 0x1d9 0x1 0x1da 0x1 0x1db 0x1 - 0x1dc 0x1 0x1dd 0x1 0x1de 0x1 0x1df 0x1 - 0x1e0 0x1 0x1e1 0x1 0x1e2 0x1 0x1e3 0x1 - 0x1e4 0x1 0x1e5 0x1 0x1e6 0x1 0x1e7 0x1 - 0x1e8 0x1 0x1e9 0x1 0x1ea 0x1 0x1eb 0x1 - 0x1ec 0x1 0x1ed 0x1 0x1ee 0x1 0x1ef 0x1 - 0x1f0 0x1 0x1f1 0x1 0x1f2 0x1 0x1f3 0x1 - 0x1f4 0x1 0x1f5 0x1 0x1f6 0x1 0x1f7 0x1 - 0x1f8 0x1 0x1f9 0x1 0x1fa 0x1 0x1fb 0x1 - 0x1fc 0x1 0x1fd 0x1 0x1fe 0x1 0x1ff 0x1 - 0x200 0x1 0x201 0x1 0x202 0x1 0x203 0x1 - 0x204 0x1 0x205 0x1 0x206 0x1 0x207 0x1 - 0x208 0x1 0x209 0x1 0x20a 0x1 0x20b 0x1 - 0x20c 0x1 0x20d 0x1 0x20e 0x1 0x20f 0x1 - 0x210 0x1 0x211 0x1 0x212 0x1 0x213 0x1 - 0x214 0x1 0x215 0x1 0x216 0x1 0x217 0x1 - 0x218 0x1 0x219 0x1 0x21a 0x1 0x21b 0x1 - 0x21c 0x1 0x21d 0x1 0x21e 0x1 0x21f 0x1 - 0x220 0x1 0x221 0x1 0x222 0x1 0x223 0x1 - 0x224 0x1 0x225 0x1 0x226 0x1 0x227 0x1 - 0x228 0x1 0x229 0x1 0x22a 0x1 0x22b 0x1 - 0x22c 0x1 0x22d 0x1 0x22e 0x1 0x22f 0x1 - 0x230 0x1 0x231 0x1 0x232 0x1 0x233 0x1 - 0x234 0x1 0x235 0x1 0x236 0x1 0x237 0x1 - 0x238 0x1 0x239 0x1 0x23a 0x1 0x23b 0x1 - 0x23c 0x1 0x23d 0x1 0x23e 0x1 0x23f 0x1 - 0x240 0x1 0x241 0x1 0x242 0x1 0x243 0x1 - 0x244 0x1 0x245 0x1 0x246 0x1 0x247 0x1 - 0x248 0x1 0x249 0x1 0x24a 0x1 0x24b 0x1 - 0x24c 0x1 0x24d 0x1 0x24e 0x1 0x24f 0x1 - 0x250 0x1 0x251 0x1 0x252 0x1 0x253 0x1 - 0x254 0x1 0x255 0x1 0x256 0x1 0x257 0x1 - 0x258 0x1 0x259 0x1 0x25a 0x1 0x25b 0x1 - 0x25c 0x1 0x25d 0x1 0x25e 0x1 0x25f 0x1 - 0x260 0x1 0x261 0x1 0x262 0x1 0x263 0x1 - 0x264 0x1 0x265 0x1 0x266 0x1 0x267 0x1 - 0x268 0x1 0x269 0x1 0x26a 0x1 0x26b 0x1 - 0x26c 0x1 0x26d 0x1 0x26e 0x1 0x26f 0x1 - 0x270 0x1 0x271 0x1 0x272 0x1 0x273 0x1 - 0x274 0x1 0x275 0x1 0x276 0x1 0x277 0x1 - 0x278 0x1 0x279 0x1 0x27a 0x1 0x27b 0x1 - 0x27c 0x1 0x27d 0x1 0x27e 0x1 0x27f 0x1>; - buf-size = <4096>; - desc-num = <1024>; - dma-coherent; - - port@0 { - reg = <0>; - serdes-syscon = <&serdes_ctrl0>; - }; - port@1 { - reg = <1>; - serdes-syscon = <&serdes_ctrl0>; - }; - port@4 { - reg = <4>; - phy-handle = <&soc0_phy0>; - serdes-syscon = <&serdes_ctrl1>; - }; - port@5 { - reg = <5>; - phy-handle = <&soc0_phy1>; - serdes-syscon = <&serdes_ctrl1>; - }; - }; - - eth0: ethernet@0{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-idx-in-ae = <0>; - local-mac-address = [00 00 00 01 00 58]; - status = "disabled"; - dma-coherent; - }; - eth1: ethernet@1{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-idx-in-ae = <1>; - local-mac-address = [00 00 00 01 00 59]; - status = "disabled"; - dma-coherent; - }; - eth2: ethernet@4{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-idx-in-ae = <4>; - local-mac-address = [00 00 00 01 00 5a]; - status = "disabled"; - dma-coherent; - }; - eth3: ethernet@5{ - compatible = "hisilicon,hns-nic-v1"; - ae-handle = <&dsaf0>; - port-idx-in-ae = <5>; - local-mac-address = [00 00 00 01 00 5b]; - status = "disabled"; - dma-coherent; - }; -}; diff --git a/arch/arm64/boot/dts/hisilicon/hip06-d03.dts b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts index f3e5323e430b..7c4114a67753 100644 --- a/arch/arm64/boot/dts/hisilicon/hip06-d03.dts +++ b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts @@ -25,6 +25,26 @@ chosen { }; }; +ð0 { + status = "ok"; +}; + +ð1 { + status = "ok"; +}; + +ð2 { + status = "ok"; +}; + +ð3 { + status = "ok"; +}; + +&sas1 { + status = "ok"; +}; + &usb_ohci { status = "ok"; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi index 5927bc472f1b..a049b64f2101 100644 --- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi @@ -277,6 +277,39 @@ #interrupt-cells = <2>; num-pins = <2>; }; + + mbigen_sas1: intc_sas1 { + msi-parent = <&its_dsa 0x40000>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <128>; + }; + + mbigen_sas2: intc_sas2 { + msi-parent = <&its_dsa 0x40040>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <128>; + }; + }; + + mbigen_dsa@c0080000 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x0 0xc0080000 0x0 0x10000>; + + mbigen_dsaf0: intc_dsaf0 { + msi-parent = <&its_dsa 0x40800>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <409>; + }; + + mbigen_sas0: intc-sas0 { + msi-parent = <&its_dsa 0x40900>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <128>; + }; }; soc { @@ -285,11 +318,17 @@ #size-cells = <2>; ranges; + refclk: refclk { + compatible = "fixed-clock"; + clock-frequency = <50000000>; + #clock-cells = <0>; + }; + usb_ohci: ohci@a7030000 { compatible = "generic-ohci"; reg = <0x0 0xa7030000 0x0 0x10000>; interrupt-parent = <&mbigen_usb>; - interrupts = <64 4>; + interrupts = <640 4>; dma-coherent; status = "disabled"; }; @@ -298,8 +337,343 @@ compatible = "generic-ehci"; reg = <0x0 0xa7020000 0x0 0x10000>; interrupt-parent = <&mbigen_usb>; - interrupts = <65 4>; + interrupts = <641 4>; + dma-coherent; + status = "disabled"; + }; + + peri_c_subctrl: sub_ctrl_c@60000000 { + compatible = "hisilicon,peri-subctrl","syscon"; + reg = <0 0x60000000 0x0 0x10000>; + }; + + dsa_subctrl: dsa_subctrl@c0000000 { + compatible = "hisilicon,dsa-subctrl", "syscon"; + reg = <0x0 0xc0000000 0x0 0x10000>; + }; + + pcie_subctl: pcie_subctl@a0000000 { + compatible = "hisilicon,pcie-sas-subctrl", "syscon"; + reg = <0x0 0xa0000000 0x0 0x10000>; + }; + + serdes_ctrl: sds_ctrl@c2200000 { + compatible = "syscon"; + reg = <0 0xc2200000 0x0 0x80000>; + }; + + mdio@603c0000 { + compatible = "hisilicon,hns-mdio"; + reg = <0x0 0x603c0000 0x0 0x1000>; + subctrl-vbase = <&peri_c_subctrl 0x338 0xa38 0x531c 0x5a1c>; + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + }; + + phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + }; + + dsaf0: dsa@c7000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "hisilicon,hns-dsaf-v2"; + mode = "6port-16rss"; + reg = <0x0 0xc5000000 0x0 0x890000 + 0x0 0xc7000000 0x0 0x600000>; + reg-names = "ppe-base", "dsaf-base"; + interrupt-parent = <&mbigen_dsaf0>; + subctrl-syscon = <&dsa_subctrl>; + reset-field-offset = <0>; + interrupts = + <576 1>, <577 1>, <578 1>, <579 1>, <580 1>, + <581 1>, <582 1>, <583 1>, <584 1>, <585 1>, + <586 1>, <587 1>, <588 1>, <589 1>, <590 1>, + <591 1>, <592 1>, <593 1>, <594 1>, <595 1>, + <596 1>, <597 1>, <598 1>, <599 1>, <600 1>, + <960 1>, <961 1>, <962 1>, <963 1>, <964 1>, + <965 1>, <966 1>, <967 1>, <968 1>, <969 1>, + <970 1>, <971 1>, <972 1>, <973 1>, <974 1>, + <975 1>, <976 1>, <977 1>, <978 1>, <979 1>, + <980 1>, <981 1>, <982 1>, <983 1>, <984 1>, + <985 1>, <986 1>, <987 1>, <988 1>, <989 1>, + <990 1>, <991 1>, <992 1>, <993 1>, <994 1>, + <995 1>, <996 1>, <997 1>, <998 1>, <999 1>, + <1000 1>, <1001 1>, <1002 1>, <1003 1>, <1004 1>, + <1005 1>, <1006 1>, <1007 1>, <1008 1>, <1009 1>, + <1010 1>, <1011 1>, <1012 1>, <1013 1>, <1014 1>, + <1015 1>, <1016 1>, <1017 1>, <1018 1>, <1019 1>, + <1020 1>, <1021 1>, <1022 1>, <1023 1>, <1024 1>, + <1025 1>, <1026 1>, <1027 1>, <1028 1>, <1029 1>, + <1030 1>, <1031 1>, <1032 1>, <1033 1>, <1034 1>, + <1035 1>, <1036 1>, <1037 1>, <1038 1>, <1039 1>, + <1040 1>, <1041 1>, <1042 1>, <1043 1>, <1044 1>, + <1045 1>, <1046 1>, <1047 1>, <1048 1>, <1049 1>, + <1050 1>, <1051 1>, <1052 1>, <1053 1>, <1054 1>, + <1055 1>, <1056 1>, <1057 1>, <1058 1>, <1059 1>, + <1060 1>, <1061 1>, <1062 1>, <1063 1>, <1064 1>, + <1065 1>, <1066 1>, <1067 1>, <1068 1>, <1069 1>, + <1070 1>, <1071 1>, <1072 1>, <1073 1>, <1074 1>, + <1075 1>, <1076 1>, <1077 1>, <1078 1>, <1079 1>, + <1080 1>, <1081 1>, <1082 1>, <1083 1>, <1084 1>, + <1085 1>, <1086 1>, <1087 1>, <1088 1>, <1089 1>, + <1090 1>, <1091 1>, <1092 1>, <1093 1>, <1094 1>, + <1095 1>, <1096 1>, <1097 1>, <1098 1>, <1099 1>, + <1100 1>, <1101 1>, <1102 1>, <1103 1>, <1104 1>, + <1105 1>, <1106 1>, <1107 1>, <1108 1>, <1109 1>, + <1110 1>, <1111 1>, <1112 1>, <1113 1>, <1114 1>, + <1115 1>, <1116 1>, <1117 1>, <1118 1>, <1119 1>, + <1120 1>, <1121 1>, <1122 1>, <1123 1>, <1124 1>, + <1125 1>, <1126 1>, <1127 1>, <1128 1>, <1129 1>, + <1130 1>, <1131 1>, <1132 1>, <1133 1>, <1134 1>, + <1135 1>, <1136 1>, <1137 1>, <1138 1>, <1139 1>, + <1140 1>, <1141 1>, <1142 1>, <1143 1>, <1144 1>, + <1145 1>, <1146 1>, <1147 1>, <1148 1>, <1149 1>, + <1150 1>, <1151 1>, <1152 1>, <1153 1>, <1154 1>, + <1155 1>, <1156 1>, <1157 1>, <1158 1>, <1159 1>, + <1160 1>, <1161 1>, <1162 1>, <1163 1>, <1164 1>, + <1165 1>, <1166 1>, <1167 1>, <1168 1>, <1169 1>, + <1170 1>, <1171 1>, <1172 1>, <1173 1>, <1174 1>, + <1175 1>, <1176 1>, <1177 1>, <1178 1>, <1179 1>, + <1180 1>, <1181 1>, <1182 1>, <1183 1>, <1184 1>, + <1185 1>, <1186 1>, <1187 1>, <1188 1>, <1189 1>, + <1190 1>, <1191 1>, <1192 1>, <1193 1>, <1194 1>, + <1195 1>, <1196 1>, <1197 1>, <1198 1>, <1199 1>, + <1200 1>, <1201 1>, <1202 1>, <1203 1>, <1204 1>, + <1205 1>, <1206 1>, <1207 1>, <1208 1>, <1209 1>, + <1210 1>, <1211 1>, <1212 1>, <1213 1>, <1214 1>, + <1215 1>, <1216 1>, <1217 1>, <1218 1>, <1219 1>, + <1220 1>, <1221 1>, <1222 1>, <1223 1>, <1224 1>, + <1225 1>, <1226 1>, <1227 1>, <1228 1>, <1229 1>, + <1230 1>, <1231 1>, <1232 1>, <1233 1>, <1234 1>, + <1235 1>, <1236 1>, <1237 1>, <1238 1>, <1239 1>, + <1240 1>, <1241 1>, <1242 1>, <1243 1>, <1244 1>, + <1245 1>, <1246 1>, <1247 1>, <1248 1>, <1249 1>, + <1250 1>, <1251 1>, <1252 1>, <1253 1>, <1254 1>, + <1255 1>, <1256 1>, <1257 1>, <1258 1>, <1259 1>, + <1260 1>, <1261 1>, <1262 1>, <1263 1>, <1264 1>, + <1265 1>, <1266 1>, <1267 1>, <1268 1>, <1269 1>, + <1270 1>, <1271 1>, <1272 1>, <1273 1>, <1274 1>, + <1275 1>, <1276 1>, <1277 1>, <1278 1>, <1279 1>, + <1280 1>, <1281 1>, <1282 1>, <1283 1>, <1284 1>, + <1285 1>, <1286 1>, <1287 1>, <1288 1>, <1289 1>, + <1290 1>, <1291 1>, <1292 1>, <1293 1>, <1294 1>, + <1295 1>, <1296 1>, <1297 1>, <1298 1>, <1299 1>, + <1300 1>, <1301 1>, <1302 1>, <1303 1>, <1304 1>, + <1305 1>, <1306 1>, <1307 1>, <1308 1>, <1309 1>, + <1310 1>, <1311 1>, <1312 1>, <1313 1>, <1314 1>, + <1315 1>, <1316 1>, <1317 1>, <1318 1>, <1319 1>, + <1320 1>, <1321 1>, <1322 1>, <1323 1>, <1324 1>, + <1325 1>, <1326 1>, <1327 1>, <1328 1>, <1329 1>, + <1330 1>, <1331 1>, <1332 1>, <1333 1>, <1334 1>, + <1335 1>, <1336 1>, <1337 1>, <1338 1>, <1339 1>, + <1340 1>, <1341 1>, <1342 1>, <1343 1>; + + desc-num = <0x400>; + buf-size = <0x1000>; + dma-coherent; + + port@0 { + reg = <0>; + serdes-syscon = <&serdes_ctrl>; + port-rst-offset = <0>; + port-mode-offset = <0>; + media-type = "fiber"; + }; + + port@1 { + reg = <1>; + serdes-syscon= <&serdes_ctrl>; + port-rst-offset = <1>; + port-mode-offset = <1>; + media-type = "fiber"; + }; + + port@4 { + reg = <4>; + phy-handle = <&phy0>; + serdes-syscon= <&serdes_ctrl>; + port-rst-offset = <4>; + port-mode-offset = <2>; + media-type = "copper"; + }; + + port@5 { + reg = <5>; + phy-handle = <&phy1>; + serdes-syscon= <&serdes_ctrl>; + port-rst-offset = <5>; + port-mode-offset = <3>; + media-type = "copper"; + }; + }; + + eth0: ethernet-4{ + compatible = "hisilicon,hns-nic-v2"; + ae-handle = <&dsaf0>; + port-idx-in-ae = <4>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + dma-coherent; + }; + + eth1: ethernet-5{ + compatible = "hisilicon,hns-nic-v2"; + ae-handle = <&dsaf0>; + port-idx-in-ae = <5>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + dma-coherent; + }; + + eth2: ethernet-0{ + compatible = "hisilicon,hns-nic-v2"; + ae-handle = <&dsaf0>; + port-idx-in-ae = <0>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + dma-coherent; + }; + + eth3: ethernet-1{ + compatible = "hisilicon,hns-nic-v2"; + ae-handle = <&dsaf0>; + port-idx-in-ae = <1>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + dma-coherent; + }; + + sas0: sas@c3000000 { + compatible = "hisilicon,hip06-sas-v2"; + reg = <0 0xc3000000 0 0x10000>; + sas-addr = [50 01 88 20 16 00 00 00]; + hisilicon,sas-syscon = <&dsa_subctrl>; + ctrl-reset-reg = <0xa60>; + ctrl-reset-sts-reg = <0x5a30>; + ctrl-clock-ena-reg = <0x338>; + clocks = <&refclk 0>; + queue-count = <16>; + phy-count = <8>; + dma-coherent; + interrupt-parent = <&mbigen_sas0>; + interrupts = <64 4>,<65 4>,<66 4>,<67 4>,<68 4>, + <69 4>,<70 4>,<71 4>,<72 4>,<73 4>, + <75 4>,<76 4>,<77 4>,<78 4>,<79 4>, + <80 4>,<81 4>,<82 4>,<83 4>,<84 4>, + <85 4>,<86 4>,<87 4>,<88 4>,<89 4>, + <90 4>,<91 4>,<92 4>,<93 4>,<94 4>, + <95 4>,<96 4>,<97 4>,<98 4>,<99 4>, + <100 4>,<101 4>,<102 4>,<103 4>,<104 4>, + <105 4>,<106 4>,<107 4>,<108 4>,<109 4>, + <110 4>,<111 4>,<112 4>,<113 4>,<114 4>, + <115 4>,<116 4>,<117 4>,<118 4>,<119 4>, + <120 4>,<121 4>,<122 4>,<123 4>,<124 4>, + <125 4>,<126 4>,<127 4>,<128 4>,<129 4>, + <130 4>,<131 4>,<132 4>,<133 4>,<134 4>, + <135 4>,<136 4>,<137 4>,<138 4>,<139 4>, + <140 4>,<141 4>,<142 4>,<143 4>,<144 4>, + <145 4>,<146 4>,<147 4>,<148 4>,<149 4>, + <150 4>,<151 4>,<152 4>,<153 4>,<154 4>, + <155 4>,<156 4>,<157 4>,<158 4>,<159 4>, + <160 4>,<601 1>,<602 1>,<603 1>,<604 1>, + <605 1>,<606 1>,<607 1>,<608 1>,<609 1>, + <610 1>,<611 1>,<612 1>,<613 1>,<614 1>, + <615 1>,<616 1>,<617 1>,<618 1>,<619 1>, + <620 1>,<621 1>,<622 1>,<623 1>,<624 1>, + <625 1>,<626 1>,<627 1>,<628 1>,<629 1>, + <630 1>,<631 1>,<632 1>; + status = "disabled"; + }; + + sas1: sas@a2000000 { + compatible = "hisilicon,hip06-sas-v2"; + reg = <0 0xa2000000 0 0x10000>; + sas-addr = [50 01 88 20 16 00 00 00]; + hisilicon,sas-syscon = <&pcie_subctl>; + hip06-sas-v2-quirk-amt; + ctrl-reset-reg = <0xa18>; + ctrl-reset-sts-reg = <0x5a0c>; + ctrl-clock-ena-reg = <0x318>; + clocks = <&refclk 0>; + queue-count = <16>; + phy-count = <8>; + dma-coherent; + interrupt-parent = <&mbigen_sas1>; + interrupts = <64 4>,<65 4>,<66 4>,<67 4>,<68 4>, + <69 4>,<70 4>,<71 4>,<72 4>,<73 4>, + <74 4>,<75 4>,<76 4>,<77 4>,<78 4>, + <79 4>,<80 4>,<81 4>,<82 4>,<83 4>, + <84 4>,<85 4>,<86 4>,<87 4>,<88 4>, + <89 4>,<90 4>,<91 4>,<92 4>,<93 4>, + <94 4>,<95 4>,<96 4>,<97 4>,<98 4>, + <99 4>,<100 4>,<101 4>,<102 4>,<103 4>, + <104 4>,<105 4>,<106 4>,<107 4>,<108 4>, + <109 4>,<110 4>,<111 4>,<112 4>,<113 4>, + <114 4>,<115 4>,<116 4>,<117 4>,<118 4>, + <119 4>,<120 4>,<121 4>,<122 4>,<123 4>, + <124 4>,<125 4>,<126 4>,<127 4>,<128 4>, + <129 4>,<130 4>,<131 4>,<132 4>,<133 4>, + <134 4>,<135 4>,<136 4>,<137 4>,<138 4>, + <139 4>,<140 4>,<141 4>,<142 4>,<143 4>, + <144 4>,<145 4>,<146 4>,<147 4>,<148 4>, + <149 4>,<150 4>,<151 4>,<152 4>,<153 4>, + <154 4>,<155 4>,<156 4>,<157 4>,<158 4>, + <159 4>,<576 1>,<577 1>,<578 1>,<579 1>, + <580 1>,<581 1>,<582 1>,<583 1>,<584 1>, + <585 1>,<586 1>,<587 1>,<588 1>,<589 1>, + <590 1>,<591 1>,<592 1>,<593 1>,<594 1>, + <595 1>,<596 1>,<597 1>,<598 1>,<599 1>, + <600 1>,<601 1>,<602 1>,<603 1>,<604 1>, + <605 1>,<606 1>,<607 1>; + status = "disabled"; + }; + + sas2: sas@a3000000 { + compatible = "hisilicon,hip06-sas-v2"; + reg = <0 0xa3000000 0 0x10000>; + sas-addr = [50 01 88 20 16 00 00 00]; + hisilicon,sas-syscon = <&pcie_subctl>; + ctrl-reset-reg = <0xae0>; + ctrl-reset-sts-reg = <0x5a70>; + ctrl-clock-ena-reg = <0x3a8>; + clocks = <&refclk 0>; + queue-count = <16>; + phy-count = <9>; dma-coherent; + interrupt-parent = <&mbigen_sas2>; + interrupts = <192 4>,<193 4>,<194 4>,<195 4>,<196 4>, + <197 4>,<198 4>,<199 4>,<200 4>,<201 4>, + <202 4>,<203 4>,<204 4>,<205 4>,<206 4>, + <207 4>,<208 4>,<209 4>,<210 4>,<211 4>, + <212 4>,<213 4>,<214 4>,<215 4>,<216 4>, + <217 4>,<218 4>,<219 4>,<220 4>,<221 4>, + <222 4>,<223 4>,<224 4>,<225 4>,<226 4>, + <227 4>,<228 4>,<229 4>,<230 4>,<231 4>, + <232 4>,<233 4>,<234 4>,<235 4>,<236 4>, + <237 4>,<238 4>,<239 4>,<240 4>,<241 4>, + <242 4>,<243 4>,<244 4>,<245 4>,<246 4>, + <247 4>,<248 4>,<249 4>,<250 4>,<251 4>, + <252 4>,<253 4>,<254 4>,<255 4>,<256 4>, + <257 4>,<258 4>,<259 4>,<260 4>,<261 4>, + <262 4>,<263 4>,<264 4>,<265 4>,<266 4>, + <267 4>,<268 4>,<269 4>,<270 4>,<271 4>, + <272 4>,<273 4>,<274 4>,<275 4>,<276 4>, + <277 4>,<278 4>,<279 4>,<280 4>,<281 4>, + <282 4>,<283 4>,<284 4>,<285 4>,<286 4>, + <287 4>,<608 1>,<609 1>,<610 1>,<611 1>, + <612 1>,<613 1>,<614 1>,<615 1>,<616 1>, + <617 1>,<618 1>,<619 1>,<620 1>,<621 1>, + <622 1>,<623 1>,<624 1>,<625 1>,<626 1>, + <627 1>,<628 1>,<629 1>,<630 1>,<631 1>, + <632 1>,<633 1>,<634 1>,<635 1>,<636 1>, + <637 1>,<638 1>,<639 1>; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hip07-d05.dts b/arch/arm64/boot/dts/hisilicon/hip07-d05.dts new file mode 100644 index 000000000000..e05844230583 --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip07-d05.dts @@ -0,0 +1,66 @@ +/** + * dts file for Hisilicon D05 Development Board + * + * Copyright (C) 2016 Hisilicon 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 + * publishhed by the Free Software Foundation. + * + */ + +/dts-v1/; + +#include "hip07.dtsi" + +/ { + model = "Hisilicon Hip07 D05 Development Board"; + compatible = "hisilicon,hip07-d05"; + + /* the mem node will be updated by UEFI. */ + memory@0 { + device_type = "memory"; + reg = <0x0 0x00000000 0x0 0x40000000>; + numa-node-id = <0>; + }; + + distance-map { + compatible = "numa-distance-map-v1"; + distance-matrix = <0 0 10>, + <0 1 15>, + <0 2 20>, + <0 3 25>, + <1 0 15>, + <1 1 10>, + <1 2 25>, + <1 3 30>, + <2 0 20>, + <2 1 25>, + <2 2 10>, + <2 3 15>, + <3 0 25>, + <3 1 30>, + <3 2 15>, + <3 3 10>; + }; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + status = "ok"; +}; + +&usb_ohci { + status = "ok"; +}; + +&usb_ehci { + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi new file mode 100644 index 000000000000..5144eb1c179d --- /dev/null +++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi @@ -0,0 +1,1059 @@ +/** + * dts file for Hisilicon D05 Development Board + * + * Copyright (C) 2016 Hisilicon 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 + * publishhed by the Free Software Foundation. + * + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "hisilicon,hip07-d05"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + cpus { + #address-cells = <1>; + #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>; + }; + }; + + cluster2 { + core0 { + cpu = <&cpu8>; + }; + core1 { + cpu = <&cpu9>; + }; + core2 { + cpu = <&cpu10>; + }; + core3 { + cpu = <&cpu11>; + }; + }; + + cluster3 { + core0 { + cpu = <&cpu12>; + }; + core1 { + cpu = <&cpu13>; + }; + core2 { + cpu = <&cpu14>; + }; + core3 { + cpu = <&cpu15>; + }; + }; + + cluster4 { + core0 { + cpu = <&cpu16>; + }; + core1 { + cpu = <&cpu17>; + }; + core2 { + cpu = <&cpu18>; + }; + core3 { + cpu = <&cpu19>; + }; + }; + + cluster5 { + core0 { + cpu = <&cpu20>; + }; + core1 { + cpu = <&cpu21>; + }; + core2 { + cpu = <&cpu22>; + }; + core3 { + cpu = <&cpu23>; + }; + }; + + cluster6 { + core0 { + cpu = <&cpu24>; + }; + core1 { + cpu = <&cpu25>; + }; + core2 { + cpu = <&cpu26>; + }; + core3 { + cpu = <&cpu27>; + }; + }; + + cluster7 { + core0 { + cpu = <&cpu28>; + }; + core1 { + cpu = <&cpu29>; + }; + core2 { + cpu = <&cpu30>; + }; + core3 { + cpu = <&cpu31>; + }; + }; + + cluster8 { + core0 { + cpu = <&cpu32>; + }; + core1 { + cpu = <&cpu33>; + }; + core2 { + cpu = <&cpu34>; + }; + core3 { + cpu = <&cpu35>; + }; + }; + + cluster9 { + core0 { + cpu = <&cpu36>; + }; + core1 { + cpu = <&cpu37>; + }; + core2 { + cpu = <&cpu38>; + }; + core3 { + cpu = <&cpu39>; + }; + }; + + cluster10 { + core0 { + cpu = <&cpu40>; + }; + core1 { + cpu = <&cpu41>; + }; + core2 { + cpu = <&cpu42>; + }; + core3 { + cpu = <&cpu43>; + }; + }; + + cluster11 { + core0 { + cpu = <&cpu44>; + }; + core1 { + cpu = <&cpu45>; + }; + core2 { + cpu = <&cpu46>; + }; + core3 { + cpu = <&cpu47>; + }; + }; + + cluster12 { + core0 { + cpu = <&cpu48>; + }; + core1 { + cpu = <&cpu49>; + }; + core2 { + cpu = <&cpu50>; + }; + core3 { + cpu = <&cpu51>; + }; + }; + + cluster13 { + core0 { + cpu = <&cpu52>; + }; + core1 { + cpu = <&cpu53>; + }; + core2 { + cpu = <&cpu54>; + }; + core3 { + cpu = <&cpu55>; + }; + }; + + cluster14 { + core0 { + cpu = <&cpu56>; + }; + core1 { + cpu = <&cpu57>; + }; + core2 { + cpu = <&cpu58>; + }; + core3 { + cpu = <&cpu59>; + }; + }; + + cluster15 { + core0 { + cpu = <&cpu60>; + }; + core1 { + cpu = <&cpu61>; + }; + core2 { + cpu = <&cpu62>; + }; + core3 { + cpu = <&cpu63>; + }; + }; + }; + + cpu0: cpu@10000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10000>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + numa-node-id = <0>; + }; + + cpu1: cpu@10001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10001>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + numa-node-id = <0>; + }; + + cpu2: cpu@10002 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10002>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + numa-node-id = <0>; + }; + + cpu3: cpu@10003 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10003>; + enable-method = "psci"; + next-level-cache = <&cluster0_l2>; + numa-node-id = <0>; + }; + + cpu4: cpu@10100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10100>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + numa-node-id = <0>; + }; + + cpu5: cpu@10101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10101>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + numa-node-id = <0>; + }; + + cpu6: cpu@10102 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10102>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + numa-node-id = <0>; + }; + + cpu7: cpu@10103 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10103>; + enable-method = "psci"; + next-level-cache = <&cluster1_l2>; + numa-node-id = <0>; + }; + + cpu8: cpu@10200 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10200>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + numa-node-id = <0>; + }; + + cpu9: cpu@10201 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10201>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + numa-node-id = <0>; + }; + + cpu10: cpu@10202 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10202>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + numa-node-id = <0>; + }; + + cpu11: cpu@10203 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10203>; + enable-method = "psci"; + next-level-cache = <&cluster2_l2>; + numa-node-id = <0>; + }; + + cpu12: cpu@10300 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10300>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + numa-node-id = <0>; + }; + + cpu13: cpu@10301 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10301>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + numa-node-id = <0>; + }; + + cpu14: cpu@10302 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10302>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + numa-node-id = <0>; + }; + + cpu15: cpu@10303 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x10303>; + enable-method = "psci"; + next-level-cache = <&cluster3_l2>; + numa-node-id = <0>; + }; + + cpu16: cpu@30000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30000>; + enable-method = "psci"; + next-level-cache = <&cluster4_l2>; + numa-node-id = <1>; + }; + + cpu17: cpu@30001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30001>; + enable-method = "psci"; + next-level-cache = <&cluster4_l2>; + numa-node-id = <1>; + }; + + cpu18: cpu@30002 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30002>; + enable-method = "psci"; + next-level-cache = <&cluster4_l2>; + numa-node-id = <1>; + }; + + cpu19: cpu@30003 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30003>; + enable-method = "psci"; + next-level-cache = <&cluster4_l2>; + numa-node-id = <1>; + }; + + cpu20: cpu@30100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30100>; + enable-method = "psci"; + next-level-cache = <&cluster5_l2>; + numa-node-id = <1>; + }; + + cpu21: cpu@30101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30101>; + enable-method = "psci"; + next-level-cache = <&cluster5_l2>; + numa-node-id = <1>; + }; + + cpu22: cpu@30102 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30102>; + enable-method = "psci"; + next-level-cache = <&cluster5_l2>; + numa-node-id = <1>; + }; + + cpu23: cpu@30103 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30103>; + enable-method = "psci"; + next-level-cache = <&cluster5_l2>; + numa-node-id = <1>; + }; + + cpu24: cpu@30200 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30200>; + enable-method = "psci"; + next-level-cache = <&cluster6_l2>; + numa-node-id = <1>; + }; + + cpu25: cpu@30201 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30201>; + enable-method = "psci"; + next-level-cache = <&cluster6_l2>; + numa-node-id = <1>; + }; + + cpu26: cpu@30202 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30202>; + enable-method = "psci"; + next-level-cache = <&cluster6_l2>; + numa-node-id = <1>; + }; + + cpu27: cpu@30203 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30203>; + enable-method = "psci"; + next-level-cache = <&cluster6_l2>; + numa-node-id = <1>; + }; + + cpu28: cpu@30300 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30300>; + enable-method = "psci"; + next-level-cache = <&cluster7_l2>; + numa-node-id = <1>; + }; + + cpu29: cpu@30301 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30301>; + enable-method = "psci"; + next-level-cache = <&cluster7_l2>; + numa-node-id = <1>; + }; + + cpu30: cpu@30302 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30302>; + enable-method = "psci"; + next-level-cache = <&cluster7_l2>; + numa-node-id = <1>; + }; + + cpu31: cpu@30303 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x30303>; + enable-method = "psci"; + next-level-cache = <&cluster7_l2>; + numa-node-id = <1>; + }; + + cpu32: cpu@50000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50000>; + enable-method = "psci"; + next-level-cache = <&cluster8_l2>; + numa-node-id = <2>; + }; + + cpu33: cpu@50001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50001>; + enable-method = "psci"; + next-level-cache = <&cluster8_l2>; + numa-node-id = <2>; + }; + + cpu34: cpu@50002 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50002>; + enable-method = "psci"; + next-level-cache = <&cluster8_l2>; + numa-node-id = <2>; + }; + + cpu35: cpu@50003 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50003>; + enable-method = "psci"; + next-level-cache = <&cluster8_l2>; + numa-node-id = <2>; + }; + + cpu36: cpu@50100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50100>; + enable-method = "psci"; + next-level-cache = <&cluster9_l2>; + numa-node-id = <2>; + }; + + cpu37: cpu@50101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50101>; + enable-method = "psci"; + next-level-cache = <&cluster9_l2>; + numa-node-id = <2>; + }; + + cpu38: cpu@50102 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50102>; + enable-method = "psci"; + next-level-cache = <&cluster9_l2>; + numa-node-id = <2>; + }; + + cpu39: cpu@50103 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50103>; + enable-method = "psci"; + next-level-cache = <&cluster9_l2>; + numa-node-id = <2>; + }; + + cpu40: cpu@50200 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50200>; + enable-method = "psci"; + next-level-cache = <&cluster10_l2>; + numa-node-id = <2>; + }; + + cpu41: cpu@50201 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50201>; + enable-method = "psci"; + next-level-cache = <&cluster10_l2>; + numa-node-id = <2>; + }; + + cpu42: cpu@50202 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50202>; + enable-method = "psci"; + next-level-cache = <&cluster10_l2>; + numa-node-id = <2>; + }; + + cpu43: cpu@50203 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50203>; + enable-method = "psci"; + next-level-cache = <&cluster10_l2>; + numa-node-id = <2>; + }; + + cpu44: cpu@50300 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50300>; + enable-method = "psci"; + next-level-cache = <&cluster11_l2>; + numa-node-id = <2>; + }; + + cpu45: cpu@50301 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50301>; + enable-method = "psci"; + next-level-cache = <&cluster11_l2>; + numa-node-id = <2>; + }; + + cpu46: cpu@50302 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50302>; + enable-method = "psci"; + next-level-cache = <&cluster11_l2>; + numa-node-id = <2>; + }; + + cpu47: cpu@50303 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x50303>; + enable-method = "psci"; + next-level-cache = <&cluster11_l2>; + numa-node-id = <2>; + }; + + cpu48: cpu@70000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70000>; + enable-method = "psci"; + next-level-cache = <&cluster12_l2>; + numa-node-id = <3>; + }; + + cpu49: cpu@70001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70001>; + enable-method = "psci"; + next-level-cache = <&cluster12_l2>; + numa-node-id = <3>; + }; + + cpu50: cpu@70002 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70002>; + enable-method = "psci"; + next-level-cache = <&cluster12_l2>; + numa-node-id = <3>; + }; + + cpu51: cpu@70003 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70003>; + enable-method = "psci"; + next-level-cache = <&cluster12_l2>; + numa-node-id = <3>; + }; + + cpu52: cpu@70100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70100>; + enable-method = "psci"; + next-level-cache = <&cluster13_l2>; + numa-node-id = <3>; + }; + + cpu53: cpu@70101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70101>; + enable-method = "psci"; + next-level-cache = <&cluster13_l2>; + numa-node-id = <3>; + }; + + cpu54: cpu@70102 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70102>; + enable-method = "psci"; + next-level-cache = <&cluster13_l2>; + numa-node-id = <3>; + }; + + cpu55: cpu@70103 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70103>; + enable-method = "psci"; + next-level-cache = <&cluster13_l2>; + numa-node-id = <3>; + }; + + cpu56: cpu@70200 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70200>; + enable-method = "psci"; + next-level-cache = <&cluster14_l2>; + numa-node-id = <3>; + }; + + cpu57: cpu@70201 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70201>; + enable-method = "psci"; + next-level-cache = <&cluster14_l2>; + numa-node-id = <3>; + }; + + cpu58: cpu@70202 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70202>; + enable-method = "psci"; + next-level-cache = <&cluster14_l2>; + numa-node-id = <3>; + }; + + cpu59: cpu@70203 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70203>; + enable-method = "psci"; + next-level-cache = <&cluster14_l2>; + numa-node-id = <3>; + }; + + cpu60: cpu@70300 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70300>; + enable-method = "psci"; + next-level-cache = <&cluster15_l2>; + numa-node-id = <3>; + }; + + cpu61: cpu@70301 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70301>; + enable-method = "psci"; + next-level-cache = <&cluster15_l2>; + numa-node-id = <3>; + }; + + cpu62: cpu@70302 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70302>; + enable-method = "psci"; + next-level-cache = <&cluster15_l2>; + numa-node-id = <3>; + }; + + cpu63: cpu@70303 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x70303>; + enable-method = "psci"; + next-level-cache = <&cluster15_l2>; + numa-node-id = <3>; + }; + + cluster0_l2: l2-cache0 { + compatible = "cache"; + }; + + cluster1_l2: l2-cache1 { + compatible = "cache"; + }; + + cluster2_l2: l2-cache2 { + compatible = "cache"; + }; + + cluster3_l2: l2-cache3 { + compatible = "cache"; + }; + + cluster4_l2: l2-cache4 { + compatible = "cache"; + }; + + cluster5_l2: l2-cache5 { + compatible = "cache"; + }; + + cluster6_l2: l2-cache6 { + compatible = "cache"; + }; + + cluster7_l2: l2-cache7 { + compatible = "cache"; + }; + + cluster8_l2: l2-cache8 { + compatible = "cache"; + }; + + cluster9_l2: l2-cache9 { + compatible = "cache"; + }; + + cluster10_l2: l2-cache10 { + compatible = "cache"; + }; + + cluster11_l2: l2-cache11 { + compatible = "cache"; + }; + + cluster12_l2: l2-cache12 { + compatible = "cache"; + }; + + cluster13_l2: l2-cache13 { + compatible = "cache"; + }; + + cluster14_l2: l2-cache14 { + compatible = "cache"; + }; + + cluster15_l2: l2-cache15 { + compatible = "cache"; + }; + }; + + gic: interrupt-controller@4d000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + #redistributor-regions = <4>; + redistributor-stride = <0x0 0x40000>; + reg = <0x0 0x4d000000 0x0 0x10000>, /* GICD */ + <0x0 0x4d100000 0x0 0x400000>, /* p0 GICR node 0 */ + <0x0 0x6d100000 0x0 0x400000>, /* p0 GICR node 1 */ + <0x400 0x4d100000 0x0 0x400000>, /* p1 GICR node 2 */ + <0x400 0x6d100000 0x0 0x400000>, /* p1 GICR node 3 */ + <0x0 0xfe000000 0x0 0x10000>, /* GICC */ + <0x0 0xfe010000 0x0 0x10000>, /* GICH */ + <0x0 0xfe020000 0x0 0x10000>; /* GICV */ + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; + + p0_its_peri_a: interrupt-controller@4c000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x4c000000 0x0 0x40000>; + }; + + p0_its_peri_b: interrupt-controller@6c000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x6c000000 0x0 0x40000>; + }; + + p0_its_dsa_a: interrupt-controller@c6000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0xc6000000 0x0 0x40000>; + }; + + p0_its_dsa_b: interrupt-controller@8,c6000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x8 0xc6000000 0x0 0x40000>; + }; + + p1_its_peri_a: interrupt-controller@400,4c000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x4c000000 0x0 0x40000>; + }; + + p1_its_peri_b: interrupt-controller@400,6c000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x6c000000 0x0 0x40000>; + }; + + p1_its_dsa_a: interrupt-controller@400,c6000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0xc6000000 0x0 0x40000>; + }; + + p1_its_dsa_b: interrupt-controller@408,c6000000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x408 0xc6000000 0x0 0x40000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; + }; + + pmu { + compatible = "arm,cortex-a72-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; + }; + + p0_mbigen_peri_b: interrupt-controller@60080000 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x0 0x60080000 0x0 0x10000>; + + mbigen_uart: uart_intc { + msi-parent = <&p0_its_peri_b 0x120c7>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <1>; + }; + }; + + p0_mbigen_pcie_a: interrupt-controller@a0080000 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x0 0xa0080000 0x0 0x10000>; + + mbigen_usb: intc_usb { + msi-parent = <&p0_its_dsa_a 0x40080>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <2>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + uart0: uart@602b0000 { + compatible = "arm,sbsa-uart"; + reg = <0x0 0x602b0000 0x0 0x1000>; + interrupt-parent = <&mbigen_uart>; + interrupts = <807 4>; + current-speed = <115200>; + reg-io-width = <4>; + status = "disabled"; + }; + + usb_ohci: ohci@a7030000 { + compatible = "generic-ohci"; + reg = <0x0 0xa7030000 0x0 0x10000>; + interrupt-parent = <&mbigen_usb>; + interrupts = <640 4>; + dma-coherent; + status = "disabled"; + }; + + usb_ehci: ehci@a7020000 { + compatible = "generic-ehci"; + reg = <0x0 0xa7020000 0x0 0x10000>; + interrupt-parent = <&mbigen_usb>; + interrupts = <641 4>; + dma-coherent; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile index 308468d377d0..1690883b931a 100644 --- a/arch/arm64/boot/dts/marvell/Makefile +++ b/arch/arm64/boot/dts/marvell/Makefile @@ -4,7 +4,9 @@ dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-stb.dtb # Mvebu SoC Family 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-db.dtb always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts index 1372e9a6aaa4..89de0a751093 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts @@ -56,7 +56,7 @@ stdout-path = "serial0:115200n8"; }; - memory { + memory@0 { device_type = "memory"; reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; @@ -81,3 +81,26 @@ &pcie0 { status = "okay"; }; + +&mdio { + status = "okay"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +ð0 { + phy-mode = "rgmii-id"; + phy = <&phy0>; + status = "okay"; +}; + +ð1 { + phy-mode = "sgmii"; + phy = <&phy1>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts new file mode 100644 index 000000000000..83178d909fc2 --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts @@ -0,0 +1,82 @@ +/* + * Device Tree file for Globalscale Marvell ESPRESSOBin Board + * Copyright (C) 2016 Marvell + * + * Romain Perier <romain.perier@free-electrons.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 , 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 "armada-372x.dtsi" + +/ { + model = "Globalscale Marvell ESPRESSOBin Board"; + compatible = "globalscale,espressobin", "marvell,armada3720", "marvell,armada3710"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; +}; + +/* J9 */ +&pcie0 { + status = "okay"; +}; + +/* J6 */ +&sata { + status = "okay"; +}; + +/* Exported on the micro USB connector J5 through an FTDI */ +&uart0 { + status = "okay"; +}; + +/* J7 */ +&usb3 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index c4762538ec01..bab5c6ff5745 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -91,7 +91,7 @@ #size-cells = <2>; ranges; - internal-regs { + internal-regs@d0000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; @@ -105,7 +105,7 @@ status = "disabled"; }; - nb_perih_clk: nb-periph-clk@13000{ + nb_periph_clk: nb-periph-clk@13000 { compatible = "marvell,armada-3700-periph-clock-nb"; reg = <0x13000 0x100>; clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, @@ -113,7 +113,7 @@ #clock-cells = <1>; }; - sb_perih_clk: sb-periph-clk@18000{ + sb_periph_clk: sb-periph-clk@18000 { compatible = "marvell,armada-3700-periph-clock-sb"; reg = <0x18000 0x100>; clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, @@ -140,6 +140,29 @@ }; }; + eth0: ethernet@30000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x30000 0x4000>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sb_periph_clk 8>; + status = "disabled"; + }; + + mdio: mdio@32004 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x32004 0x4>; + }; + + eth1: ethernet@40000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x40000 0x4000>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sb_periph_clk 7>; + status = "disabled"; + }; + usb3: usb@58000 { compatible = "marvell,armada3700-xhci", "generic-xhci"; diff --git a/arch/arm64/boot/dts/marvell/armada-8020.dtsi b/arch/arm64/boot/dts/marvell/armada-8020.dtsi index 3753c1c6d54d..048e5cf5160e 100644 --- a/arch/arm64/boot/dts/marvell/armada-8020.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-8020.dtsi @@ -47,6 +47,7 @@ #include "armada-ap806-dual.dtsi" #include "armada-cp110-master.dtsi" +#include "armada-cp110-slave.dtsi" / { model = "Marvell Armada 8020"; diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts new file mode 100644 index 000000000000..6e6f182fb297 --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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. + */ + +/* + * Device Tree file for Marvell Armada 8040 Development board platform + */ + +#include "armada-8040.dtsi" + +/ { + model = "Marvell Armada 8040 DB board"; + compatible = "marvell,armada8040-db", "marvell,armada8040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; + }; + }; + }; +}; + +/* Accessible over the mini-USB CON9 connector on the main board */ +&uart0 { + status = "okay"; +}; + + +/* CON5 on CP0 expansion */ +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +/* CON4 on CP0 expansion */ +&cpm_sata0 { + status = "okay"; +}; + +/* CON9 on CP0 expansion */ +&cpm_usb3_0 { + status = "okay"; +}; + +/* CON10 on CP0 expansion */ +&cpm_usb3_1 { + status = "okay"; +}; + +/* CON5 on CP1 expansion */ +&cps_pcie2 { + status = "okay"; +}; + +&cps_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +/* CON4 on CP1 expansion */ +&cps_sata0 { + status = "okay"; +}; + +/* CON9 on CP1 expansion */ +&cps_usb3_0 { + status = "okay"; +}; + +/* CON10 on CP1 expansion */ +&cps_usb3_1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/marvell/armada-8040.dtsi b/arch/arm64/boot/dts/marvell/armada-8040.dtsi index 8bd0d8f8ad4c..9c1b28c47683 100644 --- a/arch/arm64/boot/dts/marvell/armada-8040.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-8040.dtsi @@ -47,6 +47,7 @@ #include "armada-ap806-quad.dtsi" #include "armada-cp110-master.dtsi" +#include "armada-cp110-slave.dtsi" / { model = "Marvell Armada 8040"; diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi index c2a6745f168c..a749ba2edec4 100644 --- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi @@ -71,7 +71,7 @@ interrupt-parent = <&gic>; ranges; - config-space { + config-space@f0000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; @@ -128,6 +128,12 @@ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; }; + pmu { + compatible = "arm,cortex-a72-pmu"; + interrupt-parent = <&pic>; + interrupts = <17>; + }; + odmi: odmi@300000 { compatible = "marvell,odmi-controller"; interrupt-controller; @@ -140,6 +146,14 @@ marvell,spi-base = <128>, <136>, <144>, <152>; }; + pic: interrupt-controller@3f0100 { + compatible = "marvell,armada-8k-pic"; + reg = <0x3f0100 0x10>; + #interrupt-cells = <1>; + interrupt-controller; + interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>; + }; + xor@400000 { compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; reg = <0x400000 0x1000>, diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi index da31bbbbb59e..05222f749a45 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi @@ -52,7 +52,7 @@ interrupt-parent = <&gic>; ranges; - config-space { + config-space@f2000000 { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; @@ -131,7 +131,7 @@ #address-cells = <0x1>; #size-cells = <0x0>; cell-index = <1>; - clocks = <&cpm_syscon0 0 3>; + clocks = <&cpm_syscon0 1 21>; status = "disabled"; }; @@ -164,6 +164,14 @@ clocks = <&cpm_syscon0 1 21>; status = "disabled"; }; + + cpm_trng: trng@760000 { + compatible = "marvell,armada-8k-rng", "inside-secure,safexcel-eip76"; + reg = <0x760000 0x7d>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpm_syscon0 1 25>; + status = "okay"; + }; }; cpm_pcie0: pcie@f2600000 { @@ -176,6 +184,7 @@ #interrupt-cells = <1>; device_type = "pci"; dma-coherent; + msi-parent = <&gic_v2m0>; bus-range = <0 0xff>; ranges = @@ -201,6 +210,7 @@ #interrupt-cells = <1>; device_type = "pci"; dma-coherent; + msi-parent = <&gic_v2m0>; bus-range = <0 0xff>; ranges = @@ -227,6 +237,7 @@ #interrupt-cells = <1>; device_type = "pci"; dma-coherent; + msi-parent = <&gic_v2m0>; bus-range = <0 0xff>; ranges = diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi new file mode 100644 index 000000000000..638820ce977d --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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. + */ + +/* + * Device Tree file for Marvell Armada CP110 Slave. + */ + +/ { + cp110-slave { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space@f4000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0x0 0xf4000000 0x2000000>; + + cps_syscon0: system-controller@440000 { + compatible = "marvell,cp110-system-controller0", + "syscon"; + reg = <0x440000 0x1000>; + #clock-cells = <2>; + core-clock-output-names = + "cps-apll", "cps-ppv2-core", "cps-eip", + "cps-core", "cps-nand-core"; + gate-clock-output-names = + "cps-audio", "cps-communit", "cps-nand", + "cps-ppv2", "cps-sdio", "cps-mg-domain", + "cps-mg-core", "cps-xor1", "cps-xor0", + "cps-gop-dp", "none", "cps-pcie_x10", + "cps-pcie_x11", "cps-pcie_x4", "cps-pcie-xor", + "cps-sata", "cps-sata-usb", "cps-main", + "cps-sd-mmc", "none", "none", + "cps-slow-io", "cps-usb3h0", "cps-usb3h1", + "cps-usb3dev", "cps-eip150", "cps-eip197"; + }; + + cps_sata0: sata@540000 { + compatible = "marvell,armada-8k-ahci"; + reg = <0x540000 0x30000>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 15>; + status = "disabled"; + }; + + cps_usb3_0: usb3@500000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x500000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 22>; + status = "disabled"; + }; + + cps_usb3_1: usb3@510000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x510000 0x4000>; + dma-coherent; + interrupts = <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 23>; + status = "disabled"; + }; + + cps_xor0: xor@6a0000 { + compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; + reg = <0x6a0000 0x1000>, + <0x6b0000 0x1000>; + dma-coherent; + msi-parent = <&gic_v2m0>; + clocks = <&cps_syscon0 1 8>; + }; + + cps_xor1: xor@6c0000 { + compatible = "marvell,armada-7k-xor", "marvell,xor-v2"; + reg = <0x6c0000 0x1000>, + <0x6d0000 0x1000>; + dma-coherent; + msi-parent = <&gic_v2m0>; + clocks = <&cps_syscon0 1 7>; + }; + + cps_spi0: spi@700600 { + compatible = "marvell,armada-380-spi"; + reg = <0x700600 0x50>; + #address-cells = <0x1>; + #size-cells = <0x0>; + cell-index = <3>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_spi1: spi@700680 { + compatible = "marvell,armada-380-spi"; + reg = <0x700680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <4>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_i2c0: i2c@701000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_i2c1: i2c@701100 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 21>; + status = "disabled"; + }; + + cps_trng: trng@760000 { + compatible = "marvell,armada-8k-rng", "inside-secure,safexcel-eip76"; + reg = <0x760000 0x7d>; + interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cps_syscon0 1 25>; + status = "okay"; + }; + }; + + cps_pcie0: pcie@f4600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4600000 0 0x10000>, + <0 0xfaf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd000000 0 0xfd000000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfa000000 0 0xfa000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; + num-lanes = <1>; + clocks = <&cps_syscon0 1 13>; + status = "disabled"; + }; + + cps_pcie1: pcie@f4620000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4620000 0 0x10000>, + <0 0xfbf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd010000 0 0xfd010000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfb000000 0 0xfb000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cps_syscon0 1 11>; + status = "disabled"; + }; + + cps_pcie2: pcie@f4640000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf4640000 0 0x10000>, + <0 0xfcf00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + msi-parent = <&gic_v2m0>; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xfd020000 0 0xfd020000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xfc000000 0 0xfc000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>; + + num-lanes = <1>; + clocks = <&cps_syscon0 1 12>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts b/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts index 0d70d39fa8d2..fae6c6924705 100644 --- a/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts +++ b/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts @@ -54,7 +54,7 @@ stdout-path = "serial0:115200n8"; }; - memory { + memory@1000000 { device_type = "memory"; /* the first 16MB is for firmwares' usage */ reg = <0 0x01000000 0 0x7f000000>; diff --git a/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts b/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts index 348c37ecf069..d47edad13e68 100644 --- a/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts +++ b/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts @@ -54,7 +54,7 @@ stdout-path = "serial0:115200n8"; }; - memory { + memory@1000000 { device_type = "memory"; /* the first 16MB is for firmwares' usage */ reg = <0 0x01000000 0 0x7f000000>; diff --git a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi b/arch/arm64/boot/dts/marvell/berlin4ct.dtsi index 099ad93bb49b..d6b800fd26d0 100644 --- a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi +++ b/arch/arm64/boot/dts/marvell/berlin4ct.dtsi @@ -68,6 +68,7 @@ device_type = "cpu"; reg = <0x0>; enable-method = "psci"; + next-level-cache = <&l2>; cpu-idle-states = <&CPU_SLEEP_0>; }; @@ -76,6 +77,7 @@ device_type = "cpu"; reg = <0x1>; enable-method = "psci"; + next-level-cache = <&l2>; cpu-idle-states = <&CPU_SLEEP_0>; }; @@ -84,6 +86,7 @@ device_type = "cpu"; reg = <0x2>; enable-method = "psci"; + next-level-cache = <&l2>; cpu-idle-states = <&CPU_SLEEP_0>; }; @@ -92,9 +95,14 @@ 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 { @@ -115,7 +123,7 @@ }; pmu { - compatible = "arm,armv8-pmuv3"; + compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3"; interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>, @@ -134,7 +142,7 @@ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; }; - soc { + soc@f7000000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; @@ -279,7 +287,6 @@ reg = <0x4000 0x100>; clocks = <&osc>; interrupts = <1>; - status = "disabled"; }; wdt2: watchdog@5000 { @@ -287,7 +294,6 @@ reg = <0x5000 0x100>; clocks = <&osc>; interrupts = <2>; - status = "disabled"; }; sm_gpio0: gpio@8000 { diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts index 7453a47b3047..0ecaad4333a7 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts @@ -34,6 +34,23 @@ chosen { }; + connector { + compatible = "hdmi-connector"; + label = "hdmi"; + type = "d"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi0_out>; + }; + }; + }; + + extcon_usb: extcon_iddig { + compatible = "linux,extcon-usb-gpio"; + id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>; + }; + usb_p1_vbus: regulator@0 { compatible = "regulator-fixed"; regulator-name = "usb_vbus"; @@ -42,6 +59,41 @@ gpio = <&pio 130 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + usb_p0_vbus: regulator@1 { + compatible = "regulator-fixed"; + regulator-name = "vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pio 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&cec { + status = "okay"; +}; + +&dpi0 { + status = "okay"; +}; + +&hdmi_phy { + status = "okay"; +}; + +&hdmi0 { + status = "okay"; + + ports { + port@1 { + reg = <1>; + + hdmi0_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; }; &i2c1 { @@ -205,6 +257,20 @@ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; }; }; + + usb_id_pins_float: usb_iddig_pull_up { + pins_iddig { + pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>; + bias-pull-up; + }; + }; + + usb_id_pins_ground: usb_iddig_pull_down { + pins_iddig { + pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>; + bias-pull-down; + }; + }; }; &pwm0 { @@ -431,12 +497,25 @@ status = "okay"; }; +&ssusb { + vusb33-supply = <&mt6397_vusb_reg>; + vbus-supply = <&usb_p0_vbus>; + extcon = <&extcon_usb>; + dr_mode = "otg"; + mediatek,enable-wakeup; + pinctrl-names = "default", "id_float", "id_ground"; + pinctrl-0 = <&usb_id_pins_float>; + pinctrl-1 = <&usb_id_pins_float>; + pinctrl-2 = <&usb_id_pins_ground>; + status = "okay"; +}; + &uart0 { status = "okay"; }; -&usb30 { +&usb_host { vusb33-supply = <&mt6397_vusb_reg>; vbus-supply = <&usb_p1_vbus>; - mediatek,wakeup-src = <1>; + status = "okay"; }; diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 10f638f4e7d8..12e702771f5c 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -41,6 +41,14 @@ dpi0 = &dpi0; dsi0 = &dsi0; dsi1 = &dsi1; + mdp_rdma0 = &mdp_rdma0; + mdp_rdma1 = &mdp_rdma1; + mdp_rsz0 = &mdp_rsz0; + mdp_rsz1 = &mdp_rsz1; + mdp_rsz2 = &mdp_rsz2; + mdp_wdma0 = &mdp_wdma0; + mdp_wrot0 = &mdp_wrot0; + mdp_wrot1 = &mdp_wrot1; }; cpus { @@ -254,6 +262,16 @@ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>; + hdmi_pin: xxx { + + /*hdmi htplg pin*/ + pins1 { + pinmux = <MT8173_PIN_21_HTPLG__FUNC_HTPLG>; + input-enable; + bias-pull-down; + }; + }; + i2c0_pins_a: i2c0 { pins1 { pinmux = <MT8173_PIN_45_SDA0__FUNC_SDA0>, @@ -341,6 +359,14 @@ clock-names = "spi", "wrap"; }; + cec: cec@10013000 { + compatible = "mediatek,mt8173-cec"; + reg = <0 0x10013000 0 0xbc>; + interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_LOW>; + clocks = <&infracfg CLK_INFRA_CEC>; + status = "disabled"; + }; + vpu: vpu@10020000 { compatible = "mediatek,mt8173-vpu"; reg = <0 0x10020000 0 0x30000>, @@ -383,6 +409,19 @@ #clock-cells = <1>; }; + hdmi_phy: hdmi-phy@10209100 { + compatible = "mediatek,mt8173-hdmi-phy"; + reg = <0 0x10209100 0 0x24>; + clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; + clock-names = "pll_ref"; + clock-output-names = "hdmitx_dig_cts"; + mediatek,ibias = <0xa>; + mediatek,ibias_up = <0x1c>; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; @@ -419,6 +458,9 @@ auxadc: auxadc@11001000 { compatible = "mediatek,mt8173-auxadc"; reg = <0 0x11001000 0 0x1000>; + clocks = <&pericfg CLK_PERI_AUXADC>; + clock-names = "main"; + #io-channel-cells = <1>; }; uart0: serial@11002000 { @@ -577,6 +619,14 @@ status = "disabled"; }; + hdmiddc0: i2c@11012000 { + compatible = "mediatek,mt8173-hdmi-ddc"; + interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_LOW>; + reg = <0 0x11012000 0 0x1C>; + clocks = <&pericfg CLK_PERI_I2C5>; + clock-names = "ddc-i2c"; + }; + i2c6: i2c@11013000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11013000 0 0x70>, @@ -668,11 +718,14 @@ status = "disabled"; }; - usb30: usb@11270000 { - compatible = "mediatek,mt8173-xhci"; - reg = <0 0x11270000 0 0x1000>, + ssusb: usb@11271000 { + compatible = "mediatek,mt8173-mtu3"; + reg = <0 0x11271000 0 0x3000>, <0 0x11280700 0 0x0100>; - interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>; + reg-names = "mac", "ippc"; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>; + phys = <&phy_port0 PHY_TYPE_USB3>, + <&phy_port1 PHY_TYPE_USB2>; power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>; clocks = <&topckgen CLK_TOP_USB30_SEL>, <&pericfg CLK_PERI_USB0>, @@ -680,10 +733,22 @@ clock-names = "sys_ck", "wakeup_deb_p0", "wakeup_deb_p1"; - phys = <&phy_port0 PHY_TYPE_USB3>, - <&phy_port1 PHY_TYPE_USB2>; mediatek,syscon-wakeup = <&pericfg>; - status = "okay"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + usb_host: xhci@11270000 { + compatible = "mediatek,mt8173-xhci"; + reg = <0 0x11270000 0 0x1000>; + reg-names = "mac"; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>; + clocks = <&topckgen CLK_TOP_USB30_SEL>; + clock-names = "sys_ck"; + status = "disabled"; + }; }; u3phy: usb-phy@11290000 { @@ -716,6 +781,82 @@ #clock-cells = <1>; }; + mdp { + compatible = "mediatek,mt8173-mdp"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + mediatek,vpu = <&vpu>; + + mdp_rdma0: rdma@14001000 { + compatible = "mediatek,mt8173-mdp-rdma"; + reg = <0 0x14001000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_RDMA0>, + <&mmsys CLK_MM_MUTEX_32K>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + iommus = <&iommu M4U_PORT_MDP_RDMA0>; + mediatek,larb = <&larb0>; + }; + + mdp_rdma1: rdma@14002000 { + compatible = "mediatek,mt8173-mdp-rdma"; + reg = <0 0x14002000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_RDMA1>, + <&mmsys CLK_MM_MUTEX_32K>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + iommus = <&iommu M4U_PORT_MDP_RDMA1>; + mediatek,larb = <&larb4>; + }; + + mdp_rsz0: rsz@14003000 { + compatible = "mediatek,mt8173-mdp-rsz"; + reg = <0 0x14003000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_RSZ0>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + }; + + mdp_rsz1: rsz@14004000 { + compatible = "mediatek,mt8173-mdp-rsz"; + reg = <0 0x14004000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_RSZ1>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + }; + + mdp_rsz2: rsz@14005000 { + compatible = "mediatek,mt8173-mdp-rsz"; + reg = <0 0x14005000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_RSZ2>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + }; + + mdp_wdma0: wdma@14006000 { + compatible = "mediatek,mt8173-mdp-wdma"; + reg = <0 0x14006000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_WDMA>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + iommus = <&iommu M4U_PORT_MDP_WDMA>; + mediatek,larb = <&larb0>; + }; + + mdp_wrot0: wrot@14007000 { + compatible = "mediatek,mt8173-mdp-wrot"; + reg = <0 0x14007000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_WROT0>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + iommus = <&iommu M4U_PORT_MDP_WROT0>; + mediatek,larb = <&larb0>; + }; + + mdp_wrot1: wrot@14008000 { + compatible = "mediatek,mt8173-mdp-wrot"; + reg = <0 0x14008000 0 0x1000>; + clocks = <&mmsys CLK_MM_MDP_WROT1>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + iommus = <&iommu M4U_PORT_MDP_WROT1>; + mediatek,larb = <&larb4>; + }; + }; + ovl0: ovl@1400c000 { compatible = "mediatek,mt8173-disp-ovl"; reg = <0 0x1400c000 0 0x1000>; @@ -885,6 +1026,12 @@ <&apmixedsys CLK_APMIXED_TVDPLL>; clock-names = "pixel", "engine", "pll"; status = "disabled"; + + port { + dpi0_out: endpoint { + remote-endpoint = <&hdmi0_in>; + }; + }; }; pwm0: pwm@1401e000 { @@ -942,6 +1089,38 @@ clocks = <&mmsys CLK_MM_DISP_OD>; }; + hdmi0: hdmi@14025000 { + compatible = "mediatek,mt8173-hdmi"; + reg = <0 0x14025000 0 0x400>; + interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_LOW>; + clocks = <&mmsys CLK_MM_HDMI_PIXEL>, + <&mmsys CLK_MM_HDMI_PLLCK>, + <&mmsys CLK_MM_HDMI_AUDIO>, + <&mmsys CLK_MM_HDMI_SPDIF>; + clock-names = "pixel", "pll", "bclk", "spdif"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pin>; + phys = <&hdmi_phy>; + phy-names = "hdmi"; + mediatek,syscon-hdmi = <&mmsys 0x900>; + assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; + assigned-clock-parents = <&hdmi_phy>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; + }; + }; + }; + }; + larb4: larb@14027000 { compatible = "mediatek,mt8173-smi-larb"; reg = <0 0x14027000 0 0x1000>; @@ -974,6 +1153,50 @@ #clock-cells = <1>; }; + vcodec_dec: vcodec@16000000 { + compatible = "mediatek,mt8173-vcodec-dec"; + reg = <0 0x16000000 0 0x100>, /* VDEC_SYS */ + <0 0x16020000 0 0x1000>, /* VDEC_MISC */ + <0 0x16021000 0 0x800>, /* VDEC_LD */ + <0 0x16021800 0 0x800>, /* VDEC_TOP */ + <0 0x16022000 0 0x1000>, /* VDEC_CM */ + <0 0x16023000 0 0x1000>, /* VDEC_AD */ + <0 0x16024000 0 0x1000>, /* VDEC_AV */ + <0 0x16025000 0 0x1000>, /* VDEC_PP */ + <0 0x16026800 0 0x800>, /* VDEC_HWD */ + <0 0x16027000 0 0x800>, /* VDEC_HWQ */ + <0 0x16027800 0 0x800>, /* VDEC_HWB */ + <0 0x16028400 0 0x400>; /* VDEC_HWG */ + interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>; + mediatek,larb = <&larb1>; + iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>, + <&iommu M4U_PORT_HW_VDEC_PP_EXT>, + <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>, + <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>, + <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>, + <&iommu M4U_PORT_HW_VDEC_UFO_EXT>, + <&iommu M4U_PORT_HW_VDEC_VLD_EXT>, + <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>; + mediatek,vpu = <&vpu>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>; + clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>, + <&topckgen CLK_TOP_UNIVPLL_D2>, + <&topckgen CLK_TOP_CCI400_SEL>, + <&topckgen CLK_TOP_VDEC_SEL>, + <&topckgen CLK_TOP_VCODECPLL>, + <&apmixedsys CLK_APMIXED_VENCPLL>, + <&topckgen CLK_TOP_VENC_LT_SEL>, + <&topckgen CLK_TOP_VCODECPLL_370P5>; + clock-names = "vcodecpll", + "univpll_d2", + "clk_cci400_sel", + "vdec_sel", + "vdecpll", + "vencpll", + "venc_lt_sel", + "vdec_bus_clk_src"; + }; + larb1: larb@16010000 { compatible = "mediatek,mt8173-smi-larb"; reg = <0 0x16010000 0 0x1000>; diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile index 0f7cdf3e05c1..18941458cb4d 100644 --- a/arch/arm64/boot/dts/nvidia/Makefile +++ b/arch/arm64/boot/dts/nvidia/Makefile @@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb +dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb always := $(dtb-y) clean-files := *.dtb diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi index 2013f8916084..3f3a46a4bd01 100644 --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi @@ -4,6 +4,7 @@ #include <dt-bindings/pinctrl/pinctrl-tegra.h> #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/thermal/tegra124-soctherm.h> / { compatible = "nvidia,tegra132", "nvidia,tegra124"; @@ -727,8 +728,10 @@ }; soctherm: thermal-sensor@700e2000 { - compatible = "nvidia,tegra124-soctherm"; - reg = <0x0 0x700e2000 0x0 0x1000>; + compatible = "nvidia,tegra132-soctherm"; + reg = <0x0 0x700e2000 0x0 0x600 /* 0: SOC_THERM reg_base */ + 0x0 0x70040000 0x0 0x200>; /* 2: CCROC reg_base */ + reg-names = "soctherm-reg", "ccroc-reg"; interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; clocks = <&tegra_car TEGRA124_CLK_TSENSOR>, <&tegra_car TEGRA124_CLK_SOC_THERM>; @@ -736,6 +739,118 @@ resets = <&tegra_car 78>; reset-names = "soctherm"; #thermal-sensor-cells = <1>; + + throttle-cfgs { + throttle_heavy: heavy { + nvidia,priority = <100>; + nvidia,cpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>; + + #cooling-cells = <2>; + }; + }; + }; + + thermal-zones { + cpu { + polling-delay-passive = <1000>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>; + + trips { + cpu_shutdown_trip { + temperature = <105000>; + hysteresis = <1000>; + type = "critical"; + }; + + cpu_throttle_trip: throttle-trip { + temperature = <102000>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; + }; + mem { + polling-delay-passive = <0>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>; + + trips { + mem_shutdown_trip { + temperature = <101000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; + }; + gpu { + polling-delay-passive = <1000>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>; + + trips { + gpu_shutdown_trip { + temperature = <101000>; + hysteresis = <1000>; + type = "critical"; + }; + + gpu_throttle_trip: throttle-trip { + temperature = <99000>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; + }; + pllx { + polling-delay-passive = <0>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>; + + trips { + pllx_shutdown_trip { + temperature = <105000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; + }; }; ahub@70300000 { diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts new file mode 100644 index 000000000000..0d3c0996d832 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts @@ -0,0 +1,8 @@ +/dts-v1/; + +#include "tegra186-p3310.dtsi" + +/ { + model = "NVIDIA Tegra186 P2771-0000 Development Board"; + compatible = "nvidia,p2771-0000", "nvidia,tegra186"; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi new file mode 100644 index 000000000000..1abe2eceb3d1 --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi @@ -0,0 +1,64 @@ +#include "tegra186.dtsi" + +/ { + model = "NVIDIA Tegra186 P3310 Processor Module"; + compatible = "nvidia,p3310", "nvidia,tegra186"; + + aliases { + serial0 = &uarta; + }; + + chosen { + bootargs = "earlycon console=ttyS0,115200n8"; + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + serial@3100000 { + status = "okay"; + }; + + hsp@3c00000 { + status = "okay"; + }; + + cpus { + cpu@0 { + enable-method = "psci"; + }; + + cpu@1 { + enable-method = "psci"; + }; + + cpu@2 { + enable-method = "psci"; + }; + + cpu@3 { + enable-method = "psci"; + }; + + cpu@4 { + enable-method = "psci"; + }; + + cpu@5 { + enable-method = "psci"; + }; + }; + + bpmp { + status = "okay"; + }; + + psci { + compatible = "arm,psci-1.0"; + status = "okay"; + method = "smc"; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi new file mode 100644 index 000000000000..a918e10240fd --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi @@ -0,0 +1,398 @@ +#include <dt-bindings/gpio/tegra186-gpio.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + compatible = "nvidia,tegra186"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + gpio: gpio@2200000 { + compatible = "nvidia,tegra186-gpio"; + reg-names = "security", "gpio"; + reg = <0x0 0x2200000 0x0 0x10000>, + <0x0 0x2210000 0x0 0x10000>; + interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + #gpio-cells = <2>; + gpio-controller; + }; + + uarta: serial@3100000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x03100000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 55>; + clock-names = "serial"; + resets = <&bpmp 47>; + reset-names = "serial"; + status = "disabled"; + }; + + uartb: serial@3110000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x03110000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 56>; + clock-names = "serial"; + resets = <&bpmp 48>; + reset-names = "serial"; + status = "disabled"; + }; + + uartd: serial@3130000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x03130000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 77>; + clock-names = "serial"; + resets = <&bpmp 50>; + reset-names = "serial"; + status = "disabled"; + }; + + uarte: serial@3140000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x03140000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 194>; + clock-names = "serial"; + resets = <&bpmp 132>; + reset-names = "serial"; + status = "disabled"; + }; + + uartf: serial@3150000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x03150000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 195>; + clock-names = "serial"; + resets = <&bpmp 111>; + reset-names = "serial"; + status = "disabled"; + }; + + gen1_i2c: i2c@3160000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x03160000 0x0 0x10000>; + interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 47>; + clock-names = "div-clk"; + resets = <&bpmp 19>; + reset-names = "i2c"; + status = "disabled"; + }; + + cam_i2c: i2c@3180000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x03180000 0x0 0x10000>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 75>; + clock-names = "div-clk"; + resets = <&bpmp 21>; + reset-names = "i2c"; + status = "disabled"; + }; + + /* shares pads with dpaux1 */ + dp_aux_ch1_i2c: i2c@3190000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x03190000 0x0 0x10000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 86>; + clock-names = "div-clk"; + resets = <&bpmp 22>; + reset-names = "i2c"; + status = "disabled"; + }; + + /* controlled by BPMP, should not be enabled */ + pwr_i2c: i2c@31a0000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x031a0000 0x0 0x10000>; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 48>; + clock-names = "div-clk"; + resets = <&bpmp 23>; + reset-names = "i2c"; + status = "disabled"; + }; + + /* shares pads with dpaux0 */ + dp_aux_ch0_i2c: i2c@31b0000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x031b0000 0x0 0x10000>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 125>; + clock-names = "div-clk"; + resets = <&bpmp 24>; + reset-names = "i2c"; + status = "disabled"; + }; + + gen7_i2c: i2c@31c0000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x031c0000 0x0 0x10000>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 182>; + clock-names = "div-clk"; + resets = <&bpmp 81>; + reset-names = "i2c"; + status = "disabled"; + }; + + gen9_i2c: i2c@31e0000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x031e0000 0x0 0x10000>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 183>; + clock-names = "div-clk"; + resets = <&bpmp 83>; + reset-names = "i2c"; + status = "disabled"; + }; + + sdmmc1: sdhci@3400000 { + compatible = "nvidia,tegra186-sdhci"; + reg = <0x0 0x03400000 0x0 0x10000>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 52>; + clock-names = "sdhci"; + resets = <&bpmp 33>; + reset-names = "sdhci"; + status = "disabled"; + }; + + sdmmc2: sdhci@3420000 { + compatible = "nvidia,tegra186-sdhci"; + reg = <0x0 0x03420000 0x0 0x10000>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 53>; + clock-names = "sdhci"; + resets = <&bpmp 34>; + reset-names = "sdhci"; + status = "disabled"; + }; + + sdmmc3: sdhci@3440000 { + compatible = "nvidia,tegra186-sdhci"; + reg = <0x0 0x03440000 0x0 0x10000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 76>; + clock-names = "sdhci"; + resets = <&bpmp 35>; + reset-names = "sdhci"; + status = "disabled"; + }; + + sdmmc4: sdhci@3460000 { + compatible = "nvidia,tegra186-sdhci"; + reg = <0x0 0x03460000 0x0 0x10000>; + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 54>; + clock-names = "sdhci"; + resets = <&bpmp 36>; + reset-names = "sdhci"; + status = "disabled"; + }; + + gic: interrupt-controller@3881000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x03881000 0x0 0x1000>, + <0x0 0x03882000 0x0 0x2000>; + interrupts = <GIC_PPI 9 + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupt-parent = <&gic>; + }; + + hsp_top0: hsp@3c00000 { + compatible = "nvidia,tegra186-hsp"; + reg = <0x0 0x03c00000 0x0 0xa0000>; + interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "doorbell"; + #mbox-cells = <2>; + status = "disabled"; + }; + + gen2_i2c: i2c@c240000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x0c240000 0x0 0x10000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 218>; + clock-names = "div-clk"; + resets = <&bpmp 20>; + reset-names = "i2c"; + status = "disabled"; + }; + + gen8_i2c: i2c@c250000 { + compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c"; + reg = <0x0 0x0c250000 0x0 0x10000>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&bpmp 219>; + clock-names = "div-clk"; + resets = <&bpmp 82>; + reset-names = "i2c"; + status = "disabled"; + }; + + uartc: serial@c280000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x0c280000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 215>; + clock-names = "serial"; + resets = <&bpmp 49>; + reset-names = "serial"; + status = "disabled"; + }; + + uartg: serial@c290000 { + compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart"; + reg = <0x0 0x0c290000 0x0 0x40>; + reg-shift = <2>; + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&bpmp 216>; + clock-names = "serial"; + resets = <&bpmp 112>; + reset-names = "serial"; + status = "disabled"; + }; + + gpio_aon: gpio@c2f0000 { + compatible = "nvidia,tegra186-gpio-aon"; + reg-names = "security", "gpio"; + reg = <0x0 0xc2f0000 0x0 0x1000>, + <0x0 0xc2f1000 0x0 0x1000>; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + sysram@30000000 { + compatible = "nvidia,tegra186-sysram", "mmio-sram"; + reg = <0x0 0x30000000 0x0 0x50000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>; + + cpu_bpmp_tx: shmem@4e000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4e000 0x0 0x1000>; + label = "cpu-bpmp-tx"; + pool; + }; + + cpu_bpmp_rx: shmem@4f000 { + compatible = "nvidia,tegra186-bpmp-shmem"; + reg = <0x0 0x4f000 0x0 0x1000>; + label = "cpu-bpmp-rx"; + pool; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "nvidia,tegra186-denver", "arm,armv8"; + device_type = "cpu"; + reg = <0x000>; + }; + + cpu@1 { + compatible = "nvidia,tegra186-denver", "arm,armv8"; + device_type = "cpu"; + reg = <0x001>; + }; + + cpu@2 { + compatible = "arm,cortex-a57", "arm,armv8"; + device_type = "cpu"; + reg = <0x100>; + }; + + cpu@3 { + compatible = "arm,cortex-a57", "arm,armv8"; + device_type = "cpu"; + reg = <0x101>; + }; + + cpu@4 { + compatible = "arm,cortex-a57", "arm,armv8"; + device_type = "cpu"; + reg = <0x102>; + }; + + cpu@5 { + compatible = "arm,cortex-a57", "arm,armv8"; + device_type = "cpu"; + reg = <0x103>; + }; + }; + + bpmp: bpmp { + compatible = "nvidia,tegra186-bpmp"; + mboxes = <&hsp_top0 0 19>; + shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>; + #clock-cells = <1>; + #reset-cells = <1>; + + bpmp_i2c: i2c { + compatible = "nvidia,tegra186-bpmp-i2c"; + nvidia,bpmp-bus-id = <5>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + 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)>; + interrupt-parent = <&gic>; + }; +}; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi index 5fda583351d7..906fb836d241 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi @@ -21,6 +21,10 @@ reg = <0x0 0x80000000 0x1 0x0>; }; + gpu@57000000 { + vdd-supply = <&vdd_gpu>; + }; + /* debug port */ serial@70006000 { status = "okay"; @@ -291,4 +295,18 @@ clock-frequency = <32768>; }; }; + + regulators { + vdd_gpu: regulator@100 { + compatible = "pwm-regulator"; + reg = <100>; + pwms = <&pwm 1 4880>; + regulator-name = "VDD_GPU"; + regulator-min-microvolt = <710000>; + regulator-max-microvolt = <1320000>; + enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>; + regulator-ramp-delay = <80>; + regulator-enable-ramp-delay = <1000>; + }; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts index 983775e637a4..4c1ea7a08d43 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts @@ -7,6 +7,32 @@ model = "NVIDIA Jetson TX1 Developer Kit"; compatible = "nvidia,p2371-2180", "nvidia,tegra210"; + pcie-controller@01003000 { + status = "okay"; + + avdd-pll-uerefe-supply = <&avdd_1v05_pll>; + hvddio-pex-supply = <&vdd_1v8>; + dvddio-pex-supply = <&vdd_pex_1v05>; + dvdd-pex-pll-supply = <&vdd_pex_1v05>; + hvdd-pex-pll-e-supply = <&vdd_1v8>; + vddio-pex-ctl-supply = <&vdd_1v8>; + + pci@1,0 { + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>, + <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>, + <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>, + <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>; + phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3"; + status = "okay"; + }; + + pci@2,0 { + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>; + phy-names = "pcie-0"; + status = "okay"; + }; + }; + host1x@50000000 { dsi@54300000 { status = "okay"; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts index 431266a48e9c..7703227f5d1a 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts @@ -11,7 +11,8 @@ compatible = "google,smaug-rev8", "google,smaug-rev7", "google,smaug-rev6", "google,smaug-rev5", "google,smaug-rev4", "google,smaug-rev3", - "google,smaug-rev1", "google,smaug", "nvidia,tegra210"; + "google,smaug-rev2", "google,smaug-rev1", + "google,smaug", "nvidia,tegra210"; aliases { serial0 = &uarta; @@ -27,6 +28,12 @@ reg = <0x0 0x80000000 0x0 0xc0000000>; }; + host1x@50000000 { + dpaux: dpaux@545c0000 { + status = "okay"; + }; + }; + pinmux: pinmux@700008d4 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; @@ -1556,6 +1563,46 @@ }; }; + i2c@7000d100 { + status = "okay"; + clock-frequency = <400000>; + + nau8825@1a { + compatible = "nuvoton,nau8825"; + reg = <0x1a>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(E, 6) IRQ_TYPE_LEVEL_LOW>; + clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; + clock-names = "mclk"; + + nuvoton,jkdet-enable; + nuvoton,jkdet-polarity = <GPIO_ACTIVE_LOW>; + nuvoton,vref-impedance = <2>; + nuvoton,micbias-voltage = <6>; + nuvoton,sar-threshold-num = <4>; + nuvoton,sar-threshold = <0xc 0x1e 0x38 0x60>; + nuvoton,sar-hysteresis = <1>; + nuvoton,sar-voltage = <0>; + nuvoton,sar-compare-time = <0>; + nuvoton,sar-sampling-time = <0>; + nuvoton,short-key-debounce = <2>; + nuvoton,jack-insert-debounce = <7>; + nuvoton,jack-eject-debounce = <7>; + status = "okay"; + }; + + audio-codec@2d { + compatible = "realtek,rt5677"; + reg = <0x2d>; + interrupt-parent = <&gpio>; + interrupts = <TEGRA_GPIO(X, 0) IRQ_TYPE_LEVEL_HIGH>; + realtek,reset-gpio = <&gpio TEGRA_GPIO(BB, 3) GPIO_ACTIVE_LOW>; + gpio-controller; + #gpio-cells = <2>; + status = "okay"; + }; + }; + pmc@7000e400 { nvidia,invert-interrupt; nvidia,suspend-mode = <0>; @@ -1568,12 +1615,81 @@ status = "okay"; }; + usb@70090000 { + phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>, + <&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>; + phy-names = "usb2-0", "usb3-0"; + + dvddio-pex-supply = <&avddio_1v05>; + hvddio-pex-supply = <&pp1800>; + avdd-usb-supply = <&pp3300>; + avdd-pll-utmip-supply = <&pp1800>; + avdd-pll-uerefe-supply = <&pp1050_avdd>; + dvdd-pex-pll-supply = <&avddio_1v05>; + hvdd-pex-pll-e-supply = <&pp1800>; + + status = "okay"; + }; + + padctl@7009f000 { + status = "okay"; + + pads { + usb2 { + status = "okay"; + + lanes { + usb2-0 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; + }; + + pcie { + status = "okay"; + + lanes { + pcie-6 { + nvidia,function = "usb3-ss"; + status = "okay"; + }; + }; + }; + }; + + ports { + usb2-0 { + status = "okay"; + vbus-supply = <&usbc_vbus>; + mode = "otg"; + }; + + usb3-0 { + nvidia,usb2-companion = <0>; + status = "okay"; + }; + }; + }; + sdhci@700b0600 { bus-width = <8>; non-removable; status = "okay"; }; + aconnect@702c0000 { + status = "okay"; + + dma@702e2000 { + status = "okay"; + }; + + agic@702f9000 { + status = "okay"; + }; + }; + clocks { compatible = "simple-bus"; #address-cells = <1>; @@ -1646,6 +1762,11 @@ }; }; + max98357a { + compatible = "maxim,max98357a"; + status = "okay"; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index c4cfdcf60d26..2f832df29da8 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -3,6 +3,7 @@ #include <dt-bindings/memory/tegra210-mc.h> #include <dt-bindings/pinctrl/pinctrl-tegra.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/thermal/tegra124-soctherm.h> / { compatible = "nvidia,tegra210"; @@ -10,6 +11,69 @@ #address-cells = <2>; #size-cells = <2>; + pcie-controller@01003000 { + compatible = "nvidia,tegra210-pcie"; + device_type = "pci"; + reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ + 0x0 0x01003800 0x0 0x00000800 /* AFI registers */ + 0x0 0x02000000 0x0 0x10000000>; /* configuration space */ + reg-names = "pads", "afi", "cs"; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */ + <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */ + interrupt-names = "intr", "msi"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + + bus-range = <0x00 0xff>; + #address-cells = <3>; + #size-cells = <2>; + + ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000 /* port 0 configuration space */ + 0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000 /* port 1 configuration space */ + 0x81000000 0 0x0 0x0 0x12000000 0 0x00010000 /* downstream I/O (64 KiB) */ + 0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000 /* non-prefetchable memory (208 MiB) */ + 0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */ + + clocks = <&tegra_car TEGRA210_CLK_PCIE>, + <&tegra_car TEGRA210_CLK_AFI>, + <&tegra_car TEGRA210_CLK_PLL_E>, + <&tegra_car TEGRA210_CLK_CML0>; + clock-names = "pex", "afi", "pll_e", "cml"; + resets = <&tegra_car 70>, + <&tegra_car 72>, + <&tegra_car 74>; + reset-names = "pex", "afi", "pcie_x"; + status = "disabled"; + + pci@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>; + reg = <0x000800 0 0 0 0>; + status = "disabled"; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + + nvidia,num-lanes = <4>; + }; + + pci@2,0 { + device_type = "pci"; + assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>; + reg = <0x001000 0 0 0 0>; + status = "disabled"; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + + nvidia,num-lanes = <1>; + }; + }; + host1x@50000000 { compatible = "nvidia,tegra210-host1x", "simple-bus"; reg = <0x0 0x50000000 0x0 0x00034000>; @@ -34,6 +98,7 @@ clock-names = "dpaux", "parent"; resets = <&tegra_car 207>; reset-names = "dpaux"; + power-domains = <&pd_sor>; status = "disabled"; state_dpaux1_aux: pinmux-aux { @@ -108,6 +173,7 @@ clock-names = "dsi", "lp", "parent"; resets = <&tegra_car 48>; reset-names = "dsi"; + power-domains = <&pd_sor>; nvidia,mipi-calibrate = <&mipi 0x0c0>; /* DSIA & DSIB pads */ status = "disabled"; @@ -137,6 +203,7 @@ clock-names = "dsi", "lp", "parent"; resets = <&tegra_car 82>; reset-names = "dsi"; + power-domains = <&pd_sor>; nvidia,mipi-calibrate = <&mipi 0x300>; /* DSIC & DSID pads */ status = "disabled"; @@ -178,6 +245,7 @@ pinctrl-1 = <&state_dpaux_i2c>; pinctrl-2 = <&state_dpaux_off>; pinctrl-names = "aux", "i2c", "off"; + power-domains = <&pd_sor>; status = "disabled"; }; @@ -197,6 +265,7 @@ pinctrl-1 = <&state_dpaux1_i2c>; pinctrl-2 = <&state_dpaux1_off>; pinctrl-names = "aux", "i2c", "off"; + power-domains = <&pd_sor>; status = "disabled"; }; @@ -209,6 +278,7 @@ clock-names = "dpaux", "parent"; resets = <&tegra_car 181>; reset-names = "dpaux"; + power-domains = <&pd_sor>; status = "disabled"; state_dpaux_aux: pinmux-aux { @@ -325,7 +395,7 @@ }; gpio: gpio@6000d000 { - compatible = "nvidia,tegra210-gpio", "nvidia,tegra124-gpio", "nvidia,tegra30-gpio"; + compatible = "nvidia,tegra210-gpio", "nvidia,tegra30-gpio"; reg = <0x0 0x6000d000 0x0 0x1000>; interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>, @@ -648,27 +718,41 @@ #power-domain-cells = <0>; }; + pd_sor: sor { + clocks = <&tegra_car TEGRA210_CLK_SOR0>, + <&tegra_car TEGRA210_CLK_SOR1>, + <&tegra_car TEGRA210_CLK_CSI>, + <&tegra_car TEGRA210_CLK_DSIA>, + <&tegra_car TEGRA210_CLK_DSIB>, + <&tegra_car TEGRA210_CLK_DPAUX>, + <&tegra_car TEGRA210_CLK_DPAUX1>, + <&tegra_car TEGRA210_CLK_MIPI_CAL>; + resets = <&tegra_car TEGRA210_CLK_SOR0>, + <&tegra_car TEGRA210_CLK_SOR1>, + <&tegra_car TEGRA210_CLK_CSI>, + <&tegra_car TEGRA210_CLK_DSIA>, + <&tegra_car TEGRA210_CLK_DSIB>, + <&tegra_car TEGRA210_CLK_DPAUX>, + <&tegra_car TEGRA210_CLK_DPAUX1>, + <&tegra_car TEGRA210_CLK_MIPI_CAL>; + #power-domain-cells = <0>; + }; + pd_xusbss: xusba { clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>; - clock-names = "xusb-ss"; resets = <&tegra_car TEGRA210_CLK_XUSB_SS>; - reset-names = "xusb-ss"; #power-domain-cells = <0>; }; pd_xusbdev: xusbb { clocks = <&tegra_car TEGRA210_CLK_XUSB_DEV>; - clock-names = "xusb-dev"; resets = <&tegra_car 95>; - reset-names = "xusb-dev"; #power-domain-cells = <0>; }; pd_xusbhost: xusbc { clocks = <&tegra_car TEGRA210_CLK_XUSB_HOST>; - clock-names = "xusb-host"; resets = <&tegra_car TEGRA210_CLK_XUSB_HOST>; - reset-names = "xusb-host"; #power-domain-cells = <0>; }; }; @@ -948,6 +1032,7 @@ reg = <0x0 0x700e3000 0x0 0x100>; clocks = <&tegra_car TEGRA210_CLK_MIPI_CAL>; clock-names = "mipi-cal"; + power-domains = <&pd_sor>; #nvidia,mipi-calibrate-cells = <1>; }; @@ -961,6 +1046,50 @@ #size-cells = <1>; ranges = <0x702c0000 0x0 0x702c0000 0x00040000>; status = "disabled"; + + adma: dma@702e2000 { + compatible = "nvidia,tegra210-adma"; + reg = <0x702e2000 0x2000>; + interrupt-parent = <&agic>; + interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>, + <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>; + #dma-cells = <1>; + clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>; + clock-names = "d_audio"; + status = "disabled"; + }; + + agic: agic@702f9000 { + compatible = "nvidia,tegra210-agic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x702f9000 0x2000>, + <0x702fa000 0x2000>; + interrupts = <GIC_SPI 102 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + clocks = <&tegra_car TEGRA210_CLK_APE>; + clock-names = "clk"; + status = "disabled"; + }; }; spi@70410000 { @@ -1094,4 +1223,130 @@ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; interrupt-parent = <&gic>; }; + + soctherm: thermal-sensor@700e2000 { + compatible = "nvidia,tegra210-soctherm"; + reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */ + 0x0 0x60006000 0x0 0x400>; /* CAR reg_base */ + reg-names = "soctherm-reg", "car-reg"; + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&tegra_car TEGRA210_CLK_TSENSOR>, + <&tegra_car TEGRA210_CLK_SOC_THERM>; + clock-names = "tsensor", "soctherm"; + resets = <&tegra_car 78>; + reset-names = "soctherm"; + #thermal-sensor-cells = <1>; + + throttle-cfgs { + throttle_heavy: heavy { + nvidia,priority = <100>; + nvidia,cpu-throt-percent = <85>; + + #cooling-cells = <2>; + }; + }; + }; + + thermal-zones { + cpu { + polling-delay-passive = <1000>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>; + + trips { + cpu-shutdown-trip { + temperature = <102500>; + hysteresis = <0>; + type = "critical"; + }; + + cpu_throttle_trip: throttle-trip { + temperature = <98500>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; + }; + mem { + polling-delay-passive = <0>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>; + + trips { + mem-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; + }; + gpu { + polling-delay-passive = <1000>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>; + + trips { + gpu-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + + gpu_throttle_trip: throttle-trip { + temperature = <100000>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; + }; + pllx { + polling-delay-passive = <0>; + polling-delay = <0>; + + thermal-sensors = + <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>; + + trips { + pllx-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index fa1f661ccccf..cc0f02d9dd02 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -1,4 +1,8 @@ -dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb msm8916-mtp.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8016-sbc.dtb +dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb +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 always := $(dtb-y) diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi index ee828a8a8236..e1e6c6b5c489 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc-soc-pins.dtsi @@ -24,4 +24,52 @@ bias-pull-up; }; }; + + adv7533_int_active: adv533_int_active { + pinmux { + function = "gpio"; + pins = "gpio31"; + }; + pinconf { + pins = "gpio31"; + drive-strength = <16>; + bias-disable; + }; + }; + + adv7533_int_suspend: adv7533_int_suspend { + pinmux { + function = "gpio"; + pins = "gpio31"; + }; + pinconf { + pins = "gpio31"; + drive-strength = <2>; + bias-disable; + }; + }; + + adv7533_switch_active: adv7533_switch_active { + pinmux { + function = "gpio"; + pins = "gpio32"; + }; + pinconf { + pins = "gpio32"; + drive-strength = <16>; + bias-disable; + }; + }; + + adv7533_switch_suspend: adv7533_switch_suspend { + pinmux { + function = "gpio"; + pins = "gpio32"; + }; + pinconf { + pins = "gpio32"; + drive-strength = <2>; + bias-disable; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi index 18639bc0a506..08bd5ebafb4e 100644 --- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi +++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi @@ -15,6 +15,7 @@ #include "pm8916.dtsi" #include "apq8016-sbc-soc-pins.dtsi" #include "apq8016-sbc-pmic-pins.dtsi" +#include <dt-bindings/sound/apq8016-lpass.h> / { aliases { @@ -63,6 +64,47 @@ /* On High speed expansion */ label = "HS-I2C2"; status = "okay"; + + adv_bridge: bridge@39 { + status = "okay"; + + compatible = "adi,adv7533"; + reg = <0x39>; + + interrupt-parent = <&msmgpio>; + interrupts = <31 2>; + + adi,dsi-lanes = <4>; + + pd-gpios = <&msmgpio 32 0>; + + avdd-supply = <&pm8916_l6>; + v1p2-supply = <&pm8916_l6>; + v3p3-supply = <&pm8916_l17>; + + pinctrl-names = "default","sleep"; + pinctrl-0 = <&adv7533_int_active &adv7533_switch_active>; + pinctrl-1 = <&adv7533_int_suspend &adv7533_switch_suspend>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7533_in: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7533_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; }; i2c@78ba000 { @@ -180,6 +222,90 @@ lpass@07708000 { status = "okay"; }; + + mdss@1a00000 { + status = "okay"; + + mdp@1a01000 { + status = "okay"; + }; + + dsi@1a98000 { + status = "okay"; + + vdda-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; + + ports { + port@1 { + endpoint { + remote-endpoint = <&adv7533_in>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; + + dsi-phy@1a98300 { + status = "okay"; + + vddio-supply = <&pm8916_l6>; + }; + }; + + lpass_codec: codec{ + status = "okay"; + }; + + /* + Internal Codec + playback - Primary MI2S + capture - Ter MI2S + + External Primary: + playback - secondary MI2S + capture - Quat MI2S + + External Secondary: + playback - Quat MI2S + capture - Quat MI2S + + */ + + sound: sound { + compatible = "qcom,apq8016-sbc-sndcard"; + reg = <0x07702000 0x4>, <0x07702004 0x4>; + reg-names = "mic-iomux", "spkr-iomux"; + + status = "okay"; + pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; + pinctrl-names = "default", "sleep"; + qcom,model = "DB410c"; + qcom,audio-routing = + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External1"; + + internal-codec-playback-dai-link@0 { /* I2S - Internal codec */ + link-name = "WCD"; + cpu { /* PRIMARY */ + sound-dai = <&lpass MI2S_PRIMARY>; + }; + codec { + sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + }; + }; + + internal-codec-capture-dai-link@0 { /* I2S - Internal codec */ + link-name = "WCD-Capture"; + cpu { /* PRIMARY */ + sound-dai = <&lpass MI2S_TERTIARY>; + }; + codec { + sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; + }; + }; + }; }; usb2513 { @@ -194,6 +320,23 @@ pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7533_out>; + }; + }; + }; +}; + +&wcd_codec { + status = "okay"; + clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "mclk"; }; &smd_rpm_regulators { @@ -226,8 +369,8 @@ }; l2 { - regulator-min-microvolt = <375000>; - regulator-max-microvolt = <1525000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; }; l3 { @@ -246,8 +389,8 @@ }; l6 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; }; l7 { @@ -306,8 +449,8 @@ }; l17 { - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <3337000>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; }; l18 { diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c-pins.dtsi new file mode 100644 index 000000000000..24552f19b3fa --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c-pins.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013-2016, The Linux Foundation. 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 and + * only 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. + */ +&msmgpio { + sdc2_cd_on: sdc2_cd_on { + mux { + pins = "gpio38"; + function = "gpio"; + }; + + config { + pins = "gpio38"; + bias-pull-up; /* pull up */ + drive-strength = <16>; /* 16 MA */ + }; + }; + + sdc2_cd_off: sdc2_cd_off { + mux { + pins = "gpio38"; + function = "gpio"; + }; + + config { + pins = "gpio38"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi new file mode 100644 index 000000000000..0de95171d6d0 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi @@ -0,0 +1,15 @@ + +#include <dt-bindings/pinctrl/qcom,pmic-gpio.h> +&pm8994_gpios { + + pinctrl-names = "default"; + pinctrl-0 = <&ls_exp_gpio_f>; + + ls_exp_gpio_f: pm8916_mpp4 { + pinconf { + pins = "gpio5"; + output-low; + power-source = <2>; // PM8994_GPIO_S4, 1.8V + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts new file mode 100644 index 000000000000..230e9c8484ac --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014-2016, The Linux Foundation. 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 and + * only 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. + */ + +/dts-v1/; + +#include "apq8096-db820c.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. DB820c"; + compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc"; +}; diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi new file mode 100644 index 000000000000..422959b87d12 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014-2016, The Linux Foundation. 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 and + * only 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. + */ + +#include "msm8996.dtsi" +#include "pm8994.dtsi" +#include "apq8096-db820c-pins.dtsi" +#include "apq8096-db820c-pmic-pins.dtsi" + +/ { + aliases { + serial0 = &blsp2_uart1; + serial1 = &blsp2_uart2; + i2c0 = &blsp1_i2c2; + i2c1 = &blsp2_i2c1; + i2c2 = &blsp2_i2c0; + spi0 = &blsp1_spi0; + spi1 = &blsp2_spi5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + serial@75b0000 { + label = "LS-UART1"; + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp2_uart1_2pins_default>; + pinctrl-1 = <&blsp2_uart1_2pins_sleep>; + }; + + serial@75b1000 { + label = "LS-UART0"; + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp2_uart2_4pins_default>; + pinctrl-1 = <&blsp2_uart2_4pins_sleep>; + }; + + i2c@07577000 { + /* On Low speed expansion */ + label = "LS-I2C0"; + status = "okay"; + }; + + i2c@075b6000 { + /* On Low speed expansion */ + label = "LS-I2C1"; + status = "okay"; + }; + + spi@07575000 { + /* On Low speed expansion */ + label = "LS-SPI0"; + status = "okay"; + }; + + i2c@075b5000 { + /* On High speed expansion */ + label = "HS-I2C2"; + status = "okay"; + }; + + spi@075ba000{ + /* On High speed expansion */ + label = "HS-SPI1"; + status = "okay"; + }; + + sdhci@74a4900 { + /* External SD card */ + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + cd-gpios = <&msmgpio 38 0x1>; + status = "okay"; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 11bdc24cfc74..f8ff327667c5 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -77,7 +77,7 @@ no-map; }; - mpss@86800000 { + mpss_mem: mpss@86800000 { reg = <0x0 0x86800000 0x0 0x2b00000>; no-map; }; @@ -86,6 +86,11 @@ reg = <0x0 0x89300000 0x0 0x600000>; no-map; }; + + mba_mem: mba@8ea00000 { + no-map; + reg = <0 0x8ea00000 0 0x100000>; + }; }; cpus { @@ -155,6 +160,49 @@ interrupts = <GIC_PPI 7 GIC_CPU_MASK_SIMPLE(4)>; }; + thermal-zones { + cpu-thermal0 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens 4>; + + 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 = <&tsens 3>; + + trips { + cpu_alert1: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + cpu_crit1: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + + }; + timer { compatible = "arm,armv8-timer"; interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, @@ -187,10 +235,11 @@ }; firmware { - scm { + scm: scm { compatible = "qcom,scm"; clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>; clock-names = "core", "bus", "iface"; + #reset-cells = <1>; }; }; @@ -228,6 +277,11 @@ reg = <0x1905000 0x20000>; }; + tcsr: syscon@1937000 { + compatible = "qcom,tcsr-msm8916", "syscon"; + reg = <0x1937000 0x30000>; + }; + tcsr_mutex: hwlock { compatible = "qcom,tcsr-mutex"; syscon = <&tcsr_mutex_regs 0 0x1000>; @@ -450,6 +504,15 @@ reg-names = "lpass-lpaif"; }; + lpass_codec: codec{ + compatible = "qcom,msm8916-wcd-digital-codec"; + reg = <0x0771c000 0x400>; + clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, + <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "ahbix-clk", "mclk"; + #sound-dai-cells = <1>; + }; + sdhc_1: sdhci@07824000 { compatible = "qcom,sdhci-msm-v4"; reg = <0x07824900 0x11c>, <0x07824000 0x800>; @@ -458,8 +521,10 @@ interrupts = <0 123 0>, <0 138 0>; interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC1_APPS_CLK>, - <&gcc GCC_SDCC1_AHB_CLK>; - clock-names = "core", "iface"; + <&gcc GCC_SDCC1_AHB_CLK>, + <&xo_board>; + clock-names = "core", "iface", "xo"; + mmc-ddr-1_8v; bus-width = <8>; non-removable; status = "disabled"; @@ -473,8 +538,9 @@ interrupts = <0 125 0>, <0 221 0>; interrupt-names = "hc_irq", "pwr_irq"; clocks = <&gcc GCC_SDCC2_APPS_CLK>, - <&gcc GCC_SDCC2_AHB_CLK>; - clock-names = "core", "iface"; + <&gcc GCC_SDCC2_AHB_CLK>, + <&xo_board>; + clock-names = "core", "iface", "xo"; bus-width = <4>; status = "disabled"; }; @@ -483,7 +549,7 @@ compatible = "qcom,ci-hdrc"; reg = <0x78d9000 0x400>; dr_mode = "peripheral"; - interrupts = <GIC_SPI 134 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; usb-phy = <&usb_otg>; status = "disabled"; }; @@ -491,7 +557,7 @@ usb_host: ehci@78d9000 { compatible = "qcom,ehci-host"; reg = <0x78d9000 0x400>; - interrupts = <GIC_SPI 134 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; usb-phy = <&usb_otg>; status = "disabled"; }; @@ -499,8 +565,8 @@ usb_otg: phy@78d9000 { compatible = "qcom,usb-otg-snps"; reg = <0x78d9000 0x400>; - interrupts = <GIC_SPI 134 IRQ_TYPE_EDGE_BOTH>, - <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>; + interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>; qcom,vdd-levels = <500000 1000000 1320000>; qcom,phy-init-sequence = <0x44 0x6B 0x24 0x13>; @@ -594,7 +660,7 @@ <0x200a000 0x002100>; reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; interrupt-names = "periph_irq"; - interrupts = <GIC_SPI 190 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; qcom,ee = <0>; qcom,channel = <0>; #address-cells = <2>; @@ -609,6 +675,187 @@ clocks = <&gcc GCC_PRNG_AHB_CLK>; clock-names = "core"; }; + + qfprom: qfprom@5c000 { + compatible = "qcom,qfprom"; + reg = <0x5c000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + tsens_caldata: caldata@d0 { + reg = <0xd0 0x8>; + }; + tsens_calsel: calsel@ec { + reg = <0xec 0x4>; + }; + }; + + tsens: thermal-sensor@4a8000 { + compatible = "qcom,msm8916-tsens"; + reg = <0x4a8000 0x2000>; + nvmem-cells = <&tsens_caldata>, <&tsens_calsel>; + nvmem-cell-names = "calib", "calib_sel"; + #thermal-sensor-cells = <1>; + }; + + mdss: mdss@1a00000 { + compatible = "qcom,mdss"; + reg = <0x1a00000 0x1000>, + <0x1ac8000 0x3000>; + reg-names = "mdss_phys", "vbif_phys"; + + power-domains = <&gcc MDSS_GDSC>; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_VSYNC_CLK>; + clock-names = "iface_clk", + "bus_clk", + "vsync_clk"; + + interrupts = <0 72 0>; + + interrupt-controller; + #interrupt-cells = <1>; + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mdp: mdp@1a01000 { + compatible = "qcom,mdp5"; + reg = <0x1a01000 0x90000>; + reg-names = "mdp_phys"; + + interrupt-parent = <&mdss>; + interrupts = <0 0>; + + clocks = <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_MDP_CLK>, + <&gcc GCC_MDSS_VSYNC_CLK>; + clock-names = "iface_clk", + "bus_clk", + "core_clk", + "vsync_clk"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mdp5_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + }; + }; + + dsi0: dsi@1a98000 { + compatible = "qcom,mdss-dsi-ctrl"; + reg = <0x1a98000 0x25c>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4 0>; + + assigned-clocks = <&gcc BYTE0_CLK_SRC>, + <&gcc PCLK0_CLK_SRC>; + assigned-clock-parents = <&dsi_phy0 0>, + <&dsi_phy0 1>; + + clocks = <&gcc GCC_MDSS_MDP_CLK>, + <&gcc GCC_MDSS_AHB_CLK>, + <&gcc GCC_MDSS_AXI_CLK>, + <&gcc GCC_MDSS_BYTE0_CLK>, + <&gcc GCC_MDSS_PCLK0_CLK>, + <&gcc GCC_MDSS_ESC0_CLK>; + clock-names = "mdp_core_clk", + "iface_clk", + "bus_clk", + "byte_clk", + "pixel_clk", + "core_clk"; + phys = <&dsi_phy0>; + phy-names = "dsi-phy"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + remote-endpoint = <&mdp5_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + }; + }; + }; + }; + + dsi_phy0: dsi-phy@1a98300 { + compatible = "qcom,dsi-phy-28nm-lp"; + reg = <0x1a98300 0xd4>, + <0x1a98500 0x280>, + <0x1a98780 0x30>; + reg-names = "dsi_pll", + "dsi_phy", + "dsi_phy_regulator"; + + #clock-cells = <1>; + + clocks = <&gcc GCC_MDSS_AHB_CLK>; + clock-names = "iface_clk"; + }; + }; + + + hexagon@4080000 { + compatible = "qcom,q6v5-pil"; + reg = <0x04080000 0x100>, + <0x04020000 0x040>; + + reg-names = "qdsp6", "rmb"; + + interrupts-extended = <&intc 0 24 1>, + <&hexagon_smp2p_in 0 0>, + <&hexagon_smp2p_in 1 0>, + <&hexagon_smp2p_in 2 0>, + <&hexagon_smp2p_in 3 0>; + interrupt-names = "wdog", "fatal", "ready", + "handover", "stop-ack"; + + clocks = <&gcc GCC_MSS_CFG_AHB_CLK>, + <&gcc GCC_MSS_Q6_BIMC_AXI_CLK>, + <&gcc GCC_BOOT_ROM_AHB_CLK>; + clock-names = "iface", "bus", "mem"; + + qcom,smem-states = <&hexagon_smp2p_out 0>; + qcom,smem-state-names = "stop"; + + resets = <&scm 0>; + reset-names = "mss_restart"; + + mx-supply = <&pm8916_l3>; + pll-supply = <&pm8916_l7>; + + qcom,halt-regs = <&tcsr 0x18000 0x19000 0x1a000>; + + status = "disabled"; + + mba { + memory-region = <&mba_mem>; + }; + + mpss { + memory-region = <&mpss_mem>; + }; + }; }; smd { @@ -656,6 +903,96 @@ }; }; }; + + hexagon { + interrupts = <0 25 IRQ_TYPE_EDGE_RISING>; + + qcom,smd-edge = <0>; + qcom,ipc = <&apcs 8 12>; + qcom,remote-pid = <1>; + }; + }; + + hexagon-smp2p { + compatible = "qcom,smp2p"; + qcom,smem = <435>, <428>; + + interrupts = <0 27 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&apcs 8 14>; + + qcom,local-pid = <0>; + qcom,remote-pid = <1>; + + hexagon_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + + #qcom,smem-state-cells = <1>; + }; + + hexagon_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + wcnss-smp2p { + compatible = "qcom,smp2p"; + qcom,smem = <451>, <431>; + + interrupts = <0 143 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&apcs 8 18>; + + qcom,local-pid = <0>; + qcom,remote-pid = <4>; + + wcnss_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + + #qcom,smem-state-cells = <1>; + }; + + wcnss_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + smsm { + compatible = "qcom,smsm"; + + #address-cells = <1>; + #size-cells = <0>; + + qcom,ipc-1 = <&apcs 0 13>; + qcom,ipc-6 = <&apcs 0 19>; + + apps_smsm: apps@0 { + reg = <0>; + + #qcom,smem-state-cells = <1>; + }; + + hexagon_smsm: hexagon@1 { + reg = <1>; + interrupts = <0 26 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + wcnss_smsm: wcnss@6 { + reg = <6>; + interrupts = <0 144 IRQ_TYPE_EDGE_RISING>; + + interrupt-controller; + #interrupt-cells = <2>; + }; }; }; diff --git a/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts new file mode 100644 index 000000000000..454213391671 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts @@ -0,0 +1,41 @@ +/* Copyright (c) 2015, LGE Inc. All rights reserved. + * Copyright (c) 2016, The Linux Foundation. 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 and + * only 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. + */ + +/dts-v1/; + +#include "msm8992.dtsi" + +/ { + model = "LG Nexus 5X"; + compatible = "lg,bullhead", "qcom,msm8992"; + /* required for bootloader to select correct board */ + qcom,board-id = <0xb64 0>; + qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + serial@f991e000 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp1_uart2_default>; + pinctrl-1 = <&blsp1_uart2_sleep>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi new file mode 100644 index 000000000000..d2a26f0f8d73 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013-2015, The Linux Foundation. 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 and + * only 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. + */ + +&msmgpio { + blsp1_uart2_default: blsp1_uart2_default { + pinmux { + function = "blsp_uart2"; + pins = "gpio4", "gpio5"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <16>; + bias-disable; + }; + }; + + blsp1_uart2_sleep: blsp1_uart2_sleep { + pinmux { + function = "gpio"; + pins = "gpio4", "gpio5"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi new file mode 100644 index 000000000000..44b2d37d8c4b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi @@ -0,0 +1,184 @@ +/* Copyright (c) 2013-2016, The Linux Foundation. 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 and + * only 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. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/qcom,gcc-msm8994.h> + +/ { + model = "Qualcomm Technologies, Inc. MSM 8992"; + compatible = "qcom,msm8992"; + // msm-id needed by bootloader for selecting correct blob + qcom,msm-id = <251 0>, <252 0>; + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + }; + }; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x0>; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + }; + + xo_board: xo_board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + }; + + sleep_clk: sleep_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + intc: interrupt-controller@f9000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0xf9000000 0x1000>, + <0xf9002000 0x1000>; + }; + + timer@f9020000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0xf9020000 0x1000>; + + frame@f9021000 { + frame-number = <0>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9021000 0x1000>, + <0xf9022000 0x1000>; + }; + + frame@f9023000 { + frame-number = <1>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9023000 0x1000>; + status = "disabled"; + }; + + frame@f9024000 { + frame-number = <2>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9024000 0x1000>; + status = "disabled"; + }; + + frame@f9025000 { + frame-number = <3>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9025000 0x1000>; + status = "disabled"; + }; + + frame@f9026000 { + frame-number = <4>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9026000 0x1000>; + status = "disabled"; + }; + + frame@f9027000 { + frame-number = <5>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9027000 0x1000>; + status = "disabled"; + }; + + frame@f9028000 { + frame-number = <6>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9028000 0x1000>; + status = "disabled"; + }; + }; + + restart@fc4ab000 { + compatible = "qcom,pshold"; + reg = <0xfc4ab000 0x4>; + }; + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8994-pinctrl"; + reg = <0xfd510000 0x4000>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + blsp1_uart2: serial@f991e000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xf991e000 0x1000>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_LOW>; + status = "disabled"; + clock-names = "core", "iface"; + clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>, + <&clock_gcc GCC_BLSP1_AHB_CLK>; + }; + + clock_gcc: clock-controller@fc400000 { + compatible = "qcom,gcc-msm8994"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + reg = <0xfc400000 0x2000>; + }; + }; + + memory { + device_type = "memory"; + reg = <0 0 0 0>; // bootloader will update + }; +}; + + +#include "msm8992-pins.dtsi" diff --git a/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts new file mode 100644 index 000000000000..dfa08f513dc4 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts @@ -0,0 +1,40 @@ +/* Copyright (c) 2015, Huawei Inc. All rights reserved. + * Copyright (c) 2016, The Linux Foundation. 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 and + * only 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. + */ + +/dts-v1/; + +#include "msm8994.dtsi" + +/ { + model = "Huawei Nexus 6P"; + compatible = "huawei,angler", "qcom,msm8994"; + /* required for bootloader to select correct board */ + qcom,board-id = <8026 0>; + + aliases { + serial0 = &blsp1_uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + serial@f991e000 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&blsp1_uart2_default>; + pinctrl-1 = <&blsp1_uart2_sleep>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi new file mode 100644 index 000000000000..0e4eea0df25d --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013-2016, The Linux Foundation. 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 and + * only 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. + */ + +&msmgpio { + blsp1_uart2_default: blsp1_uart2_default { + pinmux { + function = "blsp_uart2"; + pins = "gpio4", "gpio5"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <16>; + bias-disable; + }; + }; + + blsp1_uart2_sleep: blsp1_uart2_sleep { + pinmux { + function = "gpio"; + pins = "gpio4", "gpio5"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi new file mode 100644 index 000000000000..f33c41d01c86 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi @@ -0,0 +1,216 @@ +/* Copyright (c) 2013-2016, The Linux Foundation. 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 and + * only 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. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/qcom,gcc-msm8994.h> + +/ { + model = "Qualcomm Technologies, Inc. MSM 8994"; + compatible = "qcom,msm8994"; + // msm-id and pmic-id are required by bootloader for + // proper selection of dt blob + qcom,msm-id = <207 0x20000>; + qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>; + interrupt-parent = <&intc>; + + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + }; + }; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0>; + next-level-cache = <&L2_0>; + L2_0: l2-cache { + compatible = "cache"; + cache-level = <2>; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 2 0xff08>, + <1 3 0xff08>, + <1 4 0xff08>, + <1 1 0xff08>; + }; + + soc: soc { + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + intc: interrupt-controller@f9000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0xf9000000 0x1000>, + <0xf9002000 0x1000>; + }; + + timer@f9020000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0xf9020000 0x1000>; + + frame@f9021000 { + frame-number = <0>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9021000 0x1000>, + <0xf9022000 0x1000>; + }; + + frame@f9023000 { + frame-number = <1>; + interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9023000 0x1000>; + status = "disabled"; + }; + + frame@f9024000 { + frame-number = <2>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9024000 0x1000>; + status = "disabled"; + }; + + frame@f9025000 { + frame-number = <3>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9025000 0x1000>; + status = "disabled"; + }; + + frame@f9026000 { + frame-number = <4>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9026000 0x1000>; + status = "disabled"; + }; + + frame@f9027000 { + frame-number = <5>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9027000 0x1000>; + status = "disabled"; + }; + + frame@f9028000 { + frame-number = <6>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xf9028000 0x1000>; + status = "disabled"; + }; + }; + + restart@fc4ab000 { + compatible = "qcom,pshold"; + reg = <0xfc4ab000 0x4>; + }; + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8994-pinctrl"; + reg = <0xfd510000 0x4000>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + blsp1_uart2: serial@f991e000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0xf991e000 0x1000>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + clock-names = "core", "iface"; + clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>, + <&clock_gcc GCC_BLSP1_AHB_CLK>; + }; + + tcsr_mutex_regs: syscon@fd484000 { + compatible = "syscon"; + reg = <0xfd484000 0x2000>; + }; + + clock_gcc: clock-controller@fc400000 { + compatible = "qcom,gcc-msm8994"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + reg = <0xfc400000 0x2000>; + }; + }; + + memory { + device_type = "memory"; + // We expect the bootloader to fill in the reg + reg = <0 0 0 0>; + }; + + xo_board: xo_board { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + }; + + sleep_clk: sleep_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + smem_mem: smem_region@6a00000 { + reg = <0x0 0x6a00000 0x0 0x200000>; + no-map; + }; + }; + + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x80>; + #hwlock-cells = <1>; + }; + + qcom,smem@6a00000 { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; +}; + + +#include "msm8994-pins.dtsi" diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 55ec3e8326b7..29ed6b61c737 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -30,6 +30,52 @@ reg = <0 0 0 0>; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + mba_region: mba@91500000 { + reg = <0x0 0x91500000 0x0 0x200000>; + no-map; + }; + + slpi_region: slpi@90b00000 { + reg = <0x0 0x90b00000 0x0 0xa00000>; + no-map; + }; + + venus_region: venus@90400000 { + reg = <0x0 0x90400000 0x0 0x700000>; + no-map; + }; + + adsp_region: adsp@8ea00000 { + reg = <0x0 0x8ea00000 0x0 0x1a00000>; + no-map; + }; + + mpss_region: mpss@88800000 { + reg = <0x0 0x88800000 0x0 0x6200000>; + no-map; + }; + + smem_mem: smem-mem@86000000 { + reg = <0x0 0x86000000 0x0 0x200000>; + no-map; + }; + + memory@85800000 { + reg = <0x0 0x85800000 0x0 0x800000>; + no-map; + }; + + memory@86200000 { + reg = <0x0 0x86200000 0x0 0x2600000>; + no-map; + }; + }; + cpus { #address-cells = <2>; #size-cells = <0>; @@ -97,6 +143,92 @@ }; }; + thermal-zones { + cpu-thermal0 { + polling-delay-passive = <250>; + polling-delay = <1000>; + + thermal-sensors = <&tsens0 3>; + + 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 5>; + + 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 10>; + + trips { + cpu_alert3: trip0 { + temperature = <75000>; + hysteresis = <2000>; + type = "passive"; + }; + + cpu_crit3: trip1 { + temperature = <110000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, @@ -106,14 +238,14 @@ }; clocks { - xo_board { + xo_board: xo_board { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <19200000>; clock-output-names = "xo_board"; }; - sleep_clk { + sleep_clk: sleep_clk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <32764>; @@ -126,12 +258,29 @@ method = "smc"; }; + tcsr_mutex: hwlock { + compatible = "qcom,tcsr-mutex"; + syscon = <&tcsr_mutex_regs 0 0x1000>; + #hwlock-cells = <1>; + }; + + smem { + compatible = "qcom,smem"; + memory-region = <&smem_mem>; + hwlocks = <&tcsr_mutex 3>; + }; + soc: soc { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; compatible = "simple-bus"; + tcsr_mutex_regs: syscon@740000 { + compatible = "syscon"; + reg = <0x740000 0x20000>; + }; + intc: interrupt-controller@9bc0000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; @@ -143,6 +292,11 @@ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; }; + apcs: syscon@9820000 { + compatible = "syscon"; + reg = <0x9820000 0x1000>; + }; + gcc: clock-controller@300000 { compatible = "qcom,gcc-msm8996"; #clock-cells = <1>; @@ -181,6 +335,12 @@ status = "disabled"; }; + tsens0: thermal-sensor@4a8000 { + compatible = "qcom,msm8996-tsens"; + reg = <0x4a8000 0x2000>; + #thermal-sensor-cells = <1>; + }; + blsp2_uart1: serial@75b0000 { compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; reg = <0x75b0000 0x1000>; @@ -255,9 +415,10 @@ interrupts = <0 125 0>, <0 221 0>; interrupt-names = "hc_irq", "pwr_irq"; - clock-names = "iface", "core"; + clock-names = "iface", "core", "xo"; clocks = <&gcc GCC_SDCC2_AHB_CLK>, - <&gcc GCC_SDCC2_APPS_CLK>; + <&gcc GCC_SDCC2_APPS_CLK>, + <&xo_board>; bus-width = <4>; }; @@ -339,7 +500,7 @@ <0x400a000 0x002100>; reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; interrupt-names = "periph_irq"; - interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>; + interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>; qcom,ee = <0>; qcom,channel = <0>; #address-cells = <2>; @@ -366,5 +527,29 @@ <825000000>; }; }; + + adsp-smp2p { + compatible = "qcom,smp2p"; + qcom,smem = <443>, <429>; + + interrupts = <0 158 IRQ_TYPE_EDGE_RISING>; + + qcom,ipc = <&apcs 16 10>; + + qcom,local-pid = <0>; + qcom,remote-pid = <2>; + + adsp_smp2p_out: master-kernel { + qcom,entry-name = "master-kernel"; + #qcom,state-cells = <1>; + }; + + adsp_smp2p_in: slave-kernel { + qcom,entry-name = "slave-kernel"; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; }; #include "msm8996-pins.dtsi" diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi index f71679b15d54..53deebf9f515 100644 --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi @@ -91,9 +91,52 @@ }; pm8916_1: pm8916@1 { - compatible = "qcom,spmi-pmic"; + compatible = "qcom,pm8916", "qcom,spmi-pmic"; reg = <0x1 SPMI_USID>; #address-cells = <1>; #size-cells = <0>; + + wcd_codec: codec@f000 { + compatible = "qcom,pm8916-wcd-analog-codec"; + reg = <0xf000 0x200>; + reg-names = "pmic-codec-core"; + clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>; + clock-names = "mclk"; + interrupt-parent = <&spmi_bus>; + interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>, + <0x1 0xf0 0x1 IRQ_TYPE_NONE>, + <0x1 0xf0 0x2 IRQ_TYPE_NONE>, + <0x1 0xf0 0x3 IRQ_TYPE_NONE>, + <0x1 0xf0 0x4 IRQ_TYPE_NONE>, + <0x1 0xf0 0x5 IRQ_TYPE_NONE>, + <0x1 0xf0 0x6 IRQ_TYPE_NONE>, + <0x1 0xf0 0x7 IRQ_TYPE_NONE>, + <0x1 0xf1 0x0 IRQ_TYPE_NONE>, + <0x1 0xf1 0x1 IRQ_TYPE_NONE>, + <0x1 0xf1 0x2 IRQ_TYPE_NONE>, + <0x1 0xf1 0x3 IRQ_TYPE_NONE>, + <0x1 0xf1 0x4 IRQ_TYPE_NONE>, + <0x1 0xf1 0x5 IRQ_TYPE_NONE>; + interrupt-names = "cdc_spk_cnp_int", + "cdc_spk_clip_int", + "cdc_spk_ocp_int", + "mbhc_ins_rem_det1", + "mbhc_but_rel_det", + "mbhc_but_press_det", + "mbhc_ins_rem_det", + "mbhc_switch_int", + "cdc_ear_ocp_int", + "cdc_hphr_ocp_int", + "cdc_hphl_ocp_det", + "cdc_ear_cnp_int", + "cdc_hphr_cnp_int", + "cdc_hphl_cnp_int"; + vdd-cdc-io-supply = <&pm8916_l5>; + vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>; + vdd-micbias-supply = <&pm8916_l13>; + #sound-dai-cells = <1>; + + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/pm8994.dtsi b/arch/arm64/boot/dts/qcom/pm8994.dtsi index 1222d2e904f6..0f1866024ae3 100644 --- a/arch/arm64/boot/dts/qcom/pm8994.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8994.dtsi @@ -29,6 +29,7 @@ <0 0xcc 0 IRQ_TYPE_NONE>, <0 0xcd 0 IRQ_TYPE_NONE>, <0 0xce 0 IRQ_TYPE_NONE>, + <0 0xcf 0 IRQ_TYPE_NONE>, <0 0xd0 0 IRQ_TYPE_NONE>, <0 0xd1 0 IRQ_TYPE_NONE>, <0 0xd2 0 IRQ_TYPE_NONE>, diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile index 17139f7003a6..1618e0a3c81d 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile @@ -1,5 +1,5 @@ -dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb -dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb +dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb +dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb always := $(dtb-y) clean-files := *.dtb diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts new file mode 100644 index 000000000000..dbea2c3d8f0c --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts @@ -0,0 +1,371 @@ +/* + * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board + * + * Copyright (C) 2016 Renesas Electronics Corp. + * Copyright (C) 2016 Cogent Embedded, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; +#include "r8a7795.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "Renesas H3ULCB board based on r8a7795"; + compatible = "renesas,h3ulcb", "renesas,r8a7795"; + + aliases { + serial0 = &scif2; + ethernet0 = &avb; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + + leds { + compatible = "gpio-leds"; + + led5 { + gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; + }; + led6 { + gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; + }; + }; + + keyboard { + compatible = "gpio-keys"; + + key-1 { + linux,code = <KEY_1>; + label = "SW3"; + wakeup-source; + debounce-interval = <20>; + gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; + }; + }; + + x12_clk: x12 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; + }; + + reg_1p8v: regulator0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + 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; + }; + + vcc_sdhi0: regulator-vcc-sdhi0 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi0: regulator-vccq-sdhi0 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; + + audio_clkout: audio-clkout { + /* + * This is same as <&rcar_sound 0> + * but needed to avoid cs2000/rcar_sound probe dead-lock + */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <11289600>; + }; + + rsnd_ak4613: sound { + compatible = "simple-audio-card"; + + simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&sndcpu>; + simple-audio-card,frame-master = <&sndcpu>; + + sndcpu: simple-audio-card,cpu { + sound-dai = <&rcar_sound>; + }; + + sndcodec: simple-audio-card,codec { + sound-dai = <&ak4613>; + }; + }; +}; + +&extal_clk { + clock-frequency = <16666666>; +}; + +&extalr_clk { + clock-frequency = <32768>; +}; + +&pfc { + pinctrl-0 = <&scif_clk_pins>; + pinctrl-names = "default"; + + scif2_pins: scif2 { + groups = "scif2_data_a"; + function = "scif2"; + }; + + scif_clk_pins: scif_clk { + groups = "scif_clk_a"; + function = "scif_clk"; + }; + + i2c2_pins: i2c2 { + groups = "i2c2_a"; + function = "i2c2"; + }; + + avb_pins: avb { + groups = "avb_mdc"; + function = "avb"; + }; + + sdhi0_pins: sd0 { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; + }; + + sdhi2_pins: sd2 { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <3300>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; + }; + + sound_pins: sound { + groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; + function = "ssi"; + }; + + sound_clk_pins: sound-clk { + groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", + "audio_clkout_a", "audio_clkout3_a"; + function = "audio_clk"; + }; + + usb1_pins: usb1 { + groups = "usb1"; + function = "usb1"; + }; +}; + +&scif2 { + pinctrl-0 = <&scif2_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&scif_clk { + clock-frequency = <14745600>; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_pins>; + pinctrl-names = "default"; + + status = "okay"; + + clock-frequency = <100000>; + + ak4613: codec@10 { + compatible = "asahi-kasei,ak4613"; + #sound-dai-cells = <0>; + reg = <0x10>; + clocks = <&rcar_sound 3>; + + asahi-kasei,in1-single-end; + asahi-kasei,in2-single-end; + asahi-kasei,out1-single-end; + asahi-kasei,out2-single-end; + asahi-kasei,out3-single-end; + asahi-kasei,out4-single-end; + asahi-kasei,out5-single-end; + asahi-kasei,out6-single-end; + }; + + cs2000: clk-multiplier@4f { + #clock-cells = <0>; + compatible = "cirrus,cs2000-cp"; + reg = <0x4f>; + clocks = <&audio_clkout>, <&x12_clk>; + clock-names = "clk_in", "ref_clk"; + + assigned-clocks = <&cs2000>; + assigned-clock-rates = <24576000>; /* 1/1 divide */ + }; +}; + +&rcar_sound { + pinctrl-0 = <&sound_pins &sound_clk_pins>; + pinctrl-names = "default"; + + /* Single DAI */ + #sound-dai-cells = <0>; + + /* audio_clkout0/1/2/3 */ + #clock-cells = <1>; + clock-frequency = <11289600>; + + status = "okay"; + + /* update <audio_clk_b> to <cs2000> */ + 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 1019>, <&cpg CPG_MOD 1018>, + <&audio_clk_a>, <&cs2000>, + <&audio_clk_c>, + <&cpg CPG_CORE R8A7795_CLK_S0D4>; + + rcar_sound,dai { + dai0 { + playback = <&ssi0 &src0 &dvc0>; + capture = <&ssi1 &src1 &dvc1>; + }; + }; +}; + +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <&vcc_sdhi0>; + vqmmc-supply = <&vccq_sdhi0>; + cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + bus-width = <4>; + sd-uhs-sdr50; + status = "okay"; +}; + +&sdhi2 { + /* used for on-board 8bit eMMC */ + pinctrl-0 = <&sdhi2_pins>; + pinctrl-1 = <&sdhi2_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&ssi1 { + shared-pin; +}; + +&wdt0 { + timeout-sec = <60>; + status = "okay"; +}; + +&audio_clk_a { + clock-frequency = <22579200>; +}; + +&avb { + pinctrl-0 = <&avb_pins>; + pinctrl-names = "default"; + renesas,no-ether-link; + phy-handle = <&phy0>; + status = "okay"; + + phy0: ethernet-phy@0 { + rxc-skew-ps = <900>; + rxdv-skew-ps = <0>; + rxd0-skew-ps = <0>; + rxd1-skew-ps = <0>; + rxd2-skew-ps = <0>; + rxd3-skew-ps = <0>; + txc-skew-ps = <900>; + txen-skew-ps = <0>; + txd0-skew-ps = <0>; + txd1-skew-ps = <0>; + txd2-skew-ps = <0>; + txd3-skew-ps = <0>; + reg = <0>; + interrupt-parent = <&gpio2>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&usb2_phy1 { + pinctrl-0 = <&usb1_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 98f02631a0f0..bcaf4008d32d 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -62,6 +62,24 @@ clock-frequency = <24576000>; }; + reg_1p8v: regulator0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + 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; + }; + vcc_sdhi0: regulator-vcc-sdhi0 { compatible = "regulator-fixed"; @@ -110,6 +128,17 @@ 1800000 0>; }; + vbus0_usb2: regulator-vbus0-usb2 { + compatible = "regulator-fixed"; + + regulator-name = "USB20_VBUS0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpio = <&gpio6 16 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + audio_clkout: audio_clkout { /* * This is same as <&rcar_sound 0> @@ -135,6 +164,56 @@ sound-dai = <&ak4613>; }; }; + + 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>; + }; + }; + }; + }; + + vga { + compatible = "vga-connector"; + + port { + vga_in: endpoint { + remote-endpoint = <&adv7123_out>; + }; + }; + }; +}; + +&du { + pinctrl-0 = <&du_pins>; + pinctrl-names = "default"; + status = "okay"; + + ports { + port@0 { + endpoint { + remote-endpoint = <&adv7123_in>; + }; + }; + port@3 { + lvds_connector: endpoint { + }; + }; + }; }; &extal_clk { @@ -172,14 +251,45 @@ function = "avb"; }; + du_pins: du { + groups = "du_rgb888", "du_sync", "du_oddf", "du_clk_out_0"; + function = "du"; + }; + sdhi0_pins: sd0 { groups = "sdhi0_data4", "sdhi0_ctrl"; function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; + }; + + sdhi2_pins: sd2 { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <3300>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; }; sdhi3_pins: sd3 { groups = "sdhi3_data4", "sdhi3_ctrl"; function = "sdhi3"; + power-source = <3300>; + }; + + sdhi3_pins_uhs: sd3_uhs { + groups = "sdhi3_data4", "sdhi3_ctrl"; + function = "sdhi3"; + power-source = <1800>; }; sound_pins: sound { @@ -193,9 +303,26 @@ function = "audio_clk"; }; + usb0_pins: usb0 { + groups = "usb0"; + function = "usb0"; + }; + usb1_pins: usb1 { - groups = "usb1"; - function = "usb1"; + mux { + groups = "usb1"; + function = "usb1"; + }; + + ovc { + pins = "GP_6_27"; + bias-pull-up; + }; + + pwen { + pins = "GP_6_26"; + bias-pull-down; + }; }; usb2_pins: usb2 { @@ -304,25 +431,42 @@ &sdhi0 { pinctrl-0 = <&sdhi0_pins>; - pinctrl-names = "default"; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; vmmc-supply = <&vcc_sdhi0>; vqmmc-supply = <&vccq_sdhi0>; cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; bus-width = <4>; + sd-uhs-sdr50; + status = "okay"; +}; + +&sdhi2 { + /* used for on-board 8bit eMMC */ + pinctrl-0 = <&sdhi2_pins>; + pinctrl-1 = <&sdhi2_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + non-removable; status = "okay"; }; &sdhi3 { pinctrl-0 = <&sdhi3_pins>; - pinctrl-names = "default"; + pinctrl-1 = <&sdhi3_pins_uhs>; + pinctrl-names = "default", "state_uhs"; vmmc-supply = <&vcc_sdhi3>; vqmmc-supply = <&vccq_sdhi3>; cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; bus-width = <4>; + sd-uhs-sdr50; status = "okay"; }; @@ -369,6 +513,14 @@ status = "okay"; }; +&usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; + + vbus-supply = <&vbus0_usb2>; + status = "okay"; +}; + &usb2_phy1 { pinctrl-0 = <&usb1_pins>; pinctrl-names = "default"; @@ -383,6 +535,10 @@ status = "okay"; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -391,6 +547,10 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; }; @@ -399,6 +559,10 @@ status = "okay"; }; +&hsusb { + status = "okay"; +}; + &pcie_bus_clk { clock-frequency = <100000000>; status = "okay"; diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index b902356873c2..bbf594bce930 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -321,6 +321,16 @@ #power-domain-cells = <0>; }; + rst: reset-controller@e6160000 { + compatible = "renesas,r8a7795-rst"; + reg = <0 0xe6160000 0 0x0200>; + }; + + prr: chipid@fff00044 { + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; + }; + sysc: system-controller@e6180000 { compatible = "renesas,r8a7795-sysc"; reg = <0 0xe6180000 0 0x0400>; @@ -328,7 +338,8 @@ }; audma0: dma-controller@ec700000 { - compatible = "renesas,rcar-dmac"; + compatible = "renesas,dmac-r8a7795", + "renesas,rcar-dmac"; reg = <0 0xec700000 0 0x10000>; interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH @@ -360,7 +371,8 @@ }; audma1: dma-controller@ec720000 { - compatible = "renesas,rcar-dmac"; + compatible = "renesas,dmac-r8a7795", + "renesas,rcar-dmac"; reg = <0 0xec720000 0 0x10000>; interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH @@ -1098,6 +1110,7 @@ reg = <0 0xee100000 0 0x2000>; interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 314>; + max-frequency = <200000000>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1107,6 +1120,7 @@ reg = <0 0xee120000 0 0x2000>; interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 313>; + max-frequency = <200000000>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; @@ -1116,8 +1130,8 @@ reg = <0 0xee140000 0 0x2000>; interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 312>; + max-frequency = <200000000>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - cap-mmc-highspeed; status = "disabled"; }; @@ -1126,8 +1140,8 @@ reg = <0 0xee160000 0 0x2000>; interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_MOD 311>; + max-frequency = <200000000>; power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; - cap-mmc-highspeed; status = "disabled"; }; @@ -1224,6 +1238,23 @@ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; + + hsusb: usb@e6590000 { + compatible = "renesas,usbhs-r8a7795", + "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 R8A7795_PD_ALWAYS_ON>; + status = "disabled"; + }; + pciec0: pcie@fe000000 { compatible = "renesas,pcie-r8a7795"; reg = <0 0xfe000000 0 0x80000>; @@ -1273,5 +1304,252 @@ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; status = "disabled"; }; + + vspbc: vsp@fe920000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe920000 0 0x8000>; + interrupts = <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 624>; + power-domains = <&sysc R8A7795_PD_A3VP>; + + renesas,fcp = <&fcpvb1>; + }; + + fcpvb1: fcp@fe92f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe92f000 0 0x200>; + clocks = <&cpg CPG_MOD 606>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + fcpf0: fcp@fe950000 { + compatible = "renesas,fcpf"; + reg = <0 0xfe950000 0 0x200>; + clocks = <&cpg CPG_MOD 615>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + fcpf1: fcp@fe951000 { + compatible = "renesas,fcpf"; + reg = <0 0xfe951000 0 0x200>; + clocks = <&cpg CPG_MOD 614>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + fcpf2: fcp@fe952000 { + compatible = "renesas,fcpf"; + reg = <0 0xfe952000 0 0x200>; + clocks = <&cpg CPG_MOD 613>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + vspbd: 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 R8A7795_PD_A3VP>; + + renesas,fcp = <&fcpvb0>; + }; + + fcpvb0: fcp@fe96f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe96f000 0 0x200>; + clocks = <&cpg CPG_MOD 607>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + 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 R8A7795_PD_A3VP>; + + renesas,fcp = <&fcpvi0>; + }; + + fcpvi0: fcp@fe9af000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9af000 0 0x200>; + clocks = <&cpg CPG_MOD 611>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + vspi1: vsp@fe9b0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9b0000 0 0x8000>; + interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 630>; + power-domains = <&sysc R8A7795_PD_A3VP>; + + renesas,fcp = <&fcpvi1>; + }; + + fcpvi1: fcp@fe9bf000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9bf000 0 0x200>; + clocks = <&cpg CPG_MOD 610>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + vspi2: vsp@fe9c0000 { + compatible = "renesas,vsp2"; + reg = <0 0xfe9c0000 0 0x8000>; + interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 629>; + power-domains = <&sysc R8A7795_PD_A3VP>; + + renesas,fcp = <&fcpvi2>; + }; + + fcpvi2: fcp@fe9cf000 { + compatible = "renesas,fcpv"; + reg = <0 0xfe9cf000 0 0x200>; + clocks = <&cpg CPG_MOD 609>; + power-domains = <&sysc R8A7795_PD_A3VP>; + }; + + vspd0: vsp@fea20000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea20000 0 0x4000>; + interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 623>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + + renesas,fcp = <&fcpvd0>; + }; + + fcpvd0: fcp@fea27000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea27000 0 0x200>; + clocks = <&cpg CPG_MOD 603>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + }; + + vspd1: vsp@fea28000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea28000 0 0x4000>; + interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 622>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + + renesas,fcp = <&fcpvd1>; + }; + + fcpvd1: fcp@fea2f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea2f000 0 0x200>; + clocks = <&cpg CPG_MOD 602>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + }; + + vspd2: vsp@fea30000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea30000 0 0x4000>; + interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 621>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + + renesas,fcp = <&fcpvd2>; + }; + + fcpvd2: fcp@fea37000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea37000 0 0x200>; + clocks = <&cpg CPG_MOD 601>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + }; + + vspd3: vsp@fea38000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea38000 0 0x4000>; + interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 620>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + + renesas,fcp = <&fcpvd3>; + }; + + fcpvd3: fcp@fea3f000 { + compatible = "renesas,fcpv"; + reg = <0 0xfea3f000 0 0x200>; + clocks = <&cpg CPG_MOD 600>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + }; + + 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 R8A7795_PD_A3VP>; + renesas,fcp = <&fcpf0>; + }; + + fdp1@fe944000 { + compatible = "renesas,fdp1"; + reg = <0 0xfe944000 0 0x2400>; + interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 118>; + power-domains = <&sysc R8A7795_PD_A3VP>; + renesas,fcp = <&fcpf1>; + }; + + fdp1@fe948000 { + compatible = "renesas,fdp1"; + reg = <0 0xfe948000 0 0x2400>; + interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 117>; + power-domains = <&sysc R8A7795_PD_A3VP>; + renesas,fcp = <&fcpf2>; + }; + + du: display@feb00000 { + compatible = "renesas,du-r8a7795"; + reg = <0 0xfeb00000 0 0x80000>, + <0 0xfeb90000 0 0x14>; + reg-names = "du", "lvds.0"; + interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>; + 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"; + status = "disabled"; + + vsps = <&vspd0 &vspd1 &vspd2 &vspd3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + du_out_rgb: endpoint { + }; + }; + port@1 { + reg = <1>; + du_out_hdmi0: endpoint { + }; + }; + port@2 { + reg = <2>; + du_out_hdmi1: endpoint { + }; + }; + port@3 { + reg = <3>; + du_out_lvds0: endpoint { + }; + }; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts new file mode 100644 index 000000000000..c3f064ac2cb4 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts @@ -0,0 +1,189 @@ +/* + * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board + * + * Copyright (C) 2016 Renesas Electronics Corp. + * Copyright (C) 2016 Cogent Embedded, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; +#include "r8a7796.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "Renesas M3ULCB board based on r8a7796"; + compatible = "renesas,m3ulcb", "renesas,r8a7796"; + + aliases { + serial0 = &scif2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + + leds { + compatible = "gpio-leds"; + + led5 { + gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; + }; + led6 { + gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; + }; + }; + + keyboard { + compatible = "gpio-keys"; + + key-1 { + linux,code = <KEY_1>; + label = "SW3"; + wakeup-source; + debounce-interval = <20>; + gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; + }; + }; + + reg_1p8v: regulator0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + 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; + }; + + vcc_sdhi0: regulator-vcc-sdhi0 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi0: regulator-vccq-sdhi0 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; +}; + +&extal_clk { + clock-frequency = <16666666>; +}; + +&extalr_clk { + clock-frequency = <32768>; +}; + +&pfc { + pinctrl-0 = <&scif_clk_pins>; + pinctrl-names = "default"; + + scif2_pins: scif2 { + groups = "scif2_data_a"; + function = "scif2"; + }; + + scif_clk_pins: scif_clk { + groups = "scif_clk_a"; + function = "scif_clk"; + }; + + sdhi0_pins: sd0 { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; + }; + + sdhi2_pins: sd2 { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <3300>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; + }; +}; + +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <&vcc_sdhi0>; + vqmmc-supply = <&vccq_sdhi0>; + cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + bus-width = <4>; + sd-uhs-sdr50; + status = "okay"; +}; + +&sdhi2 { + /* used for on-board 8bit eMMC */ + pinctrl-0 = <&sdhi2_pins>; + pinctrl-1 = <&sdhi2_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&scif2 { + pinctrl-0 = <&scif2_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&scif_clk { + clock-frequency = <14745600>; + status = "okay"; +}; + +&wdt0 { + timeout-sec = <60>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts index e72be3856d79..f35e96ca7d60 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts @@ -10,6 +10,7 @@ /dts-v1/; #include "r8a7796.dtsi" +#include <dt-bindings/gpio/gpio.h> / { model = "Renesas Salvator-X board based on r8a7796"; @@ -29,13 +30,181 @@ /* first 128MB is reserved for secure area. */ reg = <0x0 0x48000000 0x0 0x78000000>; }; + + reg_1p8v: regulator0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + 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; + }; + + vcc_sdhi0: regulator-vcc-sdhi0 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi0: regulator-vccq-sdhi0 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; + + vcc_sdhi3: regulator-vcc-sdhi3 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI3 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + vccq_sdhi3: regulator-vccq-sdhi3 { + compatible = "regulator-gpio"; + + regulator-name = "SDHI3 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; + gpios-states = <1>; + states = <3300000 1 + 1800000 0>; + }; +}; + +&pfc { + pinctrl-0 = <&scif_clk_pins>; + pinctrl-names = "default"; + + scif2_pins: scif2 { + groups = "scif2_data_a"; + function = "scif2"; + }; + scif_clk_pins: scif_clk { + groups = "scif_clk_a"; + function = "scif_clk"; + }; + + i2c2_pins: i2c2 { + groups = "i2c2_a"; + function = "i2c2"; + }; + + sdhi0_pins: sd0 { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <3300>; + }; + + sdhi0_pins_uhs: sd0_uhs { + groups = "sdhi0_data4", "sdhi0_ctrl"; + function = "sdhi0"; + power-source = <1800>; + }; + + sdhi2_pins: sd2 { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <3300>; + }; + + sdhi2_pins_uhs: sd2_uhs { + groups = "sdhi2_data8", "sdhi2_ctrl"; + function = "sdhi2"; + power-source = <1800>; + }; + + sdhi3_pins: sd3 { + groups = "sdhi3_data4", "sdhi3_ctrl"; + function = "sdhi3"; + power-source = <3300>; + }; + + sdhi3_pins_uhs: sd3_uhs { + groups = "sdhi3_data4", "sdhi3_ctrl"; + function = "sdhi3"; + power-source = <1800>; + }; }; &extal_clk { clock-frequency = <16666666>; }; +&extalr_clk { + clock-frequency = <32768>; +}; + +&sdhi0 { + pinctrl-0 = <&sdhi0_pins>; + pinctrl-1 = <&sdhi0_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <&vcc_sdhi0>; + vqmmc-supply = <&vccq_sdhi0>; + cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + bus-width = <4>; + sd-uhs-sdr50; + status = "okay"; +}; + +&sdhi2 { + /* used for on-board 8bit eMMC */ + pinctrl-0 = <&sdhi2_pins>; + pinctrl-1 = <&sdhi2_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&sdhi3 { + pinctrl-0 = <&sdhi3_pins>; + pinctrl-1 = <&sdhi3_pins_uhs>; + pinctrl-names = "default", "state_uhs"; + + vmmc-supply = <&vcc_sdhi3>; + vqmmc-supply = <&vccq_sdhi3>; + cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; + bus-width = <4>; + sd-uhs-sdr50; + status = "okay"; +}; + &scif2 { + pinctrl-0 = <&scif2_pins>; + pinctrl-names = "default"; status = "okay"; }; @@ -44,6 +213,13 @@ status = "okay"; }; +&i2c2 { + pinctrl-0 = <&i2c2_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + &wdt0 { timeout-sec = <60>; status = "okay"; diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi index 1edf82440d78..28ba59a00cd8 100644 --- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi @@ -17,6 +17,16 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + i2c6 = &i2c6; + }; + psci { compatible = "arm,psci-0.2"; method = "smc"; @@ -107,6 +117,123 @@ status = "disabled"; }; + gpio0: gpio@e6050000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio1: gpio@e6051000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio2: gpio@e6052000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio3: gpio@e6053000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio4: gpio@e6054000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio5: gpio@e6055000 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio6: gpio@e6055400 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + gpio7: gpio@e6055800 { + compatible = "renesas,gpio-r8a7796", + "renesas,gpio-rcar"; + 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 R8A7796_PD_ALWAYS_ON>; + }; + + pfc: pin-controller@e6060000 { + compatible = "renesas,pfc-r8a7796"; + reg = <0 0xe6060000 0 0x50c>; + }; + cpg: clock-controller@e6150000 { compatible = "renesas,r8a7796-cpg-mssr"; reg = <0 0xe6150000 0 0x1000>; @@ -116,12 +243,123 @@ #power-domain-cells = <0>; }; + rst: reset-controller@e6160000 { + compatible = "renesas,r8a7796-rst"; + reg = <0 0xe6160000 0 0x0200>; + }; + + prr: chipid@fff00044 { + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; + }; + sysc: system-controller@e6180000 { compatible = "renesas,r8a7796-sysc"; reg = <0 0xe6180000 0 0x0400>; #power-domain-cells = <1>; }; + i2c0: i2c@e6500000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "renesas,i2c-r8a7796"; + reg = <0 0xe6500000 0 0x40>; + interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 931>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe6508000 0 0x40>; + interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 930>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe6510000 0 0x40>; + interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 929>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe66d0000 0 0x40>; + interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 928>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe66d8000 0 0x40>; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 927>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe66e0000 0 0x40>; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 919>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + 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-r8a7796"; + reg = <0 0xe66e8000 0 0x40>; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 918>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + dmas = <&dmac0 0x9d>, <&dmac0 0x9c>; + dma-names = "tx", "rx"; + i2c-scl-internal-delay-ns = <6>; + status = "disabled"; + }; + scif2: serial@e6e88000 { compatible = "renesas,scif-r8a7796", "renesas,rcar-gen3-scif", "renesas,scif"; @@ -134,5 +372,144 @@ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; status = "disabled"; }; + + dmac0: dma-controller@e6700000 { + compatible = "renesas,dmac-r8a7796", + "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 R8A7796_PD_ALWAYS_ON>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a7796", + "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 R8A7796_PD_ALWAYS_ON>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + dmac2: dma-controller@e7310000 { + compatible = "renesas,dmac-r8a7796", + "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 R8A7796_PD_ALWAYS_ON>; + #dma-cells = <1>; + dma-channels = <16>; + }; + + sdhi0: sd@ee100000 { + compatible = "renesas,sdhi-r8a7796"; + reg = <0 0xee100000 0 0x2000>; + interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 314>; + max-frequency = <200000000>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; + }; + + sdhi1: sd@ee120000 { + compatible = "renesas,sdhi-r8a7796"; + reg = <0 0xee120000 0 0x2000>; + interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 313>; + max-frequency = <200000000>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; + }; + + sdhi2: sd@ee140000 { + compatible = "renesas,sdhi-r8a7796"; + reg = <0 0xee140000 0 0x2000>; + interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 312>; + max-frequency = <200000000>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; + }; + + sdhi3: sd@ee160000 { + compatible = "renesas,sdhi-r8a7796"; + reg = <0 0xee160000 0 0x2000>; + interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 311>; + max-frequency = <200000000>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 7037a161b6ef..3a862894ea44 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -1,5 +1,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-orion-r68-meta.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts index 46cdddfcea6c..e5eeca2c2456 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts @@ -116,7 +116,6 @@ cap-mmc-highspeed; clock-frequency = <150000000>; disable-wp; - keep-power-in-suspend; non-removable; num-slots = <1>; vmmc-supply = <&vcc_io>; @@ -258,8 +257,6 @@ }; vcc_sd: SWITCH_REG1 { - regulator-always-on; - regulator-boot-on; regulator-name = "vcc_sd"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts b/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts new file mode 100644 index 000000000000..ff5a40399d02 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2016 Matthias Brugger <mbrugger@suse.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 <dt-bindings/input/input.h> +#include "rk3368.dtsi" + +/ { + model = "Rockchip Orion R68"; + compatible = "tronsmart,orion-r68-meta", "rockchip,rk3368"; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + emmc_pwrseq: emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + pinctrl-0 = <&emmc_reset>; + pinctrl-names = "default"; + reset-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + }; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + }; + + keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + + power { + wakeup-source; + gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + label = "GPIO Power"; + linux,code = <KEY_POWER>; + }; + }; + + leds: gpio-leds { + compatible = "gpio-leds"; + + red { + gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>; + label = "orion:red:led"; + pinctrl-names = "default"; + pinctrl-0 = <&led_ctl>; + default-state = "on"; + }; + + blue { + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + label = "orion:blue:led"; + pinctrl-names = "default"; + pinctrl-0 = <&stby_pwren>; + default-state = "off"; + }; + }; + + vcc_18: vcc18-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; + + /* supplies both host and otg */ + vcc_host: vcc-host-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 4 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc_host"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; + + vcc_io: vcc-io-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; + + vcc_lan: vcc-lan-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_lan"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_io>; + }; + + vcc_sd: vcc-sd-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sd"; + gpio = <&gpio3 11 GPIO_ACTIVE_LOW>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io>; + }; + + vcc_sys: vcc-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + vccio_sd: vcc-io-sd-regulator { + compatible = "regulator-fixed"; + regulator-name= "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_io>; + }; + + vccio_wl: vccio-wl-regulator { + compatible = "regulator-fixed"; + regulator-name = "vccio_wl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_io>; + }; + + vdd_10: vdd-10-regulator { + compatible = "regulator-fixed"; + regulator-name = "vdd_10"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + disable-wp; + mmc-pwrseq = <&emmc_pwrseq>; + mmc-hs200-1_2v; + mmc-hs200-1_8v; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 12 0>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 1000000>; + tx_delay = <0x30>; + rx_delay = <0x10>; + status = "ok"; +}; + +&i2c0 { + status = "okay"; + + vdd_cpu: syr827@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu"; + regulator-enable-ramp-delay = <300>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <8000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc_sys>; + }; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "xin32k"; + /* rtc_int is not connected */ + }; +}; + +&pinctrl { + pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma { + bias-disable; + drive-strength = <8>; + }; + + pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma { + bias-pull-up; + drive-strength = <8>; + }; + + emmc { + emmc_bus8: emmc-bus8 { + rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>, + <1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>; + }; + + emmc-clk { + rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>; + }; + + emmc-cmd { + rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>; + }; + + emmc_reset: emmc-reset { + rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + keys { + pwr_key: pwr-key { + rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + stby_pwren: stby-pwren { + rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_ctl: led-ctl { + rockchip,pins = <3 29 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdmmc { + sdmmc_clk: sdmmc-clk { + rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none_drv_8ma>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + + sdmmc_cd: sdmmc-cd { + rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <2 6 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <2 7 RK_FUNC_1 &pcfg_pull_up_drv_8ma>, + <2 8 RK_FUNC_1 &pcfg_pull_up_drv_8ma>; + }; + }; + + usb { + host_vbus_drv: host-vbus-drv { + rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&saradc { + vref-supply = <&vcc_18>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + clock-frequency = <50000000>; + max-frequency = <50000000>; + cap-sd-highspeed; + card-detect-delay = <200>; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_xfer>; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_otg { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts new file mode 100644 index 000000000000..85f7a243d744 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd + * + * 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 "rk3368.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "Rockchip PX5 EVB"; + compatible = "rockchip,px5-evb", "rockchip,px5", "rockchip,rk3368"; + + chosen { + stdout-path = "serial4:115200n8"; + }; + + memory@0 { + reg = <0x0 0x0 0x0 0x80000000>; + device_type = "memory"; + }; + + keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + + power { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "GPIO Power"; + linux,code = <KEY_POWER>; + wakeup-source; + }; + }; + + vcc_sys: vcc-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_sys"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&emmc { + status = "okay"; + bus-width = <8>; + cap-mmc-highspeed; + clock-frequency = <150000000>; + disable-wp; + keep-power-in-suspend; + mmc-hs200-1_8v; + no-sdio; + no-sd; + non-removable; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>; + vmmc-supply = <&vcc_io>; + vqmmc-supply = <&vcc18_flash>; +}; + +&i2c0 { + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio0>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&pmic_sleep>; + rockchip,system-power-controller; + 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_sys>; + vcc10-supply = <&vcc_sys>; + vcc11-supply = <&vcc_sys>; + vcc12-supply = <&vcc_io>; + clock-output-names = "xin32k", "rk808-clkout2"; + #clock-cells = <1>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_cpu"; + }; + + vdd_log: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd_log"; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + }; + + vcc18_flash: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_flash"; + }; + + vcca_33: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcca_33"; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + }; + + avdd_33: LDO_REG4 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "avdd_33"; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + }; + + vcc18_lcd: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + }; + + vcc_sd: SWITCH_REG1 { + regulator-name = "vcc_sd"; + }; + + vcc33_lcd: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc33_lcd"; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + + accelerometer@18 { + compatible = "bosch,bma250"; + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c2 { + status = "okay"; + + gsl1680: touchscreen@40 { + compatible = "silead,gsl1680"; + reg = <0x40>; + interrupt-parent = <&gpio3>; + interrupts = <28 IRQ_TYPE_EDGE_FALLING>; + power-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>; + touchscreen-size-x = <800>; + touchscreen-size-y = <1280>; + silead,max-fingers = <5>; + }; +}; + +&pinctrl { + keys { + pwr_key: pwr-key { + rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_sleep: pmic-sleep { + rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>; + }; + + pmic_int: pmic-int { + rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&sdmmc { + status = "okay"; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + no-emmc; + no-sdio; + num-slots = <1>; + sd-uhs-sdr12; + sd-uhs-sdr25; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_bus4>, <&sdmmc_cd>; + rockchip,default-sample-phase = <90>; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; +}; + +&tsadc { + status = "okay"; + rockchip,hw-tshut-mode = <0>; /* CRU */ + rockchip,hw-tshut-polarity = <1>; /* high */ +}; + +&uart4 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_otg { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts index 82a32e5591e2..eed1ef6669ff 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts +++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts @@ -248,7 +248,6 @@ &sdio0 { assigned-clocks = <&cru SCLK_SDIO0>; assigned-clock-parents = <&cru PLL_CPLL>; - broken-cd; bus-width = <4>; cap-sd-highspeed; cap-sdio-irq; diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index 4f44d1191bfd..a635adc47e74 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -45,6 +45,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/soc/rockchip,boot-mode.h> #include <dt-bindings/thermal/thermal.h> / { @@ -230,7 +231,7 @@ sdmmc: dwmmc@ff0c0000 { compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xff0c0000 0x0 0x4000>; - clock-freq-min-max = <400000 150000000>; + max-frequency = <150000000>; clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; @@ -242,7 +243,7 @@ sdio0: dwmmc@ff0d0000 { compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xff0d0000 0x0 0x4000>; - clock-freq-min-max = <400000 150000000>; + max-frequency = <150000000>; clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>, <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>; clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; @@ -254,7 +255,7 @@ emmc: dwmmc@ff0f0000 { compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xff0f0000 0x0 0x4000>; - clock-freq-min-max = <400000 150000000>; + max-frequency = <150000000>; clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; @@ -314,16 +315,16 @@ status = "disabled"; }; - i2c1: i2c@ff140000 { + i2c2: i2c@ff140000 { compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; reg = <0x0 0xff140000 0x0 0x1000>; interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; clock-names = "i2c"; - clocks = <&cru PCLK_I2C1>; + clocks = <&cru PCLK_I2C2>; pinctrl-names = "default"; - pinctrl-0 = <&i2c1_xfer>; + pinctrl-0 = <&i2c2_xfer>; status = "disabled"; }; @@ -536,7 +537,6 @@ g-np-tx-fifo-size = <16>; g-rx-fifo-size = <275>; g-tx-fifo-size = <256 128 128 64 64 32>; - g-use-dma; status = "disabled"; }; @@ -553,16 +553,16 @@ status = "disabled"; }; - i2c2: i2c@ff660000 { + i2c1: i2c@ff660000 { compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c"; reg = <0x0 0xff660000 0x0 0x1000>; interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; #address-cells = <1>; #size-cells = <0>; clock-names = "i2c"; - clocks = <&cru PCLK_I2C2>; + clocks = <&cru PCLK_I2C1>; pinctrl-names = "default"; - pinctrl-0 = <&i2c2_xfer>; + pinctrl-0 = <&i2c1_xfer>; status = "disabled"; }; @@ -641,6 +641,15 @@ compatible = "rockchip,rk3368-pmu-io-voltage-domain"; status = "disabled"; }; + + reboot-mode { + compatible = "syscon-reboot-mode"; + offset = <0x200>; + mode-normal = <BOOT_NORMAL>; + mode-recovery = <BOOT_RECOVERY>; + mode-bootloader = <BOOT_FASTBOOT>; + mode-loader = <BOOT_BL_DOWNLOAD>; + }; }; cru: clock-controller@ff760000 { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index d33aa06d46f5..3040a989d699 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts @@ -49,6 +49,53 @@ compatible = "rockchip,rk3399-evb", "rockchip,rk3399", "google,rk3399evb-rev2"; + backlight: backlight { + compatible = "pwm-backlight"; + brightness-levels = < + 0 1 2 3 4 5 6 7 + 8 9 10 11 12 13 14 15 + 16 17 18 19 20 21 22 23 + 24 25 26 27 28 29 30 31 + 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255>; + default-brightness-level = <200>; + enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + pwms = <&pwm0 0 25000 0>; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + vdd_center: vdd-center { compatible = "pwm-regulator"; pwms = <&pwm3 0 25000 0>; @@ -69,18 +116,61 @@ regulator-max-microvolt = <3300000>; }; + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-name = "vcc5v0_host"; + vin-supply = <&vcc5v0_sys>; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_phy"; regulator-always-on; regulator-boot-on; }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; + }; &emmc_phy { status = "okay"; }; +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_phy>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 15 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; +}; + &pwm0 { status = "okay"; }; @@ -101,6 +191,36 @@ status = "okay"; }; +&pcie_phy { + status = "disabled"; +}; + +&pcie0 { + ep-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; + num-lanes = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_clkreqn>; + status = "disabled"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + &uart2 { status = "okay"; }; @@ -133,4 +253,11 @@ <1 18 RK_FUNC_GPIO &pcfg_pull_down>; }; }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = + <4 25 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index a6dd623a8845..c928015d39a2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -45,6 +45,7 @@ #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/pinctrl/rockchip.h> +#include <dt-bindings/power/rk3399-power.h> #include <dt-bindings/thermal/thermal.h> / { @@ -152,6 +153,16 @@ }; }; + pmu_a53 { + compatible = "arm,cortex-a53-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>; + }; + + pmu_a72 { + compatible = "arm,cortex-a72-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>; + }; + psci { compatible = "arm,psci-1.0"; method = "smc"; @@ -159,10 +170,11 @@ timer { compatible = "arm,armv8-timer"; - interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, - <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, - <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, - <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>, + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>; + arm,no-tick-in-suspend; }; xin24m: xin24m { @@ -181,8 +193,8 @@ dmac_bus: dma-controller@ff6d0000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x0 0xff6d0000 0x0 0x4000>; - interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <1>; clocks = <&cru ACLK_DMAC0_PERILP>; clock-names = "apb_pclk"; @@ -191,20 +203,40 @@ dmac_peri: dma-controller@ff6e0000 { compatible = "arm,pl330", "arm,primecell"; reg = <0x0 0xff6e0000 0x0 0x4000>; - interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <1>; clocks = <&cru ACLK_DMAC1_PERILP>; clock-names = "apb_pclk"; }; }; + gmac: ethernet@fe300000 { + compatible = "rockchip,rk3399-gmac"; + reg = <0x0 0xfe300000 0x0 0x10000>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "macirq"; + clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>, + <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>, + <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_ref", + "clk_mac_refout", "aclk_mac", + "pclk_mac"; + power-domains = <&power RK3399_PD_GMAC>; + resets = <&cru SRST_A_GMAC>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; + status = "disabled"; + }; + sdio0: dwmmc@fe310000 { compatible = "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xfe310000 0x0 0x4000>; - interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; - clock-freq-min-max = <400000 150000000>; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH 0>; + max-frequency = <150000000>; clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; @@ -216,19 +248,20 @@ compatible = "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xfe320000 0x0 0x4000>; - interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; - clock-freq-min-max = <400000 150000000>; + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>; + max-frequency = <150000000>; clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; fifo-depth = <0x100>; + power-domains = <&power RK3399_PD_SD>; status = "disabled"; }; sdhci: sdhci@fe330000 { compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1"; reg = <0x0 0xfe330000 0x0 0x10000>; - interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH 0>; arasan,soc-ctl-syscon = <&grf>; assigned-clocks = <&cru SCLK_EMMC>; assigned-clock-rates = <200000000>; @@ -238,22 +271,67 @@ #clock-cells = <0>; phys = <&emmc_phy>; phy-names = "phy_arasan"; + power-domains = <&power RK3399_PD_EMMC>; status = "disabled"; }; + pcie0: pcie@f8000000 { + compatible = "rockchip,rk3399-pcie"; + reg = <0x0 0xf8000000 0x0 0x2000000>, + <0x0 0xfd000000 0x0 0x1000000>; + reg-names = "axi-base", "apb-base"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + bus-range = <0x0 0x1>; + clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, + <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; + clock-names = "aclk", "aclk-perf", + "hclk", "pm"; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "sys", "legacy", "client"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie0_intc 0>, + <0 0 0 2 &pcie0_intc 1>, + <0 0 0 3 &pcie0_intc 2>, + <0 0 0 4 &pcie0_intc 3>; + msi-map = <0x0 &its 0x0 0x1000>; + phys = <&pcie_phy>; + phy-names = "pcie-phy"; + ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000 + 0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>; + resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, + <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>, + <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, + <&cru SRST_A_PCIE>; + reset-names = "core", "mgmt", "mgmt-sticky", "pipe", + "pm", "pclk", "aclk"; + status = "disabled"; + + pcie0_intc: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + usb_host0_ehci: usb@fe380000 { compatible = "generic-ehci"; reg = <0x0 0xfe380000 0x0 0x20000>; - interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>; clock-names = "hclk_host0", "hclk_host0_arb"; + phys = <&u2phy0_host>; + phy-names = "usb"; status = "disabled"; }; usb_host0_ohci: usb@fe3a0000 { compatible = "generic-ohci"; reg = <0x0 0xfe3a0000 0x0 0x20000>; - interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>; clock-names = "hclk_host0", "hclk_host0_arb"; status = "disabled"; @@ -262,16 +340,18 @@ usb_host1_ehci: usb@fe3c0000 { compatible = "generic-ehci"; reg = <0x0 0xfe3c0000 0x0 0x20000>; - interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>; clock-names = "hclk_host1", "hclk_host1_arb"; + phys = <&u2phy1_host>; + phy-names = "usb"; status = "disabled"; }; usb_host1_ohci: usb@fe3e0000 { compatible = "generic-ohci"; reg = <0x0 0xfe3e0000 0x0 0x20000>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>; clock-names = "hclk_host1", "hclk_host1_arb"; status = "disabled"; @@ -279,7 +359,7 @@ gic: interrupt-controller@fee00000 { compatible = "arm,gic-v3"; - #interrupt-cells = <3>; + #interrupt-cells = <4>; #address-cells = <2>; #size-cells = <2>; ranges; @@ -290,12 +370,34 @@ <0x0 0xfff00000 0 0x10000>, /* GICC */ <0x0 0xfff10000 0 0x10000>, /* GICH */ <0x0 0xfff20000 0 0x10000>; /* GICV */ - interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>; its: interrupt-controller@fee20000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0xfee20000 0x0 0x20000>; }; + + ppi-partitions { + ppi_cluster0: interrupt-partition-0 { + affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>; + }; + + ppi_cluster1: interrupt-partition-1 { + affinity = <&cpu_b0 &cpu_b1>; + }; + }; + }; + + saradc: saradc@ff100000 { + compatible = "rockchip,rk3399-saradc"; + reg = <0x0 0xff100000 0x0 0x100>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH 0>; + #io-channel-cells = <1>; + clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>; + clock-names = "saradc", "apb_pclk"; + resets = <&cru SRST_P_SARADC>; + reset-names = "saradc-apb"; + status = "disabled"; }; i2c1: i2c@ff110000 { @@ -305,7 +407,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c1_xfer>; #address-cells = <1>; @@ -320,7 +422,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c2_xfer>; #address-cells = <1>; @@ -335,7 +437,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c3_xfer>; #address-cells = <1>; @@ -350,7 +452,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c5_xfer>; #address-cells = <1>; @@ -365,7 +467,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c6_xfer>; #address-cells = <1>; @@ -380,7 +482,7 @@ assigned-clock-rates = <200000000>; clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c7_xfer>; #address-cells = <1>; @@ -393,7 +495,7 @@ reg = <0x0 0xff180000 0x0 0x100>; clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -406,7 +508,7 @@ reg = <0x0 0xff190000 0x0 0x100>; clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -419,7 +521,7 @@ reg = <0x0 0xff1a0000 0x0 0x100>; clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -432,7 +534,7 @@ reg = <0x0 0xff1b0000 0x0 0x100>; clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -445,7 +547,7 @@ reg = <0x0 0xff1c0000 0x0 0x1000>; clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>; #address-cells = <1>; @@ -458,7 +560,7 @@ reg = <0x0 0xff1d0000 0x0 0x1000>; clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>; #address-cells = <1>; @@ -471,7 +573,7 @@ reg = <0x0 0xff1e0000 0x0 0x1000>; clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>; #address-cells = <1>; @@ -484,7 +586,7 @@ reg = <0x0 0xff1f0000 0x0 0x1000>; clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>; #address-cells = <1>; @@ -497,7 +599,7 @@ reg = <0x0 0xff200000 0x0 0x1000>; clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>; #address-cells = <1>; @@ -577,7 +679,7 @@ tsadc: tsadc@ff260000 { compatible = "rockchip,rk3399-tsadc"; reg = <0x0 0xff260000 0x0 0x100>; - interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH 0>; assigned-clocks = <&cru SCLK_TSADC>; assigned-clock-rates = <750000>; clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; @@ -594,6 +696,225 @@ status = "disabled"; }; + qos_sd: qos@ffa74000 { + compatible = "syscon"; + reg = <0x0 0xffa74000 0x0 0x20>; + }; + + qos_emmc: qos@ffa58000 { + compatible = "syscon"; + reg = <0x0 0xffa58000 0x0 0x20>; + }; + + qos_gmac: qos@ffa5c000 { + compatible = "syscon"; + reg = <0x0 0xffa5c000 0x0 0x20>; + }; + + qos_hdcp: qos@ffa90000 { + compatible = "syscon"; + reg = <0x0 0xffa90000 0x0 0x20>; + }; + + qos_iep: qos@ffa98000 { + compatible = "syscon"; + reg = <0x0 0xffa98000 0x0 0x20>; + }; + + qos_isp0_m0: qos@ffaa0000 { + compatible = "syscon"; + reg = <0x0 0xffaa0000 0x0 0x20>; + }; + + qos_isp0_m1: qos@ffaa0080 { + compatible = "syscon"; + reg = <0x0 0xffaa0080 0x0 0x20>; + }; + + qos_isp1_m0: qos@ffaa8000 { + compatible = "syscon"; + reg = <0x0 0xffaa8000 0x0 0x20>; + }; + + qos_isp1_m1: qos@ffaa8080 { + compatible = "syscon"; + reg = <0x0 0xffaa8080 0x0 0x20>; + }; + + qos_rga_r: qos@ffab0000 { + compatible = "syscon"; + reg = <0x0 0xffab0000 0x0 0x20>; + }; + + qos_rga_w: qos@ffab0080 { + compatible = "syscon"; + reg = <0x0 0xffab0080 0x0 0x20>; + }; + + qos_video_m0: qos@ffab8000 { + compatible = "syscon"; + reg = <0x0 0xffab8000 0x0 0x20>; + }; + + qos_video_m1_r: qos@ffac0000 { + compatible = "syscon"; + reg = <0x0 0xffac0000 0x0 0x20>; + }; + + qos_video_m1_w: qos@ffac0080 { + compatible = "syscon"; + reg = <0x0 0xffac0080 0x0 0x20>; + }; + + qos_vop_big_r: qos@ffac8000 { + compatible = "syscon"; + reg = <0x0 0xffac8000 0x0 0x20>; + }; + + qos_vop_big_w: qos@ffac8080 { + compatible = "syscon"; + reg = <0x0 0xffac8080 0x0 0x20>; + }; + + qos_vop_little: qos@ffad0000 { + compatible = "syscon"; + reg = <0x0 0xffad0000 0x0 0x20>; + }; + + qos_gpu: qos@ffae0000 { + compatible = "syscon"; + reg = <0x0 0xffae0000 0x0 0x20>; + }; + + pmu: power-management@ff310000 { + compatible = "rockchip,rk3399-pmu", "syscon", "simple-mfd"; + reg = <0x0 0xff310000 0x0 0x1000>; + + /* + * Note: RK3399 supports 6 voltage domains including VD_CORE_L, + * VD_CORE_B, VD_CENTER, VD_GPU, VD_LOGIC and VD_PMU. + * Some of the power domains are grouped together for every + * voltage domain. + * The detail contents as below. + */ + power: power-controller { + compatible = "rockchip,rk3399-power-controller"; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + + /* These power domains are grouped by VD_CENTER */ + pd_iep@RK3399_PD_IEP { + reg = <RK3399_PD_IEP>; + clocks = <&cru ACLK_IEP>, + <&cru HCLK_IEP>; + pm_qos = <&qos_iep>; + }; + pd_rga@RK3399_PD_RGA { + reg = <RK3399_PD_RGA>; + clocks = <&cru ACLK_RGA>, + <&cru HCLK_RGA>; + pm_qos = <&qos_rga_r>, + <&qos_rga_w>; + }; + pd_vcodec@RK3399_PD_VCODEC { + reg = <RK3399_PD_VCODEC>; + clocks = <&cru ACLK_VCODEC>, + <&cru HCLK_VCODEC>; + pm_qos = <&qos_video_m0>; + }; + pd_vdu@RK3399_PD_VDU { + reg = <RK3399_PD_VDU>; + clocks = <&cru ACLK_VDU>, + <&cru HCLK_VDU>; + pm_qos = <&qos_video_m1_r>, + <&qos_video_m1_w>; + }; + + /* These power domains are grouped by VD_GPU */ + pd_gpu@RK3399_PD_GPU { + reg = <RK3399_PD_GPU>; + clocks = <&cru ACLK_GPU>; + pm_qos = <&qos_gpu>; + }; + + /* These power domains are grouped by VD_LOGIC */ + pd_emmc@RK3399_PD_EMMC { + reg = <RK3399_PD_EMMC>; + clocks = <&cru ACLK_EMMC>; + pm_qos = <&qos_emmc>; + }; + pd_gmac@RK3399_PD_GMAC { + reg = <RK3399_PD_GMAC>; + clocks = <&cru ACLK_GMAC>, + <&cru PCLK_GMAC>; + pm_qos = <&qos_gmac>; + }; + pd_sd@RK3399_PD_SD { + reg = <RK3399_PD_SD>; + clocks = <&cru HCLK_SDMMC>, + <&cru SCLK_SDMMC>; + pm_qos = <&qos_sd>; + }; + pd_vio@RK3399_PD_VIO { + reg = <RK3399_PD_VIO>; + #address-cells = <1>; + #size-cells = <0>; + + pd_hdcp@RK3399_PD_HDCP { + reg = <RK3399_PD_HDCP>; + clocks = <&cru ACLK_HDCP>, + <&cru HCLK_HDCP>, + <&cru PCLK_HDCP>; + pm_qos = <&qos_hdcp>; + }; + pd_isp0@RK3399_PD_ISP0 { + reg = <RK3399_PD_ISP0>; + clocks = <&cru ACLK_ISP0>, + <&cru HCLK_ISP0>; + pm_qos = <&qos_isp0_m0>, + <&qos_isp0_m1>; + }; + pd_isp1@RK3399_PD_ISP1 { + reg = <RK3399_PD_ISP1>; + clocks = <&cru ACLK_ISP1>, + <&cru HCLK_ISP1>; + pm_qos = <&qos_isp1_m0>, + <&qos_isp1_m1>; + }; + pd_tcpc0@RK3399_PD_TCPC0 { + reg = <RK3399_PD_TCPD0>; + clocks = <&cru SCLK_UPHY0_TCPDCORE>, + <&cru SCLK_UPHY0_TCPDPHY_REF>; + }; + pd_tcpc1@RK3399_PD_TCPC1 { + reg = <RK3399_PD_TCPD1>; + clocks = <&cru SCLK_UPHY1_TCPDCORE>, + <&cru SCLK_UPHY1_TCPDPHY_REF>; + }; + pd_vo@RK3399_PD_VO { + reg = <RK3399_PD_VO>; + #address-cells = <1>; + #size-cells = <0>; + + pd_vopb@RK3399_PD_VOPB { + reg = <RK3399_PD_VOPB>; + clocks = <&cru ACLK_VOP0>, + <&cru HCLK_VOP0>; + pm_qos = <&qos_vop_big_r>, + <&qos_vop_big_w>; + }; + pd_vopl@RK3399_PD_VOPL { + reg = <RK3399_PD_VOPL>; + clocks = <&cru ACLK_VOP1>, + <&cru HCLK_VOP1>; + pm_qos = <&qos_vop_little>; + }; + }; + }; + }; + }; + pmugrf: syscon@ff320000 { compatible = "rockchip,rk3399-pmugrf", "syscon", "simple-mfd"; reg = <0x0 0xff320000 0x0 0x1000>; @@ -611,7 +932,7 @@ reg = <0x0 0xff350000 0x0 0x1000>; clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>; clock-names = "spiclk", "apb_pclk"; - interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>; #address-cells = <1>; @@ -624,7 +945,7 @@ reg = <0x0 0xff370000 0x0 0x100>; clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>; clock-names = "baudclk", "apb_pclk"; - interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -639,7 +960,7 @@ assigned-clock-rates = <200000000>; clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c0_xfer>; #address-cells = <1>; @@ -654,7 +975,7 @@ assigned-clock-rates = <200000000>; clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c4_xfer>; #address-cells = <1>; @@ -669,7 +990,7 @@ assigned-clock-rates = <200000000>; clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>; clock-names = "i2c", "pclk"; - interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH 0>; pinctrl-names = "default"; pinctrl-0 = <&i2c8_xfer>; #address-cells = <1>; @@ -721,6 +1042,38 @@ status = "disabled"; }; + efuse0: efuse@ff690000 { + compatible = "rockchip,rk3399-efuse"; + reg = <0x0 0xff690000 0x0 0x80>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&cru PCLK_EFUSE1024NS>; + clock-names = "pclk_efuse"; + + /* Data cells */ + cpu_id: cpu-id@7 { + reg = <0x07 0x10>; + }; + cpub_leakage: cpu-leakage@17 { + reg = <0x17 0x1>; + }; + gpu_leakage: gpu-leakage@18 { + reg = <0x18 0x1>; + }; + center_leakage: center-leakage@19 { + reg = <0x19 0x1>; + }; + cpul_leakage: cpu-leakage@1a { + reg = <0x1a 0x1>; + }; + logic_leakage: logic-leakage@1b { + reg = <0x1b 0x1>; + }; + wafer_info: wafer-info@1c { + reg = <0x1c 0x1>; + }; + }; + pmucru: pmu-clock-controller@ff750000 { compatible = "rockchip,rk3399-pmucru"; reg = <0x0 0xff750000 0x0 0x1000>; @@ -741,7 +1094,7 @@ <&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>, <&cru PCLK_PERIHP>, <&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>, - <&cru PCLK_PERILP0>, + <&cru PCLK_PERILP0>, <&cru ACLK_CCI>, <&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>; assigned-clock-rates = <594000000>, <800000000>, @@ -749,7 +1102,7 @@ <150000000>, <75000000>, <37500000>, <100000000>, <100000000>, - <50000000>, + <50000000>, <600000000>, <100000000>, <50000000>; }; @@ -764,6 +1117,60 @@ status = "disabled"; }; + u2phy0: usb2-phy@e450 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe450 0x10>; + clocks = <&cru SCLK_USB2PHY0_REF>; + clock-names = "phyclk"; + #clock-cells = <0>; + clock-output-names = "clk_usbphy0_480m"; + status = "disabled"; + + u2phy0_host: host-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "linestate"; + status = "disabled"; + }; + + u2phy0_otg: otg-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "otg-bvalid", "otg-id", + "linestate"; + status = "disabled"; + }; + }; + + u2phy1: usb2-phy@e460 { + compatible = "rockchip,rk3399-usb2phy"; + reg = <0xe460 0x10>; + clocks = <&cru SCLK_USB2PHY1_REF>; + clock-names = "phyclk"; + #clock-cells = <0>; + clock-output-names = "clk_usbphy1_480m"; + status = "disabled"; + + u2phy1_host: host-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "linestate"; + status = "disabled"; + }; + + u2phy1_otg: otg-port { + #phy-cells = <0>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>; + interrupt-names = "otg-bvalid", "otg-id", + "linestate"; + status = "disabled"; + }; + }; + emmc_phy: phy@f780 { compatible = "rockchip,rk3399-emmc-phy"; reg = <0xf780 0x24>; @@ -772,19 +1179,87 @@ #phy-cells = <0>; status = "disabled"; }; + + pcie_phy: pcie-phy { + compatible = "rockchip,rk3399-pcie-phy"; + clocks = <&cru SCLK_PCIEPHY_REF>; + clock-names = "refclk"; + #phy-cells = <0>; + resets = <&cru SRST_PCIEPHY>; + reset-names = "phy"; + status = "disabled"; + }; }; - watchdog@ff840000 { + tcphy0: phy@ff7c0000 { + compatible = "rockchip,rk3399-typec-phy"; + reg = <0x0 0xff7c0000 0x0 0x40000>; + clocks = <&cru SCLK_UPHY0_TCPDCORE>, + <&cru SCLK_UPHY0_TCPDPHY_REF>; + clock-names = "tcpdcore", "tcpdphy-ref"; + assigned-clocks = <&cru SCLK_UPHY0_TCPDCORE>; + assigned-clock-rates = <50000000>; + power-domains = <&power RK3399_PD_TCPD0>; + resets = <&cru SRST_UPHY0>, + <&cru SRST_UPHY0_PIPE_L00>, + <&cru SRST_P_UPHY0_TCPHY>; + reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; + rockchip,grf = <&grf>; + rockchip,typec-conn-dir = <0xe580 0 16>; + rockchip,usb3tousb2-en = <0xe580 3 19>; + rockchip,external-psm = <0xe588 14 30>; + rockchip,pipe-status = <0xe5c0 0 0>; + status = "disabled"; + + tcphy0_dp: dp-port { + #phy-cells = <0>; + }; + + tcphy0_usb3: usb3-port { + #phy-cells = <0>; + }; + }; + + tcphy1: phy@ff800000 { + compatible = "rockchip,rk3399-typec-phy"; + reg = <0x0 0xff800000 0x0 0x40000>; + clocks = <&cru SCLK_UPHY1_TCPDCORE>, + <&cru SCLK_UPHY1_TCPDPHY_REF>; + clock-names = "tcpdcore", "tcpdphy-ref"; + assigned-clocks = <&cru SCLK_UPHY1_TCPDCORE>; + assigned-clock-rates = <50000000>; + power-domains = <&power RK3399_PD_TCPD1>; + resets = <&cru SRST_UPHY1>, + <&cru SRST_UPHY1_PIPE_L00>, + <&cru SRST_P_UPHY1_TCPHY>; + reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; + rockchip,grf = <&grf>; + rockchip,typec-conn-dir = <0xe58c 0 16>; + rockchip,usb3tousb2-en = <0xe58c 3 19>; + rockchip,external-psm = <0xe594 14 30>; + rockchip,pipe-status = <0xe5c0 16 16>; + status = "disabled"; + + tcphy1_dp: dp-port { + #phy-cells = <0>; + }; + + tcphy1_usb3: usb3-port { + #phy-cells = <0>; + }; + }; + + watchdog@ff848000 { compatible = "snps,dw-wdt"; - reg = <0x0 0xff840000 0x0 0x100>; + reg = <0x0 0xff848000 0x0 0x100>; clocks = <&cru PCLK_WDT>; - interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>; }; rktimer: rktimer@ff850000 { compatible = "rockchip,rk3399-timer"; reg = <0x0 0xff850000 0x0 0x1000>; - interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>; clock-names = "pclk", "timer"; }; @@ -792,7 +1267,7 @@ spdif: spdif@ff870000 { compatible = "rockchip,rk3399-spdif"; reg = <0x0 0xff870000 0x0 0x1000>; - interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dmac_bus 7>; dma-names = "tx"; clock-names = "mclk", "hclk"; @@ -806,7 +1281,7 @@ compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; reg = <0x0 0xff880000 0x0 0x1000>; rockchip,grf = <&grf>; - interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dmac_bus 0>, <&dmac_bus 1>; dma-names = "tx", "rx"; clock-names = "i2s_clk", "i2s_hclk"; @@ -819,7 +1294,7 @@ i2s1: i2s@ff890000 { compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; reg = <0x0 0xff890000 0x0 0x1000>; - interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dmac_bus 2>, <&dmac_bus 3>; dma-names = "tx", "rx"; clock-names = "i2s_clk", "i2s_hclk"; @@ -832,7 +1307,7 @@ i2s2: i2s@ff8a0000 { compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s"; reg = <0x0 0xff8a0000 0x0 0x1000>; - interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dmac_bus 4>, <&dmac_bus 5>; dma-names = "tx", "rx"; clock-names = "i2s_clk", "i2s_hclk"; @@ -852,7 +1327,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff720000 0x0 0x100>; clocks = <&pmucru PCLK_GPIO0_PMU>; - interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>; gpio-controller; #gpio-cells = <0x2>; @@ -865,7 +1340,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff730000 0x0 0x100>; clocks = <&pmucru PCLK_GPIO1_PMU>; - interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH 0>; gpio-controller; #gpio-cells = <0x2>; @@ -878,7 +1353,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff780000 0x0 0x100>; clocks = <&cru PCLK_GPIO2>; - interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH 0>; gpio-controller; #gpio-cells = <0x2>; @@ -891,7 +1366,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff788000 0x0 0x100>; clocks = <&cru PCLK_GPIO3>; - interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>; gpio-controller; #gpio-cells = <0x2>; @@ -904,7 +1379,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x0 0xff790000 0x0 0x100>; clocks = <&cru PCLK_GPIO4>; - interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; gpio-controller; #gpio-cells = <0x2>; @@ -955,6 +1430,72 @@ drive-strength = <13>; }; + clock { + clk_32k: clk-32k { + rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>; + }; + }; + + gmac { + rgmii_pins: rgmii-pins { + rockchip,pins = + /* mac_txclk */ + <3 17 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_rxclk */ + <3 14 RK_FUNC_1 &pcfg_pull_none>, + /* mac_mdio */ + <3 13 RK_FUNC_1 &pcfg_pull_none>, + /* mac_txen */ + <3 12 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_clk */ + <3 11 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxdv */ + <3 9 RK_FUNC_1 &pcfg_pull_none>, + /* mac_mdc */ + <3 8 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxd1 */ + <3 7 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxd0 */ + <3 6 RK_FUNC_1 &pcfg_pull_none>, + /* mac_txd1 */ + <3 5 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_txd0 */ + <3 4 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_rxd3 */ + <3 3 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxd2 */ + <3 2 RK_FUNC_1 &pcfg_pull_none>, + /* mac_txd3 */ + <3 1 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_txd2 */ + <3 0 RK_FUNC_1 &pcfg_pull_none_13ma>; + }; + + rmii_pins: rmii-pins { + rockchip,pins = + /* mac_mdio */ + <3 13 RK_FUNC_1 &pcfg_pull_none>, + /* mac_txen */ + <3 12 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_clk */ + <3 11 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxer */ + <3 10 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxdv */ + <3 9 RK_FUNC_1 &pcfg_pull_none>, + /* mac_mdc */ + <3 8 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxd1 */ + <3 7 RK_FUNC_1 &pcfg_pull_none>, + /* mac_rxd0 */ + <3 6 RK_FUNC_1 &pcfg_pull_none>, + /* mac_txd1 */ + <3 5 RK_FUNC_1 &pcfg_pull_none_13ma>, + /* mac_txd0 */ + <3 4 RK_FUNC_1 &pcfg_pull_none_13ma>; + }; + }; + i2c0 { i2c0_xfer: i2c0-xfer { rockchip,pins = @@ -1326,5 +1867,18 @@ <1 14 RK_FUNC_1 &pcfg_pull_none>; }; }; + + pcie { + pcie_clkreqn: pci-clkreqn { + rockchip,pins = + <2 26 RK_FUNC_2 &pcfg_pull_none>; + }; + + pcie_clkreqnb: pci-clkreqnb { + rockchip,pins = + <4 24 RK_FUNC_1 &pcfg_pull_none>; + }; + }; + }; }; diff --git a/arch/arm64/boot/dts/socionext/Makefile b/arch/arm64/boot/dts/socionext/Makefile index 299b67ec4d44..5538598b302c 100644 --- a/arch/arm64/boot/dts/socionext/Makefile +++ b/arch/arm64/boot/dts/socionext/Makefile @@ -1,4 +1,6 @@ -dtb-$(CONFIG_ARCH_UNIPHIER) += uniphier-ph1-ld20-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER) += \ + uniphier-ld11-ref.dtb \ + uniphier-ld20-ref.dtb always := $(dtb-y) clean-files := *.dtb diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11-ref.dts b/arch/arm64/boot/dts/socionext/uniphier-ld11-ref.dts new file mode 100644 index 000000000000..7168cf818ad8 --- /dev/null +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11-ref.dts @@ -0,0 +1,100 @@ +/* + * Device Tree Source for UniPhier LD11 Reference Board + * + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.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/ "uniphier-ld11.dtsi" +/include/ "uniphier-ref-daughter.dtsi" +/include/ "uniphier-support-card.dtsi" + +/ { + model = "UniPhier LD11 Reference Board"; + compatible = "socionext,uniphier-ld11-ref", "socionext,uniphier-ld11"; + + memory { + device_type = "memory"; + reg = <0 0x80000000 0 0x40000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + serial2 = &serial2; + serial3 = &serial3; + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; + }; +}; + +ðsc { + interrupts = <0 48 4>; +}; + +&serial0 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&usb2 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi new file mode 100644 index 000000000000..7c7511b9d231 --- /dev/null +++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi @@ -0,0 +1,379 @@ +/* + * Device Tree Source for UniPhier LD11 SoC + * + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.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. + */ + +/memreserve/ 0x80000000 0x00080000; + +/ { + compatible = "socionext,uniphier-ld11"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x000>; + clocks = <&sys_clk 33>; + enable-method = "psci"; + operating-points-v2 = <&cluster0_opp>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x001>; + clocks = <&sys_clk 33>; + enable-method = "psci"; + operating-points-v2 = <&cluster0_opp>; + }; + }; + + cluster0_opp: opp_table { + compatible = "operating-points-v2"; + opp-shared; + + opp@245000000 { + opp-hz = /bits/ 64 <245000000>; + clock-latency-ns = <300>; + }; + opp@250000000 { + opp-hz = /bits/ 64 <250000000>; + clock-latency-ns = <300>; + }; + opp@490000000 { + opp-hz = /bits/ 64 <490000000>; + clock-latency-ns = <300>; + }; + opp@500000000 { + opp-hz = /bits/ 64 <500000000>; + clock-latency-ns = <300>; + }; + opp@653334000 { + opp-hz = /bits/ 64 <653334000>; + clock-latency-ns = <300>; + }; + opp@666667000 { + opp-hz = /bits/ 64 <666667000>; + clock-latency-ns = <300>; + }; + opp@980000000 { + opp-hz = /bits/ 64 <980000000>; + clock-latency-ns = <300>; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + clocks { + refclk: ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 4>, + <1 14 4>, + <1 11 4>, + <1 10 4>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + + serial0: serial@54006800 { + compatible = "socionext,uniphier-uart"; + status = "disabled"; + reg = <0x54006800 0x40>; + interrupts = <0 33 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + clocks = <&peri_clk 0>; + }; + + serial1: serial@54006900 { + compatible = "socionext,uniphier-uart"; + status = "disabled"; + reg = <0x54006900 0x40>; + interrupts = <0 35 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + clocks = <&peri_clk 1>; + }; + + serial2: serial@54006a00 { + compatible = "socionext,uniphier-uart"; + status = "disabled"; + reg = <0x54006a00 0x40>; + interrupts = <0 37 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + clocks = <&peri_clk 2>; + }; + + serial3: serial@54006b00 { + compatible = "socionext,uniphier-uart"; + status = "disabled"; + reg = <0x54006b00 0x40>; + interrupts = <0 177 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + clocks = <&peri_clk 3>; + }; + + i2c0: i2c@58780000 { + compatible = "socionext,uniphier-fi2c"; + status = "disabled"; + reg = <0x58780000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 41 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0>; + clocks = <&peri_clk 4>; + clock-frequency = <100000>; + }; + + i2c1: i2c@58781000 { + compatible = "socionext,uniphier-fi2c"; + status = "disabled"; + reg = <0x58781000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 42 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + clocks = <&peri_clk 5>; + clock-frequency = <100000>; + }; + + i2c2: i2c@58782000 { + compatible = "socionext,uniphier-fi2c"; + reg = <0x58782000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 43 4>; + clocks = <&peri_clk 6>; + clock-frequency = <400000>; + }; + + i2c3: i2c@58783000 { + compatible = "socionext,uniphier-fi2c"; + status = "disabled"; + reg = <0x58783000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 44 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + clocks = <&peri_clk 7>; + clock-frequency = <100000>; + }; + + i2c4: i2c@58784000 { + compatible = "socionext,uniphier-fi2c"; + status = "disabled"; + reg = <0x58784000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 45 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c4>; + clocks = <&peri_clk 8>; + clock-frequency = <100000>; + }; + + i2c5: i2c@58785000 { + compatible = "socionext,uniphier-fi2c"; + reg = <0x58785000 0x80>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0 25 4>; + clocks = <&peri_clk 9>; + clock-frequency = <400000>; + }; + + system_bus: system-bus@58c00000 { + compatible = "socionext,uniphier-system-bus"; + status = "disabled"; + reg = <0x58c00000 0x400>; + #address-cells = <2>; + #size-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_system_bus>; + }; + + smpctrl@59800000 { + compatible = "socionext,uniphier-smpctrl"; + reg = <0x59801000 0x400>; + }; + + perictrl@59820000 { + compatible = "socionext,uniphier-ld11-perictrl", + "simple-mfd", "syscon"; + reg = <0x59820000 0x200>; + + peri_clk: clock { + compatible = "socionext,uniphier-ld11-peri-clock"; + #clock-cells = <1>; + }; + + peri_rst: reset { + compatible = "socionext,uniphier-ld11-peri-reset"; + #reset-cells = <1>; + }; + }; + + usb0: usb@5a800100 { + compatible = "socionext,uniphier-ehci", "generic-ehci"; + status = "disabled"; + reg = <0x5a800100 0x100>; + interrupts = <0 243 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>; + clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>; + resets = <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>, <&sys_rst 8>; + }; + + usb1: usb@5a810100 { + compatible = "socionext,uniphier-ehci", "generic-ehci"; + status = "disabled"; + reg = <0x5a810100 0x100>; + interrupts = <0 244 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>; + clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>; + resets = <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>, <&sys_rst 8>; + }; + + usb2: usb@5a820100 { + compatible = "socionext,uniphier-ehci", "generic-ehci"; + status = "disabled"; + reg = <0x5a820100 0x100>; + interrupts = <0 245 4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb2>; + clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>; + resets = <&mio_rst 7>, <&mio_rst 10>, <&mio_rst 14>, <&sys_rst 8>; + }; + + mioctrl@5b3e0000 { + compatible = "socionext,uniphier-ld11-mioctrl", + "simple-mfd", "syscon"; + reg = <0x5b3e0000 0x800>; + + mio_clk: clock { + compatible = "socionext,uniphier-ld11-mio-clock"; + #clock-cells = <1>; + }; + + mio_rst: reset { + compatible = "socionext,uniphier-ld11-mio-reset"; + #reset-cells = <1>; + resets = <&sys_rst 7>; + }; + }; + + soc-glue@5f800000 { + compatible = "socionext,uniphier-ld11-soc-glue", + "simple-mfd", "syscon"; + reg = <0x5f800000 0x2000>; + + pinctrl: pinctrl { + compatible = "socionext,uniphier-ld11-pinctrl"; + }; + }; + + gic: interrupt-controller@5fe00000 { + compatible = "arm,gic-v3"; + reg = <0x5fe00000 0x10000>, /* GICD */ + <0x5fe40000 0x80000>; /* GICR */ + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <1 9 4>; + }; + + sysctrl@61840000 { + compatible = "socionext,uniphier-ld11-sysctrl", + "simple-mfd", "syscon"; + reg = <0x61840000 0x10000>; + + sys_clk: clock { + compatible = "socionext,uniphier-ld11-clock"; + #clock-cells = <1>; + }; + + sys_rst: reset { + compatible = "socionext,uniphier-ld11-reset"; + #reset-cells = <1>; + }; + }; + }; +}; + +/include/ "uniphier-pinctrl.dtsi" diff --git a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts b/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts index 2adad8c8cd27..609162a1a322 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts @@ -1,7 +1,8 @@ /* - * Device Tree Source for UniPhier PH1-LD20 Reference Board + * Device Tree Source for UniPhier LD20 Reference Board * - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.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 @@ -43,13 +44,13 @@ */ /dts-v1/; -/include/ "uniphier-ph1-ld20.dtsi" +/include/ "uniphier-ld20.dtsi" /include/ "uniphier-ref-daughter.dtsi" /include/ "uniphier-support-card.dtsi" / { - model = "UniPhier PH1-LD20 Reference Board"; - compatible = "socionext,ph1-ld20-ref", "socionext,ph1-ld20"; + model = "UniPhier LD20 Reference Board"; + compatible = "socionext,uniphier-ld20-ref", "socionext,uniphier-ld20"; memory { device_type = "memory"; diff --git a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi index d73bdc8c9115..fcaecc6bdeac 100644 --- a/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi +++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi @@ -1,7 +1,8 @@ /* - * Device Tree Source for UniPhier PH1-LD20 SoC + * Device Tree Source for UniPhier LD20 SoC * - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.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 @@ -42,10 +43,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/memreserve/ 0x80000000 0x00000008; /* cpu-release-addr */ +/memreserve/ 0x80000000 0x00080000; / { - compatible = "socionext,ph1-ld20"; + compatible = "socionext,uniphier-ld20"; #address-cells = <2>; #size-cells = <2>; interrupt-parent = <&gic>; @@ -78,52 +79,125 @@ device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0 0x000>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x80000000>; + clocks = <&sys_clk 32>; + enable-method = "psci"; + operating-points-v2 = <&cluster0_opp>; }; cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a72", "arm,armv8"; reg = <0 0x001>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x80000000>; + clocks = <&sys_clk 32>; + enable-method = "psci"; + operating-points-v2 = <&cluster0_opp>; }; cpu2: cpu@100 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0 0x100>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x80000000>; + clocks = <&sys_clk 33>; + enable-method = "psci"; + operating-points-v2 = <&cluster1_opp>; }; cpu3: cpu@101 { device_type = "cpu"; compatible = "arm,cortex-a53", "arm,armv8"; reg = <0 0x101>; - enable-method = "spin-table"; - cpu-release-addr = <0 0x80000000>; + clocks = <&sys_clk 33>; + enable-method = "psci"; + operating-points-v2 = <&cluster1_opp>; }; }; - clocks { - refclk: ref { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <25000000>; + cluster0_opp: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp@250000000 { + opp-hz = /bits/ 64 <250000000>; + clock-latency-ns = <300>; + }; + opp@275000000 { + opp-hz = /bits/ 64 <275000000>; + clock-latency-ns = <300>; + }; + opp@500000000 { + opp-hz = /bits/ 64 <500000000>; + clock-latency-ns = <300>; + }; + opp@550000000 { + opp-hz = /bits/ 64 <550000000>; + clock-latency-ns = <300>; + }; + opp@666667000 { + opp-hz = /bits/ 64 <666667000>; + clock-latency-ns = <300>; + }; + opp@733334000 { + opp-hz = /bits/ 64 <733334000>; + clock-latency-ns = <300>; + }; + opp@1000000000 { + opp-hz = /bits/ 64 <1000000000>; + clock-latency-ns = <300>; + }; + opp@1100000000 { + opp-hz = /bits/ 64 <1100000000>; + clock-latency-ns = <300>; }; + }; - uart_clk: uart_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <58820000>; + cluster1_opp: opp_table1 { + compatible = "operating-points-v2"; + opp-shared; + + opp@250000000 { + opp-hz = /bits/ 64 <250000000>; + clock-latency-ns = <300>; + }; + opp@275000000 { + opp-hz = /bits/ 64 <275000000>; + clock-latency-ns = <300>; + }; + opp@500000000 { + opp-hz = /bits/ 64 <500000000>; + clock-latency-ns = <300>; + }; + opp@550000000 { + opp-hz = /bits/ 64 <550000000>; + clock-latency-ns = <300>; }; + opp@666667000 { + opp-hz = /bits/ 64 <666667000>; + clock-latency-ns = <300>; + }; + opp@733334000 { + opp-hz = /bits/ 64 <733334000>; + clock-latency-ns = <300>; + }; + opp@1000000000 { + opp-hz = /bits/ 64 <1000000000>; + clock-latency-ns = <300>; + }; + opp@1100000000 { + opp-hz = /bits/ 64 <1100000000>; + clock-latency-ns = <300>; + }; + }; - i2c_clk: i2c_clk { - #clock-cells = <0>; + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + clocks { + refclk: ref { compatible = "fixed-clock"; - clock-frequency = <50000000>; + #clock-cells = <0>; + clock-frequency = <25000000>; }; }; @@ -148,7 +222,7 @@ interrupts = <0 33 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart0>; - clocks = <&uart_clk>; + clocks = <&peri_clk 0>; }; serial1: serial@54006900 { @@ -158,7 +232,7 @@ interrupts = <0 35 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; - clocks = <&uart_clk>; + clocks = <&peri_clk 1>; }; serial2: serial@54006a00 { @@ -168,7 +242,7 @@ interrupts = <0 37 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; - clocks = <&uart_clk>; + clocks = <&peri_clk 2>; }; serial3: serial@54006b00 { @@ -178,7 +252,7 @@ interrupts = <0 177 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3>; - clocks = <&uart_clk>; + clocks = <&peri_clk 3>; }; i2c0: i2c@58780000 { @@ -190,7 +264,7 @@ interrupts = <0 41 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c0>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 4>; clock-frequency = <100000>; }; @@ -203,7 +277,7 @@ interrupts = <0 42 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 5>; clock-frequency = <100000>; }; @@ -213,7 +287,7 @@ #address-cells = <1>; #size-cells = <0>; interrupts = <0 43 4>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 6>; clock-frequency = <400000>; }; @@ -226,7 +300,7 @@ interrupts = <0 44 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c3>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 7>; clock-frequency = <100000>; }; @@ -239,7 +313,7 @@ interrupts = <0 45 4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c4>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 8>; clock-frequency = <100000>; }; @@ -249,7 +323,7 @@ #address-cells = <1>; #size-cells = <0>; interrupts = <0 25 4>; - clocks = <&i2c_clk>; + clocks = <&peri_clk 9>; clock-frequency = <400000>; }; @@ -259,6 +333,8 @@ reg = <0x58c00000 0x400>; #address-cells = <2>; #size-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_system_bus>; }; smpctrl@59800000 { @@ -266,12 +342,45 @@ reg = <0x59801000 0x400>; }; + sdctrl@59810000 { + compatible = "socionext,uniphier-ld20-sdctrl", + "simple-mfd", "syscon"; + reg = <0x59810000 0x800>; + + sd_clk: clock { + compatible = "socionext,uniphier-ld20-sd-clock"; + #clock-cells = <1>; + }; + + sd_rst: reset { + compatible = "socionext,uniphier-ld20-sd-reset"; + #reset-cells = <1>; + }; + }; + + perictrl@59820000 { + compatible = "socionext,uniphier-ld20-perictrl", + "simple-mfd", "syscon"; + reg = <0x59820000 0x200>; + + peri_clk: clock { + compatible = "socionext,uniphier-ld20-peri-clock"; + #clock-cells = <1>; + }; + + peri_rst: reset { + compatible = "socionext,uniphier-ld20-peri-reset"; + #reset-cells = <1>; + }; + }; + soc-glue@5f800000 { - compatible = "simple-mfd", "syscon"; + compatible = "socionext,uniphier-ld20-soc-glue", + "simple-mfd", "syscon"; reg = <0x5f800000 0x2000>; pinctrl: pinctrl { - compatible = "socionext,uniphier-ld20-pinctrl"; + compatible = "socionext,uniphier-ld20-pinctrl"; }; }; @@ -283,6 +392,22 @@ #interrupt-cells = <3>; interrupts = <1 9 4>; }; + + sysctrl@61840000 { + compatible = "socionext,uniphier-ld20-sysctrl", + "simple-mfd", "syscon"; + reg = <0x61840000 0x10000>; + + sys_clk: clock { + compatible = "socionext,uniphier-ld20-clock"; + #clock-cells = <1>; + }; + + sys_rst: reset { + compatible = "socionext,uniphier-ld20-reset"; + #reset-cells = <1>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts index acb0527fdc4a..358089687a69 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts @@ -29,7 +29,7 @@ memory { device_type = "memory"; - reg = <0x0 0x0 0x40000000>; + reg = <0x0 0x0 0x0 0x40000000>; }; }; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi index 3e2e51fbd2bc..68a908334c7b 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi +++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi @@ -14,7 +14,7 @@ / { compatible = "xlnx,zynqmp"; #address-cells = <2>; - #size-cells = <1>; + #size-cells = <2>; cpus { #address-cells = <1>; @@ -51,6 +51,7 @@ pmu { compatible = "arm,armv8-pmuv3"; + interrupt-parent = <&gic>; interrupts = <0 143 4>, <0 144 4>, <0 145 4>, @@ -75,15 +76,15 @@ compatible = "simple-bus"; #address-cells = <2>; #size-cells = <1>; - ranges; + ranges = <0 0 0 0 0xffffffff>; gic: interrupt-controller@f9010000 { compatible = "arm,gic-400", "arm,cortex-a15-gic"; #interrupt-cells = <3>; reg = <0x0 0xf9010000 0x10000>, - <0x0 0xf902f000 0x2000>, + <0x0 0xf9020000 0x20000>, <0x0 0xf9040000 0x20000>, - <0x0 0xf906f000 0x2000>; + <0x0 0xf9060000 0x20000>; interrupt-controller; interrupt-parent = <&gic>; interrupts = <1 9 0xf04>; @@ -93,14 +94,14 @@ amba: amba { compatible = "simple-bus"; #address-cells = <2>; - #size-cells = <1>; + #size-cells = <2>; ranges; can0: can@ff060000 { compatible = "xlnx,zynq-can-1.0"; status = "disabled"; clock-names = "can_clk", "pclk"; - reg = <0x0 0xff060000 0x1000>; + reg = <0x0 0xff060000 0x0 0x1000>; interrupts = <0 23 4>; interrupt-parent = <&gic>; tx-fifo-depth = <0x40>; @@ -111,7 +112,7 @@ compatible = "xlnx,zynq-can-1.0"; status = "disabled"; clock-names = "can_clk", "pclk"; - reg = <0x0 0xff070000 0x1000>; + reg = <0x0 0xff070000 0x0 0x1000>; interrupts = <0 24 4>; interrupt-parent = <&gic>; tx-fifo-depth = <0x40>; @@ -123,7 +124,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 57 4>, <0 57 4>; - reg = <0x0 0xff0b0000 0x1000>; + reg = <0x0 0xff0b0000 0x0 0x1000>; clock-names = "pclk", "hclk", "tx_clk"; #address-cells = <1>; #size-cells = <0>; @@ -134,7 +135,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 59 4>, <0 59 4>; - reg = <0x0 0xff0c0000 0x1000>; + reg = <0x0 0xff0c0000 0x0 0x1000>; clock-names = "pclk", "hclk", "tx_clk"; #address-cells = <1>; #size-cells = <0>; @@ -145,7 +146,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 61 4>, <0 61 4>; - reg = <0x0 0xff0d0000 0x1000>; + reg = <0x0 0xff0d0000 0x0 0x1000>; clock-names = "pclk", "hclk", "tx_clk"; #address-cells = <1>; #size-cells = <0>; @@ -156,7 +157,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 63 4>, <0 63 4>; - reg = <0x0 0xff0e0000 0x1000>; + reg = <0x0 0xff0e0000 0x0 0x1000>; clock-names = "pclk", "hclk", "tx_clk"; #address-cells = <1>; #size-cells = <0>; @@ -170,7 +171,7 @@ interrupts = <0 16 4>; interrupt-controller; #interrupt-cells = <2>; - reg = <0x0 0xff0a0000 0x1000>; + reg = <0x0 0xff0a0000 0x0 0x1000>; }; i2c0: i2c@ff020000 { @@ -178,7 +179,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 17 4>; - reg = <0x0 0xff020000 0x1000>; + reg = <0x0 0xff020000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; }; @@ -188,15 +189,54 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 18 4>; - reg = <0x0 0xff030000 0x1000>; + reg = <0x0 0xff030000 0x0 0x1000>; #address-cells = <1>; #size-cells = <0>; }; + pcie: pcie@fd0e0000 { + compatible = "xlnx,nwl-pcie-2.11"; + status = "disabled"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + msi-controller; + device_type = "pci"; + interrupt-parent = <&gic>; + interrupts = <0 118 4>, + <0 117 4>, + <0 116 4>, + <0 115 4>, /* MSI_1 [63...32] */ + <0 114 4>; /* MSI_0 [31...0] */ + interrupt-names = "misc", "dummy", "intx", + "msi1", "msi0"; + msi-parent = <&pcie>; + reg = <0x0 0xfd0e0000 0x0 0x1000>, + <0x0 0xfd480000 0x0 0x1000>, + <0x80 0x00000000 0x0 0x1000000>; + reg-names = "breg", "pcireg", "cfg"; + ranges = <0x02000000 0x00000000 0xe0000000 0x00000000 + 0xe0000000 0x00000000 0x10000000 + /* non-prefetchable memory */ + 0x43000000 0x00000006 0x00000000 0x00000006 + 0x00000000 0x00000002 0x00000000>; + /* prefetchable memory */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>, + <0x0 0x0 0x0 0x2 &pcie_intc 0x2>, + <0x0 0x0 0x0 0x3 &pcie_intc 0x3>, + <0x0 0x0 0x0 0x4 &pcie_intc 0x4>; + pcie_intc: legacy-interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + sata: ahci@fd0c0000 { compatible = "ceva,ahci-1v84"; status = "disabled"; - reg = <0x0 0xfd0c0000 0x2000>; + reg = <0x0 0xfd0c0000 0x0 0x2000>; interrupt-parent = <&gic>; interrupts = <0 133 4>; }; @@ -206,7 +246,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 48 4>; - reg = <0x0 0xff160000 0x1000>; + reg = <0x0 0xff160000 0x0 0x1000>; clock-names = "clk_xin", "clk_ahb"; }; @@ -215,13 +255,13 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 49 4>; - reg = <0x0 0xff170000 0x1000>; + reg = <0x0 0xff170000 0x0 0x1000>; clock-names = "clk_xin", "clk_ahb"; }; smmu: smmu@fd800000 { compatible = "arm,mmu-500"; - reg = <0x0 0xfd800000 0x20000>; + reg = <0x0 0xfd800000 0x0 0x20000>; #global-interrupts = <1>; interrupt-parent = <&gic>; interrupts = <0 157 4>, @@ -236,7 +276,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 19 4>; - reg = <0x0 0xff040000 0x1000>; + reg = <0x0 0xff040000 0x0 0x1000>; clock-names = "ref_clk", "pclk"; #address-cells = <1>; #size-cells = <0>; @@ -247,7 +287,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 20 4>; - reg = <0x0 0xff050000 0x1000>; + reg = <0x0 0xff050000 0x0 0x1000>; clock-names = "ref_clk", "pclk"; #address-cells = <1>; #size-cells = <0>; @@ -258,7 +298,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 36 4>, <0 37 4>, <0 38 4>; - reg = <0x0 0xff110000 0x1000>; + reg = <0x0 0xff110000 0x0 0x1000>; timer-width = <32>; }; @@ -267,7 +307,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 39 4>, <0 40 4>, <0 41 4>; - reg = <0x0 0xff120000 0x1000>; + reg = <0x0 0xff120000 0x0 0x1000>; timer-width = <32>; }; @@ -276,7 +316,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 42 4>, <0 43 4>, <0 44 4>; - reg = <0x0 0xff130000 0x1000>; + reg = <0x0 0xff130000 0x0 0x1000>; timer-width = <32>; }; @@ -285,7 +325,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 45 4>, <0 46 4>, <0 47 4>; - reg = <0x0 0xff140000 0x1000>; + reg = <0x0 0xff140000 0x0 0x1000>; timer-width = <32>; }; @@ -294,7 +334,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 21 4>; - reg = <0x0 0xff000000 0x1000>; + reg = <0x0 0xff000000 0x0 0x1000>; clock-names = "uart_clk", "pclk"; }; @@ -303,7 +343,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 22 4>; - reg = <0x0 0xff010000 0x1000>; + reg = <0x0 0xff010000 0x0 0x1000>; clock-names = "uart_clk", "pclk"; }; @@ -312,7 +352,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 65 4>; - reg = <0x0 0xfe200000 0x40000>; + reg = <0x0 0xfe200000 0x0 0x40000>; clock-names = "clk_xin", "clk_ahb"; }; @@ -321,7 +361,7 @@ status = "disabled"; interrupt-parent = <&gic>; interrupts = <0 70 4>; - reg = <0x0 0xfe300000 0x40000>; + reg = <0x0 0xfe300000 0x0 0x40000>; clock-names = "clk_xin", "clk_ahb"; }; @@ -329,8 +369,8 @@ compatible = "cdns,wdt-r1p2"; status = "disabled"; interrupt-parent = <&gic>; - interrupts = <0 52 1>; - reg = <0x0 0xfd4d0000 0x1000>; + interrupts = <0 113 1>; + reg = <0x0 0xfd4d0000 0x0 0x1000>; timeout-sec = <10>; }; }; diff --git a/arch/arm64/boot/dts/zte/Makefile b/arch/arm64/boot/dts/zte/Makefile new file mode 100644 index 000000000000..667806620f59 --- /dev/null +++ b/arch/arm64/boot/dts/zte/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_ZX) += zx296718-evb.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/zte/zx296718-evb.dts b/arch/arm64/boot/dts/zte/zx296718-evb.dts new file mode 100644 index 000000000000..e164ff6de5fc --- /dev/null +++ b/arch/arm64/boot/dts/zte/zx296718-evb.dts @@ -0,0 +1,64 @@ +/* + * Copyright 2016 ZTE Corporation. + * Copyright 2016 Linaro Ltd. + * + * 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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 "zx296718.dtsi" + +/ { + model = "ZTE zx296718 evaluation board"; + compatible = "zte,zx296718-evb", "zte,zx296718"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x40000000>; + }; + +}; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi new file mode 100644 index 000000000000..88ff70a06086 --- /dev/null +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi @@ -0,0 +1,309 @@ +/* + * Copyright 2016 ZTE Corporation. + * Copyright 2016 Linaro Ltd. + * + * 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 library 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 library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU 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/input/input.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + compatible = "zte,zx296718"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + + aliases { + serial0 = &uart0; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + }; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + }; + }; + + clk24k: clk-24k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000>; + clock-output-names = "rtcclk"; + }; + + osc32k: clk-osc32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + clock-output-names = "osc32k"; + }; + + osc12m: clk-osc12m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <12000000>; + clock-output-names = "osc12m"; + }; + + osc24m: clk-osc24m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "osc24m"; + }; + + osc25m: clk-osc25m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "osc25m"; + }; + + osc60m: clk-osc60m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <60000000>; + clock-output-names = "osc60m"; + }; + + osc99m: clk-osc99m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <99000000>; + clock-output-names = "osc99m"; + }; + + osc125m: clk-osc125m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + clock-output-names = "osc125m"; + }; + + osc198m: clk-osc198m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <198000000>; + clock-output-names = "osc198m"; + }; + + pll_audio: clk-pll-884m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <884000000>; + clock-output-names = "pll_audio"; + }; + + pll_ddr: clk-pll-932m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <932000000>; + clock-output-names = "pll_ddr"; + }; + + pll_hsic: clk-pll-960m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <960000000>; + clock-output-names = "pll_hsic"; + }; + + pll_mac: clk-pll-1000m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000000>; + clock-output-names = "pll_mac"; + }; + + pll_vga: clk-pll-1073m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1073000000>; + clock-output-names = "pll_vga"; + }; + + pll_mm0: clk-pll-1188m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1188000000>; + clock-output-names = "pll_mm0"; + }; + + pll_mm1: clk-pll-1296m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1296000000>; + clock-output-names = "pll_mm1"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; + }; + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; + }; + + gic: interrupt-controller@2a00000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x02a00000 0x10000>, + <0x02b00000 0xc0000>; + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + aon_sysctrl: aon-sysctrl@116000 { + compatible = "zte,zx296718-aon-sysctrl", "syscon"; + reg = <0x116000 0x1000>; + }; + + uart0: uart@11f000 { + compatible = "arm,pl011", "arm,primecell"; + arm,primecell-periphid = <0x001feffe>; + reg = <0x11f000 0x1000>; + interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc24m>; + clock-names = "apb_pclk"; + status = "disabled"; + }; + + dma: dma-controller@1460000 { + compatible = "zte,zx296702-dma"; + reg = <0x01460000 0x1000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&osc24m>; + clock-names = "dmaclk"; + #dma-cells = <1>; + dma-channels = <32>; + dma-requests = <32>; + }; + + lsp0crm: clock-controller@1420000 { + compatible = "zte,zx296718-lsp0crm"; + reg = <0x01420000 0x1000>; + #clock-cells = <1>; + }; + + lsp1crm: clock-controller@1430000 { + compatible = "zte,zx296718-lsp1crm"; + reg = <0x01430000 0x1000>; + #clock-cells = <1>; + }; + + topcrm: clock-controller@1461000 { + compatible = "zte,zx296718-topcrm"; + reg = <0x01461000 0x1000>; + #clock-cells = <1>; + }; + + sysctrl: sysctrl@1463000 { + compatible = "zte,zx296718-sysctrl", "syscon"; + reg = <0x1463000 0x1000>; + }; + + audiocrm: clock-controller@1480000 { + compatible = "zte,zx296718-audiocrm"; + reg = <0x01480000 0x1000>; + #clock-cells = <1>; + }; + }; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index eadf4855ad2d..33b744d54739 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -11,7 +11,6 @@ CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y @@ -34,6 +33,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_IOSCHED_DEADLINE is not set CONFIG_ARCH_SUNXI=y CONFIG_ARCH_ALPINE=y +CONFIG_ARCH_BCM2835=y CONFIG_ARCH_BCM_IPROC=y CONFIG_ARCH_BERLIN=y CONFIG_ARCH_EXYNOS=y @@ -57,10 +57,12 @@ CONFIG_ARCH_UNIPHIER=y CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_VULCAN=y CONFIG_ARCH_XGENE=y +CONFIG_ARCH_ZX=y CONFIG_ARCH_ZYNQMP=y CONFIG_PCI=y CONFIG_PCI_MSI=y CONFIG_PCI_IOV=y +CONFIG_PCI_AARDVARK=y CONFIG_PCIE_RCAR=y CONFIG_PCI_HOST_GENERIC=y CONFIG_PCI_XGENE=y @@ -80,8 +82,10 @@ CONFIG_KEXEC=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y CONFIG_CPU_IDLE=y +CONFIG_HIBERNATION=y CONFIG_ARM_CPUIDLE=y CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y CONFIG_ARM_BIG_LITTLE_CPUFREQ=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_NET=y @@ -120,6 +124,14 @@ CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q_GVRP=y CONFIG_VLAN_8021Q_MVRP=y CONFIG_BPF_JIT=y +CONFIG_BT=m +CONFIG_BT_HIDP=m +# CONFIG_BT_HS is not set +# CONFIG_BT_LE is not set +CONFIG_BT_LEDS=y +# CONFIG_BT_DEBUGFS is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y CONFIG_CFG80211=m CONFIG_MAC80211=m CONFIG_MAC80211_LEDS=y @@ -136,10 +148,12 @@ CONFIG_MTD_SPI_NOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=m CONFIG_VIRTIO_BLK=y +CONFIG_EEPROM_AT25=m CONFIG_SRAM=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y -# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_HISI_SAS=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y @@ -160,6 +174,8 @@ CONFIG_VIRTIO_NET=y CONFIG_AMD_XGBE=y CONFIG_NET_XGENE=y CONFIG_MACB=y +CONFIG_HNS_DSAF=y +CONFIG_HNS_ENET=y CONFIG_E1000E=y CONFIG_IGB=y CONFIG_IGBVF=y @@ -169,7 +185,10 @@ CONFIG_SMC91X=y CONFIG_SMSC911X=y CONFIG_STMMAC_ETH=m CONFIG_REALTEK_PHY=m +CONFIG_MESON_GXL_PHY=m CONFIG_MICREL_PHY=y +CONFIG_MDIO_BUS_MUX=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_RTL8152=m @@ -180,17 +199,22 @@ CONFIG_USB_NET_SMSC75XX=m CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_NET_PLUSB=m CONFIG_USB_NET_MCS7830=m +CONFIG_BRCMFMAC=m CONFIG_WL18XX=m CONFIG_WLCORE_SDIO=m CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y CONFIG_INPUT_MISC=y CONFIG_INPUT_PM8941_PWRKEY=y +CONFIG_INPUT_HISI_POWERKEY=y # CONFIG_SERIO_SERPORT is not set CONFIG_SERIO_AMBAKMI=y CONFIG_LEGACY_PTY_COUNT=16 CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_8250_UNIPHIER=y @@ -211,19 +235,24 @@ CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y CONFIG_SERIAL_MVEBU_UART=y CONFIG_VIRTIO_CONSOLE=y -# CONFIG_HW_RANDOM is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_BCM2835=m CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_IMX=y +CONFIG_I2C_MESON=y CONFIG_I2C_MV64XXX=y CONFIG_I2C_QUP=y +CONFIG_I2C_RK3X=y CONFIG_I2C_TEGRA=y CONFIG_I2C_UNIPHIER_F=y CONFIG_I2C_RCAR=y CONFIG_I2C_CROS_EC_TUNNEL=y CONFIG_SPI=y +CONFIG_SPI_MESON_SPIFC=m +CONFIG_SPI_BCM2835=m +CONFIG_SPI_BCM2835AUX=m CONFIG_SPI_ORION=y CONFIG_SPI_PL022=y CONFIG_SPI_QUP=y @@ -233,13 +262,15 @@ CONFIG_SPMI=y CONFIG_PINCTRL_SINGLE=y CONFIG_PINCTRL_MAX77620=y CONFIG_PINCTRL_MSM8916=y +CONFIG_PINCTRL_MSM8994=y CONFIG_PINCTRL_MSM8996=y +CONFIG_PINCTRL_QDF2XXX=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y -CONFIG_GPIO_SYSFS=y CONFIG_GPIO_DWAPB=y CONFIG_GPIO_PL061=y CONFIG_GPIO_RCAR=y CONFIG_GPIO_XGENE=y +CONFIG_GPIO_XGENE_SB=y CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y CONFIG_GPIO_MAX77620=y @@ -252,11 +283,18 @@ CONFIG_SENSORS_INA2XX=m CONFIG_SENSORS_ARM_SCPI=y CONFIG_THERMAL=y CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +CONFIG_BCM2835_THERMAL=y CONFIG_EXYNOS_THERMAL=y CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y CONFIG_RENESAS_WDT=y CONFIG_S3C2410_WATCHDOG=y +CONFIG_MESON_GXBB_WATCHDOG=m +CONFIG_MESON_WATCHDOG=m CONFIG_MFD_MAX77620=y +CONFIG_MFD_RK808=y CONFIG_MFD_SPMI_PMIC=y CONFIG_MFD_SEC_CORE=y CONFIG_MFD_HI655X_PMIC=y @@ -264,16 +302,36 @@ CONFIG_REGULATOR=y CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC_I2C=y CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_HI655X=y CONFIG_REGULATOR_MAX77620=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_QCOM_SMD_RPM=y CONFIG_REGULATOR_QCOM_SPMI=y +CONFIG_REGULATOR_RK808=y CONFIG_REGULATOR_S2MPS11=y +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +# CONFIG_DVB_NET is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_RENESAS_FCP=m +CONFIG_VIDEO_RENESAS_VSP1=m CONFIG_DRM=m CONFIG_DRM_NOUVEAU=m +CONFIG_DRM_RCAR_DU=m +CONFIG_DRM_RCAR_HDMI=y +CONFIG_DRM_RCAR_LVDS=y +CONFIG_DRM_RCAR_VSP=y CONFIG_DRM_TEGRA=m +CONFIG_DRM_VC4=m CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_I2C_ADV7511=m +CONFIG_DRM_HISI_KIRIN=m +CONFIG_DRM_MESON=m CONFIG_FB=y CONFIG_FB_ARMCLCD=y CONFIG_BACKLIGHT_GENERIC=m @@ -285,12 +343,14 @@ CONFIG_LOGO=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y +CONFIG_SND_BCM2835_SOC_I2S=m CONFIG_SND_SOC_RCAR=y CONFIG_SND_SOC_SAMSUNG=y CONFIG_SND_SOC_AK4613=y CONFIG_USB=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y CONFIG_USB_XHCI_RCAR=y CONFIG_USB_EHCI_EXYNOS=y CONFIG_USB_XHCI_TEGRA=y @@ -300,6 +360,7 @@ CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_OHCI_EXYNOS=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_RENESAS_USBHS=m CONFIG_USB_STORAGE=y CONFIG_USB_DWC2=y CONFIG_USB_DWC3=y @@ -311,18 +372,24 @@ CONFIG_USB_HSIC_USB3503=y CONFIG_USB_MSM_OTG=y CONFIG_USB_ULPI=y CONFIG_USB_GADGET=y +CONFIG_USB_RENESAS_USBHS_UDC=m CONFIG_MMC=y CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_MESON_GX=y CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ACPI=y CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_MMC_SDHCI_TEGRA=y CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SPI=y +CONFIG_MMC_SDHI=y CONFIG_MMC_DW=y CONFIG_MMC_DW_EXYNOS=y CONFIG_MMC_DW_K3=y +CONFIG_MMC_DW_ROCKCHIP=y CONFIG_MMC_SUNXI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -338,13 +405,17 @@ CONFIG_RTC_DRV_DS3232=y CONFIG_RTC_DRV_EFI=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_SUN6I=y +CONFIG_RTC_DRV_RK808=m CONFIG_RTC_DRV_TEGRA=y CONFIG_RTC_DRV_XGENE=y CONFIG_RTC_DRV_S3C=y CONFIG_DMADEVICES=y CONFIG_PL330_DMA=y +CONFIG_DMA_BCM2835=m CONFIG_TEGRA20_APB_DMA=y CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_HIDMA_MGMT=y +CONFIG_QCOM_HIDMA=y CONFIG_RCAR_DMAC=y CONFIG_VFIO=y CONFIG_VFIO_PCI=y @@ -356,26 +427,39 @@ CONFIG_XEN_GRANT_DEV_ALLOC=y CONFIG_COMMON_CLK_SCPI=y CONFIG_COMMON_CLK_CS2000_CP=y CONFIG_COMMON_CLK_S2MPS11=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_COMMON_CLK_RK808=y CONFIG_CLK_QORIQ=y CONFIG_COMMON_CLK_QCOM=y CONFIG_MSM_GCC_8916=y +CONFIG_MSM_GCC_8994=y CONFIG_MSM_MMCC_8996=y CONFIG_HWSPINLOCK_QCOM=y CONFIG_MAILBOX=y CONFIG_ARM_MHU=y +CONFIG_PLATFORM_MHU=y +CONFIG_BCM2835_MBOX=y CONFIG_HI6220_MBOX=y CONFIG_ARM_SMMU=y +CONFIG_RASPBERRYPI_POWER=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD=y CONFIG_QCOM_SMD_RPM=y +CONFIG_ROCKCHIP_PM_DOMAINS=y CONFIG_ARCH_TEGRA_132_SOC=y CONFIG_ARCH_TEGRA_210_SOC=y +CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_EXTCON_USB_GPIO=y CONFIG_PWM=y +CONFIG_PWM_BCM2835=m +CONFIG_PWM_ROCKCHIP=y CONFIG_PWM_TEGRA=m +CONFIG_PWM_MESON=m CONFIG_COMMON_RESET_HI6220=y CONFIG_PHY_RCAR_GEN3_USB2=y CONFIG_PHY_HI6220_USB=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_EMMC=y CONFIG_PHY_XGENE=y CONFIG_PHY_TEGRA_XUSB=y CONFIG_ARM_SCPI_PROTOCOL=y @@ -383,6 +467,7 @@ CONFIG_ACPI=y CONFIG_IIO=y CONFIG_EXYNOS_ADC=y CONFIG_PWM_SAMSUNG=y +CONFIG_RASPBERRYPI_FIRMWARE=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS_POSIX_ACL=y diff --git a/arch/arm64/crypto/.gitignore b/arch/arm64/crypto/.gitignore new file mode 100644 index 000000000000..879df8781ed5 --- /dev/null +++ b/arch/arm64/crypto/.gitignore @@ -0,0 +1,2 @@ +sha256-core.S +sha512-core.S diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 2cf32e9887e1..450a85df041a 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -8,6 +8,14 @@ menuconfig ARM64_CRYPTO if ARM64_CRYPTO +config CRYPTO_SHA256_ARM64 + tristate "SHA-224/SHA-256 digest algorithm for arm64" + select CRYPTO_HASH + +config CRYPTO_SHA512_ARM64 + tristate "SHA-384/SHA-512 digest algorithm for arm64" + select CRYPTO_HASH + config CRYPTO_SHA1_ARM64_CE tristate "SHA-1 digest algorithm (ARMv8 Crypto Extensions)" depends on ARM64 && KERNEL_MODE_NEON @@ -23,6 +31,16 @@ config CRYPTO_GHASH_ARM64_CE depends on ARM64 && KERNEL_MODE_NEON select CRYPTO_HASH +config CRYPTO_CRCT10DIF_ARM64_CE + tristate "CRCT10DIF digest algorithm using PMULL instructions" + depends on KERNEL_MODE_NEON && CRC_T10DIF + select CRYPTO_HASH + +config CRYPTO_CRC32_ARM64_CE + tristate "CRC32 and CRC32C digest algorithms using PMULL instructions" + depends on KERNEL_MODE_NEON && CRC32 + select CRYPTO_HASH + config CRYPTO_AES_ARM64_CE tristate "AES core cipher using ARMv8 Crypto Extensions" depends on ARM64 && KERNEL_MODE_NEON @@ -40,17 +58,18 @@ config CRYPTO_AES_ARM64_CE_BLK depends on ARM64 && KERNEL_MODE_NEON select CRYPTO_BLKCIPHER select CRYPTO_AES_ARM64_CE - select CRYPTO_ABLK_HELPER + select CRYPTO_SIMD config CRYPTO_AES_ARM64_NEON_BLK tristate "AES in ECB/CBC/CTR/XTS modes using NEON instructions" depends on ARM64 && KERNEL_MODE_NEON select CRYPTO_BLKCIPHER select CRYPTO_AES - select CRYPTO_ABLK_HELPER + select CRYPTO_SIMD config CRYPTO_CRC32_ARM64 tristate "CRC32 and CRC32C using optional ARMv8 instructions" depends on ARM64 select CRYPTO_HASH + endif diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index abb79b3cfcfe..aa8888d7b744 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -17,6 +17,12 @@ sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o 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 CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto @@ -29,6 +35,12 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o aes-neon-blk-y := aes-glue-neon.o aes-neon.o +obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o +sha256-arm64-y := sha256-glue.o sha256-core.o + +obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o +sha512-arm64-y := sha512-glue.o sha512-core.o + AFLAGS_aes-ce.o := -DINTERLEAVE=4 AFLAGS_aes-neon.o := -DINTERLEAVE=4 @@ -40,3 +52,14 @@ CFLAGS_crc32-arm64.o := -mcpu=generic+crc $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE $(call if_changed_rule,cc_o_c) + +quiet_cmd_perlasm = PERLASM $@ + cmd_perlasm = $(PERL) $(<) void $(@) + +$(src)/sha256-core.S_shipped: $(src)/sha512-armv8.pl + $(call cmd,perlasm) + +$(src)/sha512-core.S_shipped: $(src)/sha512-armv8.pl + $(call cmd,perlasm) + +.PRECIOUS: $(obj)/sha256-core.S $(obj)/sha512-core.S diff --git a/arch/arm64/crypto/aes-ce-ccm-core.S b/arch/arm64/crypto/aes-ce-ccm-core.S index a2a7fbcacc14..3363560c79b7 100644 --- a/arch/arm64/crypto/aes-ce-ccm-core.S +++ b/arch/arm64/crypto/aes-ce-ccm-core.S @@ -9,6 +9,7 @@ */ #include <linux/linkage.h> +#include <asm/assembler.h> .text .arch armv8-a+crypto @@ -19,7 +20,7 @@ */ ENTRY(ce_aes_ccm_auth_data) ldr w8, [x3] /* leftover from prev round? */ - ld1 {v0.2d}, [x0] /* load mac */ + ld1 {v0.16b}, [x0] /* load mac */ cbz w8, 1f sub w8, w8, #16 eor v1.16b, v1.16b, v1.16b @@ -31,7 +32,7 @@ ENTRY(ce_aes_ccm_auth_data) beq 8f /* out of input? */ cbnz w8, 0b eor v0.16b, v0.16b, v1.16b -1: ld1 {v3.2d}, [x4] /* load first round key */ +1: ld1 {v3.16b}, [x4] /* load first round key */ prfm pldl1strm, [x1] cmp w5, #12 /* which key size? */ add x6, x4, #16 @@ -41,17 +42,17 @@ ENTRY(ce_aes_ccm_auth_data) mov v5.16b, v3.16b b 4f 2: mov v4.16b, v3.16b - ld1 {v5.2d}, [x6], #16 /* load 2nd round key */ + ld1 {v5.16b}, [x6], #16 /* load 2nd round key */ 3: aese v0.16b, v4.16b aesmc v0.16b, v0.16b -4: ld1 {v3.2d}, [x6], #16 /* load next round key */ +4: ld1 {v3.16b}, [x6], #16 /* load next round key */ aese v0.16b, v5.16b aesmc v0.16b, v0.16b -5: ld1 {v4.2d}, [x6], #16 /* load next round key */ +5: ld1 {v4.16b}, [x6], #16 /* load next round key */ subs w7, w7, #3 aese v0.16b, v3.16b aesmc v0.16b, v0.16b - ld1 {v5.2d}, [x6], #16 /* load next round key */ + ld1 {v5.16b}, [x6], #16 /* load next round key */ bpl 3b aese v0.16b, v4.16b subs w2, w2, #16 /* last data? */ @@ -60,7 +61,7 @@ ENTRY(ce_aes_ccm_auth_data) ld1 {v1.16b}, [x1], #16 /* load next input block */ eor v0.16b, v0.16b, v1.16b /* xor with mac */ bne 1b -6: st1 {v0.2d}, [x0] /* store mac */ +6: st1 {v0.16b}, [x0] /* store mac */ beq 10f adds w2, w2, #16 beq 10f @@ -79,7 +80,7 @@ ENTRY(ce_aes_ccm_auth_data) adds w7, w7, #1 bne 9b eor v0.16b, v0.16b, v1.16b - st1 {v0.2d}, [x0] + st1 {v0.16b}, [x0] 10: str w8, [x3] ret ENDPROC(ce_aes_ccm_auth_data) @@ -89,27 +90,27 @@ ENDPROC(ce_aes_ccm_auth_data) * u32 rounds); */ ENTRY(ce_aes_ccm_final) - ld1 {v3.2d}, [x2], #16 /* load first round key */ - ld1 {v0.2d}, [x0] /* load mac */ + ld1 {v3.16b}, [x2], #16 /* load first round key */ + ld1 {v0.16b}, [x0] /* load mac */ cmp w3, #12 /* which key size? */ sub w3, w3, #2 /* modified # of rounds */ - ld1 {v1.2d}, [x1] /* load 1st ctriv */ + ld1 {v1.16b}, [x1] /* load 1st ctriv */ bmi 0f bne 3f mov v5.16b, v3.16b b 2f 0: mov v4.16b, v3.16b -1: ld1 {v5.2d}, [x2], #16 /* load next round key */ +1: ld1 {v5.16b}, [x2], #16 /* load next round key */ aese v0.16b, v4.16b aesmc v0.16b, v0.16b aese v1.16b, v4.16b aesmc v1.16b, v1.16b -2: ld1 {v3.2d}, [x2], #16 /* load next round key */ +2: ld1 {v3.16b}, [x2], #16 /* load next round key */ aese v0.16b, v5.16b aesmc v0.16b, v0.16b aese v1.16b, v5.16b aesmc v1.16b, v1.16b -3: ld1 {v4.2d}, [x2], #16 /* load next round key */ +3: ld1 {v4.16b}, [x2], #16 /* load next round key */ subs w3, w3, #3 aese v0.16b, v3.16b aesmc v0.16b, v0.16b @@ -120,47 +121,47 @@ ENTRY(ce_aes_ccm_final) aese v1.16b, v4.16b /* final round key cancels out */ eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */ - st1 {v0.2d}, [x0] /* store result */ + st1 {v0.16b}, [x0] /* store result */ ret ENDPROC(ce_aes_ccm_final) .macro aes_ccm_do_crypt,enc ldr x8, [x6, #8] /* load lower ctr */ - ld1 {v0.2d}, [x5] /* load mac */ - rev x8, x8 /* keep swabbed ctr in reg */ + ld1 {v0.16b}, [x5] /* load mac */ +CPU_LE( rev x8, x8 ) /* keep swabbed ctr in reg */ 0: /* outer loop */ - ld1 {v1.1d}, [x6] /* load upper ctr */ + ld1 {v1.8b}, [x6] /* load upper ctr */ prfm pldl1strm, [x1] add x8, x8, #1 rev x9, x8 cmp w4, #12 /* which key size? */ sub w7, w4, #2 /* get modified # of rounds */ ins v1.d[1], x9 /* no carry in lower ctr */ - ld1 {v3.2d}, [x3] /* load first round key */ + ld1 {v3.16b}, [x3] /* load first round key */ add x10, x3, #16 bmi 1f bne 4f mov v5.16b, v3.16b b 3f 1: mov v4.16b, v3.16b - ld1 {v5.2d}, [x10], #16 /* load 2nd round key */ + ld1 {v5.16b}, [x10], #16 /* load 2nd round key */ 2: /* inner loop: 3 rounds, 2x interleaved */ aese v0.16b, v4.16b aesmc v0.16b, v0.16b aese v1.16b, v4.16b aesmc v1.16b, v1.16b -3: ld1 {v3.2d}, [x10], #16 /* load next round key */ +3: ld1 {v3.16b}, [x10], #16 /* load next round key */ aese v0.16b, v5.16b aesmc v0.16b, v0.16b aese v1.16b, v5.16b aesmc v1.16b, v1.16b -4: ld1 {v4.2d}, [x10], #16 /* load next round key */ +4: ld1 {v4.16b}, [x10], #16 /* load next round key */ subs w7, w7, #3 aese v0.16b, v3.16b aesmc v0.16b, v0.16b aese v1.16b, v3.16b aesmc v1.16b, v1.16b - ld1 {v5.2d}, [x10], #16 /* load next round key */ + ld1 {v5.16b}, [x10], #16 /* load next round key */ bpl 2b aese v0.16b, v4.16b aese v1.16b, v4.16b @@ -177,14 +178,14 @@ ENDPROC(ce_aes_ccm_final) eor v0.16b, v0.16b, v2.16b /* xor mac with pt ^ rk[last] */ st1 {v1.16b}, [x0], #16 /* write output block */ bne 0b - rev x8, x8 - st1 {v0.2d}, [x5] /* store mac */ +CPU_LE( rev x8, x8 ) + st1 {v0.16b}, [x5] /* store mac */ str x8, [x6, #8] /* store lsb end of ctr (BE) */ 5: ret 6: eor v0.16b, v0.16b, v5.16b /* final round mac */ eor v1.16b, v1.16b, v5.16b /* final round enc */ - st1 {v0.2d}, [x5] /* store mac */ + st1 {v0.16b}, [x5] /* store mac */ add w2, w2, #16 /* process partial tail block */ 7: ldrb w9, [x1], #1 /* get 1 byte of input */ umov w6, v1.b[0] /* get top crypted ctr byte */ diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c index f4bf2f2a014c..cc5515dac74a 100644 --- a/arch/arm64/crypto/aes-ce-ccm-glue.c +++ b/arch/arm64/crypto/aes-ce-ccm-glue.c @@ -11,9 +11,9 @@ #include <asm/neon.h> #include <asm/unaligned.h> #include <crypto/aes.h> -#include <crypto/algapi.h> #include <crypto/scatterwalk.h> #include <crypto/internal/aead.h> +#include <crypto/internal/skcipher.h> #include <linux/module.h> #include "aes-ce-setkey.h" @@ -149,12 +149,7 @@ static int ccm_encrypt(struct aead_request *req) { struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead); - struct blkcipher_desc desc = { .info = req->iv }; - struct blkcipher_walk walk; - struct scatterlist srcbuf[2]; - struct scatterlist dstbuf[2]; - struct scatterlist *src; - struct scatterlist *dst; + struct skcipher_walk walk; u8 __aligned(8) mac[AES_BLOCK_SIZE]; u8 buf[AES_BLOCK_SIZE]; u32 len = req->cryptlen; @@ -172,27 +167,19 @@ static int ccm_encrypt(struct aead_request *req) /* preserve the original iv for the final round */ memcpy(buf, req->iv, AES_BLOCK_SIZE); - src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen); - dst = src; - if (req->src != req->dst) - dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen); - - blkcipher_walk_init(&walk, dst, src, len); - err = blkcipher_aead_walk_virt_block(&desc, &walk, aead, - AES_BLOCK_SIZE); + err = skcipher_walk_aead_encrypt(&walk, req, true); while (walk.nbytes) { u32 tail = walk.nbytes % AES_BLOCK_SIZE; - if (walk.nbytes == len) + if (walk.nbytes == walk.total) tail = 0; ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr, walk.nbytes - tail, ctx->key_enc, num_rounds(ctx), mac, walk.iv); - len -= walk.nbytes - tail; - err = blkcipher_walk_done(&desc, &walk, tail); + err = skcipher_walk_done(&walk, tail); } if (!err) ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx)); @@ -203,7 +190,7 @@ static int ccm_encrypt(struct aead_request *req) return err; /* copy authtag to end of dst */ - scatterwalk_map_and_copy(mac, dst, req->cryptlen, + scatterwalk_map_and_copy(mac, req->dst, req->assoclen + req->cryptlen, crypto_aead_authsize(aead), 1); return 0; @@ -214,12 +201,7 @@ static int ccm_decrypt(struct aead_request *req) struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead); unsigned int authsize = crypto_aead_authsize(aead); - struct blkcipher_desc desc = { .info = req->iv }; - struct blkcipher_walk walk; - struct scatterlist srcbuf[2]; - struct scatterlist dstbuf[2]; - struct scatterlist *src; - struct scatterlist *dst; + struct skcipher_walk walk; u8 __aligned(8) mac[AES_BLOCK_SIZE]; u8 buf[AES_BLOCK_SIZE]; u32 len = req->cryptlen - authsize; @@ -237,27 +219,19 @@ static int ccm_decrypt(struct aead_request *req) /* preserve the original iv for the final round */ memcpy(buf, req->iv, AES_BLOCK_SIZE); - src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen); - dst = src; - if (req->src != req->dst) - dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen); - - blkcipher_walk_init(&walk, dst, src, len); - err = blkcipher_aead_walk_virt_block(&desc, &walk, aead, - AES_BLOCK_SIZE); + err = skcipher_walk_aead_decrypt(&walk, req, true); while (walk.nbytes) { u32 tail = walk.nbytes % AES_BLOCK_SIZE; - if (walk.nbytes == len) + if (walk.nbytes == walk.total) tail = 0; ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr, walk.nbytes - tail, ctx->key_enc, num_rounds(ctx), mac, walk.iv); - len -= walk.nbytes - tail; - err = blkcipher_walk_done(&desc, &walk, tail); + err = skcipher_walk_done(&walk, tail); } if (!err) ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx)); @@ -268,7 +242,8 @@ static int ccm_decrypt(struct aead_request *req) return err; /* compare calculated auth tag with the stored one */ - scatterwalk_map_and_copy(buf, src, req->cryptlen - authsize, + scatterwalk_map_and_copy(buf, req->src, + req->assoclen + req->cryptlen - authsize, authsize, 0); if (crypto_memneq(mac, buf, authsize)) @@ -287,6 +262,7 @@ static struct aead_alg ccm_aes_alg = { .cra_module = THIS_MODULE, }, .ivsize = AES_BLOCK_SIZE, + .chunksize = AES_BLOCK_SIZE, .maxauthsize = AES_BLOCK_SIZE, .setkey = ccm_setkey, .setauthsize = ccm_setauthsize, diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c index f7bd9bf0bbb3..50d9fe11d0c8 100644 --- a/arch/arm64/crypto/aes-ce-cipher.c +++ b/arch/arm64/crypto/aes-ce-cipher.c @@ -47,24 +47,24 @@ static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) kernel_neon_begin_partial(4); __asm__(" ld1 {v0.16b}, %[in] ;" - " ld1 {v1.2d}, [%[key]], #16 ;" + " ld1 {v1.16b}, [%[key]], #16 ;" " cmp %w[rounds], #10 ;" " bmi 0f ;" " bne 3f ;" " mov v3.16b, v1.16b ;" " b 2f ;" "0: mov v2.16b, v1.16b ;" - " ld1 {v3.2d}, [%[key]], #16 ;" + " ld1 {v3.16b}, [%[key]], #16 ;" "1: aese v0.16b, v2.16b ;" " aesmc v0.16b, v0.16b ;" - "2: ld1 {v1.2d}, [%[key]], #16 ;" + "2: ld1 {v1.16b}, [%[key]], #16 ;" " aese v0.16b, v3.16b ;" " aesmc v0.16b, v0.16b ;" - "3: ld1 {v2.2d}, [%[key]], #16 ;" + "3: ld1 {v2.16b}, [%[key]], #16 ;" " subs %w[rounds], %w[rounds], #3 ;" " aese v0.16b, v1.16b ;" " aesmc v0.16b, v0.16b ;" - " ld1 {v3.2d}, [%[key]], #16 ;" + " ld1 {v3.16b}, [%[key]], #16 ;" " bpl 1b ;" " aese v0.16b, v2.16b ;" " eor v0.16b, v0.16b, v3.16b ;" @@ -92,24 +92,24 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) kernel_neon_begin_partial(4); __asm__(" ld1 {v0.16b}, %[in] ;" - " ld1 {v1.2d}, [%[key]], #16 ;" + " ld1 {v1.16b}, [%[key]], #16 ;" " cmp %w[rounds], #10 ;" " bmi 0f ;" " bne 3f ;" " mov v3.16b, v1.16b ;" " b 2f ;" "0: mov v2.16b, v1.16b ;" - " ld1 {v3.2d}, [%[key]], #16 ;" + " ld1 {v3.16b}, [%[key]], #16 ;" "1: aesd v0.16b, v2.16b ;" " aesimc v0.16b, v0.16b ;" - "2: ld1 {v1.2d}, [%[key]], #16 ;" + "2: ld1 {v1.16b}, [%[key]], #16 ;" " aesd v0.16b, v3.16b ;" " aesimc v0.16b, v0.16b ;" - "3: ld1 {v2.2d}, [%[key]], #16 ;" + "3: ld1 {v2.16b}, [%[key]], #16 ;" " subs %w[rounds], %w[rounds], #3 ;" " aesd v0.16b, v1.16b ;" " aesimc v0.16b, v0.16b ;" - " ld1 {v3.2d}, [%[key]], #16 ;" + " ld1 {v3.16b}, [%[key]], #16 ;" " bpl 1b ;" " aesd v0.16b, v2.16b ;" " eor v0.16b, v0.16b, v3.16b ;" @@ -173,7 +173,12 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, u32 *rki = ctx->key_enc + (i * kwords); u32 *rko = rki + kwords; +#ifndef CONFIG_CPU_BIG_ENDIAN rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0]; +#else + rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^ + rki[0]; +#endif rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; diff --git a/arch/arm64/crypto/aes-ce.S b/arch/arm64/crypto/aes-ce.S index 78f3cfe92c08..b46093d567e5 100644 --- a/arch/arm64/crypto/aes-ce.S +++ b/arch/arm64/crypto/aes-ce.S @@ -10,6 +10,7 @@ */ #include <linux/linkage.h> +#include <asm/assembler.h> #define AES_ENTRY(func) ENTRY(ce_ ## func) #define AES_ENDPROC(func) ENDPROC(ce_ ## func) diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c index 6b2aa0fd6cd0..4e3f8adb1793 100644 --- a/arch/arm64/crypto/aes-glue.c +++ b/arch/arm64/crypto/aes-glue.c @@ -11,8 +11,8 @@ #include <asm/neon.h> #include <asm/hwcap.h> #include <crypto/aes.h> -#include <crypto/ablk_helper.h> -#include <crypto/algapi.h> +#include <crypto/internal/simd.h> +#include <crypto/internal/skcipher.h> #include <linux/module.h> #include <linux/cpufeature.h> #include <crypto/xts.h> @@ -80,13 +80,19 @@ struct crypto_aes_xts_ctx { struct crypto_aes_ctx __aligned(8) key2; }; -static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, +static int skcipher_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key, + unsigned int key_len) +{ + return aes_setkey(crypto_skcipher_tfm(tfm), in_key, key_len); +} + +static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) { - struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm); int ret; - ret = xts_check_key(tfm, in_key, key_len); + ret = xts_verify_key(tfm, in_key, key_len); if (ret) return ret; @@ -97,111 +103,101 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, if (!ret) return 0; - tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } -static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int ecb_encrypt(struct skcipher_request *req) { - struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_enc, rounds, blocks, first); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int ecb_decrypt(struct skcipher_request *req) { - struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_dec, rounds, blocks, first); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int cbc_encrypt(struct skcipher_request *req) { - struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_enc, rounds, blocks, walk.iv, first); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int cbc_decrypt(struct skcipher_request *req) { - struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_dec, rounds, blocks, walk.iv, first); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int ctr_encrypt(struct skcipher_request *req) { - struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE); + err = skcipher_walk_virt(&walk, req, true); first = 1; kernel_neon_begin(); @@ -209,17 +205,14 @@ static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr, (u8 *)ctx->key_enc, rounds, blocks, walk.iv, first); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); first = 0; - nbytes -= blocks * AES_BLOCK_SIZE; - if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE) - break; - err = blkcipher_walk_done(desc, &walk, - walk.nbytes % AES_BLOCK_SIZE); } - if (walk.nbytes % AES_BLOCK_SIZE) { - u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; - u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; + if (walk.nbytes) { u8 __aligned(8) tail[AES_BLOCK_SIZE]; + unsigned int nbytes = walk.nbytes; + u8 *tdst = walk.dst.virt.addr; + u8 *tsrc = walk.src.virt.addr; /* * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need @@ -230,227 +223,169 @@ static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, rounds, blocks, walk.iv, first); memcpy(tdst, tail, nbytes); - err = blkcipher_walk_done(desc, &walk, 0); + err = skcipher_walk_done(&walk, 0); } kernel_neon_end(); return err; } -static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int xts_encrypt(struct skcipher_request *req) { - struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key1.key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { 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); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static int xts_decrypt(struct skcipher_request *req) { - struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm); int err, first, rounds = 6 + ctx->key1.key_length / 4; - struct blkcipher_walk walk; + struct skcipher_walk walk; unsigned int blocks; - desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = skcipher_walk_virt(&walk, req, true); kernel_neon_begin(); for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { 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); - err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); } kernel_neon_end(); return err; } -static struct crypto_alg aes_algs[] = { { - .cra_name = "__ecb-aes-" MODE, - .cra_driver_name = "__driver-ecb-aes-" MODE, - .cra_priority = 0, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = 0, - .setkey = aes_setkey, - .encrypt = ecb_encrypt, - .decrypt = ecb_decrypt, +static struct skcipher_alg aes_algs[] = { { + .base = { + .cra_name = "__ecb(aes)", + .cra_driver_name = "__ecb-aes-" MODE, + .cra_priority = PRIO, + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto_aes_ctx), + .cra_alignmask = 7, + .cra_module = THIS_MODULE, }, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = skcipher_aes_setkey, + .encrypt = ecb_encrypt, + .decrypt = ecb_decrypt, }, { - .cra_name = "__cbc-aes-" MODE, - .cra_driver_name = "__driver-cbc-aes-" MODE, - .cra_priority = 0, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = aes_setkey, - .encrypt = cbc_encrypt, - .decrypt = cbc_decrypt, + .base = { + .cra_name = "__cbc(aes)", + .cra_driver_name = "__cbc-aes-" MODE, + .cra_priority = PRIO, + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto_aes_ctx), + .cra_alignmask = 7, + .cra_module = THIS_MODULE, }, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = skcipher_aes_setkey, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, }, { - .cra_name = "__ctr-aes-" MODE, - .cra_driver_name = "__driver-ctr-aes-" MODE, - .cra_priority = 0, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct crypto_aes_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = aes_setkey, - .encrypt = ctr_encrypt, - .decrypt = ctr_encrypt, + .base = { + .cra_name = "__ctr(aes)", + .cra_driver_name = "__ctr-aes-" MODE, + .cra_priority = PRIO, + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct crypto_aes_ctx), + .cra_alignmask = 7, + .cra_module = THIS_MODULE, }, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .chunksize = AES_BLOCK_SIZE, + .setkey = skcipher_aes_setkey, + .encrypt = ctr_encrypt, + .decrypt = ctr_encrypt, }, { - .cra_name = "__xts-aes-" MODE, - .cra_driver_name = "__driver-xts-aes-" MODE, - .cra_priority = 0, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_INTERNAL, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_blkcipher = { - .min_keysize = 2 * AES_MIN_KEY_SIZE, - .max_keysize = 2 * AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = xts_set_key, - .encrypt = xts_encrypt, - .decrypt = xts_decrypt, + .base = { + .cra_name = "__xts(aes)", + .cra_driver_name = "__xts-aes-" MODE, + .cra_priority = PRIO, + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), + .cra_alignmask = 7, + .cra_module = THIS_MODULE, }, -}, { - .cra_name = "ecb(aes)", - .cra_driver_name = "ecb-aes-" MODE, - .cra_priority = PRIO, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_helper_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = ablk_init, - .cra_exit = ablk_exit, - .cra_ablkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = 0, - .setkey = ablk_set_key, - .encrypt = ablk_encrypt, - .decrypt = ablk_decrypt, - } -}, { - .cra_name = "cbc(aes)", - .cra_driver_name = "cbc-aes-" MODE, - .cra_priority = PRIO, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_helper_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = ablk_init, - .cra_exit = ablk_exit, - .cra_ablkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = ablk_set_key, - .encrypt = ablk_encrypt, - .decrypt = ablk_decrypt, - } -}, { - .cra_name = "ctr(aes)", - .cra_driver_name = "ctr-aes-" MODE, - .cra_priority = PRIO, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_helper_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = ablk_init, - .cra_exit = ablk_exit, - .cra_ablkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = ablk_set_key, - .encrypt = ablk_encrypt, - .decrypt = ablk_decrypt, - } -}, { - .cra_name = "xts(aes)", - .cra_driver_name = "xts-aes-" MODE, - .cra_priority = PRIO, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_helper_ctx), - .cra_alignmask = 7, - .cra_type = &crypto_ablkcipher_type, - .cra_module = THIS_MODULE, - .cra_init = ablk_init, - .cra_exit = ablk_exit, - .cra_ablkcipher = { - .min_keysize = 2 * AES_MIN_KEY_SIZE, - .max_keysize = 2 * AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = ablk_set_key, - .encrypt = ablk_encrypt, - .decrypt = ablk_decrypt, - } + .min_keysize = 2 * AES_MIN_KEY_SIZE, + .max_keysize = 2 * AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = xts_set_key, + .encrypt = xts_encrypt, + .decrypt = xts_decrypt, } }; -static int __init aes_init(void) +static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)]; + +static void aes_exit(void) { - return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs)); + int i; + + for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++) + simd_skcipher_free(aes_simd_algs[i]); + + crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); } -static void __exit aes_exit(void) +static int __init aes_init(void) { - crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs)); + struct simd_skcipher_alg *simd; + const char *basename; + const char *algname; + const char *drvname; + int err; + int i; + + err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { + algname = aes_algs[i].base.cra_name + 2; + drvname = aes_algs[i].base.cra_driver_name + 2; + basename = aes_algs[i].base.cra_driver_name; + simd = simd_skcipher_create_compat(algname, drvname, basename); + err = PTR_ERR(simd); + if (IS_ERR(simd)) + goto unregister_simds; + + aes_simd_algs[i] = simd; + } + + return 0; + +unregister_simds: + aes_exit(); + return err; } #ifdef USE_V8_CRYPTO_EXTENSIONS diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S index f6e372c528eb..c53dbeae79f2 100644 --- a/arch/arm64/crypto/aes-modes.S +++ b/arch/arm64/crypto/aes-modes.S @@ -386,7 +386,8 @@ AES_ENDPROC(aes_ctr_encrypt) .endm .Lxts_mul_x: - .word 1, 0, 0x87, 0 +CPU_LE( .quad 1, 0x87 ) +CPU_BE( .quad 0x87, 1 ) AES_ENTRY(aes_xts_encrypt) FRAME_PUSH diff --git a/arch/arm64/crypto/aes-neon.S b/arch/arm64/crypto/aes-neon.S index b93170e1cc93..85f07ead7c5c 100644 --- a/arch/arm64/crypto/aes-neon.S +++ b/arch/arm64/crypto/aes-neon.S @@ -9,6 +9,7 @@ */ #include <linux/linkage.h> +#include <asm/assembler.h> #define AES_ENTRY(func) ENTRY(neon_ ## func) #define AES_ENDPROC(func) ENDPROC(neon_ ## func) @@ -83,13 +84,13 @@ .endm .macro do_block, enc, in, rounds, rk, rkp, i - ld1 {v15.16b}, [\rk] + ld1 {v15.4s}, [\rk] add \rkp, \rk, #16 mov \i, \rounds 1111: eor \in\().16b, \in\().16b, v15.16b /* ^round key */ tbl \in\().16b, {\in\().16b}, v13.16b /* ShiftRows */ sub_bytes \in - ld1 {v15.16b}, [\rkp], #16 + ld1 {v15.4s}, [\rkp], #16 subs \i, \i, #1 beq 2222f .if \enc == 1 @@ -229,7 +230,7 @@ .endm .macro do_block_2x, enc, in0, in1 rounds, rk, rkp, i - ld1 {v15.16b}, [\rk] + ld1 {v15.4s}, [\rk] add \rkp, \rk, #16 mov \i, \rounds 1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ @@ -237,7 +238,7 @@ sub_bytes_2x \in0, \in1 tbl \in0\().16b, {\in0\().16b}, v13.16b /* ShiftRows */ tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */ - ld1 {v15.16b}, [\rkp], #16 + ld1 {v15.4s}, [\rkp], #16 subs \i, \i, #1 beq 2222f .if \enc == 1 @@ -254,7 +255,7 @@ .endm .macro do_block_4x, enc, in0, in1, in2, in3, rounds, rk, rkp, i - ld1 {v15.16b}, [\rk] + ld1 {v15.4s}, [\rk] add \rkp, \rk, #16 mov \i, \rounds 1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ @@ -266,7 +267,7 @@ tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */ tbl \in2\().16b, {\in2\().16b}, v13.16b /* ShiftRows */ tbl \in3\().16b, {\in3\().16b}, v13.16b /* ShiftRows */ - ld1 {v15.16b}, [\rkp], #16 + ld1 {v15.4s}, [\rkp], #16 subs \i, \i, #1 beq 2222f .if \enc == 1 @@ -306,12 +307,16 @@ .text .align 4 .LForward_ShiftRows: - .byte 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3 - .byte 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb +CPU_LE( .byte 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3 ) +CPU_LE( .byte 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb ) +CPU_BE( .byte 0xb, 0x6, 0x1, 0xc, 0x7, 0x2, 0xd, 0x8 ) +CPU_BE( .byte 0x3, 0xe, 0x9, 0x4, 0xf, 0xa, 0x5, 0x0 ) .LReverse_ShiftRows: - .byte 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb - .byte 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3 +CPU_LE( .byte 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb ) +CPU_LE( .byte 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3 ) +CPU_BE( .byte 0x3, 0x6, 0x9, 0xc, 0xf, 0x2, 0x5, 0x8 ) +CPU_BE( .byte 0xb, 0xe, 0x1, 0x4, 0x7, 0xa, 0xd, 0x0 ) .LForward_Sbox: .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 diff --git a/arch/arm64/crypto/crc32-ce-core.S b/arch/arm64/crypto/crc32-ce-core.S new file mode 100644 index 000000000000..18f5a8442276 --- /dev/null +++ b/arch/arm64/crypto/crc32-ce-core.S @@ -0,0 +1,266 @@ +/* + * 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> + + .text + .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 x0 + LEN .req x1 + CRC .req x2 + + 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) + */ +ENTRY(crc32_pmull_le) + adr x3, .Lcrc32_constants + b 0f + +ENTRY(crc32c_pmull_le) + adr x3, .Lcrc32c_constants + +0: 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, [x3] + +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.ge loop_64 + +less_64: /* Folding cache line into 128bit */ + ldr qCONSTANT, [x3, #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, [x3, #32] + ldr d3, [x3, #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, [x3, #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] + + 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 new file mode 100644 index 000000000000..8594127d5e01 --- /dev/null +++ b/arch/arm64/crypto/crc32-ce-glue.c @@ -0,0 +1,212 @@ +/* + * Accelerated CRC32(C) using arm64 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. + */ + +#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/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_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) { + l = round_down(length, SCALE_F); + + kernel_neon_begin_partial(10); + *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) { + l = round_down(length, SCALE_F); + + kernel_neon_begin_partial(10); + *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_pmull_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_blocksize = 1, + .base.cra_module = THIS_MODULE, +}, { + .setkey = crc32_pmull_setkey, + .init = crc32_pmull_init, + .update = crc32c_pmull_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_blocksize = 1, + .base.cra_module = THIS_MODULE, +} }; + +static int __init crc32_pmull_mod_init(void) +{ + if (elf_hwcap & HWCAP_CRC32) { + fallback_crc32 = crc32_armv8_le; + fallback_crc32c = crc32c_armv8_le; + } else { + fallback_crc32 = crc32_le; + fallback_crc32c = __crc32c_le; + } + + 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)); +} + +module_cpu_feature_match(PMULL, 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 new file mode 100644 index 000000000000..d5b5a8c038c8 --- /dev/null +++ b/arch/arm64/crypto/crct10dif-ce-core.S @@ -0,0 +1,392 @@ +// +// Accelerated CRC-T10DIF using arm64 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. +// + +// +// Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions +// +// Copyright (c) 2013, Intel Corporation +// +// Authors: +// Erdinc Ozturk <erdinc.ozturk@intel.com> +// Vinodh Gopal <vinodh.gopal@intel.com> +// James Guilford <james.guilford@intel.com> +// Tim Chen <tim.c.chen@linux.intel.com> +// +// This software is available to you under a choice of one of two +// licenses. You may choose to be licensed under the terms of the GNU +// General Public License (GPL) Version 2, available from the file +// COPYING in the main directory of this source tree, or the +// OpenIB.org BSD license below: +// +// 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 the 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 INTEL CORPORATION ""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 INTEL CORPORATION 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. +// +// Function API: +// UINT16 crc_t10dif_pcl( +// UINT16 init_crc, //initial CRC value, 16 bits +// const unsigned char *buf, //buffer pointer to calculate CRC on +// UINT64 len //buffer length in bytes (64-bit data) +// ); +// +// Reference paper titled "Fast CRC Computation for Generic +// Polynomials Using PCLMULQDQ Instruction" +// URL: http://www.intel.com/content/dam/www/public/us/en/documents +// /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf +// +// + +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + .cpu generic+crypto + + arg1_low32 .req w0 + arg2 .req x1 + arg3 .req x2 + + vzr .req v13 + +ENTRY(crc_t10dif_pmull) + movi vzr.16b, #0 // init zero register + + // adjust the 16-bit initial_crc value, scale it to 32 bits + lsl arg1_low32, arg1_low32, #16 + + // check if smaller than 256 + cmp arg3, #256 + + // for sizes less than 128, we can't fold 64B at a time... + b.lt _less_than_128 + + // load the initial crc value + // crc value does not need to be byte-reflected, but it needs + // to be moved to the high part of the register. + // because data will be byte-reflected and will align with + // initial crc at correct place. + movi v10.16b, #0 + mov v10.s[3], arg1_low32 // initial crc + + // receive the initial 64B data, xor the initial crc value + ldp q0, q1, [arg2] + ldp q2, q3, [arg2, #0x20] + ldp q4, q5, [arg2, #0x40] + ldp q6, q7, [arg2, #0x60] + add arg2, arg2, #0x80 + +CPU_LE( rev64 v0.16b, v0.16b ) +CPU_LE( rev64 v1.16b, v1.16b ) +CPU_LE( rev64 v2.16b, v2.16b ) +CPU_LE( rev64 v3.16b, v3.16b ) +CPU_LE( rev64 v4.16b, v4.16b ) +CPU_LE( rev64 v5.16b, v5.16b ) +CPU_LE( rev64 v6.16b, v6.16b ) +CPU_LE( rev64 v7.16b, v7.16b ) + +CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 ) +CPU_LE( ext v1.16b, v1.16b, v1.16b, #8 ) +CPU_LE( ext v2.16b, v2.16b, v2.16b, #8 ) +CPU_LE( ext v3.16b, v3.16b, v3.16b, #8 ) +CPU_LE( ext v4.16b, v4.16b, v4.16b, #8 ) +CPU_LE( ext v5.16b, v5.16b, v5.16b, #8 ) +CPU_LE( ext v6.16b, v6.16b, v6.16b, #8 ) +CPU_LE( ext v7.16b, v7.16b, v7.16b, #8 ) + + // XOR the initial_crc value + eor v0.16b, v0.16b, v10.16b + + ldr q10, rk3 // xmm10 has rk3 and rk4 + // type of pmull instruction + // will determine which constant to use + + // + // we subtract 256 instead of 128 to save one instruction from the loop + // + sub arg3, arg3, #256 + + // at this section of the code, there is 64*x+y (0<=y<64) bytes of + // 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: + + .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 + + subs arg3, arg3, #128 + + // check if there is another 64B in the buffer to be able to fold + b.ge _fold_64_B_loop + + // 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 + + // fold the 8 vector registers to 1 vector register with different + // constants + + ldr q10, rk9 + + .macro fold16, reg, rk + pmull v8.1q, \reg\().1d, v10.1d + pmull2 \reg\().1q, \reg\().2d, v10.2d + .ifnb \rk + ldr q10, \rk + .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 + + // 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 + + // 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 + eor v7.16b, v7.16b, v8.16b + + ldr q0, [arg2], #16 +CPU_LE( rev64 v0.16b, v0.16b ) +CPU_LE( ext v0.16b, v0.16b, v0.16b, #8 ) + eor v7.16b, v7.16b, v0.16b + subs arg3, arg3, #16 + + // 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 + + // 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: + // 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 + + // 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: + add arg2, arg2, arg3 + ldr q1, [arg2, #-16] +CPU_LE( rev64 v1.16b, v1.16b ) +CPU_LE( ext v1.16b, v1.16b, v1.16b, #8 ) + + // get rid of the extra data that was loaded before + // load the shift constant + adr x4, tbl_shf_table + 16 + sub x4, x4, arg3 + ld1 {v0.16b}, [x4] + + // shift v2 to the left by arg3 bytes + tbl v2.16b, {v7.16b}, v0.16b + + // shift v7 to the right by 16-arg3 bytes + movi v9.16b, #0x80 + eor v0.16b, v0.16b, v9.16b + tbl v7.16b, {v7.16b}, v0.16b + + // blend + sshr v0.16b, v0.16b, #7 // convert to 8-bit mask + bsl v0.16b, v2.16b, v1.16b + + // fold 16 Bytes + pmull v8.1q, v7.1d, v10.1d + pmull2 v7.1q, v7.2d, v10.2d + eor v7.16b, v7.16b, v8.16b + eor v7.16b, v7.16b, v0.16b + +_128_done: + // compute crc of a 128-bit value + ldr q10, rk5 // rk5 and rk6 in xmm10 + + // 64b fold + ext v0.16b, vzr.16b, v7.16b, #8 + mov v7.d[0], v7.d[1] + pmull v7.1q, v7.1d, v10.1d + 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 + eor v7.16b, v7.16b, v0.16b + + // barrett reduction +_barrett: + ldr q10, rk7 + mov v0.d[0], v7.d[1] + + pmull v0.1q, v0.1d, v10.1d + ext v0.16b, vzr.16b, v0.16b, #12 + pmull2 v0.1q, v0.2d, v10.2d + ext v0.16b, vzr.16b, v0.16b, #12 + eor v7.16b, v7.16b, v0.16b + mov w0, v7.s[1] + +_cleanup: + // scale the result back to 16 bits + lsr x0, x0, #16 + ret + +_less_than_128: + cbz arg3, _cleanup + + movi v0.16b, #0 + mov v0.s[3], arg1_low32 // get the initial crc value + + ldr q7, [arg2], #0x10 +CPU_LE( rev64 v7.16b, v7.16b ) +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 + + ldr q10, rk1 // rk1 and rk2 in xmm10 + + // update the counter. subtract 32 instead of 16 to save one + // instruction from the loop + subs arg3, arg3, #32 + b.ge _16B_reduction_loop + + add arg3, arg3, #16 + b _get_last_two_regs + +_less_than_16_left: + // shl r9, 4 + adr x0, tbl_shf_table + 16 + sub x0, x0, arg3 + ld1 {v0.16b}, [x0] + 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) + +// precomputed constants +// these constants are precomputed from the poly: +// 0x8bb70000 (0x8bb7 scaled to 32 bits) + .align 4 +// Q = 0x18BB70000 +// rk1 = 2^(32*3) mod Q << 32 +// rk2 = 2^(32*5) mod Q << 32 +// rk3 = 2^(32*15) mod Q << 32 +// rk4 = 2^(32*17) mod Q << 32 +// rk5 = 2^(32*3) mod Q << 32 +// rk6 = 2^(32*2) mod Q << 32 +// rk7 = floor(2^64/Q) +// rk8 = Q + +rk1: .octa 0x06df0000000000002d56000000000000 +rk3: .octa 0x7cf50000000000009d9d000000000000 +rk5: .octa 0x13680000000000002d56000000000000 +rk7: .octa 0x000000018bb7000000000001f65a57f8 +rk9: .octa 0xbfd6000000000000ceae000000000000 +rk11: .octa 0x713c0000000000001e16000000000000 +rk13: .octa 0x80a6000000000000f7f9000000000000 +rk15: .octa 0xe658000000000000044c000000000000 +rk17: .octa 0xa497000000000000ad18000000000000 +rk19: .octa 0xe7b50000000000006ee3000000000000 + +tbl_shf_table: +// use these values for shift constants for the tbl/tbx instruction +// different alignments result in values as shown: +// DDQ 0x008f8e8d8c8b8a898887868584838281 # shl 15 (16-1) / shr1 +// DDQ 0x01008f8e8d8c8b8a8988878685848382 # shl 14 (16-3) / shr2 +// DDQ 0x0201008f8e8d8c8b8a89888786858483 # shl 13 (16-4) / shr3 +// DDQ 0x030201008f8e8d8c8b8a898887868584 # shl 12 (16-4) / shr4 +// DDQ 0x04030201008f8e8d8c8b8a8988878685 # shl 11 (16-5) / shr5 +// DDQ 0x0504030201008f8e8d8c8b8a89888786 # shl 10 (16-6) / shr6 +// DDQ 0x060504030201008f8e8d8c8b8a898887 # shl 9 (16-7) / shr7 +// DDQ 0x07060504030201008f8e8d8c8b8a8988 # shl 8 (16-8) / shr8 +// DDQ 0x0807060504030201008f8e8d8c8b8a89 # shl 7 (16-9) / shr9 +// DDQ 0x090807060504030201008f8e8d8c8b8a # shl 6 (16-10) / shr10 +// DDQ 0x0a090807060504030201008f8e8d8c8b # shl 5 (16-11) / shr11 +// DDQ 0x0b0a090807060504030201008f8e8d8c # shl 4 (16-12) / shr12 +// DDQ 0x0c0b0a090807060504030201008f8e8d # shl 3 (16-13) / shr13 +// DDQ 0x0d0c0b0a090807060504030201008f8e # shl 2 (16-14) / shr14 +// DDQ 0x0e0d0c0b0a090807060504030201008f # shl 1 (16-15) / shr15 + + .byte 0x0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 + .byte 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f + .byte 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 + .byte 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe , 0x0 diff --git a/arch/arm64/crypto/crct10dif-ce-glue.c b/arch/arm64/crypto/crct10dif-ce-glue.c new file mode 100644 index 000000000000..60cb590c2590 --- /dev/null +++ b/arch/arm64/crypto/crct10dif-ce-glue.c @@ -0,0 +1,95 @@ +/* + * Accelerated CRC-T10DIF using arm64 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. + */ + +#include <linux/cpufeature.h> +#include <linux/crc-t10dif.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> + +#include <crypto/internal/hash.h> + +#include <asm/neon.h> + +#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U + +asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 buf[], u64 len); + +static int crct10dif_init(struct shash_desc *desc) +{ + u16 *crc = shash_desc_ctx(desc); + + *crc = 0; + return 0; +} + +static int crct10dif_update(struct shash_desc *desc, const u8 *data, + unsigned int length) +{ + u16 *crc = shash_desc_ctx(desc); + unsigned int l; + + if (unlikely((u64)data % CRC_T10DIF_PMULL_CHUNK_SIZE)) { + l = min_t(u32, length, CRC_T10DIF_PMULL_CHUNK_SIZE - + ((u64)data % CRC_T10DIF_PMULL_CHUNK_SIZE)); + + *crc = crc_t10dif_generic(*crc, data, l); + + length -= l; + data += l; + } + + if (length > 0) { + kernel_neon_begin_partial(14); + *crc = crc_t10dif_pmull(*crc, data, length); + kernel_neon_end(); + } + + return 0; +} + +static int crct10dif_final(struct shash_desc *desc, u8 *out) +{ + u16 *crc = shash_desc_ctx(desc); + + *(u16 *)out = *crc; + return 0; +} + +static struct shash_alg crc_t10dif_alg = { + .digestsize = CRC_T10DIF_DIGEST_SIZE, + .init = crct10dif_init, + .update = crct10dif_update, + .final = crct10dif_final, + .descsize = CRC_T10DIF_DIGEST_SIZE, + + .base.cra_name = "crct10dif", + .base.cra_driver_name = "crct10dif-arm64-ce", + .base.cra_priority = 200, + .base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +}; + +static int __init crc_t10dif_mod_init(void) +{ + return crypto_register_shash(&crc_t10dif_alg); +} + +static void __exit crc_t10dif_mod_exit(void) +{ + crypto_unregister_shash(&crc_t10dif_alg); +} + +module_cpu_feature_match(PMULL, crc_t10dif_mod_init); +module_exit(crc_t10dif_mod_exit); + +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm64/crypto/ghash-ce-core.S b/arch/arm64/crypto/ghash-ce-core.S index dc457015884e..f0bb9f0b524f 100644 --- a/arch/arm64/crypto/ghash-ce-core.S +++ b/arch/arm64/crypto/ghash-ce-core.S @@ -29,8 +29,8 @@ * struct ghash_key const *k, const char *head) */ ENTRY(pmull_ghash_update) - ld1 {SHASH.16b}, [x3] - ld1 {XL.16b}, [x1] + ld1 {SHASH.2d}, [x3] + ld1 {XL.2d}, [x1] movi MASK.16b, #0xe1 ext SHASH2.16b, SHASH.16b, SHASH.16b, #8 shl MASK.2d, MASK.2d, #57 @@ -74,6 +74,6 @@ CPU_LE( rev64 T1.16b, T1.16b ) cbnz w0, 0b - st1 {XL.16b}, [x1] + st1 {XL.2d}, [x1] ret ENDPROC(pmull_ghash_update) diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S index 033aae6d732a..c98e7e849f06 100644 --- a/arch/arm64/crypto/sha1-ce-core.S +++ b/arch/arm64/crypto/sha1-ce-core.S @@ -78,7 +78,7 @@ ENTRY(sha1_ce_transform) ld1r {k3.4s}, [x6] /* load state */ - ldr dga, [x0] + ld1 {dgav.4s}, [x0] ldr dgb, [x0, #16] /* load sha1_ce_state::finalize */ @@ -144,7 +144,7 @@ CPU_LE( rev32 v11.16b, v11.16b ) b 1b /* store new state */ -3: str dga, [x0] +3: st1 {dgav.4s}, [x0] str dgb, [x0, #16] ret ENDPROC(sha1_ce_transform) diff --git a/arch/arm64/crypto/sha2-ce-core.S b/arch/arm64/crypto/sha2-ce-core.S index 5df9d9d470ad..01cfee066837 100644 --- a/arch/arm64/crypto/sha2-ce-core.S +++ b/arch/arm64/crypto/sha2-ce-core.S @@ -85,7 +85,7 @@ ENTRY(sha2_ce_transform) ld1 {v12.4s-v15.4s}, [x8] /* load state */ - ldp dga, dgb, [x0] + ld1 {dgav.4s, dgbv.4s}, [x0] /* load sha256_ce_state::finalize */ ldr w4, [x0, #:lo12:sha256_ce_offsetof_finalize] @@ -148,6 +148,6 @@ CPU_LE( rev32 v19.16b, v19.16b ) b 1b /* store new state */ -3: stp dga, dgb, [x0] +3: st1 {dgav.4s, dgbv.4s}, [x0] ret ENDPROC(sha2_ce_transform) diff --git a/arch/arm64/crypto/sha256-core.S_shipped b/arch/arm64/crypto/sha256-core.S_shipped new file mode 100644 index 000000000000..3ce82cc860bc --- /dev/null +++ b/arch/arm64/crypto/sha256-core.S_shipped @@ -0,0 +1,2061 @@ +// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html + +// ==================================================================== +// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL +// project. The module is, however, dual licensed under OpenSSL and +// CRYPTOGAMS licenses depending on where you obtain it. For further +// details see http://www.openssl.org/~appro/cryptogams/. +// +// Permission to use under GPLv2 terms is granted. +// ==================================================================== +// +// SHA256/512 for ARMv8. +// +// Performance in cycles per processed byte and improvement coefficient +// over code generated with "default" compiler: +// +// SHA256-hw SHA256(*) SHA512 +// Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) +// Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) +// Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +// Denver 2.01 10.5 (+26%) 6.70 (+8%) +// X-Gene 20.0 (+100%) 12.8 (+300%(***)) +// Mongoose 2.36 13.0 (+50%) 8.36 (+33%) +// +// (*) Software SHA256 results are of lesser relevance, presented +// mostly for informational purposes. +// (**) The result is a trade-off: it's possible to improve it by +// 10% (or by 1 cycle per round), but at the cost of 20% loss +// on Cortex-A53 (or by 4 cycles per round). +// (***) Super-impressive coefficients over gcc-generated code are +// indication of some compiler "pathology", most notably code +// generated with -mgeneral-regs-only is significanty faster +// and the gap is only 40-90%. +// +// October 2016. +// +// Originally it was reckoned that it makes no sense to implement NEON +// version of SHA256 for 64-bit processors. This is because performance +// improvement on most wide-spread Cortex-A5x processors was observed +// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was +// observed that 32-bit NEON SHA256 performs significantly better than +// 64-bit scalar version on *some* of the more recent processors. As +// result 64-bit NEON version of SHA256 was added to provide best +// all-round performance. For example it executes ~30% faster on X-Gene +// and Mongoose. [For reference, NEON version of SHA512 is bound to +// deliver much less improvement, likely *negative* on Cortex-A5x. +// Which is why NEON support is limited to SHA256.] + +#ifndef __KERNEL__ +# include "arm_arch.h" +#endif + +.text + +.extern OPENSSL_armcap_P +.globl sha256_block_data_order +.type sha256_block_data_order,%function +.align 6 +sha256_block_data_order: +#ifndef __KERNEL__ +# ifdef __ILP32__ + ldrsw x16,.LOPENSSL_armcap_P +# else + ldr x16,.LOPENSSL_armcap_P +# endif + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] + tst w16,#ARMV8_SHA256 + b.ne .Lv8_entry + tst w16,#ARMV7_NEON + b.ne .Lneon_entry +#endif + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#4*4 + + ldp w20,w21,[x0] // load context + ldp w22,w23,[x0,#2*4] + ldp w24,w25,[x0,#4*4] + add x2,x1,x2,lsl#6 // end of input + ldp w26,w27,[x0,#6*4] + adr x30,.LK256 + stp x0,x2,[x29,#96] + +.Loop: + ldp w3,w4,[x1],#2*4 + ldr w19,[x30],#4 // *K++ + eor w28,w21,w22 // magic seed + str x1,[x29,#112] +#ifndef __AARCH64EB__ + rev w3,w3 // 0 +#endif + ror w16,w24,#6 + add w27,w27,w19 // h+=K[i] + eor w6,w24,w24,ror#14 + and w17,w25,w24 + bic w19,w26,w24 + add w27,w27,w3 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w20,w21 // a^b, b^c in next round + eor w16,w16,w6,ror#11 // Sigma1(e) + ror w6,w20,#2 + add w27,w27,w17 // h+=Ch(e,f,g) + eor w17,w20,w20,ror#9 + add w27,w27,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w23,w23,w27 // d+=h + eor w28,w28,w21 // Maj(a,b,c) + eor w17,w6,w17,ror#13 // Sigma0(a) + add w27,w27,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w27,w27,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w4,w4 // 1 +#endif + ldp w5,w6,[x1],#2*4 + add w27,w27,w17 // h+=Sigma0(a) + ror w16,w23,#6 + add w26,w26,w28 // h+=K[i] + eor w7,w23,w23,ror#14 + and w17,w24,w23 + bic w28,w25,w23 + add w26,w26,w4 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w27,w20 // a^b, b^c in next round + eor w16,w16,w7,ror#11 // Sigma1(e) + ror w7,w27,#2 + add w26,w26,w17 // h+=Ch(e,f,g) + eor w17,w27,w27,ror#9 + add w26,w26,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w22,w22,w26 // d+=h + eor w19,w19,w20 // Maj(a,b,c) + eor w17,w7,w17,ror#13 // Sigma0(a) + add w26,w26,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w26,w26,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w5,w5 // 2 +#endif + add w26,w26,w17 // h+=Sigma0(a) + ror w16,w22,#6 + add w25,w25,w19 // h+=K[i] + eor w8,w22,w22,ror#14 + and w17,w23,w22 + bic w19,w24,w22 + add w25,w25,w5 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w26,w27 // a^b, b^c in next round + eor w16,w16,w8,ror#11 // Sigma1(e) + ror w8,w26,#2 + add w25,w25,w17 // h+=Ch(e,f,g) + eor w17,w26,w26,ror#9 + add w25,w25,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w21,w21,w25 // d+=h + eor w28,w28,w27 // Maj(a,b,c) + eor w17,w8,w17,ror#13 // Sigma0(a) + add w25,w25,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w25,w25,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w6,w6 // 3 +#endif + ldp w7,w8,[x1],#2*4 + add w25,w25,w17 // h+=Sigma0(a) + ror w16,w21,#6 + add w24,w24,w28 // h+=K[i] + eor w9,w21,w21,ror#14 + and w17,w22,w21 + bic w28,w23,w21 + add w24,w24,w6 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w25,w26 // a^b, b^c in next round + eor w16,w16,w9,ror#11 // Sigma1(e) + ror w9,w25,#2 + add w24,w24,w17 // h+=Ch(e,f,g) + eor w17,w25,w25,ror#9 + add w24,w24,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w20,w20,w24 // d+=h + eor w19,w19,w26 // Maj(a,b,c) + eor w17,w9,w17,ror#13 // Sigma0(a) + add w24,w24,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w24,w24,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w7,w7 // 4 +#endif + add w24,w24,w17 // h+=Sigma0(a) + ror w16,w20,#6 + add w23,w23,w19 // h+=K[i] + eor w10,w20,w20,ror#14 + and w17,w21,w20 + bic w19,w22,w20 + add w23,w23,w7 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w24,w25 // a^b, b^c in next round + eor w16,w16,w10,ror#11 // Sigma1(e) + ror w10,w24,#2 + add w23,w23,w17 // h+=Ch(e,f,g) + eor w17,w24,w24,ror#9 + add w23,w23,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w27,w27,w23 // d+=h + eor w28,w28,w25 // Maj(a,b,c) + eor w17,w10,w17,ror#13 // Sigma0(a) + add w23,w23,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w23,w23,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w8,w8 // 5 +#endif + ldp w9,w10,[x1],#2*4 + add w23,w23,w17 // h+=Sigma0(a) + ror w16,w27,#6 + add w22,w22,w28 // h+=K[i] + eor w11,w27,w27,ror#14 + and w17,w20,w27 + bic w28,w21,w27 + add w22,w22,w8 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w23,w24 // a^b, b^c in next round + eor w16,w16,w11,ror#11 // Sigma1(e) + ror w11,w23,#2 + add w22,w22,w17 // h+=Ch(e,f,g) + eor w17,w23,w23,ror#9 + add w22,w22,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w26,w26,w22 // d+=h + eor w19,w19,w24 // Maj(a,b,c) + eor w17,w11,w17,ror#13 // Sigma0(a) + add w22,w22,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w22,w22,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w9,w9 // 6 +#endif + add w22,w22,w17 // h+=Sigma0(a) + ror w16,w26,#6 + add w21,w21,w19 // h+=K[i] + eor w12,w26,w26,ror#14 + and w17,w27,w26 + bic w19,w20,w26 + add w21,w21,w9 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w22,w23 // a^b, b^c in next round + eor w16,w16,w12,ror#11 // Sigma1(e) + ror w12,w22,#2 + add w21,w21,w17 // h+=Ch(e,f,g) + eor w17,w22,w22,ror#9 + add w21,w21,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w25,w25,w21 // d+=h + eor w28,w28,w23 // Maj(a,b,c) + eor w17,w12,w17,ror#13 // Sigma0(a) + add w21,w21,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w21,w21,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w10,w10 // 7 +#endif + ldp w11,w12,[x1],#2*4 + add w21,w21,w17 // h+=Sigma0(a) + ror w16,w25,#6 + add w20,w20,w28 // h+=K[i] + eor w13,w25,w25,ror#14 + and w17,w26,w25 + bic w28,w27,w25 + add w20,w20,w10 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w21,w22 // a^b, b^c in next round + eor w16,w16,w13,ror#11 // Sigma1(e) + ror w13,w21,#2 + add w20,w20,w17 // h+=Ch(e,f,g) + eor w17,w21,w21,ror#9 + add w20,w20,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w24,w24,w20 // d+=h + eor w19,w19,w22 // Maj(a,b,c) + eor w17,w13,w17,ror#13 // Sigma0(a) + add w20,w20,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w20,w20,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w11,w11 // 8 +#endif + add w20,w20,w17 // h+=Sigma0(a) + ror w16,w24,#6 + add w27,w27,w19 // h+=K[i] + eor w14,w24,w24,ror#14 + and w17,w25,w24 + bic w19,w26,w24 + add w27,w27,w11 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w20,w21 // a^b, b^c in next round + eor w16,w16,w14,ror#11 // Sigma1(e) + ror w14,w20,#2 + add w27,w27,w17 // h+=Ch(e,f,g) + eor w17,w20,w20,ror#9 + add w27,w27,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w23,w23,w27 // d+=h + eor w28,w28,w21 // Maj(a,b,c) + eor w17,w14,w17,ror#13 // Sigma0(a) + add w27,w27,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w27,w27,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w12,w12 // 9 +#endif + ldp w13,w14,[x1],#2*4 + add w27,w27,w17 // h+=Sigma0(a) + ror w16,w23,#6 + add w26,w26,w28 // h+=K[i] + eor w15,w23,w23,ror#14 + and w17,w24,w23 + bic w28,w25,w23 + add w26,w26,w12 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w27,w20 // a^b, b^c in next round + eor w16,w16,w15,ror#11 // Sigma1(e) + ror w15,w27,#2 + add w26,w26,w17 // h+=Ch(e,f,g) + eor w17,w27,w27,ror#9 + add w26,w26,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w22,w22,w26 // d+=h + eor w19,w19,w20 // Maj(a,b,c) + eor w17,w15,w17,ror#13 // Sigma0(a) + add w26,w26,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w26,w26,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w13,w13 // 10 +#endif + add w26,w26,w17 // h+=Sigma0(a) + ror w16,w22,#6 + add w25,w25,w19 // h+=K[i] + eor w0,w22,w22,ror#14 + and w17,w23,w22 + bic w19,w24,w22 + add w25,w25,w13 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w26,w27 // a^b, b^c in next round + eor w16,w16,w0,ror#11 // Sigma1(e) + ror w0,w26,#2 + add w25,w25,w17 // h+=Ch(e,f,g) + eor w17,w26,w26,ror#9 + add w25,w25,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w21,w21,w25 // d+=h + eor w28,w28,w27 // Maj(a,b,c) + eor w17,w0,w17,ror#13 // Sigma0(a) + add w25,w25,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w25,w25,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w14,w14 // 11 +#endif + ldp w15,w0,[x1],#2*4 + add w25,w25,w17 // h+=Sigma0(a) + str w6,[sp,#12] + ror w16,w21,#6 + add w24,w24,w28 // h+=K[i] + eor w6,w21,w21,ror#14 + and w17,w22,w21 + bic w28,w23,w21 + add w24,w24,w14 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w25,w26 // a^b, b^c in next round + eor w16,w16,w6,ror#11 // Sigma1(e) + ror w6,w25,#2 + add w24,w24,w17 // h+=Ch(e,f,g) + eor w17,w25,w25,ror#9 + add w24,w24,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w20,w20,w24 // d+=h + eor w19,w19,w26 // Maj(a,b,c) + eor w17,w6,w17,ror#13 // Sigma0(a) + add w24,w24,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w24,w24,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w15,w15 // 12 +#endif + add w24,w24,w17 // h+=Sigma0(a) + str w7,[sp,#0] + ror w16,w20,#6 + add w23,w23,w19 // h+=K[i] + eor w7,w20,w20,ror#14 + and w17,w21,w20 + bic w19,w22,w20 + add w23,w23,w15 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w24,w25 // a^b, b^c in next round + eor w16,w16,w7,ror#11 // Sigma1(e) + ror w7,w24,#2 + add w23,w23,w17 // h+=Ch(e,f,g) + eor w17,w24,w24,ror#9 + add w23,w23,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w27,w27,w23 // d+=h + eor w28,w28,w25 // Maj(a,b,c) + eor w17,w7,w17,ror#13 // Sigma0(a) + add w23,w23,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w23,w23,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w0,w0 // 13 +#endif + ldp w1,w2,[x1] + add w23,w23,w17 // h+=Sigma0(a) + str w8,[sp,#4] + ror w16,w27,#6 + add w22,w22,w28 // h+=K[i] + eor w8,w27,w27,ror#14 + and w17,w20,w27 + bic w28,w21,w27 + add w22,w22,w0 // h+=X[i] + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w23,w24 // a^b, b^c in next round + eor w16,w16,w8,ror#11 // Sigma1(e) + ror w8,w23,#2 + add w22,w22,w17 // h+=Ch(e,f,g) + eor w17,w23,w23,ror#9 + add w22,w22,w16 // h+=Sigma1(e) + and w19,w19,w28 // (b^c)&=(a^b) + add w26,w26,w22 // d+=h + eor w19,w19,w24 // Maj(a,b,c) + eor w17,w8,w17,ror#13 // Sigma0(a) + add w22,w22,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + //add w22,w22,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w1,w1 // 14 +#endif + ldr w6,[sp,#12] + add w22,w22,w17 // h+=Sigma0(a) + str w9,[sp,#8] + ror w16,w26,#6 + add w21,w21,w19 // h+=K[i] + eor w9,w26,w26,ror#14 + and w17,w27,w26 + bic w19,w20,w26 + add w21,w21,w1 // h+=X[i] + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w22,w23 // a^b, b^c in next round + eor w16,w16,w9,ror#11 // Sigma1(e) + ror w9,w22,#2 + add w21,w21,w17 // h+=Ch(e,f,g) + eor w17,w22,w22,ror#9 + add w21,w21,w16 // h+=Sigma1(e) + and w28,w28,w19 // (b^c)&=(a^b) + add w25,w25,w21 // d+=h + eor w28,w28,w23 // Maj(a,b,c) + eor w17,w9,w17,ror#13 // Sigma0(a) + add w21,w21,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + //add w21,w21,w17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev w2,w2 // 15 +#endif + ldr w7,[sp,#0] + add w21,w21,w17 // h+=Sigma0(a) + str w10,[sp,#12] + ror w16,w25,#6 + add w20,w20,w28 // h+=K[i] + ror w9,w4,#7 + and w17,w26,w25 + ror w8,w1,#17 + bic w28,w27,w25 + ror w10,w21,#2 + add w20,w20,w2 // h+=X[i] + eor w16,w16,w25,ror#11 + eor w9,w9,w4,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w21,w22 // a^b, b^c in next round + eor w16,w16,w25,ror#25 // Sigma1(e) + eor w10,w10,w21,ror#13 + add w20,w20,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w8,w8,w1,ror#19 + eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) + add w20,w20,w16 // h+=Sigma1(e) + eor w19,w19,w22 // Maj(a,b,c) + eor w17,w10,w21,ror#22 // Sigma0(a) + eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) + add w3,w3,w12 + add w24,w24,w20 // d+=h + add w20,w20,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w3,w3,w9 + add w20,w20,w17 // h+=Sigma0(a) + add w3,w3,w8 +.Loop_16_xx: + ldr w8,[sp,#4] + str w11,[sp,#0] + ror w16,w24,#6 + add w27,w27,w19 // h+=K[i] + ror w10,w5,#7 + and w17,w25,w24 + ror w9,w2,#17 + bic w19,w26,w24 + ror w11,w20,#2 + add w27,w27,w3 // h+=X[i] + eor w16,w16,w24,ror#11 + eor w10,w10,w5,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w20,w21 // a^b, b^c in next round + eor w16,w16,w24,ror#25 // Sigma1(e) + eor w11,w11,w20,ror#13 + add w27,w27,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w9,w9,w2,ror#19 + eor w10,w10,w5,lsr#3 // sigma0(X[i+1]) + add w27,w27,w16 // h+=Sigma1(e) + eor w28,w28,w21 // Maj(a,b,c) + eor w17,w11,w20,ror#22 // Sigma0(a) + eor w9,w9,w2,lsr#10 // sigma1(X[i+14]) + add w4,w4,w13 + add w23,w23,w27 // d+=h + add w27,w27,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w4,w4,w10 + add w27,w27,w17 // h+=Sigma0(a) + add w4,w4,w9 + ldr w9,[sp,#8] + str w12,[sp,#4] + ror w16,w23,#6 + add w26,w26,w28 // h+=K[i] + ror w11,w6,#7 + and w17,w24,w23 + ror w10,w3,#17 + bic w28,w25,w23 + ror w12,w27,#2 + add w26,w26,w4 // h+=X[i] + eor w16,w16,w23,ror#11 + eor w11,w11,w6,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w27,w20 // a^b, b^c in next round + eor w16,w16,w23,ror#25 // Sigma1(e) + eor w12,w12,w27,ror#13 + add w26,w26,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w10,w10,w3,ror#19 + eor w11,w11,w6,lsr#3 // sigma0(X[i+1]) + add w26,w26,w16 // h+=Sigma1(e) + eor w19,w19,w20 // Maj(a,b,c) + eor w17,w12,w27,ror#22 // Sigma0(a) + eor w10,w10,w3,lsr#10 // sigma1(X[i+14]) + add w5,w5,w14 + add w22,w22,w26 // d+=h + add w26,w26,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w5,w5,w11 + add w26,w26,w17 // h+=Sigma0(a) + add w5,w5,w10 + ldr w10,[sp,#12] + str w13,[sp,#8] + ror w16,w22,#6 + add w25,w25,w19 // h+=K[i] + ror w12,w7,#7 + and w17,w23,w22 + ror w11,w4,#17 + bic w19,w24,w22 + ror w13,w26,#2 + add w25,w25,w5 // h+=X[i] + eor w16,w16,w22,ror#11 + eor w12,w12,w7,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w26,w27 // a^b, b^c in next round + eor w16,w16,w22,ror#25 // Sigma1(e) + eor w13,w13,w26,ror#13 + add w25,w25,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w11,w11,w4,ror#19 + eor w12,w12,w7,lsr#3 // sigma0(X[i+1]) + add w25,w25,w16 // h+=Sigma1(e) + eor w28,w28,w27 // Maj(a,b,c) + eor w17,w13,w26,ror#22 // Sigma0(a) + eor w11,w11,w4,lsr#10 // sigma1(X[i+14]) + add w6,w6,w15 + add w21,w21,w25 // d+=h + add w25,w25,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w6,w6,w12 + add w25,w25,w17 // h+=Sigma0(a) + add w6,w6,w11 + ldr w11,[sp,#0] + str w14,[sp,#12] + ror w16,w21,#6 + add w24,w24,w28 // h+=K[i] + ror w13,w8,#7 + and w17,w22,w21 + ror w12,w5,#17 + bic w28,w23,w21 + ror w14,w25,#2 + add w24,w24,w6 // h+=X[i] + eor w16,w16,w21,ror#11 + eor w13,w13,w8,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w25,w26 // a^b, b^c in next round + eor w16,w16,w21,ror#25 // Sigma1(e) + eor w14,w14,w25,ror#13 + add w24,w24,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w12,w12,w5,ror#19 + eor w13,w13,w8,lsr#3 // sigma0(X[i+1]) + add w24,w24,w16 // h+=Sigma1(e) + eor w19,w19,w26 // Maj(a,b,c) + eor w17,w14,w25,ror#22 // Sigma0(a) + eor w12,w12,w5,lsr#10 // sigma1(X[i+14]) + add w7,w7,w0 + add w20,w20,w24 // d+=h + add w24,w24,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w7,w7,w13 + add w24,w24,w17 // h+=Sigma0(a) + add w7,w7,w12 + ldr w12,[sp,#4] + str w15,[sp,#0] + ror w16,w20,#6 + add w23,w23,w19 // h+=K[i] + ror w14,w9,#7 + and w17,w21,w20 + ror w13,w6,#17 + bic w19,w22,w20 + ror w15,w24,#2 + add w23,w23,w7 // h+=X[i] + eor w16,w16,w20,ror#11 + eor w14,w14,w9,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w24,w25 // a^b, b^c in next round + eor w16,w16,w20,ror#25 // Sigma1(e) + eor w15,w15,w24,ror#13 + add w23,w23,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w13,w13,w6,ror#19 + eor w14,w14,w9,lsr#3 // sigma0(X[i+1]) + add w23,w23,w16 // h+=Sigma1(e) + eor w28,w28,w25 // Maj(a,b,c) + eor w17,w15,w24,ror#22 // Sigma0(a) + eor w13,w13,w6,lsr#10 // sigma1(X[i+14]) + add w8,w8,w1 + add w27,w27,w23 // d+=h + add w23,w23,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w8,w8,w14 + add w23,w23,w17 // h+=Sigma0(a) + add w8,w8,w13 + ldr w13,[sp,#8] + str w0,[sp,#4] + ror w16,w27,#6 + add w22,w22,w28 // h+=K[i] + ror w15,w10,#7 + and w17,w20,w27 + ror w14,w7,#17 + bic w28,w21,w27 + ror w0,w23,#2 + add w22,w22,w8 // h+=X[i] + eor w16,w16,w27,ror#11 + eor w15,w15,w10,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w23,w24 // a^b, b^c in next round + eor w16,w16,w27,ror#25 // Sigma1(e) + eor w0,w0,w23,ror#13 + add w22,w22,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w14,w14,w7,ror#19 + eor w15,w15,w10,lsr#3 // sigma0(X[i+1]) + add w22,w22,w16 // h+=Sigma1(e) + eor w19,w19,w24 // Maj(a,b,c) + eor w17,w0,w23,ror#22 // Sigma0(a) + eor w14,w14,w7,lsr#10 // sigma1(X[i+14]) + add w9,w9,w2 + add w26,w26,w22 // d+=h + add w22,w22,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w9,w9,w15 + add w22,w22,w17 // h+=Sigma0(a) + add w9,w9,w14 + ldr w14,[sp,#12] + str w1,[sp,#8] + ror w16,w26,#6 + add w21,w21,w19 // h+=K[i] + ror w0,w11,#7 + and w17,w27,w26 + ror w15,w8,#17 + bic w19,w20,w26 + ror w1,w22,#2 + add w21,w21,w9 // h+=X[i] + eor w16,w16,w26,ror#11 + eor w0,w0,w11,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w22,w23 // a^b, b^c in next round + eor w16,w16,w26,ror#25 // Sigma1(e) + eor w1,w1,w22,ror#13 + add w21,w21,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w15,w15,w8,ror#19 + eor w0,w0,w11,lsr#3 // sigma0(X[i+1]) + add w21,w21,w16 // h+=Sigma1(e) + eor w28,w28,w23 // Maj(a,b,c) + eor w17,w1,w22,ror#22 // Sigma0(a) + eor w15,w15,w8,lsr#10 // sigma1(X[i+14]) + add w10,w10,w3 + add w25,w25,w21 // d+=h + add w21,w21,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w10,w10,w0 + add w21,w21,w17 // h+=Sigma0(a) + add w10,w10,w15 + ldr w15,[sp,#0] + str w2,[sp,#12] + ror w16,w25,#6 + add w20,w20,w28 // h+=K[i] + ror w1,w12,#7 + and w17,w26,w25 + ror w0,w9,#17 + bic w28,w27,w25 + ror w2,w21,#2 + add w20,w20,w10 // h+=X[i] + eor w16,w16,w25,ror#11 + eor w1,w1,w12,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w21,w22 // a^b, b^c in next round + eor w16,w16,w25,ror#25 // Sigma1(e) + eor w2,w2,w21,ror#13 + add w20,w20,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w0,w0,w9,ror#19 + eor w1,w1,w12,lsr#3 // sigma0(X[i+1]) + add w20,w20,w16 // h+=Sigma1(e) + eor w19,w19,w22 // Maj(a,b,c) + eor w17,w2,w21,ror#22 // Sigma0(a) + eor w0,w0,w9,lsr#10 // sigma1(X[i+14]) + add w11,w11,w4 + add w24,w24,w20 // d+=h + add w20,w20,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w11,w11,w1 + add w20,w20,w17 // h+=Sigma0(a) + add w11,w11,w0 + ldr w0,[sp,#4] + str w3,[sp,#0] + ror w16,w24,#6 + add w27,w27,w19 // h+=K[i] + ror w2,w13,#7 + and w17,w25,w24 + ror w1,w10,#17 + bic w19,w26,w24 + ror w3,w20,#2 + add w27,w27,w11 // h+=X[i] + eor w16,w16,w24,ror#11 + eor w2,w2,w13,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w20,w21 // a^b, b^c in next round + eor w16,w16,w24,ror#25 // Sigma1(e) + eor w3,w3,w20,ror#13 + add w27,w27,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w1,w1,w10,ror#19 + eor w2,w2,w13,lsr#3 // sigma0(X[i+1]) + add w27,w27,w16 // h+=Sigma1(e) + eor w28,w28,w21 // Maj(a,b,c) + eor w17,w3,w20,ror#22 // Sigma0(a) + eor w1,w1,w10,lsr#10 // sigma1(X[i+14]) + add w12,w12,w5 + add w23,w23,w27 // d+=h + add w27,w27,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w12,w12,w2 + add w27,w27,w17 // h+=Sigma0(a) + add w12,w12,w1 + ldr w1,[sp,#8] + str w4,[sp,#4] + ror w16,w23,#6 + add w26,w26,w28 // h+=K[i] + ror w3,w14,#7 + and w17,w24,w23 + ror w2,w11,#17 + bic w28,w25,w23 + ror w4,w27,#2 + add w26,w26,w12 // h+=X[i] + eor w16,w16,w23,ror#11 + eor w3,w3,w14,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w27,w20 // a^b, b^c in next round + eor w16,w16,w23,ror#25 // Sigma1(e) + eor w4,w4,w27,ror#13 + add w26,w26,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w2,w2,w11,ror#19 + eor w3,w3,w14,lsr#3 // sigma0(X[i+1]) + add w26,w26,w16 // h+=Sigma1(e) + eor w19,w19,w20 // Maj(a,b,c) + eor w17,w4,w27,ror#22 // Sigma0(a) + eor w2,w2,w11,lsr#10 // sigma1(X[i+14]) + add w13,w13,w6 + add w22,w22,w26 // d+=h + add w26,w26,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w13,w13,w3 + add w26,w26,w17 // h+=Sigma0(a) + add w13,w13,w2 + ldr w2,[sp,#12] + str w5,[sp,#8] + ror w16,w22,#6 + add w25,w25,w19 // h+=K[i] + ror w4,w15,#7 + and w17,w23,w22 + ror w3,w12,#17 + bic w19,w24,w22 + ror w5,w26,#2 + add w25,w25,w13 // h+=X[i] + eor w16,w16,w22,ror#11 + eor w4,w4,w15,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w26,w27 // a^b, b^c in next round + eor w16,w16,w22,ror#25 // Sigma1(e) + eor w5,w5,w26,ror#13 + add w25,w25,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w3,w3,w12,ror#19 + eor w4,w4,w15,lsr#3 // sigma0(X[i+1]) + add w25,w25,w16 // h+=Sigma1(e) + eor w28,w28,w27 // Maj(a,b,c) + eor w17,w5,w26,ror#22 // Sigma0(a) + eor w3,w3,w12,lsr#10 // sigma1(X[i+14]) + add w14,w14,w7 + add w21,w21,w25 // d+=h + add w25,w25,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w14,w14,w4 + add w25,w25,w17 // h+=Sigma0(a) + add w14,w14,w3 + ldr w3,[sp,#0] + str w6,[sp,#12] + ror w16,w21,#6 + add w24,w24,w28 // h+=K[i] + ror w5,w0,#7 + and w17,w22,w21 + ror w4,w13,#17 + bic w28,w23,w21 + ror w6,w25,#2 + add w24,w24,w14 // h+=X[i] + eor w16,w16,w21,ror#11 + eor w5,w5,w0,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w25,w26 // a^b, b^c in next round + eor w16,w16,w21,ror#25 // Sigma1(e) + eor w6,w6,w25,ror#13 + add w24,w24,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w4,w4,w13,ror#19 + eor w5,w5,w0,lsr#3 // sigma0(X[i+1]) + add w24,w24,w16 // h+=Sigma1(e) + eor w19,w19,w26 // Maj(a,b,c) + eor w17,w6,w25,ror#22 // Sigma0(a) + eor w4,w4,w13,lsr#10 // sigma1(X[i+14]) + add w15,w15,w8 + add w20,w20,w24 // d+=h + add w24,w24,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w15,w15,w5 + add w24,w24,w17 // h+=Sigma0(a) + add w15,w15,w4 + ldr w4,[sp,#4] + str w7,[sp,#0] + ror w16,w20,#6 + add w23,w23,w19 // h+=K[i] + ror w6,w1,#7 + and w17,w21,w20 + ror w5,w14,#17 + bic w19,w22,w20 + ror w7,w24,#2 + add w23,w23,w15 // h+=X[i] + eor w16,w16,w20,ror#11 + eor w6,w6,w1,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w24,w25 // a^b, b^c in next round + eor w16,w16,w20,ror#25 // Sigma1(e) + eor w7,w7,w24,ror#13 + add w23,w23,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w5,w5,w14,ror#19 + eor w6,w6,w1,lsr#3 // sigma0(X[i+1]) + add w23,w23,w16 // h+=Sigma1(e) + eor w28,w28,w25 // Maj(a,b,c) + eor w17,w7,w24,ror#22 // Sigma0(a) + eor w5,w5,w14,lsr#10 // sigma1(X[i+14]) + add w0,w0,w9 + add w27,w27,w23 // d+=h + add w23,w23,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w0,w0,w6 + add w23,w23,w17 // h+=Sigma0(a) + add w0,w0,w5 + ldr w5,[sp,#8] + str w8,[sp,#4] + ror w16,w27,#6 + add w22,w22,w28 // h+=K[i] + ror w7,w2,#7 + and w17,w20,w27 + ror w6,w15,#17 + bic w28,w21,w27 + ror w8,w23,#2 + add w22,w22,w0 // h+=X[i] + eor w16,w16,w27,ror#11 + eor w7,w7,w2,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w23,w24 // a^b, b^c in next round + eor w16,w16,w27,ror#25 // Sigma1(e) + eor w8,w8,w23,ror#13 + add w22,w22,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w6,w6,w15,ror#19 + eor w7,w7,w2,lsr#3 // sigma0(X[i+1]) + add w22,w22,w16 // h+=Sigma1(e) + eor w19,w19,w24 // Maj(a,b,c) + eor w17,w8,w23,ror#22 // Sigma0(a) + eor w6,w6,w15,lsr#10 // sigma1(X[i+14]) + add w1,w1,w10 + add w26,w26,w22 // d+=h + add w22,w22,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w1,w1,w7 + add w22,w22,w17 // h+=Sigma0(a) + add w1,w1,w6 + ldr w6,[sp,#12] + str w9,[sp,#8] + ror w16,w26,#6 + add w21,w21,w19 // h+=K[i] + ror w8,w3,#7 + and w17,w27,w26 + ror w7,w0,#17 + bic w19,w20,w26 + ror w9,w22,#2 + add w21,w21,w1 // h+=X[i] + eor w16,w16,w26,ror#11 + eor w8,w8,w3,ror#18 + orr w17,w17,w19 // Ch(e,f,g) + eor w19,w22,w23 // a^b, b^c in next round + eor w16,w16,w26,ror#25 // Sigma1(e) + eor w9,w9,w22,ror#13 + add w21,w21,w17 // h+=Ch(e,f,g) + and w28,w28,w19 // (b^c)&=(a^b) + eor w7,w7,w0,ror#19 + eor w8,w8,w3,lsr#3 // sigma0(X[i+1]) + add w21,w21,w16 // h+=Sigma1(e) + eor w28,w28,w23 // Maj(a,b,c) + eor w17,w9,w22,ror#22 // Sigma0(a) + eor w7,w7,w0,lsr#10 // sigma1(X[i+14]) + add w2,w2,w11 + add w25,w25,w21 // d+=h + add w21,w21,w28 // h+=Maj(a,b,c) + ldr w28,[x30],#4 // *K++, w19 in next round + add w2,w2,w8 + add w21,w21,w17 // h+=Sigma0(a) + add w2,w2,w7 + ldr w7,[sp,#0] + str w10,[sp,#12] + ror w16,w25,#6 + add w20,w20,w28 // h+=K[i] + ror w9,w4,#7 + and w17,w26,w25 + ror w8,w1,#17 + bic w28,w27,w25 + ror w10,w21,#2 + add w20,w20,w2 // h+=X[i] + eor w16,w16,w25,ror#11 + eor w9,w9,w4,ror#18 + orr w17,w17,w28 // Ch(e,f,g) + eor w28,w21,w22 // a^b, b^c in next round + eor w16,w16,w25,ror#25 // Sigma1(e) + eor w10,w10,w21,ror#13 + add w20,w20,w17 // h+=Ch(e,f,g) + and w19,w19,w28 // (b^c)&=(a^b) + eor w8,w8,w1,ror#19 + eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) + add w20,w20,w16 // h+=Sigma1(e) + eor w19,w19,w22 // Maj(a,b,c) + eor w17,w10,w21,ror#22 // Sigma0(a) + eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) + add w3,w3,w12 + add w24,w24,w20 // d+=h + add w20,w20,w19 // h+=Maj(a,b,c) + ldr w19,[x30],#4 // *K++, w28 in next round + add w3,w3,w9 + add w20,w20,w17 // h+=Sigma0(a) + add w3,w3,w8 + cbnz w19,.Loop_16_xx + + ldp x0,x2,[x29,#96] + ldr x1,[x29,#112] + sub x30,x30,#260 // rewind + + ldp w3,w4,[x0] + ldp w5,w6,[x0,#2*4] + add x1,x1,#14*4 // advance input pointer + ldp w7,w8,[x0,#4*4] + add w20,w20,w3 + ldp w9,w10,[x0,#6*4] + add w21,w21,w4 + add w22,w22,w5 + add w23,w23,w6 + stp w20,w21,[x0] + add w24,w24,w7 + add w25,w25,w8 + stp w22,w23,[x0,#2*4] + add w26,w26,w9 + add w27,w27,w10 + cmp x1,x2 + stp w24,w25,[x0,#4*4] + stp w26,w27,[x0,#6*4] + b.ne .Loop + + ldp x19,x20,[x29,#16] + add sp,sp,#4*4 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + ret +.size sha256_block_data_order,.-sha256_block_data_order + +.align 6 +.type .LK256,%object +.LK256: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0 //terminator +.size .LK256,.-.LK256 +#ifndef __KERNEL__ +.align 3 +.LOPENSSL_armcap_P: +# ifdef __ILP32__ + .long OPENSSL_armcap_P-. +# else + .quad OPENSSL_armcap_P-. +# endif +#endif +.asciz "SHA256 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>" +.align 2 +#ifndef __KERNEL__ +.type sha256_block_armv8,%function +.align 6 +sha256_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1 {v0.4s,v1.4s},[x0] + adr x3,.LK256 + +.Loop_hw: + ld1 {v4.16b-v7.16b},[x1],#64 + sub x2,x2,#1 + ld1 {v16.4s},[x3],#16 + rev32 v4.16b,v4.16b + rev32 v5.16b,v5.16b + rev32 v6.16b,v6.16b + rev32 v7.16b,v7.16b + orr v18.16b,v0.16b,v0.16b // offload + orr v19.16b,v1.16b,v1.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s + .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s + .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s + .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s + .inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s + .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s + .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s + .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s + .inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s + .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s + .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v6.4s + .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v7.4s + .inst 0x5e282887 //sha256su0 v7.16b,v4.16b + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b + ld1 {v17.4s},[x3],#16 + add v16.4s,v16.4s,v4.4s + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + + ld1 {v16.4s},[x3],#16 + add v17.4s,v17.4s,v5.4s + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + + ld1 {v17.4s},[x3] + add v16.4s,v16.4s,v6.4s + sub x3,x3,#64*4-16 // rewind + orr v2.16b,v0.16b,v0.16b + .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s + .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s + + add v17.4s,v17.4s,v7.4s + orr v2.16b,v0.16b,v0.16b + .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s + .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s + + add v0.4s,v0.4s,v18.4s + add v1.4s,v1.4s,v19.4s + + cbnz x2,.Loop_hw + + st1 {v0.4s,v1.4s},[x0] + + ldr x29,[sp],#16 + ret +.size sha256_block_armv8,.-sha256_block_armv8 +#endif +#ifdef __KERNEL__ +.globl sha256_block_neon +#endif +.type sha256_block_neon,%function +.align 4 +sha256_block_neon: +.Lneon_entry: + stp x29, x30, [sp, #-16]! + mov x29, sp + sub sp,sp,#16*4 + + adr x16,.LK256 + add x2,x1,x2,lsl#6 // len to point at the end of inp + + ld1 {v0.16b},[x1], #16 + ld1 {v1.16b},[x1], #16 + ld1 {v2.16b},[x1], #16 + ld1 {v3.16b},[x1], #16 + ld1 {v4.4s},[x16], #16 + ld1 {v5.4s},[x16], #16 + ld1 {v6.4s},[x16], #16 + ld1 {v7.4s},[x16], #16 + rev32 v0.16b,v0.16b // yes, even on + rev32 v1.16b,v1.16b // big-endian + rev32 v2.16b,v2.16b + rev32 v3.16b,v3.16b + mov x17,sp + add v4.4s,v4.4s,v0.4s + add v5.4s,v5.4s,v1.4s + add v6.4s,v6.4s,v2.4s + st1 {v4.4s-v5.4s},[x17], #32 + add v7.4s,v7.4s,v3.4s + st1 {v6.4s-v7.4s},[x17] + sub x17,x17,#32 + + ldp w3,w4,[x0] + ldp w5,w6,[x0,#8] + ldp w7,w8,[x0,#16] + ldp w9,w10,[x0,#24] + ldr w12,[sp,#0] + mov w13,wzr + eor w14,w4,w5 + mov w15,wzr + b .L_00_48 + +.align 4 +.L_00_48: + ext v4.16b,v0.16b,v1.16b,#4 + add w10,w10,w12 + add w3,w3,w15 + and w12,w8,w7 + bic w15,w9,w7 + ext v7.16b,v2.16b,v3.16b,#4 + eor w11,w7,w7,ror#5 + add w3,w3,w13 + mov d19,v3.d[1] + orr w12,w12,w15 + eor w11,w11,w7,ror#19 + ushr v6.4s,v4.4s,#7 + eor w15,w3,w3,ror#11 + ushr v5.4s,v4.4s,#3 + add w10,w10,w12 + add v0.4s,v0.4s,v7.4s + ror w11,w11,#6 + sli v6.4s,v4.4s,#25 + eor w13,w3,w4 + eor w15,w15,w3,ror#20 + ushr v7.4s,v4.4s,#18 + add w10,w10,w11 + ldr w12,[sp,#4] + and w14,w14,w13 + eor v5.16b,v5.16b,v6.16b + ror w15,w15,#2 + add w6,w6,w10 + sli v7.4s,v4.4s,#14 + eor w14,w14,w4 + ushr v16.4s,v19.4s,#17 + add w9,w9,w12 + add w10,w10,w15 + and w12,w7,w6 + eor v5.16b,v5.16b,v7.16b + bic w15,w8,w6 + eor w11,w6,w6,ror#5 + sli v16.4s,v19.4s,#15 + add w10,w10,w14 + orr w12,w12,w15 + ushr v17.4s,v19.4s,#10 + eor w11,w11,w6,ror#19 + eor w15,w10,w10,ror#11 + ushr v7.4s,v19.4s,#19 + add w9,w9,w12 + ror w11,w11,#6 + add v0.4s,v0.4s,v5.4s + eor w14,w10,w3 + eor w15,w15,w10,ror#20 + sli v7.4s,v19.4s,#13 + add w9,w9,w11 + ldr w12,[sp,#8] + and w13,w13,w14 + eor v17.16b,v17.16b,v16.16b + ror w15,w15,#2 + add w5,w5,w9 + eor w13,w13,w3 + eor v17.16b,v17.16b,v7.16b + add w8,w8,w12 + add w9,w9,w15 + and w12,w6,w5 + add v0.4s,v0.4s,v17.4s + bic w15,w7,w5 + eor w11,w5,w5,ror#5 + add w9,w9,w13 + ushr v18.4s,v0.4s,#17 + orr w12,w12,w15 + ushr v19.4s,v0.4s,#10 + eor w11,w11,w5,ror#19 + eor w15,w9,w9,ror#11 + sli v18.4s,v0.4s,#15 + add w8,w8,w12 + ushr v17.4s,v0.4s,#19 + ror w11,w11,#6 + eor w13,w9,w10 + eor v19.16b,v19.16b,v18.16b + eor w15,w15,w9,ror#20 + add w8,w8,w11 + sli v17.4s,v0.4s,#13 + ldr w12,[sp,#12] + and w14,w14,w13 + ror w15,w15,#2 + ld1 {v4.4s},[x16], #16 + add w4,w4,w8 + eor v19.16b,v19.16b,v17.16b + eor w14,w14,w10 + eor v17.16b,v17.16b,v17.16b + add w7,w7,w12 + add w8,w8,w15 + and w12,w5,w4 + mov v17.d[1],v19.d[0] + bic w15,w6,w4 + eor w11,w4,w4,ror#5 + add w8,w8,w14 + add v0.4s,v0.4s,v17.4s + orr w12,w12,w15 + eor w11,w11,w4,ror#19 + eor w15,w8,w8,ror#11 + add v4.4s,v4.4s,v0.4s + add w7,w7,w12 + ror w11,w11,#6 + eor w14,w8,w9 + eor w15,w15,w8,ror#20 + add w7,w7,w11 + ldr w12,[sp,#16] + and w13,w13,w14 + ror w15,w15,#2 + add w3,w3,w7 + eor w13,w13,w9 + st1 {v4.4s},[x17], #16 + ext v4.16b,v1.16b,v2.16b,#4 + add w6,w6,w12 + add w7,w7,w15 + and w12,w4,w3 + bic w15,w5,w3 + ext v7.16b,v3.16b,v0.16b,#4 + eor w11,w3,w3,ror#5 + add w7,w7,w13 + mov d19,v0.d[1] + orr w12,w12,w15 + eor w11,w11,w3,ror#19 + ushr v6.4s,v4.4s,#7 + eor w15,w7,w7,ror#11 + ushr v5.4s,v4.4s,#3 + add w6,w6,w12 + add v1.4s,v1.4s,v7.4s + ror w11,w11,#6 + sli v6.4s,v4.4s,#25 + eor w13,w7,w8 + eor w15,w15,w7,ror#20 + ushr v7.4s,v4.4s,#18 + add w6,w6,w11 + ldr w12,[sp,#20] + and w14,w14,w13 + eor v5.16b,v5.16b,v6.16b + ror w15,w15,#2 + add w10,w10,w6 + sli v7.4s,v4.4s,#14 + eor w14,w14,w8 + ushr v16.4s,v19.4s,#17 + add w5,w5,w12 + add w6,w6,w15 + and w12,w3,w10 + eor v5.16b,v5.16b,v7.16b + bic w15,w4,w10 + eor w11,w10,w10,ror#5 + sli v16.4s,v19.4s,#15 + add w6,w6,w14 + orr w12,w12,w15 + ushr v17.4s,v19.4s,#10 + eor w11,w11,w10,ror#19 + eor w15,w6,w6,ror#11 + ushr v7.4s,v19.4s,#19 + add w5,w5,w12 + ror w11,w11,#6 + add v1.4s,v1.4s,v5.4s + eor w14,w6,w7 + eor w15,w15,w6,ror#20 + sli v7.4s,v19.4s,#13 + add w5,w5,w11 + ldr w12,[sp,#24] + and w13,w13,w14 + eor v17.16b,v17.16b,v16.16b + ror w15,w15,#2 + add w9,w9,w5 + eor w13,w13,w7 + eor v17.16b,v17.16b,v7.16b + add w4,w4,w12 + add w5,w5,w15 + and w12,w10,w9 + add v1.4s,v1.4s,v17.4s + bic w15,w3,w9 + eor w11,w9,w9,ror#5 + add w5,w5,w13 + ushr v18.4s,v1.4s,#17 + orr w12,w12,w15 + ushr v19.4s,v1.4s,#10 + eor w11,w11,w9,ror#19 + eor w15,w5,w5,ror#11 + sli v18.4s,v1.4s,#15 + add w4,w4,w12 + ushr v17.4s,v1.4s,#19 + ror w11,w11,#6 + eor w13,w5,w6 + eor v19.16b,v19.16b,v18.16b + eor w15,w15,w5,ror#20 + add w4,w4,w11 + sli v17.4s,v1.4s,#13 + ldr w12,[sp,#28] + and w14,w14,w13 + ror w15,w15,#2 + ld1 {v4.4s},[x16], #16 + add w8,w8,w4 + eor v19.16b,v19.16b,v17.16b + eor w14,w14,w6 + eor v17.16b,v17.16b,v17.16b + add w3,w3,w12 + add w4,w4,w15 + and w12,w9,w8 + mov v17.d[1],v19.d[0] + bic w15,w10,w8 + eor w11,w8,w8,ror#5 + add w4,w4,w14 + add v1.4s,v1.4s,v17.4s + orr w12,w12,w15 + eor w11,w11,w8,ror#19 + eor w15,w4,w4,ror#11 + add v4.4s,v4.4s,v1.4s + add w3,w3,w12 + ror w11,w11,#6 + eor w14,w4,w5 + eor w15,w15,w4,ror#20 + add w3,w3,w11 + ldr w12,[sp,#32] + and w13,w13,w14 + ror w15,w15,#2 + add w7,w7,w3 + eor w13,w13,w5 + st1 {v4.4s},[x17], #16 + ext v4.16b,v2.16b,v3.16b,#4 + add w10,w10,w12 + add w3,w3,w15 + and w12,w8,w7 + bic w15,w9,w7 + ext v7.16b,v0.16b,v1.16b,#4 + eor w11,w7,w7,ror#5 + add w3,w3,w13 + mov d19,v1.d[1] + orr w12,w12,w15 + eor w11,w11,w7,ror#19 + ushr v6.4s,v4.4s,#7 + eor w15,w3,w3,ror#11 + ushr v5.4s,v4.4s,#3 + add w10,w10,w12 + add v2.4s,v2.4s,v7.4s + ror w11,w11,#6 + sli v6.4s,v4.4s,#25 + eor w13,w3,w4 + eor w15,w15,w3,ror#20 + ushr v7.4s,v4.4s,#18 + add w10,w10,w11 + ldr w12,[sp,#36] + and w14,w14,w13 + eor v5.16b,v5.16b,v6.16b + ror w15,w15,#2 + add w6,w6,w10 + sli v7.4s,v4.4s,#14 + eor w14,w14,w4 + ushr v16.4s,v19.4s,#17 + add w9,w9,w12 + add w10,w10,w15 + and w12,w7,w6 + eor v5.16b,v5.16b,v7.16b + bic w15,w8,w6 + eor w11,w6,w6,ror#5 + sli v16.4s,v19.4s,#15 + add w10,w10,w14 + orr w12,w12,w15 + ushr v17.4s,v19.4s,#10 + eor w11,w11,w6,ror#19 + eor w15,w10,w10,ror#11 + ushr v7.4s,v19.4s,#19 + add w9,w9,w12 + ror w11,w11,#6 + add v2.4s,v2.4s,v5.4s + eor w14,w10,w3 + eor w15,w15,w10,ror#20 + sli v7.4s,v19.4s,#13 + add w9,w9,w11 + ldr w12,[sp,#40] + and w13,w13,w14 + eor v17.16b,v17.16b,v16.16b + ror w15,w15,#2 + add w5,w5,w9 + eor w13,w13,w3 + eor v17.16b,v17.16b,v7.16b + add w8,w8,w12 + add w9,w9,w15 + and w12,w6,w5 + add v2.4s,v2.4s,v17.4s + bic w15,w7,w5 + eor w11,w5,w5,ror#5 + add w9,w9,w13 + ushr v18.4s,v2.4s,#17 + orr w12,w12,w15 + ushr v19.4s,v2.4s,#10 + eor w11,w11,w5,ror#19 + eor w15,w9,w9,ror#11 + sli v18.4s,v2.4s,#15 + add w8,w8,w12 + ushr v17.4s,v2.4s,#19 + ror w11,w11,#6 + eor w13,w9,w10 + eor v19.16b,v19.16b,v18.16b + eor w15,w15,w9,ror#20 + add w8,w8,w11 + sli v17.4s,v2.4s,#13 + ldr w12,[sp,#44] + and w14,w14,w13 + ror w15,w15,#2 + ld1 {v4.4s},[x16], #16 + add w4,w4,w8 + eor v19.16b,v19.16b,v17.16b + eor w14,w14,w10 + eor v17.16b,v17.16b,v17.16b + add w7,w7,w12 + add w8,w8,w15 + and w12,w5,w4 + mov v17.d[1],v19.d[0] + bic w15,w6,w4 + eor w11,w4,w4,ror#5 + add w8,w8,w14 + add v2.4s,v2.4s,v17.4s + orr w12,w12,w15 + eor w11,w11,w4,ror#19 + eor w15,w8,w8,ror#11 + add v4.4s,v4.4s,v2.4s + add w7,w7,w12 + ror w11,w11,#6 + eor w14,w8,w9 + eor w15,w15,w8,ror#20 + add w7,w7,w11 + ldr w12,[sp,#48] + and w13,w13,w14 + ror w15,w15,#2 + add w3,w3,w7 + eor w13,w13,w9 + st1 {v4.4s},[x17], #16 + ext v4.16b,v3.16b,v0.16b,#4 + add w6,w6,w12 + add w7,w7,w15 + and w12,w4,w3 + bic w15,w5,w3 + ext v7.16b,v1.16b,v2.16b,#4 + eor w11,w3,w3,ror#5 + add w7,w7,w13 + mov d19,v2.d[1] + orr w12,w12,w15 + eor w11,w11,w3,ror#19 + ushr v6.4s,v4.4s,#7 + eor w15,w7,w7,ror#11 + ushr v5.4s,v4.4s,#3 + add w6,w6,w12 + add v3.4s,v3.4s,v7.4s + ror w11,w11,#6 + sli v6.4s,v4.4s,#25 + eor w13,w7,w8 + eor w15,w15,w7,ror#20 + ushr v7.4s,v4.4s,#18 + add w6,w6,w11 + ldr w12,[sp,#52] + and w14,w14,w13 + eor v5.16b,v5.16b,v6.16b + ror w15,w15,#2 + add w10,w10,w6 + sli v7.4s,v4.4s,#14 + eor w14,w14,w8 + ushr v16.4s,v19.4s,#17 + add w5,w5,w12 + add w6,w6,w15 + and w12,w3,w10 + eor v5.16b,v5.16b,v7.16b + bic w15,w4,w10 + eor w11,w10,w10,ror#5 + sli v16.4s,v19.4s,#15 + add w6,w6,w14 + orr w12,w12,w15 + ushr v17.4s,v19.4s,#10 + eor w11,w11,w10,ror#19 + eor w15,w6,w6,ror#11 + ushr v7.4s,v19.4s,#19 + add w5,w5,w12 + ror w11,w11,#6 + add v3.4s,v3.4s,v5.4s + eor w14,w6,w7 + eor w15,w15,w6,ror#20 + sli v7.4s,v19.4s,#13 + add w5,w5,w11 + ldr w12,[sp,#56] + and w13,w13,w14 + eor v17.16b,v17.16b,v16.16b + ror w15,w15,#2 + add w9,w9,w5 + eor w13,w13,w7 + eor v17.16b,v17.16b,v7.16b + add w4,w4,w12 + add w5,w5,w15 + and w12,w10,w9 + add v3.4s,v3.4s,v17.4s + bic w15,w3,w9 + eor w11,w9,w9,ror#5 + add w5,w5,w13 + ushr v18.4s,v3.4s,#17 + orr w12,w12,w15 + ushr v19.4s,v3.4s,#10 + eor w11,w11,w9,ror#19 + eor w15,w5,w5,ror#11 + sli v18.4s,v3.4s,#15 + add w4,w4,w12 + ushr v17.4s,v3.4s,#19 + ror w11,w11,#6 + eor w13,w5,w6 + eor v19.16b,v19.16b,v18.16b + eor w15,w15,w5,ror#20 + add w4,w4,w11 + sli v17.4s,v3.4s,#13 + ldr w12,[sp,#60] + and w14,w14,w13 + ror w15,w15,#2 + ld1 {v4.4s},[x16], #16 + add w8,w8,w4 + eor v19.16b,v19.16b,v17.16b + eor w14,w14,w6 + eor v17.16b,v17.16b,v17.16b + add w3,w3,w12 + add w4,w4,w15 + and w12,w9,w8 + mov v17.d[1],v19.d[0] + bic w15,w10,w8 + eor w11,w8,w8,ror#5 + add w4,w4,w14 + add v3.4s,v3.4s,v17.4s + orr w12,w12,w15 + eor w11,w11,w8,ror#19 + eor w15,w4,w4,ror#11 + add v4.4s,v4.4s,v3.4s + add w3,w3,w12 + ror w11,w11,#6 + eor w14,w4,w5 + eor w15,w15,w4,ror#20 + add w3,w3,w11 + ldr w12,[x16] + and w13,w13,w14 + ror w15,w15,#2 + add w7,w7,w3 + eor w13,w13,w5 + st1 {v4.4s},[x17], #16 + cmp w12,#0 // check for K256 terminator + ldr w12,[sp,#0] + sub x17,x17,#64 + bne .L_00_48 + + sub x16,x16,#256 // rewind x16 + cmp x1,x2 + mov x17, #64 + csel x17, x17, xzr, eq + sub x1,x1,x17 // avoid SEGV + mov x17,sp + add w10,w10,w12 + add w3,w3,w15 + and w12,w8,w7 + ld1 {v0.16b},[x1],#16 + bic w15,w9,w7 + eor w11,w7,w7,ror#5 + ld1 {v4.4s},[x16],#16 + add w3,w3,w13 + orr w12,w12,w15 + eor w11,w11,w7,ror#19 + eor w15,w3,w3,ror#11 + rev32 v0.16b,v0.16b + add w10,w10,w12 + ror w11,w11,#6 + eor w13,w3,w4 + eor w15,w15,w3,ror#20 + add v4.4s,v4.4s,v0.4s + add w10,w10,w11 + ldr w12,[sp,#4] + and w14,w14,w13 + ror w15,w15,#2 + add w6,w6,w10 + eor w14,w14,w4 + add w9,w9,w12 + add w10,w10,w15 + and w12,w7,w6 + bic w15,w8,w6 + eor w11,w6,w6,ror#5 + add w10,w10,w14 + orr w12,w12,w15 + eor w11,w11,w6,ror#19 + eor w15,w10,w10,ror#11 + add w9,w9,w12 + ror w11,w11,#6 + eor w14,w10,w3 + eor w15,w15,w10,ror#20 + add w9,w9,w11 + ldr w12,[sp,#8] + and w13,w13,w14 + ror w15,w15,#2 + add w5,w5,w9 + eor w13,w13,w3 + add w8,w8,w12 + add w9,w9,w15 + and w12,w6,w5 + bic w15,w7,w5 + eor w11,w5,w5,ror#5 + add w9,w9,w13 + orr w12,w12,w15 + eor w11,w11,w5,ror#19 + eor w15,w9,w9,ror#11 + add w8,w8,w12 + ror w11,w11,#6 + eor w13,w9,w10 + eor w15,w15,w9,ror#20 + add w8,w8,w11 + ldr w12,[sp,#12] + and w14,w14,w13 + ror w15,w15,#2 + add w4,w4,w8 + eor w14,w14,w10 + add w7,w7,w12 + add w8,w8,w15 + and w12,w5,w4 + bic w15,w6,w4 + eor w11,w4,w4,ror#5 + add w8,w8,w14 + orr w12,w12,w15 + eor w11,w11,w4,ror#19 + eor w15,w8,w8,ror#11 + add w7,w7,w12 + ror w11,w11,#6 + eor w14,w8,w9 + eor w15,w15,w8,ror#20 + add w7,w7,w11 + ldr w12,[sp,#16] + and w13,w13,w14 + ror w15,w15,#2 + add w3,w3,w7 + eor w13,w13,w9 + st1 {v4.4s},[x17], #16 + add w6,w6,w12 + add w7,w7,w15 + and w12,w4,w3 + ld1 {v1.16b},[x1],#16 + bic w15,w5,w3 + eor w11,w3,w3,ror#5 + ld1 {v4.4s},[x16],#16 + add w7,w7,w13 + orr w12,w12,w15 + eor w11,w11,w3,ror#19 + eor w15,w7,w7,ror#11 + rev32 v1.16b,v1.16b + add w6,w6,w12 + ror w11,w11,#6 + eor w13,w7,w8 + eor w15,w15,w7,ror#20 + add v4.4s,v4.4s,v1.4s + add w6,w6,w11 + ldr w12,[sp,#20] + and w14,w14,w13 + ror w15,w15,#2 + add w10,w10,w6 + eor w14,w14,w8 + add w5,w5,w12 + add w6,w6,w15 + and w12,w3,w10 + bic w15,w4,w10 + eor w11,w10,w10,ror#5 + add w6,w6,w14 + orr w12,w12,w15 + eor w11,w11,w10,ror#19 + eor w15,w6,w6,ror#11 + add w5,w5,w12 + ror w11,w11,#6 + eor w14,w6,w7 + eor w15,w15,w6,ror#20 + add w5,w5,w11 + ldr w12,[sp,#24] + and w13,w13,w14 + ror w15,w15,#2 + add w9,w9,w5 + eor w13,w13,w7 + add w4,w4,w12 + add w5,w5,w15 + and w12,w10,w9 + bic w15,w3,w9 + eor w11,w9,w9,ror#5 + add w5,w5,w13 + orr w12,w12,w15 + eor w11,w11,w9,ror#19 + eor w15,w5,w5,ror#11 + add w4,w4,w12 + ror w11,w11,#6 + eor w13,w5,w6 + eor w15,w15,w5,ror#20 + add w4,w4,w11 + ldr w12,[sp,#28] + and w14,w14,w13 + ror w15,w15,#2 + add w8,w8,w4 + eor w14,w14,w6 + add w3,w3,w12 + add w4,w4,w15 + and w12,w9,w8 + bic w15,w10,w8 + eor w11,w8,w8,ror#5 + add w4,w4,w14 + orr w12,w12,w15 + eor w11,w11,w8,ror#19 + eor w15,w4,w4,ror#11 + add w3,w3,w12 + ror w11,w11,#6 + eor w14,w4,w5 + eor w15,w15,w4,ror#20 + add w3,w3,w11 + ldr w12,[sp,#32] + and w13,w13,w14 + ror w15,w15,#2 + add w7,w7,w3 + eor w13,w13,w5 + st1 {v4.4s},[x17], #16 + add w10,w10,w12 + add w3,w3,w15 + and w12,w8,w7 + ld1 {v2.16b},[x1],#16 + bic w15,w9,w7 + eor w11,w7,w7,ror#5 + ld1 {v4.4s},[x16],#16 + add w3,w3,w13 + orr w12,w12,w15 + eor w11,w11,w7,ror#19 + eor w15,w3,w3,ror#11 + rev32 v2.16b,v2.16b + add w10,w10,w12 + ror w11,w11,#6 + eor w13,w3,w4 + eor w15,w15,w3,ror#20 + add v4.4s,v4.4s,v2.4s + add w10,w10,w11 + ldr w12,[sp,#36] + and w14,w14,w13 + ror w15,w15,#2 + add w6,w6,w10 + eor w14,w14,w4 + add w9,w9,w12 + add w10,w10,w15 + and w12,w7,w6 + bic w15,w8,w6 + eor w11,w6,w6,ror#5 + add w10,w10,w14 + orr w12,w12,w15 + eor w11,w11,w6,ror#19 + eor w15,w10,w10,ror#11 + add w9,w9,w12 + ror w11,w11,#6 + eor w14,w10,w3 + eor w15,w15,w10,ror#20 + add w9,w9,w11 + ldr w12,[sp,#40] + and w13,w13,w14 + ror w15,w15,#2 + add w5,w5,w9 + eor w13,w13,w3 + add w8,w8,w12 + add w9,w9,w15 + and w12,w6,w5 + bic w15,w7,w5 + eor w11,w5,w5,ror#5 + add w9,w9,w13 + orr w12,w12,w15 + eor w11,w11,w5,ror#19 + eor w15,w9,w9,ror#11 + add w8,w8,w12 + ror w11,w11,#6 + eor w13,w9,w10 + eor w15,w15,w9,ror#20 + add w8,w8,w11 + ldr w12,[sp,#44] + and w14,w14,w13 + ror w15,w15,#2 + add w4,w4,w8 + eor w14,w14,w10 + add w7,w7,w12 + add w8,w8,w15 + and w12,w5,w4 + bic w15,w6,w4 + eor w11,w4,w4,ror#5 + add w8,w8,w14 + orr w12,w12,w15 + eor w11,w11,w4,ror#19 + eor w15,w8,w8,ror#11 + add w7,w7,w12 + ror w11,w11,#6 + eor w14,w8,w9 + eor w15,w15,w8,ror#20 + add w7,w7,w11 + ldr w12,[sp,#48] + and w13,w13,w14 + ror w15,w15,#2 + add w3,w3,w7 + eor w13,w13,w9 + st1 {v4.4s},[x17], #16 + add w6,w6,w12 + add w7,w7,w15 + and w12,w4,w3 + ld1 {v3.16b},[x1],#16 + bic w15,w5,w3 + eor w11,w3,w3,ror#5 + ld1 {v4.4s},[x16],#16 + add w7,w7,w13 + orr w12,w12,w15 + eor w11,w11,w3,ror#19 + eor w15,w7,w7,ror#11 + rev32 v3.16b,v3.16b + add w6,w6,w12 + ror w11,w11,#6 + eor w13,w7,w8 + eor w15,w15,w7,ror#20 + add v4.4s,v4.4s,v3.4s + add w6,w6,w11 + ldr w12,[sp,#52] + and w14,w14,w13 + ror w15,w15,#2 + add w10,w10,w6 + eor w14,w14,w8 + add w5,w5,w12 + add w6,w6,w15 + and w12,w3,w10 + bic w15,w4,w10 + eor w11,w10,w10,ror#5 + add w6,w6,w14 + orr w12,w12,w15 + eor w11,w11,w10,ror#19 + eor w15,w6,w6,ror#11 + add w5,w5,w12 + ror w11,w11,#6 + eor w14,w6,w7 + eor w15,w15,w6,ror#20 + add w5,w5,w11 + ldr w12,[sp,#56] + and w13,w13,w14 + ror w15,w15,#2 + add w9,w9,w5 + eor w13,w13,w7 + add w4,w4,w12 + add w5,w5,w15 + and w12,w10,w9 + bic w15,w3,w9 + eor w11,w9,w9,ror#5 + add w5,w5,w13 + orr w12,w12,w15 + eor w11,w11,w9,ror#19 + eor w15,w5,w5,ror#11 + add w4,w4,w12 + ror w11,w11,#6 + eor w13,w5,w6 + eor w15,w15,w5,ror#20 + add w4,w4,w11 + ldr w12,[sp,#60] + and w14,w14,w13 + ror w15,w15,#2 + add w8,w8,w4 + eor w14,w14,w6 + add w3,w3,w12 + add w4,w4,w15 + and w12,w9,w8 + bic w15,w10,w8 + eor w11,w8,w8,ror#5 + add w4,w4,w14 + orr w12,w12,w15 + eor w11,w11,w8,ror#19 + eor w15,w4,w4,ror#11 + add w3,w3,w12 + ror w11,w11,#6 + eor w14,w4,w5 + eor w15,w15,w4,ror#20 + add w3,w3,w11 + and w13,w13,w14 + ror w15,w15,#2 + add w7,w7,w3 + eor w13,w13,w5 + st1 {v4.4s},[x17], #16 + add w3,w3,w15 // h+=Sigma0(a) from the past + ldp w11,w12,[x0,#0] + add w3,w3,w13 // h+=Maj(a,b,c) from the past + ldp w13,w14,[x0,#8] + add w3,w3,w11 // accumulate + add w4,w4,w12 + ldp w11,w12,[x0,#16] + add w5,w5,w13 + add w6,w6,w14 + ldp w13,w14,[x0,#24] + add w7,w7,w11 + add w8,w8,w12 + ldr w12,[sp,#0] + stp w3,w4,[x0,#0] + add w9,w9,w13 + mov w13,wzr + stp w5,w6,[x0,#8] + add w10,w10,w14 + stp w7,w8,[x0,#16] + eor w14,w4,w5 + stp w9,w10,[x0,#24] + mov w15,wzr + mov x17,sp + b.ne .L_00_48 + + ldr x29,[x29] + add sp,sp,#16*4+16 + ret +.size sha256_block_neon,.-sha256_block_neon +#ifndef __KERNEL__ +.comm OPENSSL_armcap_P,4,4 +#endif diff --git a/arch/arm64/crypto/sha256-glue.c b/arch/arm64/crypto/sha256-glue.c new file mode 100644 index 000000000000..a2226f841960 --- /dev/null +++ b/arch/arm64/crypto/sha256-glue.c @@ -0,0 +1,185 @@ +/* + * Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64 + * + * 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 as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <asm/hwcap.h> +#include <asm/neon.h> +#include <asm/simd.h> +#include <crypto/internal/hash.h> +#include <crypto/sha.h> +#include <crypto/sha256_base.h> +#include <linux/cryptohash.h> +#include <linux/types.h> +#include <linux/string.h> + +MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64"); +MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>"); +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha224"); +MODULE_ALIAS_CRYPTO("sha256"); + +asmlinkage void sha256_block_data_order(u32 *digest, const void *data, + unsigned int num_blks); + +asmlinkage void sha256_block_neon(u32 *digest, const void *data, + unsigned int num_blks); + +static int sha256_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + return sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_data_order); +} + +static int sha256_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + if (len) + sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_data_order); + sha256_base_do_finalize(desc, + (sha256_block_fn *)sha256_block_data_order); + + return sha256_base_finish(desc, out); +} + +static int sha256_final(struct shash_desc *desc, u8 *out) +{ + return sha256_finup(desc, NULL, 0, out); +} + +static struct shash_alg algs[] = { { + .digestsize = SHA256_DIGEST_SIZE, + .init = sha256_base_init, + .update = sha256_update, + .final = sha256_final, + .finup = sha256_finup, + .descsize = sizeof(struct sha256_state), + .base.cra_name = "sha256", + .base.cra_driver_name = "sha256-arm64", + .base.cra_priority = 100, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA256_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +}, { + .digestsize = SHA224_DIGEST_SIZE, + .init = sha224_base_init, + .update = sha256_update, + .final = sha256_final, + .finup = sha256_finup, + .descsize = sizeof(struct sha256_state), + .base.cra_name = "sha224", + .base.cra_driver_name = "sha224-arm64", + .base.cra_priority = 100, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA224_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +} }; + +static int sha256_update_neon(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + /* + * Stacking and unstacking a substantial slice of the NEON register + * file may significantly affect performance for small updates when + * executing in interrupt context, so fall back to the scalar code + * in that case. + */ + if (!may_use_simd()) + return sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_data_order); + + kernel_neon_begin(); + sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_neon); + kernel_neon_end(); + + return 0; +} + +static int sha256_finup_neon(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + if (!may_use_simd()) { + if (len) + sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_data_order); + sha256_base_do_finalize(desc, + (sha256_block_fn *)sha256_block_data_order); + } else { + kernel_neon_begin(); + if (len) + sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_neon); + sha256_base_do_finalize(desc, + (sha256_block_fn *)sha256_block_neon); + kernel_neon_end(); + } + return sha256_base_finish(desc, out); +} + +static int sha256_final_neon(struct shash_desc *desc, u8 *out) +{ + return sha256_finup_neon(desc, NULL, 0, out); +} + +static struct shash_alg neon_algs[] = { { + .digestsize = SHA256_DIGEST_SIZE, + .init = sha256_base_init, + .update = sha256_update_neon, + .final = sha256_final_neon, + .finup = sha256_finup_neon, + .descsize = sizeof(struct sha256_state), + .base.cra_name = "sha256", + .base.cra_driver_name = "sha256-arm64-neon", + .base.cra_priority = 150, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA256_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +}, { + .digestsize = SHA224_DIGEST_SIZE, + .init = sha224_base_init, + .update = sha256_update_neon, + .final = sha256_final_neon, + .finup = sha256_finup_neon, + .descsize = sizeof(struct sha256_state), + .base.cra_name = "sha224", + .base.cra_driver_name = "sha224-arm64-neon", + .base.cra_priority = 150, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA224_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +} }; + +static int __init sha256_mod_init(void) +{ + int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs)); + if (ret) + return ret; + + if (elf_hwcap & HWCAP_ASIMD) { + ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs)); + if (ret) + crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); + } + return ret; +} + +static void __exit sha256_mod_fini(void) +{ + if (elf_hwcap & HWCAP_ASIMD) + crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs)); + crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); +} + +module_init(sha256_mod_init); +module_exit(sha256_mod_fini); diff --git a/arch/arm64/crypto/sha512-armv8.pl b/arch/arm64/crypto/sha512-armv8.pl new file mode 100644 index 000000000000..c55efb308544 --- /dev/null +++ b/arch/arm64/crypto/sha512-armv8.pl @@ -0,0 +1,778 @@ +#! /usr/bin/env perl +# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# ==================================================================== +# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL +# project. The module is, however, dual licensed under OpenSSL and +# CRYPTOGAMS licenses depending on where you obtain it. For further +# details see http://www.openssl.org/~appro/cryptogams/. +# +# Permission to use under GPLv2 terms is granted. +# ==================================================================== +# +# SHA256/512 for ARMv8. +# +# Performance in cycles per processed byte and improvement coefficient +# over code generated with "default" compiler: +# +# SHA256-hw SHA256(*) SHA512 +# Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) +# Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) +# Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +# Denver 2.01 10.5 (+26%) 6.70 (+8%) +# X-Gene 20.0 (+100%) 12.8 (+300%(***)) +# Mongoose 2.36 13.0 (+50%) 8.36 (+33%) +# +# (*) Software SHA256 results are of lesser relevance, presented +# mostly for informational purposes. +# (**) The result is a trade-off: it's possible to improve it by +# 10% (or by 1 cycle per round), but at the cost of 20% loss +# on Cortex-A53 (or by 4 cycles per round). +# (***) Super-impressive coefficients over gcc-generated code are +# indication of some compiler "pathology", most notably code +# generated with -mgeneral-regs-only is significanty faster +# and the gap is only 40-90%. +# +# October 2016. +# +# Originally it was reckoned that it makes no sense to implement NEON +# version of SHA256 for 64-bit processors. This is because performance +# improvement on most wide-spread Cortex-A5x processors was observed +# to be marginal, same on Cortex-A53 and ~10% on A57. But then it was +# observed that 32-bit NEON SHA256 performs significantly better than +# 64-bit scalar version on *some* of the more recent processors. As +# result 64-bit NEON version of SHA256 was added to provide best +# all-round performance. For example it executes ~30% faster on X-Gene +# and Mongoose. [For reference, NEON version of SHA512 is bound to +# deliver much less improvement, likely *negative* on Cortex-A5x. +# Which is why NEON support is limited to SHA256.] + +$output=pop; +$flavour=pop; + +if ($flavour && $flavour ne "void") { + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; + ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or + ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or + die "can't locate arm-xlate.pl"; + + open OUT,"| \"$^X\" $xlate $flavour $output"; + *STDOUT=*OUT; +} else { + open STDOUT,">$output"; +} + +if ($output =~ /512/) { + $BITS=512; + $SZ=8; + @Sigma0=(28,34,39); + @Sigma1=(14,18,41); + @sigma0=(1, 8, 7); + @sigma1=(19,61, 6); + $rounds=80; + $reg_t="x"; +} else { + $BITS=256; + $SZ=4; + @Sigma0=( 2,13,22); + @Sigma1=( 6,11,25); + @sigma0=( 7,18, 3); + @sigma1=(17,19,10); + $rounds=64; + $reg_t="w"; +} + +$func="sha${BITS}_block_data_order"; + +($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30)); + +@X=map("$reg_t$_",(3..15,0..2)); +@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27)); +($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28)); + +sub BODY_00_xx { +my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_; +my $j=($i+1)&15; +my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]); + $T0=@X[$i+3] if ($i<11); + +$code.=<<___ if ($i<16); +#ifndef __AARCH64EB__ + rev @X[$i],@X[$i] // $i +#endif +___ +$code.=<<___ if ($i<13 && ($i&1)); + ldp @X[$i+1],@X[$i+2],[$inp],#2*$SZ +___ +$code.=<<___ if ($i==13); + ldp @X[14],@X[15],[$inp] +___ +$code.=<<___ if ($i>=14); + ldr @X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`] +___ +$code.=<<___ if ($i>0 && $i<16); + add $a,$a,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=11); + str @X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`] +___ +# While ARMv8 specifies merged rotate-n-logical operation such as +# 'eor x,y,z,ror#n', it was found to negatively affect performance +# on Apple A7. The reason seems to be that it requires even 'y' to +# be available earlier. This means that such merged instruction is +# not necessarily best choice on critical path... On the other hand +# Cortex-A5x handles merged instructions much better than disjoint +# rotate and logical... See (**) footnote above. +$code.=<<___ if ($i<15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + eor $T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]` + and $t1,$f,$e + bic $t2,$g,$e + add $h,$h,@X[$i&15] // h+=X[i] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$T0,ror#$Sigma1[1] // Sigma1(e) + ror $T0,$a,#$Sigma0[0] + add $h,$h,$t1 // h+=Ch(e,f,g) + eor $t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]` + add $h,$h,$t0 // h+=Sigma1(e) + and $t3,$t3,$t2 // (b^c)&=(a^b) + add $d,$d,$h // d+=h + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$t1,ror#$Sigma0[1] // Sigma0(a) + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + //add $h,$h,$t1 // h+=Sigma0(a) +___ +$code.=<<___ if ($i>=15); + ror $t0,$e,#$Sigma1[0] + add $h,$h,$t2 // h+=K[i] + ror $T1,@X[($j+1)&15],#$sigma0[0] + and $t1,$f,$e + ror $T2,@X[($j+14)&15],#$sigma1[0] + bic $t2,$g,$e + ror $T0,$a,#$Sigma0[0] + add $h,$h,@X[$i&15] // h+=X[i] + eor $t0,$t0,$e,ror#$Sigma1[1] + eor $T1,$T1,@X[($j+1)&15],ror#$sigma0[1] + orr $t1,$t1,$t2 // Ch(e,f,g) + eor $t2,$a,$b // a^b, b^c in next round + eor $t0,$t0,$e,ror#$Sigma1[2] // Sigma1(e) + eor $T0,$T0,$a,ror#$Sigma0[1] + add $h,$h,$t1 // h+=Ch(e,f,g) + and $t3,$t3,$t2 // (b^c)&=(a^b) + eor $T2,$T2,@X[($j+14)&15],ror#$sigma1[1] + eor $T1,$T1,@X[($j+1)&15],lsr#$sigma0[2] // sigma0(X[i+1]) + add $h,$h,$t0 // h+=Sigma1(e) + eor $t3,$t3,$b // Maj(a,b,c) + eor $t1,$T0,$a,ror#$Sigma0[2] // Sigma0(a) + eor $T2,$T2,@X[($j+14)&15],lsr#$sigma1[2] // sigma1(X[i+14]) + add @X[$j],@X[$j],@X[($j+9)&15] + add $d,$d,$h // d+=h + add $h,$h,$t3 // h+=Maj(a,b,c) + ldr $t3,[$Ktbl],#$SZ // *K++, $t2 in next round + add @X[$j],@X[$j],$T1 + add $h,$h,$t1 // h+=Sigma0(a) + add @X[$j],@X[$j],$T2 +___ + ($t2,$t3)=($t3,$t2); +} + +$code.=<<___; +#ifndef __KERNEL__ +# include "arm_arch.h" +#endif + +.text + +.extern OPENSSL_armcap_P +.globl $func +.type $func,%function +.align 6 +$func: +___ +$code.=<<___ if ($SZ==4); +#ifndef __KERNEL__ +# ifdef __ILP32__ + ldrsw x16,.LOPENSSL_armcap_P +# else + ldr x16,.LOPENSSL_armcap_P +# endif + adr x17,.LOPENSSL_armcap_P + add x16,x16,x17 + ldr w16,[x16] + tst w16,#ARMV8_SHA256 + b.ne .Lv8_entry + tst w16,#ARMV7_NEON + b.ne .Lneon_entry +#endif +___ +$code.=<<___; + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#4*$SZ + + ldp $A,$B,[$ctx] // load context + ldp $C,$D,[$ctx,#2*$SZ] + ldp $E,$F,[$ctx,#4*$SZ] + add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input + ldp $G,$H,[$ctx,#6*$SZ] + adr $Ktbl,.LK$BITS + stp $ctx,$num,[x29,#96] + +.Loop: + ldp @X[0],@X[1],[$inp],#2*$SZ + ldr $t2,[$Ktbl],#$SZ // *K++ + eor $t3,$B,$C // magic seed + str $inp,[x29,#112] +___ +for ($i=0;$i<16;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=".Loop_16_xx:\n"; +for (;$i<32;$i++) { &BODY_00_xx($i,@V); unshift(@V,pop(@V)); } +$code.=<<___; + cbnz $t2,.Loop_16_xx + + ldp $ctx,$num,[x29,#96] + ldr $inp,[x29,#112] + sub $Ktbl,$Ktbl,#`$SZ*($rounds+1)` // rewind + + ldp @X[0],@X[1],[$ctx] + ldp @X[2],@X[3],[$ctx,#2*$SZ] + add $inp,$inp,#14*$SZ // advance input pointer + ldp @X[4],@X[5],[$ctx,#4*$SZ] + add $A,$A,@X[0] + ldp @X[6],@X[7],[$ctx,#6*$SZ] + add $B,$B,@X[1] + add $C,$C,@X[2] + add $D,$D,@X[3] + stp $A,$B,[$ctx] + add $E,$E,@X[4] + add $F,$F,@X[5] + stp $C,$D,[$ctx,#2*$SZ] + add $G,$G,@X[6] + add $H,$H,@X[7] + cmp $inp,$num + stp $E,$F,[$ctx,#4*$SZ] + stp $G,$H,[$ctx,#6*$SZ] + b.ne .Loop + + ldp x19,x20,[x29,#16] + add sp,sp,#4*$SZ + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + ret +.size $func,.-$func + +.align 6 +.type .LK$BITS,%object +.LK$BITS: +___ +$code.=<<___ if ($SZ==8); + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0 // terminator +___ +$code.=<<___ if ($SZ==4); + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + .long 0 //terminator +___ +$code.=<<___; +.size .LK$BITS,.-.LK$BITS +#ifndef __KERNEL__ +.align 3 +.LOPENSSL_armcap_P: +# ifdef __ILP32__ + .long OPENSSL_armcap_P-. +# else + .quad OPENSSL_armcap_P-. +# endif +#endif +.asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>" +.align 2 +___ + +if ($SZ==4) { +my $Ktbl="x3"; + +my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2)); +my @MSG=map("v$_.16b",(4..7)); +my ($W0,$W1)=("v16.4s","v17.4s"); +my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b"); + +$code.=<<___; +#ifndef __KERNEL__ +.type sha256_block_armv8,%function +.align 6 +sha256_block_armv8: +.Lv8_entry: + stp x29,x30,[sp,#-16]! + add x29,sp,#0 + + ld1.32 {$ABCD,$EFGH},[$ctx] + adr $Ktbl,.LK256 + +.Loop_hw: + ld1 {@MSG[0]-@MSG[3]},[$inp],#64 + sub $num,$num,#1 + ld1.32 {$W0},[$Ktbl],#16 + rev32 @MSG[0],@MSG[0] + rev32 @MSG[1],@MSG[1] + rev32 @MSG[2],@MSG[2] + rev32 @MSG[3],@MSG[3] + orr $ABCD_SAVE,$ABCD,$ABCD // offload + orr $EFGH_SAVE,$EFGH,$EFGH +___ +for($i=0;$i<12;$i++) { +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + sha256su0 @MSG[0],@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + sha256su1 @MSG[0],@MSG[2],@MSG[3] +___ + ($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG)); +} +$code.=<<___; + ld1.32 {$W1},[$Ktbl],#16 + add.i32 $W0,$W0,@MSG[0] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + ld1.32 {$W0},[$Ktbl],#16 + add.i32 $W1,$W1,@MSG[1] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + ld1.32 {$W1},[$Ktbl] + add.i32 $W0,$W0,@MSG[2] + sub $Ktbl,$Ktbl,#$rounds*$SZ-16 // rewind + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W0 + sha256h2 $EFGH,$abcd,$W0 + + add.i32 $W1,$W1,@MSG[3] + orr $abcd,$ABCD,$ABCD + sha256h $ABCD,$EFGH,$W1 + sha256h2 $EFGH,$abcd,$W1 + + add.i32 $ABCD,$ABCD,$ABCD_SAVE + add.i32 $EFGH,$EFGH,$EFGH_SAVE + + cbnz $num,.Loop_hw + + st1.32 {$ABCD,$EFGH},[$ctx] + + ldr x29,[sp],#16 + ret +.size sha256_block_armv8,.-sha256_block_armv8 +#endif +___ +} + +if ($SZ==4) { ######################################### NEON stuff # +# You'll surely note a lot of similarities with sha256-armv4 module, +# and of course it's not a coincidence. sha256-armv4 was used as +# initial template, but was adapted for ARMv8 instruction set and +# extensively re-tuned for all-round performance. + +my @V = ($A,$B,$C,$D,$E,$F,$G,$H) = map("w$_",(3..10)); +my ($t0,$t1,$t2,$t3,$t4) = map("w$_",(11..15)); +my $Ktbl="x16"; +my $Xfer="x17"; +my @X = map("q$_",(0..3)); +my ($T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7) = map("q$_",(4..7,16..19)); +my $j=0; + +sub AUTOLOAD() # thunk [simplified] x86-style perlasm +{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./; + my $arg = pop; + $arg = "#$arg" if ($arg*1 eq $arg); + $code .= "\t$opcode\t".join(',',@_,$arg)."\n"; +} + +sub Dscalar { shift =~ m|[qv]([0-9]+)|?"d$1":""; } +sub Dlo { shift =~ m|[qv]([0-9]+)|?"v$1.d[0]":""; } +sub Dhi { shift =~ m|[qv]([0-9]+)|?"v$1.d[1]":""; } + +sub Xupdate() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + &ext_8 ($T0,@X[0],@X[1],4); # X[1..4] + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &ext_8 ($T3,@X[2],@X[3],4); # X[9..12] + eval(shift(@insns)); + eval(shift(@insns)); + &mov (&Dscalar($T7),&Dhi(@X[3])); # X[14..15] + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T2,$T0,$sigma0[0]); + eval(shift(@insns)); + &ushr_32 ($T1,$T0,$sigma0[2]); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T3); # X[0..3] += X[9..12] + eval(shift(@insns)); + &sli_32 ($T2,$T0,32-$sigma0[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T3,$T0,$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T1,$T1,$T2); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T3,$T0,32-$sigma0[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T4,$T7,$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T1,$T1,$T3); # sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T4,$T7,32-$sigma1[0]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T5,$T7,$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T3,$T7,$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4]) + eval(shift(@insns)); + eval(shift(@insns)); + &sli_u32 ($T3,$T7,32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T4); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T3); # sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T5); # X[0..1] += sigma1(X[14..15]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &ushr_32 ($T6,@X[0],$sigma1[0]); + eval(shift(@insns)); + &ushr_32 ($T7,@X[0],$sigma1[2]); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T6,@X[0],32-$sigma1[0]); + eval(shift(@insns)); + &ushr_32 ($T5,@X[0],$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T7,$T7,$T6); + eval(shift(@insns)); + eval(shift(@insns)); + &sli_32 ($T5,@X[0],32-$sigma1[1]); + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_32 ("{$T0}","[$Ktbl], #16"); + eval(shift(@insns)); + &eor_8 ($T7,$T7,$T5); # sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + &eor_8 ($T5,$T5,$T5); + eval(shift(@insns)); + eval(shift(@insns)); + &mov (&Dhi($T5), &Dlo($T7)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 (@X[0],@X[0],$T5); # X[2..3] += sigma1(X[16..17]) + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 ($T0,$T0,@X[0]); + while($#insns>=1) { eval(shift(@insns)); } + &st1_32 ("{$T0}","[$Xfer], #16"); + eval(shift(@insns)); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub Xpreload() +{ use integer; + my $body = shift; + my @insns = (&$body,&$body,&$body,&$body); + my ($a,$b,$c,$d,$e,$f,$g,$h); + + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_8 ("{@X[0]}","[$inp],#16"); + eval(shift(@insns)); + eval(shift(@insns)); + &ld1_32 ("{$T0}","[$Ktbl],#16"); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &rev32 (@X[0],@X[0]); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + eval(shift(@insns)); + &add_32 ($T0,$T0,@X[0]); + foreach (@insns) { eval; } # remaining instructions + &st1_32 ("{$T0}","[$Xfer], #16"); + + push(@X,shift(@X)); # "rotate" X[] +} + +sub body_00_15 () { + ( + '($a,$b,$c,$d,$e,$f,$g,$h)=@V;'. + '&add ($h,$h,$t1)', # h+=X[i]+K[i] + '&add ($a,$a,$t4);'. # h+=Sigma0(a) from the past + '&and ($t1,$f,$e)', + '&bic ($t4,$g,$e)', + '&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))', + '&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past + '&orr ($t1,$t1,$t4)', # Ch(e,f,g) + '&eor ($t0,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e) + '&eor ($t4,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))', + '&add ($h,$h,$t1)', # h+=Ch(e,f,g) + '&ror ($t0,$t0,"#$Sigma1[0]")', + '&eor ($t2,$a,$b)', # a^b, b^c in next round + '&eor ($t4,$t4,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a) + '&add ($h,$h,$t0)', # h+=Sigma1(e) + '&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'. + '&ldr ($t1,"[$Ktbl]") if ($j==15);'. + '&and ($t3,$t3,$t2)', # (b^c)&=(a^b) + '&ror ($t4,$t4,"#$Sigma0[0]")', + '&add ($d,$d,$h)', # d+=h + '&eor ($t3,$t3,$b)', # Maj(a,b,c) + '$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);' + ) +} + +$code.=<<___; +#ifdef __KERNEL__ +.globl sha256_block_neon +#endif +.type sha256_block_neon,%function +.align 4 +sha256_block_neon: +.Lneon_entry: + stp x29, x30, [sp, #-16]! + mov x29, sp + sub sp,sp,#16*4 + + adr $Ktbl,.LK256 + add $num,$inp,$num,lsl#6 // len to point at the end of inp + + ld1.8 {@X[0]},[$inp], #16 + ld1.8 {@X[1]},[$inp], #16 + ld1.8 {@X[2]},[$inp], #16 + ld1.8 {@X[3]},[$inp], #16 + ld1.32 {$T0},[$Ktbl], #16 + ld1.32 {$T1},[$Ktbl], #16 + ld1.32 {$T2},[$Ktbl], #16 + ld1.32 {$T3},[$Ktbl], #16 + rev32 @X[0],@X[0] // yes, even on + rev32 @X[1],@X[1] // big-endian + rev32 @X[2],@X[2] + rev32 @X[3],@X[3] + mov $Xfer,sp + add.32 $T0,$T0,@X[0] + add.32 $T1,$T1,@X[1] + add.32 $T2,$T2,@X[2] + st1.32 {$T0-$T1},[$Xfer], #32 + add.32 $T3,$T3,@X[3] + st1.32 {$T2-$T3},[$Xfer] + sub $Xfer,$Xfer,#32 + + ldp $A,$B,[$ctx] + ldp $C,$D,[$ctx,#8] + ldp $E,$F,[$ctx,#16] + ldp $G,$H,[$ctx,#24] + ldr $t1,[sp,#0] + mov $t2,wzr + eor $t3,$B,$C + mov $t4,wzr + b .L_00_48 + +.align 4 +.L_00_48: +___ + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); + &Xupdate(\&body_00_15); +$code.=<<___; + cmp $t1,#0 // check for K256 terminator + ldr $t1,[sp,#0] + sub $Xfer,$Xfer,#64 + bne .L_00_48 + + sub $Ktbl,$Ktbl,#256 // rewind $Ktbl + cmp $inp,$num + mov $Xfer, #64 + csel $Xfer, $Xfer, xzr, eq + sub $inp,$inp,$Xfer // avoid SEGV + mov $Xfer,sp +___ + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); + &Xpreload(\&body_00_15); +$code.=<<___; + add $A,$A,$t4 // h+=Sigma0(a) from the past + ldp $t0,$t1,[$ctx,#0] + add $A,$A,$t2 // h+=Maj(a,b,c) from the past + ldp $t2,$t3,[$ctx,#8] + add $A,$A,$t0 // accumulate + add $B,$B,$t1 + ldp $t0,$t1,[$ctx,#16] + add $C,$C,$t2 + add $D,$D,$t3 + ldp $t2,$t3,[$ctx,#24] + add $E,$E,$t0 + add $F,$F,$t1 + ldr $t1,[sp,#0] + stp $A,$B,[$ctx,#0] + add $G,$G,$t2 + mov $t2,wzr + stp $C,$D,[$ctx,#8] + add $H,$H,$t3 + stp $E,$F,[$ctx,#16] + eor $t3,$B,$C + stp $G,$H,[$ctx,#24] + mov $t4,wzr + mov $Xfer,sp + b.ne .L_00_48 + + ldr x29,[x29] + add sp,sp,#16*4+16 + ret +.size sha256_block_neon,.-sha256_block_neon +___ +} + +$code.=<<___; +#ifndef __KERNEL__ +.comm OPENSSL_armcap_P,4,4 +#endif +___ + +{ my %opcode = ( + "sha256h" => 0x5e004000, "sha256h2" => 0x5e005000, + "sha256su0" => 0x5e282800, "sha256su1" => 0x5e006000 ); + + sub unsha256 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16), + $mnemonic,$arg; + } +} + +open SELF,$0; +while(<SELF>) { + next if (/^#!/); + last if (!s/^#/\/\// and !/^$/); + print; +} +close SELF; + +foreach(split("\n",$code)) { + + s/\`([^\`]*)\`/eval($1)/ge; + + s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/ge; + + s/\bq([0-9]+)\b/v$1.16b/g; # old->new registers + + s/\.[ui]?8(\s)/$1/; + s/\.\w?32\b// and s/\.16b/\.4s/g; + m/(ld|st)1[^\[]+\[0\]/ and s/\.4s/\.s/g; + + print $_,"\n"; +} + +close STDOUT; diff --git a/arch/arm64/crypto/sha512-core.S_shipped b/arch/arm64/crypto/sha512-core.S_shipped new file mode 100644 index 000000000000..bd0f59f06c9d --- /dev/null +++ b/arch/arm64/crypto/sha512-core.S_shipped @@ -0,0 +1,1085 @@ +// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. +// +// Licensed under the OpenSSL license (the "License"). You may not use +// this file except in compliance with the License. You can obtain a copy +// in the file LICENSE in the source distribution or at +// https://www.openssl.org/source/license.html + +// ==================================================================== +// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL +// project. The module is, however, dual licensed under OpenSSL and +// CRYPTOGAMS licenses depending on where you obtain it. For further +// details see http://www.openssl.org/~appro/cryptogams/. +// +// Permission to use under GPLv2 terms is granted. +// ==================================================================== +// +// SHA256/512 for ARMv8. +// +// Performance in cycles per processed byte and improvement coefficient +// over code generated with "default" compiler: +// +// SHA256-hw SHA256(*) SHA512 +// Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) +// Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) +// Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) +// Denver 2.01 10.5 (+26%) 6.70 (+8%) +// X-Gene 20.0 (+100%) 12.8 (+300%(***)) +// Mongoose 2.36 13.0 (+50%) 8.36 (+33%) +// +// (*) Software SHA256 results are of lesser relevance, presented +// mostly for informational purposes. +// (**) The result is a trade-off: it's possible to improve it by +// 10% (or by 1 cycle per round), but at the cost of 20% loss +// on Cortex-A53 (or by 4 cycles per round). +// (***) Super-impressive coefficients over gcc-generated code are +// indication of some compiler "pathology", most notably code +// generated with -mgeneral-regs-only is significanty faster +// and the gap is only 40-90%. +// +// October 2016. +// +// Originally it was reckoned that it makes no sense to implement NEON +// version of SHA256 for 64-bit processors. This is because performance +// improvement on most wide-spread Cortex-A5x processors was observed +// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was +// observed that 32-bit NEON SHA256 performs significantly better than +// 64-bit scalar version on *some* of the more recent processors. As +// result 64-bit NEON version of SHA256 was added to provide best +// all-round performance. For example it executes ~30% faster on X-Gene +// and Mongoose. [For reference, NEON version of SHA512 is bound to +// deliver much less improvement, likely *negative* on Cortex-A5x. +// Which is why NEON support is limited to SHA256.] + +#ifndef __KERNEL__ +# include "arm_arch.h" +#endif + +.text + +.extern OPENSSL_armcap_P +.globl sha512_block_data_order +.type sha512_block_data_order,%function +.align 6 +sha512_block_data_order: + stp x29,x30,[sp,#-128]! + add x29,sp,#0 + + stp x19,x20,[sp,#16] + stp x21,x22,[sp,#32] + stp x23,x24,[sp,#48] + stp x25,x26,[sp,#64] + stp x27,x28,[sp,#80] + sub sp,sp,#4*8 + + ldp x20,x21,[x0] // load context + ldp x22,x23,[x0,#2*8] + ldp x24,x25,[x0,#4*8] + add x2,x1,x2,lsl#7 // end of input + ldp x26,x27,[x0,#6*8] + adr x30,.LK512 + stp x0,x2,[x29,#96] + +.Loop: + ldp x3,x4,[x1],#2*8 + ldr x19,[x30],#8 // *K++ + eor x28,x21,x22 // magic seed + str x1,[x29,#112] +#ifndef __AARCH64EB__ + rev x3,x3 // 0 +#endif + ror x16,x24,#14 + add x27,x27,x19 // h+=K[i] + eor x6,x24,x24,ror#23 + and x17,x25,x24 + bic x19,x26,x24 + add x27,x27,x3 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x20,x21 // a^b, b^c in next round + eor x16,x16,x6,ror#18 // Sigma1(e) + ror x6,x20,#28 + add x27,x27,x17 // h+=Ch(e,f,g) + eor x17,x20,x20,ror#5 + add x27,x27,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x23,x23,x27 // d+=h + eor x28,x28,x21 // Maj(a,b,c) + eor x17,x6,x17,ror#34 // Sigma0(a) + add x27,x27,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x27,x27,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x4,x4 // 1 +#endif + ldp x5,x6,[x1],#2*8 + add x27,x27,x17 // h+=Sigma0(a) + ror x16,x23,#14 + add x26,x26,x28 // h+=K[i] + eor x7,x23,x23,ror#23 + and x17,x24,x23 + bic x28,x25,x23 + add x26,x26,x4 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x27,x20 // a^b, b^c in next round + eor x16,x16,x7,ror#18 // Sigma1(e) + ror x7,x27,#28 + add x26,x26,x17 // h+=Ch(e,f,g) + eor x17,x27,x27,ror#5 + add x26,x26,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x22,x22,x26 // d+=h + eor x19,x19,x20 // Maj(a,b,c) + eor x17,x7,x17,ror#34 // Sigma0(a) + add x26,x26,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x26,x26,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x5,x5 // 2 +#endif + add x26,x26,x17 // h+=Sigma0(a) + ror x16,x22,#14 + add x25,x25,x19 // h+=K[i] + eor x8,x22,x22,ror#23 + and x17,x23,x22 + bic x19,x24,x22 + add x25,x25,x5 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x26,x27 // a^b, b^c in next round + eor x16,x16,x8,ror#18 // Sigma1(e) + ror x8,x26,#28 + add x25,x25,x17 // h+=Ch(e,f,g) + eor x17,x26,x26,ror#5 + add x25,x25,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x21,x21,x25 // d+=h + eor x28,x28,x27 // Maj(a,b,c) + eor x17,x8,x17,ror#34 // Sigma0(a) + add x25,x25,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x25,x25,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x6,x6 // 3 +#endif + ldp x7,x8,[x1],#2*8 + add x25,x25,x17 // h+=Sigma0(a) + ror x16,x21,#14 + add x24,x24,x28 // h+=K[i] + eor x9,x21,x21,ror#23 + and x17,x22,x21 + bic x28,x23,x21 + add x24,x24,x6 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x25,x26 // a^b, b^c in next round + eor x16,x16,x9,ror#18 // Sigma1(e) + ror x9,x25,#28 + add x24,x24,x17 // h+=Ch(e,f,g) + eor x17,x25,x25,ror#5 + add x24,x24,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x20,x20,x24 // d+=h + eor x19,x19,x26 // Maj(a,b,c) + eor x17,x9,x17,ror#34 // Sigma0(a) + add x24,x24,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x24,x24,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x7,x7 // 4 +#endif + add x24,x24,x17 // h+=Sigma0(a) + ror x16,x20,#14 + add x23,x23,x19 // h+=K[i] + eor x10,x20,x20,ror#23 + and x17,x21,x20 + bic x19,x22,x20 + add x23,x23,x7 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x24,x25 // a^b, b^c in next round + eor x16,x16,x10,ror#18 // Sigma1(e) + ror x10,x24,#28 + add x23,x23,x17 // h+=Ch(e,f,g) + eor x17,x24,x24,ror#5 + add x23,x23,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x27,x27,x23 // d+=h + eor x28,x28,x25 // Maj(a,b,c) + eor x17,x10,x17,ror#34 // Sigma0(a) + add x23,x23,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x23,x23,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x8,x8 // 5 +#endif + ldp x9,x10,[x1],#2*8 + add x23,x23,x17 // h+=Sigma0(a) + ror x16,x27,#14 + add x22,x22,x28 // h+=K[i] + eor x11,x27,x27,ror#23 + and x17,x20,x27 + bic x28,x21,x27 + add x22,x22,x8 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x23,x24 // a^b, b^c in next round + eor x16,x16,x11,ror#18 // Sigma1(e) + ror x11,x23,#28 + add x22,x22,x17 // h+=Ch(e,f,g) + eor x17,x23,x23,ror#5 + add x22,x22,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x26,x26,x22 // d+=h + eor x19,x19,x24 // Maj(a,b,c) + eor x17,x11,x17,ror#34 // Sigma0(a) + add x22,x22,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x22,x22,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x9,x9 // 6 +#endif + add x22,x22,x17 // h+=Sigma0(a) + ror x16,x26,#14 + add x21,x21,x19 // h+=K[i] + eor x12,x26,x26,ror#23 + and x17,x27,x26 + bic x19,x20,x26 + add x21,x21,x9 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x22,x23 // a^b, b^c in next round + eor x16,x16,x12,ror#18 // Sigma1(e) + ror x12,x22,#28 + add x21,x21,x17 // h+=Ch(e,f,g) + eor x17,x22,x22,ror#5 + add x21,x21,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x25,x25,x21 // d+=h + eor x28,x28,x23 // Maj(a,b,c) + eor x17,x12,x17,ror#34 // Sigma0(a) + add x21,x21,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x21,x21,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x10,x10 // 7 +#endif + ldp x11,x12,[x1],#2*8 + add x21,x21,x17 // h+=Sigma0(a) + ror x16,x25,#14 + add x20,x20,x28 // h+=K[i] + eor x13,x25,x25,ror#23 + and x17,x26,x25 + bic x28,x27,x25 + add x20,x20,x10 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x21,x22 // a^b, b^c in next round + eor x16,x16,x13,ror#18 // Sigma1(e) + ror x13,x21,#28 + add x20,x20,x17 // h+=Ch(e,f,g) + eor x17,x21,x21,ror#5 + add x20,x20,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x24,x24,x20 // d+=h + eor x19,x19,x22 // Maj(a,b,c) + eor x17,x13,x17,ror#34 // Sigma0(a) + add x20,x20,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x20,x20,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x11,x11 // 8 +#endif + add x20,x20,x17 // h+=Sigma0(a) + ror x16,x24,#14 + add x27,x27,x19 // h+=K[i] + eor x14,x24,x24,ror#23 + and x17,x25,x24 + bic x19,x26,x24 + add x27,x27,x11 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x20,x21 // a^b, b^c in next round + eor x16,x16,x14,ror#18 // Sigma1(e) + ror x14,x20,#28 + add x27,x27,x17 // h+=Ch(e,f,g) + eor x17,x20,x20,ror#5 + add x27,x27,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x23,x23,x27 // d+=h + eor x28,x28,x21 // Maj(a,b,c) + eor x17,x14,x17,ror#34 // Sigma0(a) + add x27,x27,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x27,x27,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x12,x12 // 9 +#endif + ldp x13,x14,[x1],#2*8 + add x27,x27,x17 // h+=Sigma0(a) + ror x16,x23,#14 + add x26,x26,x28 // h+=K[i] + eor x15,x23,x23,ror#23 + and x17,x24,x23 + bic x28,x25,x23 + add x26,x26,x12 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x27,x20 // a^b, b^c in next round + eor x16,x16,x15,ror#18 // Sigma1(e) + ror x15,x27,#28 + add x26,x26,x17 // h+=Ch(e,f,g) + eor x17,x27,x27,ror#5 + add x26,x26,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x22,x22,x26 // d+=h + eor x19,x19,x20 // Maj(a,b,c) + eor x17,x15,x17,ror#34 // Sigma0(a) + add x26,x26,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x26,x26,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x13,x13 // 10 +#endif + add x26,x26,x17 // h+=Sigma0(a) + ror x16,x22,#14 + add x25,x25,x19 // h+=K[i] + eor x0,x22,x22,ror#23 + and x17,x23,x22 + bic x19,x24,x22 + add x25,x25,x13 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x26,x27 // a^b, b^c in next round + eor x16,x16,x0,ror#18 // Sigma1(e) + ror x0,x26,#28 + add x25,x25,x17 // h+=Ch(e,f,g) + eor x17,x26,x26,ror#5 + add x25,x25,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x21,x21,x25 // d+=h + eor x28,x28,x27 // Maj(a,b,c) + eor x17,x0,x17,ror#34 // Sigma0(a) + add x25,x25,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x25,x25,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x14,x14 // 11 +#endif + ldp x15,x0,[x1],#2*8 + add x25,x25,x17 // h+=Sigma0(a) + str x6,[sp,#24] + ror x16,x21,#14 + add x24,x24,x28 // h+=K[i] + eor x6,x21,x21,ror#23 + and x17,x22,x21 + bic x28,x23,x21 + add x24,x24,x14 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x25,x26 // a^b, b^c in next round + eor x16,x16,x6,ror#18 // Sigma1(e) + ror x6,x25,#28 + add x24,x24,x17 // h+=Ch(e,f,g) + eor x17,x25,x25,ror#5 + add x24,x24,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x20,x20,x24 // d+=h + eor x19,x19,x26 // Maj(a,b,c) + eor x17,x6,x17,ror#34 // Sigma0(a) + add x24,x24,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x24,x24,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x15,x15 // 12 +#endif + add x24,x24,x17 // h+=Sigma0(a) + str x7,[sp,#0] + ror x16,x20,#14 + add x23,x23,x19 // h+=K[i] + eor x7,x20,x20,ror#23 + and x17,x21,x20 + bic x19,x22,x20 + add x23,x23,x15 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x24,x25 // a^b, b^c in next round + eor x16,x16,x7,ror#18 // Sigma1(e) + ror x7,x24,#28 + add x23,x23,x17 // h+=Ch(e,f,g) + eor x17,x24,x24,ror#5 + add x23,x23,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x27,x27,x23 // d+=h + eor x28,x28,x25 // Maj(a,b,c) + eor x17,x7,x17,ror#34 // Sigma0(a) + add x23,x23,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x23,x23,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x0,x0 // 13 +#endif + ldp x1,x2,[x1] + add x23,x23,x17 // h+=Sigma0(a) + str x8,[sp,#8] + ror x16,x27,#14 + add x22,x22,x28 // h+=K[i] + eor x8,x27,x27,ror#23 + and x17,x20,x27 + bic x28,x21,x27 + add x22,x22,x0 // h+=X[i] + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x23,x24 // a^b, b^c in next round + eor x16,x16,x8,ror#18 // Sigma1(e) + ror x8,x23,#28 + add x22,x22,x17 // h+=Ch(e,f,g) + eor x17,x23,x23,ror#5 + add x22,x22,x16 // h+=Sigma1(e) + and x19,x19,x28 // (b^c)&=(a^b) + add x26,x26,x22 // d+=h + eor x19,x19,x24 // Maj(a,b,c) + eor x17,x8,x17,ror#34 // Sigma0(a) + add x22,x22,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + //add x22,x22,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x1,x1 // 14 +#endif + ldr x6,[sp,#24] + add x22,x22,x17 // h+=Sigma0(a) + str x9,[sp,#16] + ror x16,x26,#14 + add x21,x21,x19 // h+=K[i] + eor x9,x26,x26,ror#23 + and x17,x27,x26 + bic x19,x20,x26 + add x21,x21,x1 // h+=X[i] + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x22,x23 // a^b, b^c in next round + eor x16,x16,x9,ror#18 // Sigma1(e) + ror x9,x22,#28 + add x21,x21,x17 // h+=Ch(e,f,g) + eor x17,x22,x22,ror#5 + add x21,x21,x16 // h+=Sigma1(e) + and x28,x28,x19 // (b^c)&=(a^b) + add x25,x25,x21 // d+=h + eor x28,x28,x23 // Maj(a,b,c) + eor x17,x9,x17,ror#34 // Sigma0(a) + add x21,x21,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + //add x21,x21,x17 // h+=Sigma0(a) +#ifndef __AARCH64EB__ + rev x2,x2 // 15 +#endif + ldr x7,[sp,#0] + add x21,x21,x17 // h+=Sigma0(a) + str x10,[sp,#24] + ror x16,x25,#14 + add x20,x20,x28 // h+=K[i] + ror x9,x4,#1 + and x17,x26,x25 + ror x8,x1,#19 + bic x28,x27,x25 + ror x10,x21,#28 + add x20,x20,x2 // h+=X[i] + eor x16,x16,x25,ror#18 + eor x9,x9,x4,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x21,x22 // a^b, b^c in next round + eor x16,x16,x25,ror#41 // Sigma1(e) + eor x10,x10,x21,ror#34 + add x20,x20,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x8,x8,x1,ror#61 + eor x9,x9,x4,lsr#7 // sigma0(X[i+1]) + add x20,x20,x16 // h+=Sigma1(e) + eor x19,x19,x22 // Maj(a,b,c) + eor x17,x10,x21,ror#39 // Sigma0(a) + eor x8,x8,x1,lsr#6 // sigma1(X[i+14]) + add x3,x3,x12 + add x24,x24,x20 // d+=h + add x20,x20,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x3,x3,x9 + add x20,x20,x17 // h+=Sigma0(a) + add x3,x3,x8 +.Loop_16_xx: + ldr x8,[sp,#8] + str x11,[sp,#0] + ror x16,x24,#14 + add x27,x27,x19 // h+=K[i] + ror x10,x5,#1 + and x17,x25,x24 + ror x9,x2,#19 + bic x19,x26,x24 + ror x11,x20,#28 + add x27,x27,x3 // h+=X[i] + eor x16,x16,x24,ror#18 + eor x10,x10,x5,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x20,x21 // a^b, b^c in next round + eor x16,x16,x24,ror#41 // Sigma1(e) + eor x11,x11,x20,ror#34 + add x27,x27,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x9,x9,x2,ror#61 + eor x10,x10,x5,lsr#7 // sigma0(X[i+1]) + add x27,x27,x16 // h+=Sigma1(e) + eor x28,x28,x21 // Maj(a,b,c) + eor x17,x11,x20,ror#39 // Sigma0(a) + eor x9,x9,x2,lsr#6 // sigma1(X[i+14]) + add x4,x4,x13 + add x23,x23,x27 // d+=h + add x27,x27,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x4,x4,x10 + add x27,x27,x17 // h+=Sigma0(a) + add x4,x4,x9 + ldr x9,[sp,#16] + str x12,[sp,#8] + ror x16,x23,#14 + add x26,x26,x28 // h+=K[i] + ror x11,x6,#1 + and x17,x24,x23 + ror x10,x3,#19 + bic x28,x25,x23 + ror x12,x27,#28 + add x26,x26,x4 // h+=X[i] + eor x16,x16,x23,ror#18 + eor x11,x11,x6,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x27,x20 // a^b, b^c in next round + eor x16,x16,x23,ror#41 // Sigma1(e) + eor x12,x12,x27,ror#34 + add x26,x26,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x10,x10,x3,ror#61 + eor x11,x11,x6,lsr#7 // sigma0(X[i+1]) + add x26,x26,x16 // h+=Sigma1(e) + eor x19,x19,x20 // Maj(a,b,c) + eor x17,x12,x27,ror#39 // Sigma0(a) + eor x10,x10,x3,lsr#6 // sigma1(X[i+14]) + add x5,x5,x14 + add x22,x22,x26 // d+=h + add x26,x26,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x5,x5,x11 + add x26,x26,x17 // h+=Sigma0(a) + add x5,x5,x10 + ldr x10,[sp,#24] + str x13,[sp,#16] + ror x16,x22,#14 + add x25,x25,x19 // h+=K[i] + ror x12,x7,#1 + and x17,x23,x22 + ror x11,x4,#19 + bic x19,x24,x22 + ror x13,x26,#28 + add x25,x25,x5 // h+=X[i] + eor x16,x16,x22,ror#18 + eor x12,x12,x7,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x26,x27 // a^b, b^c in next round + eor x16,x16,x22,ror#41 // Sigma1(e) + eor x13,x13,x26,ror#34 + add x25,x25,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x11,x11,x4,ror#61 + eor x12,x12,x7,lsr#7 // sigma0(X[i+1]) + add x25,x25,x16 // h+=Sigma1(e) + eor x28,x28,x27 // Maj(a,b,c) + eor x17,x13,x26,ror#39 // Sigma0(a) + eor x11,x11,x4,lsr#6 // sigma1(X[i+14]) + add x6,x6,x15 + add x21,x21,x25 // d+=h + add x25,x25,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x6,x6,x12 + add x25,x25,x17 // h+=Sigma0(a) + add x6,x6,x11 + ldr x11,[sp,#0] + str x14,[sp,#24] + ror x16,x21,#14 + add x24,x24,x28 // h+=K[i] + ror x13,x8,#1 + and x17,x22,x21 + ror x12,x5,#19 + bic x28,x23,x21 + ror x14,x25,#28 + add x24,x24,x6 // h+=X[i] + eor x16,x16,x21,ror#18 + eor x13,x13,x8,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x25,x26 // a^b, b^c in next round + eor x16,x16,x21,ror#41 // Sigma1(e) + eor x14,x14,x25,ror#34 + add x24,x24,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x12,x12,x5,ror#61 + eor x13,x13,x8,lsr#7 // sigma0(X[i+1]) + add x24,x24,x16 // h+=Sigma1(e) + eor x19,x19,x26 // Maj(a,b,c) + eor x17,x14,x25,ror#39 // Sigma0(a) + eor x12,x12,x5,lsr#6 // sigma1(X[i+14]) + add x7,x7,x0 + add x20,x20,x24 // d+=h + add x24,x24,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x7,x7,x13 + add x24,x24,x17 // h+=Sigma0(a) + add x7,x7,x12 + ldr x12,[sp,#8] + str x15,[sp,#0] + ror x16,x20,#14 + add x23,x23,x19 // h+=K[i] + ror x14,x9,#1 + and x17,x21,x20 + ror x13,x6,#19 + bic x19,x22,x20 + ror x15,x24,#28 + add x23,x23,x7 // h+=X[i] + eor x16,x16,x20,ror#18 + eor x14,x14,x9,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x24,x25 // a^b, b^c in next round + eor x16,x16,x20,ror#41 // Sigma1(e) + eor x15,x15,x24,ror#34 + add x23,x23,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x13,x13,x6,ror#61 + eor x14,x14,x9,lsr#7 // sigma0(X[i+1]) + add x23,x23,x16 // h+=Sigma1(e) + eor x28,x28,x25 // Maj(a,b,c) + eor x17,x15,x24,ror#39 // Sigma0(a) + eor x13,x13,x6,lsr#6 // sigma1(X[i+14]) + add x8,x8,x1 + add x27,x27,x23 // d+=h + add x23,x23,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x8,x8,x14 + add x23,x23,x17 // h+=Sigma0(a) + add x8,x8,x13 + ldr x13,[sp,#16] + str x0,[sp,#8] + ror x16,x27,#14 + add x22,x22,x28 // h+=K[i] + ror x15,x10,#1 + and x17,x20,x27 + ror x14,x7,#19 + bic x28,x21,x27 + ror x0,x23,#28 + add x22,x22,x8 // h+=X[i] + eor x16,x16,x27,ror#18 + eor x15,x15,x10,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x23,x24 // a^b, b^c in next round + eor x16,x16,x27,ror#41 // Sigma1(e) + eor x0,x0,x23,ror#34 + add x22,x22,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x14,x14,x7,ror#61 + eor x15,x15,x10,lsr#7 // sigma0(X[i+1]) + add x22,x22,x16 // h+=Sigma1(e) + eor x19,x19,x24 // Maj(a,b,c) + eor x17,x0,x23,ror#39 // Sigma0(a) + eor x14,x14,x7,lsr#6 // sigma1(X[i+14]) + add x9,x9,x2 + add x26,x26,x22 // d+=h + add x22,x22,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x9,x9,x15 + add x22,x22,x17 // h+=Sigma0(a) + add x9,x9,x14 + ldr x14,[sp,#24] + str x1,[sp,#16] + ror x16,x26,#14 + add x21,x21,x19 // h+=K[i] + ror x0,x11,#1 + and x17,x27,x26 + ror x15,x8,#19 + bic x19,x20,x26 + ror x1,x22,#28 + add x21,x21,x9 // h+=X[i] + eor x16,x16,x26,ror#18 + eor x0,x0,x11,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x22,x23 // a^b, b^c in next round + eor x16,x16,x26,ror#41 // Sigma1(e) + eor x1,x1,x22,ror#34 + add x21,x21,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x15,x15,x8,ror#61 + eor x0,x0,x11,lsr#7 // sigma0(X[i+1]) + add x21,x21,x16 // h+=Sigma1(e) + eor x28,x28,x23 // Maj(a,b,c) + eor x17,x1,x22,ror#39 // Sigma0(a) + eor x15,x15,x8,lsr#6 // sigma1(X[i+14]) + add x10,x10,x3 + add x25,x25,x21 // d+=h + add x21,x21,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x10,x10,x0 + add x21,x21,x17 // h+=Sigma0(a) + add x10,x10,x15 + ldr x15,[sp,#0] + str x2,[sp,#24] + ror x16,x25,#14 + add x20,x20,x28 // h+=K[i] + ror x1,x12,#1 + and x17,x26,x25 + ror x0,x9,#19 + bic x28,x27,x25 + ror x2,x21,#28 + add x20,x20,x10 // h+=X[i] + eor x16,x16,x25,ror#18 + eor x1,x1,x12,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x21,x22 // a^b, b^c in next round + eor x16,x16,x25,ror#41 // Sigma1(e) + eor x2,x2,x21,ror#34 + add x20,x20,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x0,x0,x9,ror#61 + eor x1,x1,x12,lsr#7 // sigma0(X[i+1]) + add x20,x20,x16 // h+=Sigma1(e) + eor x19,x19,x22 // Maj(a,b,c) + eor x17,x2,x21,ror#39 // Sigma0(a) + eor x0,x0,x9,lsr#6 // sigma1(X[i+14]) + add x11,x11,x4 + add x24,x24,x20 // d+=h + add x20,x20,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x11,x11,x1 + add x20,x20,x17 // h+=Sigma0(a) + add x11,x11,x0 + ldr x0,[sp,#8] + str x3,[sp,#0] + ror x16,x24,#14 + add x27,x27,x19 // h+=K[i] + ror x2,x13,#1 + and x17,x25,x24 + ror x1,x10,#19 + bic x19,x26,x24 + ror x3,x20,#28 + add x27,x27,x11 // h+=X[i] + eor x16,x16,x24,ror#18 + eor x2,x2,x13,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x20,x21 // a^b, b^c in next round + eor x16,x16,x24,ror#41 // Sigma1(e) + eor x3,x3,x20,ror#34 + add x27,x27,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x1,x1,x10,ror#61 + eor x2,x2,x13,lsr#7 // sigma0(X[i+1]) + add x27,x27,x16 // h+=Sigma1(e) + eor x28,x28,x21 // Maj(a,b,c) + eor x17,x3,x20,ror#39 // Sigma0(a) + eor x1,x1,x10,lsr#6 // sigma1(X[i+14]) + add x12,x12,x5 + add x23,x23,x27 // d+=h + add x27,x27,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x12,x12,x2 + add x27,x27,x17 // h+=Sigma0(a) + add x12,x12,x1 + ldr x1,[sp,#16] + str x4,[sp,#8] + ror x16,x23,#14 + add x26,x26,x28 // h+=K[i] + ror x3,x14,#1 + and x17,x24,x23 + ror x2,x11,#19 + bic x28,x25,x23 + ror x4,x27,#28 + add x26,x26,x12 // h+=X[i] + eor x16,x16,x23,ror#18 + eor x3,x3,x14,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x27,x20 // a^b, b^c in next round + eor x16,x16,x23,ror#41 // Sigma1(e) + eor x4,x4,x27,ror#34 + add x26,x26,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x2,x2,x11,ror#61 + eor x3,x3,x14,lsr#7 // sigma0(X[i+1]) + add x26,x26,x16 // h+=Sigma1(e) + eor x19,x19,x20 // Maj(a,b,c) + eor x17,x4,x27,ror#39 // Sigma0(a) + eor x2,x2,x11,lsr#6 // sigma1(X[i+14]) + add x13,x13,x6 + add x22,x22,x26 // d+=h + add x26,x26,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x13,x13,x3 + add x26,x26,x17 // h+=Sigma0(a) + add x13,x13,x2 + ldr x2,[sp,#24] + str x5,[sp,#16] + ror x16,x22,#14 + add x25,x25,x19 // h+=K[i] + ror x4,x15,#1 + and x17,x23,x22 + ror x3,x12,#19 + bic x19,x24,x22 + ror x5,x26,#28 + add x25,x25,x13 // h+=X[i] + eor x16,x16,x22,ror#18 + eor x4,x4,x15,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x26,x27 // a^b, b^c in next round + eor x16,x16,x22,ror#41 // Sigma1(e) + eor x5,x5,x26,ror#34 + add x25,x25,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x3,x3,x12,ror#61 + eor x4,x4,x15,lsr#7 // sigma0(X[i+1]) + add x25,x25,x16 // h+=Sigma1(e) + eor x28,x28,x27 // Maj(a,b,c) + eor x17,x5,x26,ror#39 // Sigma0(a) + eor x3,x3,x12,lsr#6 // sigma1(X[i+14]) + add x14,x14,x7 + add x21,x21,x25 // d+=h + add x25,x25,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x14,x14,x4 + add x25,x25,x17 // h+=Sigma0(a) + add x14,x14,x3 + ldr x3,[sp,#0] + str x6,[sp,#24] + ror x16,x21,#14 + add x24,x24,x28 // h+=K[i] + ror x5,x0,#1 + and x17,x22,x21 + ror x4,x13,#19 + bic x28,x23,x21 + ror x6,x25,#28 + add x24,x24,x14 // h+=X[i] + eor x16,x16,x21,ror#18 + eor x5,x5,x0,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x25,x26 // a^b, b^c in next round + eor x16,x16,x21,ror#41 // Sigma1(e) + eor x6,x6,x25,ror#34 + add x24,x24,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x4,x4,x13,ror#61 + eor x5,x5,x0,lsr#7 // sigma0(X[i+1]) + add x24,x24,x16 // h+=Sigma1(e) + eor x19,x19,x26 // Maj(a,b,c) + eor x17,x6,x25,ror#39 // Sigma0(a) + eor x4,x4,x13,lsr#6 // sigma1(X[i+14]) + add x15,x15,x8 + add x20,x20,x24 // d+=h + add x24,x24,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x15,x15,x5 + add x24,x24,x17 // h+=Sigma0(a) + add x15,x15,x4 + ldr x4,[sp,#8] + str x7,[sp,#0] + ror x16,x20,#14 + add x23,x23,x19 // h+=K[i] + ror x6,x1,#1 + and x17,x21,x20 + ror x5,x14,#19 + bic x19,x22,x20 + ror x7,x24,#28 + add x23,x23,x15 // h+=X[i] + eor x16,x16,x20,ror#18 + eor x6,x6,x1,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x24,x25 // a^b, b^c in next round + eor x16,x16,x20,ror#41 // Sigma1(e) + eor x7,x7,x24,ror#34 + add x23,x23,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x5,x5,x14,ror#61 + eor x6,x6,x1,lsr#7 // sigma0(X[i+1]) + add x23,x23,x16 // h+=Sigma1(e) + eor x28,x28,x25 // Maj(a,b,c) + eor x17,x7,x24,ror#39 // Sigma0(a) + eor x5,x5,x14,lsr#6 // sigma1(X[i+14]) + add x0,x0,x9 + add x27,x27,x23 // d+=h + add x23,x23,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x0,x0,x6 + add x23,x23,x17 // h+=Sigma0(a) + add x0,x0,x5 + ldr x5,[sp,#16] + str x8,[sp,#8] + ror x16,x27,#14 + add x22,x22,x28 // h+=K[i] + ror x7,x2,#1 + and x17,x20,x27 + ror x6,x15,#19 + bic x28,x21,x27 + ror x8,x23,#28 + add x22,x22,x0 // h+=X[i] + eor x16,x16,x27,ror#18 + eor x7,x7,x2,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x23,x24 // a^b, b^c in next round + eor x16,x16,x27,ror#41 // Sigma1(e) + eor x8,x8,x23,ror#34 + add x22,x22,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x6,x6,x15,ror#61 + eor x7,x7,x2,lsr#7 // sigma0(X[i+1]) + add x22,x22,x16 // h+=Sigma1(e) + eor x19,x19,x24 // Maj(a,b,c) + eor x17,x8,x23,ror#39 // Sigma0(a) + eor x6,x6,x15,lsr#6 // sigma1(X[i+14]) + add x1,x1,x10 + add x26,x26,x22 // d+=h + add x22,x22,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x1,x1,x7 + add x22,x22,x17 // h+=Sigma0(a) + add x1,x1,x6 + ldr x6,[sp,#24] + str x9,[sp,#16] + ror x16,x26,#14 + add x21,x21,x19 // h+=K[i] + ror x8,x3,#1 + and x17,x27,x26 + ror x7,x0,#19 + bic x19,x20,x26 + ror x9,x22,#28 + add x21,x21,x1 // h+=X[i] + eor x16,x16,x26,ror#18 + eor x8,x8,x3,ror#8 + orr x17,x17,x19 // Ch(e,f,g) + eor x19,x22,x23 // a^b, b^c in next round + eor x16,x16,x26,ror#41 // Sigma1(e) + eor x9,x9,x22,ror#34 + add x21,x21,x17 // h+=Ch(e,f,g) + and x28,x28,x19 // (b^c)&=(a^b) + eor x7,x7,x0,ror#61 + eor x8,x8,x3,lsr#7 // sigma0(X[i+1]) + add x21,x21,x16 // h+=Sigma1(e) + eor x28,x28,x23 // Maj(a,b,c) + eor x17,x9,x22,ror#39 // Sigma0(a) + eor x7,x7,x0,lsr#6 // sigma1(X[i+14]) + add x2,x2,x11 + add x25,x25,x21 // d+=h + add x21,x21,x28 // h+=Maj(a,b,c) + ldr x28,[x30],#8 // *K++, x19 in next round + add x2,x2,x8 + add x21,x21,x17 // h+=Sigma0(a) + add x2,x2,x7 + ldr x7,[sp,#0] + str x10,[sp,#24] + ror x16,x25,#14 + add x20,x20,x28 // h+=K[i] + ror x9,x4,#1 + and x17,x26,x25 + ror x8,x1,#19 + bic x28,x27,x25 + ror x10,x21,#28 + add x20,x20,x2 // h+=X[i] + eor x16,x16,x25,ror#18 + eor x9,x9,x4,ror#8 + orr x17,x17,x28 // Ch(e,f,g) + eor x28,x21,x22 // a^b, b^c in next round + eor x16,x16,x25,ror#41 // Sigma1(e) + eor x10,x10,x21,ror#34 + add x20,x20,x17 // h+=Ch(e,f,g) + and x19,x19,x28 // (b^c)&=(a^b) + eor x8,x8,x1,ror#61 + eor x9,x9,x4,lsr#7 // sigma0(X[i+1]) + add x20,x20,x16 // h+=Sigma1(e) + eor x19,x19,x22 // Maj(a,b,c) + eor x17,x10,x21,ror#39 // Sigma0(a) + eor x8,x8,x1,lsr#6 // sigma1(X[i+14]) + add x3,x3,x12 + add x24,x24,x20 // d+=h + add x20,x20,x19 // h+=Maj(a,b,c) + ldr x19,[x30],#8 // *K++, x28 in next round + add x3,x3,x9 + add x20,x20,x17 // h+=Sigma0(a) + add x3,x3,x8 + cbnz x19,.Loop_16_xx + + ldp x0,x2,[x29,#96] + ldr x1,[x29,#112] + sub x30,x30,#648 // rewind + + ldp x3,x4,[x0] + ldp x5,x6,[x0,#2*8] + add x1,x1,#14*8 // advance input pointer + ldp x7,x8,[x0,#4*8] + add x20,x20,x3 + ldp x9,x10,[x0,#6*8] + add x21,x21,x4 + add x22,x22,x5 + add x23,x23,x6 + stp x20,x21,[x0] + add x24,x24,x7 + add x25,x25,x8 + stp x22,x23,[x0,#2*8] + add x26,x26,x9 + add x27,x27,x10 + cmp x1,x2 + stp x24,x25,[x0,#4*8] + stp x26,x27,[x0,#6*8] + b.ne .Loop + + ldp x19,x20,[x29,#16] + add sp,sp,#4*8 + ldp x21,x22,[x29,#32] + ldp x23,x24,[x29,#48] + ldp x25,x26,[x29,#64] + ldp x27,x28,[x29,#80] + ldp x29,x30,[sp],#128 + ret +.size sha512_block_data_order,.-sha512_block_data_order + +.align 6 +.type .LK512,%object +.LK512: + .quad 0x428a2f98d728ae22,0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538,0x59f111f1b605d019 + .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242,0x12835b0145706fbe + .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235,0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 + .quad 0x983e5152ee66dfab,0xa831c66d2db43210 + .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 + .quad 0x06ca6351e003826f,0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df + .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6,0x92722c851482353b + .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 + .quad 0xd192e819d6ef5218,0xd69906245565a910 + .quad 0xf40e35855771202a,0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec + .quad 0x90befffa23631e28,0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b + .quad 0xca273eceea26619c,0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae,0x1b710b35131c471b + .quad 0x28db77f523047d84,0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 + .quad 0 // terminator +.size .LK512,.-.LK512 +#ifndef __KERNEL__ +.align 3 +.LOPENSSL_armcap_P: +# ifdef __ILP32__ + .long OPENSSL_armcap_P-. +# else + .quad OPENSSL_armcap_P-. +# endif +#endif +.asciz "SHA512 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>" +.align 2 +#ifndef __KERNEL__ +.comm OPENSSL_armcap_P,4,4 +#endif diff --git a/arch/arm64/crypto/sha512-glue.c b/arch/arm64/crypto/sha512-glue.c new file mode 100644 index 000000000000..aff35c9992a4 --- /dev/null +++ b/arch/arm64/crypto/sha512-glue.c @@ -0,0 +1,94 @@ +/* + * Linux/arm64 port of the OpenSSL SHA512 implementation for AArch64 + * + * 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 as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <crypto/internal/hash.h> +#include <linux/cryptohash.h> +#include <linux/types.h> +#include <linux/string.h> +#include <crypto/sha.h> +#include <crypto/sha512_base.h> +#include <asm/neon.h> + +MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64"); +MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>"); +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha384"); +MODULE_ALIAS_CRYPTO("sha512"); + +asmlinkage void sha512_block_data_order(u32 *digest, const void *data, + unsigned int num_blks); + +static int sha512_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + return sha512_base_do_update(desc, data, len, + (sha512_block_fn *)sha512_block_data_order); +} + +static int sha512_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + if (len) + sha512_base_do_update(desc, data, len, + (sha512_block_fn *)sha512_block_data_order); + sha512_base_do_finalize(desc, + (sha512_block_fn *)sha512_block_data_order); + + return sha512_base_finish(desc, out); +} + +static int sha512_final(struct shash_desc *desc, u8 *out) +{ + return sha512_finup(desc, NULL, 0, out); +} + +static struct shash_alg algs[] = { { + .digestsize = SHA512_DIGEST_SIZE, + .init = sha512_base_init, + .update = sha512_update, + .final = sha512_final, + .finup = sha512_finup, + .descsize = sizeof(struct sha512_state), + .base.cra_name = "sha512", + .base.cra_driver_name = "sha512-arm64", + .base.cra_priority = 150, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA512_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +}, { + .digestsize = SHA384_DIGEST_SIZE, + .init = sha384_base_init, + .update = sha512_update, + .final = sha512_final, + .finup = sha512_finup, + .descsize = sizeof(struct sha512_state), + .base.cra_name = "sha384", + .base.cra_driver_name = "sha384-arm64", + .base.cra_priority = 150, + .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, + .base.cra_blocksize = SHA384_BLOCK_SIZE, + .base.cra_module = THIS_MODULE, +} }; + +static int __init sha512_mod_init(void) +{ + return crypto_register_shashes(algs, ARRAY_SIZE(algs)); +} + +static void __exit sha512_mod_fini(void) +{ + crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); +} + +module_init(sha512_mod_init); +module_exit(sha512_mod_fini); diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index f43d2c44c765..8365a84c2640 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -1,8 +1,6 @@ -generic-y += bug.h generic-y += bugs.h generic-y += clkdev.h generic-y += cputime.h -generic-y += current.h generic-y += delay.h generic-y += div64.h generic-y += dma.h @@ -10,7 +8,6 @@ generic-y += dma-contiguous.h generic-y += early_ioremap.h generic-y += emergency-restart.h generic-y += errno.h -generic-y += ftrace.h generic-y += hw_irq.h generic-y += ioctl.h generic-y += ioctls.h @@ -26,13 +23,10 @@ generic-y += mm-arch-hooks.h generic-y += mman.h generic-y += msgbuf.h generic-y += msi.h -generic-y += mutex.h -generic-y += pci.h generic-y += poll.h generic-y += preempt.h generic-y += resource.h generic-y += rwsem.h -generic-y += sections.h generic-y += segment.h generic-y += sembuf.h generic-y += serial.h @@ -45,7 +39,6 @@ generic-y += swab.h generic-y += switch_to.h generic-y += termbits.h generic-y += termios.h -generic-y += topology.h generic-y += trace_clock.h generic-y += types.h generic-y += unaligned.h diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 5420cb0fcb3e..c1976c0adca7 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -12,11 +12,12 @@ #ifndef _ASM_ACPI_H #define _ASM_ACPI_H -#include <linux/mm.h> +#include <linux/memblock.h> #include <linux/psci.h> #include <asm/cputype.h> #include <asm/smp_plat.h> +#include <asm/tlbflush.h> /* Macros for consistency checks of the GICC subtable of MADT */ #define ACPI_MADT_GICC_LENGTH \ @@ -28,11 +29,15 @@ /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI -/* ACPI table mapping after acpi_gbl_permanent_mmap is set */ +/* ACPI table mapping after acpi_permanent_mmap is set */ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) { - if (!page_is_ram(phys >> PAGE_SHIFT)) + /* + * EFI's reserve_regions() call adds memory with the WB attribute + * to memblock via early_init_dt_add_memory_arch(). + */ + if (!memblock_is_memory(phys)) return ioremap(phys, size); return ioremap_cache(phys, size); @@ -110,8 +115,28 @@ static inline const char *acpi_get_enable_method(int cpu) } #ifdef CONFIG_ACPI_APEI +/* + * acpi_disable_cmcff is used in drivers/acpi/apei/hest.c for disabling + * IA-32 Architecture Corrected Machine Check (CMC) Firmware-First mode + * with a kernel command line parameter "acpi=nocmcoff". But we don't + * have this IA-32 specific feature on ARM64, this definition is only + * for compatibility. + */ +#define acpi_disable_cmcff 1 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr); -#endif + +/* + * Despite its name, this function must still broadcast the TLB + * invalidation in order to ensure other CPUs don't end up with junk + * entries as a result of speculation. Unusually, its also called in + * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for + * TLB broadcasting, then we're in trouble here. + */ +static inline void arch_apei_flush_tlb_one(unsigned long addr) +{ + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); +} +#endif /* CONFIG_ACPI_APEI */ #ifdef CONFIG_ACPI_NUMA int arm64_acpi_numa_init(void); diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 8746ff6abd77..6e1cb8c5af4d 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -1,12 +1,12 @@ #ifndef __ASM_ALTERNATIVE_H #define __ASM_ALTERNATIVE_H -#include <asm/cpufeature.h> +#include <asm/cpucaps.h> +#include <asm/insn.h> #ifndef __ASSEMBLY__ #include <linux/init.h> -#include <linux/kconfig.h> #include <linux/types.h> #include <linux/stddef.h> #include <linux/stringify.h> @@ -90,34 +90,55 @@ void apply_alternatives(void *start, size_t length); .endm /* - * Begin an alternative code sequence. + * Alternative sequences + * + * The code for the case where the capability is not present will be + * assembled and linked as normal. There are no restrictions on this + * code. + * + * The code for the case where the capability is present will be + * assembled into a special section to be used for dynamic patching. + * Code for that case must: + * + * 1. Be exactly the same length (in bytes) as the default code + * sequence. * - * The code that follows this macro will be assembled and linked as - * normal. There are no restrictions on this code. + * 2. Not contain a branch target that is used outside of the + * alternative sequence it is defined in (branches into an + * alternative sequence are not fixed up). + */ + +/* + * Begin an alternative code sequence. */ .macro alternative_if_not cap + .set .Lasm_alt_mode, 0 .pushsection .altinstructions, "a" altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f .popsection 661: .endm +.macro alternative_if cap + .set .Lasm_alt_mode, 1 + .pushsection .altinstructions, "a" + altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f + .popsection + .pushsection .altinstr_replacement, "ax" + .align 2 /* So GAS knows label 661 is suitably aligned */ +661: +.endm + /* - * Provide the alternative code sequence. - * - * The code that follows this macro is assembled into a special - * section to be used for dynamic patching. Code that follows this - * macro must: - * - * 1. Be exactly the same length (in bytes) as the default code - * sequence. - * - * 2. Not contain a branch target that is used outside of the - * alternative sequence it is defined in (branches into an - * alternative sequence are not fixed up). + * Provide the other half of the alternative code sequence. */ .macro alternative_else -662: .pushsection .altinstr_replacement, "ax" +662: + .if .Lasm_alt_mode==0 + .pushsection .altinstr_replacement, "ax" + .else + .popsection + .endif 663: .endm @@ -125,11 +146,25 @@ void apply_alternatives(void *start, size_t length); * Complete an alternative code sequence. */ .macro alternative_endif -664: .popsection +664: + .if .Lasm_alt_mode==0 + .popsection + .endif .org . - (664b-663b) + (662b-661b) .org . - (662b-661b) + (664b-663b) .endm +/* + * Provides a trivial alternative or default sequence consisting solely + * of NOPs. The number of NOPs is chosen automatically to match the + * previous case. + */ +.macro alternative_else_nop_endif +alternative_else + nops (662b-661b) / AARCH64_INSN_SIZE +alternative_endif +.endm + #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \ alternative_insn insn1, insn2, cap, IS_ENABLED(cfg) diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h index 8ec88e5b290f..f37e3a21f6e7 100644 --- a/arch/arm64/include/asm/arch_gicv3.h +++ b/arch/arm64/include/asm/arch_gicv3.h @@ -28,6 +28,7 @@ #define ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4) #define ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5) #define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7) +#define ICC_BPR1_EL1 sys_reg(3, 0, 12, 12, 3) #define ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) @@ -78,6 +79,10 @@ #include <linux/stringify.h> #include <asm/barrier.h> +#include <asm/cacheflush.h> + +#define read_gicreg read_sysreg_s +#define write_gicreg write_sysreg_s /* * Low-level accessors @@ -88,13 +93,13 @@ static inline void gic_write_eoir(u32 irq) { - asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq)); + write_sysreg_s(irq, ICC_EOIR1_EL1); isb(); } static inline void gic_write_dir(u32 irq) { - asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq)); + write_sysreg_s(irq, ICC_DIR_EL1); isb(); } @@ -102,7 +107,7 @@ static inline u64 gic_read_iar_common(void) { u64 irqstat; - asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat)); + irqstat = read_sysreg_s(ICC_IAR1_EL1); dsb(sy); return irqstat; } @@ -118,12 +123,9 @@ static inline u64 gic_read_iar_cavium_thunderx(void) { u64 irqstat; - asm volatile( - "nop;nop;nop;nop\n\t" - "nop;nop;nop;nop\n\t" - "mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t" - "nop;nop;nop;nop" - : "=r" (irqstat)); + nops(8); + irqstat = read_sysreg_s(ICC_IAR1_EL1); + nops(4); mb(); return irqstat; @@ -131,42 +133,60 @@ static inline u64 gic_read_iar_cavium_thunderx(void) static inline void gic_write_pmr(u32 val) { - asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val)); + write_sysreg_s(val, ICC_PMR_EL1); } static inline void gic_write_ctlr(u32 val) { - asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val)); + write_sysreg_s(val, ICC_CTLR_EL1); isb(); } static inline void gic_write_grpen1(u32 val) { - asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val)); + write_sysreg_s(val, ICC_GRPEN1_EL1); isb(); } static inline void gic_write_sgi1r(u64 val) { - asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val)); + write_sysreg_s(val, ICC_SGI1R_EL1); } static inline u32 gic_read_sre(void) { - u64 val; - - asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val)); - return val; + return read_sysreg_s(ICC_SRE_EL1); } static inline void gic_write_sre(u32 val) { - asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val)); + write_sysreg_s(val, ICC_SRE_EL1); isb(); } +static inline void gic_write_bpr1(u32 val) +{ + asm volatile("msr_s " __stringify(ICC_BPR1_EL1) ", %0" : : "r" (val)); +} + #define gic_read_typer(c) readq_relaxed(c) #define gic_write_irouter(v, c) writeq_relaxed(v, c) +#define gic_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) + +#define gits_read_baser(c) readq_relaxed(c) +#define gits_write_baser(v, c) writeq_relaxed(v, c) + +#define gits_read_cbaser(c) readq_relaxed(c) +#define gits_write_cbaser(v, c) writeq_relaxed(v, c) + +#define gits_write_cwriter(v, c) writeq_relaxed(v, c) + +#define gicr_read_propbaser(c) readq_relaxed(c) +#define gicr_write_propbaser(v, c) writeq_relaxed(v, c) + +#define gicr_write_pendbaser(v, c) writeq_relaxed(v, c) +#define gicr_read_pendbaser(c) readq_relaxed(c) + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARCH_GICV3_H */ diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index fbe0ca31a99c..eaa5bbe3fa87 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -20,13 +20,55 @@ #define __ASM_ARCH_TIMER_H #include <asm/barrier.h> +#include <asm/sysreg.h> #include <linux/bug.h> #include <linux/init.h> +#include <linux/jump_label.h> #include <linux/types.h> #include <clocksource/arm_arch_timer.h> +#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) +extern struct static_key_false arch_timer_read_ool_enabled; +#define needs_fsl_a008585_workaround() \ + static_branch_unlikely(&arch_timer_read_ool_enabled) +#else +#define needs_fsl_a008585_workaround() false +#endif + +u32 __fsl_a008585_read_cntp_tval_el0(void); +u32 __fsl_a008585_read_cntv_tval_el0(void); +u64 __fsl_a008585_read_cntvct_el0(void); + +/* + * The number of retries is an arbitrary value well beyond the highest number + * of iterations the loop has been observed to take. + */ +#define __fsl_a008585_read_reg(reg) ({ \ + u64 _old, _new; \ + int _retries = 200; \ + \ + do { \ + _old = read_sysreg(reg); \ + _new = read_sysreg(reg); \ + _retries--; \ + } while (unlikely(_old != _new) && _retries); \ + \ + WARN_ON_ONCE(!_retries); \ + _new; \ +}) + +#define arch_timer_reg_read_stable(reg) \ +({ \ + u64 _val; \ + if (needs_fsl_a008585_workaround()) \ + _val = __fsl_a008585_read_##reg(); \ + else \ + _val = read_sysreg(reg); \ + _val; \ +}) + /* * These register accessors are marked inline so the compiler can * nicely work out which register we want, and chuck away the rest of @@ -38,19 +80,19 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: - asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); + write_sysreg(val, cntp_ctl_el0); break; case ARCH_TIMER_REG_TVAL: - asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); + write_sysreg(val, cntp_tval_el0); break; } } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: - asm volatile("msr cntv_ctl_el0, %0" : : "r" (val)); + write_sysreg(val, cntv_ctl_el0); break; case ARCH_TIMER_REG_TVAL: - asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); + write_sysreg(val, cntv_tval_el0); break; } } @@ -61,48 +103,38 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) static __always_inline u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) { - u32 val; - if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: - asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val)); - break; + return read_sysreg(cntp_ctl_el0); case ARCH_TIMER_REG_TVAL: - asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); - break; + return arch_timer_reg_read_stable(cntp_tval_el0); } } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: - asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val)); - break; + return read_sysreg(cntv_ctl_el0); case ARCH_TIMER_REG_TVAL: - asm volatile("mrs %0, cntv_tval_el0" : "=r" (val)); - break; + return arch_timer_reg_read_stable(cntv_tval_el0); } } - return val; + BUG(); } static inline u32 arch_timer_get_cntfrq(void) { - u32 val; - asm volatile("mrs %0, cntfrq_el0" : "=r" (val)); - return val; + return read_sysreg(cntfrq_el0); } static inline u32 arch_timer_get_cntkctl(void) { - u32 cntkctl; - asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); - return cntkctl; + return read_sysreg(cntkctl_el1); } static inline void arch_timer_set_cntkctl(u32 cntkctl) { - asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); + write_sysreg(cntkctl, cntkctl_el1); } static inline u64 arch_counter_get_cntpct(void) @@ -116,12 +148,8 @@ static inline u64 arch_counter_get_cntpct(void) static inline u64 arch_counter_get_cntvct(void) { - u64 cval; - isb(); - asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); - - return cval; + return arch_timer_reg_read_stable(cntvct_el0); } static inline int arch_timer_arch_init(void) diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h new file mode 100644 index 000000000000..df411f3e083c --- /dev/null +++ b/arch/arm64/include/asm/asm-uaccess.h @@ -0,0 +1,65 @@ +#ifndef __ASM_ASM_UACCESS_H +#define __ASM_ASM_UACCESS_H + +#include <asm/alternative.h> +#include <asm/kernel-pgtable.h> +#include <asm/sysreg.h> +#include <asm/assembler.h> + +/* + * User access enabling/disabling macros. + */ +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + .macro __uaccess_ttbr0_disable, tmp1 + mrs \tmp1, ttbr1_el1 // swapper_pg_dir + add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir + msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 + isb + .endm + + .macro __uaccess_ttbr0_enable, tmp1 + get_thread_info \tmp1 + ldr \tmp1, [\tmp1, #TSK_TI_TTBR0] // load saved TTBR0_EL1 + msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1 + isb + .endm + + .macro uaccess_ttbr0_disable, tmp1 +alternative_if_not ARM64_HAS_PAN + __uaccess_ttbr0_disable \tmp1 +alternative_else_nop_endif + .endm + + .macro uaccess_ttbr0_enable, tmp1, tmp2 +alternative_if_not ARM64_HAS_PAN + save_and_disable_irq \tmp2 // avoid preemption + __uaccess_ttbr0_enable \tmp1 + restore_irq \tmp2 +alternative_else_nop_endif + .endm +#else + .macro uaccess_ttbr0_disable, tmp1 + .endm + + .macro uaccess_ttbr0_enable, tmp1, tmp2 + .endm +#endif + +/* + * These macros are no-ops when UAO is present. + */ + .macro uaccess_disable_not_uao, tmp1 + uaccess_ttbr0_disable \tmp1 +alternative_if ARM64_ALT_PAN_NOT_UAO + SET_PSTATE_PAN(1) +alternative_else_nop_endif + .endm + + .macro uaccess_enable_not_uao, tmp1, tmp2 + uaccess_ttbr0_enable \tmp1, \tmp2 +alternative_if ARM64_ALT_PAN_NOT_UAO + SET_PSTATE_PAN(0) +alternative_else_nop_endif + .endm + +#endif diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index d5025c69ca81..446f6c46d4b1 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -41,6 +41,15 @@ msr daifclr, #2 .endm + .macro save_and_disable_irq, flags + mrs \flags, daif + msr daifset, #2 + .endm + + .macro restore_irq, flags + msr daif, \flags + .endm + /* * Enable and disable debug exceptions. */ @@ -87,6 +96,15 @@ .endm /* + * NOP sequence + */ + .macro nops, num + .rept \num + nop + .endr + .endm + +/* * Emit an entry into the exception table */ .macro _asm_extable, from, to @@ -193,14 +211,25 @@ lr .req x30 // link register .endm /* + * @dst: Result of per_cpu(sym, smp_processor_id()) + * @sym: The name of the per-cpu variable + * @tmp: scratch register + */ + .macro adr_this_cpu, dst, sym, tmp + adr_l \dst, \sym + mrs \tmp, tpidr_el1 + add \dst, \dst, \tmp + .endm + + /* + * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id())) * @sym: The name of the per-cpu variable - * @reg: Result of per_cpu(sym, smp_processor_id()) * @tmp: scratch register */ - .macro this_cpu_ptr, sym, reg, tmp - adr_l \reg, \sym + .macro ldr_this_cpu dst, sym, tmp + adr_l \dst, \sym mrs \tmp, tpidr_el1 - add \reg, \reg, \tmp + ldr \dst, [\dst, \tmp] .endm /* @@ -216,11 +245,26 @@ lr .req x30 // link register .macro mmid, rd, rn ldr \rd, [\rn, #MM_CONTEXT_ID] .endm +/* + * read_ctr - read CTR_EL0. If the system has mismatched + * cache line sizes, provide the system wide safe value + * from arm64_ftr_reg_ctrel0.sys_val + */ + .macro read_ctr, reg +alternative_if_not ARM64_MISMATCHED_CACHE_LINE_SIZE + mrs \reg, ctr_el0 // read CTR + nop +alternative_else + ldr_l \reg, arm64_ftr_reg_ctrel0 + ARM64_FTR_SYSVAL +alternative_endif + .endm + /* - * dcache_line_size - get the minimum D-cache line size from the CTR register. + * raw_dcache_line_size - get the minimum D-cache line size on this CPU + * from the CTR register. */ - .macro dcache_line_size, reg, tmp + .macro raw_dcache_line_size, reg, tmp mrs \tmp, ctr_el0 // read CTR ubfm \tmp, \tmp, #16, #19 // cache line size encoding mov \reg, #4 // bytes per word @@ -228,9 +272,20 @@ lr .req x30 // link register .endm /* - * icache_line_size - get the minimum I-cache line size from the CTR register. + * dcache_line_size - get the safe D-cache line size across all CPUs */ - .macro icache_line_size, reg, tmp + .macro dcache_line_size, reg, tmp + read_ctr \tmp + ubfm \tmp, \tmp, #16, #19 // cache line size encoding + mov \reg, #4 // bytes per word + lsl \reg, \reg, \tmp // actual cache line size + .endm + +/* + * raw_icache_line_size - get the minimum I-cache line size on this CPU + * from the CTR register. + */ + .macro raw_icache_line_size, reg, tmp mrs \tmp, ctr_el0 // read CTR and \tmp, \tmp, #0xf // cache line size encoding mov \reg, #4 // bytes per word @@ -238,6 +293,16 @@ lr .req x30 // link register .endm /* + * icache_line_size - get the safe I-cache line size across all CPUs + */ + .macro icache_line_size, reg, tmp + read_ctr \tmp + and \tmp, \tmp, #0xf // cache line size encoding + mov \reg, #4 // bytes per word + lsl \reg, \reg, \tmp // actual cache line size + .endm + +/* * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map */ .macro tcr_set_idmap_t0sz, valreg, tmpreg @@ -350,4 +415,24 @@ alternative_endif movk \reg, :abs_g0_nc:\val .endm +/* + * Return the current thread_info. + */ + .macro get_thread_info, rd + mrs \rd, sp_el0 + .endm + +/* + * Errata workaround post TTBR0_EL1 update. + */ + .macro post_ttbr0_update_workaround +#ifdef CONFIG_CAVIUM_ERRATUM_27456 +alternative_if ARM64_WORKAROUND_CAVIUM_27456 + ic iallu + dsb nsh + isb +alternative_else_nop_endif +#endif + .endm + #endif /* __ASM_ASSEMBLER_H */ diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h index b5890be8f257..7457ce082b5f 100644 --- a/arch/arm64/include/asm/atomic_lse.h +++ b/arch/arm64/include/asm/atomic_lse.h @@ -86,8 +86,8 @@ static inline int atomic_add_return##name(int i, atomic_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC(add_return##name), \ + __LL_SC_ATOMIC(add_return##name) \ + __nops(1), \ /* LSE atomics */ \ " ldadd" #mb " %w[i], w30, %[v]\n" \ " add %w[i], %w[i], w30") \ @@ -112,8 +112,8 @@ static inline void atomic_and(int i, atomic_t *v) asm volatile(ARM64_LSE_ATOMIC_INSN( /* LL/SC */ - " nop\n" - __LL_SC_ATOMIC(and), + __LL_SC_ATOMIC(and) + __nops(1), /* LSE atomics */ " mvn %w[i], %w[i]\n" " stclr %w[i], %[v]") @@ -130,8 +130,8 @@ static inline int atomic_fetch_and##name(int i, atomic_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC(fetch_and##name), \ + __LL_SC_ATOMIC(fetch_and##name) \ + __nops(1), \ /* LSE atomics */ \ " mvn %w[i], %w[i]\n" \ " ldclr" #mb " %w[i], %w[i], %[v]") \ @@ -156,8 +156,8 @@ static inline void atomic_sub(int i, atomic_t *v) asm volatile(ARM64_LSE_ATOMIC_INSN( /* LL/SC */ - " nop\n" - __LL_SC_ATOMIC(sub), + __LL_SC_ATOMIC(sub) + __nops(1), /* LSE atomics */ " neg %w[i], %w[i]\n" " stadd %w[i], %[v]") @@ -174,9 +174,8 @@ static inline int atomic_sub_return##name(int i, atomic_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ __LL_SC_ATOMIC(sub_return##name) \ - " nop", \ + __nops(2), \ /* LSE atomics */ \ " neg %w[i], %w[i]\n" \ " ldadd" #mb " %w[i], w30, %[v]\n" \ @@ -203,8 +202,8 @@ static inline int atomic_fetch_sub##name(int i, atomic_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC(fetch_sub##name), \ + __LL_SC_ATOMIC(fetch_sub##name) \ + __nops(1), \ /* LSE atomics */ \ " neg %w[i], %w[i]\n" \ " ldadd" #mb " %w[i], %w[i], %[v]") \ @@ -284,8 +283,8 @@ static inline long atomic64_add_return##name(long i, atomic64_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC64(add_return##name), \ + __LL_SC_ATOMIC64(add_return##name) \ + __nops(1), \ /* LSE atomics */ \ " ldadd" #mb " %[i], x30, %[v]\n" \ " add %[i], %[i], x30") \ @@ -310,8 +309,8 @@ static inline void atomic64_and(long i, atomic64_t *v) asm volatile(ARM64_LSE_ATOMIC_INSN( /* LL/SC */ - " nop\n" - __LL_SC_ATOMIC64(and), + __LL_SC_ATOMIC64(and) + __nops(1), /* LSE atomics */ " mvn %[i], %[i]\n" " stclr %[i], %[v]") @@ -328,8 +327,8 @@ static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC64(fetch_and##name), \ + __LL_SC_ATOMIC64(fetch_and##name) \ + __nops(1), \ /* LSE atomics */ \ " mvn %[i], %[i]\n" \ " ldclr" #mb " %[i], %[i], %[v]") \ @@ -354,8 +353,8 @@ static inline void atomic64_sub(long i, atomic64_t *v) asm volatile(ARM64_LSE_ATOMIC_INSN( /* LL/SC */ - " nop\n" - __LL_SC_ATOMIC64(sub), + __LL_SC_ATOMIC64(sub) + __nops(1), /* LSE atomics */ " neg %[i], %[i]\n" " stadd %[i], %[v]") @@ -372,9 +371,8 @@ static inline long atomic64_sub_return##name(long i, atomic64_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ __LL_SC_ATOMIC64(sub_return##name) \ - " nop", \ + __nops(2), \ /* LSE atomics */ \ " neg %[i], %[i]\n" \ " ldadd" #mb " %[i], x30, %[v]\n" \ @@ -401,8 +399,8 @@ static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_ATOMIC64(fetch_sub##name), \ + __LL_SC_ATOMIC64(fetch_sub##name) \ + __nops(1), \ /* LSE atomics */ \ " neg %[i], %[i]\n" \ " ldadd" #mb " %[i], %[i], %[v]") \ @@ -426,13 +424,8 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) asm volatile(ARM64_LSE_ATOMIC_INSN( /* LL/SC */ - " nop\n" __LL_SC_ATOMIC64(dec_if_positive) - " nop\n" - " nop\n" - " nop\n" - " nop\n" - " nop", + __nops(6), /* LSE atomics */ "1: ldr x30, %[v]\n" " subs %[ret], x30, #1\n" @@ -464,9 +457,8 @@ static inline unsigned long __cmpxchg_case_##name(volatile void *ptr, \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - __LL_SC_CMPXCHG(name) \ - " nop", \ + __LL_SC_CMPXCHG(name) \ + __nops(2), \ /* LSE atomics */ \ " mov " #w "30, %" #w "[old]\n" \ " cas" #mb #sz "\t" #w "30, %" #w "[new], %[v]\n" \ @@ -517,10 +509,8 @@ static inline long __cmpxchg_double##name(unsigned long old1, \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ /* LL/SC */ \ - " nop\n" \ - " nop\n" \ - " nop\n" \ - __LL_SC_CMPXCHG_DBL(name), \ + __LL_SC_CMPXCHG_DBL(name) \ + __nops(3), \ /* LSE atomics */ \ " casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\ " eor %[old1], %[old1], %[oldval1]\n" \ diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 4eea7f618dce..4e0497f581a0 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -20,6 +20,9 @@ #ifndef __ASSEMBLY__ +#define __nops(n) ".rept " #n "\nnop\n.endr\n" +#define nops(n) asm volatile(__nops(n)) + #define sev() asm volatile("sev" : : : "memory") #define wfe() asm volatile("wfe" : : : "memory") #define wfi() asm volatile("wfi" : : : "memory") diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h index c64268dbff64..5a2a6ee65f65 100644 --- a/arch/arm64/include/asm/cacheflush.h +++ b/arch/arm64/include/asm/cacheflush.h @@ -65,11 +65,12 @@ * - kaddr - page address * - size - region size */ -extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_icache_range(unsigned long start, unsigned long end); extern void __flush_dcache_area(void *addr, size_t len); +extern void __clean_dcache_area_poc(void *addr, size_t len); extern void __clean_dcache_area_pou(void *addr, size_t len); extern long __flush_cache_user_range(unsigned long start, unsigned long end); +extern void sync_icache_aliases(void *kaddr, unsigned long len); static inline void flush_cache_mm(struct mm_struct *mm) { @@ -80,12 +81,17 @@ static inline void flush_cache_page(struct vm_area_struct *vma, { } +static inline void flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ +} + /* * Cache maintenance functions used by the DMA API. No to be used directly. */ extern void __dma_map_area(const void *, size_t, int); extern void __dma_unmap_area(const void *, size_t, int); -extern void __dma_flush_range(const void *, const void *); +extern void __dma_flush_area(const void *, size_t); /* * Copy user data from/to a page which is mapped into a different diff --git a/arch/arm64/include/asm/clocksource.h b/arch/arm64/include/asm/clocksource.h new file mode 100644 index 000000000000..0b350a7e26f3 --- /dev/null +++ b/arch/arm64/include/asm/clocksource.h @@ -0,0 +1,8 @@ +#ifndef _ASM_CLOCKSOURCE_H +#define _ASM_CLOCKSOURCE_H + +struct arch_clocksource_data { + bool vdso_direct; /* Usable for direct VDSO access? */ +}; + +#endif diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index bd86a79491bc..91b26d26af8a 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -43,10 +43,8 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \ " cbnz %w1, 1b\n" \ " " #mb, \ /* LSE atomics */ \ - " nop\n" \ - " nop\n" \ " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ - " nop\n" \ + __nops(3) \ " " #nop_lse) \ : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \ : "r" (x) \ diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h new file mode 100644 index 000000000000..4174f09678c4 --- /dev/null +++ b/arch/arm64/include/asm/cpucaps.h @@ -0,0 +1,41 @@ +/* + * arch/arm64/include/asm/cpucaps.h + * + * 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 __ASM_CPUCAPS_H +#define __ASM_CPUCAPS_H + +#define ARM64_WORKAROUND_CLEAN_CACHE 0 +#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 +#define ARM64_WORKAROUND_845719 2 +#define ARM64_HAS_SYSREG_GIC_CPUIF 3 +#define ARM64_HAS_PAN 4 +#define ARM64_HAS_LSE_ATOMICS 5 +#define ARM64_WORKAROUND_CAVIUM_23154 6 +#define ARM64_WORKAROUND_834220 7 +#define ARM64_HAS_NO_HW_PREFETCH 8 +#define ARM64_HAS_UAO 9 +#define ARM64_ALT_PAN_NOT_UAO 10 +#define ARM64_HAS_VIRT_HOST_EXTN 11 +#define ARM64_WORKAROUND_CAVIUM_27456 12 +#define ARM64_HAS_32BIT_EL0 13 +#define ARM64_HYP_OFFSET_LOW 14 +#define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 +#define ARM64_HAS_NO_FPSIMD 16 + +#define ARM64_NCAPS 17 + +#endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 7099f26e3702..b4989df48670 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -9,6 +9,7 @@ #ifndef __ASM_CPUFEATURE_H #define __ASM_CPUFEATURE_H +#include <asm/cpucaps.h> #include <asm/hwcap.h> #include <asm/sysreg.h> @@ -22,26 +23,10 @@ #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) #define cpu_feature(x) ilog2(HWCAP_ ## x) -#define ARM64_WORKAROUND_CLEAN_CACHE 0 -#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE 1 -#define ARM64_WORKAROUND_845719 2 -#define ARM64_HAS_SYSREG_GIC_CPUIF 3 -#define ARM64_HAS_PAN 4 -#define ARM64_HAS_LSE_ATOMICS 5 -#define ARM64_WORKAROUND_CAVIUM_23154 6 -#define ARM64_WORKAROUND_834220 7 -#define ARM64_HAS_NO_HW_PREFETCH 8 -#define ARM64_HAS_UAO 9 -#define ARM64_ALT_PAN_NOT_UAO 10 -#define ARM64_HAS_VIRT_HOST_EXTN 11 -#define ARM64_WORKAROUND_CAVIUM_27456 12 -#define ARM64_HAS_32BIT_EL0 13 -#define ARM64_HYP_OFFSET_LOW 14 - -#define ARM64_NCAPS 15 - #ifndef __ASSEMBLY__ +#include <linux/bug.h> +#include <linux/jump_label.h> #include <linux/kernel.h> /* CPU feature register tracking */ @@ -63,7 +48,7 @@ struct arm64_ftr_bits { enum ftr_type type; u8 shift; u8 width; - s64 safe_val; /* safe value for discrete features */ + s64 safe_val; /* safe value for FTR_EXACT features */ }; /* @@ -72,13 +57,14 @@ struct arm64_ftr_bits { * @sys_val Safe value across the CPUs (system view) */ struct arm64_ftr_reg { - u32 sys_id; - const char *name; - u64 strict_mask; - u64 sys_val; - struct arm64_ftr_bits *ftr_bits; + const char *name; + u64 strict_mask; + u64 sys_val; + const struct arm64_ftr_bits *ftr_bits; }; +extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0; + /* scope of capability check */ enum { SCOPE_SYSTEM, @@ -90,7 +76,7 @@ struct arm64_cpu_capabilities { u16 capability; int def_scope; /* default scope */ bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope); - void (*enable)(void *); /* Called on all active CPUs */ + int (*enable)(void *); /* Called on all active CPUs */ union { struct { /* To be used for erratum handling only */ u32 midr_model; @@ -109,6 +95,7 @@ struct arm64_cpu_capabilities { }; extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); +extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; bool this_cpu_has_cap(unsigned int cap); @@ -117,6 +104,14 @@ static inline bool cpu_have_feature(unsigned int num) return elf_hwcap & (1UL << num); } +/* System capability check for constant caps */ +static inline bool cpus_have_const_cap(int num) +{ + if (num >= ARM64_NCAPS) + return false; + return static_branch_unlikely(&cpu_hwcap_keys[num]); +} + static inline bool cpus_have_cap(unsigned int num) { if (num >= ARM64_NCAPS) @@ -126,11 +121,13 @@ static inline bool cpus_have_cap(unsigned int num) static inline void cpus_set_cap(unsigned int num) { - if (num >= ARM64_NCAPS) + if (num >= ARM64_NCAPS) { pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n", num, ARM64_NCAPS); - else + } else { __set_bit(num, cpu_hwcaps); + static_branch_enable(&cpu_hwcap_keys[num]); + } } static inline int __attribute_const__ @@ -157,7 +154,7 @@ cpuid_feature_extract_unsigned_field(u64 features, int field) return cpuid_feature_extract_unsigned_field_width(features, field, 4); } -static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp) +static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp) { return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift); } @@ -170,7 +167,7 @@ cpuid_feature_extract_field(u64 features, int field, bool sign) cpuid_feature_extract_unsigned_field(features, field); } -static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val) +static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val) { return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign); } @@ -193,11 +190,11 @@ void __init setup_cpu_features(void); void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, const char *info); void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps); -void check_local_cpu_errata(void); -void __init enable_errata_workarounds(void); +void check_local_cpu_capabilities(void); -void verify_local_cpu_errata(void); -void verify_local_cpu_capabilities(void); +void update_cpu_errata_workarounds(void); +void __init enable_errata_workarounds(void); +void verify_local_cpu_errata_workarounds(void); u64 read_system_reg(u32 id); @@ -208,7 +205,7 @@ static inline bool cpu_supports_mixed_endian_el0(void) static inline bool system_supports_32bit_el0(void) { - return cpus_have_cap(ARM64_HAS_32BIT_EL0); + return cpus_have_const_cap(ARM64_HAS_32BIT_EL0); } static inline bool system_supports_mixed_endian_el0(void) @@ -216,6 +213,17 @@ static inline bool system_supports_mixed_endian_el0(void) return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1)); } +static inline bool system_supports_fpsimd(void) +{ + return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD); +} + +static inline bool system_uses_ttbr0_pan(void) +{ + return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) && + !cpus_have_cap(ARM64_HAS_PAN); +} + #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 9d9fd4b9a72e..26a68ddb11c1 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -93,11 +93,7 @@ #include <asm/sysreg.h> -#define read_cpuid(reg) ({ \ - u64 __val; \ - asm("mrs_s %0, " __stringify(SYS_ ## reg) : "=r" (__val)); \ - __val; \ -}) +#define read_cpuid(reg) read_sysreg_s(SYS_ ## reg) /* * The CPU ID never changes at run time, so we might as well tell the diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h new file mode 100644 index 000000000000..86c404171305 --- /dev/null +++ b/arch/arm64/include/asm/current.h @@ -0,0 +1,30 @@ +#ifndef __ASM_CURRENT_H +#define __ASM_CURRENT_H + +#include <linux/compiler.h> + +#include <asm/sysreg.h> + +#ifndef __ASSEMBLY__ + +struct task_struct; + +/* + * We don't use read_sysreg() as we want the compiler to cache the value where + * possible. + */ +static __always_inline struct task_struct *get_current(void) +{ + unsigned long sp_el0; + + asm ("mrs %0, sp_el0" : "=r" (sp_el0)); + + return (struct task_struct *)sp_el0; +} + +#define current get_current() + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_CURRENT_H */ + diff --git a/arch/arm64/include/asm/dcc.h b/arch/arm64/include/asm/dcc.h index 65e0190e97c8..836b05630003 100644 --- a/arch/arm64/include/asm/dcc.h +++ b/arch/arm64/include/asm/dcc.h @@ -21,21 +21,16 @@ #define __ASM_DCC_H #include <asm/barrier.h> +#include <asm/sysreg.h> static inline u32 __dcc_getstatus(void) { - u32 ret; - - asm volatile("mrs %0, mdccsr_el0" : "=r" (ret)); - - return ret; + return read_sysreg(mdccsr_el0); } static inline char __dcc_getchar(void) { - char c; - - asm volatile("mrs %0, dbgdtrrx_el0" : "=r" (c)); + char c = read_sysreg(dbgdtrrx_el0); isb(); return c; @@ -47,8 +42,7 @@ static inline void __dcc_putchar(char c) * The typecast is to make absolutely certain that 'c' is * zero-extended. */ - asm volatile("msr dbgdtrtx_el0, %0" - : : "r" ((unsigned long)(unsigned char)c)); + write_sysreg((unsigned char)c, dbgdtrtx_el0); isb(); } diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index b71420a12f26..a44cf5225429 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -68,6 +68,9 @@ #define BRK64_ESR_MASK 0xFFFF #define BRK64_ESR_KPROBES 0x0004 #define BRK64_OPCODE_KPROBES (AARCH64_BREAK_MON | (BRK64_ESR_KPROBES << 5)) +/* uprobes BRK opcodes with ESR encoding */ +#define BRK64_ESR_UPROBES 0x0005 +#define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (BRK64_ESR_UPROBES << 5)) /* AArch32 */ #define DBG_ESR_EVT_BKPT 0x4 diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a9e54aad15ef..0b6b1633017f 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -1,6 +1,7 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H +#include <asm/cpufeature.h> #include <asm/io.h> #include <asm/mmu_context.h> #include <asm/neon.h> @@ -51,6 +52,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); #define __efi_call_early(f, ...) f(__VA_ARGS__) #define efi_is_64bit() (true) +#define efi_call_proto(protocol, f, instance, ...) \ + ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) + #define alloc_screen_info(x...) &screen_info #define free_screen_info(x...) @@ -75,7 +79,30 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) static inline void efi_set_pgd(struct mm_struct *mm) { - switch_mm(NULL, mm, NULL); + __switch_mm(mm); + + if (system_uses_ttbr0_pan()) { + if (mm != current->active_mm) { + /* + * Update the current thread's saved ttbr0 since it is + * restored as part of a return from exception. Set + * the hardware TTBR0_EL1 using cpu_switch_mm() + * directly to enable potential errata workarounds. + */ + update_saved_ttbr0(current, mm); + cpu_switch_mm(mm->pgd, mm); + } else { + /* + * Defer the switch to the current thread's TTBR0_EL1 + * until uaccess_enable(). Restore the current + * thread's saved ttbr0 corresponding to its active_mm + * (if different from init_mm). + */ + cpu_set_reserved_ttbr0(); + if (current->active_mm != &init_mm) + update_saved_ttbr0(current, current->active_mm); + } + } } void efi_virtmap_load(void); diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index a55384f4a5d7..5d1700425efe 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -138,7 +138,11 @@ typedef struct user_fpsimd_state elf_fpregset_t; */ #define ELF_PLAT_INIT(_r, load_addr) (_r)->regs[0] = 0 -#define SET_PERSONALITY(ex) clear_thread_flag(TIF_32BIT); +#define SET_PERSONALITY(ex) \ +({ \ + clear_bit(TIF_32BIT, ¤t->mm->context.flags); \ + clear_thread_flag(TIF_32BIT); \ +}) /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ #define ARCH_DLINFO \ @@ -183,7 +187,11 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; ((x)->e_flags & EF_ARM_EABI_MASK)) #define compat_start_thread compat_start_thread -#define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT); +#define COMPAT_SET_PERSONALITY(ex) \ +({ \ + set_bit(TIF_32BIT, ¤t->mm->context.flags); \ + set_thread_flag(TIF_32BIT); \ + }) #define COMPAT_ARCH_DLINFO extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp); diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index f772e15c4766..d14c478976d0 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -78,6 +78,23 @@ #define ESR_ELx_IL (UL(1) << 25) #define ESR_ELx_ISS_MASK (ESR_ELx_IL - 1) + +/* ISS field definitions shared by different classes */ +#define ESR_ELx_WNR (UL(1) << 6) + +/* Shared ISS field definitions for Data/Instruction aborts */ +#define ESR_ELx_EA (UL(1) << 9) +#define ESR_ELx_S1PTW (UL(1) << 7) + +/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */ +#define ESR_ELx_FSC (0x3F) +#define ESR_ELx_FSC_TYPE (0x3C) +#define ESR_ELx_FSC_EXTABT (0x10) +#define ESR_ELx_FSC_ACCESS (0x08) +#define ESR_ELx_FSC_FAULT (0x04) +#define ESR_ELx_FSC_PERM (0x0C) + +/* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV (UL(1) << 24) #define ESR_ELx_SAS_SHIFT (22) #define ESR_ELx_SAS (UL(3) << ESR_ELx_SAS_SHIFT) @@ -86,16 +103,9 @@ #define ESR_ELx_SRT_MASK (UL(0x1F) << ESR_ELx_SRT_SHIFT) #define ESR_ELx_SF (UL(1) << 15) #define ESR_ELx_AR (UL(1) << 14) -#define ESR_ELx_EA (UL(1) << 9) #define ESR_ELx_CM (UL(1) << 8) -#define ESR_ELx_S1PTW (UL(1) << 7) -#define ESR_ELx_WNR (UL(1) << 6) -#define ESR_ELx_FSC (0x3F) -#define ESR_ELx_FSC_TYPE (0x3C) -#define ESR_ELx_FSC_EXTABT (0x10) -#define ESR_ELx_FSC_ACCESS (0x08) -#define ESR_ELx_FSC_FAULT (0x04) -#define ESR_ELx_FSC_PERM (0x0C) + +/* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) #define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT) @@ -109,6 +119,62 @@ ((ESR_ELx_EC_BRK64 << ESR_ELx_EC_SHIFT) | ESR_ELx_IL | \ ((imm) & 0xffff)) +/* ISS field definitions for System instruction traps */ +#define ESR_ELx_SYS64_ISS_RES0_SHIFT 22 +#define ESR_ELx_SYS64_ISS_RES0_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_RES0_SHIFT) +#define ESR_ELx_SYS64_ISS_DIR_MASK 0x1 +#define ESR_ELx_SYS64_ISS_DIR_READ 0x1 +#define ESR_ELx_SYS64_ISS_DIR_WRITE 0x0 + +#define ESR_ELx_SYS64_ISS_RT_SHIFT 5 +#define ESR_ELx_SYS64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_SYS64_ISS_RT_SHIFT) +#define ESR_ELx_SYS64_ISS_CRM_SHIFT 1 +#define ESR_ELx_SYS64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRM_SHIFT) +#define ESR_ELx_SYS64_ISS_CRN_SHIFT 10 +#define ESR_ELx_SYS64_ISS_CRN_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRN_SHIFT) +#define ESR_ELx_SYS64_ISS_OP1_SHIFT 14 +#define ESR_ELx_SYS64_ISS_OP1_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP1_SHIFT) +#define ESR_ELx_SYS64_ISS_OP2_SHIFT 17 +#define ESR_ELx_SYS64_ISS_OP2_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP2_SHIFT) +#define ESR_ELx_SYS64_ISS_OP0_SHIFT 20 +#define ESR_ELx_SYS64_ISS_OP0_MASK (UL(0x3) << ESR_ELx_SYS64_ISS_OP0_SHIFT) +#define ESR_ELx_SYS64_ISS_SYS_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \ + ESR_ELx_SYS64_ISS_OP1_MASK | \ + ESR_ELx_SYS64_ISS_OP2_MASK | \ + ESR_ELx_SYS64_ISS_CRN_MASK | \ + ESR_ELx_SYS64_ISS_CRM_MASK) +#define ESR_ELx_SYS64_ISS_SYS_VAL(op0, op1, op2, crn, crm) \ + (((op0) << ESR_ELx_SYS64_ISS_OP0_SHIFT) | \ + ((op1) << ESR_ELx_SYS64_ISS_OP1_SHIFT) | \ + ((op2) << ESR_ELx_SYS64_ISS_OP2_SHIFT) | \ + ((crn) << ESR_ELx_SYS64_ISS_CRN_SHIFT) | \ + ((crm) << ESR_ELx_SYS64_ISS_CRM_SHIFT)) + +#define ESR_ELx_SYS64_ISS_SYS_OP_MASK (ESR_ELx_SYS64_ISS_SYS_MASK | \ + ESR_ELx_SYS64_ISS_DIR_MASK) +/* + * User space cache operations have the following sysreg encoding + * in System instructions. + * op0=1, op1=3, op2=1, crn=7, crm={ 5, 10, 11, 14 }, WRITE (L=0) + */ +#define ESR_ELx_SYS64_ISS_CRM_DC_CIVAC 14 +#define ESR_ELx_SYS64_ISS_CRM_DC_CVAU 11 +#define ESR_ELx_SYS64_ISS_CRM_DC_CVAC 10 +#define ESR_ELx_SYS64_ISS_CRM_IC_IVAU 5 + +#define ESR_ELx_SYS64_ISS_EL0_CACHE_OP_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \ + ESR_ELx_SYS64_ISS_OP1_MASK | \ + ESR_ELx_SYS64_ISS_OP2_MASK | \ + ESR_ELx_SYS64_ISS_CRN_MASK | \ + ESR_ELx_SYS64_ISS_DIR_MASK) +#define ESR_ELx_SYS64_ISS_EL0_CACHE_OP_VAL \ + (ESR_ELx_SYS64_ISS_SYS_VAL(1, 3, 1, 7, 0) | \ + ESR_ELx_SYS64_ISS_DIR_WRITE) + +#define ESR_ELx_SYS64_ISS_SYS_CTR ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 1, 0, 0) +#define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #ifndef __ASSEMBLY__ #include <asm/types.h> diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h index db0563c23482..f7865dd9d868 100644 --- a/arch/arm64/include/asm/exec.h +++ b/arch/arm64/include/asm/exec.h @@ -18,6 +18,9 @@ #ifndef __ASM_EXEC_H #define __ASM_EXEC_H +#include <linux/sched.h> + extern unsigned long arch_align_stack(unsigned long sp); +void uao_thread_switch(struct task_struct *next); #endif /* __ASM_EXEC_H */ diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h index f2585cdd32c2..85c4a8981d47 100644 --- a/arch/arm64/include/asm/futex.h +++ b/arch/arm64/include/asm/futex.h @@ -21,15 +21,12 @@ #include <linux/futex.h> #include <linux/uaccess.h> -#include <asm/alternative.h> -#include <asm/cpufeature.h> #include <asm/errno.h> -#include <asm/sysreg.h> #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ +do { \ + uaccess_enable(); \ asm volatile( \ - ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ - CONFIG_ARM64_PAN) \ " prfm pstl1strm, %2\n" \ "1: ldxr %w1, %2\n" \ insn "\n" \ @@ -44,11 +41,11 @@ " .popsection\n" \ _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ - ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ - CONFIG_ARM64_PAN) \ : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ : "r" (oparg), "Ir" (-EFAULT) \ - : "memory") + : "memory"); \ + uaccess_disable(); \ +} while (0) static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) @@ -118,8 +115,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; + uaccess_enable(); asm volatile("// futex_atomic_cmpxchg_inatomic\n" -ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN) " prfm pstl1strm, %2\n" "1: ldxr %w1, %2\n" " sub %w3, %w1, %w4\n" @@ -134,10 +131,10 @@ ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN) " .popsection\n" _ASM_EXTABLE(1b, 4b) _ASM_EXTABLE(2b, 4b) -ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN) : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) : "r" (oldval), "r" (newval), "Ir" (-EFAULT) : "memory"); + uaccess_disable(); *uval = val; return ret; diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index 115ea2a64520..b6b167ac082b 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h @@ -18,6 +18,7 @@ #include <asm/cputype.h> #include <asm/cpufeature.h> +#include <asm/sysreg.h> #include <asm/virt.h> #ifdef __KERNEL__ @@ -76,7 +77,11 @@ static inline void decode_ctrl_reg(u32 reg, /* Lengths */ #define ARM_BREAKPOINT_LEN_1 0x1 #define ARM_BREAKPOINT_LEN_2 0x3 +#define ARM_BREAKPOINT_LEN_3 0x7 #define ARM_BREAKPOINT_LEN_4 0xf +#define ARM_BREAKPOINT_LEN_5 0x1f +#define ARM_BREAKPOINT_LEN_6 0x3f +#define ARM_BREAKPOINT_LEN_7 0x7f #define ARM_BREAKPOINT_LEN_8 0xff /* Kernel stepping */ @@ -98,18 +103,18 @@ static inline void decode_ctrl_reg(u32 reg, #define AARCH64_DBG_REG_WCR (AARCH64_DBG_REG_WVR + ARM_MAX_WRP) /* Debug register names. */ -#define AARCH64_DBG_REG_NAME_BVR "bvr" -#define AARCH64_DBG_REG_NAME_BCR "bcr" -#define AARCH64_DBG_REG_NAME_WVR "wvr" -#define AARCH64_DBG_REG_NAME_WCR "wcr" +#define AARCH64_DBG_REG_NAME_BVR bvr +#define AARCH64_DBG_REG_NAME_BCR bcr +#define AARCH64_DBG_REG_NAME_WVR wvr +#define AARCH64_DBG_REG_NAME_WCR wcr /* Accessor macros for the debug registers. */ #define AARCH64_DBG_READ(N, REG, VAL) do {\ - asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\ + VAL = read_sysreg(dbg##REG##N##_el1);\ } while (0) #define AARCH64_DBG_WRITE(N, REG, VAL) do {\ - asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\ + write_sysreg(VAL, dbg##REG##N##_el1);\ } while (0) struct task_struct; @@ -118,7 +123,7 @@ struct perf_event; struct pmu; extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, - int *gen_len, int *gen_type); + int *gen_len, int *gen_type, int *offset); extern int arch_check_bp_in_kernelspace(struct perf_event *bp); extern int arch_validate_hwbkpt_settings(struct perf_event *bp); extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, @@ -141,8 +146,6 @@ static inline void ptrace_hw_copy_thread(struct task_struct *task) } #endif -extern struct pmu perf_ops_bp; - /* Determine number of BRP registers available. */ static inline int get_num_brps(void) { diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 1dbaa901d7e5..bc853663dd51 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -246,7 +246,8 @@ static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ { return (val); } -__AARCH64_INSN_FUNCS(adr_adrp, 0x1F000000, 0x10000000) +__AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000) +__AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000) __AARCH64_INSN_FUNCS(prfm_lit, 0xFF000000, 0xD8000000) __AARCH64_INSN_FUNCS(str_reg, 0x3FE0EC00, 0x38206800) __AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800) @@ -318,6 +319,11 @@ __AARCH64_INSN_FUNCS(msr_reg, 0xFFF00000, 0xD5100000) bool aarch64_insn_is_nop(u32 insn); bool aarch64_insn_is_branch_imm(u32 insn); +static inline bool aarch64_insn_is_adr_adrp(u32 insn) +{ + return aarch64_insn_is_adr(insn) || aarch64_insn_is_adrp(insn); +} + int aarch64_insn_read(void *addr, u32 *insnp); int aarch64_insn_write(void *addr, u32 insn); enum aarch64_insn_encoding_class aarch64_get_insn_class(u32 insn); @@ -398,6 +404,9 @@ int aarch64_insn_patch_text_nosync(void *addr, u32 insn); int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt); int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt); +s32 aarch64_insn_adrp_get_offset(u32 insn); +u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset); + bool aarch32_insn_is_wide(u32 insn); #define A32_RN_OFFSET 16 diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 9b6e408cfa51..0c00c87bb9dd 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -22,7 +22,6 @@ #ifdef __KERNEL__ #include <linux/types.h> -#include <linux/blk_types.h> #include <asm/byteorder.h> #include <asm/barrier.h> @@ -40,25 +39,25 @@ #define __raw_writeb __raw_writeb static inline void __raw_writeb(u8 val, volatile void __iomem *addr) { - asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr)); + asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_writew __raw_writew static inline void __raw_writew(u16 val, volatile void __iomem *addr) { - asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr)); + asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_writel __raw_writel static inline void __raw_writel(u32 val, volatile void __iomem *addr) { - asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr)); + asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_writeq __raw_writeq static inline void __raw_writeq(u64 val, volatile void __iomem *addr) { - asm volatile("str %0, [%1]" : : "r" (val), "r" (addr)); + asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr)); } #define __raw_readb __raw_readb @@ -184,17 +183,6 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); #define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); }) #define iowrite64be(v,p) ({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); }) -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - #include <asm-generic/io.h> /* diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index 7e51d1b57c0c..7803343e5881 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -19,6 +19,7 @@ #ifndef __ASM_KERNEL_PGTABLE_H #define __ASM_KERNEL_PGTABLE_H +#include <asm/pgtable.h> #include <asm/sparsemem.h> /* @@ -54,6 +55,12 @@ #define SWAPPER_DIR_SIZE (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE) #define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE) +#ifdef CONFIG_ARM64_SW_TTBR0_PAN +#define RESERVED_TTBR0_SIZE (PAGE_SIZE) +#else +#define RESERVED_TTBR0_SIZE (0) +#endif + /* Initial memory map size */ #if ARM64_SWAPPER_USES_SECTION_MAPS #define SWAPPER_BLOCK_SHIFT SECTION_SHIFT diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 4b5c977af465..2a2752b5b6aa 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -50,7 +50,7 @@ #define HCR_BSU (3 << 10) #define HCR_BSU_IS (UL(1) << 10) #define HCR_FB (UL(1) << 9) -#define HCR_VA (UL(1) << 8) +#define HCR_VSE (UL(1) << 8) #define HCR_VI (UL(1) << 7) #define HCR_VF (UL(1) << 6) #define HCR_AMO (UL(1) << 5) @@ -80,7 +80,7 @@ #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW) -#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) +#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF) #define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO) #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 7561f63f1c28..ec3553eb9349 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -20,10 +20,15 @@ #include <asm/virt.h> +#define ARM_EXIT_WITH_SERROR_BIT 31 +#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) +#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT)) + #define ARM_EXCEPTION_IRQ 0 -#define ARM_EXCEPTION_TRAP 1 +#define ARM_EXCEPTION_EL1_SERROR 1 +#define ARM_EXCEPTION_TRAP 2 /* The hyp-stub will return this for any kvm_call_hyp() call */ -#define ARM_EXCEPTION_HYP_GONE 2 +#define ARM_EXCEPTION_HYP_GONE 3 #define KVM_ARM64_DEBUG_DIRTY_SHIFT 0 #define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT) @@ -49,6 +54,7 @@ extern char __kvm_hyp_vector[]; extern void __kvm_flush_vm_context(void); extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa); extern void __kvm_tlb_flush_vmid(struct kvm *kvm); +extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu); extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 4cdeae3b17c6..f5ea0ba70f07 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -38,6 +38,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu); void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr); void kvm_inject_undefined(struct kvm_vcpu *vcpu); +void kvm_inject_vabt(struct kvm_vcpu *vcpu); void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); @@ -147,6 +148,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) +{ + u32 esr = kvm_vcpu_get_hsr(vcpu); + + if (esr & ESR_ELx_CV) + return (esr & ESR_ELx_COND_MASK) >> ESR_ELx_COND_SHIFT; + + return -1; +} + static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu) { return vcpu->arch.fault.far_el2; @@ -167,11 +178,6 @@ static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu) return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV); } -static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) -{ - return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR); -} - static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu) { return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE); @@ -192,6 +198,12 @@ static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu) return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW); } +static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu) +{ + return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) || + kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */ +} + static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu) { return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3eda975837d0..e5050388e062 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -62,6 +62,9 @@ struct kvm_arch { /* VTTBR value associated with above pgd and vmid */ u64 vttbr; + /* The last vcpu id that ran on each physical CPU */ + int __percpu *last_vcpu_ran; + /* The maximum number of vCPUs depends on the used GIC model */ int max_vcpus; @@ -290,15 +293,15 @@ struct kvm_vcpu_arch { #endif struct kvm_vm_stat { - u32 remote_tlb_flush; + ulong remote_tlb_flush; }; struct kvm_vcpu_stat { - u32 halt_successful_poll; - u32 halt_attempted_poll; - u32 halt_poll_invalid; - u32 halt_wakeup; - u32 hvc_exit_stat; + u64 halt_successful_poll; + u64 halt_attempted_poll; + u64 halt_poll_invalid; + u64 halt_wakeup; + u64 hvc_exit_stat; u64 wfe_exit_stat; u64 wfi_exit_stat; u64 mmio_exit_user; diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index cff510574fae..b18e852d27e8 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -123,6 +123,7 @@ typeof(orig) * __hyp_text fname(void) \ void __vgic_v2_save_state(struct kvm_vcpu *vcpu); void __vgic_v2_restore_state(struct kvm_vcpu *vcpu); +int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu); void __vgic_v3_save_state(struct kvm_vcpu *vcpu); void __vgic_v3_restore_state(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index b6bb83400cd8..6f72fe8b0e3e 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -99,14 +99,10 @@ .macro kern_hyp_va reg alternative_if_not ARM64_HAS_VIRT_HOST_EXTN and \reg, \reg, #HYP_PAGE_OFFSET_HIGH_MASK -alternative_else - nop -alternative_endif -alternative_if_not ARM64_HYP_OFFSET_LOW - nop -alternative_else +alternative_else_nop_endif +alternative_if ARM64_HYP_OFFSET_LOW and \reg, \reg, #HYP_PAGE_OFFSET_LOW_MASK -alternative_endif +alternative_else_nop_endif .endm #else @@ -132,7 +128,7 @@ static inline unsigned long __kern_hyp_va(unsigned long v) return v; } -#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v))) +#define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v)))) /* * We currently only support a 40bit IPA. @@ -166,12 +162,6 @@ void kvm_clear_hyp_idmap(void); #define kvm_set_pte(ptep, pte) set_pte(ptep, pte) #define kvm_set_pmd(pmdp, pmd) set_pmd(pmdp, pmd) -static inline void kvm_clean_pgd(pgd_t *pgd) {} -static inline void kvm_clean_pmd(pmd_t *pmd) {} -static inline void kvm_clean_pmd_entry(pmd_t *pmd) {} -static inline void kvm_clean_pte(pte_t *pte) {} -static inline void kvm_clean_pte_entry(pte_t *pte) {} - static inline pte_t kvm_s2pte_mkwrite(pte_t pte) { pte_val(pte) |= PTE_S2_RDWR; diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h index 23acc00be32d..fc756e22c84c 100644 --- a/arch/arm64/include/asm/lse.h +++ b/arch/arm64/include/asm/lse.h @@ -5,7 +5,6 @@ #include <linux/stringify.h> #include <asm/alternative.h> -#include <asm/cpufeature.h> #ifdef __ASSEMBLER__ diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 31b73227b41f..bfe632808d77 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -165,6 +165,11 @@ extern u64 kimage_vaddr; /* the offset between the kernel virtual and physical mappings */ extern u64 kimage_voffset; +static inline unsigned long kaslr_offset(void) +{ + return kimage_vaddr - KIMAGE_VADDR; +} + /* * Allow all memory at the discovery stage. We will clip it later. */ @@ -214,19 +219,23 @@ static inline void *phys_to_virt(phys_addr_t x) #ifndef CONFIG_SPARSEMEM_VMEMMAP #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #else #define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) -#define __page_to_voff(kaddr) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) +#define __page_to_voff(page) (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) #define page_to_virt(page) ((void *)((__page_to_voff(page)) | PAGE_OFFSET)) #define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START)) -#define virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \ +#define _virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \ + PHYS_OFFSET) >> PAGE_SHIFT) #endif #endif +#define _virt_addr_is_linear(kaddr) (((u64)(kaddr)) >= PAGE_OFFSET) +#define virt_addr_valid(kaddr) (_virt_addr_is_linear(kaddr) && \ + _virt_addr_valid(kaddr)) + #include <asm-generic/memory_model.h> #endif diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 8d9fce037b2f..47619411f0ff 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -19,6 +19,7 @@ typedef struct { atomic64_t id; void *vdso; + unsigned long flags; } mm_context_t; /* @@ -34,7 +35,7 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, - pgprot_t prot, bool allow_block_mappings); + pgprot_t prot, bool page_mappings_only); extern void *fixmap_remap_fdt(phys_addr_t dt_phys); #endif diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index b1892a0dbcb0..0363fe80455c 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -23,26 +23,22 @@ #include <linux/sched.h> #include <asm/cacheflush.h> +#include <asm/cpufeature.h> #include <asm/proc-fns.h> #include <asm-generic/mm_hooks.h> #include <asm/cputype.h> #include <asm/pgtable.h> +#include <asm/sysreg.h> #include <asm/tlbflush.h> -#ifdef CONFIG_PID_IN_CONTEXTIDR -static inline void contextidr_thread_switch(struct task_struct *next) -{ - asm( - " msr contextidr_el1, %0\n" - " isb" - : - : "r" (task_pid_nr(next))); -} -#else static inline void contextidr_thread_switch(struct task_struct *next) { + if (!IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR)) + return; + + write_sysreg(task_pid_nr(next), contextidr_el1); + isb(); } -#endif /* * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0. @@ -51,11 +47,8 @@ static inline void cpu_set_reserved_ttbr0(void) { unsigned long ttbr = virt_to_phys(empty_zero_page); - asm( - " msr ttbr0_el1, %0 // set TTBR0\n" - " isb" - : - : "r" (ttbr)); + write_sysreg(ttbr, ttbr0_el1); + isb(); } /* @@ -81,13 +74,11 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) if (!__cpu_uses_extended_idmap()) return; - asm volatile ( - " mrs %0, tcr_el1 ;" - " bfi %0, %1, %2, %3 ;" - " msr tcr_el1, %0 ;" - " isb" - : "=&r" (tcr) - : "r"(t0sz), "I"(TCR_T0SZ_OFFSET), "I"(TCR_TxSZ_WIDTH)); + tcr = read_sysreg(tcr_el1); + tcr &= ~TCR_T0SZ_MASK; + tcr |= t0sz << TCR_T0SZ_OFFSET; + write_sysreg(tcr, tcr_el1); + isb(); } #define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS)) @@ -113,7 +104,7 @@ static inline void cpu_uninstall_idmap(void) local_flush_tlb_all(); cpu_set_default_tcr_t0sz(); - if (mm != &init_mm) + if (mm != &init_mm && !system_uses_ttbr0_pan()) cpu_switch_mm(mm->pgd, mm); } @@ -173,20 +164,26 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } -/* - * This is the actual mm switch as far as the scheduler - * is concerned. No registers are touched. We avoid - * calling the CPU specific function when the mm hasn't - * actually changed. - */ -static inline void -switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) +#ifdef CONFIG_ARM64_SW_TTBR0_PAN +static inline void update_saved_ttbr0(struct task_struct *tsk, + struct mm_struct *mm) { - unsigned int cpu = smp_processor_id(); + if (system_uses_ttbr0_pan()) { + BUG_ON(mm->pgd == swapper_pg_dir); + task_thread_info(tsk)->ttbr0 = + virt_to_phys(mm->pgd) | ASID(mm) << 48; + } +} +#else +static inline void update_saved_ttbr0(struct task_struct *tsk, + struct mm_struct *mm) +{ +} +#endif - if (prev == next) - return; +static inline void __switch_mm(struct mm_struct *next) +{ + unsigned int cpu = smp_processor_id(); /* * init_mm.pgd does not contain any user mappings and it is always @@ -200,8 +197,26 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, check_and_switch_context(next, cpu); } +static inline void +switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + if (prev != next) + __switch_mm(next); + + /* + * Update the saved TTBR0_EL1 of the scheduled-in task as the previous + * value may have not been initialised yet (activate_mm caller) or the + * ASID has changed since the last run (following the context switch + * of another thread of the same process). Avoid setting the reserved + * TTBR0_EL1 to swapper_pg_dir (init_mm; e.g. via idle_task_exit). + */ + if (next != &init_mm) + update_saved_ttbr0(tsk, next); +} + #define deactivate_mm(tsk,mm) do { } while (0) -#define activate_mm(prev,next) switch_mm(prev, next, NULL) +#define activate_mm(prev,next) switch_mm(prev, next, current) void verify_cpu_asid_bits(void); diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index e12af6754634..06ff7fd9e81f 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -17,6 +17,7 @@ #define __ASM_MODULE_H #include <asm-generic/module.h> +#include <asm/memory.h> #define MODULE_ARCH_VERMAGIC "aarch64" @@ -32,6 +33,10 @@ u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela, Elf64_Sym *sym); #ifdef CONFIG_RANDOMIZE_BASE +#ifdef CONFIG_MODVERSIONS +#define ARCH_RELOCATES_KCRCTAB +#define reloc_start (kimage_vaddr - KIMAGE_VADDR) +#endif extern u64 module_alloc_base; #else #define module_alloc_base ((u64)_etext - MODULES_VSIZE) diff --git a/arch/arm64/include/asm/neon.h b/arch/arm64/include/asm/neon.h index 13ce4cc18e26..ad4cdc966c0f 100644 --- a/arch/arm64/include/asm/neon.h +++ b/arch/arm64/include/asm/neon.h @@ -9,8 +9,9 @@ */ #include <linux/types.h> +#include <asm/fpsimd.h> -#define cpu_has_neon() (1) +#define cpu_has_neon() system_supports_fpsimd() #define kernel_neon_begin() kernel_neon_begin_partial(32) diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h index 600887e491fd..bf466d1876e3 100644 --- a/arch/arm64/include/asm/numa.h +++ b/arch/arm64/include/asm/numa.h @@ -15,6 +15,8 @@ int __node_distance(int from, int to); extern nodemask_t numa_nodes_parsed __initdata; +extern bool numa_off; + /* Mappings between node number and cpus on that node. */ extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; void numa_clear_node(unsigned int cpu); diff --git a/arch/arm64/include/asm/opcodes.h b/arch/arm64/include/asm/opcodes.h deleted file mode 100644 index 123f45d92cd1..000000000000 --- a/arch/arm64/include/asm/opcodes.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef CONFIG_CPU_BIG_ENDIAN -#define CONFIG_CPU_ENDIAN_BE8 CONFIG_CPU_BIG_ENDIAN -#endif - -#include <../../arm/include/asm/opcodes.h> diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h index 2fee2f59288c..3bd498e4de4c 100644 --- a/arch/arm64/include/asm/percpu.h +++ b/arch/arm64/include/asm/percpu.h @@ -16,6 +16,8 @@ #ifndef __ASM_PERCPU_H #define __ASM_PERCPU_H +#include <asm/stack_pointer.h> + static inline void set_my_cpu_offset(unsigned long off) { asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory"); @@ -44,48 +46,44 @@ static inline unsigned long __percpu_##op(void *ptr, \ \ switch (size) { \ case 1: \ - do { \ - asm ("//__per_cpu_" #op "_1\n" \ - "ldxrb %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_1\n" \ + "1: ldxrb %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrb %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u8 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrb %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u8 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 2: \ - do { \ - asm ("//__per_cpu_" #op "_2\n" \ - "ldxrh %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_2\n" \ + "1: ldxrh %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxrh %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u16 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxrh %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u16 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 4: \ - do { \ - asm ("//__per_cpu_" #op "_4\n" \ - "ldxr %w[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_4\n" \ + "1: ldxr %w[ret], %[ptr]\n" \ #asm_op " %w[ret], %w[ret], %w[val]\n" \ - "stxr %w[loop], %w[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u32 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %w[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u32 *)ptr) \ + : [val] "Ir" (val)); \ break; \ case 8: \ - do { \ - asm ("//__per_cpu_" #op "_8\n" \ - "ldxr %[ret], %[ptr]\n" \ + asm ("//__per_cpu_" #op "_8\n" \ + "1: ldxr %[ret], %[ptr]\n" \ #asm_op " %[ret], %[ret], %[val]\n" \ - "stxr %w[loop], %[ret], %[ptr]\n" \ - : [loop] "=&r" (loop), [ret] "=&r" (ret), \ - [ptr] "+Q"(*(u64 *)ptr) \ - : [val] "Ir" (val)); \ - } while (loop); \ + " stxr %w[loop], %[ret], %[ptr]\n" \ + " cbnz %w[loop], 1b" \ + : [loop] "=&r" (loop), [ret] "=&r" (ret), \ + [ptr] "+Q"(*(u64 *)ptr) \ + : [val] "Ir" (val)); \ break; \ default: \ BUILD_BUG(); \ @@ -105,16 +103,16 @@ static inline unsigned long __percpu_read(void *ptr, int size) switch (size) { case 1: - ret = ACCESS_ONCE(*(u8 *)ptr); + ret = READ_ONCE(*(u8 *)ptr); break; case 2: - ret = ACCESS_ONCE(*(u16 *)ptr); + ret = READ_ONCE(*(u16 *)ptr); break; case 4: - ret = ACCESS_ONCE(*(u32 *)ptr); + ret = READ_ONCE(*(u32 *)ptr); break; case 8: - ret = ACCESS_ONCE(*(u64 *)ptr); + ret = READ_ONCE(*(u64 *)ptr); break; default: BUILD_BUG(); @@ -127,16 +125,16 @@ static inline void __percpu_write(void *ptr, unsigned long val, int size) { switch (size) { case 1: - ACCESS_ONCE(*(u8 *)ptr) = (u8)val; + WRITE_ONCE(*(u8 *)ptr, (u8)val); break; case 2: - ACCESS_ONCE(*(u16 *)ptr) = (u16)val; + WRITE_ONCE(*(u16 *)ptr, (u16)val); break; case 4: - ACCESS_ONCE(*(u32 *)ptr) = (u32)val; + WRITE_ONCE(*(u32 *)ptr, (u32)val); break; case 8: - ACCESS_ONCE(*(u64 *)ptr) = (u64)val; + WRITE_ONCE(*(u64 *)ptr, (u64)val); break; default: BUILD_BUG(); @@ -150,44 +148,40 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val, switch (size) { case 1: - do { - asm ("//__percpu_xchg_1\n" - "ldxrb %w[ret], %[ptr]\n" - "stxrb %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u8 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_1\n" + "1: ldxrb %w[ret], %[ptr]\n" + " stxrb %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u8 *)ptr) + : [val] "r" (val)); break; case 2: - do { - asm ("//__percpu_xchg_2\n" - "ldxrh %w[ret], %[ptr]\n" - "stxrh %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u16 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_2\n" + "1: ldxrh %w[ret], %[ptr]\n" + " stxrh %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u16 *)ptr) + : [val] "r" (val)); break; case 4: - do { - asm ("//__percpu_xchg_4\n" - "ldxr %w[ret], %[ptr]\n" - "stxr %w[loop], %w[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u32 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_4\n" + "1: ldxr %w[ret], %[ptr]\n" + " stxr %w[loop], %w[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u32 *)ptr) + : [val] "r" (val)); break; case 8: - do { - asm ("//__percpu_xchg_8\n" - "ldxr %[ret], %[ptr]\n" - "stxr %w[loop], %[val], %[ptr]\n" - : [loop] "=&r"(loop), [ret] "=&r"(ret), - [ptr] "+Q"(*(u64 *)ptr) - : [val] "r" (val)); - } while (loop); + asm ("//__percpu_xchg_8\n" + "1: ldxr %[ret], %[ptr]\n" + " stxr %w[loop], %[val], %[ptr]\n" + " cbnz %w[loop], 1b" + : [loop] "=&r"(loop), [ret] "=&r"(ret), + [ptr] "+Q"(*(u64 *)ptr) + : [val] "r" (val)); break; default: BUILD_BUG(); diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h index 2065f46fa740..8d5cbec17d80 100644 --- a/arch/arm64/include/asm/perf_event.h +++ b/arch/arm64/include/asm/perf_event.h @@ -17,6 +17,8 @@ #ifndef __ASM_PERF_EVENT_H #define __ASM_PERF_EVENT_H +#include <asm/stack_pointer.h> + #define ARMV8_PMU_MAX_COUNTERS 32 #define ARMV8_PMU_COUNTER_MASK (ARMV8_PMU_MAX_COUNTERS - 1) @@ -46,7 +48,15 @@ #define ARMV8_PMU_EVTYPE_MASK 0xc800ffff /* Mask for writable bits */ #define ARMV8_PMU_EVTYPE_EVENT 0xffff /* Mask for EVENT bits */ -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR 0 /* Software increment event */ +/* + * PMUv3 event types: required events + */ +#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00 +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03 +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04 +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10 +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11 +#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12 /* * Event filters for PMUv3 diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index c3ae239db3ee..eb0c2bd90de9 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -208,6 +208,7 @@ #define TCR_T1SZ(x) ((UL(64) - (x)) << TCR_T1SZ_OFFSET) #define TCR_TxSZ(x) (TCR_T0SZ(x) | TCR_T1SZ(x)) #define TCR_TxSZ_WIDTH 6 +#define TCR_T0SZ_MASK (((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T0SZ_OFFSET) #define TCR_IRGN0_SHIFT 8 #define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT) diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index 39f5252673f7..2142c7726e76 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -70,12 +70,13 @@ #define PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) +#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN) #define __P000 PAGE_NONE #define __P001 PAGE_READONLY #define __P010 PAGE_COPY #define __P011 PAGE_COPY -#define __P100 PAGE_READONLY_EXEC +#define __P100 PAGE_EXECONLY #define __P101 PAGE_READONLY_EXEC #define __P110 PAGE_COPY_EXEC #define __P111 PAGE_COPY_EXEC @@ -84,7 +85,7 @@ #define __S001 PAGE_READONLY #define __S010 PAGE_SHARED #define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY_EXEC +#define __S100 PAGE_EXECONLY #define __S101 PAGE_READONLY_EXEC #define __S110 PAGE_SHARED_EXEC #define __S111 PAGE_SHARED_EXEC diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index e20bd431184a..ffbb9a520563 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -73,7 +73,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT)) -#define pte_user(pte) (!!(pte_val(pte) & PTE_USER)) +#define pte_ng(pte) (!!(pte_val(pte) & PTE_NG)) #ifdef CONFIG_ARM64_HW_AFDBM #define pte_hw_dirty(pte) (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY)) @@ -84,8 +84,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_dirty(pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte)) #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) -#define pte_valid_not_user(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) +#define pte_valid_global(pte) \ + ((pte_val(pte) & (PTE_VALID | PTE_NG)) == PTE_VALID) #define pte_valid_young(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF)) @@ -155,6 +155,16 @@ static inline pte_t pte_mknoncont(pte_t pte) return clear_pte_bit(pte, __pgprot(PTE_CONT)); } +static inline pte_t pte_clear_rdonly(pte_t pte) +{ + return clear_pte_bit(pte, __pgprot(PTE_RDONLY)); +} + +static inline pte_t pte_mkpresent(pte_t pte) +{ + return set_pte_bit(pte, __pgprot(PTE_VALID)); +} + static inline pmd_t pmd_mkcont(pmd_t pmd) { return __pmd(pmd_val(pmd) | PMD_SECT_CONT); @@ -168,7 +178,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte) * Only if the new pte is valid and kernel, otherwise TLB maintenance * or update_mmu_cache() have the necessary barriers. */ - if (pte_valid_not_user(pte)) { + if (pte_valid_global(pte)) { dsb(ishst); isb(); } @@ -202,7 +212,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_val(pte) &= ~PTE_RDONLY; else pte_val(pte) |= PTE_RDONLY; - if (pte_user(pte) && pte_exec(pte) && !pte_special(pte)) + if (pte_ng(pte) && pte_exec(pte) && !pte_special(pte)) __sync_icache_dcache(pte, addr); } diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h index 5af574d632fa..6a5b28904c33 100644 --- a/arch/arm64/include/asm/probes.h +++ b/arch/arm64/include/asm/probes.h @@ -15,21 +15,22 @@ #ifndef _ARM_PROBES_H #define _ARM_PROBES_H -#include <asm/opcodes.h> - -struct kprobe; -struct arch_specific_insn; - -typedef u32 kprobe_opcode_t; -typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *); +typedef u32 probe_opcode_t; +typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); /* architecture specific copy of original instruction */ -struct arch_specific_insn { - kprobe_opcode_t *insn; +struct arch_probe_insn { + probe_opcode_t *insn; pstate_check_t *pstate_cc; - kprobes_handler_t *handler; + probes_handler_t *handler; /* restore address after step xol */ unsigned long restore; }; +#ifdef CONFIG_KPROBES +typedef u32 kprobe_opcode_t; +struct arch_specific_insn { + struct arch_probe_insn api; +}; +#endif #endif diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index ace0a96e7d6e..747c65a616ed 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -37,7 +37,6 @@ #include <asm/ptrace.h> #include <asm/types.h> -#ifdef __KERNEL__ #define STACK_TOP_MAX TASK_SIZE_64 #ifdef CONFIG_COMPAT #define AARCH32_VECTORS_BASE 0xffff0000 @@ -49,7 +48,6 @@ extern phys_addr_t arm64_dma_phys_limit; #define ARCH_LOW_ADDRESS_LIMIT (arm64_dma_phys_limit - 1) -#endif /* __KERNEL__ */ struct debug_info { /* Have we suspended stepping by a debugger? */ @@ -151,8 +149,6 @@ static inline void cpu_relax(void) asm volatile("yield" ::: "memory"); } -#define cpu_relax_lowlatency() cpu_relax() - /* Thread switching */ extern struct task_struct *cpu_switch_to(struct task_struct *prev, struct task_struct *next); @@ -190,8 +186,8 @@ static inline void spin_lock_prefetch(const void *ptr) #endif -void cpu_enable_pan(void *__unused); -void cpu_enable_uao(void *__unused); -void cpu_enable_cache_maint_trap(void *__unused); +int cpu_enable_pan(void *__unused); +int cpu_enable_uao(void *__unused); +int cpu_enable_cache_maint_trap(void *__unused); #endif /* __ASM_PROCESSOR_H */ diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index 07b8ed037dee..6afd8476c60c 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/arch/arm64/include/asm/ptdump.h @@ -16,9 +16,10 @@ #ifndef __ASM_PTDUMP_H #define __ASM_PTDUMP_H -#ifdef CONFIG_ARM64_PTDUMP +#ifdef CONFIG_ARM64_PTDUMP_CORE #include <linux/mm_types.h> +#include <linux/seq_file.h> struct addr_marker { unsigned long start_address; @@ -29,16 +30,25 @@ struct ptdump_info { struct mm_struct *mm; const struct addr_marker *markers; unsigned long base_addr; - unsigned long max_addr; }; -int ptdump_register(struct ptdump_info *info, const char *name); - +void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info); +#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS +int ptdump_debugfs_register(struct ptdump_info *info, const char *name); #else -static inline int ptdump_register(struct ptdump_info *info, const char *name) +static inline int ptdump_debugfs_register(struct ptdump_info *info, + const char *name) { return 0; } -#endif /* CONFIG_ARM64_PTDUMP */ +#endif +void ptdump_check_wx(void); +#endif /* CONFIG_ARM64_PTDUMP_CORE */ + +#ifdef CONFIG_DEBUG_WX +#define debug_checkwx() ptdump_check_wx() +#else +#define debug_checkwx() do { } while (0) +#endif #endif /* __ASM_PTDUMP_H */ diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index ada08b5b036d..513daf050e84 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -217,6 +217,14 @@ int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task); #include <asm-generic/ptrace.h> +#define procedure_link_pointer(regs) ((regs)->regs[30]) + +static inline void procedure_link_pointer_set(struct pt_regs *regs, + unsigned long val) +{ + procedure_link_pointer(regs) = val; +} + #undef profile_pc extern unsigned long profile_pc(struct pt_regs *regs); diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h new file mode 100644 index 000000000000..4e7e7067afdb --- /dev/null +++ b/arch/arm64/include/asm/sections.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 ARM Limited + * + * 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_SECTIONS_H +#define __ASM_SECTIONS_H + +#include <asm-generic/sections.h> + +extern char __alt_instructions[], __alt_instructions_end[]; +extern char __exception_text_start[], __exception_text_end[]; +extern char __hibernate_exit_text_start[], __hibernate_exit_text_end[]; +extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[]; +extern char __hyp_text_start[], __hyp_text_end[]; +extern char __idmap_text_start[], __idmap_text_end[]; +extern char __irqentry_text_start[], __irqentry_text_end[]; +extern char __mmuoff_data_start[], __mmuoff_data_end[]; + +#endif /* __ASM_SECTIONS_H */ diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 022644704a93..d050d720a1b4 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -29,11 +29,22 @@ #ifndef __ASSEMBLY__ +#include <asm/percpu.h> + #include <linux/threads.h> #include <linux/cpumask.h> #include <linux/thread_info.h> -#define raw_smp_processor_id() (current_thread_info()->cpu) +DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number); + +/* + * We don't use this_cpu_read(cpu_number) as that has implicit writes to + * preempt_count, and associated (compiler) barriers, that we'd like to avoid + * the expense of. If we're preemptible, the value can be stale at use anyway. + * And we can't use this_cpu_ptr() either, as that winds up recursing back + * here under CONFIG_DEBUG_PREEMPT=y. + */ +#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number)) struct seq_file; @@ -73,6 +84,7 @@ asmlinkage void secondary_start_kernel(void); */ struct secondary_data { void *stack; + struct task_struct *task; long status; }; diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h index 89206b568cd4..cae331d553f8 100644 --- a/arch/arm64/include/asm/spinlock.h +++ b/arch/arm64/include/asm/spinlock.h @@ -66,8 +66,7 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock) ARM64_LSE_ATOMIC_INSN( /* LL/SC */ " stxr %w1, %w0, %2\n" -" nop\n" -" nop\n", + __nops(2), /* LSE atomics */ " mov %w1, %w0\n" " cas %w0, %w0, %2\n" @@ -99,9 +98,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) /* LSE atomics */ " mov %w2, %w5\n" " ldadda %w2, %w0, %3\n" -" nop\n" -" nop\n" -" nop\n" + __nops(3) ) /* Did we get the lock? */ @@ -165,8 +162,8 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) " stlrh %w1, %0", /* LSE atomics */ " mov %w1, #1\n" - " nop\n" - " staddlh %w1, %0") + " staddlh %w1, %0\n" + __nops(1)) : "=Q" (lock->owner), "=&r" (tmp) : : "memory"); @@ -212,7 +209,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) " cbnz %w0, 1b\n" " stxr %w0, %w2, %1\n" " cbnz %w0, 2b\n" - " nop", + __nops(1), /* LSE atomics */ "1: mov %w0, wzr\n" "2: casa %w0, %w2, %1\n" @@ -241,8 +238,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) /* LSE atomics */ " mov %w0, wzr\n" " casa %w0, %w2, %1\n" - " nop\n" - " nop") + __nops(2)) : "=&r" (tmp), "+Q" (rw->lock) : "r" (0x80000000) : "memory"); @@ -290,8 +286,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw) " add %w0, %w0, #1\n" " tbnz %w0, #31, 1b\n" " stxr %w1, %w0, %2\n" - " nop\n" - " cbnz %w1, 2b", + " cbnz %w1, 2b\n" + __nops(1), /* LSE atomics */ "1: wfe\n" "2: ldxr %w0, %2\n" @@ -317,9 +313,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) " cbnz %w1, 1b", /* LSE atomics */ " movn %w0, #0\n" - " nop\n" - " nop\n" - " staddl %w0, %2") + " staddl %w0, %2\n" + __nops(2)) : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock) : : "memory"); @@ -344,7 +339,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) " tbnz %w1, #31, 1f\n" " casa %w0, %w1, %2\n" " sbc %w1, %w1, %w0\n" - " nop\n" + __nops(1) "1:") : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock) : diff --git a/arch/arm64/include/asm/stack_pointer.h b/arch/arm64/include/asm/stack_pointer.h new file mode 100644 index 000000000000..ffcdf742cddf --- /dev/null +++ b/arch/arm64/include/asm/stack_pointer.h @@ -0,0 +1,9 @@ +#ifndef __ASM_STACK_POINTER_H +#define __ASM_STACK_POINTER_H + +/* + * how to get the current stack pointer from C + */ +register unsigned long current_stack_pointer asm ("sp"); + +#endif /* __ASM_STACK_POINTER_H */ diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h index 024d623f662e..de5600f40adf 100644 --- a/arch/arm64/include/asm/suspend.h +++ b/arch/arm64/include/asm/suspend.h @@ -1,7 +1,7 @@ #ifndef __ASM_SUSPEND_H #define __ASM_SUSPEND_H -#define NR_CTX_REGS 10 +#define NR_CTX_REGS 12 #define NR_CALLEE_SAVED_REGS 12 /* @@ -47,4 +47,7 @@ int swsusp_arch_resume(void); int arch_hibernation_header_save(void *addr, unsigned int max_size); int arch_hibernation_header_restore(void *addr); +/* Used to resume on the CPU we hibernated on */ +int hibernate_resume_nonboot_cpu_disable(void); + #endif diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index cc06794b7346..98ae03f8eedd 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -22,8 +22,6 @@ #include <linux/stringify.h> -#include <asm/opcodes.h> - /* * ARMv8 ARM reserves the following encoding for system registers: * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview", @@ -37,6 +35,33 @@ #define sys_reg(op0, op1, crn, crm, op2) \ ((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5)) +#ifndef CONFIG_BROKEN_GAS_INST + +#ifdef __ASSEMBLY__ +#define __emit_inst(x) .inst (x) +#else +#define __emit_inst(x) ".inst " __stringify((x)) "\n\t" +#endif + +#else /* CONFIG_BROKEN_GAS_INST */ + +#ifndef CONFIG_CPU_BIG_ENDIAN +#define __INSTR_BSWAP(x) (x) +#else /* CONFIG_CPU_BIG_ENDIAN */ +#define __INSTR_BSWAP(x) ((((x) << 24) & 0xff000000) | \ + (((x) << 8) & 0x00ff0000) | \ + (((x) >> 8) & 0x0000ff00) | \ + (((x) >> 24) & 0x000000ff)) +#endif /* CONFIG_CPU_BIG_ENDIAN */ + +#ifdef __ASSEMBLY__ +#define __emit_inst(x) .long __INSTR_BSWAP(x) +#else /* __ASSEMBLY__ */ +#define __emit_inst(x) ".long " __stringify(__INSTR_BSWAP(x)) "\n\t" +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_BROKEN_GAS_INST */ + #define SYS_MIDR_EL1 sys_reg(3, 0, 0, 0, 0) #define SYS_MPIDR_EL1 sys_reg(3, 0, 0, 0, 5) #define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6) @@ -81,10 +106,10 @@ #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) #define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3) -#define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\ - (!!x)<<8 | 0x1f) -#define SET_PSTATE_UAO(x) __inst_arm(0xd5000000 | REG_PSTATE_UAO_IMM |\ - (!!x)<<8 | 0x1f) +#define SET_PSTATE_PAN(x) __emit_inst(0xd5000000 | REG_PSTATE_PAN_IMM | \ + (!!x)<<8 | 0x1f) +#define SET_PSTATE_UAO(x) __emit_inst(0xd5000000 | REG_PSTATE_UAO_IMM | \ + (!!x)<<8 | 0x1f) /* Common SCTLR_ELx flags. */ #define SCTLR_ELx_EE (1 << 25) @@ -100,6 +125,7 @@ /* SCTLR_EL1 specific flags. */ #define SCTLR_EL1_UCI (1 << 26) #define SCTLR_EL1_SPAN (1 << 23) +#define SCTLR_EL1_UCT (1 << 15) #define SCTLR_EL1_SED (1 << 8) #define SCTLR_EL1_CP15BEN (1 << 5) @@ -227,11 +253,11 @@ .equ .L__reg_num_xzr, 31 .macro mrs_s, rt, sreg - .inst 0xd5200000|(\sreg)|(.L__reg_num_\rt) + __emit_inst(0xd5200000|(\sreg)|(.L__reg_num_\rt)) .endm .macro msr_s, sreg, rt - .inst 0xd5000000|(\sreg)|(.L__reg_num_\rt) + __emit_inst(0xd5000000|(\sreg)|(.L__reg_num_\rt)) .endm #else @@ -245,24 +271,14 @@ asm( " .equ .L__reg_num_xzr, 31\n" "\n" " .macro mrs_s, rt, sreg\n" -" .inst 0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n" + __emit_inst(0xd5200000|(\\sreg)|(.L__reg_num_\\rt)) " .endm\n" "\n" " .macro msr_s, sreg, rt\n" -" .inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n" + __emit_inst(0xd5000000|(\\sreg)|(.L__reg_num_\\rt)) " .endm\n" ); -static inline void config_sctlr_el1(u32 clear, u32 set) -{ - u32 val; - - asm volatile("mrs %0, sctlr_el1" : "=r" (val)); - val &= ~clear; - val |= set; - asm volatile("msr sctlr_el1, %0" : : "r" (val)); -} - /* * Unlike read_cpuid, calls to read_sysreg are never expected to be * optimized away or replaced with synthetic values. @@ -273,12 +289,41 @@ static inline void config_sctlr_el1(u32 clear, u32 set) __val; \ }) +/* + * The "Z" constraint normally means a zero immediate, but when combined with + * the "%x0" template means XZR. + */ #define write_sysreg(v, r) do { \ u64 __val = (u64)v; \ - asm volatile("msr " __stringify(r) ", %0" \ - : : "r" (__val)); \ + asm volatile("msr " __stringify(r) ", %x0" \ + : : "rZ" (__val)); \ +} while (0) + +/* + * For registers without architectural names, or simply unsupported by + * GAS. + */ +#define read_sysreg_s(r) ({ \ + u64 __val; \ + asm volatile("mrs_s %0, " __stringify(r) : "=r" (__val)); \ + __val; \ +}) + +#define write_sysreg_s(v, r) do { \ + u64 __val = (u64)v; \ + asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \ } while (0) +static inline void config_sctlr_el1(u32 clear, u32 set) +{ + u32 val; + + val = read_sysreg(sctlr_el1); + val &= ~clear; + val |= set; + write_sysreg(val, sctlr_el1); +} + #endif #endif /* __ASM_SYSREG_H */ diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 57f110bea6a8..bc812435bc76 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -56,12 +56,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); __show_ratelimited; \ }) -#define UDBG_UNDEFINED (1 << 0) -#define UDBG_SYSCALL (1 << 1) -#define UDBG_BADABORT (1 << 2) -#define UDBG_SEGV (1 << 3) -#define UDBG_BUS (1 << 4) - #endif /* __ASSEMBLY__ */ #endif /* __ASM_SYSTEM_MISC_H */ diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index abd64bd1f6d9..46c3b93cf865 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -36,55 +36,31 @@ struct task_struct; +#include <asm/stack_pointer.h> #include <asm/types.h> typedef unsigned long mm_segment_t; /* * low level task data that entry.S needs immediate access to. - * __switch_to() assumes cpu_context follows immediately after cpu_domain. */ struct thread_info { unsigned long flags; /* low level flags */ mm_segment_t addr_limit; /* address limit */ - struct task_struct *task; /* main task structure */ +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + u64 ttbr0; /* saved TTBR0_EL1 */ +#endif int preempt_count; /* 0 => preemptable, <0 => bug */ - int cpu; /* cpu */ }; #define INIT_THREAD_INFO(tsk) \ { \ - .task = &tsk, \ - .flags = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ .addr_limit = KERNEL_DS, \ } -#define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) -/* - * how to get the current stack pointer from C - */ -register unsigned long current_stack_pointer asm ("sp"); - -/* - * how to get the thread information struct from C - */ -static inline struct thread_info *current_thread_info(void) __attribute_const__; - -/* - * struct thread_info can be accessed directly via sp_el0. - */ -static inline struct thread_info *current_thread_info(void) -{ - unsigned long sp_el0; - - asm ("mrs %0, sp_el0" : "=r" (sp_el0)); - - return (struct thread_info *)sp_el0; -} - #define thread_saved_pc(tsk) \ ((unsigned long)(tsk->thread.cpu_context.pc)) #define thread_saved_sp(tsk) \ @@ -109,6 +85,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NEED_RESCHED 1 #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */ +#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */ #define TIF_NOHZ 7 #define TIF_SYSCALL_TRACE 8 #define TIF_SYSCALL_AUDIT 9 @@ -129,10 +106,12 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) +#define _TIF_UPROBE (1 << TIF_UPROBE) #define _TIF_32BIT (1 << TIF_32BIT) #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE) + _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \ + _TIF_UPROBE) #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index b460ae28e346..deab52374119 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -25,6 +25,24 @@ #include <asm/cputype.h> /* + * Raw TLBI operations. + * + * Where necessary, use the __tlbi() macro to avoid asm() + * boilerplate. Drivers and most kernel code should use the TLB + * management routines in preference to the macro below. + * + * The macro can be used as __tlbi(op) or __tlbi(op, arg), depending + * on whether a particular TLBI operation takes an argument or + * not. The macros handles invoking the asm with or without the + * register argument as appropriate. + */ +#define __TLBI_0(op, arg) asm ("tlbi " #op) +#define __TLBI_1(op, arg) asm ("tlbi " #op ", %0" : : "r" (arg)) +#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg) + +#define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) + +/* * TLB Management * ============== * @@ -66,7 +84,7 @@ static inline void local_flush_tlb_all(void) { dsb(nshst); - asm("tlbi vmalle1"); + __tlbi(vmalle1); dsb(nsh); isb(); } @@ -74,7 +92,7 @@ static inline void local_flush_tlb_all(void) static inline void flush_tlb_all(void) { dsb(ishst); - asm("tlbi vmalle1is"); + __tlbi(vmalle1is); dsb(ish); isb(); } @@ -84,7 +102,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) unsigned long asid = ASID(mm) << 48; dsb(ishst); - asm("tlbi aside1is, %0" : : "r" (asid)); + __tlbi(aside1is, asid); dsb(ish); } @@ -94,7 +112,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr = uaddr >> 12 | (ASID(vma->vm_mm) << 48); dsb(ishst); - asm("tlbi vale1is, %0" : : "r" (addr)); + __tlbi(vale1is, addr); dsb(ish); } @@ -122,9 +140,9 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { if (last_level) - asm("tlbi vale1is, %0" : : "r"(addr)); + __tlbi(vale1is, addr); else - asm("tlbi vae1is, %0" : : "r"(addr)); + __tlbi(vae1is, addr); } dsb(ish); } @@ -149,7 +167,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) - asm("tlbi vaae1is, %0" : : "r"(addr)); + __tlbi(vaae1is, addr); dsb(ish); isb(); } @@ -163,7 +181,7 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, { unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); - asm("tlbi vae1is, %0" : : "r" (addr)); + __tlbi(vae1is, addr); dsb(ish); } diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index 9cd03f3e812f..02e9035b0685 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -19,6 +19,7 @@ #define __ASM_TRAP_H #include <linux/list.h> +#include <asm/sections.h> struct pt_regs; @@ -39,9 +40,6 @@ void arm64_notify_segfault(struct pt_regs *regs, unsigned long addr); #ifdef CONFIG_FUNCTION_GRAPH_TRACER static inline int __in_irqentry_text(unsigned long ptr) { - extern char __irqentry_text_start[]; - extern char __irqentry_text_end[]; - return ptr >= (unsigned long)&__irqentry_text_start && ptr < (unsigned long)&__irqentry_text_end; } @@ -54,8 +52,6 @@ static inline int __in_irqentry_text(unsigned long ptr) static inline int in_exception_text(unsigned long ptr) { - extern char __exception_text_start[]; - extern char __exception_text_end[]; int in; in = ptr >= (unsigned long)&__exception_text_start && diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index c47257c91b77..46da3ea638bb 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -18,17 +18,20 @@ #ifndef __ASM_UACCESS_H #define __ASM_UACCESS_H +#include <asm/alternative.h> +#include <asm/kernel-pgtable.h> +#include <asm/sysreg.h> + /* * User space memory access functions */ +#include <linux/bitops.h> #include <linux/kasan-checks.h> #include <linux/string.h> #include <linux/thread_info.h> -#include <asm/alternative.h> #include <asm/cpufeature.h> #include <asm/ptrace.h> -#include <asm/sysreg.h> #include <asm/errno.h> #include <asm/memory.h> #include <asm/compiler.h> @@ -102,6 +105,13 @@ static inline void set_fs(mm_segment_t fs) flag; \ }) +/* + * When dealing with data aborts or instruction traps we may end up with + * a tagged userland pointer. Clear the tag to get a sane pointer to pass + * on to access_ok(), for instance. + */ +#define untagged_addr(addr) sign_extend64(addr, 55) + #define access_ok(type, addr, size) __range_ok(addr, size) #define user_addr_max get_fs @@ -112,6 +122,99 @@ static inline void set_fs(mm_segment_t fs) " .popsection\n" /* + * User access enabling/disabling. + */ +#ifdef CONFIG_ARM64_SW_TTBR0_PAN +static inline void __uaccess_ttbr0_disable(void) +{ + unsigned long ttbr; + + /* reserved_ttbr0 placed at the end of swapper_pg_dir */ + ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE; + write_sysreg(ttbr, ttbr0_el1); + isb(); +} + +static inline void __uaccess_ttbr0_enable(void) +{ + unsigned long flags; + + /* + * Disable interrupts to avoid preemption between reading the 'ttbr0' + * variable and the MSR. A context switch could trigger an ASID + * roll-over and an update of 'ttbr0'. + */ + local_irq_save(flags); + write_sysreg(current_thread_info()->ttbr0, ttbr0_el1); + isb(); + local_irq_restore(flags); +} + +static inline bool uaccess_ttbr0_disable(void) +{ + if (!system_uses_ttbr0_pan()) + return false; + __uaccess_ttbr0_disable(); + return true; +} + +static inline bool uaccess_ttbr0_enable(void) +{ + if (!system_uses_ttbr0_pan()) + return false; + __uaccess_ttbr0_enable(); + return true; +} +#else +static inline bool uaccess_ttbr0_disable(void) +{ + return false; +} + +static inline bool uaccess_ttbr0_enable(void) +{ + return false; +} +#endif + +#define __uaccess_disable(alt) \ +do { \ + if (!uaccess_ttbr0_disable()) \ + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), alt, \ + CONFIG_ARM64_PAN)); \ +} while (0) + +#define __uaccess_enable(alt) \ +do { \ + if (!uaccess_ttbr0_enable()) \ + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), alt, \ + CONFIG_ARM64_PAN)); \ +} while (0) + +static inline void uaccess_disable(void) +{ + __uaccess_disable(ARM64_HAS_PAN); +} + +static inline void uaccess_enable(void) +{ + __uaccess_enable(ARM64_HAS_PAN); +} + +/* + * These functions are no-ops when UAO is present. + */ +static inline void uaccess_disable_not_uao(void) +{ + __uaccess_disable(ARM64_ALT_PAN_NOT_UAO); +} + +static inline void uaccess_enable_not_uao(void) +{ + __uaccess_enable(ARM64_ALT_PAN_NOT_UAO); +} + +/* * The "__xxx" versions of the user access functions do not verify the address * space - it must have been done previously with a separate "access_ok()" * call. @@ -138,8 +241,7 @@ static inline void set_fs(mm_segment_t fs) do { \ unsigned long __gu_val; \ __chk_user_ptr(ptr); \ - asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\ - CONFIG_ARM64_PAN)); \ + uaccess_enable_not_uao(); \ switch (sizeof(*(ptr))) { \ case 1: \ __get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr), \ @@ -160,9 +262,8 @@ do { \ default: \ BUILD_BUG(); \ } \ + uaccess_disable_not_uao(); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ - asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\ - CONFIG_ARM64_PAN)); \ } while (0) #define __get_user(x, ptr) \ @@ -207,8 +308,7 @@ do { \ do { \ __typeof__(*(ptr)) __pu_val = (x); \ __chk_user_ptr(ptr); \ - asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\ - CONFIG_ARM64_PAN)); \ + uaccess_enable_not_uao(); \ switch (sizeof(*(ptr))) { \ case 1: \ __put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr), \ @@ -229,8 +329,7 @@ do { \ default: \ BUILD_BUG(); \ } \ - asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\ - CONFIG_ARM64_PAN)); \ + uaccess_disable_not_uao(); \ } while (0) #define __put_user(x, ptr) \ @@ -278,14 +377,16 @@ static inline unsigned long __must_check __copy_to_user(void __user *to, const v static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { + unsigned long res = n; kasan_check_write(to, n); if (access_ok(VERIFY_READ, from, n)) { check_object_size(to, n, false); - n = __arch_copy_from_user(to, from, n); - } else /* security hole - plug it */ - memset(to, 0, n); - return n; + res = __arch_copy_from_user(to, from, n); + } + if (unlikely(res)) + memset(to + (n - res), 0, res); + return res; } static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h new file mode 100644 index 000000000000..8d004073d0e8 --- /dev/null +++ b/arch/arm64/include/asm/uprobes.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.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. + */ + +#ifndef _ASM_UPROBES_H +#define _ASM_UPROBES_H + +#include <asm/debug-monitors.h> +#include <asm/insn.h> +#include <asm/probes.h> + +#define MAX_UINSN_BYTES AARCH64_INSN_SIZE + +#define UPROBE_SWBP_INSN BRK64_OPCODE_UPROBES +#define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE +#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES + +typedef u32 uprobe_opcode_t; + +struct arch_uprobe_task { +}; + +struct arch_uprobe { + union { + u8 insn[MAX_UINSN_BYTES]; + u8 ixol[MAX_UINSN_BYTES]; + }; + struct arch_probe_insn api; + bool simulate; +}; + +#endif diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h index 1788545f25bc..fea10736b11f 100644 --- a/arch/arm64/include/asm/virt.h +++ b/arch/arm64/include/asm/virt.h @@ -45,6 +45,8 @@ #ifndef __ASSEMBLY__ #include <asm/ptrace.h> +#include <asm/sections.h> +#include <asm/sysreg.h> /* * __boot_cpu_mode records what mode CPUs were booted in. @@ -75,10 +77,7 @@ static inline bool is_hyp_mode_mismatched(void) static inline bool is_kernel_in_hyp_mode(void) { - u64 el; - - asm("mrs %0, CurrentEL" : "=r" (el)); - return el == CurrentEL_EL2; + return read_sysreg(CurrentEL) == CurrentEL_EL2; } #ifdef CONFIG_ARM64_VHE @@ -87,14 +86,6 @@ extern void verify_cpu_run_el(void); static inline void verify_cpu_run_el(void) {} #endif -/* The section containing the hypervisor idmap text */ -extern char __hyp_idmap_text_start[]; -extern char __hyp_idmap_text_end[]; - -/* The section containing the hypervisor text */ -extern char __hyp_text_start[]; -extern char __hyp_text_end[]; - #endif /* __ASSEMBLY__ */ #endif /* ! __ASM__VIRT_H */ diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h index 2b79b8a89457..b0d708ff7f4e 100644 --- a/arch/arm64/include/asm/word-at-a-time.h +++ b/arch/arm64/include/asm/word-at-a-time.h @@ -16,7 +16,7 @@ #ifndef __ASM_WORD_AT_A_TIME_H #define __ASM_WORD_AT_A_TIME_H -#include <asm/uaccess.h> +#include <linux/uaccess.h> #ifndef __AARCH64EB__ diff --git a/arch/arm64/include/asm/xen/hypercall.h b/arch/arm64/include/asm/xen/hypercall.h index 74b0c423ff5b..3522cbaed316 100644 --- a/arch/arm64/include/asm/xen/hypercall.h +++ b/arch/arm64/include/asm/xen/hypercall.h @@ -1 +1 @@ -#include <../../arm/include/asm/xen/hypercall.h> +#include <xen/arm/hypercall.h> diff --git a/arch/arm64/include/asm/xen/hypervisor.h b/arch/arm64/include/asm/xen/hypervisor.h index f263da8e8769..d6e7709d0688 100644 --- a/arch/arm64/include/asm/xen/hypervisor.h +++ b/arch/arm64/include/asm/xen/hypervisor.h @@ -1 +1 @@ -#include <../../arm/include/asm/xen/hypervisor.h> +#include <xen/arm/hypervisor.h> diff --git a/arch/arm64/include/asm/xen/interface.h b/arch/arm64/include/asm/xen/interface.h index 44457aebeed4..88c0d75da190 100644 --- a/arch/arm64/include/asm/xen/interface.h +++ b/arch/arm64/include/asm/xen/interface.h @@ -1 +1 @@ -#include <../../arm/include/asm/xen/interface.h> +#include <xen/arm/interface.h> diff --git a/arch/arm64/include/asm/xen/page-coherent.h b/arch/arm64/include/asm/xen/page-coherent.h index 2052102b4e02..b3ef061d8b74 100644 --- a/arch/arm64/include/asm/xen/page-coherent.h +++ b/arch/arm64/include/asm/xen/page-coherent.h @@ -1 +1 @@ -#include <../../arm/include/asm/xen/page-coherent.h> +#include <xen/arm/page-coherent.h> diff --git a/arch/arm64/include/asm/xen/page.h b/arch/arm64/include/asm/xen/page.h index bed87ec36780..31bbc803cecb 100644 --- a/arch/arm64/include/asm/xen/page.h +++ b/arch/arm64/include/asm/xen/page.h @@ -1 +1 @@ -#include <../../arm/include/asm/xen/page.h> +#include <xen/arm/page.h> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 14f7b651c787..7d66bbaafc0c 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -10,6 +10,8 @@ CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_insn.o = -pg CFLAGS_REMOVE_return_address.o = -pg +CFLAGS_setup.o = -DUTS_MACHINE='"$(UTS_MACHINE)"' + # Object file lists. arm64-obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ entry-fpsimd.o process.o ptrace.o setup.o signal.o \ diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 3e4f1a45b125..64d9cbd61678 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -24,6 +24,7 @@ #include <linux/memblock.h> #include <linux/of_fdt.h> #include <linux/smp.h> +#include <linux/serial_core.h> #include <asm/cputype.h> #include <asm/cpu_ops.h> @@ -131,14 +132,13 @@ static int __init acpi_fadt_sanity_check(void) struct acpi_table_header *table; struct acpi_table_fadt *fadt; acpi_status status; - acpi_size tbl_size; int ret = 0; /* * FADT is required on arm64; retrieve it to check its presence * and carry out revision and ACPI HW reduced compliancy tests */ - status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size); + status = acpi_get_table(ACPI_SIG_FADT, 0, &table); if (ACPI_FAILURE(status)) { const char *msg = acpi_format_exception(status); @@ -169,10 +169,10 @@ static int __init acpi_fadt_sanity_check(void) out: /* - * acpi_get_table_with_size() creates FADT table mapping that + * acpi_get_table() creates FADT table mapping that * should be released after parsing and before resuming boot */ - early_acpi_os_unmap_memory(table, tbl_size); + acpi_put_table(table); return ret; } @@ -206,7 +206,7 @@ void __init acpi_boot_table_init(void) if (param_acpi_off || (!param_acpi_on && !param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) - return; + goto done; /* * ACPI is disabled at this point. Enable it in order to parse @@ -226,6 +226,14 @@ void __init acpi_boot_table_init(void) if (!param_acpi_force) disable_acpi(); } + +done: + if (acpi_disabled) { + if (earlycon_init_is_deferred) + early_init_dt_scan_chosen_stdout(); + } else { + parse_spcr(earlycon_init_is_deferred); + } } #ifdef CONFIG_ACPI_APEI diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c index f85149cc7c71..f01fab637dab 100644 --- a/arch/arm64/kernel/acpi_numa.c +++ b/arch/arm64/kernel/acpi_numa.c @@ -105,8 +105,10 @@ int __init arm64_acpi_numa_init(void) int ret; ret = acpi_numa_init(); - if (ret) + if (ret) { + pr_info("Failed to initialise from firmware\n"); return ret; + } return srat_disabled() ? -EINVAL : 0; } diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c index d2ee1b21a10d..06d650f61da7 100644 --- a/arch/arm64/kernel/alternative.c +++ b/arch/arm64/kernel/alternative.c @@ -25,14 +25,13 @@ #include <asm/alternative.h> #include <asm/cpufeature.h> #include <asm/insn.h> +#include <asm/sections.h> #include <linux/stop_machine.h> #define __ALT_PTR(a,f) (u32 *)((void *)&(a)->f + (a)->f) #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset) #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset) -extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; - struct alt_region { struct alt_instr *begin; struct alt_instr *end; @@ -59,6 +58,8 @@ static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc) BUG(); } +#define align_down(x, a) ((unsigned long)(x) & ~(((unsigned long)(a)) - 1)) + static u32 get_alt_insn(struct alt_instr *alt, u32 *insnptr, u32 *altinsnptr) { u32 insn; @@ -80,6 +81,25 @@ static u32 get_alt_insn(struct alt_instr *alt, u32 *insnptr, u32 *altinsnptr) offset = target - (unsigned long)insnptr; insn = aarch64_set_branch_offset(insn, offset); } + } else if (aarch64_insn_is_adrp(insn)) { + s32 orig_offset, new_offset; + unsigned long target; + + /* + * If we're replacing an adrp instruction, which uses PC-relative + * immediate addressing, adjust the offset to reflect the new + * PC. adrp operates on 4K aligned addresses. + */ + orig_offset = aarch64_insn_adrp_get_offset(insn); + target = align_down(altinsnptr, SZ_4K) + orig_offset; + new_offset = target - align_down(insnptr, SZ_4K); + insn = aarch64_insn_adrp_set_offset(insn, new_offset); + } else if (aarch64_insn_uses_literal(insn)) { + /* + * Disallow patching unhandled instructions using PC relative + * literal addresses + */ + BUG(); } return insn; @@ -124,8 +144,8 @@ static int __apply_alternatives_multi_stop(void *unused) { static int patched = 0; struct alt_region region = { - .begin = __alt_instructions, - .end = __alt_instructions_end, + .begin = (struct alt_instr *)__alt_instructions, + .end = (struct alt_instr *)__alt_instructions_end, }; /* We always have a CPU 0 at this point (__init) */ diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 42ffdb54e162..ecf9298a12d4 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -14,14 +14,12 @@ #include <linux/slab.h> #include <linux/sysctl.h> -#include <asm/alternative.h> #include <asm/cpufeature.h> #include <asm/insn.h> -#include <asm/opcodes.h> #include <asm/sysreg.h> #include <asm/system_misc.h> #include <asm/traps.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/cpufeature.h> #define CREATE_TRACE_POINTS @@ -280,35 +278,43 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table) /* * Error-checking SWP macros implemented using ldxr{b}/stxr{b} */ -#define __user_swpX_asm(data, addr, res, temp, B) \ + +/* Arbitrary constant to ensure forward-progress of the LL/SC loop */ +#define __SWP_LL_SC_LOOPS 4 + +#define __user_swpX_asm(data, addr, res, temp, temp2, B) \ +do { \ + uaccess_enable(); \ __asm__ __volatile__( \ - ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \ - CONFIG_ARM64_PAN) \ - "0: ldxr"B" %w2, [%3]\n" \ - "1: stxr"B" %w0, %w1, [%3]\n" \ + " mov %w3, %w7\n" \ + "0: ldxr"B" %w2, [%4]\n" \ + "1: stxr"B" %w0, %w1, [%4]\n" \ " cbz %w0, 2f\n" \ - " mov %w0, %w4\n" \ + " sub %w3, %w3, #1\n" \ + " cbnz %w3, 0b\n" \ + " mov %w0, %w5\n" \ " b 3f\n" \ "2:\n" \ " mov %w1, %w2\n" \ "3:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ - "4: mov %w0, %w5\n" \ + "4: mov %w0, %w6\n" \ " b 3b\n" \ " .popsection" \ _ASM_EXTABLE(0b, 4b) \ _ASM_EXTABLE(1b, 4b) \ - ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ - CONFIG_ARM64_PAN) \ - : "=&r" (res), "+r" (data), "=&r" (temp) \ - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ - : "memory") - -#define __user_swp_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "") -#define __user_swpb_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "b") + : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \ + : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT), \ + "i" (__SWP_LL_SC_LOOPS) \ + : "memory"); \ + uaccess_disable(); \ +} while (0) + +#define __user_swp_asm(data, addr, res, temp, temp2) \ + __user_swpX_asm(data, addr, res, temp, temp2, "") +#define __user_swpb_asm(data, addr, res, temp, temp2) \ + __user_swpX_asm(data, addr, res, temp, temp2, "b") /* * Bit 22 of the instruction encoding distinguishes between @@ -328,12 +334,12 @@ static int emulate_swpX(unsigned int address, unsigned int *data, } while (1) { - unsigned long temp; + unsigned long temp, temp2; if (type == TYPE_SWPB) - __user_swpb_asm(*data, address, res, temp); + __user_swpb_asm(*data, address, res, temp, temp2); else - __user_swp_asm(*data, address, res, temp); + __user_swp_asm(*data, address, res, temp, temp2); if (likely(res != -EAGAIN) || signal_pending(current)) break; @@ -344,6 +350,10 @@ static int emulate_swpX(unsigned int address, unsigned int *data, return res; } +#define ARM_OPCODE_CONDTEST_FAIL 0 +#define ARM_OPCODE_CONDTEST_PASS 1 +#define ARM_OPCODE_CONDTEST_UNCOND 2 + #define ARM_OPCODE_CONDITION_UNCOND 0xf static unsigned int __kprobes aarch32_check_condition(u32 opcode, u32 psr) @@ -630,7 +640,7 @@ static int __init armv8_deprecated_init(void) } cpuhp_setup_state_nocalls(CPUHP_AP_ARM64_ISNDEP_STARTING, - "AP_ARM64_ISNDEP_STARTING", + "arm64/isndep:starting", run_all_insn_set_hw_mode, NULL); register_insn_emulation_sysctl(ctl_abi); diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 05070b72fc28..bc049afc73a7 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -23,6 +23,7 @@ #include <linux/dma-mapping.h> #include <linux/kvm_host.h> #include <linux/suspend.h> +#include <asm/cpufeature.h> #include <asm/thread_info.h> #include <asm/memory.h> #include <asm/smp_plat.h> @@ -35,11 +36,13 @@ int main(void) { DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); + DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); + DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count)); + DEFINE(TSK_TI_ADDR_LIMIT, offsetof(struct task_struct, thread_info.addr_limit)); +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0)); +#endif + DEFINE(TSK_STACK, offsetof(struct task_struct, stack)); BLANK(); DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context)); BLANK(); @@ -122,6 +125,7 @@ int main(void) DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); BLANK(); DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack)); + DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task)); BLANK(); #ifdef CONFIG_KVM_ARM_HOST DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); @@ -145,5 +149,6 @@ int main(void) DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address)); DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address)); DEFINE(HIBERN_PBE_NEXT, offsetof(struct pbe, next)); + DEFINE(ARM64_FTR_SYSVAL, offsetof(struct arm64_ftr_reg, sys_val)); return 0; } diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index b8629d52fba9..9617301f76b5 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -39,7 +39,7 @@ static inline enum cache_type get_cache_type(int level) if (level > MAX_CACHE_LEVEL) return CACHE_TYPE_NOCACHE; - asm volatile ("mrs %x0, clidr_el1" : "=r" (clidr)); + clidr = read_sysreg(clidr_el1); return CLIDR_CTYPE(clidr, level); } @@ -55,11 +55,9 @@ u64 __attribute_const__ cache_get_ccsidr(u64 csselr) WARN_ON(preemptible()); - /* Put value into CSSELR */ - asm volatile("msr csselr_el1, %x0" : : "r" (csselr)); + write_sysreg(csselr, csselr_el1); isb(); - /* Read result out of CCSIDR */ - asm volatile("mrs %x0, ccsidr_el1" : "=r" (ccsidr)); + ccsidr = read_sysreg(ccsidr_el1); return ccsidr; } diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 82b0fc2e637b..b75e917aac46 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -30,6 +30,22 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) entry->midr_range_max); } +static bool +has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry, + int scope) +{ + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); + return (read_cpuid_cachetype() & arm64_ftr_reg_ctrel0.strict_mask) != + (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask); +} + +static int cpu_enable_trap_ctr_access(void *__unused) +{ + /* Clear SCTLR_EL1.UCT */ + config_sctlr_el1(SCTLR_EL1_UCT, 0); + return 0; +} + #define MIDR_RANGE(model, min, max) \ .def_scope = SCOPE_LOCAL_CPU, \ .matches = is_affected_midr_range, \ @@ -108,6 +124,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { }, #endif { + .desc = "Mismatched cache line size", + .capability = ARM64_MISMATCHED_CACHE_LINE_SIZE, + .matches = has_mismatched_cache_line_size, + .def_scope = SCOPE_LOCAL_CPU, + .enable = cpu_enable_trap_ctr_access, + }, + { } }; @@ -116,7 +139,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = { * and the related information is freed soon after. If the new CPU requires * an errata not detected at boot, fail this CPU. */ -void verify_local_cpu_errata(void) +void verify_local_cpu_errata_workarounds(void) { const struct arm64_cpu_capabilities *caps = arm64_errata; @@ -131,7 +154,7 @@ void verify_local_cpu_errata(void) } } -void check_local_cpu_errata(void) +void update_cpu_errata_workarounds(void) { update_cpu_capabilities(arm64_errata, "enabling workaround for"); } diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c index c7cfb8fe06f9..e137ceaf5016 100644 --- a/arch/arm64/kernel/cpu_ops.c +++ b/arch/arm64/kernel/cpu_ops.c @@ -17,6 +17,7 @@ */ #include <linux/acpi.h> +#include <linux/cache.h> #include <linux/errno.h> #include <linux/of.h> #include <linux/string.h> @@ -28,7 +29,7 @@ extern const struct cpu_operations smp_spin_table_ops; extern const struct cpu_operations acpi_parking_protocol_ops; extern const struct cpu_operations cpu_psci_ops; -const struct cpu_operations *cpu_ops[NR_CPUS]; +const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init; static const struct cpu_operations *dt_supported_cpu_ops[] __initconst = { &smp_spin_table_ops, diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 62272eac1352..fdf8f045929f 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -19,7 +19,9 @@ #define pr_fmt(fmt) "CPU features: " fmt #include <linux/bsearch.h> +#include <linux/cpumask.h> #include <linux/sort.h> +#include <linux/stop_machine.h> #include <linux/types.h> #include <asm/cpu.h> #include <asm/cpufeature.h> @@ -45,6 +47,10 @@ unsigned int compat_elf_hwcap2 __read_mostly; #endif DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); +EXPORT_SYMBOL(cpu_hwcaps); + +DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS); +EXPORT_SYMBOL(cpu_hwcap_keys); #define __ARM64_FTR_BITS(SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ { \ @@ -74,7 +80,7 @@ static bool __maybe_unused cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused); -static struct arm64_ftr_bits ftr_id_aa64isar0[] = { +static const struct arm64_ftr_bits ftr_id_aa64isar0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 24, 4, 0), @@ -87,7 +93,7 @@ static struct arm64_ftr_bits ftr_id_aa64isar0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_aa64pfr0[] = { +static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), @@ -101,7 +107,7 @@ static struct arm64_ftr_bits ftr_id_aa64pfr0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { +static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), @@ -119,7 +125,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { +static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_LOR_SHIFT, 4, 0), @@ -130,7 +136,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { +static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0), @@ -139,7 +145,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_ctr[] = { +static const struct arm64_ftr_bits ftr_ctr[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RAO */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ @@ -147,15 +153,21 @@ static struct arm64_ftr_bits ftr_ctr[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ /* * Linux can handle differing I-cache policies. Userspace JITs will - * make use of *minLine + * make use of *minLine. + * If we have differing I-cache policies, report it as the weakest - AIVIVT. */ - ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0), /* L1Ip */ + ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, ICACHE_POLICY_AIVIVT), /* L1Ip */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* IminLine */ ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_mmfr0[] = { +struct arm64_ftr_reg arm64_ftr_reg_ctrel0 = { + .name = "SYS_CTR_EL0", + .ftr_bits = ftr_ctr +}; + +static const struct arm64_ftr_bits ftr_id_mmfr0[] = { S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 4, 0xf), /* InnerShr */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 24, 4, 0), /* FCSE */ ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, 20, 4, 0), /* AuxReg */ @@ -167,7 +179,7 @@ static struct arm64_ftr_bits ftr_id_mmfr0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_aa64dfr0[] = { +static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0), @@ -178,14 +190,14 @@ static struct arm64_ftr_bits ftr_id_aa64dfr0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_mvfr2[] = { +static const struct arm64_ftr_bits ftr_mvfr2[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 24, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0), /* FPMisc */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0), /* SIMDMisc */ ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_dczid[] = { +static const struct arm64_ftr_bits ftr_dczid[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 5, 27, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 1, 1), /* DZP */ ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* BS */ @@ -193,7 +205,7 @@ static struct arm64_ftr_bits ftr_dczid[] = { }; -static struct arm64_ftr_bits ftr_id_isar5[] = { +static const struct arm64_ftr_bits ftr_id_isar5[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_RDM_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 20, 4, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_ISAR5_CRC32_SHIFT, 4, 0), @@ -204,14 +216,14 @@ static struct arm64_ftr_bits ftr_id_isar5[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_mmfr4[] = { +static const struct arm64_ftr_bits ftr_id_mmfr4[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 24, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 4, 0), /* ac2 */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 4, 0), /* RAZ */ ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_pfr0[] = { +static const struct arm64_ftr_bits ftr_id_pfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 16, 16, 0), /* RAZ */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 12, 4, 0), /* State3 */ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 8, 4, 0), /* State2 */ @@ -220,7 +232,7 @@ static struct arm64_ftr_bits ftr_id_pfr0[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_id_dfr0[] = { +static const struct arm64_ftr_bits ftr_id_dfr0[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0), S_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0xf), /* PerfMon */ ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), @@ -238,7 +250,7 @@ static struct arm64_ftr_bits ftr_id_dfr0[] = { * 0. Covers the following 32bit registers: * id_isar[0-4], id_mmfr[1-3], id_pfr1, mvfr[0-1] */ -static struct arm64_ftr_bits ftr_generic_32bits[] = { +static const struct arm64_ftr_bits ftr_generic_32bits[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0), ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), @@ -250,29 +262,32 @@ static struct arm64_ftr_bits ftr_generic_32bits[] = { ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_generic[] = { +static const struct arm64_ftr_bits ftr_generic[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 64, 0), ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_generic32[] = { +static const struct arm64_ftr_bits ftr_generic32[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 32, 0), ARM64_FTR_END, }; -static struct arm64_ftr_bits ftr_aa64raz[] = { +static const struct arm64_ftr_bits ftr_aa64raz[] = { ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 0, 64, 0), ARM64_FTR_END, }; -#define ARM64_FTR_REG(id, table) \ - { \ - .sys_id = id, \ +#define ARM64_FTR_REG(id, table) { \ + .sys_id = id, \ + .reg = &(struct arm64_ftr_reg){ \ .name = #id, \ .ftr_bits = &((table)[0]), \ - } + }} -static struct arm64_ftr_reg arm64_ftr_regs[] = { +static const struct __ftr_reg_entry { + u32 sys_id; + struct arm64_ftr_reg *reg; +} arm64_ftr_regs[] = { /* Op1 = 0, CRn = 0, CRm = 1 */ ARM64_FTR_REG(SYS_ID_PFR0_EL1, ftr_id_pfr0), @@ -315,7 +330,7 @@ static struct arm64_ftr_reg arm64_ftr_regs[] = { ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2), /* Op1 = 3, CRn = 0, CRm = 0 */ - ARM64_FTR_REG(SYS_CTR_EL0, ftr_ctr), + { SYS_CTR_EL0, &arm64_ftr_reg_ctrel0 }, ARM64_FTR_REG(SYS_DCZID_EL0, ftr_dczid), /* Op1 = 3, CRn = 14, CRm = 0 */ @@ -324,7 +339,7 @@ static struct arm64_ftr_reg arm64_ftr_regs[] = { static int search_cmp_ftr_reg(const void *id, const void *regp) { - return (int)(unsigned long)id - (int)((const struct arm64_ftr_reg *)regp)->sys_id; + return (int)(unsigned long)id - (int)((const struct __ftr_reg_entry *)regp)->sys_id; } /* @@ -339,14 +354,20 @@ static int search_cmp_ftr_reg(const void *id, const void *regp) */ static struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id) { - return bsearch((const void *)(unsigned long)sys_id, + const struct __ftr_reg_entry *ret; + + ret = bsearch((const void *)(unsigned long)sys_id, arm64_ftr_regs, ARRAY_SIZE(arm64_ftr_regs), sizeof(arm64_ftr_regs[0]), search_cmp_ftr_reg); + if (ret) + return ret->reg; + return NULL; } -static u64 arm64_ftr_set_value(struct arm64_ftr_bits *ftrp, s64 reg, s64 ftr_val) +static u64 arm64_ftr_set_value(const struct arm64_ftr_bits *ftrp, s64 reg, + s64 ftr_val) { u64 mask = arm64_ftr_mask(ftrp); @@ -355,7 +376,8 @@ static u64 arm64_ftr_set_value(struct arm64_ftr_bits *ftrp, s64 reg, s64 ftr_val return reg; } -static s64 arm64_ftr_safe_value(struct arm64_ftr_bits *ftrp, s64 new, s64 cur) +static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, + s64 cur) { s64 ret = 0; @@ -376,27 +398,13 @@ static s64 arm64_ftr_safe_value(struct arm64_ftr_bits *ftrp, s64 new, s64 cur) return ret; } -static int __init sort_cmp_ftr_regs(const void *a, const void *b) -{ - return ((const struct arm64_ftr_reg *)a)->sys_id - - ((const struct arm64_ftr_reg *)b)->sys_id; -} - -static void __init swap_ftr_regs(void *a, void *b, int size) -{ - struct arm64_ftr_reg tmp = *(struct arm64_ftr_reg *)a; - *(struct arm64_ftr_reg *)a = *(struct arm64_ftr_reg *)b; - *(struct arm64_ftr_reg *)b = tmp; -} - static void __init sort_ftr_regs(void) { - /* Keep the array sorted so that we can do the binary search */ - sort(arm64_ftr_regs, - ARRAY_SIZE(arm64_ftr_regs), - sizeof(arm64_ftr_regs[0]), - sort_cmp_ftr_regs, - swap_ftr_regs); + int i; + + /* Check that the array is sorted so that we can do the binary search */ + for (i = 1; i < ARRAY_SIZE(arm64_ftr_regs); i++) + BUG_ON(arm64_ftr_regs[i].sys_id < arm64_ftr_regs[i - 1].sys_id); } /* @@ -407,7 +415,7 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new) { u64 val = 0; u64 strict_mask = ~0x0ULL; - struct arm64_ftr_bits *ftrp; + const struct arm64_ftr_bits *ftrp; struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg); BUG_ON(!reg); @@ -464,7 +472,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new) { - struct arm64_ftr_bits *ftrp; + const struct arm64_ftr_bits *ftrp; for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) { s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val); @@ -739,6 +747,14 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry, return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode(); } +static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused) +{ + u64 pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1); + + return cpuid_feature_extract_signed_field(pfr0, + ID_AA64PFR0_FP_SHIFT) < 0; +} + static const struct arm64_cpu_capabilities arm64_features[] = { { .desc = "GIC system register CPU interface", @@ -822,6 +838,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .def_scope = SCOPE_SYSTEM, .matches = hyp_offset_low, }, + { + /* FP/SIMD is not implemented */ + .capability = ARM64_HAS_NO_FPSIMD, + .def_scope = SCOPE_SYSTEM, + .min_field_value = 0, + .matches = has_no_fpsimd, + }, {}, }; @@ -936,7 +959,13 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) { for (; caps->matches; caps++) if (caps->enable && cpus_have_cap(caps->capability)) - on_each_cpu(caps->enable, NULL, true); + /* + * Use stop_machine() as it schedules the work allowing + * us to modify PSTATE, instead of on_each_cpu() which + * uses an IPI, giving us a PSTATE that disappears when + * we return. + */ + stop_machine(caps->enable, NULL, cpu_online_mask); } /* @@ -1004,23 +1033,33 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps) * cannot do anything to fix it up and could cause unexpected failures. So * we park the CPU. */ -void verify_local_cpu_capabilities(void) +static void verify_local_cpu_capabilities(void) { + verify_local_cpu_errata_workarounds(); + verify_local_cpu_features(arm64_features); + verify_local_elf_hwcaps(arm64_elf_hwcaps); + if (system_supports_32bit_el0()) + verify_local_elf_hwcaps(compat_elf_hwcaps); +} +void check_local_cpu_capabilities(void) +{ + /* + * All secondary CPUs should conform to the early CPU features + * in use by the kernel based on boot CPU. + */ check_early_cpu_features(); /* - * If we haven't computed the system capabilities, there is nothing - * to verify. + * If we haven't finalised the system capabilities, this CPU gets + * a chance to update the errata work arounds. + * Otherwise, this CPU should verify that it has all the system + * advertised capabilities. */ if (!sys_caps_initialised) - return; - - verify_local_cpu_errata(); - verify_local_cpu_features(arm64_features); - verify_local_elf_hwcaps(arm64_elf_hwcaps); - if (system_supports_32bit_el0()) - verify_local_elf_hwcaps(compat_elf_hwcaps); + update_cpu_errata_workarounds(); + else + verify_local_cpu_capabilities(); } static void __init setup_feature_capabilities(void) @@ -1079,5 +1118,5 @@ void __init setup_cpu_features(void) static bool __maybe_unused cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused) { - return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO)); + return (cpus_have_const_cap(ARM64_HAS_PAN) && !cpus_have_const_cap(ARM64_HAS_UAO)); } diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index ed1b84fe6925..7b7be71e87bf 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -227,7 +227,7 @@ static struct attribute_group cpuregs_attr_group = { .name = "identification" }; -static int cpuid_add_regs(int cpu) +static int cpuid_cpu_online(unsigned int cpu) { int rc; struct device *dev; @@ -248,7 +248,7 @@ out: return rc; } -static int cpuid_remove_regs(int cpu) +static int cpuid_cpu_offline(unsigned int cpu) { struct device *dev; struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu); @@ -264,40 +264,22 @@ static int cpuid_remove_regs(int cpu) return 0; } -static int cpuid_callback(struct notifier_block *nb, - unsigned long action, void *hcpu) -{ - int rc = 0; - unsigned long cpu = (unsigned long)hcpu; - - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - rc = cpuid_add_regs(cpu); - break; - case CPU_DEAD: - rc = cpuid_remove_regs(cpu); - break; - } - - return notifier_from_errno(rc); -} - static int __init cpuinfo_regs_init(void) { - int cpu; - - cpu_notifier_register_begin(); + int cpu, ret; for_each_possible_cpu(cpu) { struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu); kobject_init(&info->kobj, &cpuregs_kobj_type); - if (cpu_online(cpu)) - cpuid_add_regs(cpu); } - __hotcpu_notifier(cpuid_callback, 0); - cpu_notifier_register_done(); + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/cpuinfo:online", + cpuid_cpu_online, cpuid_cpu_offline); + if (ret < 0) { + pr_err("cpuinfo: failed to register hotplug callbacks.\n"); + return ret; + } return 0; } static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info) @@ -363,8 +345,6 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) } cpuinfo_detect_icache_policy(info); - - check_local_cpu_errata(); } void cpuinfo_store_cpu(void) diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 91fff48d0f57..2bd426448fc1 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -46,16 +46,14 @@ static void mdscr_write(u32 mdscr) { unsigned long flags; local_dbg_save(flags); - asm volatile("msr mdscr_el1, %0" :: "r" (mdscr)); + write_sysreg(mdscr, mdscr_el1); local_dbg_restore(flags); } NOKPROBE_SYMBOL(mdscr_write); static u32 mdscr_read(void) { - u32 mdscr; - asm volatile("mrs %0, mdscr_el1" : "=r" (mdscr)); - return mdscr; + return read_sysreg(mdscr_el1); } NOKPROBE_SYMBOL(mdscr_read); @@ -132,36 +130,18 @@ NOKPROBE_SYMBOL(disable_debug_monitors); /* * OS lock clearing. */ -static void clear_os_lock(void *unused) +static int clear_os_lock(unsigned int cpu) { - asm volatile("msr oslar_el1, %0" : : "r" (0)); -} - -static int os_lock_notify(struct notifier_block *self, - unsigned long action, void *data) -{ - if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) - clear_os_lock(NULL); - return NOTIFY_OK; + write_sysreg(0, oslar_el1); + isb(); + return 0; } -static struct notifier_block os_lock_nb = { - .notifier_call = os_lock_notify, -}; - static int debug_monitors_init(void) { - cpu_notifier_register_begin(); - - /* Clear the OS lock. */ - on_each_cpu(clear_os_lock, NULL, 1); - isb(); - - /* Register hotplug handler. */ - __register_cpu_notifier(&os_lock_nb); - - cpu_notifier_register_done(); - return 0; + return cpuhp_setup_state(CPUHP_AP_ARM64_DEBUG_MONITORS_STARTING, + "arm64/debug_monitors:starting", + clear_os_lock, NULL); } postcore_initcall(debug_monitors_init); @@ -246,6 +226,8 @@ static void send_user_sigtrap(int si_code) static int single_step_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) { + bool handler_found = false; + /* * If we are stepping a pending breakpoint, call the hw_breakpoint * handler first. @@ -253,8 +235,15 @@ static int single_step_handler(unsigned long addr, unsigned int esr, if (!reinstall_suspended_bps(regs)) return 0; - if (user_mode(regs)) { - send_user_sigtrap(TRAP_HWBKPT); +#ifdef CONFIG_KPROBES + if (kprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED) + handler_found = true; +#endif + if (!handler_found && call_step_hook(regs, esr) == DBG_HOOK_HANDLED) + handler_found = true; + + if (!handler_found && user_mode(regs)) { + send_user_sigtrap(TRAP_TRACE); /* * ptrace will disable single step unless explicitly @@ -263,15 +252,8 @@ static int single_step_handler(unsigned long addr, unsigned int esr, * to the active-not-pending state). */ user_rewind_single_step(current); - } else { -#ifdef CONFIG_KPROBES - if (kprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED) - return 0; -#endif - if (call_step_hook(regs, esr) == DBG_HOOK_HANDLED) - return 0; - - pr_warning("Unexpected kernel single-step exception at EL1\n"); + } else if (!handler_found) { + pr_warn("Unexpected kernel single-step exception at EL1\n"); /* * Re-enable stepping since we know that we will be * returning to regs. @@ -324,16 +306,20 @@ NOKPROBE_SYMBOL(call_break_hook); static int brk_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - if (user_mode(regs)) { - send_user_sigtrap(TRAP_BRKPT); - } + bool handler_found = false; + #ifdef CONFIG_KPROBES - else if ((esr & BRK64_ESR_MASK) == BRK64_ESR_KPROBES) { - if (kprobe_breakpoint_handler(regs, esr) != DBG_HOOK_HANDLED) - return -EFAULT; + if ((esr & BRK64_ESR_MASK) == BRK64_ESR_KPROBES) { + if (kprobe_breakpoint_handler(regs, esr) == DBG_HOOK_HANDLED) + handler_found = true; } #endif - else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) { + if (!handler_found && call_break_hook(regs, esr) == DBG_HOOK_HANDLED) + handler_found = true; + + if (!handler_found && user_mode(regs)) { + send_user_sigtrap(TRAP_BRKPT); + } else if (!handler_found) { pr_warn("Unexpected kernel BRK exception at EL1\n"); return -EFAULT; } @@ -382,7 +368,7 @@ NOKPROBE_SYMBOL(aarch32_break_handler); static int __init debug_traps_init(void) { hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP, - TRAP_HWBKPT, "single-step handler"); + TRAP_TRACE, "single-step handler"); hook_debug_fault_code(DBG_ESR_EVT_BRK, brk_handler, SIGTRAP, TRAP_BRKPT, "ptrace BRK handler"); return 0; @@ -435,8 +421,10 @@ NOKPROBE_SYMBOL(kernel_active_single_step); /* ptrace API */ void user_enable_single_step(struct task_struct *task) { - set_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP); - set_regs_spsr_ss(task_pt_regs(task)); + struct thread_info *ti = task_thread_info(task); + + if (!test_and_set_ti_thread_flag(ti, TIF_SINGLESTEP)) + set_regs_spsr_ss(task_pt_regs(task)); } NOKPROBE_SYMBOL(user_enable_single_step); diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index ba9bee389fd5..5d17f377d905 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -62,8 +62,8 @@ struct screen_info screen_info __section(.data); int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) { pteval_t prot_val = create_mapping_protection(md); - bool allow_block_mappings = (md->type != EFI_RUNTIME_SERVICES_CODE && - md->type != EFI_RUNTIME_SERVICES_DATA); + bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE || + md->type == EFI_RUNTIME_SERVICES_DATA); if (!PAGE_ALIGNED(md->phys_addr) || !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT)) { @@ -76,12 +76,12 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) * from the MMU routines. So avoid block mappings altogether in * that case. */ - allow_block_mappings = false; + page_mappings_only = true; } create_pgd_mapping(mm, md->phys_addr, md->virt_addr, md->num_pages << EFI_PAGE_SHIFT, - __pgprot(prot_val | PTE_NG), allow_block_mappings); + __pgprot(prot_val | PTE_NG), page_mappings_only); return 0; } diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S index 0f03a8fe2314..aef02d2af3b5 100644 --- a/arch/arm64/kernel/entry-ftrace.S +++ b/arch/arm64/kernel/entry-ftrace.S @@ -219,7 +219,7 @@ ENDPROC(ftrace_graph_caller) * * Run ftrace_return_to_handler() before going back to parent. * @fp is checked against the value passed by ftrace_graph_caller() - * only when CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST is enabled. + * only when HAVE_FUNCTION_GRAPH_FP_TEST is enabled. */ ENTRY(return_to_handler) save_return_regs diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 441420ca7d08..923841ffe4a9 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -29,7 +29,9 @@ #include <asm/esr.h> #include <asm/irq.h> #include <asm/memory.h> +#include <asm/ptrace.h> #include <asm/thread_info.h> +#include <asm/asm-uaccess.h> #include <asm/unistd.h> /* @@ -90,9 +92,8 @@ .if \el == 0 mrs x21, sp_el0 - mov tsk, sp - and tsk, tsk, #~(THREAD_SIZE - 1) // Ensure MDSCR_EL1.SS is clear, - ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug + ldr_this_cpu tsk, __entry_task, x20 // Ensure MDSCR_EL1.SS is clear, + ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug disable_step_tsk x19, x20 // exceptions when scheduling. mov x29, xzr // fp pointed to user-space @@ -100,15 +101,41 @@ add x21, sp, #S_FRAME_SIZE get_thread_info tsk /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */ - ldr x20, [tsk, #TI_ADDR_LIMIT] + ldr x20, [tsk, #TSK_TI_ADDR_LIMIT] str x20, [sp, #S_ORIG_ADDR_LIMIT] mov x20, #TASK_SIZE_64 - str x20, [tsk, #TI_ADDR_LIMIT] - ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO) + str x20, [tsk, #TSK_TI_ADDR_LIMIT] + /* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */ .endif /* \el == 0 */ mrs x22, elr_el1 mrs x23, spsr_el1 stp lr, x21, [sp, #S_LR] + +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + /* + * Set the TTBR0 PAN bit in SPSR. When the exception is taken from + * EL0, there is no need to check the state of TTBR0_EL1 since + * accesses are always enabled. + * Note that the meaning of this bit differs from the ARMv8.1 PAN + * feature as all TTBR0_EL1 accesses are disabled, not just those to + * user mappings. + */ +alternative_if ARM64_HAS_PAN + b 1f // skip TTBR0 PAN +alternative_else_nop_endif + + .if \el != 0 + mrs x21, ttbr0_el1 + tst x21, #0xffff << 48 // Check for the reserved ASID + orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR + b.eq 1f // TTBR0 access already disabled + and x23, x23, #~PSR_PAN_BIT // Clear the emulated PAN in the saved SPSR + .endif + + __uaccess_ttbr0_disable x21 +1: +#endif + stp x22, x23, [sp, #S_PC] /* @@ -139,7 +166,7 @@ .if \el != 0 /* Restore the task's original addr_limit. */ ldr x20, [sp, #S_ORIG_ADDR_LIMIT] - str x20, [tsk, #TI_ADDR_LIMIT] + str x20, [tsk, #TSK_TI_ADDR_LIMIT] /* No need to restore UAO, it will be restored from SPSR_EL1 */ .endif @@ -147,16 +174,44 @@ ldp x21, x22, [sp, #S_PC] // load ELR, SPSR .if \el == 0 ct_user_enter + .endif + +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + /* + * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR + * PAN bit checking. + */ +alternative_if ARM64_HAS_PAN + b 2f // skip TTBR0 PAN +alternative_else_nop_endif + + .if \el != 0 + tbnz x22, #22, 1f // Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set + .endif + + __uaccess_ttbr0_enable x0 + + .if \el == 0 + /* + * Enable errata workarounds only if returning to user. The only + * workaround currently required for TTBR0_EL1 changes are for the + * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache + * corruption). + */ + post_ttbr0_update_workaround + .endif +1: + .if \el != 0 + and x22, x22, #~PSR_PAN_BIT // ARMv8.0 CPUs do not understand this bit + .endif +2: +#endif + + .if \el == 0 ldr x23, [sp, #S_SP] // load return stack pointer msr sp_el0, x23 #ifdef CONFIG_ARM64_ERRATUM_845719 -alternative_if_not ARM64_WORKAROUND_845719 - nop - nop -#ifdef CONFIG_PID_IN_CONTEXTIDR - nop -#endif -alternative_else +alternative_if ARM64_WORKAROUND_845719 tbz x22, #4, 1f #ifdef CONFIG_PID_IN_CONTEXTIDR mrs x29, contextidr_el1 @@ -165,9 +220,10 @@ alternative_else msr contextidr_el1, xzr #endif 1: -alternative_endif +alternative_else_nop_endif #endif .endif + msr elr_el1, x21 // set up the return data msr spsr_el1, x22 ldp x0, x1, [sp, #16 * 0] @@ -190,23 +246,20 @@ alternative_endif eret // return to kernel .endm - .macro get_thread_info, rd - mrs \rd, sp_el0 - .endm - .macro irq_stack_entry mov x19, sp // preserve the original sp /* - * Compare sp with the current thread_info, if the top - * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and - * should switch to the irq stack. + * Compare sp with the base of the task stack. + * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack, + * and should switch to the irq stack. */ - and x25, x19, #~(THREAD_SIZE - 1) - cmp x25, tsk - b.ne 9998f + ldr x25, [tsk, TSK_STACK] + eor x25, x25, x19 + and x25, x25, #~(THREAD_SIZE - 1) + cbnz x25, 9998f - this_cpu_ptr irq_stack, x25, x26 + adr_this_cpu x25, irq_stack, x26 mov x26, #IRQ_STACK_START_SP add x26, x25, x26 @@ -433,9 +486,9 @@ el1_irq: irq_handler #ifdef CONFIG_PREEMPT - ldr w24, [tsk, #TI_PREEMPT] // get preempt count + ldr w24, [tsk, #TSK_TI_PREEMPT] // get preempt count cbnz w24, 1f // preempt count != 0 - ldr x0, [tsk, #TI_FLAGS] // get flags + ldr x0, [tsk, #TSK_TI_FLAGS] // get flags tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? bl el1_preempt 1: @@ -450,7 +503,7 @@ ENDPROC(el1_irq) el1_preempt: mov x24, lr 1: bl preempt_schedule_irq // irq en/disable is done inside - ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS + ldr x0, [tsk, #TSK_TI_FLAGS] // get new tasks TI_FLAGS tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? ret x24 #endif @@ -680,8 +733,7 @@ ENTRY(cpu_switch_to) ldp x29, x9, [x8], #16 ldr lr, [x8] mov sp, x9 - and x9, x9, #~(THREAD_SIZE - 1) - msr sp_el0, x9 + msr sp_el0, x1 ret ENDPROC(cpu_switch_to) @@ -692,7 +744,7 @@ ENDPROC(cpu_switch_to) ret_fast_syscall: disable_irq // disable interrupts str x0, [sp, #S_X0] // returned x0 - ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing + ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for syscall tracing and x2, x1, #_TIF_SYSCALL_WORK cbnz x2, ret_fast_syscall_trace and x2, x1, #_TIF_WORK_MASK @@ -707,26 +759,22 @@ ret_fast_syscall_trace: * Ok, we need to do extra processing, enter the slow path. */ work_pending: - tbnz x1, #TIF_NEED_RESCHED, work_resched - /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */ mov x0, sp // 'regs' - enable_irq // enable interrupts for do_notify_resume() bl do_notify_resume - b ret_to_user -work_resched: #ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off // the IRQs are off here, inform the tracing code + bl trace_hardirqs_on // enabled while in userspace #endif - bl schedule - + ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for single-step + b finish_ret_to_user /* * "slow" syscall return path. */ ret_to_user: disable_irq // disable interrupts - ldr x1, [tsk, #TI_FLAGS] + ldr x1, [tsk, #TSK_TI_FLAGS] and x2, x1, #_TIF_WORK_MASK cbnz x2, work_pending +finish_ret_to_user: enable_step_tsk x1, x2 kernel_exit 0 ENDPROC(ret_to_user) @@ -756,7 +804,7 @@ el0_svc_naked: // compat entry point enable_dbg_and_irq ct_user_exit 1 - ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks + ldr x16, [tsk, #TSK_TI_FLAGS] // check for syscall hooks tst x16, #_TIF_SYSCALL_WORK b.ne __sys_trace cmp scno, sc_nr // check upper syscall limit diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 975b274ee7b5..b883f1f75216 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -127,6 +127,8 @@ void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) void fpsimd_thread_switch(struct task_struct *next) { + if (!system_supports_fpsimd()) + return; /* * Save the current FPSIMD state to memory, but only if whatever is in * the registers is in fact the most recent userland FPSIMD state of @@ -157,6 +159,8 @@ void fpsimd_thread_switch(struct task_struct *next) void fpsimd_flush_thread(void) { + if (!system_supports_fpsimd()) + return; memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); fpsimd_flush_task_state(current); set_thread_flag(TIF_FOREIGN_FPSTATE); @@ -168,6 +172,8 @@ void fpsimd_flush_thread(void) */ void fpsimd_preserve_current_state(void) { + if (!system_supports_fpsimd()) + return; preempt_disable(); if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) fpsimd_save_state(¤t->thread.fpsimd_state); @@ -181,6 +187,8 @@ void fpsimd_preserve_current_state(void) */ void fpsimd_restore_current_state(void) { + if (!system_supports_fpsimd()) + return; preempt_disable(); if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { struct fpsimd_state *st = ¤t->thread.fpsimd_state; @@ -199,6 +207,8 @@ void fpsimd_restore_current_state(void) */ void fpsimd_update_current_state(struct fpsimd_state *state) { + if (!system_supports_fpsimd()) + return; preempt_disable(); fpsimd_load_state(state); if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { @@ -228,6 +238,8 @@ static DEFINE_PER_CPU(struct fpsimd_partial_state, softirq_fpsimdstate); */ void kernel_neon_begin_partial(u32 num_regs) { + if (WARN_ON(!system_supports_fpsimd())) + return; if (in_interrupt()) { struct fpsimd_partial_state *s = this_cpu_ptr( in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate); @@ -252,6 +264,8 @@ EXPORT_SYMBOL(kernel_neon_begin_partial); void kernel_neon_end(void) { + if (!system_supports_fpsimd()) + return; if (in_interrupt()) { struct fpsimd_partial_state *s = this_cpu_ptr( in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate); @@ -299,28 +313,16 @@ static inline void fpsimd_pm_init(void) { } #endif /* CONFIG_CPU_PM */ #ifdef CONFIG_HOTPLUG_CPU -static int fpsimd_cpu_hotplug_notifier(struct notifier_block *nfb, - unsigned long action, - void *hcpu) +static int fpsimd_cpu_dead(unsigned int cpu) { - unsigned int cpu = (long)hcpu; - - switch (action) { - case CPU_DEAD: - case CPU_DEAD_FROZEN: - per_cpu(fpsimd_last_state, cpu) = NULL; - break; - } - return NOTIFY_OK; + per_cpu(fpsimd_last_state, cpu) = NULL; + return 0; } -static struct notifier_block fpsimd_cpu_hotplug_notifier_block = { - .notifier_call = fpsimd_cpu_hotplug_notifier, -}; - static inline void fpsimd_hotplug_init(void) { - register_cpu_notifier(&fpsimd_cpu_hotplug_notifier_block); + cpuhp_setup_state_nocalls(CPUHP_ARM64_FPSIMD_DEAD, "arm64/fpsimd:dead", + NULL, fpsimd_cpu_dead); } #else diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c index ebecf9aa33d1..40ad08ac569a 100644 --- a/arch/arm64/kernel/ftrace.c +++ b/arch/arm64/kernel/ftrace.c @@ -138,7 +138,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, return; err = ftrace_push_return_trace(old, self_addr, &trace.depth, - frame_pointer); + frame_pointer, NULL); if (err == -EBUSY) return; else diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 3e7b050e99dc..4b1abac3485a 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -208,13 +208,23 @@ efi_header_end: __INIT + /* + * The following callee saved general purpose registers are used on the + * primary lowlevel boot path: + * + * Register Scope Purpose + * x21 stext() .. start_kernel() FDT pointer passed at boot in x0 + * x23 stext() .. start_kernel() physical misalignment/KASLR offset + * x28 __create_page_tables() callee preserved temp register + * x19/x20 __primary_switch() callee preserved temp registers + */ ENTRY(stext) bl preserve_boot_args - bl el2_setup // Drop to EL1, w20=cpu_boot_mode - adrp x24, __PHYS_OFFSET - and x23, x24, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0 + bl el2_setup // Drop to EL1, w0=cpu_boot_mode + adrp x23, __PHYS_OFFSET + and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0 bl set_cpu_boot_mode_flag - bl __create_page_tables // x25=TTBR0, x26=TTBR1 + bl __create_page_tables /* * The following calls CPU setup code, see arch/arm64/mm/proc.S for * details. @@ -222,9 +232,7 @@ ENTRY(stext) * the TCR will have been set. */ bl __cpu_setup // initialise processor - adr_l x27, __primary_switch // address to jump to after - // MMU has been enabled - b __enable_mmu + b __primary_switch ENDPROC(stext) /* @@ -311,23 +319,21 @@ ENDPROC(preserve_boot_args) * been enabled */ __create_page_tables: - adrp x25, idmap_pg_dir - adrp x26, swapper_pg_dir mov x28, lr /* * Invalidate the idmap and swapper page tables to avoid potential * dirty cache lines being evicted. */ - mov x0, x25 - add x1, x26, #SWAPPER_DIR_SIZE + adrp x0, idmap_pg_dir + adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE bl __inval_cache_range /* * Clear the idmap and swapper page tables. */ - mov x0, x25 - add x6, x26, #SWAPPER_DIR_SIZE + adrp x0, idmap_pg_dir + adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE 1: stp xzr, xzr, [x0], #16 stp xzr, xzr, [x0], #16 stp xzr, xzr, [x0], #16 @@ -340,7 +346,7 @@ __create_page_tables: /* * Create the identity mapping. */ - mov x0, x25 // idmap_pg_dir + adrp x0, idmap_pg_dir adrp x3, __idmap_text_start // __pa(__idmap_text_start) #ifndef CONFIG_ARM64_VA_BITS_48 @@ -390,7 +396,7 @@ __create_page_tables: /* * Map the kernel image (starting with PHYS_OFFSET). */ - mov x0, x26 // swapper_pg_dir + adrp x0, swapper_pg_dir mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) add x5, x5, x23 // add KASLR displacement create_pgd_entry x0, x5, x3, x6 @@ -405,8 +411,8 @@ __create_page_tables: * accesses (MMU disabled), invalidate the idmap and swapper page * tables again to remove any speculatively loaded cache lines. */ - mov x0, x25 - add x1, x26, #SWAPPER_DIR_SIZE + adrp x0, idmap_pg_dir + adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE dmb sy bl __inval_cache_range @@ -416,14 +422,28 @@ ENDPROC(__create_page_tables) /* * The following fragment of code is executed with the MMU enabled. + * + * x0 = __PHYS_OFFSET */ - .set initial_sp, init_thread_union + THREAD_START_SP __primary_switched: - mov x28, lr // preserve LR + adrp x4, init_thread_union + add sp, x4, #THREAD_SIZE + adr_l x5, init_task + msr sp_el0, x5 // Save thread_info + adr_l x8, vectors // load VBAR_EL1 with virtual msr vbar_el1, x8 // vector table address isb + stp xzr, x30, [sp, #-16]! + mov x29, sp + + str_l x21, __fdt_pointer, x5 // Save FDT pointer + + ldr_l x4, kimage_vaddr // Save the offset between + sub x4, x4, x0 // the kernel virtual and + str_l x4, kimage_voffset, x5 // physical mappings + // Clear BSS adr_l x0, __bss_start mov x1, xzr @@ -432,17 +452,6 @@ __primary_switched: bl __pi_memset dsb ishst // Make zero page visible to PTW - adr_l sp, initial_sp, x4 - mov x4, sp - and x4, x4, #~(THREAD_SIZE - 1) - msr sp_el0, x4 // Save thread_info - str_l x21, __fdt_pointer, x5 // Save FDT pointer - - ldr_l x4, kimage_vaddr // Save the offset between - sub x4, x4, x24 // the kernel virtual and - str_l x4, kimage_voffset, x5 // physical mappings - - mov x29, #0 #ifdef CONFIG_KASAN bl kasan_early_init #endif @@ -454,8 +463,8 @@ __primary_switched: bl kaslr_early_init // parse FDT for KASLR options cbz x0, 0f // KASLR disabled? just proceed orr x23, x23, x0 // record KASLR offset - ret x28 // we must enable KASLR, return - // to __enable_mmu() + ldp x29, x30, [sp], #16 // we must enable KASLR, return + ret // to __primary_switch() 0: #endif b start_kernel @@ -465,7 +474,7 @@ ENDPROC(__primary_switched) * end early head section, begin head code that is also used for * hotplug and needs to have the same protections as the text region */ - .section ".text","ax" + .section ".idmap.text","ax" ENTRY(kimage_vaddr) .quad _text - TEXT_OFFSET @@ -490,7 +499,7 @@ CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2 CPU_BE( orr x0, x0, #(3 << 24) ) // Set the EE and E0E bits for EL1 CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1 msr sctlr_el1, x0 - mov w20, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1 + mov w0, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1 isb ret @@ -516,10 +525,21 @@ set_hcr: msr hcr_el2, x0 isb - /* Generic timers. */ + /* + * Allow Non-secure EL1 and EL0 to access physical timer and counter. + * This is not necessary for VHE, since the host kernel runs in EL2, + * and EL0 accesses are configured in the later stage of boot process. + * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout + * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined + * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1 + * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in + * EL2. + */ + cbnz x2, 1f mrs x0, cnthctl_el2 orr x0, x0, #3 // Enable EL1 physical timers msr cnthctl_el2, x0 +1: msr cntvoff_el2, xzr // Clear virtual offset #ifdef CONFIG_ARM_GIC_V3 @@ -578,15 +598,16 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems b.lt 4f // Skip if no PMU present mrs x0, pmcr_el0 // Disable debug access traps ubfx x0, x0, #11, #5 // to EL2 and allow access to - msr mdcr_el2, x0 // all PMU counters from EL1 4: + csel x0, xzr, x0, lt // all PMU counters from EL1 + msr mdcr_el2, x0 // (if they exist) /* Stage-2 translation */ msr vttbr_el2, xzr cbz x2, install_el2_stub - mov w20, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 + mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 isb ret @@ -601,7 +622,7 @@ install_el2_stub: PSR_MODE_EL1h) msr spsr_el2, x0 msr elr_el2, lr - mov w20, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 + mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 eret ENDPROC(el2_setup) @@ -611,27 +632,39 @@ ENDPROC(el2_setup) */ set_cpu_boot_mode_flag: adr_l x1, __boot_cpu_mode - cmp w20, #BOOT_CPU_MODE_EL2 + cmp w0, #BOOT_CPU_MODE_EL2 b.ne 1f add x1, x1, #4 -1: str w20, [x1] // This CPU has booted in EL1 +1: str w0, [x1] // This CPU has booted in EL1 dmb sy dc ivac, x1 // Invalidate potentially stale cache line ret ENDPROC(set_cpu_boot_mode_flag) /* + * These values are written with the MMU off, but read with the MMU on. + * Writers will invalidate the corresponding address, discarding up to a + * 'Cache Writeback Granule' (CWG) worth of data. The linker script ensures + * sufficient alignment that the CWG doesn't overlap another section. + */ + .pushsection ".mmuoff.data.write", "aw" +/* * We need to find out the CPU boot mode long after boot, so we need to * store it in a writable variable. * * This is not in .bss, because we set it sufficiently early that the boot-time * zeroing of .bss would clobber it. */ - .pushsection .data..cacheline_aligned - .align L1_CACHE_SHIFT ENTRY(__boot_cpu_mode) .long BOOT_CPU_MODE_EL2 .long BOOT_CPU_MODE_EL1 +/* + * The booting CPU updates the failed status @__early_cpu_boot_status, + * with MMU turned off. + */ +ENTRY(__early_cpu_boot_status) + .long 0 + .popsection /* @@ -639,7 +672,7 @@ ENTRY(__boot_cpu_mode) * cores are held until we're ready for them to initialise. */ ENTRY(secondary_holding_pen) - bl el2_setup // Drop to EL1, w20=cpu_boot_mode + bl el2_setup // Drop to EL1, w0=cpu_boot_mode bl set_cpu_boot_mode_flag mrs x0, mpidr_el1 mov_q x1, MPIDR_HWID_BITMASK @@ -666,12 +699,10 @@ secondary_startup: /* * Common entry point for secondary CPUs. */ - adrp x25, idmap_pg_dir - adrp x26, swapper_pg_dir bl __cpu_setup // initialise processor - - adr_l x27, __secondary_switch // address to jump to after enabling the MMU - b __enable_mmu + bl __enable_mmu + ldr x8, =__secondary_switched + br x8 ENDPROC(secondary_startup) __secondary_switched: @@ -680,10 +711,10 @@ __secondary_switched: isb adr_l x0, secondary_data - ldr x0, [x0, #CPU_BOOT_STACK] // get secondary_data.stack - mov sp, x0 - and x0, x0, #~(THREAD_SIZE - 1) - msr sp_el0, x0 // save thread_info + ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack + mov sp, x1 + ldr x2, [x0, #CPU_BOOT_TASK] + msr sp_el0, x2 mov x29, #0 b secondary_start_kernel ENDPROC(__secondary_switched) @@ -706,33 +737,27 @@ ENDPROC(__secondary_switched) dc ivac, \tmp1 // Invalidate potentially stale cache line .endm - .pushsection .data..cacheline_aligned - .align L1_CACHE_SHIFT -ENTRY(__early_cpu_boot_status) - .long 0 - .popsection - /* * Enable the MMU. * * x0 = SCTLR_EL1 value for turning on the MMU. - * x27 = *virtual* address to jump to upon completion * - * Other registers depend on the function called upon completion. + * Returns to the caller via x30/lr. This requires the caller to be covered + * by the .idmap.text section. * * Checks if the selected granule size is supported by the CPU. * If it isn't, park the CPU */ - .section ".idmap.text", "ax" ENTRY(__enable_mmu) - mrs x22, sctlr_el1 // preserve old SCTLR_EL1 value mrs x1, ID_AA64MMFR0_EL1 ubfx x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4 cmp x2, #ID_AA64MMFR0_TGRAN_SUPPORTED b.ne __no_granule_support update_early_cpu_boot_status 0, x1, x2 - msr ttbr0_el1, x25 // load TTBR0 - msr ttbr1_el1, x26 // load TTBR1 + adrp x1, idmap_pg_dir + adrp x2, swapper_pg_dir + msr ttbr0_el1, x1 // load TTBR0 + msr ttbr1_el1, x2 // load TTBR1 isb msr sctlr_el1, x0 isb @@ -744,29 +769,7 @@ ENTRY(__enable_mmu) ic iallu dsb nsh isb -#ifdef CONFIG_RANDOMIZE_BASE - mov x19, x0 // preserve new SCTLR_EL1 value - blr x27 - - /* - * If we return here, we have a KASLR displacement in x23 which we need - * to take into account by discarding the current kernel mapping and - * creating a new one. - */ - msr sctlr_el1, x22 // disable the MMU - isb - bl __create_page_tables // recreate kernel mapping - - tlbi vmalle1 // Remove any stale TLB entries - dsb nsh - - msr sctlr_el1, x19 // re-enable the MMU - isb - ic iallu // flush instructions fetched - dsb nsh // via old mapping - isb -#endif - br x27 + ret ENDPROC(__enable_mmu) __no_granule_support: @@ -775,11 +778,11 @@ __no_granule_support: 1: wfe wfi - b 1b + b 1b ENDPROC(__no_granule_support) -__primary_switch: #ifdef CONFIG_RELOCATABLE +__relocate_kernel: /* * Iterate over each entry in the relocation table, and apply the * relocations in place. @@ -801,14 +804,46 @@ __primary_switch: add x13, x13, x23 // relocate str x13, [x11, x23] b 0b +1: ret +ENDPROC(__relocate_kernel) +#endif -1: +__primary_switch: +#ifdef CONFIG_RANDOMIZE_BASE + mov x19, x0 // preserve new SCTLR_EL1 value + mrs x20, sctlr_el1 // preserve old SCTLR_EL1 value #endif + + bl __enable_mmu +#ifdef CONFIG_RELOCATABLE + bl __relocate_kernel +#ifdef CONFIG_RANDOMIZE_BASE ldr x8, =__primary_switched - br x8 -ENDPROC(__primary_switch) + adrp x0, __PHYS_OFFSET + blr x8 -__secondary_switch: - ldr x8, =__secondary_switched + /* + * If we return here, we have a KASLR displacement in x23 which we need + * to take into account by discarding the current kernel mapping and + * creating a new one. + */ + msr sctlr_el1, x20 // disable the MMU + isb + bl __create_page_tables // recreate kernel mapping + + tlbi vmalle1 // Remove any stale TLB entries + dsb nsh + + msr sctlr_el1, x19 // re-enable the MMU + isb + ic iallu // flush instructions fetched + dsb nsh // via old mapping + isb + + bl __relocate_kernel +#endif +#endif + ldr x8, =__primary_switched + adrp x0, __PHYS_OFFSET br x8 -ENDPROC(__secondary_switch) +ENDPROC(__primary_switch) diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S index 46f29b6560ec..e56d848b6466 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -36,8 +36,8 @@ .macro break_before_make_ttbr_switch zero_page, page_table msr ttbr1_el1, \zero_page isb - tlbi vmalle1is - dsb ish + tlbi vmalle1 + dsb nsh msr ttbr1_el1, \page_table isb .endm @@ -96,7 +96,7 @@ ENTRY(swsusp_arch_suspend_exit) add x1, x10, #PAGE_SIZE /* Clean the copied page to PoU - based on flush_icache_range() */ - dcache_line_size x2, x3 + raw_dcache_line_size x2, x3 sub x3, x2, #1 bic x4, x10, x3 2: dc cvau, x4 /* clean D line / unified line */ diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 65d81f965e74..fe301cbcb442 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -15,9 +15,9 @@ * License terms: GNU General Public License (GPL) version 2 */ #define pr_fmt(x) "hibernate: " x +#include <linux/cpu.h> #include <linux/kvm_host.h> #include <linux/mm.h> -#include <linux/notifier.h> #include <linux/pm.h> #include <linux/sched.h> #include <linux/suspend.h> @@ -26,6 +26,7 @@ #include <asm/barrier.h> #include <asm/cacheflush.h> +#include <asm/cputype.h> #include <asm/irqflags.h> #include <asm/memory.h> #include <asm/mmu_context.h> @@ -34,6 +35,7 @@ #include <asm/pgtable-hwdef.h> #include <asm/sections.h> #include <asm/smp.h> +#include <asm/smp_plat.h> #include <asm/suspend.h> #include <asm/sysreg.h> #include <asm/virt.h> @@ -54,12 +56,6 @@ extern int in_suspend; /* Do we need to reset el2? */ #define el2_reset_needed() (is_hyp_mode_available() && !is_kernel_in_hyp_mode()) -/* - * Start/end of the hibernate exit code, this must be copied to a 'safe' - * location in memory, and executed from there. - */ -extern char __hibernate_exit_text_start[], __hibernate_exit_text_end[]; - /* temporary el2 vectors in the __hibernate_exit_text section. */ extern char hibernate_el2_vectors[]; @@ -67,6 +63,12 @@ extern char hibernate_el2_vectors[]; extern char __hyp_stub_vectors[]; /* + * The logical cpu number we should resume on, initialised to a non-cpu + * number. + */ +static int sleep_cpu = -EINVAL; + +/* * Values that may not change over hibernate/resume. We put the build number * and date in here so that we guarantee not to resume with a different * kernel. @@ -88,6 +90,8 @@ static struct arch_hibernate_hdr { * re-configure el2. */ phys_addr_t __hyp_stub_vectors; + + u64 sleep_cpu_mpidr; } resume_hdr; static inline void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i) @@ -130,12 +134,22 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size) else hdr->__hyp_stub_vectors = 0; + /* Save the mpidr of the cpu we called cpu_suspend() on... */ + if (sleep_cpu < 0) { + pr_err("Failing to hibernate on an unknown CPU.\n"); + return -ENODEV; + } + hdr->sleep_cpu_mpidr = cpu_logical_map(sleep_cpu); + pr_info("Hibernating on CPU %d [mpidr:0x%llx]\n", sleep_cpu, + hdr->sleep_cpu_mpidr); + return 0; } EXPORT_SYMBOL(arch_hibernation_header_save); int arch_hibernation_header_restore(void *addr) { + int ret; struct arch_hibernate_hdr_invariants invariants; struct arch_hibernate_hdr *hdr = addr; @@ -145,6 +159,24 @@ int arch_hibernation_header_restore(void *addr) return -EINVAL; } + sleep_cpu = get_logical_index(hdr->sleep_cpu_mpidr); + pr_info("Hibernated on CPU %d [mpidr:0x%llx]\n", sleep_cpu, + hdr->sleep_cpu_mpidr); + if (sleep_cpu < 0) { + pr_crit("Hibernated on a CPU not known to this kernel!\n"); + sleep_cpu = -EINVAL; + return -EINVAL; + } + if (!cpu_online(sleep_cpu)) { + pr_info("Hibernated on a CPU that is offline! Bringing CPU up.\n"); + ret = cpu_up(sleep_cpu); + if (ret) { + pr_err("Failed to bring hibernate-CPU up!\n"); + sleep_cpu = -EINVAL; + return ret; + } + } + resume_hdr = *hdr; return 0; @@ -241,6 +273,7 @@ out: return rc; } +#define dcache_clean_range(start, end) __flush_dcache_area(start, (end - start)) int swsusp_arch_suspend(void) { @@ -256,10 +289,16 @@ int swsusp_arch_suspend(void) local_dbg_save(flags); if (__cpu_suspend_enter(&state)) { + sleep_cpu = smp_processor_id(); ret = swsusp_save(); } else { - /* Clean kernel to PoC for secondary core startup */ - __flush_dcache_area(LMADDR(KERNEL_START), KERNEL_END - KERNEL_START); + /* Clean kernel core startup/idle code to PoC*/ + dcache_clean_range(__mmuoff_data_start, __mmuoff_data_end); + dcache_clean_range(__idmap_text_start, __idmap_text_end); + + /* Clean kvm setup code to PoC? */ + if (el2_reset_needed()) + dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end); /* * Tell the hibernation core that we've just restored @@ -267,6 +306,7 @@ int swsusp_arch_suspend(void) */ in_suspend = 0; + sleep_cpu = -EINVAL; __cpu_suspend_exit(); } @@ -275,6 +315,33 @@ int swsusp_arch_suspend(void) return ret; } +static void _copy_pte(pte_t *dst_pte, pte_t *src_pte, unsigned long addr) +{ + pte_t pte = *src_pte; + + if (pte_valid(pte)) { + /* + * Resume will overwrite areas that may be marked + * read only (code, rodata). Clear the RDONLY bit from + * the temporary mappings we use during restore. + */ + set_pte(dst_pte, pte_clear_rdonly(pte)); + } else if (debug_pagealloc_enabled() && !pte_none(pte)) { + /* + * debug_pagealloc will removed the PTE_VALID bit if + * the page isn't in use by the resume kernel. It may have + * been in use by the original kernel, in which case we need + * to put it back in our copy to do the restore. + * + * Before marking this entry valid, check the pfn should + * be mapped. + */ + BUG_ON(!pfn_valid(pte_pfn(pte))); + + set_pte(dst_pte, pte_mkpresent(pte_clear_rdonly(pte))); + } +} + static int copy_pte(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long start, unsigned long end) { @@ -290,13 +357,7 @@ static int copy_pte(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long start, src_pte = pte_offset_kernel(src_pmd, start); do { - if (!pte_none(*src_pte)) - /* - * Resume will overwrite areas that may be marked - * read only (code, rodata). Clear the RDONLY bit from - * the temporary mappings we use during restore. - */ - set_pte(dst_pte, __pte(pte_val(*src_pte) & ~PTE_RDONLY)); + _copy_pte(dst_pte, src_pte, addr); } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end); return 0; @@ -483,27 +544,12 @@ out: return rc; } -static int check_boot_cpu_online_pm_callback(struct notifier_block *nb, - unsigned long action, void *ptr) +int hibernate_resume_nonboot_cpu_disable(void) { - if (action == PM_HIBERNATION_PREPARE && - cpumask_first(cpu_online_mask) != 0) { - pr_warn("CPU0 is offline.\n"); - return notifier_from_errno(-ENODEV); + if (sleep_cpu < 0) { + pr_err("Failing to resume from hibernate on an unknown CPU.\n"); + return -ENODEV; } - return NOTIFY_OK; -} - -static int __init check_boot_cpu_online_init(void) -{ - /* - * Set this pm_notifier callback with a lower priority than - * cpu_hotplug_pm_callback, so that cpu_hotplug_pm_callback will be - * called earlier to disable cpu hotplug before the cpu online check. - */ - pm_notifier(check_boot_cpu_online_pm_callback, -INT_MAX); - - return 0; + return freeze_secondary_cpus(sleep_cpu); } -core_initcall(check_boot_cpu_online_init); diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 26a6bf77d272..0296e7924240 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -317,9 +317,21 @@ static int get_hbp_len(u8 hbp_len) case ARM_BREAKPOINT_LEN_2: len_in_bytes = 2; break; + case ARM_BREAKPOINT_LEN_3: + len_in_bytes = 3; + break; case ARM_BREAKPOINT_LEN_4: len_in_bytes = 4; break; + case ARM_BREAKPOINT_LEN_5: + len_in_bytes = 5; + break; + case ARM_BREAKPOINT_LEN_6: + len_in_bytes = 6; + break; + case ARM_BREAKPOINT_LEN_7: + len_in_bytes = 7; + break; case ARM_BREAKPOINT_LEN_8: len_in_bytes = 8; break; @@ -349,7 +361,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp) * to generic breakpoint descriptions. */ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, - int *gen_len, int *gen_type) + int *gen_len, int *gen_type, int *offset) { /* Type */ switch (ctrl.type) { @@ -369,17 +381,33 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, return -EINVAL; } + if (!ctrl.len) + return -EINVAL; + *offset = __ffs(ctrl.len); + /* Len */ - switch (ctrl.len) { + switch (ctrl.len >> *offset) { case ARM_BREAKPOINT_LEN_1: *gen_len = HW_BREAKPOINT_LEN_1; break; case ARM_BREAKPOINT_LEN_2: *gen_len = HW_BREAKPOINT_LEN_2; break; + case ARM_BREAKPOINT_LEN_3: + *gen_len = HW_BREAKPOINT_LEN_3; + break; case ARM_BREAKPOINT_LEN_4: *gen_len = HW_BREAKPOINT_LEN_4; break; + case ARM_BREAKPOINT_LEN_5: + *gen_len = HW_BREAKPOINT_LEN_5; + break; + case ARM_BREAKPOINT_LEN_6: + *gen_len = HW_BREAKPOINT_LEN_6; + break; + case ARM_BREAKPOINT_LEN_7: + *gen_len = HW_BREAKPOINT_LEN_7; + break; case ARM_BREAKPOINT_LEN_8: *gen_len = HW_BREAKPOINT_LEN_8; break; @@ -423,9 +451,21 @@ static int arch_build_bp_info(struct perf_event *bp) case HW_BREAKPOINT_LEN_2: info->ctrl.len = ARM_BREAKPOINT_LEN_2; break; + case HW_BREAKPOINT_LEN_3: + info->ctrl.len = ARM_BREAKPOINT_LEN_3; + break; case HW_BREAKPOINT_LEN_4: info->ctrl.len = ARM_BREAKPOINT_LEN_4; break; + case HW_BREAKPOINT_LEN_5: + info->ctrl.len = ARM_BREAKPOINT_LEN_5; + break; + case HW_BREAKPOINT_LEN_6: + info->ctrl.len = ARM_BREAKPOINT_LEN_6; + break; + case HW_BREAKPOINT_LEN_7: + info->ctrl.len = ARM_BREAKPOINT_LEN_7; + break; case HW_BREAKPOINT_LEN_8: info->ctrl.len = ARM_BREAKPOINT_LEN_8; break; @@ -517,18 +557,17 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) default: return -EINVAL; } - - info->address &= ~alignment_mask; - info->ctrl.len <<= offset; } else { if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) alignment_mask = 0x3; else alignment_mask = 0x7; - if (info->address & alignment_mask) - return -EINVAL; + offset = info->address & alignment_mask; } + info->address &= ~alignment_mask; + info->ctrl.len <<= offset; + /* * Disallow per-task kernel breakpoints since these would * complicate the stepping code. @@ -661,12 +700,47 @@ unlock: } NOKPROBE_SYMBOL(breakpoint_handler); +/* + * Arm64 hardware does not always report a watchpoint hit address that matches + * one of the watchpoints set. It can also report an address "near" the + * watchpoint if a single instruction access both watched and unwatched + * addresses. There is no straight-forward way, short of disassembling the + * offending instruction, to map that address back to the watchpoint. This + * function computes the distance of the memory access from the watchpoint as a + * heuristic for the likelyhood that a given access triggered the watchpoint. + * + * See Section D2.10.5 "Determining the memory location that caused a Watchpoint + * exception" of ARMv8 Architecture Reference Manual for details. + * + * The function returns the distance of the address from the bytes watched by + * the watchpoint. In case of an exact match, it returns 0. + */ +static u64 get_distance_from_watchpoint(unsigned long addr, u64 val, + struct arch_hw_breakpoint_ctrl *ctrl) +{ + u64 wp_low, wp_high; + u32 lens, lene; + + lens = __ffs(ctrl->len); + lene = __fls(ctrl->len); + + wp_low = val + lens; + wp_high = val + lene; + if (addr < wp_low) + return wp_low - addr; + else if (addr > wp_high) + return addr - wp_high; + else + return 0; +} + static int watchpoint_handler(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - int i, step = 0, *kernel_step, access; + int i, step = 0, *kernel_step, access, closest_match = 0; + u64 min_dist = -1, dist; u32 ctrl_reg; - u64 val, alignment_mask; + u64 val; struct perf_event *wp, **slots; struct debug_info *debug_info; struct arch_hw_breakpoint *info; @@ -675,35 +749,15 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, slots = this_cpu_ptr(wp_on_reg); debug_info = ¤t->thread.debug; + /* + * Find all watchpoints that match the reported address. If no exact + * match is found. Attribute the hit to the closest watchpoint. + */ + rcu_read_lock(); for (i = 0; i < core_num_wrps; ++i) { - rcu_read_lock(); - wp = slots[i]; - if (wp == NULL) - goto unlock; - - info = counter_arch_bp(wp); - /* AArch32 watchpoints are either 4 or 8 bytes aligned. */ - if (is_compat_task()) { - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - else - alignment_mask = 0x3; - } else { - alignment_mask = 0x7; - } - - /* Check if the watchpoint value matches. */ - val = read_wb_reg(AARCH64_DBG_REG_WVR, i); - if (val != (addr & ~alignment_mask)) - goto unlock; - - /* Possible match, check the byte address select to confirm. */ - ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i); - decode_ctrl_reg(ctrl_reg, &ctrl); - if (!((1 << (addr & alignment_mask)) & ctrl.len)) - goto unlock; + continue; /* * Check that the access type matches. @@ -712,18 +766,41 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : HW_BREAKPOINT_R; if (!(access & hw_breakpoint_type(wp))) - goto unlock; + continue; + + /* Check if the watchpoint value and byte select match. */ + val = read_wb_reg(AARCH64_DBG_REG_WVR, i); + ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i); + decode_ctrl_reg(ctrl_reg, &ctrl); + dist = get_distance_from_watchpoint(addr, val, &ctrl); + if (dist < min_dist) { + min_dist = dist; + closest_match = i; + } + /* Is this an exact match? */ + if (dist != 0) + continue; + info = counter_arch_bp(wp); info->trigger = addr; perf_bp_event(wp, regs); /* Do we need to handle the stepping? */ if (is_default_overflow_handler(wp)) step = 1; + } + if (min_dist > 0 && min_dist != -1) { + /* No exact match found. */ + wp = slots[closest_match]; + info = counter_arch_bp(wp); + info->trigger = addr; + perf_bp_event(wp, regs); -unlock: - rcu_read_unlock(); + /* Do we need to handle the stepping? */ + if (is_default_overflow_handler(wp)) + step = 1; } + rcu_read_unlock(); if (!step) return 0; @@ -857,7 +934,7 @@ void hw_breakpoint_thread_switch(struct task_struct *next) /* * CPU initialisation. */ -static void hw_breakpoint_reset(void *unused) +static int hw_breakpoint_reset(unsigned int cpu) { int i; struct perf_event **slots; @@ -888,28 +965,14 @@ static void hw_breakpoint_reset(void *unused) write_wb_reg(AARCH64_DBG_REG_WVR, i, 0UL); } } -} -static int hw_breakpoint_reset_notify(struct notifier_block *self, - unsigned long action, - void *hcpu) -{ - if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) { - local_irq_disable(); - hw_breakpoint_reset(NULL); - local_irq_enable(); - } - return NOTIFY_OK; + return 0; } -static struct notifier_block hw_breakpoint_reset_nb = { - .notifier_call = hw_breakpoint_reset_notify, -}; - #ifdef CONFIG_CPU_PM -extern void cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)); +extern void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)); #else -static inline void cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) +static inline void cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) { } #endif @@ -919,36 +982,34 @@ static inline void cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) */ static int __init arch_hw_breakpoint_init(void) { + int ret; + core_num_brps = get_num_brps(); core_num_wrps = get_num_wrps(); pr_info("found %d breakpoint and %d watchpoint registers.\n", core_num_brps, core_num_wrps); - cpu_notifier_register_begin(); - - /* - * Reset the breakpoint resources. We assume that a halting - * debugger will leave the world in a nice state for us. - */ - smp_call_function(hw_breakpoint_reset, NULL, 1); - hw_breakpoint_reset(NULL); - /* Register debug fault handlers. */ hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP, TRAP_HWBKPT, "hw-breakpoint handler"); hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP, TRAP_HWBKPT, "hw-watchpoint handler"); - /* Register hotplug notifier. */ - __register_cpu_notifier(&hw_breakpoint_reset_nb); - - cpu_notifier_register_done(); + /* + * Reset the breakpoint resources. We assume that a halting + * debugger will leave the world in a nice state for us. + */ + ret = cpuhp_setup_state(CPUHP_AP_PERF_ARM_HW_BREAKPOINT_STARTING, + "perf/arm64/hw_breakpoint:starting", + hw_breakpoint_reset, NULL); + if (ret) + pr_err("failed to register CPU hotplug notifier: %d\n", ret); /* Register cpu_suspend hw breakpoint restore hook */ cpu_suspend_set_dbg_restorer(hw_breakpoint_reset); - return 0; + return ret; } arch_initcall(arch_hw_breakpoint_init); diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 63f9432d05e8..94b62c1fa4df 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -30,7 +30,6 @@ #include <asm/cacheflush.h> #include <asm/debug-monitors.h> #include <asm/fixmap.h> -#include <asm/opcodes.h> #include <asm/insn.h> #define AARCH64_INSN_SF_BIT BIT(31) @@ -96,7 +95,7 @@ static void __kprobes *patch_map(void *addr, int fixmap) if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX)) page = vmalloc_to_page(addr); - else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA)) + else if (!module) page = pfn_to_page(PHYS_PFN(__pa(addr))); else return addr; @@ -1202,6 +1201,19 @@ u32 aarch64_set_branch_offset(u32 insn, s32 offset) BUG(); } +s32 aarch64_insn_adrp_get_offset(u32 insn) +{ + BUG_ON(!aarch64_insn_is_adrp(insn)); + return aarch64_insn_decode_immediate(AARCH64_INSN_IMM_ADR, insn) << 12; +} + +u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset) +{ + BUG_ON(!aarch64_insn_is_adrp(insn)); + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn, + offset >> 12); +} + /* * Extract the Op/CR data from a msr/mrs instruction. */ diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index b05469173ba5..769f24ef628c 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -6,6 +6,7 @@ * published by the Free Software Foundation. */ +#include <linux/cache.h> #include <linux/crc32.h> #include <linux/init.h> #include <linux/libfdt.h> @@ -20,7 +21,7 @@ #include <asm/pgtable.h> #include <asm/sections.h> -u64 __read_mostly module_alloc_base; +u64 __ro_after_init module_alloc_base; u16 __initdata memstart_offset_seed; static __init u64 get_kaslr_seed(void *fdt) diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c index e017a9493b92..d217c9e95b06 100644 --- a/arch/arm64/kernel/kgdb.c +++ b/arch/arm64/kernel/kgdb.c @@ -247,6 +247,9 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_fn); static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) { + if (!kgdb_single_step) + return DBG_HOOK_ERROR; + kgdb_handle_exception(1, SIGTRAP, 0, regs); return 0; } diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index acf38722457b..4f0e3ebfea4b 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -114,6 +114,19 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) return 0; } +static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci) +{ + struct resource_entry *entry, *tmp; + int status; + + status = acpi_pci_probe_root_resources(ci); + resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { + if (!(entry->res->flags & IORESOURCE_WINDOW)) + resource_list_destroy_entry(entry); + } + return status; +} + /* * Lookup the bus range for the domain in MCFG, and set up config space * mapping. @@ -121,31 +134,33 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) static struct pci_config_window * pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) { + struct device *dev = &root->device->dev; struct resource *bus_res = &root->secondary; u16 seg = root->segment; - struct pci_config_window *cfg; + struct pci_ecam_ops *ecam_ops; struct resource cfgres; - unsigned int bsz; - - /* Use address from _CBA if present, otherwise lookup MCFG */ - if (!root->mcfg_addr) - root->mcfg_addr = pci_mcfg_lookup(seg, bus_res); + struct acpi_device *adev; + struct pci_config_window *cfg; + int ret; - if (!root->mcfg_addr) { - dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n", - seg, bus_res); + ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops); + if (ret) { + dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res); return NULL; } - bsz = 1 << pci_generic_ecam_ops.bus_shift; - cfgres.start = root->mcfg_addr + bus_res->start * bsz; - cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1; - cfgres.flags = IORESOURCE_MEM; - cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res, - &pci_generic_ecam_ops); + adev = acpi_resource_consumer(&cfgres); + if (adev) + dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres, + dev_name(&adev->dev)); + else + dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n", + &cfgres); + + cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops); if (IS_ERR(cfg)) { - dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n", - seg, bus_res, PTR_ERR(cfg)); + dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res, + PTR_ERR(cfg)); return NULL; } @@ -159,33 +174,37 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) ri = container_of(ci, struct acpi_pci_generic_root_info, common); pci_ecam_free(ri->cfg); + kfree(ci->ops); kfree(ri); } -static struct acpi_pci_root_ops acpi_pci_root_ops = { - .release_info = pci_acpi_generic_release_info, -}; - /* 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); if (!ri) return NULL; + root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node); + if (!root_ops) + return NULL; + ri->cfg = pci_acpi_setup_ecam_mapping(root); if (!ri->cfg) { kfree(ri); + kfree(root_ops); return NULL; } - acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops; - bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common, - ri->cfg); + root_ops->release_info = pci_acpi_generic_release_info; + root_ops->prepare_resources = pci_acpi_root_prepare_resources; + root_ops->pci_ops = &ri->cfg->ops->pci_ops; + bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg); if (!bus) return NULL; diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 838ccf123307..57ae9d9ed9bb 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -24,23 +24,16 @@ #include <asm/sysreg.h> #include <asm/virt.h> +#include <linux/acpi.h> #include <linux/of.h> #include <linux/perf/arm_pmu.h> #include <linux/platform_device.h> /* * ARMv8 PMUv3 Performance Events handling code. - * Common event types. + * Common event types (some are defined in asm/perf_event.h). */ -/* Required events. */ -#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00 -#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03 -#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04 -#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10 -#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11 -#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12 - /* At least one of the following is required. */ #define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08 #define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x1B @@ -190,13 +183,23 @@ #define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS 0xED /* PMUv3 HW events mapping. */ + +/* + * ARMv8 Architectural defined events, not all of these may + * be supported on any given implementation. Undefined events will + * be disabled at run-time. + */ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { PERF_MAP_ALL_UNSUPPORTED, [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED, [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED, [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, + [PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES, + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND, + [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV8_PMUV3_PERFCTR_STALL_BACKEND, }; /* ARM Cortex-A53 HW events mapping. */ @@ -258,6 +261,15 @@ static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE, [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL, + [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE, + [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL, + + [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL, + [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1D_TLB, + + [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL, + [C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1I_TLB, + [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_BR_PRED, @@ -523,12 +535,6 @@ static struct attribute_group armv8_pmuv3_format_attr_group = { .attrs = armv8_pmuv3_format_attrs, }; -static const struct attribute_group *armv8_pmuv3_attr_groups[] = { - &armv8_pmuv3_events_attr_group, - &armv8_pmuv3_format_attr_group, - NULL, -}; - /* * Perf Events' indices */ @@ -905,9 +911,22 @@ static void armv8pmu_reset(void *info) static int armv8_pmuv3_map_event(struct perf_event *event) { - return armpmu_map_event(event, &armv8_pmuv3_perf_map, - &armv8_pmuv3_perf_cache_map, - ARMV8_PMU_EVTYPE_EVENT); + int hw_event_id; + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); + + hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map, + &armv8_pmuv3_perf_cache_map, + ARMV8_PMU_EVTYPE_EVENT); + if (hw_event_id < 0) + return hw_event_id; + + /* disable micro/arch events not supported by this PMU */ + if ((hw_event_id < ARMV8_PMUV3_MAX_COMMON_EVENTS) && + !test_bit(hw_event_id, armpmu->pmceid_bitmap)) { + return -EOPNOTSUPP; + } + + return hw_event_id; } static int armv8_a53_map_event(struct perf_event *event) @@ -985,7 +1004,10 @@ static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_pmuv3"; cpu_pmu->map_event = armv8_pmuv3_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -994,7 +1016,10 @@ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_cortex_a53"; cpu_pmu->map_event = armv8_a53_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -1003,7 +1028,10 @@ static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_cortex_a57"; cpu_pmu->map_event = armv8_a57_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -1012,7 +1040,10 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_cortex_a72"; cpu_pmu->map_event = armv8_a57_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -1021,7 +1052,10 @@ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_cavium_thunder"; cpu_pmu->map_event = armv8_thunder_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -1030,7 +1064,10 @@ static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu) armv8_pmu_init(cpu_pmu); cpu_pmu->name = "armv8_brcm_vulcan"; cpu_pmu->map_event = armv8_vulcan_map_event; - cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = + &armv8_pmuv3_events_attr_group; + cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = + &armv8_pmuv3_format_attr_group; return armv8pmu_probe_pmu(cpu_pmu); } @@ -1044,21 +1081,32 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = { {}, }; +/* + * Non DT systems have their micro/arch events probed at run-time. + * A fairly complete list of generic events are provided and ones that + * aren't supported by the current PMU are disabled. + */ +static const struct pmu_probe_info armv8_pmu_probe_table[] = { + PMU_PROBE(0, 0, armv8_pmuv3_init), /* enable all defined counters */ + { /* sentinel value */ } +}; + static int armv8_pmu_device_probe(struct platform_device *pdev) { - return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, NULL); + if (acpi_disabled) + return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, + NULL); + + return arm_pmu_device_probe(pdev, armv8_pmu_of_device_ids, + armv8_pmu_probe_table); } static struct platform_driver armv8_pmu_driver = { .driver = { - .name = "armv8-pmu", + .name = ARMV8_PMU_PDEV_NAME, .of_match_table = armv8_pmu_of_device_ids, }, .probe = armv8_pmu_device_probe, }; -static int __init register_armv8_pmu_driver(void) -{ - return platform_driver_register(&armv8_pmu_driver); -} -device_initcall(register_armv8_pmu_driver); +builtin_platform_driver(armv8_pmu_driver); diff --git a/arch/arm64/kernel/probes/Makefile b/arch/arm64/kernel/probes/Makefile index ce06312e3d34..89b6df613dde 100644 --- a/arch/arm64/kernel/probes/Makefile +++ b/arch/arm64/kernel/probes/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \ kprobes_trampoline.o \ simulate-insn.o +obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \ + simulate-insn.o diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c index 37e47a9d617e..6bf6657a5a52 100644 --- a/arch/arm64/kernel/probes/decode-insn.c +++ b/arch/arm64/kernel/probes/decode-insn.c @@ -16,7 +16,7 @@ #include <linux/kernel.h> #include <linux/kprobes.h> #include <linux/module.h> -#include <asm/kprobes.h> +#include <linux/kallsyms.h> #include <asm/insn.h> #include <asm/sections.h> @@ -77,8 +77,8 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn) * INSN_GOOD If instruction is supported and uses instruction slot, * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. */ -static enum kprobe_insn __kprobes -arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) +enum probe_insn __kprobes +arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api) { /* * Instructions reading or modifying the PC won't work from the XOL @@ -88,26 +88,26 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD; if (aarch64_insn_is_bcond(insn)) { - asi->handler = simulate_b_cond; + api->handler = simulate_b_cond; } else if (aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn)) { - asi->handler = simulate_cbz_cbnz; + api->handler = simulate_cbz_cbnz; } else if (aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn)) { - asi->handler = simulate_tbz_tbnz; + api->handler = simulate_tbz_tbnz; } else if (aarch64_insn_is_adr_adrp(insn)) { - asi->handler = simulate_adr_adrp; + api->handler = simulate_adr_adrp; } else if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn)) { - asi->handler = simulate_b_bl; + api->handler = simulate_b_bl; } else if (aarch64_insn_is_br(insn) || aarch64_insn_is_blr(insn) || aarch64_insn_is_ret(insn)) { - asi->handler = simulate_br_blr_ret; + api->handler = simulate_br_blr_ret; } else if (aarch64_insn_is_ldr_lit(insn)) { - asi->handler = simulate_ldr_literal; + api->handler = simulate_ldr_literal; } else if (aarch64_insn_is_ldrsw_lit(insn)) { - asi->handler = simulate_ldrsw_literal; + api->handler = simulate_ldrsw_literal; } else { /* * Instruction cannot be stepped out-of-line and we don't @@ -119,10 +119,11 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD_NO_SLOT; } +#ifdef CONFIG_KPROBES static bool __kprobes is_probed_address_atomic(kprobe_opcode_t *scan_start, kprobe_opcode_t *scan_end) { - while (scan_start > scan_end) { + while (scan_start >= scan_end) { /* * atomic region starts from exclusive load and ends with * exclusive store. @@ -137,38 +138,36 @@ is_probed_address_atomic(kprobe_opcode_t *scan_start, kprobe_opcode_t *scan_end) return false; } -enum kprobe_insn __kprobes +enum probe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi) { - enum kprobe_insn decoded; - kprobe_opcode_t insn = le32_to_cpu(*addr); - kprobe_opcode_t *scan_start = addr - 1; - kprobe_opcode_t *scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; -#if defined(CONFIG_MODULES) && defined(MODULES_VADDR) - struct module *mod; -#endif + enum probe_insn decoded; + probe_opcode_t insn = le32_to_cpu(*addr); + probe_opcode_t *scan_end = NULL; + unsigned long size = 0, offset = 0; - if (addr >= (kprobe_opcode_t *)_text && - scan_end < (kprobe_opcode_t *)_text) - scan_end = (kprobe_opcode_t *)_text; -#if defined(CONFIG_MODULES) && defined(MODULES_VADDR) - else { - preempt_disable(); - mod = __module_address((unsigned long)addr); - if (mod && within_module_init((unsigned long)addr, mod) && - !within_module_init((unsigned long)scan_end, mod)) - scan_end = (kprobe_opcode_t *)mod->init_layout.base; - else if (mod && within_module_core((unsigned long)addr, mod) && - !within_module_core((unsigned long)scan_end, mod)) - scan_end = (kprobe_opcode_t *)mod->core_layout.base; - preempt_enable(); + /* + * If there's a symbol defined in front of and near enough to + * the probe address assume it is the entry point to this + * code and use it to further limit how far back we search + * when determining if we're in an atomic sequence. If we could + * not find any symbol skip the atomic test altogether as we + * could otherwise end up searching irrelevant text/literals. + * KPROBES depends on KALLSYMS so this last case should never + * happen. + */ + if (kallsyms_lookup_size_offset((unsigned long) addr, &size, &offset)) { + if (offset < (MAX_ATOMIC_CONTEXT_SIZE*sizeof(kprobe_opcode_t))) + scan_end = addr - (offset / sizeof(kprobe_opcode_t)); + else + scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; } -#endif - decoded = arm_probe_decode_insn(insn, asi); + decoded = arm_probe_decode_insn(insn, &asi->api); - if (decoded == INSN_REJECTED || - is_probed_address_atomic(scan_start, scan_end)) - return INSN_REJECTED; + if (decoded != INSN_REJECTED && scan_end) + if (is_probed_address_atomic(addr - 1, scan_end)) + return INSN_REJECTED; return decoded; } +#endif diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h index d438289646a6..76d3f315407f 100644 --- a/arch/arm64/kernel/probes/decode-insn.h +++ b/arch/arm64/kernel/probes/decode-insn.h @@ -23,13 +23,17 @@ */ #define MAX_ATOMIC_CONTEXT_SIZE (128 / sizeof(kprobe_opcode_t)) -enum kprobe_insn { +enum probe_insn { INSN_REJECTED, INSN_GOOD_NO_SLOT, INSN_GOOD, }; -enum kprobe_insn __kprobes +#ifdef CONFIG_KPROBES +enum probe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi); +#endif +enum probe_insn __kprobes +arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *asi); #endif /* _ARM_KERNEL_KPROBES_ARM64_H */ diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index c6b0f40620d8..f0593c92279b 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -19,7 +19,7 @@ #include <linux/kasan.h> #include <linux/kernel.h> #include <linux/kprobes.h> -#include <linux/module.h> +#include <linux/extable.h> #include <linux/slab.h> #include <linux/stop_machine.h> #include <linux/stringify.h> @@ -29,9 +29,9 @@ #include <asm/debug-monitors.h> #include <asm/system_misc.h> #include <asm/insn.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/irq.h> -#include <asm-generic/sections.h> +#include <asm/sections.h> #include "decode-insn.h" @@ -44,31 +44,31 @@ post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *); static void __kprobes arch_prepare_ss_slot(struct kprobe *p) { /* prepare insn slot */ - p->ainsn.insn[0] = cpu_to_le32(p->opcode); + p->ainsn.api.insn[0] = cpu_to_le32(p->opcode); - flush_icache_range((uintptr_t) (p->ainsn.insn), - (uintptr_t) (p->ainsn.insn) + + flush_icache_range((uintptr_t) (p->ainsn.api.insn), + (uintptr_t) (p->ainsn.api.insn) + MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); /* * Needs restoring of return address after stepping xol. */ - p->ainsn.restore = (unsigned long) p->addr + + p->ainsn.api.restore = (unsigned long) p->addr + sizeof(kprobe_opcode_t); } static void __kprobes arch_prepare_simulate(struct kprobe *p) { /* This instructions is not executed xol. No need to adjust the PC */ - p->ainsn.restore = 0; + p->ainsn.api.restore = 0; } static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) { struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - if (p->ainsn.handler) - p->ainsn.handler((u32)p->opcode, (long)p->addr, regs); + if (p->ainsn.api.handler) + p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs); /* single step simulated, now go for post processing */ post_kprobe_handler(kcb, regs); @@ -98,18 +98,18 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) return -EINVAL; case INSN_GOOD_NO_SLOT: /* insn need simulation */ - p->ainsn.insn = NULL; + p->ainsn.api.insn = NULL; break; case INSN_GOOD: /* instruction uses slot */ - p->ainsn.insn = get_insn_slot(); - if (!p->ainsn.insn) + p->ainsn.api.insn = get_insn_slot(); + if (!p->ainsn.api.insn) return -ENOMEM; break; }; /* prepare the instruction */ - if (p->ainsn.insn) + if (p->ainsn.api.insn) arch_prepare_ss_slot(p); else arch_prepare_simulate(p); @@ -142,9 +142,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - if (p->ainsn.insn) { - free_insn_slot(p->ainsn.insn, 0); - p->ainsn.insn = NULL; + if (p->ainsn.api.insn) { + free_insn_slot(p->ainsn.api.insn, 0); + p->ainsn.api.insn = NULL; } } @@ -166,13 +166,18 @@ static void __kprobes set_current_kprobe(struct kprobe *p) } /* - * The D-flag (Debug mask) is set (masked) upon debug exception entry. - * Kprobes needs to clear (unmask) D-flag -ONLY- in case of recursive - * probe i.e. when probe hit from kprobe handler context upon - * executing the pre/post handlers. In this case we return with - * D-flag clear so that single-stepping can be carried-out. - * - * Leave D-flag set in all other cases. + * When PSTATE.D is set (masked), then software step exceptions can not be + * generated. + * SPSR's D bit shows the value of PSTATE.D immediately before the + * exception was taken. PSTATE.D is set while entering into any exception + * mode, however software clears it for any normal (none-debug-exception) + * mode in the exception entry. Therefore, when we are entering into kprobe + * breakpoint handler from any normal mode then SPSR.D bit is already + * cleared, however it is set when we are entering from any debug exception + * mode. + * Since we always need to generate single step exception after a kprobe + * breakpoint exception therefore we need to clear it unconditionally, when + * we become sure that the current breakpoint exception is for kprobe. */ static void __kprobes spsr_set_debug_flag(struct pt_regs *regs, int mask) @@ -239,16 +244,13 @@ static void __kprobes setup_singlestep(struct kprobe *p, } - if (p->ainsn.insn) { + if (p->ainsn.api.insn) { /* prepare for single stepping */ - slot = (unsigned long)p->ainsn.insn; + slot = (unsigned long)p->ainsn.api.insn; set_ss_context(kcb, slot); /* mark pending ss */ - if (kcb->kprobe_status == KPROBE_REENTER) - spsr_set_debug_flag(regs, 0); - else - WARN_ON(regs->pstate & PSR_D_BIT); + spsr_set_debug_flag(regs, 0); /* IRQs and single stepping do not mix well. */ kprobes_save_local_irqflag(kcb, regs); @@ -293,8 +295,8 @@ post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs) return; /* return addr restore if non-branching insn */ - if (cur->ainsn.restore != 0) - instruction_pointer_set(regs, cur->ainsn.restore); + if (cur->ainsn.api.restore != 0) + instruction_pointer_set(regs, cur->ainsn.api.restore); /* restore back original saved kprobe variables and continue */ if (kcb->kprobe_status == KPROBE_REENTER) { @@ -333,8 +335,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr) BUG(); kernel_disable_single_step(); - if (kcb->kprobe_status == KPROBE_REENTER) - spsr_set_debug_flag(regs, 1); if (kcb->kprobe_status == KPROBE_REENTER) restore_previous_kprobe(kcb); @@ -457,9 +457,6 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr) kprobes_restore_local_irqflag(kcb, regs); kernel_disable_single_step(); - if (kcb->kprobe_status == KPROBE_REENTER) - spsr_set_debug_flag(regs, 1); - post_kprobe_handler(kcb, regs); } @@ -543,9 +540,6 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) bool arch_within_kprobe_blacklist(unsigned long addr) { - extern char __idmap_text_start[], __idmap_text_end[]; - extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[]; - if ((addr >= (unsigned long)__kprobes_text_start && addr < (unsigned long)__kprobes_text_end) || (addr >= (unsigned long)__entry_text_start && diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c index 8977ce9d009d..357d3efe1366 100644 --- a/arch/arm64/kernel/probes/simulate-insn.c +++ b/arch/arm64/kernel/probes/simulate-insn.c @@ -13,28 +13,26 @@ * General Public License for more details. */ +#include <linux/bitops.h> #include <linux/kernel.h> #include <linux/kprobes.h> #include "simulate-insn.h" -#define sign_extend(x, signbit) \ - ((x) | (0 - ((x) & (1 << (signbit))))) - #define bbl_displacement(insn) \ - sign_extend(((insn) & 0x3ffffff) << 2, 27) + sign_extend32(((insn) & 0x3ffffff) << 2, 27) #define bcond_displacement(insn) \ - sign_extend(((insn >> 5) & 0x7ffff) << 2, 20) + sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20) #define cbz_displacement(insn) \ - sign_extend(((insn >> 5) & 0x7ffff) << 2, 20) + sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20) #define tbz_displacement(insn) \ - sign_extend(((insn >> 5) & 0x3fff) << 2, 15) + sign_extend32(((insn >> 5) & 0x3fff) << 2, 15) #define ldr_displacement(insn) \ - sign_extend(((insn >> 5) & 0x7ffff) << 2, 20) + sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20) static inline void set_x_reg(struct pt_regs *regs, int reg, u64 val) { @@ -106,7 +104,7 @@ simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs) xn = opcode & 0x1f; imm = ((opcode >> 3) & 0x1ffffc) | ((opcode >> 29) & 0x3); - imm = sign_extend(imm, 20); + imm = sign_extend64(imm, 20); if (opcode & 0x80000000) val = (imm<<12) + (addr & 0xfffffffffffff000); else diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c new file mode 100644 index 000000000000..26c998534dca --- /dev/null +++ b/arch/arm64/kernel/probes/uprobes.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.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 <linux/highmem.h> +#include <linux/ptrace.h> +#include <linux/uprobes.h> +#include <asm/cacheflush.h> + +#include "decode-insn.h" + +#define UPROBE_INV_FAULT_CODE UINT_MAX + +void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len) +{ + void *xol_page_kaddr = kmap_atomic(page); + void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); + + /* Initialize the slot */ + memcpy(dst, src, len); + + /* flush caches (dcache/icache) */ + sync_icache_aliases(dst, len); + + kunmap_atomic(xol_page_kaddr); +} + +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) +{ + return instruction_pointer(regs); +} + +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, + unsigned long addr) +{ + probe_opcode_t insn; + + /* TODO: Currently we do not support AARCH32 instruction probing */ + if (test_bit(TIF_32BIT, &mm->context.flags)) + return -ENOTSUPP; + else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) + return -EINVAL; + + insn = *(probe_opcode_t *)(&auprobe->insn[0]); + + switch (arm_probe_decode_insn(insn, &auprobe->api)) { + case INSN_REJECTED: + return -EINVAL; + + case INSN_GOOD_NO_SLOT: + auprobe->simulate = true; + break; + + default: + break; + } + + return 0; +} + +int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + /* Initialize with an invalid fault code to detect if ol insn trapped */ + current->thread.fault_code = UPROBE_INV_FAULT_CODE; + + /* Instruction points to execute ol */ + instruction_pointer_set(regs, utask->xol_vaddr); + + user_enable_single_step(current); + + return 0; +} + +int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + WARN_ON_ONCE(current->thread.fault_code != UPROBE_INV_FAULT_CODE); + + /* Instruction points to execute next to breakpoint address */ + instruction_pointer_set(regs, utask->vaddr + 4); + + user_disable_single_step(current); + + return 0; +} +bool arch_uprobe_xol_was_trapped(struct task_struct *t) +{ + /* + * Between arch_uprobe_pre_xol and arch_uprobe_post_xol, if an xol + * insn itself is trapped, then detect the case with the help of + * invalid fault code which is being set in arch_uprobe_pre_xol + */ + if (t->thread.fault_code != UPROBE_INV_FAULT_CODE) + return true; + + return false; +} + +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + probe_opcode_t insn; + unsigned long addr; + + if (!auprobe->simulate) + return false; + + insn = *(probe_opcode_t *)(&auprobe->insn[0]); + addr = instruction_pointer(regs); + + if (auprobe->api.handler) + auprobe->api.handler(insn, addr, regs); + + return true; +} + +void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + /* + * Task has received a fatal signal, so reset back to probbed + * address. + */ + instruction_pointer_set(regs, utask->vaddr); + + user_disable_single_step(current); +} + +bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, + struct pt_regs *regs) +{ + /* + * If a simple branch instruction (B) was called for retprobed + * assembly label then return true even when regs->sp and ret->stack + * are same. It will ensure that cleanup and reporting of return + * instances corresponding to callee label is done when + * handle_trampoline for called function is executed. + */ + if (ctx == RP_CHECK_CHAIN_CALL) + return regs->sp <= ret->stack; + else + return regs->sp < ret->stack; +} + +unsigned long +arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, + struct pt_regs *regs) +{ + unsigned long orig_ret_vaddr; + + orig_ret_vaddr = procedure_link_pointer(regs); + /* Replace the return addr with trampoline addr */ + procedure_link_pointer_set(regs, trampoline_vaddr); + + return orig_ret_vaddr; +} + +int arch_uprobe_exception_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + return NOTIFY_DONE; +} + +static int uprobe_breakpoint_handler(struct pt_regs *regs, + unsigned int esr) +{ + if (user_mode(regs) && uprobe_pre_sstep_notifier(regs)) + return DBG_HOOK_HANDLED; + + return DBG_HOOK_ERROR; +} + +static int uprobe_single_step_handler(struct pt_regs *regs, + unsigned int esr) +{ + struct uprobe_task *utask = current->utask; + + if (user_mode(regs)) { + WARN_ON(utask && + (instruction_pointer(regs) != utask->xol_vaddr + 4)); + + if (uprobe_post_sstep_notifier(regs)) + return DBG_HOOK_HANDLED; + } + + return DBG_HOOK_ERROR; +} + +/* uprobe breakpoint handler hook */ +static struct break_hook uprobes_break_hook = { + .esr_mask = BRK64_ESR_MASK, + .esr_val = BRK64_ESR_UPROBES, + .fn = uprobe_breakpoint_handler, +}; + +/* uprobe single step handler hook */ +static struct step_hook uprobes_step_hook = { + .fn = uprobe_single_step_handler, +}; + +static int __init arch_init_uprobes(void) +{ + register_break_hook(&uprobes_break_hook); + register_step_hook(&uprobes_step_hook); + + return 0; +} + +device_initcall(arch_init_uprobes); diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 6cd2612236dc..a3a2816ba73a 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -45,10 +45,12 @@ #include <linux/personality.h> #include <linux/notifier.h> #include <trace/events/power.h> +#include <linux/percpu.h> #include <asm/alternative.h> #include <asm/compat.h> #include <asm/cacheflush.h> +#include <asm/exec.h> #include <asm/fpsimd.h> #include <asm/mmu_context.h> #include <asm/processor.h> @@ -186,10 +188,19 @@ void __show_regs(struct pt_regs *regs) printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", regs->pc, lr, regs->pstate); printk("sp : %016llx\n", sp); - for (i = top_reg; i >= 0; i--) { + + i = top_reg; + + while (i >= 0) { printk("x%-2d: %016llx ", i, regs->regs[i]); - if (i % 2 == 0) - printk("\n"); + i--; + + if (i % 2 == 0) { + pr_cont("x%-2d: %016llx ", i, regs->regs[i]); + i--; + } + + pr_cont("\n"); } printk("\n"); } @@ -202,7 +213,7 @@ void show_regs(struct pt_regs * regs) static void tls_thread_flush(void) { - asm ("msr tpidr_el0, xzr"); + write_sysreg(0, tpidr_el0); if (is_compat_task()) { current->thread.tp_value = 0; @@ -213,7 +224,7 @@ static void tls_thread_flush(void) * with a stale shadow state during context switch. */ barrier(); - asm ("msr tpidrro_el0, xzr"); + write_sysreg(0, tpidrro_el0); } } @@ -253,7 +264,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, * Read the current TLS pointer from tpidr_el0 as it may be * out-of-sync with the saved value. */ - asm("mrs %0, tpidr_el0" : "=r" (*task_user_tls(p))); + *task_user_tls(p) = read_sysreg(tpidr_el0); if (stack_start) { if (is_compat_thread(task_thread_info(p))) @@ -272,7 +283,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, memset(childregs, 0, sizeof(struct pt_regs)); childregs->pstate = PSR_MODE_EL1h; if (IS_ENABLED(CONFIG_ARM64_UAO) && - cpus_have_cap(ARM64_HAS_UAO)) + cpus_have_const_cap(ARM64_HAS_UAO)) childregs->pstate |= PSR_UAO_BIT; p->thread.cpu_context.x19 = stack_start; p->thread.cpu_context.x20 = stk_sz; @@ -289,21 +300,19 @@ static void tls_thread_switch(struct task_struct *next) { unsigned long tpidr, tpidrro; - asm("mrs %0, tpidr_el0" : "=r" (tpidr)); + tpidr = read_sysreg(tpidr_el0); *task_user_tls(current) = tpidr; tpidr = *task_user_tls(next); tpidrro = is_compat_thread(task_thread_info(next)) ? next->thread.tp_value : 0; - asm( - " msr tpidr_el0, %0\n" - " msr tpidrro_el0, %1" - : : "r" (tpidr), "r" (tpidrro)); + write_sysreg(tpidr, tpidr_el0); + write_sysreg(tpidrro, tpidrro_el0); } /* Restore the UAO state depending on next's addr_limit */ -static void uao_thread_switch(struct task_struct *next) +void uao_thread_switch(struct task_struct *next) { if (IS_ENABLED(CONFIG_ARM64_UAO)) { if (task_thread_info(next)->addr_limit == KERNEL_DS) @@ -314,6 +323,20 @@ static void uao_thread_switch(struct task_struct *next) } /* + * We store our current task in sp_el0, which is clobbered by userspace. Keep a + * shadow copy so that we can restore this upon entry from userspace. + * + * This is *only* for exception entry from EL0, and is not valid until we + * __switch_to() a user task. + */ +DEFINE_PER_CPU(struct task_struct *, __entry_task); + +static void entry_task_switch(struct task_struct *next) +{ + __this_cpu_write(__entry_task, next); +} + +/* * Thread switching. */ struct task_struct *__switch_to(struct task_struct *prev, @@ -325,6 +348,7 @@ struct task_struct *__switch_to(struct task_struct *prev, tls_thread_switch(next); hw_breakpoint_thread_switch(next); contextidr_thread_switch(next); + entry_task_switch(next); uao_thread_switch(next); /* @@ -342,27 +366,35 @@ struct task_struct *__switch_to(struct task_struct *prev, unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; - unsigned long stack_page; + unsigned long stack_page, ret = 0; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; + stack_page = (unsigned long)try_get_task_stack(p); + if (!stack_page) + return 0; + frame.fp = thread_saved_fp(p); frame.sp = thread_saved_sp(p); frame.pc = thread_saved_pc(p); #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = p->curr_ret_stack; #endif - stack_page = (unsigned long)task_stack_page(p); do { if (frame.sp < stack_page || frame.sp >= stack_page + THREAD_SIZE || unwind_frame(p, &frame)) - return 0; - if (!in_sched_functions(frame.pc)) - return frame.pc; + goto out; + if (!in_sched_functions(frame.pc)) { + ret = frame.pc; + goto out; + } } while (count ++ < 16); - return 0; + +out: + put_task_stack(p); + return ret; } unsigned long arch_align_stack(unsigned long sp) @@ -374,12 +406,8 @@ unsigned long arch_align_stack(unsigned long sp) unsigned long arch_randomize_brk(struct mm_struct *mm) { - unsigned long range_end = mm->brk; - if (is_compat_task()) - range_end += 0x02000000; + return randomize_page(mm->brk, 0x02000000); else - range_end += 0x40000000; - - return randomize_range(mm->brk, range_end, 0) ? : mm->brk; + return randomize_page(mm->brk, 0x40000000); } diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index e0c81da60f76..fc35e06ccaac 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, struct arch_hw_breakpoint_ctrl ctrl, struct perf_event_attr *attr) { - int err, len, type, disabled = !ctrl.enabled; + int err, len, type, offset, disabled = !ctrl.enabled; attr->disabled = disabled; if (disabled) return 0; - err = arch_bp_generic_fields(ctrl, &len, &type); + err = arch_bp_generic_fields(ctrl, &len, &type, &offset); if (err) return err; @@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, attr->bp_len = len; attr->bp_type = type; + attr->bp_addr += offset; return 0; } @@ -404,7 +405,7 @@ static int ptrace_hbp_get_addr(unsigned int note_type, if (IS_ERR(bp)) return PTR_ERR(bp); - *addr = bp ? bp->attr.bp_addr : 0; + *addr = bp ? counter_arch_bp(bp)->address : 0; return 0; } diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S index 51b73cdde287..ce704a4aeadd 100644 --- a/arch/arm64/kernel/relocate_kernel.S +++ b/arch/arm64/kernel/relocate_kernel.S @@ -34,7 +34,7 @@ ENTRY(arm64_relocate_new_kernel) /* Setup the list loop variables. */ mov x17, x1 /* x17 = kimage_start */ mov x16, x0 /* x16 = kimage_head */ - dcache_line_size x15, x0 /* x15 = dcache line size */ + raw_dcache_line_size x15, x0 /* x15 = dcache line size */ mov x14, xzr /* x14 = entry ptr */ mov x13, xzr /* x13 = copy dest */ diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c index 1718706fde83..12a87f2600f2 100644 --- a/arch/arm64/kernel/return_address.c +++ b/arch/arm64/kernel/return_address.c @@ -12,6 +12,7 @@ #include <linux/export.h> #include <linux/ftrace.h> +#include <asm/stack_pointer.h> #include <asm/stacktrace.h> struct return_address_data { diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 536dce22fe76..b051367e2149 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -206,10 +206,15 @@ static void __init request_standard_resources(void) for_each_memblock(memory, region) { res = alloc_bootmem_low(sizeof(*res)); - res->name = "System RAM"; + if (memblock_is_nomap(region)) { + res->name = "reserved"; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + } else { + res->name = "System RAM"; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; + } res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; - res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); @@ -228,7 +233,7 @@ void __init setup_arch(char **cmdline_p) { pr_info("Boot CPU: AArch64 Processor [%08x]\n", read_cpuid_id()); - sprintf(init_utsname()->machine, ELF_PLATFORM); + sprintf(init_utsname()->machine, UTS_MACHINE); init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; @@ -286,6 +291,15 @@ void __init setup_arch(char **cmdline_p) smp_init_cpus(); smp_build_mpidr_hash(); +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + /* + * Make sure init_thread_info.ttbr0 always generates translation + * faults in case uaccess_enable() is inadvertently called by the init + * thread. + */ + init_task.thread_info.ttbr0 = virt_to_phys(empty_zero_page); +#endif + #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; @@ -324,11 +338,11 @@ subsys_initcall(topology_init); static int dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) { - u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR; + const unsigned long offset = kaslr_offset(); - if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) { - pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n", - kaslr_offset, KIMAGE_VADDR); + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0) { + pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n", + offset, KIMAGE_VADDR); } else { pr_emerg("Kernel Offset: disabled\n"); } diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index a8eafdbc7cb8..c7b6de62f9d3 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -402,15 +402,34 @@ static void do_signal(struct pt_regs *regs) asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int thread_flags) { - if (thread_flags & _TIF_SIGPENDING) - do_signal(regs); - - if (thread_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - } - - if (thread_flags & _TIF_FOREIGN_FPSTATE) - fpsimd_restore_current_state(); + /* + * The assembly code enters us with IRQs off, but it hasn't + * informed the tracing code of that for efficiency reasons. + * Update the trace code with the current status. + */ + trace_hardirqs_off(); + do { + if (thread_flags & _TIF_NEED_RESCHED) { + schedule(); + } else { + local_irq_enable(); + + if (thread_flags & _TIF_UPROBE) + uprobe_notify_resume(regs); + + if (thread_flags & _TIF_SIGPENDING) + do_signal(regs); + + if (thread_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + + if (thread_flags & _TIF_FOREIGN_FPSTATE) + fpsimd_restore_current_state(); + } + local_irq_disable(); + thread_flags = READ_ONCE(current_thread_info()->flags); + } while (thread_flags & _TIF_WORK_MASK); } diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index b7063de792f7..c747a0fc5d7d 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -26,7 +26,7 @@ #include <asm/esr.h> #include <asm/fpsimd.h> #include <asm/signal32.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unistd.h> struct compat_sigcontext { diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index ccf79d849e0a..df67652e46f0 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -73,10 +73,9 @@ ENTRY(__cpu_suspend_enter) str x2, [x0, #SLEEP_STACK_DATA_SYSTEM_REGS + CPU_CTX_SP] /* find the mpidr_hash */ - ldr x1, =sleep_save_stash - ldr x1, [x1] + ldr_l x1, sleep_save_stash mrs x7, mpidr_el1 - ldr x9, =mpidr_hash + adr_l x9, mpidr_hash ldr x10, [x9, #MPIDR_HASH_MASK] /* * Following code relies on the struct mpidr_hash @@ -95,36 +94,30 @@ ENTRY(__cpu_suspend_enter) mov x0, #1 ret ENDPROC(__cpu_suspend_enter) - .ltorg + .pushsection ".idmap.text", "ax" ENTRY(cpu_resume) bl el2_setup // if in EL2 drop to EL1 cleanly + bl __cpu_setup /* enable the MMU early - so we can access sleep_save_stash by va */ - adr_l lr, __enable_mmu /* __cpu_setup will return here */ - adr_l x27, _resume_switched /* __enable_mmu will branch here */ - adrp x25, idmap_pg_dir - adrp x26, swapper_pg_dir - b __cpu_setup -ENDPROC(cpu_resume) - - .pushsection ".idmap.text", "ax" -_resume_switched: + bl __enable_mmu ldr x8, =_cpu_resume br x8 -ENDPROC(_resume_switched) +ENDPROC(cpu_resume) .ltorg .popsection ENTRY(_cpu_resume) mrs x1, mpidr_el1 - adrp x8, mpidr_hash - add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address - /* retrieve mpidr_hash members to compute the hash */ + adr_l x8, mpidr_hash // x8 = struct mpidr_hash virt address + + /* retrieve mpidr_hash members to compute the hash */ ldr x2, [x8, #MPIDR_HASH_MASK] ldp w3, w4, [x8, #MPIDR_HASH_SHIFTS] ldp w5, w6, [x8, #(MPIDR_HASH_SHIFTS + 8)] compute_mpidr_hash x7, x3, x4, x5, x6, x1, x2 - /* x7 contains hash index, let's use it to grab context pointer */ + + /* x7 contains hash index, let's use it to grab context pointer */ ldr_l x0, sleep_save_stash ldr x0, [x0, x7, lsl #3] add x29, x0, #SLEEP_STACK_DATA_CALLEE_REGS @@ -132,9 +125,6 @@ ENTRY(_cpu_resume) /* load sp from context */ ldr x2, [x0, #CPU_CTX_SP] mov sp, x2 - /* save thread_info */ - and x2, x2, #~(THREAD_SIZE - 1) - msr sp_el0, x2 /* * cpu_do_resume expects x0 to contain context address pointer */ @@ -142,7 +132,7 @@ ENTRY(_cpu_resume) #ifdef CONFIG_KASAN mov x0, sp - bl kasan_unpoison_remaining_stack + bl kasan_unpoison_task_stack_below #endif ldp x19, x20, [x29, #16] diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 3ff173e92582..cb87234cfcf2 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -58,6 +58,9 @@ #define CREATE_TRACE_POINTS #include <trace/events/ipi.h> +DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); +EXPORT_PER_CPU_SYMBOL(cpu_number); + /* * as from 2.5, kernels no longer have an init_tasks structure * so we need some other way of telling a new secondary core @@ -146,6 +149,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) * We need to tell the secondary core where to find its stack and the * page tables. */ + secondary_data.task = idle; secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; update_cpu_boot_status(CPU_MMU_OFF); __flush_dcache_area(&secondary_data, sizeof(secondary_data)); @@ -170,6 +174,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) pr_err("CPU%u: failed to boot: %d\n", cpu, ret); } + secondary_data.task = NULL; secondary_data.stack = NULL; status = READ_ONCE(secondary_data.status); if (ret && status) { @@ -208,7 +213,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + cpu = task_cpu(current); + set_my_cpu_offset(per_cpu_offset(cpu)); /* * All kernel threads share the same mm context; grab a @@ -217,8 +225,6 @@ asmlinkage void secondary_start_kernel(void) atomic_inc(&mm->mm_count); current->active_mm = mm; - set_my_cpu_offset(per_cpu_offset(smp_processor_id())); - /* * TTBR0 is only used for the identity mapping at this stage. Make it * point to zero page to avoid speculatively fetching new entries. @@ -233,7 +239,7 @@ asmlinkage void secondary_start_kernel(void) * this CPU ticks all of those. If it doesn't, the CPU will * fail to come online. */ - verify_local_cpu_capabilities(); + check_local_cpu_capabilities(); if (cpu_ops[cpu]->cpu_postboot) cpu_ops[cpu]->cpu_postboot(); @@ -431,8 +437,19 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_prepare_boot_cpu(void) { set_my_cpu_offset(per_cpu_offset(smp_processor_id())); + /* + * Initialise the static keys early as they may be enabled by the + * cpufeature code. + */ + jump_label_init(); cpuinfo_store_boot_cpu(); save_boot_cpu_run_el(); + /* + * Run the errata work around checks on the boot CPU, once we have + * initialised the cpu feature infrastructure from + * cpuinfo_store_boot_cpu() above. + */ + update_cpu_errata_workarounds(); } static u64 __init of_get_cpu_mpidr(struct device_node *dn) @@ -533,6 +550,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor) return; } bootcpu_valid = true; + early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid)); return; } @@ -613,6 +631,7 @@ static void __init of_parse_and_init_cpus(void) } bootcpu_valid = true; + early_map_cpu_to_node(0, of_node_to_nid(dn)); /* * cpu_logical_map has already been @@ -705,6 +724,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) */ for_each_possible_cpu(cpu) { + per_cpu(cpu_number, cpu) = cpu; + if (cpu == smp_processor_id()) continue; diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c index 18a71bcd26ee..9a00eee9acc8 100644 --- a/arch/arm64/kernel/smp_spin_table.c +++ b/arch/arm64/kernel/smp_spin_table.c @@ -29,7 +29,8 @@ #include <asm/smp_plat.h> extern void secondary_holding_pen(void); -volatile unsigned long secondary_holding_pen_release = INVALID_HWID; +volatile unsigned long __section(".mmuoff.data.read") +secondary_holding_pen_release = INVALID_HWID; static phys_addr_t cpu_release_addr[NR_CPUS]; diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c index d9751a4769e7..8a552a33c6ef 100644 --- a/arch/arm64/kernel/stacktrace.c +++ b/arch/arm64/kernel/stacktrace.c @@ -22,6 +22,7 @@ #include <linux/stacktrace.h> #include <asm/irq.h> +#include <asm/stack_pointer.h> #include <asm/stacktrace.h> /* @@ -43,6 +44,9 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) unsigned long fp = frame->fp; unsigned long irq_stack_ptr; + if (!tsk) + tsk = current; + /* * Switching between stacks is valid when tracing current and in * non-preemptible context. @@ -67,7 +71,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); #ifdef CONFIG_FUNCTION_GRAPH_TRACER - if (tsk && tsk->ret_stack && + if (tsk->ret_stack && (frame->pc == (unsigned long)return_to_handler)) { /* * This is a case where function graph tracer has @@ -125,7 +129,6 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, break; } } -EXPORT_SYMBOL(walk_stackframe); #ifdef CONFIG_STACKTRACE struct stack_trace_data { @@ -152,11 +155,35 @@ static int save_trace(struct stackframe *frame, void *d) return trace->nr_entries >= trace->max_entries; } +void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) +{ + struct stack_trace_data data; + struct stackframe frame; + + data.trace = trace; + data.skip = trace->skip; + data.no_sched_functions = 0; + + frame.fp = regs->regs[29]; + frame.sp = regs->sp; + frame.pc = regs->pc; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + frame.graph = current->curr_ret_stack; +#endif + + walk_stackframe(current, &frame, save_trace, &data); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} + void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { struct stack_trace_data data; struct stackframe frame; + if (!try_get_task_stack(tsk)) + return; + data.trace = trace; data.skip = trace->skip; @@ -178,6 +205,8 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) walk_stackframe(tsk, &frame, save_trace, &data); if (trace->nr_entries < trace->max_entries) trace->entries[trace->nr_entries++] = ULONG_MAX; + + put_task_stack(tsk); } void save_stack_trace(struct stack_trace *trace) diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index b616e365cee3..1e3be9064cfa 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c @@ -1,8 +1,11 @@ #include <linux/ftrace.h> #include <linux/percpu.h> #include <linux/slab.h> +#include <asm/alternative.h> #include <asm/cacheflush.h> +#include <asm/cpufeature.h> #include <asm/debug-monitors.h> +#include <asm/exec.h> #include <asm/pgtable.h> #include <asm/memory.h> #include <asm/mmu_context.h> @@ -23,8 +26,8 @@ unsigned long *sleep_save_stash; * time the notifier runs debug exceptions might have been enabled already, * with HW breakpoints registers content still in an unknown state. */ -static void (*hw_breakpoint_restore)(void *); -void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) +static int (*hw_breakpoint_restore)(unsigned int); +void __init cpu_suspend_set_dbg_restorer(int (*hw_bp_restore)(unsigned int)) { /* Prevent multiple restore hook initializations */ if (WARN_ON(hw_breakpoint_restore)) @@ -34,6 +37,8 @@ void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) void notrace __cpu_suspend_exit(void) { + unsigned int cpu = smp_processor_id(); + /* * We are resuming from reset with the idmap active in TTBR0_EL1. * We must uninstall the idmap and restore the expected MMU @@ -42,10 +47,12 @@ void notrace __cpu_suspend_exit(void) cpu_uninstall_idmap(); /* - * Restore per-cpu offset before any kernel - * subsystem relying on it has a chance to run. + * PSTATE was not saved over suspend/resume, re-enable any detected + * features that might not have been set correctly. */ - set_my_cpu_offset(per_cpu_offset(smp_processor_id())); + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, + CONFIG_ARM64_PAN)); + uao_thread_switch(current); /* * Restore HW breakpoint registers to sane values @@ -53,7 +60,7 @@ void notrace __cpu_suspend_exit(void) * through local_dbg_restore. */ if (hw_breakpoint_restore) - hw_breakpoint_restore(NULL); + hw_breakpoint_restore(cpu); } /* diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 28c511b06edf..abaf582fc7a8 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -94,7 +94,7 @@ long compat_arm_syscall(struct pt_regs *regs) * See comment in tls_thread_flush. */ barrier(); - asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); + write_sysreg(regs->regs[0], tpidrro_el0); return 0; default: diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 694f6deedbab..23e9e13bd2aa 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -19,10 +19,226 @@ #include <linux/nodemask.h> #include <linux/of.h> #include <linux/sched.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/cpufreq.h> +#include <asm/cpu.h> #include <asm/cputype.h> #include <asm/topology.h> +static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; +static DEFINE_MUTEX(cpu_scale_mutex); + +unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu) +{ + return per_cpu(cpu_scale, cpu); +} + +static void set_capacity_scale(unsigned int cpu, unsigned long capacity) +{ + per_cpu(cpu_scale, cpu) = capacity; +} + +#ifdef CONFIG_PROC_SYSCTL +static ssize_t cpu_capacity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cpu *cpu = container_of(dev, struct cpu, dev); + + return sprintf(buf, "%lu\n", + arch_scale_cpu_capacity(NULL, cpu->dev.id)); +} + +static ssize_t cpu_capacity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct cpu *cpu = container_of(dev, struct cpu, dev); + int this_cpu = cpu->dev.id, i; + unsigned long new_capacity; + ssize_t ret; + + if (count) { + ret = kstrtoul(buf, 0, &new_capacity); + if (ret) + return ret; + if (new_capacity > SCHED_CAPACITY_SCALE) + return -EINVAL; + + mutex_lock(&cpu_scale_mutex); + for_each_cpu(i, &cpu_topology[this_cpu].core_sibling) + set_capacity_scale(i, new_capacity); + mutex_unlock(&cpu_scale_mutex); + } + + return count; +} + +static DEVICE_ATTR_RW(cpu_capacity); + +static int register_cpu_capacity_sysctl(void) +{ + int i; + struct device *cpu; + + for_each_possible_cpu(i) { + cpu = get_cpu_device(i); + if (!cpu) { + pr_err("%s: too early to get CPU%d device!\n", + __func__, i); + continue; + } + device_create_file(cpu, &dev_attr_cpu_capacity); + } + + return 0; +} +subsys_initcall(register_cpu_capacity_sysctl); +#endif + +static u32 capacity_scale; +static u32 *raw_capacity; +static bool cap_parsing_failed; + +static void __init parse_cpu_capacity(struct device_node *cpu_node, int cpu) +{ + int ret; + u32 cpu_capacity; + + if (cap_parsing_failed) + return; + + ret = of_property_read_u32(cpu_node, + "capacity-dmips-mhz", + &cpu_capacity); + if (!ret) { + if (!raw_capacity) { + raw_capacity = kcalloc(num_possible_cpus(), + sizeof(*raw_capacity), + GFP_KERNEL); + if (!raw_capacity) { + pr_err("cpu_capacity: failed to allocate memory for raw capacities\n"); + cap_parsing_failed = true; + return; + } + } + capacity_scale = max(cpu_capacity, capacity_scale); + raw_capacity[cpu] = cpu_capacity; + pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n", + cpu_node->full_name, raw_capacity[cpu]); + } else { + if (raw_capacity) { + pr_err("cpu_capacity: missing %s raw capacity\n", + cpu_node->full_name); + pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); + } + cap_parsing_failed = true; + kfree(raw_capacity); + } +} + +static void normalize_cpu_capacity(void) +{ + u64 capacity; + int cpu; + + if (!raw_capacity || cap_parsing_failed) + return; + + pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale); + mutex_lock(&cpu_scale_mutex); + for_each_possible_cpu(cpu) { + pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n", + cpu, raw_capacity[cpu]); + capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT) + / capacity_scale; + set_capacity_scale(cpu, capacity); + pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n", + cpu, arch_scale_cpu_capacity(NULL, cpu)); + } + mutex_unlock(&cpu_scale_mutex); +} + +#ifdef CONFIG_CPU_FREQ +static cpumask_var_t cpus_to_visit; +static bool cap_parsing_done; +static void parsing_done_workfn(struct work_struct *work); +static DECLARE_WORK(parsing_done_work, parsing_done_workfn); + +static int +init_cpu_capacity_callback(struct notifier_block *nb, + unsigned long val, + void *data) +{ + struct cpufreq_policy *policy = data; + int cpu; + + if (cap_parsing_failed || cap_parsing_done) + return 0; + + switch (val) { + case CPUFREQ_NOTIFY: + pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n", + cpumask_pr_args(policy->related_cpus), + cpumask_pr_args(cpus_to_visit)); + cpumask_andnot(cpus_to_visit, + cpus_to_visit, + policy->related_cpus); + for_each_cpu(cpu, policy->related_cpus) { + raw_capacity[cpu] = arch_scale_cpu_capacity(NULL, cpu) * + policy->cpuinfo.max_freq / 1000UL; + capacity_scale = max(raw_capacity[cpu], capacity_scale); + } + if (cpumask_empty(cpus_to_visit)) { + normalize_cpu_capacity(); + kfree(raw_capacity); + pr_debug("cpu_capacity: parsing done\n"); + cap_parsing_done = true; + schedule_work(&parsing_done_work); + } + } + return 0; +} + +static struct notifier_block init_cpu_capacity_notifier = { + .notifier_call = init_cpu_capacity_callback, +}; + +static int __init register_cpufreq_notifier(void) +{ + if (cap_parsing_failed) + return -EINVAL; + + if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) { + pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n"); + return -ENOMEM; + } + cpumask_copy(cpus_to_visit, cpu_possible_mask); + + return cpufreq_register_notifier(&init_cpu_capacity_notifier, + CPUFREQ_POLICY_NOTIFIER); +} +core_initcall(register_cpufreq_notifier); + +static void parsing_done_workfn(struct work_struct *work) +{ + cpufreq_unregister_notifier(&init_cpu_capacity_notifier, + CPUFREQ_POLICY_NOTIFIER); +} + +#else +static int __init free_raw_capacity(void) +{ + kfree(raw_capacity); + + return 0; +} +core_initcall(free_raw_capacity); +#endif + static int __init get_cpu_for_node(struct device_node *node) { struct device_node *cpu_node; @@ -34,6 +250,7 @@ static int __init get_cpu_for_node(struct device_node *node) for_each_possible_cpu(cpu) { if (of_get_cpu_node(cpu, NULL) == cpu_node) { + parse_cpu_capacity(cpu_node, cpu); of_node_put(cpu_node); return cpu; } @@ -178,13 +395,17 @@ static int __init parse_dt_topology(void) * cluster with restricted subnodes. */ map = of_get_child_by_name(cn, "cpu-map"); - if (!map) + if (!map) { + cap_parsing_failed = true; goto out; + } ret = parse_cluster(map, 0); if (ret != 0) goto out_map; + normalize_cpu_capacity(); + /* * Check that all cores are in the topology; the SMP code will * only mark cores described in the DT as possible. diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index e04f83873af7..5b830be79c01 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -38,6 +38,7 @@ #include <asm/esr.h> #include <asm/insn.h> #include <asm/traps.h> +#include <asm/stack_pointer.h> #include <asm/stacktrace.h> #include <asm/exception.h> #include <asm/system_misc.h> @@ -142,6 +143,14 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) unsigned long irq_stack_ptr; int skip; + pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); + + if (!tsk) + tsk = current; + + if (!try_get_task_stack(tsk)) + return; + /* * Switching between stacks is valid when tracing current and in * non-preemptible context. @@ -151,11 +160,6 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) else irq_stack_ptr = 0; - pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); - - if (!tsk) - tsk = current; - if (tsk == current) { frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_stack_pointer; @@ -212,6 +216,8 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) stack + sizeof(struct pt_regs)); } } + + put_task_stack(tsk); } void show_stack(struct task_struct *tsk, unsigned long *sp) @@ -227,10 +233,9 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) #endif #define S_SMP " SMP" -static int __die(const char *str, int err, struct thread_info *thread, - struct pt_regs *regs) +static int __die(const char *str, int err, struct pt_regs *regs) { - struct task_struct *tsk = thread->task; + struct task_struct *tsk = current; static int die_counter; int ret; @@ -245,7 +250,8 @@ static int __die(const char *str, int err, struct thread_info *thread, print_modules(); __show_regs(regs); pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); + TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), + end_of_stack(tsk)); if (!user_mode(regs)) { dump_mem(KERN_EMERG, "Stack: ", regs->sp, @@ -264,7 +270,6 @@ static DEFINE_RAW_SPINLOCK(die_lock); */ void die(const char *str, struct pt_regs *regs, int err) { - struct thread_info *thread = current_thread_info(); int ret; oops_enter(); @@ -272,9 +277,9 @@ void die(const char *str, struct pt_regs *regs, int err) raw_spin_lock_irq(&die_lock); console_verbose(); bust_spinlocks(1); - ret = __die(str, err, thread, regs); + ret = __die(str, err, regs); - if (regs && kexec_should_crash(thread->task)) + if (regs && kexec_should_crash(current)) crash_kexec(regs); bust_spinlocks(0); @@ -428,55 +433,55 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); } -void cpu_enable_cache_maint_trap(void *__unused) +int cpu_enable_cache_maint_trap(void *__unused) { config_sctlr_el1(SCTLR_EL1_UCI, 0); + return 0; } #define __user_cache_maint(insn, address, res) \ - asm volatile ( \ - "1: " insn ", %1\n" \ - " mov %w0, #0\n" \ - "2:\n" \ - " .pushsection .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %w0, %w2\n" \ - " b 2b\n" \ - " .popsection\n" \ - _ASM_EXTABLE(1b, 3b) \ - : "=r" (res) \ - : "r" (address), "i" (-EFAULT) ) + if (untagged_addr(address) >= user_addr_max()) { \ + res = -EFAULT; \ + } else { \ + uaccess_ttbr0_enable(); \ + asm volatile ( \ + "1: " insn ", %1\n" \ + " mov %w0, #0\n" \ + "2:\n" \ + " .pushsection .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mov %w0, %w2\n" \ + " b 2b\n" \ + " .popsection\n" \ + _ASM_EXTABLE(1b, 3b) \ + : "=r" (res) \ + : "r" (address), "i" (-EFAULT)); \ + uaccess_ttbr0_disable(); \ + } -asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) +static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) { unsigned long address; - int ret; - - /* if this is a write with: Op0=1, Op2=1, Op1=3, CRn=7 */ - if ((esr & 0x01fffc01) == 0x0012dc00) { - int rt = (esr >> 5) & 0x1f; - int crm = (esr >> 1) & 0x0f; + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; + int ret = 0; - address = (rt == 31) ? 0 : regs->regs[rt]; + address = (rt == 31) ? 0 : regs->regs[rt]; - switch (crm) { - case 11: /* DC CVAU, gets promoted */ - __user_cache_maint("dc civac", address, ret); - break; - case 10: /* DC CVAC, gets promoted */ - __user_cache_maint("dc civac", address, ret); - break; - case 14: /* DC CIVAC */ - __user_cache_maint("dc civac", address, ret); - break; - case 5: /* IC IVAU */ - __user_cache_maint("ic ivau", address, ret); - break; - default: - force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); - return; - } - } else { + switch (crm) { + case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */ + __user_cache_maint("dc civac", address, ret); + break; + case ESR_ELx_SYS64_ISS_CRM_DC_CVAC: /* DC CVAC, gets promoted */ + __user_cache_maint("dc civac", address, ret); + break; + case ESR_ELx_SYS64_ISS_CRM_DC_CIVAC: /* DC CIVAC */ + __user_cache_maint("dc civac", address, ret); + break; + case ESR_ELx_SYS64_ISS_CRM_IC_IVAU: /* IC IVAU */ + __user_cache_maint("ic ivau", address, ret); + break; + default: force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); return; } @@ -487,6 +492,48 @@ asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + regs->regs[rt] = arm64_ftr_reg_ctrel0.sys_val; + regs->pc += 4; +} + +struct sys64_hook { + unsigned int esr_mask; + unsigned int esr_val; + void (*handler)(unsigned int esr, struct pt_regs *regs); +}; + +static struct sys64_hook sys64_hooks[] = { + { + .esr_mask = ESR_ELx_SYS64_ISS_EL0_CACHE_OP_MASK, + .esr_val = ESR_ELx_SYS64_ISS_EL0_CACHE_OP_VAL, + .handler = user_cache_maint_handler, + }, + { + /* Trap read access to CTR_EL0 */ + .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, + .esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ, + .handler = ctr_read_handler, + }, + {}, +}; + +asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) +{ + struct sys64_hook *hook; + + for (hook = sys64_hooks; hook->handler; hook++) + if ((hook->esr_mask & esr) == hook->esr_val) { + hook->handler(esr, regs); + return; + } + + force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); +} + long compat_arm_syscall(struct pt_regs *regs); asmlinkage long do_ni_syscall(struct pt_regs *regs) diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 076312b17d4f..a2c2478e7d78 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -18,12 +18,13 @@ * Author: Will Deacon <will.deacon@arm.com> */ -#include <linux/kernel.h> +#include <linux/cache.h> #include <linux/clocksource.h> #include <linux/elf.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/gfp.h> +#include <linux/kernel.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/signal.h> @@ -37,8 +38,7 @@ #include <asm/vdso_datapage.h> extern char vdso_start, vdso_end; -static unsigned long vdso_pages; -static struct page **vdso_pagelist; +static unsigned long vdso_pages __ro_after_init; /* * The vDSO data page. @@ -53,9 +53,9 @@ struct vdso_data *vdso_data = &vdso_data_store.data; /* * Create and map the vectors page for AArch32 tasks. */ -static struct page *vectors_page[1]; +static struct page *vectors_page[1] __ro_after_init; -static int alloc_vectors_page(void) +static int __init alloc_vectors_page(void) { extern char __kuser_helper_start[], __kuser_helper_end[]; extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[]; @@ -88,7 +88,7 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; unsigned long addr = AARCH32_VECTORS_BASE; - static struct vm_special_mapping spec = { + static const struct vm_special_mapping spec = { .name = "[vectors]", .pages = vectors_page, @@ -110,11 +110,19 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) } #endif /* CONFIG_COMPAT */ -static struct vm_special_mapping vdso_spec[2]; +static struct vm_special_mapping vdso_spec[2] __ro_after_init = { + { + .name = "[vvar]", + }, + { + .name = "[vdso]", + }, +}; static int __init vdso_init(void) { int i; + struct page **vdso_pagelist; if (memcmp(&vdso_start, "\177ELF", 4)) { pr_err("vDSO is not a valid ELF object!\n"); @@ -138,16 +146,8 @@ static int __init vdso_init(void) for (i = 0; i < vdso_pages; i++) vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i); - /* Populate the special mapping structures */ - vdso_spec[0] = (struct vm_special_mapping) { - .name = "[vvar]", - .pages = vdso_pagelist, - }; - - vdso_spec[1] = (struct vm_special_mapping) { - .name = "[vdso]", - .pages = &vdso_pagelist[1], - }; + vdso_spec[0].pages = &vdso_pagelist[0]; + vdso_spec[1].pages = &vdso_pagelist[1]; return 0; } @@ -201,7 +201,7 @@ up_fail: */ void update_vsyscall(struct timekeeper *tk) { - u32 use_syscall = strcmp(tk->tkr_mono.clock->name, "arch_sys_counter"); + u32 use_syscall = !tk->tkr_mono.clock->archdata.vdso_direct; ++vdso_data->tb_seq_count; smp_wmb(); diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 659963d40bb4..b8deffa9e1bf 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -122,6 +122,7 @@ SECTIONS ENTRY_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT HYPERVISOR_TEXT @@ -185,6 +186,25 @@ SECTIONS _data = .; _sdata = .; RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) + + /* + * Data written with the MMU off but read with the MMU on requires + * cache lines to be invalidated, discarding up to a Cache Writeback + * Granule (CWG) of data from the cache. Keep the section that + * requires this type of maintenance to be in its own Cache Writeback + * Granule (CWG) area so the cache maintenance operations don't + * interfere with adjacent data. + */ + .mmuoff.data.write : ALIGN(SZ_2K) { + __mmuoff_data_start = .; + *(.mmuoff.data.write) + } + . = ALIGN(SZ_2K); + .mmuoff.data.read : { + *(.mmuoff.data.read) + __mmuoff_data_end = .; + } + PECOFF_EDATA_PADDING _edata = .; @@ -196,6 +216,11 @@ SECTIONS swapper_pg_dir = .; . += SWAPPER_DIR_SIZE; +#ifdef CONFIG_ARM64_SW_TTBR0_PAN + reserved_ttbr0 = .; + . += RESERVED_TTBR0_SIZE; +#endif + _end = .; STABS_DEBUG diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 9c9edc98d271..52cb7ad9b2fd 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -16,9 +16,6 @@ menuconfig VIRTUALIZATION if VIRTUALIZATION -config KVM_ARM_VGIC_V3 - bool - config KVM bool "Kernel-based Virtual Machine (KVM) support" depends on OF @@ -34,7 +31,6 @@ config KVM select KVM_VFIO select HAVE_KVM_EVENTFD select HAVE_KVM_IRQFD - select KVM_ARM_VGIC_V3 select KVM_ARM_PMU if HW_PERF_EVENTS select HAVE_KVM_MSI select HAVE_KVM_IRQCHIP diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 695eb3c7ef41..d50a82a16ff6 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -16,9 +16,10 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/e kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o -kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o +kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o diff --git a/arch/arm64/kvm/emulate.c b/arch/arm64/kvm/emulate.c deleted file mode 100644 index f87d8fbaa48d..000000000000 --- a/arch/arm64/kvm/emulate.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * (not much of an) Emulation layer for 32bit guests. - * - * Copyright (C) 2012,2013 - ARM Ltd - * Author: Marc Zyngier <marc.zyngier@arm.com> - * - * based on arch/arm/kvm/emulate.c - * Copyright (C) 2012 - Virtual Open Systems and Columbia University - * Author: Christoffer Dall <c.dall@virtualopensystems.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/kvm_host.h> -#include <asm/esr.h> -#include <asm/kvm_emulate.h> - -/* - * stolen from arch/arm/kernel/opcodes.c - * - * condition code lookup table - * index into the table is test code: EQ, NE, ... LT, GT, AL, NV - * - * bit position in short is condition code: NZCV - */ -static const unsigned short cc_map[16] = { - 0xF0F0, /* EQ == Z set */ - 0x0F0F, /* NE */ - 0xCCCC, /* CS == C set */ - 0x3333, /* CC */ - 0xFF00, /* MI == N set */ - 0x00FF, /* PL */ - 0xAAAA, /* VS == V set */ - 0x5555, /* VC */ - 0x0C0C, /* HI == C set && Z clear */ - 0xF3F3, /* LS == C clear || Z set */ - 0xAA55, /* GE == (N==V) */ - 0x55AA, /* LT == (N!=V) */ - 0x0A05, /* GT == (!Z && (N==V)) */ - 0xF5FA, /* LE == (Z || (N!=V)) */ - 0xFFFF, /* AL always */ - 0 /* NV */ -}; - -static int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) -{ - u32 esr = kvm_vcpu_get_hsr(vcpu); - - if (esr & ESR_ELx_CV) - return (esr & ESR_ELx_COND_MASK) >> ESR_ELx_COND_SHIFT; - - return -1; -} - -/* - * Check if a trapped instruction should have been executed or not. - */ -bool kvm_condition_valid32(const struct kvm_vcpu *vcpu) -{ - unsigned long cpsr; - u32 cpsr_cond; - int cond; - - /* Top two bits non-zero? Unconditional. */ - if (kvm_vcpu_get_hsr(vcpu) >> 30) - return true; - - /* Is condition field valid? */ - cond = kvm_vcpu_get_condition(vcpu); - if (cond == 0xE) - return true; - - cpsr = *vcpu_cpsr(vcpu); - - if (cond < 0) { - /* This can happen in Thumb mode: examine IT state. */ - unsigned long it; - - it = ((cpsr >> 8) & 0xFC) | ((cpsr >> 25) & 0x3); - - /* it == 0 => unconditional. */ - if (it == 0) - return true; - - /* The cond for this insn works out as the top 4 bits. */ - cond = (it >> 4); - } - - cpsr_cond = cpsr >> 28; - - if (!((cc_map[cond] >> cpsr_cond) & 1)) - return false; - - return true; -} - -/** - * adjust_itstate - adjust ITSTATE when emulating instructions in IT-block - * @vcpu: The VCPU pointer - * - * When exceptions occur while instructions are executed in Thumb IF-THEN - * blocks, the ITSTATE field of the CPSR is not advanced (updated), so we have - * to do this little bit of work manually. The fields map like this: - * - * IT[7:0] -> CPSR[26:25],CPSR[15:10] - */ -static void kvm_adjust_itstate(struct kvm_vcpu *vcpu) -{ - unsigned long itbits, cond; - unsigned long cpsr = *vcpu_cpsr(vcpu); - bool is_arm = !(cpsr & COMPAT_PSR_T_BIT); - - BUG_ON(is_arm && (cpsr & COMPAT_PSR_IT_MASK)); - - if (!(cpsr & COMPAT_PSR_IT_MASK)) - return; - - cond = (cpsr & 0xe000) >> 13; - itbits = (cpsr & 0x1c00) >> (10 - 2); - itbits |= (cpsr & (0x3 << 25)) >> 25; - - /* Perform ITAdvance (see page A2-52 in ARM DDI 0406C) */ - if ((itbits & 0x7) == 0) - itbits = cond = 0; - else - itbits = (itbits << 1) & 0x1f; - - cpsr &= ~COMPAT_PSR_IT_MASK; - cpsr |= cond << 13; - cpsr |= (itbits & 0x1c) << (10 - 2); - cpsr |= (itbits & 0x3) << 25; - *vcpu_cpsr(vcpu) = cpsr; -} - -/** - * kvm_skip_instr - skip a trapped instruction and proceed to the next - * @vcpu: The vcpu pointer - */ -void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr) -{ - bool is_thumb; - - is_thumb = !!(*vcpu_cpsr(vcpu) & COMPAT_PSR_T_BIT); - if (is_thumb && !is_wide_instr) - *vcpu_pc(vcpu) += 2; - else - *vcpu_pc(vcpu) += 4; - kvm_adjust_itstate(vcpu); -} diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 3f9e15722473..b37446a8ffdb 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -26,7 +26,7 @@ #include <linux/vmalloc.h> #include <linux/fs.h> #include <asm/cputype.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/kvm.h> #include <asm/kvm_emulate.h> #include <asm/kvm_coproc.h> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index fa96fe2bd469..1bfe30dfbfe7 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -57,6 +57,16 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } +/* + * Guest access to FP/ASIMD registers are routed to this handler only + * when the system doesn't support FP/ASIMD. + */ +static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + kvm_inject_undefined(vcpu); + return 1; +} + /** * kvm_handle_wfx - handle a wait-for-interrupts or wait-for-event * instruction executed by a guest @@ -144,6 +154,7 @@ static exit_handle_fn arm_exit_handlers[] = { [ESR_ELx_EC_BREAKPT_LOW]= kvm_handle_guest_debug, [ESR_ELx_EC_BKPT32] = kvm_handle_guest_debug, [ESR_ELx_EC_BRK64] = kvm_handle_guest_debug, + [ESR_ELx_EC_FP_ASIMD] = handle_no_fpsimd, }; static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) @@ -170,9 +181,32 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, { exit_handle_fn exit_handler; + if (ARM_SERROR_PENDING(exception_index)) { + u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu)); + + /* + * HVC/SMC already have an adjusted PC, which we need + * to correct in order to return to after having + * injected the SError. + */ + if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 || + hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) { + u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2; + *vcpu_pc(vcpu) -= adj; + } + + kvm_inject_vabt(vcpu); + return 1; + } + + exception_index = ARM_EXCEPTION_CODE(exception_index); + switch (exception_index) { case ARM_EXCEPTION_IRQ: return 1; + case ARM_EXCEPTION_EL1_SERROR: + kvm_inject_vabt(vcpu); + return 1; case ARM_EXCEPTION_TRAP: /* * See ARM ARM B1.14.1: "Hyp traps on instructions diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S index 7ce931565151..2726635dceba 100644 --- a/arch/arm64/kvm/hyp.S +++ b/arch/arm64/kvm/hyp.S @@ -46,10 +46,6 @@ alternative_if_not ARM64_HAS_VIRT_HOST_EXTN hvc #0 ldr lr, [sp], #16 ret -alternative_else +alternative_else_nop_endif b __vhe_hyp_call - nop - nop - nop -alternative_endif ENDPROC(__kvm_call_hyp) diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile index 0c85febcc1eb..aaf42ae8d8c3 100644 --- a/arch/arm64/kvm/hyp/Makefile +++ b/arch/arm64/kvm/hyp/Makefile @@ -5,9 +5,9 @@ KVM=../../../../virt/kvm obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o +obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o -obj-$(CONFIG_KVM_ARM_HOST) += vgic-v3-sr.o obj-$(CONFIG_KVM_ARM_HOST) += sysreg-sr.o obj-$(CONFIG_KVM_ARM_HOST) += debug-sr.o obj-$(CONFIG_KVM_ARM_HOST) += entry.o diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c index 33342a776ec7..4ba5c9095d03 100644 --- a/arch/arm64/kvm/hyp/debug-sr.c +++ b/arch/arm64/kvm/hyp/debug-sr.c @@ -131,9 +131,7 @@ void __hyp_text __debug_cond_restore_host_state(struct kvm_vcpu *vcpu) vcpu->arch.debug_flags &= ~KVM_ARM64_DEBUG_DIRTY; } -static u32 __hyp_text __debug_read_mdcr_el2(void) +u32 __hyp_text __kvm_get_mdcr_el2(void) { return read_sysreg(mdcr_el2); } - -__alias(__debug_read_mdcr_el2) u32 __kvm_get_mdcr_el2(void); diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index ce9e5e5f28cf..12ee62d6d410 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S @@ -55,79 +55,111 @@ */ ENTRY(__guest_enter) // x0: vcpu - // x1: host/guest context - // x2-x18: clobbered by macros + // x1: host context + // x2-x17: clobbered by macros + // x18: guest context // Store the host regs save_callee_saved_regs x1 - // Preserve vcpu & host_ctxt for use at exit time - stp x0, x1, [sp, #-16]! + // Store the host_ctxt for use at exit time + str x1, [sp, #-16]! - add x1, x0, #VCPU_CONTEXT + add x18, x0, #VCPU_CONTEXT - // Prepare x0-x1 for later restore by pushing them onto the stack - ldp x2, x3, [x1, #CPU_XREG_OFFSET(0)] - stp x2, x3, [sp, #-16]! + // Restore guest regs x0-x17 + ldp x0, x1, [x18, #CPU_XREG_OFFSET(0)] + ldp x2, x3, [x18, #CPU_XREG_OFFSET(2)] + ldp x4, x5, [x18, #CPU_XREG_OFFSET(4)] + ldp x6, x7, [x18, #CPU_XREG_OFFSET(6)] + ldp x8, x9, [x18, #CPU_XREG_OFFSET(8)] + ldp x10, x11, [x18, #CPU_XREG_OFFSET(10)] + ldp x12, x13, [x18, #CPU_XREG_OFFSET(12)] + ldp x14, x15, [x18, #CPU_XREG_OFFSET(14)] + ldp x16, x17, [x18, #CPU_XREG_OFFSET(16)] - // x2-x18 - ldp x2, x3, [x1, #CPU_XREG_OFFSET(2)] - ldp x4, x5, [x1, #CPU_XREG_OFFSET(4)] - ldp x6, x7, [x1, #CPU_XREG_OFFSET(6)] - ldp x8, x9, [x1, #CPU_XREG_OFFSET(8)] - ldp x10, x11, [x1, #CPU_XREG_OFFSET(10)] - ldp x12, x13, [x1, #CPU_XREG_OFFSET(12)] - ldp x14, x15, [x1, #CPU_XREG_OFFSET(14)] - ldp x16, x17, [x1, #CPU_XREG_OFFSET(16)] - ldr x18, [x1, #CPU_XREG_OFFSET(18)] - - // x19-x29, lr - restore_callee_saved_regs x1 - - // Last bits of the 64bit state - ldp x0, x1, [sp], #16 + // Restore guest regs x19-x29, lr + restore_callee_saved_regs x18 + + // Restore guest reg x18 + ldr x18, [x18, #CPU_XREG_OFFSET(18)] // Do not touch any register after this! eret ENDPROC(__guest_enter) ENTRY(__guest_exit) - // x0: vcpu - // x1: return code - // x2-x3: free - // x4-x29,lr: vcpu regs - // vcpu x0-x3 on the stack + // x0: return code + // x1: vcpu + // x2-x29,lr: vcpu regs + // vcpu x0-x1 on the stack - add x2, x0, #VCPU_CONTEXT + add x1, x1, #VCPU_CONTEXT - stp x4, x5, [x2, #CPU_XREG_OFFSET(4)] - stp x6, x7, [x2, #CPU_XREG_OFFSET(6)] - stp x8, x9, [x2, #CPU_XREG_OFFSET(8)] - stp x10, x11, [x2, #CPU_XREG_OFFSET(10)] - stp x12, x13, [x2, #CPU_XREG_OFFSET(12)] - stp x14, x15, [x2, #CPU_XREG_OFFSET(14)] - stp x16, x17, [x2, #CPU_XREG_OFFSET(16)] - str x18, [x2, #CPU_XREG_OFFSET(18)] + ALTERNATIVE(nop, SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN) - ldp x6, x7, [sp], #16 // x2, x3 - ldp x4, x5, [sp], #16 // x0, x1 + // Store the guest regs x2 and x3 + stp x2, x3, [x1, #CPU_XREG_OFFSET(2)] - stp x4, x5, [x2, #CPU_XREG_OFFSET(0)] - stp x6, x7, [x2, #CPU_XREG_OFFSET(2)] + // Retrieve the guest regs x0-x1 from the stack + ldp x2, x3, [sp], #16 // x0, x1 + + // Store the guest regs x0-x1 and x4-x18 + stp x2, x3, [x1, #CPU_XREG_OFFSET(0)] + stp x4, x5, [x1, #CPU_XREG_OFFSET(4)] + stp x6, x7, [x1, #CPU_XREG_OFFSET(6)] + stp x8, x9, [x1, #CPU_XREG_OFFSET(8)] + stp x10, x11, [x1, #CPU_XREG_OFFSET(10)] + stp x12, x13, [x1, #CPU_XREG_OFFSET(12)] + stp x14, x15, [x1, #CPU_XREG_OFFSET(14)] + stp x16, x17, [x1, #CPU_XREG_OFFSET(16)] + str x18, [x1, #CPU_XREG_OFFSET(18)] + + // Store the guest regs x19-x29, lr + save_callee_saved_regs x1 - save_callee_saved_regs x2 + // Restore the host_ctxt from the stack + ldr x2, [sp], #16 - // Restore vcpu & host_ctxt from the stack - // (preserving return code in x1) - ldp x0, x2, [sp], #16 // Now restore the host regs restore_callee_saved_regs x2 - mov x0, x1 - ret + // If we have a pending asynchronous abort, now is the + // time to find out. From your VAXorcist book, page 666: + // "Threaten me not, oh Evil one! For I speak with + // the power of DEC, and I command thee to show thyself!" + mrs x2, elr_el2 + mrs x3, esr_el2 + mrs x4, spsr_el2 + mov x5, x0 + + dsb sy // Synchronize against in-flight ld/st + msr daifclr, #4 // Unmask aborts + + // This is our single instruction exception window. A pending + // SError is guaranteed to occur at the earliest when we unmask + // it, and at the latest just after the ISB. + .global abort_guest_exit_start +abort_guest_exit_start: + + isb + + .global abort_guest_exit_end +abort_guest_exit_end: + + // If the exception took place, restore the EL1 exception + // context so that we can report some information. + // Merge the exception code with the SError pending bit. + tbz x0, #ARM_EXIT_WITH_SERROR_BIT, 1f + msr elr_el2, x2 + msr esr_el2, x3 + msr spsr_el2, x4 + orr x0, x0, x5 +1: ret ENDPROC(__guest_exit) ENTRY(__fpsimd_guest_restore) + stp x2, x3, [sp, #-16]! stp x4, lr, [sp, #-16]! alternative_if_not ARM64_HAS_VIRT_HOST_EXTN diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index f6d9694ae3b1..5e9052f087f2 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -27,16 +27,6 @@ .text .pushsection .hyp.text, "ax" -.macro save_x0_to_x3 - stp x0, x1, [sp, #-16]! - stp x2, x3, [sp, #-16]! -.endm - -.macro restore_x0_to_x3 - ldp x2, x3, [sp], #16 - ldp x0, x1, [sp], #16 -.endm - .macro do_el2_call /* * Shuffle the parameters before calling the function @@ -79,23 +69,23 @@ ENTRY(__kvm_hyp_teardown) ENDPROC(__kvm_hyp_teardown) el1_sync: // Guest trapped into EL2 - save_x0_to_x3 + stp x0, x1, [sp, #-16]! alternative_if_not ARM64_HAS_VIRT_HOST_EXTN mrs x1, esr_el2 alternative_else mrs x1, esr_el1 alternative_endif - lsr x2, x1, #ESR_ELx_EC_SHIFT + lsr x0, x1, #ESR_ELx_EC_SHIFT - cmp x2, #ESR_ELx_EC_HVC64 + cmp x0, #ESR_ELx_EC_HVC64 b.ne el1_trap - mrs x3, vttbr_el2 // If vttbr is valid, the 64bit guest - cbnz x3, el1_trap // called HVC + mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest + cbnz x1, el1_trap // called HVC /* Here, we're pretty sure the host called HVC. */ - restore_x0_to_x3 + ldp x0, x1, [sp], #16 cmp x0, #HVC_GET_VECTORS b.ne 1f @@ -113,24 +103,58 @@ alternative_endif el1_trap: /* - * x1: ESR - * x2: ESR_EC + * x0: ESR_EC */ - /* Guest accessed VFP/SIMD registers, save host, restore Guest */ - cmp x2, #ESR_ELx_EC_FP_ASIMD + /* + * We trap the first access to the FP/SIMD to save the host context + * and restore the guest context lazily. + * If FP/SIMD is not implemented, handle the trap and inject an + * undefined instruction exception to the guest. + */ +alternative_if_not ARM64_HAS_NO_FPSIMD + cmp x0, #ESR_ELx_EC_FP_ASIMD b.eq __fpsimd_guest_restore +alternative_else_nop_endif - mrs x0, tpidr_el2 - mov x1, #ARM_EXCEPTION_TRAP + mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_TRAP b __guest_exit el1_irq: - save_x0_to_x3 - mrs x0, tpidr_el2 - mov x1, #ARM_EXCEPTION_IRQ + stp x0, x1, [sp, #-16]! + mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_IRQ + b __guest_exit + +el1_error: + stp x0, x1, [sp, #-16]! + mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_EL1_SERROR b __guest_exit +el2_error: + /* + * Only two possibilities: + * 1) Either we come from the exit path, having just unmasked + * PSTATE.A: change the return code to an EL2 fault, and + * carry on, as we're already in a sane state to handle it. + * 2) Or we come from anywhere else, and that's a bug: we panic. + * + * For (1), x0 contains the original return code and x1 doesn't + * contain anything meaningful at that stage. We can reuse them + * as temp registers. + * For (2), who cares? + */ + mrs x0, elr_el2 + adr x1, abort_guest_exit_start + cmp x0, x1 + adr x1, abort_guest_exit_end + ccmp x0, x1, #4, ne + b.ne __hyp_panic + mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT) + eret + ENTRY(__hyp_do_panic) mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ PSR_MODE_EL1h) @@ -155,11 +179,9 @@ ENDPROC(\label) invalid_vector el2h_sync_invalid invalid_vector el2h_irq_invalid invalid_vector el2h_fiq_invalid - invalid_vector el2h_error_invalid invalid_vector el1_sync_invalid invalid_vector el1_irq_invalid invalid_vector el1_fiq_invalid - invalid_vector el1_error_invalid .ltorg @@ -174,15 +196,15 @@ ENTRY(__kvm_hyp_vector) ventry el2h_sync_invalid // Synchronous EL2h ventry el2h_irq_invalid // IRQ EL2h ventry el2h_fiq_invalid // FIQ EL2h - ventry el2h_error_invalid // Error EL2h + ventry el2_error // Error EL2h ventry el1_sync // Synchronous 64-bit EL1 ventry el1_irq // IRQ 64-bit EL1 ventry el1_fiq_invalid // FIQ 64-bit EL1 - ventry el1_error_invalid // Error 64-bit EL1 + ventry el1_error // Error 64-bit EL1 ventry el1_sync // Synchronous 32-bit EL1 ventry el1_irq // IRQ 32-bit EL1 ventry el1_fiq_invalid // FIQ 32-bit EL1 - ventry el1_error_invalid // Error 32-bit EL1 + ventry el1_error // Error 32-bit EL1 ENDPROC(__kvm_hyp_vector) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 5a84b4562603..75e83dd40d43 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -16,8 +16,12 @@ */ #include <linux/types.h> +#include <linux/jump_label.h> + #include <asm/kvm_asm.h> +#include <asm/kvm_emulate.h> #include <asm/kvm_hyp.h> +#include <asm/fpsimd.h> static bool __hyp_text __fpsimd_enabled_nvhe(void) { @@ -73,16 +77,24 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) * traps are only taken to EL2 if the operation would not otherwise * trap to EL1. Therefore, always make sure that for 32-bit guests, * we set FPEXC.EN to prevent traps to EL1, when setting the TFP bit. + * If FP/ASIMD is not implemented, FPEXC is UNDEFINED and any access to + * it will cause an exception. */ val = vcpu->arch.hcr_el2; - if (!(val & HCR_RW)) { + if (!(val & HCR_RW) && system_supports_fpsimd()) { write_sysreg(1 << 30, fpexc32_el2); isb(); } write_sysreg(val, hcr_el2); /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */ write_sysreg(1 << 15, hstr_el2); - /* Make sure we trap PMU access from EL0 to EL2 */ + /* + * Make sure we trap PMU access from EL0 to EL2. Also sanitize + * PMSELR_EL0 to make sure it never contains the cycle + * counter, which could make a PMXEVCNTR_EL0 access UNDEF at + * EL1 instead of being trapped to EL2. + */ + write_sysreg(0, pmselr_el0); write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); __activate_traps_arch()(); @@ -109,6 +121,15 @@ static hyp_alternate_select(__deactivate_traps_arch, static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) { + /* + * If we pended a virtual abort, preserve it until it gets + * cleared. See D1.14.3 (Virtual Interrupts) for details, but + * the crucial bit is "On taking a vSError interrupt, + * HCR_EL2.VSE is cleared to 0." + */ + if (vcpu->arch.hcr_el2 & HCR_VSE) + vcpu->arch.hcr_el2 = read_sysreg(hcr_el2); + __deactivate_traps_arch()(); write_sysreg(0, hstr_el2); write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2); @@ -126,17 +147,13 @@ static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu) write_sysreg(0, vttbr_el2); } -static hyp_alternate_select(__vgic_call_save_state, - __vgic_v2_save_state, __vgic_v3_save_state, - ARM64_HAS_SYSREG_GIC_CPUIF); - -static hyp_alternate_select(__vgic_call_restore_state, - __vgic_v2_restore_state, __vgic_v3_restore_state, - ARM64_HAS_SYSREG_GIC_CPUIF); - static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu) { - __vgic_call_save_state()(vcpu); + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) + __vgic_v3_save_state(vcpu); + else + __vgic_v2_save_state(vcpu); + write_sysreg(read_sysreg(hcr_el2) & ~HCR_INT_OVERRIDE, hcr_el2); } @@ -149,7 +166,10 @@ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu) val |= vcpu->arch.irq_lines; write_sysreg(val, hcr_el2); - __vgic_call_restore_state()(vcpu); + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) + __vgic_v3_restore_state(vcpu); + else + __vgic_v2_restore_state(vcpu); } static bool __hyp_text __true_value(void) @@ -232,7 +252,22 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) return true; } -static int __hyp_text __guest_run(struct kvm_vcpu *vcpu) +static void __hyp_text __skip_instr(struct kvm_vcpu *vcpu) +{ + *vcpu_pc(vcpu) = read_sysreg_el2(elr); + + if (vcpu_mode_is_32bit(vcpu)) { + vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(spsr); + kvm_skip_instr32(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + write_sysreg_el2(vcpu->arch.ctxt.gp_regs.regs.pstate, spsr); + } else { + *vcpu_pc(vcpu) += 4; + } + + write_sysreg_el2(*vcpu_pc(vcpu), elr); +} + +int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; struct kvm_cpu_context *guest_ctxt; @@ -267,9 +302,43 @@ again: exit_code = __guest_enter(vcpu, host_ctxt); /* And we're baaack! */ + /* + * We're using the raw exception code in order to only process + * the trap if no SError is pending. We will come back to the + * same PC once the SError has been injected, and replay the + * trapping instruction. + */ if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu)) goto again; + if (static_branch_unlikely(&vgic_v2_cpuif_trap) && + exit_code == ARM_EXCEPTION_TRAP) { + bool valid; + + valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW && + kvm_vcpu_trap_get_fault_type(vcpu) == FSC_FAULT && + kvm_vcpu_dabt_isvalid(vcpu) && + !kvm_vcpu_dabt_isextabt(vcpu) && + !kvm_vcpu_dabt_iss1tw(vcpu); + + if (valid) { + int ret = __vgic_v2_perform_cpuif_access(vcpu); + + if (ret == 1) { + __skip_instr(vcpu); + goto again; + } + + if (ret == -1) { + /* Promote an illegal access to an SError */ + __skip_instr(vcpu); + exit_code = ARM_EXCEPTION_EL1_SERROR; + } + + /* 0 falls through to be handler out of EL2 */ + } + } + fp_enabled = __fpsimd_enabled(); __sysreg_save_guest_state(guest_ctxt); @@ -293,8 +362,6 @@ again: return exit_code; } -__alias(__guest_run) int __kvm_vcpu_run(struct kvm_vcpu *vcpu); - static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par) diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c index be8177cdd3bf..88e2f2b938f0 100644 --- a/arch/arm64/kvm/hyp/tlb.c +++ b/arch/arm64/kvm/hyp/tlb.c @@ -17,7 +17,7 @@ #include <asm/kvm_hyp.h> -static void __hyp_text __tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) +void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) { dsb(ishst); @@ -48,10 +48,7 @@ static void __hyp_text __tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) write_sysreg(0, vttbr_el2); } -__alias(__tlb_flush_vmid_ipa) void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, - phys_addr_t ipa); - -static void __hyp_text __tlb_flush_vmid(struct kvm *kvm) +void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm) { dsb(ishst); @@ -67,14 +64,25 @@ static void __hyp_text __tlb_flush_vmid(struct kvm *kvm) write_sysreg(0, vttbr_el2); } -__alias(__tlb_flush_vmid) void __kvm_tlb_flush_vmid(struct kvm *kvm); +void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm); + + /* Switch to requested VMID */ + write_sysreg(kvm->arch.vttbr, vttbr_el2); + isb(); + + asm volatile("tlbi vmalle1" : : ); + dsb(nsh); + isb(); + + write_sysreg(0, vttbr_el2); +} -static void __hyp_text __tlb_flush_vm_context(void) +void __hyp_text __kvm_flush_vm_context(void) { dsb(ishst); asm volatile("tlbi alle1is \n" "ic ialluis ": : ); dsb(ish); } - -__alias(__tlb_flush_vm_context) void __kvm_flush_vm_context(void); diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c deleted file mode 100644 index 5f8f80b4a224..000000000000 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2012-2015 - 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/compiler.h> -#include <linux/irqchip/arm-gic-v3.h> -#include <linux/kvm_host.h> - -#include <asm/kvm_hyp.h> - -#define vtr_to_max_lr_idx(v) ((v) & 0xf) -#define vtr_to_nr_pri_bits(v) (((u32)(v) >> 29) + 1) - -#define read_gicreg(r) \ - ({ \ - u64 reg; \ - asm volatile("mrs_s %0, " __stringify(r) : "=r" (reg)); \ - reg; \ - }) - -#define write_gicreg(v,r) \ - do { \ - u64 __val = (v); \ - asm volatile("msr_s " __stringify(r) ", %0" : : "r" (__val));\ - } while (0) - -static u64 __hyp_text __gic_v3_get_lr(unsigned int lr) -{ - switch (lr & 0xf) { - case 0: - return read_gicreg(ICH_LR0_EL2); - case 1: - return read_gicreg(ICH_LR1_EL2); - case 2: - return read_gicreg(ICH_LR2_EL2); - case 3: - return read_gicreg(ICH_LR3_EL2); - case 4: - return read_gicreg(ICH_LR4_EL2); - case 5: - return read_gicreg(ICH_LR5_EL2); - case 6: - return read_gicreg(ICH_LR6_EL2); - case 7: - return read_gicreg(ICH_LR7_EL2); - case 8: - return read_gicreg(ICH_LR8_EL2); - case 9: - return read_gicreg(ICH_LR9_EL2); - case 10: - return read_gicreg(ICH_LR10_EL2); - case 11: - return read_gicreg(ICH_LR11_EL2); - case 12: - return read_gicreg(ICH_LR12_EL2); - case 13: - return read_gicreg(ICH_LR13_EL2); - case 14: - return read_gicreg(ICH_LR14_EL2); - case 15: - return read_gicreg(ICH_LR15_EL2); - } - - unreachable(); -} - -static void __hyp_text __gic_v3_set_lr(u64 val, int lr) -{ - switch (lr & 0xf) { - case 0: - write_gicreg(val, ICH_LR0_EL2); - break; - case 1: - write_gicreg(val, ICH_LR1_EL2); - break; - case 2: - write_gicreg(val, ICH_LR2_EL2); - break; - case 3: - write_gicreg(val, ICH_LR3_EL2); - break; - case 4: - write_gicreg(val, ICH_LR4_EL2); - break; - case 5: - write_gicreg(val, ICH_LR5_EL2); - break; - case 6: - write_gicreg(val, ICH_LR6_EL2); - break; - case 7: - write_gicreg(val, ICH_LR7_EL2); - break; - case 8: - write_gicreg(val, ICH_LR8_EL2); - break; - case 9: - write_gicreg(val, ICH_LR9_EL2); - break; - case 10: - write_gicreg(val, ICH_LR10_EL2); - break; - case 11: - write_gicreg(val, ICH_LR11_EL2); - break; - case 12: - write_gicreg(val, ICH_LR12_EL2); - break; - case 13: - write_gicreg(val, ICH_LR13_EL2); - break; - case 14: - write_gicreg(val, ICH_LR14_EL2); - break; - case 15: - write_gicreg(val, ICH_LR15_EL2); - break; - } -} - -static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu, int nr_lr) -{ - struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; - int i; - bool expect_mi; - - expect_mi = !!(cpu_if->vgic_hcr & ICH_HCR_UIE); - - for (i = 0; i < nr_lr; i++) { - if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i))) - continue; - - expect_mi |= (!(cpu_if->vgic_lr[i] & ICH_LR_HW) && - (cpu_if->vgic_lr[i] & ICH_LR_EOI)); - } - - if (expect_mi) { - cpu_if->vgic_misr = read_gicreg(ICH_MISR_EL2); - - if (cpu_if->vgic_misr & ICH_MISR_EOI) - cpu_if->vgic_eisr = read_gicreg(ICH_EISR_EL2); - else - cpu_if->vgic_eisr = 0; - } else { - cpu_if->vgic_misr = 0; - cpu_if->vgic_eisr = 0; - } -} - -void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu) -{ - struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; - u64 val; - - /* - * Make sure stores to the GIC via the memory mapped interface - * are now visible to the system register interface. - */ - if (!cpu_if->vgic_sre) - dsb(st); - - cpu_if->vgic_vmcr = read_gicreg(ICH_VMCR_EL2); - - if (vcpu->arch.vgic_cpu.live_lrs) { - int i; - u32 max_lr_idx, nr_pri_bits; - - cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2); - - write_gicreg(0, ICH_HCR_EL2); - val = read_gicreg(ICH_VTR_EL2); - max_lr_idx = vtr_to_max_lr_idx(val); - nr_pri_bits = vtr_to_nr_pri_bits(val); - - save_maint_int_state(vcpu, max_lr_idx + 1); - - for (i = 0; i <= max_lr_idx; i++) { - if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i))) - continue; - - if (cpu_if->vgic_elrsr & (1 << i)) - cpu_if->vgic_lr[i] &= ~ICH_LR_STATE; - else - cpu_if->vgic_lr[i] = __gic_v3_get_lr(i); - - __gic_v3_set_lr(0, i); - } - - switch (nr_pri_bits) { - case 7: - cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2); - cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2); - case 6: - cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2); - default: - cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2); - } - - switch (nr_pri_bits) { - case 7: - cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2); - cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2); - case 6: - cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2); - default: - cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2); - } - - vcpu->arch.vgic_cpu.live_lrs = 0; - } else { - cpu_if->vgic_misr = 0; - cpu_if->vgic_eisr = 0; - cpu_if->vgic_elrsr = 0xffff; - cpu_if->vgic_ap0r[0] = 0; - cpu_if->vgic_ap0r[1] = 0; - cpu_if->vgic_ap0r[2] = 0; - cpu_if->vgic_ap0r[3] = 0; - cpu_if->vgic_ap1r[0] = 0; - cpu_if->vgic_ap1r[1] = 0; - cpu_if->vgic_ap1r[2] = 0; - cpu_if->vgic_ap1r[3] = 0; - } - - val = read_gicreg(ICC_SRE_EL2); - write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2); - - if (!cpu_if->vgic_sre) { - /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */ - isb(); - write_gicreg(1, ICC_SRE_EL1); - } -} - -void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu) -{ - struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; - u64 val; - u32 max_lr_idx, nr_pri_bits; - u16 live_lrs = 0; - int i; - - /* - * VFIQEn is RES1 if ICC_SRE_EL1.SRE is 1. This causes a - * Group0 interrupt (as generated in GICv2 mode) to be - * delivered as a FIQ to the guest, with potentially fatal - * consequences. So we must make sure that ICC_SRE_EL1 has - * been actually programmed with the value we want before - * starting to mess with the rest of the GIC. - */ - if (!cpu_if->vgic_sre) { - write_gicreg(0, ICC_SRE_EL1); - isb(); - } - - val = read_gicreg(ICH_VTR_EL2); - max_lr_idx = vtr_to_max_lr_idx(val); - nr_pri_bits = vtr_to_nr_pri_bits(val); - - for (i = 0; i <= max_lr_idx; i++) { - if (cpu_if->vgic_lr[i] & ICH_LR_STATE) - live_lrs |= (1 << i); - } - - write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2); - - if (live_lrs) { - write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2); - - switch (nr_pri_bits) { - case 7: - write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2); - write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2); - case 6: - write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2); - default: - write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2); - } - - switch (nr_pri_bits) { - case 7: - write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2); - write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2); - case 6: - write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2); - default: - write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2); - } - - for (i = 0; i <= max_lr_idx; i++) { - if (!(live_lrs & (1 << i))) - continue; - - __gic_v3_set_lr(cpu_if->vgic_lr[i], i); - } - } - - /* - * Ensures that the above will have reached the - * (re)distributors. This ensure the guest will read the - * correct values from the memory-mapped interface. - */ - if (!cpu_if->vgic_sre) { - isb(); - dsb(sy); - } - vcpu->arch.vgic_cpu.live_lrs = live_lrs; - - /* - * Prevent the guest from touching the GIC system registers if - * SRE isn't enabled for GICv3 emulation. - */ - write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE, - ICC_SRE_EL2); -} - -void __hyp_text __vgic_v3_init_lrs(void) -{ - int max_lr_idx = vtr_to_max_lr_idx(read_gicreg(ICH_VTR_EL2)); - int i; - - for (i = 0; i <= max_lr_idx; i++) - __gic_v3_set_lr(0, i); -} - -static u64 __hyp_text __vgic_v3_read_ich_vtr_el2(void) -{ - return read_gicreg(ICH_VTR_EL2); -} - -__alias(__vgic_v3_read_ich_vtr_el2) u64 __vgic_v3_get_ich_vtr_el2(void); diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index 898c0e6aedd4..da6a8cfa54a0 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -231,3 +231,15 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) else inject_undef64(vcpu); } + +/** + * kvm_inject_vabt - inject an async abort / SError into the guest + * @vcpu: The VCPU to receive the exception + * + * It is assumed that this code is called from the VCPU thread and that the + * VCPU therefore is not currently executing guest code. + */ +void kvm_inject_vabt(struct kvm_vcpu *vcpu) +{ + vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) | HCR_VSE); +} diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 5bc460884639..e95d4f68bf54 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -86,12 +86,6 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_VCPU_ATTRIBUTES: r = 1; break; - case KVM_CAP_MSI_DEVID: - if (!kvm) - r = -EINVAL; - else - r = kvm->arch.vgic.msis_require_devid; - break; default: r = 0; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index e51367d159d0..87e7e6608cd8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -36,6 +36,7 @@ #include <asm/kvm_host.h> #include <asm/kvm_mmu.h> #include <asm/perf_event.h> +#include <asm/sysreg.h> #include <trace/events/kvm.h> @@ -67,11 +68,9 @@ static u32 get_ccsidr(u32 csselr) /* Make sure noone else changes CSSELR during this! */ local_irq_disable(); - /* Put value into CSSELR */ - asm volatile("msr csselr_el1, %x0" : : "r" (csselr)); + write_sysreg(csselr, csselr_el1); isb(); - /* Read result out of CCSIDR */ - asm volatile("mrs %0, ccsidr_el1" : "=r" (ccsidr)); + ccsidr = read_sysreg(ccsidr_el1); local_irq_enable(); return ccsidr; @@ -174,9 +173,7 @@ static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu, if (p->is_write) { return ignore_write(vcpu, p); } else { - u32 val; - asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val)); - p->regval = val; + p->regval = read_sysreg(dbgauthstatus_el1); return true; } } @@ -429,10 +426,7 @@ static void reset_wcr(struct kvm_vcpu *vcpu, static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - u64 amair; - - asm volatile("mrs %0, amair_el1\n" : "=r" (amair)); - vcpu_sys_reg(vcpu, AMAIR_EL1) = amair; + vcpu_sys_reg(vcpu, AMAIR_EL1) = read_sysreg(amair_el1); } static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) @@ -456,8 +450,9 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 pmcr, val; - asm volatile("mrs %0, pmcr_el0\n" : "=r" (pmcr)); - /* Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) is reset to UNKNOWN + pmcr = read_sysreg(pmcr_el0); + /* + * Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN * except PMCR.E resetting to zero. */ val = ((pmcr & ~ARMV8_PMU_PMCR_MASK) @@ -557,9 +552,9 @@ static bool access_pmceid(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return false; if (!(p->Op2 & 1)) - asm volatile("mrs %0, pmceid0_el0\n" : "=r" (pmceid)); + pmceid = read_sysreg(pmceid0_el0); else - asm volatile("mrs %0, pmceid1_el0\n" : "=r" (pmceid)); + pmceid = read_sysreg(pmceid1_el0); p->regval = pmceid; @@ -602,8 +597,14 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu, idx = ARMV8_PMU_CYCLE_IDX; } else { - BUG(); + return false; } + } else if (r->CRn == 0 && r->CRm == 9) { + /* PMCCNTR */ + if (pmu_access_event_counter_el0_disabled(vcpu)) + return false; + + idx = ARMV8_PMU_CYCLE_IDX; } else if (r->CRn == 14 && (r->CRm & 12) == 8) { /* PMEVCNTRn_EL0 */ if (pmu_access_event_counter_el0_disabled(vcpu)) @@ -611,7 +612,7 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu, idx = ((r->CRm & 3) << 3) | (r->Op2 & 7); } else { - BUG(); + return false; } if (!pmu_counter_idx_valid(vcpu, idx)) @@ -1833,11 +1834,7 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu, static void get_##reg(struct kvm_vcpu *v, \ const struct sys_reg_desc *r) \ { \ - u64 val; \ - \ - asm volatile("mrs %0, " __stringify(reg) "\n" \ - : "=r" (val)); \ - ((struct sys_reg_desc *)r)->val = val; \ + ((struct sys_reg_desc *)r)->val = read_sysreg(reg); \ } FUNCTION_INVARIANT(midr_el1) diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c b/arch/arm64/kvm/sys_regs_generic_v8.c index ed90578fa120..46af7186bca6 100644 --- a/arch/arm64/kvm/sys_regs_generic_v8.c +++ b/arch/arm64/kvm/sys_regs_generic_v8.c @@ -26,6 +26,7 @@ #include <asm/kvm_host.h> #include <asm/kvm_emulate.h> #include <asm/kvm_coproc.h> +#include <asm/sysreg.h> #include <linux/init.h> #include "sys_regs.h" @@ -43,10 +44,7 @@ static bool access_actlr(struct kvm_vcpu *vcpu, static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - u64 actlr; - - asm volatile("mrs %0, actlr_el1\n" : "=r" (actlr)); - vcpu_sys_reg(vcpu, ACTLR_EL1) = actlr; + vcpu_sys_reg(vcpu, ACTLR_EL1) = read_sysreg(actlr_el1); } /* diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S index 5d1cad3ce6d6..e88fb99c1561 100644 --- a/arch/arm64/lib/clear_user.S +++ b/arch/arm64/lib/clear_user.S @@ -17,10 +17,7 @@ */ #include <linux/linkage.h> -#include <asm/alternative.h> -#include <asm/assembler.h> -#include <asm/cpufeature.h> -#include <asm/sysreg.h> +#include <asm/asm-uaccess.h> .text @@ -33,8 +30,7 @@ * Alignment fixed up by hardware. */ ENTRY(__clear_user) -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_enable_not_uao x2, x3 mov x2, x1 // save the size for fixup return subs x1, x1, #8 b.mi 2f @@ -54,8 +50,7 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2 b.mi 5f uao_user_alternative 9f, strb, sttrb, wzr, x0, 0 5: mov x0, #0 -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_disable_not_uao x2 ret ENDPROC(__clear_user) diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S index 0b90497d4424..4b5d826895ff 100644 --- a/arch/arm64/lib/copy_from_user.S +++ b/arch/arm64/lib/copy_from_user.S @@ -16,11 +16,8 @@ #include <linux/linkage.h> -#include <asm/alternative.h> -#include <asm/assembler.h> #include <asm/cache.h> -#include <asm/cpufeature.h> -#include <asm/sysreg.h> +#include <asm/asm-uaccess.h> /* * Copy from user space to a kernel buffer (alignment handled by the hardware) @@ -67,23 +64,16 @@ end .req x5 ENTRY(__arch_copy_from_user) -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_enable_not_uao x3, x4 add end, x0, x2 #include "copy_template.S" -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_disable_not_uao x3 mov x0, #0 // Nothing to copy ret ENDPROC(__arch_copy_from_user) .section .fixup,"ax" .align 2 -9998: - sub x0, end, dst -9999: - strb wzr, [dst], #1 // zero remaining buffer space - cmp dst, end - b.lo 9999b +9998: sub x0, end, dst // bytes not copied ret .previous diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S index f7292dd08c84..47184c3a97da 100644 --- a/arch/arm64/lib/copy_in_user.S +++ b/arch/arm64/lib/copy_in_user.S @@ -18,11 +18,8 @@ #include <linux/linkage.h> -#include <asm/alternative.h> -#include <asm/assembler.h> #include <asm/cache.h> -#include <asm/cpufeature.h> -#include <asm/sysreg.h> +#include <asm/asm-uaccess.h> /* * Copy from user space to user space (alignment handled by the hardware) @@ -68,12 +65,10 @@ end .req x5 ENTRY(__copy_in_user) -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_enable_not_uao x3, x4 add end, x0, x2 #include "copy_template.S" -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_disable_not_uao x3 mov x0, #0 ret ENDPROC(__copy_in_user) diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S index 4c1e700840b6..c3cd65e31814 100644 --- a/arch/arm64/lib/copy_page.S +++ b/arch/arm64/lib/copy_page.S @@ -29,14 +29,11 @@ * x1 - src */ ENTRY(copy_page) -alternative_if_not ARM64_HAS_NO_HW_PREFETCH - nop - nop -alternative_else +alternative_if ARM64_HAS_NO_HW_PREFETCH # Prefetch two cache lines ahead. prfm pldl1strm, [x1, #128] prfm pldl1strm, [x1, #256] -alternative_endif +alternative_else_nop_endif ldp x2, x3, [x1] ldp x4, x5, [x1, #16] @@ -52,11 +49,9 @@ alternative_endif 1: subs x18, x18, #128 -alternative_if_not ARM64_HAS_NO_HW_PREFETCH - nop -alternative_else +alternative_if ARM64_HAS_NO_HW_PREFETCH prfm pldl1strm, [x1, #384] -alternative_endif +alternative_else_nop_endif stnp x2, x3, [x0] ldp x2, x3, [x1] diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S index 7a7efe255034..351f0766f7a6 100644 --- a/arch/arm64/lib/copy_to_user.S +++ b/arch/arm64/lib/copy_to_user.S @@ -16,11 +16,8 @@ #include <linux/linkage.h> -#include <asm/alternative.h> -#include <asm/assembler.h> #include <asm/cache.h> -#include <asm/cpufeature.h> -#include <asm/sysreg.h> +#include <asm/asm-uaccess.h> /* * Copy to user space from a kernel buffer (alignment handled by the hardware) @@ -66,12 +63,10 @@ end .req x5 ENTRY(__arch_copy_to_user) -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_enable_not_uao x3, x4 add end, x0, x2 #include "copy_template.S" -ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ - CONFIG_ARM64_PAN) + uaccess_disable_not_uao x3 mov x0, #0 ret ENDPROC(__arch_copy_to_user) diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 54bb209cae8e..e703fb9defad 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -3,7 +3,8 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ ioremap.o mmap.o pgd.o mmu.o \ context.o proc.o pageattr.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -obj-$(CONFIG_ARM64_PTDUMP) += dump.o +obj-$(CONFIG_ARM64_PTDUMP_CORE) += dump.o +obj-$(CONFIG_ARM64_PTDUMP_DEBUGFS) += ptdump_debugfs.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_KASAN) += kasan_init.o diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index 07d7352d7c38..83c27b6e6dca 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -23,6 +23,7 @@ #include <asm/assembler.h> #include <asm/cpufeature.h> #include <asm/alternative.h> +#include <asm/asm-uaccess.h> /* * flush_icache_range(start,end) @@ -48,6 +49,7 @@ ENTRY(flush_icache_range) * - end - virtual end address of region */ ENTRY(__flush_cache_user_range) + uaccess_ttbr0_enable x2, x3 dcache_line_size x2, x3 sub x3, x2, #1 bic x4, x0, x3 @@ -69,10 +71,12 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU dsb ish isb mov x0, #0 +1: + uaccess_ttbr0_disable x1 ret 9: mov x0, #-EFAULT - ret + b 1b ENDPROC(flush_icache_range) ENDPROC(__flush_cache_user_range) @@ -105,19 +109,20 @@ ENTRY(__clean_dcache_area_pou) ENDPROC(__clean_dcache_area_pou) /* - * __inval_cache_range(start, end) - * - start - start address of region - * - end - end address of region + * __dma_inv_area(start, size) + * - start - virtual start address of region + * - size - size in question */ -ENTRY(__inval_cache_range) +__dma_inv_area: + add x1, x1, x0 /* FALLTHROUGH */ /* - * __dma_inv_range(start, end) - * - start - virtual start address of region - * - end - virtual end address of region + * __inval_cache_range(start, end) + * - start - start address of region + * - end - end address of region */ -__dma_inv_range: +ENTRY(__inval_cache_range) dcache_line_size x2, x3 sub x3, x2, #1 tst x1, x3 // end cache line aligned? @@ -136,46 +141,43 @@ __dma_inv_range: dsb sy ret ENDPIPROC(__inval_cache_range) -ENDPROC(__dma_inv_range) +ENDPROC(__dma_inv_area) + +/* + * __clean_dcache_area_poc(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are cleaned to the PoC. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__clean_dcache_area_poc) + /* FALLTHROUGH */ /* - * __dma_clean_range(start, end) + * __dma_clean_area(start, size) * - start - virtual start address of region - * - end - virtual end address of region + * - size - size in question */ -__dma_clean_range: - dcache_line_size x2, x3 - sub x3, x2, #1 - bic x0, x0, x3 -1: -alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE - dc cvac, x0 -alternative_else - dc civac, x0 -alternative_endif - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy +__dma_clean_area: + dcache_by_line_op cvac, sy, x0, x1, x2, x3 ret -ENDPROC(__dma_clean_range) +ENDPIPROC(__clean_dcache_area_poc) +ENDPROC(__dma_clean_area) /* - * __dma_flush_range(start, end) + * __dma_flush_area(start, size) + * + * clean & invalidate D / U line + * * - start - virtual start address of region - * - end - virtual end address of region + * - size - size in question */ -ENTRY(__dma_flush_range) - dcache_line_size x2, x3 - sub x3, x2, #1 - bic x0, x0, x3 -1: dc civac, x0 // clean & invalidate D / U line - add x0, x0, x2 - cmp x0, x1 - b.lo 1b - dsb sy +ENTRY(__dma_flush_area) + dcache_by_line_op civac, sy, x0, x1, x2, x3 ret -ENDPIPROC(__dma_flush_range) +ENDPIPROC(__dma_flush_area) /* * __dma_map_area(start, size, dir) @@ -184,10 +186,9 @@ ENDPIPROC(__dma_flush_range) * - dir - DMA direction */ ENTRY(__dma_map_area) - add x1, x1, x0 cmp w2, #DMA_FROM_DEVICE - b.eq __dma_inv_range - b __dma_clean_range + b.eq __dma_inv_area + b __dma_clean_area ENDPIPROC(__dma_map_area) /* @@ -197,8 +198,7 @@ ENDPIPROC(__dma_map_area) * - dir - DMA direction */ ENTRY(__dma_unmap_area) - add x1, x1, x0 cmp w2, #DMA_TO_DEVICE - b.ne __dma_inv_range + b.ne __dma_inv_area ret ENDPIPROC(__dma_unmap_area) diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index efcf1f7ef1e4..4c63cb154859 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -221,7 +221,12 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); switch_mm_fastpath: - cpu_switch_mm(mm->pgd, mm); + /* + * Defer TTBR0_EL1 setting for user threads to uaccess_enable() when + * emulating PAN. + */ + if (!system_uses_ttbr0_pan()) + cpu_switch_mm(mm->pgd, mm); } static int asids_init(void) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index c4284c432ae8..e04082700bb1 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -20,6 +20,7 @@ #include <linux/gfp.h> #include <linux/acpi.h> #include <linux/bootmem.h> +#include <linux/cache.h> #include <linux/export.h> #include <linux/slab.h> #include <linux/genalloc.h> @@ -30,7 +31,7 @@ #include <asm/cacheflush.h> -static int swiotlb __read_mostly; +static int swiotlb __ro_after_init; static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, bool coherent) @@ -168,7 +169,7 @@ static void *__dma_alloc(struct device *dev, size_t size, return ptr; /* remove any dirty cache lines on the kernel alias */ - __dma_flush_range(ptr, ptr + size); + __dma_flush_area(ptr, size); /* create a coherent mapping */ page = virt_to_page(ptr); @@ -387,7 +388,7 @@ static int __init atomic_pool_init(void) void *page_addr = page_address(page); memset(page_addr, 0, atomic_pool_size); - __dma_flush_range(page_addr, page_addr + atomic_pool_size); + __dma_flush_area(page_addr, atomic_pool_size); atomic_pool = gen_pool_create(PAGE_SHIFT, -1); if (!atomic_pool) @@ -523,7 +524,8 @@ EXPORT_SYMBOL(dummy_dma_ops); static int __init arm64_dma_init(void) { - if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) + if (swiotlb_force == SWIOTLB_FORCE || + max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) swiotlb = 1; return atomic_pool_init(); @@ -548,7 +550,7 @@ fs_initcall(dma_debug_do_init); /* Thankfully, all cache ops are by VA so we can ignore phys here */ static void flush_page(struct device *dev, const void *virt, phys_addr_t phys) { - __dma_flush_range(virt, virt + PAGE_SIZE); + __dma_flush_area(virt, PAGE_SIZE); } static void *__iommu_alloc_attrs(struct device *dev, size_t size, @@ -795,6 +797,8 @@ static struct dma_map_ops iommu_dma_ops = { .sync_single_for_device = __iommu_sync_single_for_device, .sync_sg_for_cpu = __iommu_sync_sg_for_cpu, .sync_sg_for_device = __iommu_sync_sg_for_device, + .map_resource = iommu_dma_map_resource, + .unmap_resource = iommu_dma_unmap_resource, .dma_supported = iommu_dma_supported, .mapping_error = iommu_dma_mapping_error, }; @@ -827,7 +831,7 @@ static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops, * then the IOMMU core will have already configured a group for this * device, and allocated the default domain for that group. */ - if (!domain || iommu_dma_init_domain(domain, dma_base, size)) { + if (!domain || iommu_dma_init_domain(domain, dma_base, size, dev)) { pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", dev_name(dev)); return false; @@ -937,11 +941,6 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, void arch_teardown_dma_ops(struct device *dev) { - struct iommu_domain *domain = iommu_get_domain_for_dev(dev); - - if (WARN_ON(domain)) - iommu_detach_device(domain, dev); - dev->archdata.dma_ops = NULL; } diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c index 9c3e75df2180..ca74a2aace42 100644 --- a/arch/arm64/mm/dump.c +++ b/arch/arm64/mm/dump.c @@ -50,6 +50,18 @@ static const struct addr_marker address_markers[] = { { -1, NULL }, }; +#define pt_dump_seq_printf(m, fmt, args...) \ +({ \ + if (m) \ + seq_printf(m, fmt, ##args); \ +}) + +#define pt_dump_seq_puts(m, fmt) \ +({ \ + if (m) \ + seq_printf(m, fmt); \ +}) + /* * The page dumper groups page table entries of the same type into a single * description. It uses pg_state to track the range information while @@ -62,6 +74,9 @@ struct pg_state { unsigned long start_address; unsigned level; u64 current_prot; + bool check_wx; + unsigned long wx_pages; + unsigned long uxn_pages; }; struct prot_bits { @@ -186,10 +201,39 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits, s = bits->clear; if (s) - seq_printf(st->seq, " %s", s); + pt_dump_seq_printf(st->seq, " %s", s); } } +static void note_prot_uxn(struct pg_state *st, unsigned long addr) +{ + if (!st->check_wx) + return; + + if ((st->current_prot & PTE_UXN) == PTE_UXN) + return; + + WARN_ONCE(1, "arm64/mm: Found non-UXN mapping at address %p/%pS\n", + (void *)st->start_address, (void *)st->start_address); + + st->uxn_pages += (addr - st->start_address) / PAGE_SIZE; +} + +static void note_prot_wx(struct pg_state *st, unsigned long addr) +{ + if (!st->check_wx) + return; + if ((st->current_prot & PTE_RDONLY) == PTE_RDONLY) + return; + if ((st->current_prot & PTE_PXN) == PTE_PXN) + return; + + WARN_ONCE(1, "arm64/mm: Found insecure W+X mapping at address %p/%pS\n", + (void *)st->start_address, (void *)st->start_address); + + st->wx_pages += (addr - st->start_address) / PAGE_SIZE; +} + static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u64 val) { @@ -200,14 +244,16 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, st->level = level; st->current_prot = prot; st->start_address = addr; - seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); + pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); } else if (prot != st->current_prot || level != st->level || addr >= st->marker[1].start_address) { const char *unit = units; unsigned long delta; if (st->current_prot) { - seq_printf(st->seq, "0x%016lx-0x%016lx ", + note_prot_uxn(st, addr); + note_prot_wx(st, addr); + pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr); delta = (addr - st->start_address) >> 10; @@ -215,17 +261,17 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, delta >>= 10; unit++; } - seq_printf(st->seq, "%9lu%c %s", delta, *unit, + pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit, pg_level[st->level].name); if (pg_level[st->level].bits) dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num); - seq_puts(st->seq, "\n"); + pt_dump_seq_puts(st->seq, "\n"); } if (addr >= st->marker[1].start_address) { st->marker++; - seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); + pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); } st->start_address = addr; @@ -235,7 +281,7 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level, if (addr >= st->marker[1].start_address) { st->marker++; - seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); + pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); } } @@ -304,9 +350,8 @@ static void walk_pgd(struct pg_state *st, struct mm_struct *mm, } } -static int ptdump_show(struct seq_file *m, void *v) +void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info) { - struct ptdump_info *info = m->private; struct pg_state st = { .seq = m, .marker = info->markers, @@ -315,33 +360,16 @@ static int ptdump_show(struct seq_file *m, void *v) walk_pgd(&st, info->mm, info->base_addr); note_page(&st, 0, 0, 0); - return 0; } -static int ptdump_open(struct inode *inode, struct file *file) +static void ptdump_initialize(void) { - return single_open(file, ptdump_show, inode->i_private); -} - -static const struct file_operations ptdump_fops = { - .open = ptdump_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int ptdump_register(struct ptdump_info *info, const char *name) -{ - struct dentry *pe; unsigned i, j; for (i = 0; i < ARRAY_SIZE(pg_level); i++) if (pg_level[i].bits) for (j = 0; j < pg_level[i].num; j++) pg_level[i].mask |= pg_level[i].bits[j].mask; - - pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops); - return pe ? 0 : -ENOMEM; } static struct ptdump_info kernel_ptdump_info = { @@ -350,8 +378,30 @@ static struct ptdump_info kernel_ptdump_info = { .base_addr = VA_START, }; +void ptdump_check_wx(void) +{ + struct pg_state st = { + .seq = NULL, + .marker = (struct addr_marker[]) { + { 0, NULL}, + { -1, NULL}, + }, + .check_wx = true, + }; + + walk_pgd(&st, &init_mm, 0); + note_page(&st, 0, 0, 0); + if (st.wx_pages || st.uxn_pages) + pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n", + st.wx_pages, st.uxn_pages); + else + pr_info("Checked W+X mappings: passed, no W+X pages found\n"); +} + static int ptdump_init(void) { - return ptdump_register(&kernel_ptdump_info, "kernel_page_tables"); + ptdump_initialize(); + return ptdump_debugfs_register(&kernel_ptdump_info, + "kernel_page_tables"); } device_initcall(ptdump_init); diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c index 81acd4706878..c9f118cd812b 100644 --- a/arch/arm64/mm/extable.c +++ b/arch/arm64/mm/extable.c @@ -2,7 +2,7 @@ * Based on arch/arm/mm/extable.c */ -#include <linux/module.h> +#include <linux/extable.h> #include <linux/uaccess.h> int fixup_exception(struct pt_regs *regs) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 05d2bd776c69..156169c6981b 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/module.h> +#include <linux/extable.h> #include <linux/signal.h> #include <linux/mm.h> #include <linux/hardirq.h> @@ -29,7 +29,9 @@ #include <linux/sched.h> #include <linux/highmem.h> #include <linux/perf_event.h> +#include <linux/preempt.h> +#include <asm/bug.h> #include <asm/cpufeature.h> #include <asm/exception.h> #include <asm/debug-monitors.h> @@ -86,21 +88,21 @@ void show_pte(struct mm_struct *mm, unsigned long addr) break; pud = pud_offset(pgd, addr); - printk(", *pud=%016llx", pud_val(*pud)); + pr_cont(", *pud=%016llx", pud_val(*pud)); if (pud_none(*pud) || pud_bad(*pud)) break; pmd = pmd_offset(pud, addr); - printk(", *pmd=%016llx", pmd_val(*pmd)); + pr_cont(", *pmd=%016llx", pmd_val(*pmd)); if (pmd_none(*pmd) || pmd_bad(*pmd)) break; pte = pte_offset_map(pmd, addr); - printk(", *pte=%016llx", pte_val(*pte)); + pr_cont(", *pte=%016llx", pte_val(*pte)); pte_unmap(pte); } while(0); - printk("\n"); + pr_cont("\n"); } #ifdef CONFIG_ARM64_HW_AFDBM @@ -251,8 +253,7 @@ static int __do_page_fault(struct mm_struct *mm, unsigned long addr, good_area: /* * Check that the permissions on the VMA allow for the fault which - * occurred. If we encountered a write or exec fault, we must have - * appropriate permissions, otherwise we allow any permission. + * occurred. */ if (!(vma->vm_flags & vm_flags)) { fault = VM_FAULT_BADACCESS; @@ -268,13 +269,19 @@ out: return fault; } -static inline bool is_permission_fault(unsigned int esr) +static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs) { unsigned int ec = ESR_ELx_EC(esr); unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; - return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) || - (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM); + if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR) + return false; + + if (system_uses_ttbr0_pan()) + return fsc_type == ESR_ELx_FSC_FAULT && + (regs->pstate & PSR_PAN_BIT); + else + return fsc_type == ESR_ELx_FSC_PERM; } static bool is_el0_instruction_abort(unsigned int esr) @@ -288,7 +295,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; - unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC; + unsigned long vm_flags = VM_READ | VM_WRITE; unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; if (notify_page_fault(regs, esr)) @@ -314,7 +321,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, mm_flags |= FAULT_FLAG_WRITE; } - if (is_permission_fault(esr) && (addr < USER_DS)) { + if (addr < USER_DS && is_permission_fault(esr, regs)) { /* regs->orig_addr_limit may be 0 if we entered from EL0 */ if (regs->orig_addr_limit == KERNEL_DS) die("Accessing user space memory with fs=KERNEL_DS", regs, esr); @@ -506,10 +513,10 @@ static const struct fault_info { { do_bad, SIGBUS, 0, "unknown 17" }, { do_bad, SIGBUS, 0, "unknown 18" }, { do_bad, SIGBUS, 0, "unknown 19" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, + { do_bad, SIGBUS, 0, "synchronous external abort (translation table walk)" }, + { do_bad, SIGBUS, 0, "synchronous external abort (translation table walk)" }, + { do_bad, SIGBUS, 0, "synchronous external abort (translation table walk)" }, + { do_bad, SIGBUS, 0, "synchronous external abort (translation table walk)" }, { do_bad, SIGBUS, 0, "synchronous parity error" }, { do_bad, SIGBUS, 0, "unknown 25" }, { do_bad, SIGBUS, 0, "unknown 26" }, @@ -671,9 +678,17 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, NOKPROBE_SYMBOL(do_debug_exception); #ifdef CONFIG_ARM64_PAN -void cpu_enable_pan(void *__unused) +int cpu_enable_pan(void *__unused) { + /* + * We modify PSTATE. This won't work from irq context as the PSTATE + * is discarded once we return from the exception. + */ + WARN_ON_ONCE(in_interrupt()); + config_sctlr_el1(SCTLR_EL1_SPAN, 0); + asm(SET_PSTATE_PAN(1)); + return 0; } #endif /* CONFIG_ARM64_PAN */ @@ -684,8 +699,9 @@ void cpu_enable_pan(void *__unused) * We need to enable the feature at runtime (instead of adding it to * PSR_MODE_EL1h) as the feature may not be implemented by the cpu. */ -void cpu_enable_uao(void *__unused) +int cpu_enable_uao(void *__unused) { asm(SET_PSTATE_UAO(1)); + return 0; } #endif /* CONFIG_ARM64_UAO */ diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c index 43a76b07eb32..554a2558c12e 100644 --- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c @@ -25,16 +25,7 @@ #include <asm/cachetype.h> #include <asm/tlbflush.h> -#include "mm.h" - -void flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - if (vma->vm_flags & VM_EXEC) - __flush_icache_all(); -} - -static void sync_icache_aliases(void *kaddr, unsigned long len) +void sync_icache_aliases(void *kaddr, unsigned long len) { unsigned long addr = (unsigned long)kaddr; diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 2e49bd252fe7..964b7549af5c 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -51,20 +51,8 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr, *pgsize = PAGE_SIZE; if (!pte_cont(pte)) return 1; - if (!pgd_present(*pgd)) { - VM_BUG_ON(!pgd_present(*pgd)); - return 1; - } pud = pud_offset(pgd, addr); - if (!pud_present(*pud)) { - VM_BUG_ON(!pud_present(*pud)); - return 1; - } pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) { - VM_BUG_ON(!pmd_present(*pmd)); - return 1; - } if ((pte_t *)pmd == ptep) { *pgsize = PMD_SIZE; return CONT_PMDS; @@ -212,7 +200,7 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize); /* save the 1st pte to return */ pte = ptep_get_and_clear(mm, addr, cpte); - for (i = 1; i < ncontig; ++i) { + for (i = 1, addr += pgsize; i < ncontig; ++i, addr += pgsize) { /* * If HW_AFDBM is enabled, then the HW could * turn on the dirty bit for any of the page @@ -250,7 +238,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, pfn = pte_pfn(*cpte); ncontig = find_num_contig(vma->vm_mm, addr, cpte, *cpte, &pgsize); - for (i = 0; i < ncontig; ++i, ++cpte) { + for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) { changed = ptep_set_access_flags(vma, addr, cpte, pfn_pte(pfn, hugeprot), @@ -273,7 +261,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, cpte = huge_pte_offset(mm, addr); ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize); - for (i = 0; i < ncontig; ++i, ++cpte) + for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) ptep_set_wrprotect(mm, addr, cpte); } else { ptep_set_wrprotect(mm, addr, ptep); @@ -291,7 +279,7 @@ void huge_ptep_clear_flush(struct vm_area_struct *vma, cpte = huge_pte_offset(vma->vm_mm, addr); ncontig = find_num_contig(vma->vm_mm, addr, cpte, *cpte, &pgsize); - for (i = 0; i < ncontig; ++i, ++cpte) + for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) ptep_clear_flush(vma, addr, cpte); } else { ptep_clear_flush(vma, addr, ptep); @@ -323,7 +311,7 @@ __setup("hugepagesz=", setup_hugepagesz); static __init int add_default_hugepagesz(void) { if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL) - hugetlb_add_hstate(CONT_PMD_SHIFT); + hugetlb_add_hstate(CONT_PTE_SHIFT); return 0; } arch_initcall(add_default_hugepagesz); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index bbb7ee76e319..716d1226ba69 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -23,6 +23,7 @@ #include <linux/swap.h> #include <linux/init.h> #include <linux/bootmem.h> +#include <linux/cache.h> #include <linux/mman.h> #include <linux/nodemask.h> #include <linux/initrd.h> @@ -34,6 +35,7 @@ #include <linux/dma-contiguous.h> #include <linux/efi.h> #include <linux/swiotlb.h> +#include <linux/vmalloc.h> #include <asm/boot.h> #include <asm/fixmap.h> @@ -47,16 +49,14 @@ #include <asm/tlb.h> #include <asm/alternative.h> -#include "mm.h" - /* * We need to be able to catch inadvertent references to memstart_addr * that occur (potentially in generic code) before arm64_memblock_init() * executes, which assigns it its actual value. So use a default value * that cannot be mistaken for a real physical address. */ -s64 memstart_addr __read_mostly = -1; -phys_addr_t arm64_dma_phys_limit __read_mostly; +s64 memstart_addr __ro_after_init = -1; +phys_addr_t arm64_dma_phys_limit __ro_after_init; #ifdef CONFIG_BLK_DEV_INITRD static int __init early_initrd(char *p) @@ -401,7 +401,8 @@ static void __init free_unused_memmap(void) */ void __init mem_init(void) { - if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) + if (swiotlb_force == SWIOTLB_FORCE || + max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) swiotlb_init(1); set_max_mapnr(pfn_to_page(max_pfn) - mem_map); @@ -421,35 +422,35 @@ void __init mem_init(void) pr_notice("Virtual kernel memory layout:\n"); #ifdef CONFIG_KASAN - pr_cont(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n", + pr_notice(" kasan : 0x%16lx - 0x%16lx (%6ld GB)\n", MLG(KASAN_SHADOW_START, KASAN_SHADOW_END)); #endif - pr_cont(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" modules : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(MODULES_VADDR, MODULES_END)); - pr_cont(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n", + pr_notice(" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n", MLG(VMALLOC_START, VMALLOC_END)); - pr_cont(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .text : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_text, _etext)); - pr_cont(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__start_rodata, __init_begin)); - pr_cont(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .init : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__init_begin, __init_end)); - pr_cont(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .data : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(_sdata, _edata)); - pr_cont(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n", + pr_notice(" .bss : 0x%p" " - 0x%p" " (%6ld KB)\n", MLK_ROUNDUP(__bss_start, __bss_stop)); - pr_cont(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", + pr_notice(" fixed : 0x%16lx - 0x%16lx (%6ld KB)\n", MLK(FIXADDR_START, FIXADDR_TOP)); - pr_cont(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(PCI_IO_START, PCI_IO_END)); #ifdef CONFIG_SPARSEMEM_VMEMMAP - pr_cont(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n", + pr_notice(" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n", MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE)); - pr_cont(" 0x%16lx - 0x%16lx (%6ld MB actual)\n", + pr_notice(" 0x%16lx - 0x%16lx (%6ld MB actual)\n", MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()), (unsigned long)virt_to_page(high_memory))); #endif - pr_cont(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n", + pr_notice(" memory : 0x%16lx - 0x%16lx (%6ld MB)\n", MLM(__phys_to_virt(memblock_start_of_DRAM()), (unsigned long)high_memory)); @@ -485,7 +486,12 @@ void free_initmem(void) { free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)), 0, "unused kernel"); - fixup_init(); + /* + * Unmap the __init region but leave the VM area in place. This + * prevents the region from being reused for kernel modules, which + * is not supported by kallsyms. + */ + unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin)); } #ifdef CONFIG_BLK_DEV_INITRD diff --git a/arch/arm64/mm/mm.h b/arch/arm64/mm/mm.h deleted file mode 100644 index 71fe98985455..000000000000 --- a/arch/arm64/mm/mm.h +++ /dev/null @@ -1,2 +0,0 @@ - -void fixup_init(void); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 4989948d1feb..17243e43184e 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -17,6 +17,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <linux/cache.h> #include <linux/export.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -27,8 +28,6 @@ #include <linux/memblock.h> #include <linux/fs.h> #include <linux/io.h> -#include <linux/slab.h> -#include <linux/stop_machine.h> #include <asm/barrier.h> #include <asm/cputype.h> @@ -41,12 +40,11 @@ #include <asm/tlb.h> #include <asm/memblock.h> #include <asm/mmu_context.h> - -#include "mm.h" +#include <asm/ptdump.h> u64 idmap_t0sz = TCR_T0SZ(VA_BITS); -u64 kimage_voffset __read_mostly; +u64 kimage_voffset __ro_after_init; EXPORT_SYMBOL(kimage_voffset); /* @@ -96,11 +94,24 @@ static phys_addr_t __init early_pgtable_alloc(void) return phys; } +static bool pgattr_change_is_safe(u64 old, u64 new) +{ + /* + * The following mapping attributes may be updated in live + * kernel mappings without the need for break-before-make. + */ + static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE; + + return old == 0 || new == 0 || ((old ^ new) & ~mask) == 0; +} + static void alloc_init_pte(pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, pgprot_t prot, - phys_addr_t (*pgtable_alloc)(void)) + phys_addr_t (*pgtable_alloc)(void), + bool page_mappings_only) { + pgprot_t __prot = prot; pte_t *pte; BUG_ON(pmd_sect(*pmd)); @@ -116,8 +127,28 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, pte = pte_set_fixmap_offset(pmd, addr); do { - set_pte(pte, pfn_pte(pfn, prot)); + pte_t old_pte = *pte; + + /* + * Set the contiguous bit for the subsequent group of PTEs if + * its size and alignment are appropriate. + */ + if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) { + if (end - addr >= CONT_PTE_SIZE && !page_mappings_only) + __prot = __pgprot(pgprot_val(prot) | PTE_CONT); + else + __prot = prot; + } + + set_pte(pte, pfn_pte(pfn, __prot)); pfn++; + + /* + * After the PTE entry has been populated once, we + * only allow updates to the permission attributes. + */ + BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte))); + } while (pte++, addr += PAGE_SIZE, addr != end); pte_clear_fixmap(); @@ -126,8 +157,9 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, phys_addr_t phys, pgprot_t prot, phys_addr_t (*pgtable_alloc)(void), - bool allow_block_mappings) + bool page_mappings_only) { + pgprot_t __prot = prot; pmd_t *pmd; unsigned long next; @@ -147,27 +179,39 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, pmd = pmd_set_fixmap_offset(pud, addr); do { + pmd_t old_pmd = *pmd; + next = pmd_addr_end(addr, end); + /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0 && - allow_block_mappings) { - pmd_t old_pmd =*pmd; - pmd_set_huge(pmd, phys, prot); + !page_mappings_only) { /* - * Check for previous table entries created during - * boot (__create_page_tables) and flush them. + * Set the contiguous bit for the subsequent group of + * PMDs if its size and alignment are appropriate. */ - if (!pmd_none(old_pmd)) { - flush_tlb_all(); - if (pmd_table(old_pmd)) { - phys_addr_t table = pmd_page_paddr(old_pmd); - if (!WARN_ON_ONCE(slab_is_available())) - memblock_free(table, PAGE_SIZE); - } + if (((addr | phys) & ~CONT_PMD_MASK) == 0) { + if (end - addr >= CONT_PMD_SIZE) + __prot = __pgprot(pgprot_val(prot) | + PTE_CONT); + else + __prot = prot; } + pmd_set_huge(pmd, phys, __prot); + + /* + * After the PMD entry has been populated once, we + * only allow updates to the permission attributes. + */ + BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), + pmd_val(*pmd))); } else { alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), - prot, pgtable_alloc); + prot, pgtable_alloc, + page_mappings_only); + + BUG_ON(pmd_val(old_pmd) != 0 && + pmd_val(old_pmd) != pmd_val(*pmd)); } phys += next - addr; } while (pmd++, addr = next, addr != end); @@ -190,7 +234,7 @@ static inline bool use_1G_block(unsigned long addr, unsigned long next, static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, phys_addr_t phys, pgprot_t prot, phys_addr_t (*pgtable_alloc)(void), - bool allow_block_mappings) + bool page_mappings_only) { pud_t *pud; unsigned long next; @@ -205,33 +249,28 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, pud = pud_set_fixmap_offset(pgd, addr); do { + pud_t old_pud = *pud; + next = pud_addr_end(addr, end); /* * For 4K granule only, attempt to put down a 1GB block */ - if (use_1G_block(addr, next, phys) && allow_block_mappings) { - pud_t old_pud = *pud; + if (use_1G_block(addr, next, phys) && !page_mappings_only) { pud_set_huge(pud, phys, prot); /* - * If we have an old value for a pud, it will - * be pointing to a pmd table that we no longer - * need (from swapper_pg_dir). - * - * Look up the old pmd table and free it. + * After the PUD entry has been populated once, we + * only allow updates to the permission attributes. */ - if (!pud_none(old_pud)) { - flush_tlb_all(); - if (pud_table(old_pud)) { - phys_addr_t table = pud_page_paddr(old_pud); - if (!WARN_ON_ONCE(slab_is_available())) - memblock_free(table, PAGE_SIZE); - } - } + BUG_ON(!pgattr_change_is_safe(pud_val(old_pud), + pud_val(*pud))); } else { alloc_init_pmd(pud, addr, next, phys, prot, - pgtable_alloc, allow_block_mappings); + pgtable_alloc, page_mappings_only); + + BUG_ON(pud_val(old_pud) != 0 && + pud_val(old_pud) != pud_val(*pud)); } phys += next - addr; } while (pud++, addr = next, addr != end); @@ -243,7 +282,7 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot, phys_addr_t (*pgtable_alloc)(void), - bool allow_block_mappings) + bool page_mappings_only) { unsigned long addr, length, end, next; pgd_t *pgd = pgd_offset_raw(pgdir, virt); @@ -263,7 +302,7 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, do { next = pgd_addr_end(addr, end); alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc, - allow_block_mappings); + page_mappings_only); phys += next - addr; } while (pgd++, addr = next, addr != end); } @@ -292,17 +331,17 @@ static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, &phys, virt); return; } - __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, true); + __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, false); } void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, - pgprot_t prot, bool allow_block_mappings) + pgprot_t prot, bool page_mappings_only) { BUG_ON(mm == &init_mm); __create_pgd_mapping(mm->pgd, phys, virt, size, prot, - pgd_pgtable_alloc, allow_block_mappings); + pgd_pgtable_alloc, page_mappings_only); } static void create_mapping_late(phys_addr_t phys, unsigned long virt, @@ -315,7 +354,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt, } __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, - NULL, !debug_pagealloc_enabled()); + NULL, debug_pagealloc_enabled()); } static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end) @@ -333,7 +372,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end __create_pgd_mapping(pgd, start, __phys_to_virt(start), end - start, PAGE_KERNEL, early_pgtable_alloc, - !debug_pagealloc_enabled()); + debug_pagealloc_enabled()); return; } @@ -346,13 +385,13 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end __phys_to_virt(start), kernel_start - start, PAGE_KERNEL, early_pgtable_alloc, - !debug_pagealloc_enabled()); + debug_pagealloc_enabled()); if (kernel_end < end) __create_pgd_mapping(pgd, kernel_end, __phys_to_virt(kernel_end), end - kernel_end, PAGE_KERNEL, early_pgtable_alloc, - !debug_pagealloc_enabled()); + debug_pagealloc_enabled()); /* * Map the linear alias of the [_text, __init_begin) interval as @@ -362,7 +401,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end */ __create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start), kernel_end - kernel_start, PAGE_KERNEL_RO, - early_pgtable_alloc, !debug_pagealloc_enabled()); + early_pgtable_alloc, debug_pagealloc_enabled()); } static void __init map_mem(pgd_t *pgd) @@ -397,16 +436,11 @@ void mark_rodata_ro(void) section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata; create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata, section_size, PAGE_KERNEL_RO); -} -void fixup_init(void) -{ - /* - * Unmap the __init region but leave the VM area in place. This - * prevents the region from being reused for kernel modules, which - * is not supported by kallsyms. - */ - unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin)); + /* flush the TLBs after updating live kernel mappings */ + flush_tlb_all(); + + debug_checkwx(); } static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end, @@ -419,7 +453,7 @@ static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end, BUG_ON(!PAGE_ALIGNED(size)); __create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot, - early_pgtable_alloc, !debug_pagealloc_enabled()); + early_pgtable_alloc, debug_pagealloc_enabled()); vma->addr = va_start; vma->phys_addr = pa_start; diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index 5bb15eab6f00..b388a99fea7b 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -17,6 +17,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define pr_fmt(fmt) "NUMA: " fmt + #include <linux/acpi.h> #include <linux/bootmem.h> #include <linux/memblock.h> @@ -24,6 +26,7 @@ #include <linux/of.h> #include <asm/acpi.h> +#include <asm/sections.h> struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); @@ -32,16 +35,15 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE }; static int numa_distance_cnt; static u8 *numa_distance; -static bool numa_off; +bool numa_off; static __init int numa_parse_early_param(char *opt) { if (!opt) return -EINVAL; - if (!strncmp(opt, "off", 3)) { - pr_info("%s\n", "NUMA turned off"); + if (!strncmp(opt, "off", 3)) numa_off = true; - } + return 0; } early_param("numa", numa_parse_early_param); @@ -93,7 +95,6 @@ void numa_clear_node(unsigned int cpu) */ static void __init setup_node_to_cpumask_map(void) { - unsigned int cpu; int node; /* setup nr_node_ids if not done yet */ @@ -106,11 +107,8 @@ static void __init setup_node_to_cpumask_map(void) cpumask_clear(node_to_cpumask_map[node]); } - for_each_possible_cpu(cpu) - set_cpu_numa_node(cpu, NUMA_NO_NODE); - /* cpumask_of_node() will now work */ - pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids); + pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids); } /* @@ -118,18 +116,77 @@ static void __init setup_node_to_cpumask_map(void) */ void numa_store_cpu_info(unsigned int cpu) { - map_cpu_to_node(cpu, numa_off ? 0 : cpu_to_node_map[cpu]); + map_cpu_to_node(cpu, cpu_to_node_map[cpu]); } void __init early_map_cpu_to_node(unsigned int cpu, int nid) { /* fallback to node 0 */ - if (nid < 0 || nid >= MAX_NUMNODES) + if (nid < 0 || nid >= MAX_NUMNODES || numa_off) nid = 0; cpu_to_node_map[cpu] = nid; + + /* + * We should set the numa node of cpu0 as soon as possible, because it + * has already been set up online before. cpu_to_node(0) will soon be + * called. + */ + if (!cpu) + set_cpu_numa_node(cpu, nid); } +#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA +unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(__per_cpu_offset); + +static int __init early_cpu_to_node(int cpu) +{ + return cpu_to_node_map[cpu]; +} + +static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) +{ + return node_distance(early_cpu_to_node(from), early_cpu_to_node(to)); +} + +static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, + size_t align) +{ + int nid = early_cpu_to_node(cpu); + + return memblock_virt_alloc_try_nid(size, align, + __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_ACCESSIBLE, nid); +} + +static void __init pcpu_fc_free(void *ptr, size_t size) +{ + memblock_free_early(__pa(ptr), size); +} + +void __init setup_per_cpu_areas(void) +{ + unsigned long delta; + unsigned int cpu; + int rc; + + /* + * Always reserve area for module percpu variables. That's + * what the legacy allocator did. + */ + rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE, + PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, + pcpu_cpu_distance, + pcpu_fc_alloc, pcpu_fc_free); + if (rc < 0) + panic("Failed to initialize percpu areas."); + + delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; + for_each_possible_cpu(cpu) + __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; +} +#endif + /** * numa_add_memblk - Set node id to memblk * @nid: NUMA node ID of the new memblk @@ -145,13 +202,13 @@ int __init numa_add_memblk(int nid, u64 start, u64 end) ret = memblock_set_node(start, (end - start), &memblock.memory, nid); if (ret < 0) { - pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n", + pr_err("memblock [0x%llx - 0x%llx] failed to add on node %d\n", start, (end - 1), nid); return ret; } node_set(nid, numa_nodes_parsed); - pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n", + pr_info("Adding memblock [0x%llx - 0x%llx] on node %d\n", start, (end - 1), nid); return ret; } @@ -166,19 +223,21 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) void *nd; int tnid; - pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n", - nid, start_pfn << PAGE_SHIFT, - (end_pfn << PAGE_SHIFT) - 1); + if (start_pfn < end_pfn) + pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n", nid, + start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1); + else + pr_info("Initmem setup node %d [<memory-less node>]\n", nid); nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); nd = __va(nd_pa); /* report and initialize */ - pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n", + pr_info("NODE_DATA [mem %#010Lx-%#010Lx]\n", nd_pa, nd_pa + nd_size - 1); tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); if (tnid != nid) - pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid); + pr_info("NODE_DATA(%d) on node %d\n", nid, tnid); node_data[nid] = nd; memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); @@ -235,8 +294,7 @@ static int __init numa_alloc_distance(void) numa_distance[i * numa_distance_cnt + j] = i == j ? LOCAL_DISTANCE : REMOTE_DISTANCE; - pr_debug("NUMA: Initialized distance table, cnt=%d\n", - numa_distance_cnt); + pr_debug("Initialized distance table, cnt=%d\n", numa_distance_cnt); return 0; } @@ -257,20 +315,20 @@ static int __init numa_alloc_distance(void) void __init numa_set_distance(int from, int to, int distance) { if (!numa_distance) { - pr_warn_once("NUMA: Warning: distance table not allocated yet\n"); + pr_warn_once("Warning: distance table not allocated yet\n"); return; } if (from >= numa_distance_cnt || to >= numa_distance_cnt || from < 0 || to < 0) { - pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n", + pr_warn_once("Warning: node ids are out of bound, from=%d to=%d distance=%d\n", from, to, distance); return; } if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) { - pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n", + pr_warn_once("Warning: invalid distance parameter, from=%d to=%d distance=%d\n", from, to, distance); return; } @@ -297,7 +355,7 @@ static int __init numa_register_nodes(void) /* Check that valid nid is set to memblks */ for_each_memblock(memory, mblk) if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) { - pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n", + pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n", mblk->nid, mblk->base, mblk->base + mblk->size - 1); return -EINVAL; @@ -335,8 +393,10 @@ static int __init numa_init(int (*init_func)(void)) if (ret < 0) return ret; - if (nodes_empty(numa_nodes_parsed)) + if (nodes_empty(numa_nodes_parsed)) { + pr_info("No NUMA configuration found\n"); return -EINVAL; + } ret = numa_register_nodes(); if (ret < 0) @@ -344,10 +404,6 @@ static int __init numa_init(int (*init_func)(void)) setup_node_to_cpumask_map(); - /* init boot processor */ - cpu_to_node_map[0] = 0; - map_cpu_to_node(0, 0); - return 0; } @@ -367,10 +423,8 @@ static int __init dummy_numa_init(void) if (numa_off) pr_info("NUMA disabled\n"); /* Forced off on command line. */ - else - pr_info("No NUMA configuration found\n"); - pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n", - 0LLU, PFN_PHYS(max_pfn) - 1); + pr_info("Faking a node at [mem %#018Lx-%#018Lx]\n", + 0LLU, PFN_PHYS(max_pfn) - 1); for_each_memblock(memory, mblk) { ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size); diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index ca6d268e3313..8def55e7249b 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -139,4 +139,43 @@ void __kernel_map_pages(struct page *page, int numpages, int enable) __pgprot(0), __pgprot(PTE_VALID)); } -#endif +#ifdef CONFIG_HIBERNATION +/* + * When built with CONFIG_DEBUG_PAGEALLOC and CONFIG_HIBERNATION, this function + * is used to determine if a linear map page has been marked as not-valid by + * CONFIG_DEBUG_PAGEALLOC. Walk the page table and check the PTE_VALID bit. + * This is based on kern_addr_valid(), which almost does what we need. + * + * Because this is only called on the kernel linear map, p?d_sect() implies + * p?d_present(). When debug_pagealloc is enabled, sections mappings are + * disabled. + */ +bool kernel_page_present(struct page *page) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + unsigned long addr = (unsigned long)page_address(page); + + pgd = pgd_offset_k(addr); + if (pgd_none(*pgd)) + return false; + + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) + return false; + if (pud_sect(*pud)) + return true; + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) + return false; + if (pmd_sect(*pmd)) + return true; + + pte = pte_offset_kernel(pmd, addr); + return pte_valid(*pte); +} +#endif /* CONFIG_HIBERNATION */ +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c index ae11d4e03d0e..371c5f03a170 100644 --- a/arch/arm64/mm/pgd.c +++ b/arch/arm64/mm/pgd.c @@ -26,8 +26,6 @@ #include <asm/page.h> #include <asm/tlbflush.h> -#include "mm.h" - static struct kmem_cache *pgd_cache; pgd_t *pgd_alloc(struct mm_struct *mm) diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 9d37e967fa19..32682be978e0 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -70,11 +70,14 @@ ENTRY(cpu_do_suspend) mrs x8, mdscr_el1 mrs x9, oslsr_el1 mrs x10, sctlr_el1 + mrs x11, tpidr_el1 + mrs x12, sp_el0 stp x2, x3, [x0] stp x4, xzr, [x0, #16] stp x5, x6, [x0, #32] stp x7, x8, [x0, #48] stp x9, x10, [x0, #64] + stp x11, x12, [x0, #80] ret ENDPROC(cpu_do_suspend) @@ -83,12 +86,14 @@ ENDPROC(cpu_do_suspend) * * x0: Address of context pointer */ + .pushsection ".idmap.text", "ax" ENTRY(cpu_do_resume) ldp x2, x3, [x0] ldp x4, x5, [x0, #16] ldp x6, x8, [x0, #32] ldp x9, x10, [x0, #48] ldp x11, x12, [x0, #64] + ldp x13, x14, [x0, #80] msr tpidr_el0, x2 msr tpidrro_el0, x3 msr contextidr_el1, x4 @@ -111,6 +116,8 @@ ENTRY(cpu_do_resume) msr mdscr_el1, x10 msr sctlr_el1, x12 + msr tpidr_el1, x13 + msr sp_el0, x14 /* * Restore oslsr_el1 by writing oslar_el1 */ @@ -120,6 +127,7 @@ ENTRY(cpu_do_resume) isb ret ENDPROC(cpu_do_resume) + .popsection #endif /* @@ -134,17 +142,8 @@ ENTRY(cpu_do_switch_mm) bfi x0, x1, #48, #16 // set the ASID msr ttbr0_el1, x0 // set TTBR0 isb -alternative_if_not ARM64_WORKAROUND_CAVIUM_27456 + post_ttbr0_update_workaround ret - nop - nop - nop -alternative_else - ic iallu - dsb nsh - isb - ret -alternative_endif ENDPROC(cpu_do_switch_mm) .pushsection ".idmap.text", "ax" @@ -181,6 +180,7 @@ ENDPROC(idmap_cpu_replace_ttbr1) * Initialise the processor for turning the MMU on. Return in x0 the * value of the SCTLR_EL1 register. */ + .pushsection ".idmap.text", "ax" ENTRY(__cpu_setup) tlbi vmalle1 // Invalidate local TLB dsb nsh @@ -266,3 +266,4 @@ ENDPROC(__cpu_setup) crval: .word 0xfcffffff // clear .word 0x34d5d91d // set + .popsection diff --git a/arch/arm64/mm/ptdump_debugfs.c b/arch/arm64/mm/ptdump_debugfs.c new file mode 100644 index 000000000000..eee4d864350c --- /dev/null +++ b/arch/arm64/mm/ptdump_debugfs.c @@ -0,0 +1,31 @@ +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +#include <asm/ptdump.h> + +static int ptdump_show(struct seq_file *m, void *v) +{ + struct ptdump_info *info = m->private; + ptdump_walk_pgd(m, info); + return 0; +} + +static int ptdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, ptdump_show, inode->i_private); +} + +static const struct file_operations ptdump_fops = { + .open = ptdump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int ptdump_debugfs_register(struct ptdump_info *info, const char *name) +{ + struct dentry *pe; + pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops); + return pe ? 0 : -ENOMEM; + +} diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S index 329c8027b0a9..947830a459d2 100644 --- a/arch/arm64/xen/hypercall.S +++ b/arch/arm64/xen/hypercall.S @@ -49,6 +49,7 @@ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/asm-uaccess.h> #include <xen/interface/xen.h> @@ -91,6 +92,20 @@ ENTRY(privcmd_call) mov x2, x3 mov x3, x4 mov x4, x5 + /* + * Privcmd calls are issued by the userspace. The kernel needs to + * enable access to TTBR0_EL1 as the hypervisor would issue stage 1 + * translations to user memory via AT instructions. Since AT + * instructions are not affected by the PAN bit (ARMv8.1), we only + * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation + * is enabled (it implies that hardware UAO and PAN disabled). + */ + uaccess_ttbr0_enable x6, x7 hvc XEN_IMM + + /* + * Disable userspace access from kernel once the hyp call completed. + */ + uaccess_ttbr0_disable x6 ret ENDPROC(privcmd_call); |