diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apb_timer.c | 60 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 69 | ||||
-rw-r--r-- | arch/x86/kernel/devicetree.c | 441 | ||||
-rw-r--r-- | arch/x86/kernel/e820.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/head_32.S | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/rtc.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 25 | ||||
-rw-r--r-- | arch/x86/kernel/x86_init.c | 1 |
11 files changed, 507 insertions, 125 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 34244b2cd880..62445ba2f8a8 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -66,9 +66,9 @@ obj-$(CONFIG_PCI) += early-quirks.o | |||
66 | apm-y := apm_32.o | 66 | apm-y := apm_32.o |
67 | obj-$(CONFIG_APM) += apm.o | 67 | obj-$(CONFIG_APM) += apm.o |
68 | obj-$(CONFIG_SMP) += smp.o | 68 | obj-$(CONFIG_SMP) += smp.o |
69 | obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o | 69 | obj-$(CONFIG_SMP) += smpboot.o |
70 | obj-$(CONFIG_SMP) += tsc_sync.o | ||
70 | obj-$(CONFIG_SMP) += setup_percpu.o | 71 | obj-$(CONFIG_SMP) += setup_percpu.o |
71 | obj-$(CONFIG_X86_64_SMP) += tsc_sync.o | ||
72 | obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o | 72 | obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o |
73 | obj-$(CONFIG_X86_MPPARSE) += mpparse.o | 73 | obj-$(CONFIG_X86_MPPARSE) += mpparse.o |
74 | obj-y += apic/ | 74 | obj-y += apic/ |
@@ -109,6 +109,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o | |||
109 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o | 109 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o |
110 | 110 | ||
111 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o | 111 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o |
112 | obj-$(CONFIG_OF) += devicetree.o | ||
112 | 113 | ||
113 | ### | 114 | ### |
114 | # 64 bit specific files | 115 | # 64 bit specific files |
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 51d4e1663066..1293c709ee85 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c | |||
@@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta, | |||
508 | return 0; | 508 | return 0; |
509 | } | 509 | } |
510 | 510 | ||
511 | /* | ||
512 | * APB timer clock is not in sync with pclk on Langwell, which translates to | ||
513 | * unreliable read value caused by sampling error. the error does not add up | ||
514 | * overtime and only happens when sampling a 0 as a 1 by mistake. so the time | ||
515 | * would go backwards. the following code is trying to prevent time traveling | ||
516 | * backwards. little bit paranoid. | ||
517 | */ | ||
518 | static cycle_t apbt_read_clocksource(struct clocksource *cs) | 511 | static cycle_t apbt_read_clocksource(struct clocksource *cs) |
519 | { | 512 | { |
520 | unsigned long t0, t1, t2; | 513 | unsigned long current_count; |
521 | static unsigned long last_read; | 514 | |
522 | 515 | current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE); | |
523 | bad_count: | 516 | return (cycle_t)~current_count; |
524 | t1 = apbt_readl(phy_cs_timer_id, | ||
525 | APBTMR_N_CURRENT_VALUE); | ||
526 | t2 = apbt_readl(phy_cs_timer_id, | ||
527 | APBTMR_N_CURRENT_VALUE); | ||
528 | if (unlikely(t1 < t2)) { | ||
529 | pr_debug("APBT: read current count error %lx:%lx:%lx\n", | ||
530 | t1, t2, t2 - t1); | ||
531 | goto bad_count; | ||
532 | } | ||
533 | /* | ||
534 | * check against cached last read, makes sure time does not go back. | ||
535 | * it could be a normal rollover but we will do tripple check anyway | ||
536 | */ | ||
537 | if (unlikely(t2 > last_read)) { | ||
538 | /* check if we have a normal rollover */ | ||
539 | unsigned long raw_intr_status = | ||
540 | apbt_readl_reg(APBTMRS_RAW_INT_STATUS); | ||
541 | /* | ||
542 | * cs timer interrupt is masked but raw intr bit is set if | ||
543 | * rollover occurs. then we read EOI reg to clear it. | ||
544 | */ | ||
545 | if (raw_intr_status & (1 << phy_cs_timer_id)) { | ||
546 | apbt_readl(phy_cs_timer_id, APBTMR_N_EOI); | ||
547 | goto out; | ||
548 | } | ||
549 | pr_debug("APB CS going back %lx:%lx:%lx ", | ||
550 | t2, last_read, t2 - last_read); | ||
551 | bad_count_x3: | ||
552 | pr_debug("triple check enforced\n"); | ||
553 | t0 = apbt_readl(phy_cs_timer_id, | ||
554 | APBTMR_N_CURRENT_VALUE); | ||
555 | udelay(1); | ||
556 | t1 = apbt_readl(phy_cs_timer_id, | ||
557 | APBTMR_N_CURRENT_VALUE); | ||
558 | udelay(1); | ||
559 | t2 = apbt_readl(phy_cs_timer_id, | ||
560 | APBTMR_N_CURRENT_VALUE); | ||
561 | if ((t2 > t1) || (t1 > t0)) { | ||
562 | printk(KERN_ERR "Error: APB CS tripple check failed\n"); | ||
563 | goto bad_count_x3; | ||
564 | } | ||
565 | } | ||
566 | out: | ||
567 | last_read = t2; | ||
568 | return (cycle_t)~t2; | ||
569 | } | 517 | } |
570 | 518 | ||
571 | static int apbt_clocksource_register(void) | 519 | static int apbt_clocksource_register(void) |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 562a8325cc1c..966673f44141 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -93,7 +93,7 @@ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID); | |||
93 | * | 93 | * |
94 | * +1=force-enable | 94 | * +1=force-enable |
95 | */ | 95 | */ |
96 | static int force_enable_local_apic; | 96 | static int force_enable_local_apic __initdata; |
97 | /* | 97 | /* |
98 | * APIC command line parameters | 98 | * APIC command line parameters |
99 | */ | 99 | */ |
@@ -163,7 +163,7 @@ early_param("nox2apic", setup_nox2apic); | |||
163 | unsigned long mp_lapic_addr; | 163 | unsigned long mp_lapic_addr; |
164 | int disable_apic; | 164 | int disable_apic; |
165 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ | 165 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
166 | static int disable_apic_timer __cpuinitdata; | 166 | static int disable_apic_timer __initdata; |
167 | /* Local APIC timer works in C2 */ | 167 | /* Local APIC timer works in C2 */ |
168 | int local_apic_timer_c2_ok; | 168 | int local_apic_timer_c2_ok; |
169 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | 169 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); |
@@ -187,29 +187,8 @@ static struct resource lapic_resource = { | |||
187 | 187 | ||
188 | static unsigned int calibration_result; | 188 | static unsigned int calibration_result; |
189 | 189 | ||
190 | static int lapic_next_event(unsigned long delta, | ||
191 | struct clock_event_device *evt); | ||
192 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
193 | struct clock_event_device *evt); | ||
194 | static void lapic_timer_broadcast(const struct cpumask *mask); | ||
195 | static void apic_pm_activate(void); | 190 | static void apic_pm_activate(void); |
196 | 191 | ||
197 | /* | ||
198 | * The local apic timer can be used for any function which is CPU local. | ||
199 | */ | ||
200 | static struct clock_event_device lapic_clockevent = { | ||
201 | .name = "lapic", | ||
202 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
203 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
204 | .shift = 32, | ||
205 | .set_mode = lapic_timer_setup, | ||
206 | .set_next_event = lapic_next_event, | ||
207 | .broadcast = lapic_timer_broadcast, | ||
208 | .rating = 100, | ||
209 | .irq = -1, | ||
210 | }; | ||
211 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
212 | |||
213 | static unsigned long apic_phys; | 192 | static unsigned long apic_phys; |
214 | 193 | ||
215 | /* | 194 | /* |
@@ -248,7 +227,7 @@ static int modern_apic(void) | |||
248 | * right after this call apic become NOOP driven | 227 | * right after this call apic become NOOP driven |
249 | * so apic->write/read doesn't do anything | 228 | * so apic->write/read doesn't do anything |
250 | */ | 229 | */ |
251 | void apic_disable(void) | 230 | static void __init apic_disable(void) |
252 | { | 231 | { |
253 | pr_info("APIC: switched to apic NOOP\n"); | 232 | pr_info("APIC: switched to apic NOOP\n"); |
254 | apic = &apic_noop; | 233 | apic = &apic_noop; |
@@ -292,23 +271,6 @@ u64 native_apic_icr_read(void) | |||
292 | return icr1 | ((u64)icr2 << 32); | 271 | return icr1 | ((u64)icr2 << 32); |
293 | } | 272 | } |
294 | 273 | ||
295 | /** | ||
296 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 | ||
297 | */ | ||
298 | void __cpuinit enable_NMI_through_LVT0(void) | ||
299 | { | ||
300 | unsigned int v; | ||
301 | |||
302 | /* unmask and set to NMI */ | ||
303 | v = APIC_DM_NMI; | ||
304 | |||
305 | /* Level triggered for 82489DX (32bit mode) */ | ||
306 | if (!lapic_is_integrated()) | ||
307 | v |= APIC_LVT_LEVEL_TRIGGER; | ||
308 | |||
309 | apic_write(APIC_LVT0, v); | ||
310 | } | ||
311 | |||
312 | #ifdef CONFIG_X86_32 | 274 | #ifdef CONFIG_X86_32 |
313 | /** | 275 | /** |
314 | * get_physical_broadcast - Get number of physical broadcast IDs | 276 | * get_physical_broadcast - Get number of physical broadcast IDs |
@@ -518,6 +480,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask) | |||
518 | #endif | 480 | #endif |
519 | } | 481 | } |
520 | 482 | ||
483 | |||
484 | /* | ||
485 | * The local apic timer can be used for any function which is CPU local. | ||
486 | */ | ||
487 | static struct clock_event_device lapic_clockevent = { | ||
488 | .name = "lapic", | ||
489 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
490 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
491 | .shift = 32, | ||
492 | .set_mode = lapic_timer_setup, | ||
493 | .set_next_event = lapic_next_event, | ||
494 | .broadcast = lapic_timer_broadcast, | ||
495 | .rating = 100, | ||
496 | .irq = -1, | ||
497 | }; | ||
498 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
499 | |||
521 | /* | 500 | /* |
522 | * Setup the local APIC timer for this CPU. Copy the initialized values | 501 | * Setup the local APIC timer for this CPU. Copy the initialized values |
523 | * of the boot CPU and register the clock event in the framework. | 502 | * of the boot CPU and register the clock event in the framework. |
@@ -1560,7 +1539,7 @@ static int __init detect_init_APIC(void) | |||
1560 | } | 1539 | } |
1561 | #else | 1540 | #else |
1562 | 1541 | ||
1563 | static int apic_verify(void) | 1542 | static int __init apic_verify(void) |
1564 | { | 1543 | { |
1565 | u32 features, h, l; | 1544 | u32 features, h, l; |
1566 | 1545 | ||
@@ -1585,7 +1564,7 @@ static int apic_verify(void) | |||
1585 | return 0; | 1564 | return 0; |
1586 | } | 1565 | } |
1587 | 1566 | ||
1588 | int apic_force_enable(void) | 1567 | int __init apic_force_enable(unsigned long addr) |
1589 | { | 1568 | { |
1590 | u32 h, l; | 1569 | u32 h, l; |
1591 | 1570 | ||
@@ -1601,7 +1580,7 @@ int apic_force_enable(void) | |||
1601 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | 1580 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { |
1602 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | 1581 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); |
1603 | l &= ~MSR_IA32_APICBASE_BASE; | 1582 | l &= ~MSR_IA32_APICBASE_BASE; |
1604 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | 1583 | l |= MSR_IA32_APICBASE_ENABLE | addr; |
1605 | wrmsr(MSR_IA32_APICBASE, l, h); | 1584 | wrmsr(MSR_IA32_APICBASE, l, h); |
1606 | enabled_via_apicbase = 1; | 1585 | enabled_via_apicbase = 1; |
1607 | } | 1586 | } |
@@ -1642,7 +1621,7 @@ static int __init detect_init_APIC(void) | |||
1642 | "you can enable it with \"lapic\"\n"); | 1621 | "you can enable it with \"lapic\"\n"); |
1643 | return -1; | 1622 | return -1; |
1644 | } | 1623 | } |
1645 | if (apic_force_enable()) | 1624 | if (apic_force_enable(APIC_DEFAULT_PHYS_BASE)) |
1646 | return -1; | 1625 | return -1; |
1647 | } else { | 1626 | } else { |
1648 | if (apic_verify()) | 1627 | if (apic_verify()) |
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c new file mode 100644 index 000000000000..7a8cebc9ff29 --- /dev/null +++ b/arch/x86/kernel/devicetree.c | |||
@@ -0,0 +1,441 @@ | |||
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 | |||
17 | #include <asm/hpet.h> | ||
18 | #include <asm/irq_controller.h> | ||
19 | #include <asm/apic.h> | ||
20 | #include <asm/pci_x86.h> | ||
21 | |||
22 | __initdata u64 initial_dtb; | ||
23 | char __initdata cmd_line[COMMAND_LINE_SIZE]; | ||
24 | static LIST_HEAD(irq_domains); | ||
25 | static DEFINE_RAW_SPINLOCK(big_irq_lock); | ||
26 | |||
27 | int __initdata of_ioapic; | ||
28 | |||
29 | #ifdef CONFIG_X86_IO_APIC | ||
30 | static void add_interrupt_host(struct irq_domain *ih) | ||
31 | { | ||
32 | unsigned long flags; | ||
33 | |||
34 | raw_spin_lock_irqsave(&big_irq_lock, flags); | ||
35 | list_add(&ih->l, &irq_domains); | ||
36 | raw_spin_unlock_irqrestore(&big_irq_lock, flags); | ||
37 | } | ||
38 | #endif | ||
39 | |||
40 | static struct irq_domain *get_ih_from_node(struct device_node *controller) | ||
41 | { | ||
42 | struct irq_domain *ih, *found = NULL; | ||
43 | unsigned long flags; | ||
44 | |||
45 | raw_spin_lock_irqsave(&big_irq_lock, flags); | ||
46 | list_for_each_entry(ih, &irq_domains, l) { | ||
47 | if (ih->controller == controller) { | ||
48 | found = ih; | ||
49 | break; | ||
50 | } | ||
51 | } | ||
52 | raw_spin_unlock_irqrestore(&big_irq_lock, flags); | ||
53 | return found; | ||
54 | } | ||
55 | |||
56 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
57 | const u32 *intspec, unsigned int intsize) | ||
58 | { | ||
59 | struct irq_domain *ih; | ||
60 | u32 virq, type; | ||
61 | int ret; | ||
62 | |||
63 | ih = get_ih_from_node(controller); | ||
64 | if (!ih) | ||
65 | return 0; | ||
66 | ret = ih->xlate(ih, intspec, intsize, &virq, &type); | ||
67 | if (ret) | ||
68 | return ret; | ||
69 | if (type == IRQ_TYPE_NONE) | ||
70 | return virq; | ||
71 | /* set the mask if it is different from current */ | ||
72 | if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) | ||
73 | set_irq_type(virq, type); | ||
74 | return virq; | ||
75 | } | ||
76 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
77 | |||
78 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
79 | { | ||
80 | /* | ||
81 | * The ioport address can be directly used by inX / outX | ||
82 | */ | ||
83 | BUG_ON(address >= (1 << 16)); | ||
84 | return (unsigned long)address; | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(pci_address_to_pio); | ||
87 | |||
88 | void __init early_init_dt_scan_chosen_arch(unsigned long node) | ||
89 | { | ||
90 | BUG(); | ||
91 | } | ||
92 | |||
93 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | ||
94 | { | ||
95 | BUG(); | ||
96 | } | ||
97 | |||
98 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | ||
99 | { | ||
100 | return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); | ||
101 | } | ||
102 | |||
103 | void __init add_dtb(u64 data) | ||
104 | { | ||
105 | initial_dtb = data + offsetof(struct setup_data, data); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * CE4100 ids. Will be moved to machine_device_initcall() once we have it. | ||
110 | */ | ||
111 | static struct of_device_id __initdata ce4100_ids[] = { | ||
112 | { .compatible = "intel,ce4100-cp", }, | ||
113 | { .compatible = "isa", }, | ||
114 | { .compatible = "pci", }, | ||
115 | {}, | ||
116 | }; | ||
117 | |||
118 | static int __init add_bus_probe(void) | ||
119 | { | ||
120 | if (!of_have_populated_dt()) | ||
121 | return 0; | ||
122 | |||
123 | return of_platform_bus_probe(NULL, ce4100_ids, NULL); | ||
124 | } | ||
125 | module_init(add_bus_probe); | ||
126 | |||
127 | #ifdef CONFIG_PCI | ||
128 | static int x86_of_pci_irq_enable(struct pci_dev *dev) | ||
129 | { | ||
130 | struct of_irq oirq; | ||
131 | u32 virq; | ||
132 | int ret; | ||
133 | u8 pin; | ||
134 | |||
135 | ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
136 | if (ret) | ||
137 | return ret; | ||
138 | if (!pin) | ||
139 | return 0; | ||
140 | |||
141 | ret = of_irq_map_pci(dev, &oirq); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | |||
145 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
146 | oirq.size); | ||
147 | if (virq == 0) | ||
148 | return -EINVAL; | ||
149 | dev->irq = virq; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void x86_of_pci_irq_disable(struct pci_dev *dev) | ||
154 | { | ||
155 | } | ||
156 | |||
157 | void __cpuinit x86_of_pci_init(void) | ||
158 | { | ||
159 | struct device_node *np; | ||
160 | |||
161 | pcibios_enable_irq = x86_of_pci_irq_enable; | ||
162 | pcibios_disable_irq = x86_of_pci_irq_disable; | ||
163 | |||
164 | for_each_node_by_type(np, "pci") { | ||
165 | const void *prop; | ||
166 | struct pci_bus *bus; | ||
167 | unsigned int bus_min; | ||
168 | struct device_node *child; | ||
169 | |||
170 | prop = of_get_property(np, "bus-range", NULL); | ||
171 | if (!prop) | ||
172 | continue; | ||
173 | bus_min = be32_to_cpup(prop); | ||
174 | |||
175 | bus = pci_find_bus(0, bus_min); | ||
176 | if (!bus) { | ||
177 | printk(KERN_ERR "Can't find a node for bus %s.\n", | ||
178 | np->full_name); | ||
179 | continue; | ||
180 | } | ||
181 | |||
182 | if (bus->self) | ||
183 | bus->self->dev.of_node = np; | ||
184 | else | ||
185 | bus->dev.of_node = np; | ||
186 | |||
187 | for_each_child_of_node(np, child) { | ||
188 | struct pci_dev *dev; | ||
189 | u32 devfn; | ||
190 | |||
191 | prop = of_get_property(child, "reg", NULL); | ||
192 | if (!prop) | ||
193 | continue; | ||
194 | |||
195 | devfn = (be32_to_cpup(prop) >> 8) & 0xff; | ||
196 | dev = pci_get_slot(bus, devfn); | ||
197 | if (!dev) | ||
198 | continue; | ||
199 | dev->dev.of_node = child; | ||
200 | pci_dev_put(dev); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | #endif | ||
205 | |||
206 | static void __init dtb_setup_hpet(void) | ||
207 | { | ||
208 | #ifdef CONFIG_HPET_TIMER | ||
209 | struct device_node *dn; | ||
210 | struct resource r; | ||
211 | int ret; | ||
212 | |||
213 | dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet"); | ||
214 | if (!dn) | ||
215 | return; | ||
216 | ret = of_address_to_resource(dn, 0, &r); | ||
217 | if (ret) { | ||
218 | WARN_ON(1); | ||
219 | return; | ||
220 | } | ||
221 | hpet_address = r.start; | ||
222 | #endif | ||
223 | } | ||
224 | |||
225 | static void __init dtb_lapic_setup(void) | ||
226 | { | ||
227 | #ifdef CONFIG_X86_LOCAL_APIC | ||
228 | struct device_node *dn; | ||
229 | struct resource r; | ||
230 | int ret; | ||
231 | |||
232 | dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic"); | ||
233 | if (!dn) | ||
234 | return; | ||
235 | |||
236 | ret = of_address_to_resource(dn, 0, &r); | ||
237 | if (WARN_ON(ret)) | ||
238 | return; | ||
239 | |||
240 | /* Did the boot loader setup the local APIC ? */ | ||
241 | if (!cpu_has_apic) { | ||
242 | if (apic_force_enable(r.start)) | ||
243 | return; | ||
244 | } | ||
245 | smp_found_config = 1; | ||
246 | pic_mode = 1; | ||
247 | register_lapic_address(r.start); | ||
248 | generic_processor_info(boot_cpu_physical_apicid, | ||
249 | GET_APIC_VERSION(apic_read(APIC_LVR))); | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | #ifdef CONFIG_X86_IO_APIC | ||
254 | static unsigned int ioapic_id; | ||
255 | |||
256 | static void __init dtb_add_ioapic(struct device_node *dn) | ||
257 | { | ||
258 | struct resource r; | ||
259 | int ret; | ||
260 | |||
261 | ret = of_address_to_resource(dn, 0, &r); | ||
262 | if (ret) { | ||
263 | printk(KERN_ERR "Can't obtain address from node %s.\n", | ||
264 | dn->full_name); | ||
265 | return; | ||
266 | } | ||
267 | mp_register_ioapic(++ioapic_id, r.start, gsi_top); | ||
268 | } | ||
269 | |||
270 | static void __init dtb_ioapic_setup(void) | ||
271 | { | ||
272 | struct device_node *dn; | ||
273 | |||
274 | for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic") | ||
275 | dtb_add_ioapic(dn); | ||
276 | |||
277 | if (nr_ioapics) { | ||
278 | of_ioapic = 1; | ||
279 | return; | ||
280 | } | ||
281 | printk(KERN_ERR "Error: No information about IO-APIC in OF.\n"); | ||
282 | } | ||
283 | #else | ||
284 | static void __init dtb_ioapic_setup(void) {} | ||
285 | #endif | ||
286 | |||
287 | static void __init dtb_apic_setup(void) | ||
288 | { | ||
289 | dtb_lapic_setup(); | ||
290 | dtb_ioapic_setup(); | ||
291 | } | ||
292 | |||
293 | #ifdef CONFIG_OF_FLATTREE | ||
294 | static void __init x86_flattree_get_config(void) | ||
295 | { | ||
296 | u32 size, map_len; | ||
297 | void *new_dtb; | ||
298 | |||
299 | if (!initial_dtb) | ||
300 | return; | ||
301 | |||
302 | map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), | ||
303 | (u64)sizeof(struct boot_param_header)); | ||
304 | |||
305 | initial_boot_params = early_memremap(initial_dtb, map_len); | ||
306 | size = be32_to_cpu(initial_boot_params->totalsize); | ||
307 | if (map_len < size) { | ||
308 | early_iounmap(initial_boot_params, map_len); | ||
309 | initial_boot_params = early_memremap(initial_dtb, size); | ||
310 | map_len = size; | ||
311 | } | ||
312 | |||
313 | new_dtb = alloc_bootmem(size); | ||
314 | memcpy(new_dtb, initial_boot_params, size); | ||
315 | early_iounmap(initial_boot_params, map_len); | ||
316 | |||
317 | initial_boot_params = new_dtb; | ||
318 | |||
319 | /* root level address cells */ | ||
320 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
321 | |||
322 | unflatten_device_tree(); | ||
323 | } | ||
324 | #else | ||
325 | static inline void x86_flattree_get_config(void) { } | ||
326 | #endif | ||
327 | |||
328 | void __init x86_dtb_init(void) | ||
329 | { | ||
330 | x86_flattree_get_config(); | ||
331 | |||
332 | if (!of_have_populated_dt()) | ||
333 | return; | ||
334 | |||
335 | dtb_setup_hpet(); | ||
336 | dtb_apic_setup(); | ||
337 | } | ||
338 | |||
339 | #ifdef CONFIG_X86_IO_APIC | ||
340 | |||
341 | struct of_ioapic_type { | ||
342 | u32 out_type; | ||
343 | u32 trigger; | ||
344 | u32 polarity; | ||
345 | }; | ||
346 | |||
347 | static struct of_ioapic_type of_ioapic_type[] = | ||
348 | { | ||
349 | { | ||
350 | .out_type = IRQ_TYPE_EDGE_RISING, | ||
351 | .trigger = IOAPIC_EDGE, | ||
352 | .polarity = 1, | ||
353 | }, | ||
354 | { | ||
355 | .out_type = IRQ_TYPE_LEVEL_LOW, | ||
356 | .trigger = IOAPIC_LEVEL, | ||
357 | .polarity = 0, | ||
358 | }, | ||
359 | { | ||
360 | .out_type = IRQ_TYPE_LEVEL_HIGH, | ||
361 | .trigger = IOAPIC_LEVEL, | ||
362 | .polarity = 1, | ||
363 | }, | ||
364 | { | ||
365 | .out_type = IRQ_TYPE_EDGE_FALLING, | ||
366 | .trigger = IOAPIC_EDGE, | ||
367 | .polarity = 0, | ||
368 | }, | ||
369 | }; | ||
370 | |||
371 | static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize, | ||
372 | u32 *out_hwirq, u32 *out_type) | ||
373 | { | ||
374 | struct io_apic_irq_attr attr; | ||
375 | struct of_ioapic_type *it; | ||
376 | u32 line, idx, type; | ||
377 | |||
378 | if (intsize < 2) | ||
379 | return -EINVAL; | ||
380 | |||
381 | line = *intspec; | ||
382 | idx = (u32) id->priv; | ||
383 | *out_hwirq = line + mp_gsi_routing[idx].gsi_base; | ||
384 | |||
385 | intspec++; | ||
386 | type = *intspec; | ||
387 | |||
388 | if (type >= ARRAY_SIZE(of_ioapic_type)) | ||
389 | return -EINVAL; | ||
390 | |||
391 | it = of_ioapic_type + type; | ||
392 | *out_type = it->out_type; | ||
393 | |||
394 | set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity); | ||
395 | |||
396 | return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr); | ||
397 | } | ||
398 | |||
399 | static void __init ioapic_add_ofnode(struct device_node *np) | ||
400 | { | ||
401 | struct resource r; | ||
402 | int i, ret; | ||
403 | |||
404 | ret = of_address_to_resource(np, 0, &r); | ||
405 | if (ret) { | ||
406 | printk(KERN_ERR "Failed to obtain address for %s\n", | ||
407 | np->full_name); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | for (i = 0; i < nr_ioapics; i++) { | ||
412 | if (r.start == mp_ioapics[i].apicaddr) { | ||
413 | struct irq_domain *id; | ||
414 | |||
415 | id = kzalloc(sizeof(*id), GFP_KERNEL); | ||
416 | BUG_ON(!id); | ||
417 | id->controller = np; | ||
418 | id->xlate = ioapic_xlate; | ||
419 | id->priv = (void *)i; | ||
420 | add_interrupt_host(id); | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name); | ||
425 | } | ||
426 | |||
427 | void __init x86_add_irq_domains(void) | ||
428 | { | ||
429 | struct device_node *dp; | ||
430 | |||
431 | if (!of_have_populated_dt()) | ||
432 | return; | ||
433 | |||
434 | for_each_node_with_property(dp, "interrupt-controller") { | ||
435 | if (of_device_is_compatible(dp, "intel,ce4100-ioapic")) | ||
436 | ioapic_add_ofnode(dp); | ||
437 | } | ||
438 | } | ||
439 | #else | ||
440 | void __init x86_add_irq_domains(void) { } | ||
441 | #endif | ||
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 0b5e2b546566..cdf5bfd9d4d5 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -667,21 +667,15 @@ __init void e820_setup_gap(void) | |||
667 | * boot_params.e820_map, others are passed via SETUP_E820_EXT node of | 667 | * boot_params.e820_map, others are passed via SETUP_E820_EXT node of |
668 | * linked list of struct setup_data, which is parsed here. | 668 | * linked list of struct setup_data, which is parsed here. |
669 | */ | 669 | */ |
670 | void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data) | 670 | void __init parse_e820_ext(struct setup_data *sdata) |
671 | { | 671 | { |
672 | u32 map_len; | ||
673 | int entries; | 672 | int entries; |
674 | struct e820entry *extmap; | 673 | struct e820entry *extmap; |
675 | 674 | ||
676 | entries = sdata->len / sizeof(struct e820entry); | 675 | entries = sdata->len / sizeof(struct e820entry); |
677 | map_len = sdata->len + sizeof(struct setup_data); | ||
678 | if (map_len > PAGE_SIZE) | ||
679 | sdata = early_ioremap(pa_data, map_len); | ||
680 | extmap = (struct e820entry *)(sdata->data); | 676 | extmap = (struct e820entry *)(sdata->data); |
681 | __append_e820_map(extmap, entries); | 677 | __append_e820_map(extmap, entries); |
682 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 678 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
683 | if (map_len > PAGE_SIZE) | ||
684 | early_iounmap(sdata, map_len); | ||
685 | printk(KERN_INFO "extended physical RAM map:\n"); | 679 | printk(KERN_INFO "extended physical RAM map:\n"); |
686 | e820_print_map("extended"); | 680 | e820_print_map("extended"); |
687 | } | 681 | } |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 187aa63b321f..ce0be7cd085e 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -137,7 +137,7 @@ ENTRY(startup_32) | |||
137 | movsl | 137 | movsl |
138 | 1: | 138 | 1: |
139 | 139 | ||
140 | #ifdef CONFIG_OLPC_OPENFIRMWARE | 140 | #ifdef CONFIG_OLPC |
141 | /* save OFW's pgdir table for later use when calling into OFW */ | 141 | /* save OFW's pgdir table for later use when calling into OFW */ |
142 | movl %cr3, %eax | 142 | movl %cr3, %eax |
143 | movl %eax, pa(olpc_ofw_pgd) | 143 | movl %eax, pa(olpc_ofw_pgd) |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 5ee693faa111..948a31eae75f 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -223,15 +223,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs) | |||
223 | 223 | ||
224 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 224 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
225 | 225 | ||
226 | #ifdef CONFIG_OF | ||
227 | unsigned int irq_create_of_mapping(struct device_node *controller, | ||
228 | const u32 *intspec, unsigned int intsize) | ||
229 | { | ||
230 | return intspec[0]; | ||
231 | } | ||
232 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | ||
233 | #endif | ||
234 | |||
235 | #ifdef CONFIG_HOTPLUG_CPU | 226 | #ifdef CONFIG_HOTPLUG_CPU |
236 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ | 227 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ |
237 | void fixup_irqs(void) | 228 | void fixup_irqs(void) |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index d30854b18d25..f470e4ef993e 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/setup.h> | 25 | #include <asm/setup.h> |
26 | #include <asm/i8259.h> | 26 | #include <asm/i8259.h> |
27 | #include <asm/traps.h> | 27 | #include <asm/traps.h> |
28 | #include <asm/prom.h> | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: | 31 | * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: |
@@ -120,6 +121,12 @@ void __init init_IRQ(void) | |||
120 | int i; | 121 | int i; |
121 | 122 | ||
122 | /* | 123 | /* |
124 | * We probably need a better place for this, but it works for | ||
125 | * now ... | ||
126 | */ | ||
127 | x86_add_irq_domains(); | ||
128 | |||
129 | /* | ||
123 | * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15. | 130 | * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15. |
124 | * If these IRQ's are handled by legacy interrupt-controllers like PIC, | 131 | * If these IRQ's are handled by legacy interrupt-controllers like PIC, |
125 | * then this configuration will likely be static after the boot. If | 132 | * then this configuration will likely be static after the boot. If |
@@ -308,7 +315,7 @@ void __init native_init_IRQ(void) | |||
308 | set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); | 315 | set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); |
309 | } | 316 | } |
310 | 317 | ||
311 | if (!acpi_ioapic) | 318 | if (!acpi_ioapic && !of_ioapic) |
312 | setup_irq(2, &irq2); | 319 | setup_irq(2, &irq2); |
313 | 320 | ||
314 | #ifdef CONFIG_X86_32 | 321 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 6f39cab052d5..3f2ad2640d85 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/acpi.h> | 6 | #include <linux/acpi.h> |
7 | #include <linux/bcd.h> | 7 | #include <linux/bcd.h> |
8 | #include <linux/pnp.h> | 8 | #include <linux/pnp.h> |
9 | #include <linux/of.h> | ||
9 | 10 | ||
10 | #include <asm/vsyscall.h> | 11 | #include <asm/vsyscall.h> |
11 | #include <asm/x86_init.h> | 12 | #include <asm/x86_init.h> |
@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void) | |||
236 | } | 237 | } |
237 | } | 238 | } |
238 | #endif | 239 | #endif |
240 | if (of_have_populated_dt()) | ||
241 | return 0; | ||
239 | 242 | ||
240 | platform_device_register(&rtc_device); | 243 | platform_device_register(&rtc_device); |
241 | dev_info(&rtc_device.dev, | 244 | dev_info(&rtc_device.dev, |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index c3a606c41ce0..b176f2b1f45d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -113,6 +113,7 @@ | |||
113 | #endif | 113 | #endif |
114 | #include <asm/mce.h> | 114 | #include <asm/mce.h> |
115 | #include <asm/alternative.h> | 115 | #include <asm/alternative.h> |
116 | #include <asm/prom.h> | ||
116 | 117 | ||
117 | /* | 118 | /* |
118 | * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. | 119 | * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. |
@@ -453,16 +454,30 @@ static void __init parse_setup_data(void) | |||
453 | return; | 454 | return; |
454 | pa_data = boot_params.hdr.setup_data; | 455 | pa_data = boot_params.hdr.setup_data; |
455 | while (pa_data) { | 456 | while (pa_data) { |
456 | data = early_memremap(pa_data, PAGE_SIZE); | 457 | u32 data_len, map_len; |
458 | |||
459 | map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), | ||
460 | (u64)sizeof(struct setup_data)); | ||
461 | data = early_memremap(pa_data, map_len); | ||
462 | data_len = data->len + sizeof(struct setup_data); | ||
463 | if (data_len > map_len) { | ||
464 | early_iounmap(data, map_len); | ||
465 | data = early_memremap(pa_data, data_len); | ||
466 | map_len = data_len; | ||
467 | } | ||
468 | |||
457 | switch (data->type) { | 469 | switch (data->type) { |
458 | case SETUP_E820_EXT: | 470 | case SETUP_E820_EXT: |
459 | parse_e820_ext(data, pa_data); | 471 | parse_e820_ext(data); |
472 | break; | ||
473 | case SETUP_DTB: | ||
474 | add_dtb(pa_data); | ||
460 | break; | 475 | break; |
461 | default: | 476 | default: |
462 | break; | 477 | break; |
463 | } | 478 | } |
464 | pa_data = data->next; | 479 | pa_data = data->next; |
465 | early_iounmap(data, PAGE_SIZE); | 480 | early_iounmap(data, map_len); |
466 | } | 481 | } |
467 | } | 482 | } |
468 | 483 | ||
@@ -1030,8 +1045,8 @@ void __init setup_arch(char **cmdline_p) | |||
1030 | * Read APIC and some other early information from ACPI tables. | 1045 | * Read APIC and some other early information from ACPI tables. |
1031 | */ | 1046 | */ |
1032 | acpi_boot_init(); | 1047 | acpi_boot_init(); |
1033 | |||
1034 | sfi_init(); | 1048 | sfi_init(); |
1049 | x86_dtb_init(); | ||
1035 | 1050 | ||
1036 | /* | 1051 | /* |
1037 | * get boot-time SMP configuration: | 1052 | * get boot-time SMP configuration: |
@@ -1065,6 +1080,8 @@ void __init setup_arch(char **cmdline_p) | |||
1065 | #endif | 1080 | #endif |
1066 | x86_init.oem.banner(); | 1081 | x86_init.oem.banner(); |
1067 | 1082 | ||
1083 | x86_init.timers.wallclock_init(); | ||
1084 | |||
1068 | mcheck_init(); | 1085 | mcheck_init(); |
1069 | 1086 | ||
1070 | local_irq_save(flags); | 1087 | local_irq_save(flags); |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index ceb2911aa439..c11514e9128b 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = { | |||
70 | .setup_percpu_clockev = setup_boot_APIC_clock, | 70 | .setup_percpu_clockev = setup_boot_APIC_clock, |
71 | .tsc_pre_init = x86_init_noop, | 71 | .tsc_pre_init = x86_init_noop, |
72 | .timer_init = hpet_time_init, | 72 | .timer_init = hpet_time_init, |
73 | .wallclock_init = x86_init_noop, | ||
73 | }, | 74 | }, |
74 | 75 | ||
75 | .iommu = { | 76 | .iommu = { |