aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-24 11:23:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-24 11:23:45 -0400
commit836ee4874e201a5907f9658fb2bf3527dd952d30 (patch)
tree34a9e521bbba61d127794278e7b14d96797273f4 /arch/arm64/kernel
parentfb65d872d7a8dc629837a49513911d0281577bfd (diff)
parent7676fa70feb2f3bcdd4b854a553a57d8ef8505aa (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull initial ACPI support for arm64 from Will Deacon: "This series introduces preliminary ACPI 5.1 support to the arm64 kernel using the "hardware reduced" profile. We don't support any peripherals yet, so it's fairly limited in scope: - MEMORY init (UEFI) - ACPI discovery (RSDP via UEFI) - CPU init (FADT) - GIC init (MADT) - SMP boot (MADT + PSCI) - ACPI Kconfig options (dependent on EXPERT) ACPI for arm64 has been in development for a while now and hardware has been available that can boot with either FDT or ACPI tables. This has been made possible by both changes to the ACPI spec to cater for ARM-based machines (known as "hardware-reduced" in ACPI parlance) but also a Linaro-driven effort to get this supported on top of the Linux kernel. This pull request is the result of that work. These changes allow us to initialise the CPUs, interrupt controller, and timers via ACPI tables, with memory information and cmdline coming from EFI. We don't support a hybrid ACPI/FDT scheme. Of course, there is still plenty of work to do (a serial console would be nice!) but I expect that to happen on a per-driver basis after this core series has been merged. Anyway, the diff stat here is fairly horrible, but splitting this up and merging it via all the different subsystems would have been extremely painful. Instead, we've got all the relevant Acks in place and I've not seen anything other than trivial (Kconfig) conflicts in -next (for completeness, I've included my resolution below). Nearly half of the insertions fall under Documentation/. So, we'll see how this goes. Right now, it all depends on EXPERT and I fully expect people to use FDT by default for the immediate future" * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (31 commits) ARM64 / ACPI: make acpi_map_gic_cpu_interface() as void function ARM64 / ACPI: Ignore the return error value of acpi_map_gic_cpu_interface() ARM64 / ACPI: fix usage of acpi_map_gic_cpu_interface ARM64: kernel: acpi: honour acpi=force command line parameter ARM64: kernel: acpi: refactor ACPI tables init and checks ARM64: kernel: psci: let ACPI probe PSCI version ARM64: kernel: psci: factor out probe function ACPI: move arm64 GSI IRQ model to generic GSI IRQ layer ARM64 / ACPI: Don't unflatten device tree if acpi=force is passed ARM64 / ACPI: additions of ACPI documentation for arm64 Documentation: ACPI for ARM64 ARM64 / ACPI: Enable ARM64 in Kconfig XEN / ACPI: Make XEN ACPI depend on X86 ARM64 / ACPI: Select ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64 clocksource / arch_timer: Parse GTDT to initialize arch timer irqchip: Add GICv2 specific ACPI boot support ARM64 / ACPI: Introduce ACPI_IRQ_MODEL_GIC and register device's gsi ACPI / processor: Make it possible to get CPU hardware ID via GICC ACPI / processor: Introduce phys_cpuid_t for CPU hardware ID ARM64 / ACPI: Parse MADT for SMP initialization ...
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/Makefile1
-rw-r--r--arch/arm64/kernel/acpi.c345
-rw-r--r--arch/arm64/kernel/cpu_ops.c2
-rw-r--r--arch/arm64/kernel/pci.c25
-rw-r--r--arch/arm64/kernel/psci.c112
-rw-r--r--arch/arm64/kernel/setup.c21
-rw-r--r--arch/arm64/kernel/smp.c2
-rw-r--r--arch/arm64/kernel/time.c7
8 files changed, 475 insertions, 40 deletions
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index b12e15b80516..426d0763c81b 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -35,6 +35,7 @@ arm64-obj-$(CONFIG_KGDB) += kgdb.o
35arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o 35arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o
36arm64-obj-$(CONFIG_PCI) += pci.o 36arm64-obj-$(CONFIG_PCI) += pci.o
37arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o 37arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
38arm64-obj-$(CONFIG_ACPI) += acpi.o
38 39
39obj-y += $(arm64-obj-y) vdso/ 40obj-y += $(arm64-obj-y) vdso/
40obj-m += $(arm64-obj-m) 41obj-m += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
new file mode 100644
index 000000000000..8b839558838e
--- /dev/null
+++ b/arch/arm64/kernel/acpi.c
@@ -0,0 +1,345 @@
1/*
2 * ARM64 Specific Low-Level ACPI Boot Support
3 *
4 * Copyright (C) 2013-2014, Linaro Ltd.
5 * Author: Al Stone <al.stone@linaro.org>
6 * Author: Graeme Gregory <graeme.gregory@linaro.org>
7 * Author: Hanjun Guo <hanjun.guo@linaro.org>
8 * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
9 * Author: Naresh Bhat <naresh.bhat@linaro.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#define pr_fmt(fmt) "ACPI: " fmt
17
18#include <linux/acpi.h>
19#include <linux/bootmem.h>
20#include <linux/cpumask.h>
21#include <linux/init.h>
22#include <linux/irq.h>
23#include <linux/irqdomain.h>
24#include <linux/memblock.h>
25#include <linux/of_fdt.h>
26#include <linux/smp.h>
27
28#include <asm/cputype.h>
29#include <asm/cpu_ops.h>
30#include <asm/smp_plat.h>
31
32int acpi_noirq = 1; /* skip ACPI IRQ initialization */
33int acpi_disabled = 1;
34EXPORT_SYMBOL(acpi_disabled);
35
36int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */
37EXPORT_SYMBOL(acpi_pci_disabled);
38
39/* Processors with enabled flag and sane MPIDR */
40static int enabled_cpus;
41
42/* Boot CPU is valid or not in MADT */
43static bool bootcpu_valid __initdata;
44
45static bool param_acpi_off __initdata;
46static bool param_acpi_force __initdata;
47
48static int __init parse_acpi(char *arg)
49{
50 if (!arg)
51 return -EINVAL;
52
53 /* "acpi=off" disables both ACPI table parsing and interpreter */
54 if (strcmp(arg, "off") == 0)
55 param_acpi_off = true;
56 else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
57 param_acpi_force = true;
58 else
59 return -EINVAL; /* Core will print when we return error */
60
61 return 0;
62}
63early_param("acpi", parse_acpi);
64
65static int __init dt_scan_depth1_nodes(unsigned long node,
66 const char *uname, int depth,
67 void *data)
68{
69 /*
70 * Return 1 as soon as we encounter a node at depth 1 that is
71 * not the /chosen node.
72 */
73 if (depth == 1 && (strcmp(uname, "chosen") != 0))
74 return 1;
75 return 0;
76}
77
78/*
79 * __acpi_map_table() will be called before page_init(), so early_ioremap()
80 * or early_memremap() should be called here to for ACPI table mapping.
81 */
82char *__init __acpi_map_table(unsigned long phys, unsigned long size)
83{
84 if (!size)
85 return NULL;
86
87 return early_memremap(phys, size);
88}
89
90void __init __acpi_unmap_table(char *map, unsigned long size)
91{
92 if (!map || !size)
93 return;
94
95 early_memunmap(map, size);
96}
97
98/**
99 * acpi_map_gic_cpu_interface - generates a logical cpu number
100 * and map to MPIDR represented by GICC structure
101 */
102static void __init
103acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
104{
105 int i;
106 u64 mpidr = processor->arm_mpidr & MPIDR_HWID_BITMASK;
107 bool enabled = !!(processor->flags & ACPI_MADT_ENABLED);
108
109 if (mpidr == INVALID_HWID) {
110 pr_info("Skip MADT cpu entry with invalid MPIDR\n");
111 return;
112 }
113
114 total_cpus++;
115 if (!enabled)
116 return;
117
118 if (enabled_cpus >= NR_CPUS) {
119 pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n",
120 NR_CPUS, total_cpus, mpidr);
121 return;
122 }
123
124 /* Check if GICC structure of boot CPU is available in the MADT */
125 if (cpu_logical_map(0) == mpidr) {
126 if (bootcpu_valid) {
127 pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n",
128 mpidr);
129 return;
130 }
131
132 bootcpu_valid = true;
133 }
134
135 /*
136 * Duplicate MPIDRs are a recipe for disaster. Scan
137 * all initialized entries and check for
138 * duplicates. If any is found just ignore the CPU.
139 */
140 for (i = 1; i < enabled_cpus; i++) {
141 if (cpu_logical_map(i) == mpidr) {
142 pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n",
143 mpidr);
144 return;
145 }
146 }
147
148 if (!acpi_psci_present())
149 return;
150
151 cpu_ops[enabled_cpus] = cpu_get_ops("psci");
152 /* CPU 0 was already initialized */
153 if (enabled_cpus) {
154 if (!cpu_ops[enabled_cpus])
155 return;
156
157 if (cpu_ops[enabled_cpus]->cpu_init(NULL, enabled_cpus))
158 return;
159
160 /* map the logical cpu id to cpu MPIDR */
161 cpu_logical_map(enabled_cpus) = mpidr;
162 }
163
164 enabled_cpus++;
165}
166
167static int __init
168acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
169 const unsigned long end)
170{
171 struct acpi_madt_generic_interrupt *processor;
172
173 processor = (struct acpi_madt_generic_interrupt *)header;
174
175 if (BAD_MADT_ENTRY(processor, end))
176 return -EINVAL;
177
178 acpi_table_print_madt_entry(header);
179 acpi_map_gic_cpu_interface(processor);
180 return 0;
181}
182
183/* Parse GIC cpu interface entries in MADT for SMP init */
184void __init acpi_init_cpus(void)
185{
186 int count, i;
187
188 /*
189 * do a partial walk of MADT to determine how many CPUs
190 * we have including disabled CPUs, and get information
191 * we need for SMP init
192 */
193 count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
194 acpi_parse_gic_cpu_interface, 0);
195
196 if (!count) {
197 pr_err("No GIC CPU interface entries present\n");
198 return;
199 } else if (count < 0) {
200 pr_err("Error parsing GIC CPU interface entry\n");
201 return;
202 }
203
204 if (!bootcpu_valid) {
205 pr_err("MADT missing boot CPU MPIDR, not enabling secondaries\n");
206 return;
207 }
208
209 for (i = 0; i < enabled_cpus; i++)
210 set_cpu_possible(i, true);
211
212 /* Make boot-up look pretty */
213 pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus);
214}
215
216/*
217 * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
218 * checks on it
219 *
220 * Return 0 on success, <0 on failure
221 */
222static int __init acpi_fadt_sanity_check(void)
223{
224 struct acpi_table_header *table;
225 struct acpi_table_fadt *fadt;
226 acpi_status status;
227 acpi_size tbl_size;
228 int ret = 0;
229
230 /*
231 * FADT is required on arm64; retrieve it to check its presence
232 * and carry out revision and ACPI HW reduced compliancy tests
233 */
234 status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size);
235 if (ACPI_FAILURE(status)) {
236 const char *msg = acpi_format_exception(status);
237
238 pr_err("Failed to get FADT table, %s\n", msg);
239 return -ENODEV;
240 }
241
242 fadt = (struct acpi_table_fadt *)table;
243
244 /*
245 * Revision in table header is the FADT Major revision, and there
246 * is a minor revision of FADT which was introduced by ACPI 5.1,
247 * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
248 * boot protocol configuration data.
249 */
250 if (table->revision < 5 ||
251 (table->revision == 5 && fadt->minor_revision < 1)) {
252 pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n",
253 table->revision, fadt->minor_revision);
254 ret = -EINVAL;
255 goto out;
256 }
257
258 if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
259 pr_err("FADT not ACPI hardware reduced compliant\n");
260 ret = -EINVAL;
261 }
262
263out:
264 /*
265 * acpi_get_table_with_size() creates FADT table mapping that
266 * should be released after parsing and before resuming boot
267 */
268 early_acpi_os_unmap_memory(table, tbl_size);
269 return ret;
270}
271
272/*
273 * acpi_boot_table_init() called from setup_arch(), always.
274 * 1. find RSDP and get its address, and then find XSDT
275 * 2. extract all tables and checksums them all
276 * 3. check ACPI FADT revision
277 * 4. check ACPI FADT HW reduced flag
278 *
279 * We can parse ACPI boot-time tables such as MADT after
280 * this function is called.
281 *
282 * On return ACPI is enabled if either:
283 *
284 * - ACPI tables are initialized and sanity checks passed
285 * - acpi=force was passed in the command line and ACPI was not disabled
286 * explicitly through acpi=off command line parameter
287 *
288 * ACPI is disabled on function return otherwise
289 */
290void __init acpi_boot_table_init(void)
291{
292 /*
293 * Enable ACPI instead of device tree unless
294 * - ACPI has been disabled explicitly (acpi=off), or
295 * - the device tree is not empty (it has more than just a /chosen node)
296 * and ACPI has not been force enabled (acpi=force)
297 */
298 if (param_acpi_off ||
299 (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
300 return;
301
302 /*
303 * ACPI is disabled at this point. Enable it in order to parse
304 * the ACPI tables and carry out sanity checks
305 */
306 enable_acpi();
307
308 /*
309 * If ACPI tables are initialized and FADT sanity checks passed,
310 * leave ACPI enabled and carry on booting; otherwise disable ACPI
311 * on initialization error.
312 * If acpi=force was passed on the command line it forces ACPI
313 * to be enabled even if its initialization failed.
314 */
315 if (acpi_table_init() || acpi_fadt_sanity_check()) {
316 pr_err("Failed to init ACPI tables\n");
317 if (!param_acpi_force)
318 disable_acpi();
319 }
320}
321
322void __init acpi_gic_init(void)
323{
324 struct acpi_table_header *table;
325 acpi_status status;
326 acpi_size tbl_size;
327 int err;
328
329 if (acpi_disabled)
330 return;
331
332 status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
333 if (ACPI_FAILURE(status)) {
334 const char *msg = acpi_format_exception(status);
335
336 pr_err("Failed to get MADT table, %s\n", msg);
337 return;
338 }
339
340 err = gic_v2_acpi_init(table);
341 if (err)
342 pr_err("Failed to initialize GIC IRQ controller");
343
344 early_acpi_os_unmap_memory((char *)table, tbl_size);
345}
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index cce952440c64..fb8ff9ba467a 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -35,7 +35,7 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = {
35 NULL, 35 NULL,
36}; 36};
37 37
38static const struct cpu_operations * __init cpu_get_ops(const char *name) 38const struct cpu_operations * __init cpu_get_ops(const char *name)
39{ 39{
40 const struct cpu_operations **ops = supported_cpu_ops; 40 const struct cpu_operations **ops = supported_cpu_ops;
41 41
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 6f93c24ca801..4095379dc069 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -10,6 +10,7 @@
10 * 10 *
11 */ 11 */
12 12
13#include <linux/acpi.h>
13#include <linux/init.h> 14#include <linux/init.h>
14#include <linux/io.h> 15#include <linux/io.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -46,3 +47,27 @@ int pcibios_add_device(struct pci_dev *dev)
46 47
47 return 0; 48 return 0;
48} 49}
50
51/*
52 * raw_pci_read/write - Platform-specific PCI config space access.
53 */
54int raw_pci_read(unsigned int domain, unsigned int bus,
55 unsigned int devfn, int reg, int len, u32 *val)
56{
57 return -ENXIO;
58}
59
60int raw_pci_write(unsigned int domain, unsigned int bus,
61 unsigned int devfn, int reg, int len, u32 val)
62{
63 return -ENXIO;
64}
65
66#ifdef CONFIG_ACPI
67/* Root bridge scanning */
68struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
69{
70 /* TODO: Should be revisited when implementing PCI on ACPI */
71 return NULL;
72}
73#endif
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 9b8a70ae64a1..ea18cb53921e 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -15,6 +15,7 @@
15 15
16#define pr_fmt(fmt) "psci: " fmt 16#define pr_fmt(fmt) "psci: " fmt
17 17
18#include <linux/acpi.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/of.h> 20#include <linux/of.h>
20#include <linux/smp.h> 21#include <linux/smp.h>
@@ -24,6 +25,7 @@
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <uapi/linux/psci.h> 26#include <uapi/linux/psci.h>
26 27
28#include <asm/acpi.h>
27#include <asm/compiler.h> 29#include <asm/compiler.h>
28#include <asm/cpu_ops.h> 30#include <asm/cpu_ops.h>
29#include <asm/errno.h> 31#include <asm/errno.h>
@@ -273,39 +275,8 @@ static void psci_sys_poweroff(void)
273 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); 275 invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
274} 276}
275 277
276/* 278static void __init psci_0_2_set_functions(void)
277 * PSCI Function IDs for v0.2+ are well defined so use
278 * standard values.
279 */
280static int __init psci_0_2_init(struct device_node *np)
281{ 279{
282 int err, ver;
283
284 err = get_set_conduit_method(np);
285
286 if (err)
287 goto out_put_node;
288
289 ver = psci_get_version();
290
291 if (ver == PSCI_RET_NOT_SUPPORTED) {
292 /* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */
293 pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
294 err = -EOPNOTSUPP;
295 goto out_put_node;
296 } else {
297 pr_info("PSCIv%d.%d detected in firmware.\n",
298 PSCI_VERSION_MAJOR(ver),
299 PSCI_VERSION_MINOR(ver));
300
301 if (PSCI_VERSION_MAJOR(ver) == 0 &&
302 PSCI_VERSION_MINOR(ver) < 2) {
303 err = -EINVAL;
304 pr_err("Conflicting PSCI version detected.\n");
305 goto out_put_node;
306 }
307 }
308
309 pr_info("Using standard PSCI v0.2 function IDs\n"); 280 pr_info("Using standard PSCI v0.2 function IDs\n");
310 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND; 281 psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
311 psci_ops.cpu_suspend = psci_cpu_suspend; 282 psci_ops.cpu_suspend = psci_cpu_suspend;
@@ -329,6 +300,60 @@ static int __init psci_0_2_init(struct device_node *np)
329 arm_pm_restart = psci_sys_reset; 300 arm_pm_restart = psci_sys_reset;
330 301
331 pm_power_off = psci_sys_poweroff; 302 pm_power_off = psci_sys_poweroff;
303}
304
305/*
306 * Probe function for PSCI firmware versions >= 0.2
307 */
308static int __init psci_probe(void)
309{
310 int ver = psci_get_version();
311
312 if (ver == PSCI_RET_NOT_SUPPORTED) {
313 /*
314 * PSCI versions >=0.2 mandates implementation of
315 * PSCI_VERSION.
316 */
317 pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
318 return -EOPNOTSUPP;
319 } else {
320 pr_info("PSCIv%d.%d detected in firmware.\n",
321 PSCI_VERSION_MAJOR(ver),
322 PSCI_VERSION_MINOR(ver));
323
324 if (PSCI_VERSION_MAJOR(ver) == 0 &&
325 PSCI_VERSION_MINOR(ver) < 2) {
326 pr_err("Conflicting PSCI version detected.\n");
327 return -EINVAL;
328 }
329 }
330
331 psci_0_2_set_functions();
332
333 return 0;
334}
335
336/*
337 * PSCI init function for PSCI versions >=0.2
338 *
339 * Probe based on PSCI PSCI_VERSION function
340 */
341static int __init psci_0_2_init(struct device_node *np)
342{
343 int err;
344
345 err = get_set_conduit_method(np);
346
347 if (err)
348 goto out_put_node;
349 /*
350 * Starting with v0.2, the PSCI specification introduced a call
351 * (PSCI_VERSION) that allows probing the firmware version, so
352 * that PSCI function IDs and version specific initialization
353 * can be carried out according to the specific version reported
354 * by firmware
355 */
356 err = psci_probe();
332 357
333out_put_node: 358out_put_node:
334 of_node_put(np); 359 of_node_put(np);
@@ -381,7 +406,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
381 {}, 406 {},
382}; 407};
383 408
384int __init psci_init(void) 409int __init psci_dt_init(void)
385{ 410{
386 struct device_node *np; 411 struct device_node *np;
387 const struct of_device_id *matched_np; 412 const struct of_device_id *matched_np;
@@ -396,6 +421,27 @@ int __init psci_init(void)
396 return init_fn(np); 421 return init_fn(np);
397} 422}
398 423
424/*
425 * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
426 * explicitly clarified in SBBR
427 */
428int __init psci_acpi_init(void)
429{
430 if (!acpi_psci_present()) {
431 pr_info("is not implemented in ACPI.\n");
432 return -EOPNOTSUPP;
433 }
434
435 pr_info("probing for conduit method from ACPI.\n");
436
437 if (acpi_psci_use_hvc())
438 invoke_psci_fn = __invoke_psci_fn_hvc;
439 else
440 invoke_psci_fn = __invoke_psci_fn_smc;
441
442 return psci_probe();
443}
444
399#ifdef CONFIG_SMP 445#ifdef CONFIG_SMP
400 446
401static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu) 447static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 51ef97274b52..74753132c3ac 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -17,6 +17,7 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <linux/acpi.h>
20#include <linux/export.h> 21#include <linux/export.h>
21#include <linux/kernel.h> 22#include <linux/kernel.h>
22#include <linux/stddef.h> 23#include <linux/stddef.h>
@@ -46,6 +47,7 @@
46#include <linux/efi.h> 47#include <linux/efi.h>
47#include <linux/personality.h> 48#include <linux/personality.h>
48 49
50#include <asm/acpi.h>
49#include <asm/fixmap.h> 51#include <asm/fixmap.h>
50#include <asm/cpu.h> 52#include <asm/cpu.h>
51#include <asm/cputype.h> 53#include <asm/cputype.h>
@@ -395,18 +397,27 @@ void __init setup_arch(char **cmdline_p)
395 efi_init(); 397 efi_init();
396 arm64_memblock_init(); 398 arm64_memblock_init();
397 399
400 /* Parse the ACPI tables for possible boot-time configuration */
401 acpi_boot_table_init();
402
398 paging_init(); 403 paging_init();
399 request_standard_resources(); 404 request_standard_resources();
400 405
401 early_ioremap_reset(); 406 early_ioremap_reset();
402 407
403 unflatten_device_tree(); 408 if (acpi_disabled) {
404 409 unflatten_device_tree();
405 psci_init(); 410 psci_dt_init();
411 cpu_read_bootcpu_ops();
412#ifdef CONFIG_SMP
413 of_smp_init_cpus();
414#endif
415 } else {
416 psci_acpi_init();
417 acpi_init_cpus();
418 }
406 419
407 cpu_read_bootcpu_ops();
408#ifdef CONFIG_SMP 420#ifdef CONFIG_SMP
409 smp_init_cpus();
410 smp_build_mpidr_hash(); 421 smp_build_mpidr_hash();
411#endif 422#endif
412 423
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 714411f62391..2cb008177252 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -323,7 +323,7 @@ void __init smp_prepare_boot_cpu(void)
323 * cpu logical map array containing MPIDR values related to logical 323 * cpu logical map array containing MPIDR values related to logical
324 * cpus. Assumes that cpu_logical_map(0) has already been initialized. 324 * cpus. Assumes that cpu_logical_map(0) has already been initialized.
325 */ 325 */
326void __init smp_init_cpus(void) 326void __init of_smp_init_cpus(void)
327{ 327{
328 struct device_node *dn = NULL; 328 struct device_node *dn = NULL;
329 unsigned int i, cpu = 1; 329 unsigned int i, cpu = 1;
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 1a7125c3099b..42f9195cf2f8 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -35,6 +35,7 @@
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/clocksource.h> 36#include <linux/clocksource.h>
37#include <linux/clk-provider.h> 37#include <linux/clk-provider.h>
38#include <linux/acpi.h>
38 39
39#include <clocksource/arm_arch_timer.h> 40#include <clocksource/arm_arch_timer.h>
40 41
@@ -72,6 +73,12 @@ void __init time_init(void)
72 73
73 tick_setup_hrtimer_broadcast(); 74 tick_setup_hrtimer_broadcast();
74 75
76 /*
77 * Since ACPI or FDT will only one be available in the system,
78 * we can use acpi_generic_timer_init() here safely
79 */
80 acpi_generic_timer_init();
81
75 arch_timer_rate = arch_timer_get_rate(); 82 arch_timer_rate = arch_timer_get_rate();
76 if (!arch_timer_rate) 83 if (!arch_timer_rate)
77 panic("Unable to initialise architected timer.\n"); 84 panic("Unable to initialise architected timer.\n");