Commit | Line | Data |
---|---|---|
cd1aebf5 MR |
1 | /* |
2 | * CPU kernel entry/exit control | |
3 | * | |
4 | * Copyright (C) 2013 ARM Ltd. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
0f078336 | 19 | #include <linux/acpi.h> |
e8765b26 MR |
20 | #include <linux/errno.h> |
21 | #include <linux/of.h> | |
cd1aebf5 | 22 | #include <linux/string.h> |
0f078336 LP |
23 | #include <asm/acpi.h> |
24 | #include <asm/cpu_ops.h> | |
25 | #include <asm/smp_plat.h> | |
cd1aebf5 MR |
26 | |
27 | extern const struct cpu_operations smp_spin_table_ops; | |
5e89c55e | 28 | extern const struct cpu_operations acpi_parking_protocol_ops; |
cd1aebf5 MR |
29 | extern const struct cpu_operations cpu_psci_ops; |
30 | ||
31 | const struct cpu_operations *cpu_ops[NR_CPUS]; | |
32 | ||
5e89c55e | 33 | static const struct cpu_operations *dt_supported_cpu_ops[] __initconst = { |
cd1aebf5 | 34 | &smp_spin_table_ops, |
756854d9 | 35 | &cpu_psci_ops, |
cd1aebf5 MR |
36 | NULL, |
37 | }; | |
38 | ||
5e89c55e LP |
39 | static const struct cpu_operations *acpi_supported_cpu_ops[] __initconst = { |
40 | #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL | |
41 | &acpi_parking_protocol_ops, | |
42 | #endif | |
43 | &cpu_psci_ops, | |
44 | NULL, | |
45 | }; | |
46 | ||
0f078336 | 47 | static const struct cpu_operations * __init cpu_get_ops(const char *name) |
cd1aebf5 | 48 | { |
5e89c55e LP |
49 | const struct cpu_operations **ops; |
50 | ||
51 | ops = acpi_disabled ? dt_supported_cpu_ops : acpi_supported_cpu_ops; | |
cd1aebf5 MR |
52 | |
53 | while (*ops) { | |
54 | if (!strcmp(name, (*ops)->name)) | |
55 | return *ops; | |
56 | ||
57 | ops++; | |
58 | } | |
59 | ||
60 | return NULL; | |
61 | } | |
e8765b26 | 62 | |
0f078336 LP |
63 | static const char *__init cpu_read_enable_method(int cpu) |
64 | { | |
65 | const char *enable_method; | |
66 | ||
67 | if (acpi_disabled) { | |
68 | struct device_node *dn = of_get_cpu_node(cpu, NULL); | |
69 | ||
70 | if (!dn) { | |
71 | if (!cpu) | |
72 | pr_err("Failed to find device node for boot cpu\n"); | |
73 | return NULL; | |
74 | } | |
75 | ||
76 | enable_method = of_get_property(dn, "enable-method", NULL); | |
77 | if (!enable_method) { | |
78 | /* | |
79 | * The boot CPU may not have an enable method (e.g. | |
80 | * when spin-table is used for secondaries). | |
81 | * Don't warn spuriously. | |
82 | */ | |
83 | if (cpu != 0) | |
84 | pr_err("%s: missing enable-method property\n", | |
85 | dn->full_name); | |
86 | } | |
87 | } else { | |
88 | enable_method = acpi_get_enable_method(cpu); | |
5e89c55e LP |
89 | if (!enable_method) { |
90 | /* | |
91 | * In ACPI systems the boot CPU does not require | |
92 | * checking the enable method since for some | |
93 | * boot protocol (ie parking protocol) it need not | |
94 | * be initialized. Don't warn spuriously. | |
95 | */ | |
96 | if (cpu != 0) | |
97 | pr_err("Unsupported ACPI enable-method\n"); | |
98 | } | |
0f078336 LP |
99 | } |
100 | ||
101 | return enable_method; | |
102 | } | |
e8765b26 | 103 | /* |
0f078336 | 104 | * Read a cpu's enable method and record it in cpu_ops. |
e8765b26 | 105 | */ |
819a8826 | 106 | int __init cpu_read_ops(int cpu) |
e8765b26 | 107 | { |
0f078336 | 108 | const char *enable_method = cpu_read_enable_method(cpu); |
819a8826 | 109 | |
0f078336 | 110 | if (!enable_method) |
819a8826 | 111 | return -ENODEV; |
e8765b26 MR |
112 | |
113 | cpu_ops[cpu] = cpu_get_ops(enable_method); | |
114 | if (!cpu_ops[cpu]) { | |
0f078336 | 115 | pr_warn("Unsupported enable-method: %s\n", enable_method); |
e8765b26 MR |
116 | return -EOPNOTSUPP; |
117 | } | |
118 | ||
119 | return 0; | |
120 | } |