Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/kernel/devicetree.c
10817 views
1
/*
2
* Architecture specific OF callbacks.
3
*/
4
#include <linux/bootmem.h>
5
#include <linux/io.h>
6
#include <linux/interrupt.h>
7
#include <linux/list.h>
8
#include <linux/of.h>
9
#include <linux/of_fdt.h>
10
#include <linux/of_address.h>
11
#include <linux/of_platform.h>
12
#include <linux/of_irq.h>
13
#include <linux/slab.h>
14
#include <linux/pci.h>
15
#include <linux/of_pci.h>
16
#include <linux/initrd.h>
17
18
#include <asm/hpet.h>
19
#include <asm/irq_controller.h>
20
#include <asm/apic.h>
21
#include <asm/pci_x86.h>
22
23
__initdata u64 initial_dtb;
24
char __initdata cmd_line[COMMAND_LINE_SIZE];
25
static LIST_HEAD(irq_domains);
26
static DEFINE_RAW_SPINLOCK(big_irq_lock);
27
28
int __initdata of_ioapic;
29
30
#ifdef CONFIG_X86_IO_APIC
31
static void add_interrupt_host(struct irq_domain *ih)
32
{
33
unsigned long flags;
34
35
raw_spin_lock_irqsave(&big_irq_lock, flags);
36
list_add(&ih->l, &irq_domains);
37
raw_spin_unlock_irqrestore(&big_irq_lock, flags);
38
}
39
#endif
40
41
static struct irq_domain *get_ih_from_node(struct device_node *controller)
42
{
43
struct irq_domain *ih, *found = NULL;
44
unsigned long flags;
45
46
raw_spin_lock_irqsave(&big_irq_lock, flags);
47
list_for_each_entry(ih, &irq_domains, l) {
48
if (ih->controller == controller) {
49
found = ih;
50
break;
51
}
52
}
53
raw_spin_unlock_irqrestore(&big_irq_lock, flags);
54
return found;
55
}
56
57
unsigned int irq_create_of_mapping(struct device_node *controller,
58
const u32 *intspec, unsigned int intsize)
59
{
60
struct irq_domain *ih;
61
u32 virq, type;
62
int ret;
63
64
ih = get_ih_from_node(controller);
65
if (!ih)
66
return 0;
67
ret = ih->xlate(ih, intspec, intsize, &virq, &type);
68
if (ret)
69
return 0;
70
if (type == IRQ_TYPE_NONE)
71
return virq;
72
irq_set_irq_type(virq, type);
73
return virq;
74
}
75
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
76
77
unsigned long pci_address_to_pio(phys_addr_t address)
78
{
79
/*
80
* The ioport address can be directly used by inX / outX
81
*/
82
BUG_ON(address >= (1 << 16));
83
return (unsigned long)address;
84
}
85
EXPORT_SYMBOL_GPL(pci_address_to_pio);
86
87
void __init early_init_dt_scan_chosen_arch(unsigned long node)
88
{
89
BUG();
90
}
91
92
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
93
{
94
BUG();
95
}
96
97
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
98
{
99
return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
100
}
101
102
#ifdef CONFIG_BLK_DEV_INITRD
103
void __init early_init_dt_setup_initrd_arch(unsigned long start,
104
unsigned long end)
105
{
106
initrd_start = (unsigned long)__va(start);
107
initrd_end = (unsigned long)__va(end);
108
initrd_below_start_ok = 1;
109
}
110
#endif
111
112
void __init add_dtb(u64 data)
113
{
114
initial_dtb = data + offsetof(struct setup_data, data);
115
}
116
117
/*
118
* CE4100 ids. Will be moved to machine_device_initcall() once we have it.
119
*/
120
static struct of_device_id __initdata ce4100_ids[] = {
121
{ .compatible = "intel,ce4100-cp", },
122
{ .compatible = "isa", },
123
{ .compatible = "pci", },
124
{},
125
};
126
127
static int __init add_bus_probe(void)
128
{
129
if (!of_have_populated_dt())
130
return 0;
131
132
return of_platform_bus_probe(NULL, ce4100_ids, NULL);
133
}
134
module_init(add_bus_probe);
135
136
#ifdef CONFIG_PCI
137
static int x86_of_pci_irq_enable(struct pci_dev *dev)
138
{
139
struct of_irq oirq;
140
u32 virq;
141
int ret;
142
u8 pin;
143
144
ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
145
if (ret)
146
return ret;
147
if (!pin)
148
return 0;
149
150
ret = of_irq_map_pci(dev, &oirq);
151
if (ret)
152
return ret;
153
154
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
155
oirq.size);
156
if (virq == 0)
157
return -EINVAL;
158
dev->irq = virq;
159
return 0;
160
}
161
162
static void x86_of_pci_irq_disable(struct pci_dev *dev)
163
{
164
}
165
166
void __cpuinit x86_of_pci_init(void)
167
{
168
struct device_node *np;
169
170
pcibios_enable_irq = x86_of_pci_irq_enable;
171
pcibios_disable_irq = x86_of_pci_irq_disable;
172
173
for_each_node_by_type(np, "pci") {
174
const void *prop;
175
struct pci_bus *bus;
176
unsigned int bus_min;
177
struct device_node *child;
178
179
prop = of_get_property(np, "bus-range", NULL);
180
if (!prop)
181
continue;
182
bus_min = be32_to_cpup(prop);
183
184
bus = pci_find_bus(0, bus_min);
185
if (!bus) {
186
printk(KERN_ERR "Can't find a node for bus %s.\n",
187
np->full_name);
188
continue;
189
}
190
191
if (bus->self)
192
bus->self->dev.of_node = np;
193
else
194
bus->dev.of_node = np;
195
196
for_each_child_of_node(np, child) {
197
struct pci_dev *dev;
198
u32 devfn;
199
200
prop = of_get_property(child, "reg", NULL);
201
if (!prop)
202
continue;
203
204
devfn = (be32_to_cpup(prop) >> 8) & 0xff;
205
dev = pci_get_slot(bus, devfn);
206
if (!dev)
207
continue;
208
dev->dev.of_node = child;
209
pci_dev_put(dev);
210
}
211
}
212
}
213
#endif
214
215
static void __init dtb_setup_hpet(void)
216
{
217
#ifdef CONFIG_HPET_TIMER
218
struct device_node *dn;
219
struct resource r;
220
int ret;
221
222
dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
223
if (!dn)
224
return;
225
ret = of_address_to_resource(dn, 0, &r);
226
if (ret) {
227
WARN_ON(1);
228
return;
229
}
230
hpet_address = r.start;
231
#endif
232
}
233
234
static void __init dtb_lapic_setup(void)
235
{
236
#ifdef CONFIG_X86_LOCAL_APIC
237
struct device_node *dn;
238
struct resource r;
239
int ret;
240
241
dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
242
if (!dn)
243
return;
244
245
ret = of_address_to_resource(dn, 0, &r);
246
if (WARN_ON(ret))
247
return;
248
249
/* Did the boot loader setup the local APIC ? */
250
if (!cpu_has_apic) {
251
if (apic_force_enable(r.start))
252
return;
253
}
254
smp_found_config = 1;
255
pic_mode = 1;
256
register_lapic_address(r.start);
257
generic_processor_info(boot_cpu_physical_apicid,
258
GET_APIC_VERSION(apic_read(APIC_LVR)));
259
#endif
260
}
261
262
#ifdef CONFIG_X86_IO_APIC
263
static unsigned int ioapic_id;
264
265
static void __init dtb_add_ioapic(struct device_node *dn)
266
{
267
struct resource r;
268
int ret;
269
270
ret = of_address_to_resource(dn, 0, &r);
271
if (ret) {
272
printk(KERN_ERR "Can't obtain address from node %s.\n",
273
dn->full_name);
274
return;
275
}
276
mp_register_ioapic(++ioapic_id, r.start, gsi_top);
277
}
278
279
static void __init dtb_ioapic_setup(void)
280
{
281
struct device_node *dn;
282
283
for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
284
dtb_add_ioapic(dn);
285
286
if (nr_ioapics) {
287
of_ioapic = 1;
288
return;
289
}
290
printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
291
}
292
#else
293
static void __init dtb_ioapic_setup(void) {}
294
#endif
295
296
static void __init dtb_apic_setup(void)
297
{
298
dtb_lapic_setup();
299
dtb_ioapic_setup();
300
}
301
302
#ifdef CONFIG_OF_FLATTREE
303
static void __init x86_flattree_get_config(void)
304
{
305
u32 size, map_len;
306
void *new_dtb;
307
308
if (!initial_dtb)
309
return;
310
311
map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
312
(u64)sizeof(struct boot_param_header));
313
314
initial_boot_params = early_memremap(initial_dtb, map_len);
315
size = be32_to_cpu(initial_boot_params->totalsize);
316
if (map_len < size) {
317
early_iounmap(initial_boot_params, map_len);
318
initial_boot_params = early_memremap(initial_dtb, size);
319
map_len = size;
320
}
321
322
new_dtb = alloc_bootmem(size);
323
memcpy(new_dtb, initial_boot_params, size);
324
early_iounmap(initial_boot_params, map_len);
325
326
initial_boot_params = new_dtb;
327
328
/* root level address cells */
329
of_scan_flat_dt(early_init_dt_scan_root, NULL);
330
331
unflatten_device_tree();
332
}
333
#else
334
static inline void x86_flattree_get_config(void) { }
335
#endif
336
337
void __init x86_dtb_init(void)
338
{
339
x86_flattree_get_config();
340
341
if (!of_have_populated_dt())
342
return;
343
344
dtb_setup_hpet();
345
dtb_apic_setup();
346
}
347
348
#ifdef CONFIG_X86_IO_APIC
349
350
struct of_ioapic_type {
351
u32 out_type;
352
u32 trigger;
353
u32 polarity;
354
};
355
356
static struct of_ioapic_type of_ioapic_type[] =
357
{
358
{
359
.out_type = IRQ_TYPE_EDGE_RISING,
360
.trigger = IOAPIC_EDGE,
361
.polarity = 1,
362
},
363
{
364
.out_type = IRQ_TYPE_LEVEL_LOW,
365
.trigger = IOAPIC_LEVEL,
366
.polarity = 0,
367
},
368
{
369
.out_type = IRQ_TYPE_LEVEL_HIGH,
370
.trigger = IOAPIC_LEVEL,
371
.polarity = 1,
372
},
373
{
374
.out_type = IRQ_TYPE_EDGE_FALLING,
375
.trigger = IOAPIC_EDGE,
376
.polarity = 0,
377
},
378
};
379
380
static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
381
u32 *out_hwirq, u32 *out_type)
382
{
383
struct mp_ioapic_gsi *gsi_cfg;
384
struct io_apic_irq_attr attr;
385
struct of_ioapic_type *it;
386
u32 line, idx, type;
387
388
if (intsize < 2)
389
return -EINVAL;
390
391
line = *intspec;
392
idx = (u32) id->priv;
393
gsi_cfg = mp_ioapic_gsi_routing(idx);
394
*out_hwirq = line + gsi_cfg->gsi_base;
395
396
intspec++;
397
type = *intspec;
398
399
if (type >= ARRAY_SIZE(of_ioapic_type))
400
return -EINVAL;
401
402
it = of_ioapic_type + type;
403
*out_type = it->out_type;
404
405
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
406
407
return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
408
}
409
410
static void __init ioapic_add_ofnode(struct device_node *np)
411
{
412
struct resource r;
413
int i, ret;
414
415
ret = of_address_to_resource(np, 0, &r);
416
if (ret) {
417
printk(KERN_ERR "Failed to obtain address for %s\n",
418
np->full_name);
419
return;
420
}
421
422
for (i = 0; i < nr_ioapics; i++) {
423
if (r.start == mpc_ioapic_addr(i)) {
424
struct irq_domain *id;
425
426
id = kzalloc(sizeof(*id), GFP_KERNEL);
427
BUG_ON(!id);
428
id->controller = np;
429
id->xlate = ioapic_xlate;
430
id->priv = (void *)i;
431
add_interrupt_host(id);
432
return;
433
}
434
}
435
printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
436
}
437
438
void __init x86_add_irq_domains(void)
439
{
440
struct device_node *dp;
441
442
if (!of_have_populated_dt())
443
return;
444
445
for_each_node_with_property(dp, "interrupt-controller") {
446
if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
447
ioapic_add_ofnode(dp);
448
}
449
}
450
#else
451
void __init x86_add_irq_domains(void) { }
452
#endif
453
454