aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/setup.c')
-rw-r--r--arch/powerpc/platforms/pseries/setup.c244
1 files changed, 133 insertions, 111 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 999509d28af8..54a52437265c 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -76,6 +76,9 @@
76#define DBG(fmt...) 76#define DBG(fmt...)
77#endif 77#endif
78 78
79/* move those away to a .h */
80extern void smp_init_pseries_mpic(void);
81extern void smp_init_pseries_xics(void);
79extern void find_udbg_vterm(void); 82extern void find_udbg_vterm(void);
80 83
81int fwnmi_active; /* TRUE if an FWNMI handler is present */ 84int fwnmi_active; /* TRUE if an FWNMI handler is present */
@@ -83,7 +86,7 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
83static void pseries_shared_idle_sleep(void); 86static void pseries_shared_idle_sleep(void);
84static void pseries_dedicated_idle_sleep(void); 87static void pseries_dedicated_idle_sleep(void);
85 88
86struct mpic *pSeries_mpic; 89static struct device_node *pSeries_mpic_node;
87 90
88static void pSeries_show_cpuinfo(struct seq_file *m) 91static void pSeries_show_cpuinfo(struct seq_file *m)
89{ 92{
@@ -118,63 +121,92 @@ static void __init fwnmi_init(void)
118 fwnmi_active = 1; 121 fwnmi_active = 1;
119} 122}
120 123
121static void __init pSeries_init_mpic(void) 124void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc,
125 struct pt_regs *regs)
122{ 126{
123 unsigned int *addrp; 127 unsigned int cascade_irq = i8259_irq(regs);
124 struct device_node *np; 128 if (cascade_irq != NO_IRQ)
125 unsigned long intack = 0; 129 generic_handle_irq(cascade_irq, regs);
126 130 desc->chip->eoi(irq);
127 /* All ISUs are setup, complete initialization */
128 mpic_init(pSeries_mpic);
129
130 /* Check what kind of cascade ACK we have */
131 if (!(np = of_find_node_by_name(NULL, "pci"))
132 || !(addrp = (unsigned int *)
133 get_property(np, "8259-interrupt-acknowledge", NULL)))
134 printk(KERN_ERR "Cannot find pci to get ack address\n");
135 else
136 intack = addrp[prom_n_addr_cells(np)-1];
137 of_node_put(np);
138
139 /* Setup the legacy interrupts & controller */
140 i8259_init(intack, 0);
141
142 /* Hook cascade to mpic */
143 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
144} 131}
145 132
146static void __init pSeries_setup_mpic(void) 133static void __init pseries_mpic_init_IRQ(void)
147{ 134{
135 struct device_node *np, *old, *cascade = NULL;
136 unsigned int *addrp;
137 unsigned long intack = 0;
148 unsigned int *opprop; 138 unsigned int *opprop;
149 unsigned long openpic_addr = 0; 139 unsigned long openpic_addr = 0;
150 unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS]; 140 unsigned int cascade_irq;
151 struct device_node *root; 141 int naddr, n, i, opplen;
152 int irq_count; 142 struct mpic *mpic;
153 143
154 /* Find the Open PIC if present */ 144 np = of_find_node_by_path("/");
155 root = of_find_node_by_path("/"); 145 naddr = prom_n_addr_cells(np);
156 opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); 146 opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen);
157 if (opprop != 0) { 147 if (opprop != 0) {
158 int n = prom_n_addr_cells(root); 148 openpic_addr = of_read_number(opprop, naddr);
159
160 for (openpic_addr = 0; n > 0; --n)
161 openpic_addr = (openpic_addr << 32) + *opprop++;
162 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 149 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
163 } 150 }
164 of_node_put(root); 151 of_node_put(np);
165 152
166 BUG_ON(openpic_addr == 0); 153 BUG_ON(openpic_addr == 0);
167 154
168 /* Get the sense values from OF */
169 prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
170
171 /* Setup the openpic driver */ 155 /* Setup the openpic driver */
172 irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ 156 mpic = mpic_alloc(pSeries_mpic_node, openpic_addr,
173 pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY, 157 MPIC_PRIMARY,
174 16, 16, irq_count, /* isu size, irq offset, irq count */ 158 16, 250, /* isu size, irq count */
175 NR_IRQS - 4, /* ipi offset */ 159 " MPIC ");
176 senses, irq_count, /* sense & sense size */ 160 BUG_ON(mpic == NULL);
177 " MPIC "); 161
162 /* Add ISUs */
163 opplen /= sizeof(u32);
164 for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
165 unsigned long isuaddr = of_read_number(opprop + i, naddr);
166 mpic_assign_isu(mpic, n, isuaddr);
167 }
168
169 /* All ISUs are setup, complete initialization */
170 mpic_init(mpic);
171
172 /* Look for cascade */
173 for_each_node_by_type(np, "interrupt-controller")
174 if (device_is_compatible(np, "chrp,iic")) {
175 cascade = np;
176 break;
177 }
178 if (cascade == NULL)
179 return;
180
181 cascade_irq = irq_of_parse_and_map(cascade, 0);
182 if (cascade == NO_IRQ) {
183 printk(KERN_ERR "xics: failed to map cascade interrupt");
184 return;
185 }
186
187 /* Check ACK type */
188 for (old = of_node_get(cascade); old != NULL ; old = np) {
189 np = of_get_parent(old);
190 of_node_put(old);
191 if (np == NULL)
192 break;
193 if (strcmp(np->name, "pci") != 0)
194 continue;
195 addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge",
196 NULL);
197 if (addrp == NULL)
198 continue;
199 naddr = prom_n_addr_cells(np);
200 intack = addrp[naddr-1];
201 if (naddr > 1)
202 intack |= ((unsigned long)addrp[naddr-2]) << 32;
203 }
204 if (intack)
205 printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n",
206 intack);
207 i8259_init(cascade, intack);
208 of_node_put(cascade);
209 set_irq_chained_handler(cascade_irq, pseries_8259_cascade);
178} 210}
179 211
180static void pseries_lpar_enable_pmcs(void) 212static void pseries_lpar_enable_pmcs(void)
@@ -192,23 +224,67 @@ static void pseries_lpar_enable_pmcs(void)
192 get_lppaca()->pmcregs_in_use = 1; 224 get_lppaca()->pmcregs_in_use = 1;
193} 225}
194 226
195static void __init pSeries_setup_arch(void) 227#ifdef CONFIG_KEXEC
228static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary)
196{ 229{
197 /* Fixup ppc_md depending on the type of interrupt controller */ 230 mpic_teardown_this_cpu(secondary);
198 if (ppc64_interrupt_controller == IC_OPEN_PIC) { 231}
199 ppc_md.init_IRQ = pSeries_init_mpic; 232
200 ppc_md.get_irq = mpic_get_irq; 233static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
201 /* Allocate the mpic now, so that find_and_init_phbs() can 234{
202 * fill the ISUs */ 235 /* Don't risk a hypervisor call if we're crashing */
203 pSeries_setup_mpic(); 236 if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
204 } else { 237 unsigned long vpa = __pa(get_lppaca());
205 ppc_md.init_IRQ = xics_init_IRQ; 238
206 ppc_md.get_irq = xics_get_irq; 239 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
240 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
241 "failed\n", smp_processor_id(),
242 hard_smp_processor_id());
243 }
207 } 244 }
245 xics_teardown_cpu(secondary);
246}
247#endif /* CONFIG_KEXEC */
208 248
249static void __init pseries_discover_pic(void)
250{
251 struct device_node *np;
252 char *typep;
253
254 for (np = NULL; (np = of_find_node_by_name(np,
255 "interrupt-controller"));) {
256 typep = (char *)get_property(np, "compatible", NULL);
257 if (strstr(typep, "open-pic")) {
258 pSeries_mpic_node = of_node_get(np);
259 ppc_md.init_IRQ = pseries_mpic_init_IRQ;
260 ppc_md.get_irq = mpic_get_irq;
261#ifdef CONFIG_KEXEC
262 ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic;
263#endif
264#ifdef CONFIG_SMP
265 smp_init_pseries_mpic();
266#endif
267 return;
268 } else if (strstr(typep, "ppc-xicp")) {
269 ppc_md.init_IRQ = xics_init_IRQ;
270#ifdef CONFIG_KEXEC
271 ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics;
272#endif
209#ifdef CONFIG_SMP 273#ifdef CONFIG_SMP
210 smp_init_pSeries(); 274 smp_init_pseries_xics();
211#endif 275#endif
276 return;
277 }
278 }
279 printk(KERN_ERR "pSeries_discover_pic: failed to recognize"
280 " interrupt-controller\n");
281}
282
283static void __init pSeries_setup_arch(void)
284{
285 /* Discover PIC type and setup ppc_md accordingly */
286 pseries_discover_pic();
287
212 /* openpic global configuration register (64-bit format). */ 288 /* openpic global configuration register (64-bit format). */
213 /* openpic Interrupt Source Unit pointer (64-bit format). */ 289 /* openpic Interrupt Source Unit pointer (64-bit format). */
214 /* python0 facility area (mmio) (64-bit format) REAL address. */ 290 /* python0 facility area (mmio) (64-bit format) REAL address. */
@@ -260,41 +336,11 @@ static int __init pSeries_init_panel(void)
260} 336}
261arch_initcall(pSeries_init_panel); 337arch_initcall(pSeries_init_panel);
262 338
263static void __init pSeries_discover_pic(void)
264{
265 struct device_node *np;
266 char *typep;
267
268 /*
269 * Setup interrupt mapping options that are needed for finish_device_tree
270 * to properly parse the OF interrupt tree & do the virtual irq mapping
271 */
272 __irq_offset_value = NUM_ISA_INTERRUPTS;
273 ppc64_interrupt_controller = IC_INVALID;
274 for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
275 typep = (char *)get_property(np, "compatible", NULL);
276 if (strstr(typep, "open-pic")) {
277 ppc64_interrupt_controller = IC_OPEN_PIC;
278 break;
279 } else if (strstr(typep, "ppc-xicp")) {
280 ppc64_interrupt_controller = IC_PPC_XIC;
281 break;
282 }
283 }
284 if (ppc64_interrupt_controller == IC_INVALID)
285 printk("pSeries_discover_pic: failed to recognize"
286 " interrupt-controller\n");
287
288}
289
290static void pSeries_mach_cpu_die(void) 339static void pSeries_mach_cpu_die(void)
291{ 340{
292 local_irq_disable(); 341 local_irq_disable();
293 idle_task_exit(); 342 idle_task_exit();
294 /* Some hardware requires clearing the CPPR, while other hardware does not 343 xics_teardown_cpu(0);
295 * it is safe either way
296 */
297 pSeriesLP_cppr_info(0, 0);
298 rtas_stop_self(); 344 rtas_stop_self();
299 /* Should never get here... */ 345 /* Should never get here... */
300 BUG(); 346 BUG();
@@ -332,8 +378,6 @@ static void __init pSeries_init_early(void)
332 378
333 iommu_init_early_pSeries(); 379 iommu_init_early_pSeries();
334 380
335 pSeries_discover_pic();
336
337 DBG(" <- pSeries_init_early()\n"); 381 DBG(" <- pSeries_init_early()\n");
338} 382}
339 383
@@ -505,27 +549,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
505 return PCI_PROBE_NORMAL; 549 return PCI_PROBE_NORMAL;
506} 550}
507 551
508#ifdef CONFIG_KEXEC
509static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
510{
511 /* Don't risk a hypervisor call if we're crashing */
512 if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
513 unsigned long vpa = __pa(get_lppaca());
514
515 if (unregister_vpa(hard_smp_processor_id(), vpa)) {
516 printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
517 "failed\n", smp_processor_id(),
518 hard_smp_processor_id());
519 }
520 }
521
522 if (ppc64_interrupt_controller == IC_OPEN_PIC)
523 mpic_teardown_this_cpu(secondary);
524 else
525 xics_teardown_cpu(secondary);
526}
527#endif
528
529define_machine(pseries) { 552define_machine(pseries) {
530 .name = "pSeries", 553 .name = "pSeries",
531 .probe = pSeries_probe, 554 .probe = pSeries_probe,
@@ -550,7 +573,6 @@ define_machine(pseries) {
550 .system_reset_exception = pSeries_system_reset_exception, 573 .system_reset_exception = pSeries_system_reset_exception,
551 .machine_check_exception = pSeries_machine_check_exception, 574 .machine_check_exception = pSeries_machine_check_exception,
552#ifdef CONFIG_KEXEC 575#ifdef CONFIG_KEXEC
553 .kexec_cpu_down = pseries_kexec_cpu_down,
554 .machine_kexec = default_machine_kexec, 576 .machine_kexec = default_machine_kexec,
555 .machine_kexec_prepare = default_machine_kexec_prepare, 577 .machine_kexec_prepare = default_machine_kexec_prepare,
556 .machine_crash_shutdown = default_machine_crash_shutdown, 578 .machine_crash_shutdown = default_machine_crash_shutdown,