x86: dtb: Add device tree support for HPET
[deliverable/linux.git] / arch / x86 / kernel / devicetree.c
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/slab.h>
13
14 #include <asm/hpet.h>
15 #include <asm/irq_controller.h>
16 #include <asm/apic.h>
17
18 __initdata u64 initial_dtb;
19 char __initdata cmd_line[COMMAND_LINE_SIZE];
20 static LIST_HEAD(irq_domains);
21 static DEFINE_RAW_SPINLOCK(big_irq_lock);
22
23 int __initdata of_ioapic;
24
25 void add_interrupt_host(struct irq_domain *ih)
26 {
27 unsigned long flags;
28
29 raw_spin_lock_irqsave(&big_irq_lock, flags);
30 list_add(&ih->l, &irq_domains);
31 raw_spin_unlock_irqrestore(&big_irq_lock, flags);
32 }
33
34 static struct irq_domain *get_ih_from_node(struct device_node *controller)
35 {
36 struct irq_domain *ih, *found = NULL;
37 unsigned long flags;
38
39 raw_spin_lock_irqsave(&big_irq_lock, flags);
40 list_for_each_entry(ih, &irq_domains, l) {
41 if (ih->controller == controller) {
42 found = ih;
43 break;
44 }
45 }
46 raw_spin_unlock_irqrestore(&big_irq_lock, flags);
47 return found;
48 }
49
50 unsigned int irq_create_of_mapping(struct device_node *controller,
51 const u32 *intspec, unsigned int intsize)
52 {
53 struct irq_domain *ih;
54 u32 virq, type;
55 int ret;
56
57 ih = get_ih_from_node(controller);
58 if (!ih)
59 return 0;
60 ret = ih->xlate(ih, intspec, intsize, &virq, &type);
61 if (ret)
62 return ret;
63 if (type == IRQ_TYPE_NONE)
64 return virq;
65 /* set the mask if it is different from current */
66 if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
67 set_irq_type(virq, type);
68 return virq;
69 }
70 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
71
72 unsigned long pci_address_to_pio(phys_addr_t address)
73 {
74 /*
75 * The ioport address can be directly used by inX / outX
76 */
77 BUG_ON(address >= (1 << 16));
78 return (unsigned long)address;
79 }
80 EXPORT_SYMBOL_GPL(pci_address_to_pio);
81
82 void __init early_init_dt_scan_chosen_arch(unsigned long node)
83 {
84 BUG();
85 }
86
87 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
88 {
89 BUG();
90 }
91
92 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
93 {
94 return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
95 }
96
97 void __init add_dtb(u64 data)
98 {
99 initial_dtb = data + offsetof(struct setup_data, data);
100 }
101
102 static void __init dtb_setup_hpet(void)
103 {
104 struct device_node *dn;
105 struct resource r;
106 int ret;
107
108 dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
109 if (!dn)
110 return;
111 ret = of_address_to_resource(dn, 0, &r);
112 if (ret) {
113 WARN_ON(1);
114 return;
115 }
116 hpet_address = r.start;
117 }
118
119 static void __init dtb_lapic_setup(void)
120 {
121 #ifdef CONFIG_X86_LOCAL_APIC
122 if (apic_force_enable())
123 return;
124
125 smp_found_config = 1;
126 pic_mode = 1;
127 /* Required for ioapic registration */
128 set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
129 if (boot_cpu_physical_apicid == -1U)
130 boot_cpu_physical_apicid = read_apic_id();
131
132 generic_processor_info(boot_cpu_physical_apicid,
133 GET_APIC_VERSION(apic_read(APIC_LVR)));
134 #endif
135 }
136
137 #ifdef CONFIG_X86_IO_APIC
138 static unsigned int ioapic_id;
139
140 static void __init dtb_add_ioapic(struct device_node *dn)
141 {
142 struct resource r;
143 int ret;
144
145 ret = of_address_to_resource(dn, 0, &r);
146 if (ret) {
147 printk(KERN_ERR "Can't obtain address from node %s.\n",
148 dn->full_name);
149 return;
150 }
151 mp_register_ioapic(++ioapic_id, r.start, gsi_top);
152 }
153
154 static void __init dtb_ioapic_setup(void)
155 {
156 struct device_node *dn;
157
158 if (!smp_found_config)
159 return;
160
161 for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
162 dtb_add_ioapic(dn);
163
164 if (nr_ioapics) {
165 of_ioapic = 1;
166 return;
167 }
168 printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
169 smp_found_config = 0;
170 }
171 #else
172 static void __init dtb_ioapic_setup(void) {}
173 #endif
174
175 static void __init dtb_apic_setup(void)
176 {
177 dtb_lapic_setup();
178 dtb_ioapic_setup();
179 }
180
181 void __init x86_dtb_find_config(void)
182 {
183 if (initial_dtb)
184 smp_found_config = 1;
185 else
186 printk(KERN_ERR "Missing device tree!.\n");
187 }
188
189 void __init x86_dtb_get_config(unsigned int unused)
190 {
191 u32 size, map_len;
192 void *new_dtb;
193
194 if (!initial_dtb)
195 return;
196
197 map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
198 (u64)sizeof(struct boot_param_header));
199
200 initial_boot_params = early_memremap(initial_dtb, map_len);
201 size = be32_to_cpu(initial_boot_params->totalsize);
202 if (map_len < size) {
203 early_iounmap(initial_boot_params, map_len);
204 initial_boot_params = early_memremap(initial_dtb, size);
205 map_len = size;
206 }
207
208 new_dtb = alloc_bootmem(size);
209 memcpy(new_dtb, initial_boot_params, size);
210 early_iounmap(initial_boot_params, map_len);
211
212 initial_boot_params = new_dtb;
213
214 /* root level address cells */
215 of_scan_flat_dt(early_init_dt_scan_root, NULL);
216
217 unflatten_device_tree();
218 dtb_setup_hpet();
219 dtb_apic_setup();
220 }
This page took 0.043712 seconds and 6 git commands to generate.