diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 15:39:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 15:39:07 -0500 |
commit | 01e9d22638f387b5413163d1030169b6478c09c5 (patch) | |
tree | f36991611954663429f2ed36ec19145dd0c9ec4f /drivers/firmware | |
parent | 541d284be0fcca3d3990e6dd89b091aec66849c6 (diff) | |
parent | 6660800fb7fd0f66faecb3c550fe59709220ade5 (diff) |
Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King:
- UEFI boot and runtime services support for ARM from Ard Biesheuvel
and Roy Franz.
- DT compatibility with old atags booting protocol for Nokia N900
devices from Ivaylo Dimitrov.
- PSCI firmware interface using new arm-smc calling convention from
Jens Wiklander.
- Runtime patching for udiv/sdiv instructions for ARMv7 CPUs that
support these instructions from Nicolas Pitre.
- L2x0 cache updates from Dirk B and Linus Walleij.
- Randconfig fixes from Arnd Bergmann.
- ARMv7M (nommu) updates from Ezequiel Garcia
* 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: (34 commits)
ARM: 8481/2: drivers: psci: replace psci firmware calls
ARM: 8480/2: arm64: add implementation for arm-smccc
ARM: 8479/2: add implementation for arm-smccc
ARM: 8478/2: arm/arm64: add arm-smccc
ARM: 8494/1: mm: Enable PXN when running non-LPAE kernel on LPAE processor
ARM: 8496/1: OMAP: RX51: save ATAGS data in the early boot stage
ARM: 8495/1: ATAGS: move save_atags() to arch/arm/include/asm/setup.h
ARM: 8452/3: PJ4: make coprocessor access sequences buildable in Thumb2 mode
ARM: 8482/1: l2x0: make it possible to disable outer sync from DT
ARM: 8488/1: Make IPI_CPU_BACKTRACE a "non-secure" SGI
ARM: 8487/1: Remove IPI_CALL_FUNC_SINGLE
ARM: 8485/1: cpuidle: remove cpu parameter from the cpuidle_ops suspend hook
ARM: 8484/1: Documentation: l2c2x0: Mention separate controllers explicitly
ARM: 8483/1: Documentation: l2c: Rename l2cc to l2c2x0
ARM: 8477/1: runtime patch udiv/sdiv instructions into __aeabi_{u}idiv()
ARM: 8476/1: VDSO: use PTR_ERR_OR_ZERO for vma check
ARM: 8453/2: proc-v7.S: don't locate temporary stack space in .text section
ARM: add UEFI stub support
ARM: wire up UEFI init and runtime support
ARM: only consider memblocks with NOMAP cleared for linear mapping
...
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/Kconfig | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/Makefile | 1 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 9 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 4 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm32-stub.c | 85 | ||||
-rw-r--r-- | drivers/firmware/psci.c | 23 |
6 files changed, 122 insertions, 3 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index cf478fe6b335..49a3a1185bb6 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
@@ -173,6 +173,9 @@ config QCOM_SCM_64 | |||
173 | def_bool y | 173 | def_bool y |
174 | depends on QCOM_SCM && ARM64 | 174 | depends on QCOM_SCM && ARM64 |
175 | 175 | ||
176 | config HAVE_ARM_SMCCC | ||
177 | bool | ||
178 | |||
176 | source "drivers/firmware/broadcom/Kconfig" | 179 | source "drivers/firmware/broadcom/Kconfig" |
177 | source "drivers/firmware/google/Kconfig" | 180 | source "drivers/firmware/google/Kconfig" |
178 | source "drivers/firmware/efi/Kconfig" | 181 | source "drivers/firmware/efi/Kconfig" |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index f292917b00e7..62e654f255f4 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -20,4 +20,5 @@ obj-$(CONFIG_EFI_STUB) += libstub/ | |||
20 | obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o | 20 | obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o |
21 | 21 | ||
22 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o | 22 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o |
23 | obj-$(CONFIG_ARM) += $(arm-obj-y) | ||
23 | obj-$(CONFIG_ARM64) += $(arm-obj-y) | 24 | obj-$(CONFIG_ARM64) += $(arm-obj-y) |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index c0ddd1b8dca3..9c12e18031d5 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -34,6 +34,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE | |||
34 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ | 34 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ |
35 | $(patsubst %.c,lib-%.o,$(arm-deps)) | 35 | $(patsubst %.c,lib-%.o,$(arm-deps)) |
36 | 36 | ||
37 | lib-$(CONFIG_ARM) += arm32-stub.o | ||
37 | lib-$(CONFIG_ARM64) += arm64-stub.o | 38 | lib-$(CONFIG_ARM64) += arm64-stub.o |
38 | CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | 39 | CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) |
39 | 40 | ||
@@ -67,3 +68,11 @@ quiet_cmd_stubcopy = STUBCPY $@ | |||
67 | $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ | 68 | $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ |
68 | && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ | 69 | && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ |
69 | rm -f $@; /bin/false); else /bin/false; fi | 70 | rm -f $@; /bin/false); else /bin/false; fi |
71 | |||
72 | # | ||
73 | # ARM discards the .data section because it disallows r/w data in the | ||
74 | # decompressor. So move our .data to .data.efistub, which is preserved | ||
75 | # explicitly by the decompressor linker script. | ||
76 | # | ||
77 | STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub | ||
78 | STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS | ||
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 950c87f5d279..3397902e4040 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -303,8 +303,10 @@ fail: | |||
303 | * The value chosen is the largest non-zero power of 2 suitable for this purpose | 303 | * The value chosen is the largest non-zero power of 2 suitable for this purpose |
304 | * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can | 304 | * both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can |
305 | * be mapped efficiently. | 305 | * be mapped efficiently. |
306 | * Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split, | ||
307 | * map everything below 1 GB. | ||
306 | */ | 308 | */ |
307 | #define EFI_RT_VIRTUAL_BASE 0x40000000 | 309 | #define EFI_RT_VIRTUAL_BASE SZ_512M |
308 | 310 | ||
309 | static int cmp_mem_desc(const void *l, const void *r) | 311 | static int cmp_mem_desc(const void *l, const void *r) |
310 | { | 312 | { |
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c new file mode 100644 index 000000000000..495ebd657e38 --- /dev/null +++ b/drivers/firmware/efi/libstub/arm32-stub.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Linaro Ltd; <roy.franz@linaro.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/efi.h> | ||
10 | #include <asm/efi.h> | ||
11 | |||
12 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | ||
13 | unsigned long *image_addr, | ||
14 | unsigned long *image_size, | ||
15 | unsigned long *reserve_addr, | ||
16 | unsigned long *reserve_size, | ||
17 | unsigned long dram_base, | ||
18 | efi_loaded_image_t *image) | ||
19 | { | ||
20 | unsigned long nr_pages; | ||
21 | efi_status_t status; | ||
22 | /* Use alloc_addr to tranlsate between types */ | ||
23 | efi_physical_addr_t alloc_addr; | ||
24 | |||
25 | /* | ||
26 | * Verify that the DRAM base address is compatible with the ARM | ||
27 | * boot protocol, which determines the base of DRAM by masking | ||
28 | * off the low 27 bits of the address at which the zImage is | ||
29 | * loaded. These assumptions are made by the decompressor, | ||
30 | * before any memory map is available. | ||
31 | */ | ||
32 | dram_base = round_up(dram_base, SZ_128M); | ||
33 | |||
34 | /* | ||
35 | * Reserve memory for the uncompressed kernel image. This is | ||
36 | * all that prevents any future allocations from conflicting | ||
37 | * with the kernel. Since we can't tell from the compressed | ||
38 | * image how much DRAM the kernel actually uses (due to BSS | ||
39 | * size uncertainty) we allocate the maximum possible size. | ||
40 | * Do this very early, as prints can cause memory allocations | ||
41 | * that may conflict with this. | ||
42 | */ | ||
43 | alloc_addr = dram_base; | ||
44 | *reserve_size = MAX_UNCOMP_KERNEL_SIZE; | ||
45 | nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; | ||
46 | status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, | ||
47 | EFI_LOADER_DATA, | ||
48 | nr_pages, &alloc_addr); | ||
49 | if (status != EFI_SUCCESS) { | ||
50 | *reserve_size = 0; | ||
51 | pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); | ||
52 | return status; | ||
53 | } | ||
54 | *reserve_addr = alloc_addr; | ||
55 | |||
56 | /* | ||
57 | * Relocate the zImage, so that it appears in the lowest 128 MB | ||
58 | * memory window. | ||
59 | */ | ||
60 | *image_size = image->image_size; | ||
61 | status = efi_relocate_kernel(sys_table, image_addr, *image_size, | ||
62 | *image_size, | ||
63 | dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); | ||
64 | if (status != EFI_SUCCESS) { | ||
65 | pr_efi_err(sys_table, "Failed to relocate kernel.\n"); | ||
66 | efi_free(sys_table, *reserve_size, *reserve_addr); | ||
67 | *reserve_size = 0; | ||
68 | return status; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Check to see if we were able to allocate memory low enough | ||
73 | * in memory. The kernel determines the base of DRAM from the | ||
74 | * address at which the zImage is loaded. | ||
75 | */ | ||
76 | if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { | ||
77 | pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); | ||
78 | efi_free(sys_table, *reserve_size, *reserve_addr); | ||
79 | *reserve_size = 0; | ||
80 | efi_free(sys_table, *image_size, *image_addr); | ||
81 | *image_size = 0; | ||
82 | return EFI_LOAD_ERROR; | ||
83 | } | ||
84 | return EFI_SUCCESS; | ||
85 | } | ||
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index d24f35d74b27..f25cd79c8a79 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #define pr_fmt(fmt) "psci: " fmt | 14 | #define pr_fmt(fmt) "psci: " fmt |
15 | 15 | ||
16 | #include <linux/arm-smccc.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/linkage.h> | 18 | #include <linux/linkage.h> |
18 | #include <linux/of.h> | 19 | #include <linux/of.h> |
@@ -58,8 +59,6 @@ struct psci_operations psci_ops; | |||
58 | 59 | ||
59 | typedef unsigned long (psci_fn)(unsigned long, unsigned long, | 60 | typedef unsigned long (psci_fn)(unsigned long, unsigned long, |
60 | unsigned long, unsigned long); | 61 | unsigned long, unsigned long); |
61 | asmlinkage psci_fn __invoke_psci_fn_hvc; | ||
62 | asmlinkage psci_fn __invoke_psci_fn_smc; | ||
63 | static psci_fn *invoke_psci_fn; | 62 | static psci_fn *invoke_psci_fn; |
64 | 63 | ||
65 | enum psci_function { | 64 | enum psci_function { |
@@ -107,6 +106,26 @@ bool psci_power_state_is_valid(u32 state) | |||
107 | return !(state & ~valid_mask); | 106 | return !(state & ~valid_mask); |
108 | } | 107 | } |
109 | 108 | ||
109 | static unsigned long __invoke_psci_fn_hvc(unsigned long function_id, | ||
110 | unsigned long arg0, unsigned long arg1, | ||
111 | unsigned long arg2) | ||
112 | { | ||
113 | struct arm_smccc_res res; | ||
114 | |||
115 | arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); | ||
116 | return res.a0; | ||
117 | } | ||
118 | |||
119 | static unsigned long __invoke_psci_fn_smc(unsigned long function_id, | ||
120 | unsigned long arg0, unsigned long arg1, | ||
121 | unsigned long arg2) | ||
122 | { | ||
123 | struct arm_smccc_res res; | ||
124 | |||
125 | arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); | ||
126 | return res.a0; | ||
127 | } | ||
128 | |||
110 | static int psci_to_linux_errno(int errno) | 129 | static int psci_to_linux_errno(int errno) |
111 | { | 130 | { |
112 | switch (errno) { | 131 | switch (errno) { |