projects/linux·blob master · refs

366 lines · 7.7 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Architecture specific OF callbacks.
4 */
5#include <linux/acpi.h>
6#include <linux/export.h>
7#include <linux/io.h>
8#include <linux/interrupt.h>
9#include <linux/list.h>
10#include <linux/of.h>
11#include <linux/of_fdt.h>
12#include <linux/of_address.h>
13#include <linux/of_platform.h>
14#include <linux/of_irq.h>
15#include <linux/libfdt.h>
16#include <linux/slab.h>
17#include <linux/pci.h>
18#include <linux/of_pci.h>
19#include <linux/initrd.h>
20
21#include <asm/acpi.h>
22#include <asm/irqdomain.h>
23#include <asm/hpet.h>
24#include <asm/apic.h>
25#include <asm/io_apic.h>
26#include <asm/pci_x86.h>
27#include <asm/setup.h>
28#include <asm/i8259.h>
29#include <asm/numa.h>
30#include <asm/prom.h>
31
32__initdata u64 initial_dtb;
33char __initdata cmd_line[COMMAND_LINE_SIZE];
34
35int __initdata of_ioapic;
36
37void __init add_dtb(u64 data)
38{
39 initial_dtb = data + offsetof(struct setup_data, data);
40}
41
42/*
43 * CE4100 ids. Will be moved to machine_device_initcall() once we have it.
44 */
45static struct of_device_id __initdata ce4100_ids[] = {
46 { .compatible = "intel,ce4100-cp", },
47 { .compatible = "isa", },
48 { .compatible = "pci", },
49 {},
50};
51
52static int __init add_bus_probe(void)
53{
54 if (!of_have_populated_dt())
55 return 0;
56
57 return of_platform_bus_probe(NULL, ce4100_ids, NULL);
58}
59device_initcall(add_bus_probe);
60
61#ifdef CONFIG_PCI
62struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
63{
64 struct device_node *np;
65
66 for_each_node_by_type(np, "pci") {
67 const void *prop;
68 unsigned int bus_min;
69
70 prop = of_get_property(np, "bus-range", NULL);
71 if (!prop)
72 continue;
73 bus_min = be32_to_cpup(prop);
74 if (bus->number == bus_min)
75 return np;
76 }
77 return NULL;
78}
79
80static int x86_of_pci_irq_enable(struct pci_dev *dev)
81{
82 u32 virq;
83 int ret;
84 u8 pin;
85
86 ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
87 if (ret)
88 return pcibios_err_to_errno(ret);
89 if (!pin)
90 return 0;
91
92 virq = of_irq_parse_and_map_pci(dev, 0, 0);
93 if (virq == 0)
94 return -EINVAL;
95 dev->irq = virq;
96 return 0;
97}
98
99static void x86_of_pci_irq_disable(struct pci_dev *dev)
100{
101}
102
103void x86_of_pci_init(void)
104{
105 pcibios_enable_irq = x86_of_pci_irq_enable;
106 pcibios_disable_irq = x86_of_pci_irq_disable;
107}
108#endif
109
110static void __init dtb_setup_hpet(void)
111{
112#ifdef CONFIG_HPET_TIMER
113 struct device_node *dn;
114 struct resource r;
115 int ret;
116
117 dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
118 if (!dn)
119 return;
120 ret = of_address_to_resource(dn, 0, &r);
121 if (ret) {
122 WARN_ON(1);
123 return;
124 }
125 hpet_address = r.start;
126#endif
127}
128
129#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
130
131#define WAKEUP_MAILBOX_SIZE 0x1000
132#define WAKEUP_MAILBOX_ALIGN 0x1000
133
134/** dtb_wakeup_mailbox_setup() - Parse the wakeup mailbox from the device tree
135 *
136 * Look for the presence of a wakeup mailbox in the DeviceTree. The mailbox is
137 * expected to follow the structure and operation described in the Multiprocessor
138 * Wakeup Structure of the ACPI specification.
139 */
140static void __init dtb_wakeup_mailbox_setup(void)
141{
142 struct device_node *node;
143 struct resource res;
144
145 node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox");
146 if (!node)
147 return;
148
149 if (of_address_to_resource(node, 0, &res))
150 goto done;
151
152 /* The mailbox is a 4KB-aligned region.*/
153 if (res.start & (WAKEUP_MAILBOX_ALIGN - 1))
154 goto done;
155
156 /* The mailbox has a size of 4KB. */
157 if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE)
158 goto done;
159
160 /* Not supported when the mailbox is used. */
161 cpu_hotplug_disable_offlining();
162
163 acpi_setup_mp_wakeup_mailbox(res.start);
164done:
165 of_node_put(node);
166}
167#else /* !CONFIG_X86_64 || !CONFIG_SMP */
168static inline int dtb_wakeup_mailbox_setup(void)
169{
170 return -EOPNOTSUPP;
171}
172#endif /* CONFIG_X86_64 && CONFIG_SMP */
173
174#ifdef CONFIG_X86_LOCAL_APIC
175
176static void __init dtb_cpu_setup(void)
177{
178 struct device_node *dn;
179 u32 apic_id;
180
181 for_each_of_cpu_node(dn) {
182 apic_id = of_get_cpu_hwid(dn, 0);
183 if (apic_id == ~0U) {
184 pr_warn("%pOF: missing local APIC ID\n", dn);
185 continue;
186 }
187 topology_register_apic(apic_id, CPU_ACPIID_INVALID, true);
188 set_apicid_to_node(apic_id, of_node_to_nid(dn));
189 }
190}
191
192static void __init dtb_lapic_setup(void)
193{
194 struct device_node *dn;
195 struct resource r;
196 unsigned long lapic_addr = APIC_DEFAULT_PHYS_BASE;
197 int ret;
198
199 dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
200 if (dn) {
201 ret = of_address_to_resource(dn, 0, &r);
202 if (WARN_ON(ret))
203 return;
204 lapic_addr = r.start;
205 }
206
207 /* Did the boot loader setup the local APIC ? */
208 if (!boot_cpu_has(X86_FEATURE_APIC)) {
209 /* Try force enabling, which registers the APIC address */
210 if (!apic_force_enable(lapic_addr))
211 return;
212 } else {
213 register_lapic_address(lapic_addr);
214 }
215 smp_found_config = 1;
216 pic_mode = !of_property_read_bool(dn, "intel,virtual-wire-mode");
217 pr_info("%s compatibility mode.\n", pic_mode ? "IMCR and PIC" : "Virtual Wire");
218}
219
220#endif /* CONFIG_X86_LOCAL_APIC */
221
222#ifdef CONFIG_X86_IO_APIC
223static unsigned int ioapic_id;
224
225struct of_ioapic_type {
226 u32 out_type;
227 u32 is_level;
228 u32 active_low;
229};
230
231static struct of_ioapic_type of_ioapic_type[] =
232{
233 {
234 .out_type = IRQ_TYPE_EDGE_FALLING,
235 .is_level = 0,
236 .active_low = 1,
237 },
238 {
239 .out_type = IRQ_TYPE_LEVEL_HIGH,
240 .is_level = 1,
241 .active_low = 0,
242 },
243 {
244 .out_type = IRQ_TYPE_LEVEL_LOW,
245 .is_level = 1,
246 .active_low = 1,
247 },
248 {
249 .out_type = IRQ_TYPE_EDGE_RISING,
250 .is_level = 0,
251 .active_low = 0,
252 },
253};
254
255static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
256 unsigned int nr_irqs, void *arg)
257{
258 struct irq_fwspec *fwspec = (struct irq_fwspec *)arg;
259 struct of_ioapic_type *it;
260 struct irq_alloc_info tmp;
261 int type_index;
262
263 if (WARN_ON(fwspec->param_count < 2))
264 return -EINVAL;
265
266 type_index = fwspec->param[1];
267 if (type_index >= ARRAY_SIZE(of_ioapic_type))
268 return -EINVAL;
269
270 it = &of_ioapic_type[type_index];
271 ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->is_level, it->active_low);
272 tmp.devid = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
273 tmp.ioapic.pin = fwspec->param[0];
274
275 return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
276}
277
278static const struct irq_domain_ops ioapic_irq_domain_ops = {
279 .alloc = dt_irqdomain_alloc,
280 .free = mp_irqdomain_free,
281 .activate = mp_irqdomain_activate,
282 .deactivate = mp_irqdomain_deactivate,
283};
284
285static void __init dtb_add_ioapic(struct device_node *dn)
286{
287 struct resource r;
288 int ret;
289 struct ioapic_domain_cfg cfg = {
290 .type = IOAPIC_DOMAIN_DYNAMIC,
291 .ops = &ioapic_irq_domain_ops,
292 .dev = dn,
293 };
294
295 ret = of_address_to_resource(dn, 0, &r);
296 if (ret) {
297 pr_err("Can't obtain address from device node %pOF.\n", dn);
298 return;
299 }
300 mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
301}
302
303static void __init dtb_ioapic_setup(void)
304{
305 struct device_node *dn;
306
307 for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
308 dtb_add_ioapic(dn);
309
310 if (nr_ioapics) {
311 of_ioapic = 1;
312 return;
313 }
314 pr_err("Error: No information about IO-APIC in OF.\n");
315}
316#else
317static void __init dtb_ioapic_setup(void) {}
318#endif
319
320static void __init dtb_apic_setup(void)
321{
322#ifdef CONFIG_X86_LOCAL_APIC
323 dtb_lapic_setup();
324 dtb_cpu_setup();
325#endif
326 dtb_ioapic_setup();
327}
328
329static void __init x86_dtb_parse_smp_config(void)
330{
331 if (!of_have_populated_dt())
332 return;
333
334 dtb_setup_hpet();
335 dtb_apic_setup();
336 dtb_wakeup_mailbox_setup();
337}
338
339void __init x86_flattree_get_config(void)
340{
341#ifdef CONFIG_OF_EARLY_FLATTREE
342 u32 size, map_len;
343 void *dt;
344
345 if (initial_dtb) {
346 map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
347
348 dt = early_memremap(initial_dtb, map_len);
349 size = fdt_totalsize(dt);
350 if (map_len < size) {
351 early_memunmap(dt, map_len);
352 dt = early_memremap(initial_dtb, size);
353 map_len = size;
354 }
355
356 early_init_dt_verify(dt, __pa(dt));
357 }
358
359 unflatten_and_copy_device_tree();
360
361 if (initial_dtb)
362 early_memunmap(dt, map_len);
363#endif
364 if (acpi_disabled && of_have_populated_dt())
365 x86_init.mpparse.parse_smp_cfg = x86_dtb_parse_smp_config;
366}