aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pSeries_smp.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2005-06-22 19:43:43 -0400
committerPaul Mackerras <paulus@samba.org>2005-06-22 19:43:43 -0400
commitcebf589c822b5de87098b57644024d16f8dbc1bb (patch)
tree609da06acf750cf91007bb0e2640dd0c3fd35ff8 /arch/ppc64/kernel/pSeries_smp.c
parentfef1c772fa154c16e0a54577e9ecb5480f7b937e (diff)
[PATCH] ppc64: Add driver for BPA interrupt controllers
Add support for the integrated interrupt controller on BPA CPUs. There is one of those for each SMT thread. The mapping of interrupt numbers to HW interrupt sources is described in arch/ppc64/kernel/bpa_iic.h. This version hardcodes the 'Spider' chip as the secondary interrupt controller. That is not really generic for the architecture, but at the moment it is the only secondary PIC that exists. A little more work will be needed on this as soon as we have boards with multiple external interrupt controllers. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64/kernel/pSeries_smp.c')
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 4203bd020c82..30154140f7e2 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * SMP support for pSeries machines. 2 * SMP support for pSeries and BPA machines.
3 * 3 *
4 * Dave Engebretsen, Peter Bergner, and 4 * Dave Engebretsen, Peter Bergner, and
5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com 5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
@@ -47,6 +47,7 @@
47#include <asm/pSeries_reconfig.h> 47#include <asm/pSeries_reconfig.h>
48 48
49#include "mpic.h" 49#include "mpic.h"
50#include "bpa_iic.h"
50 51
51#ifdef DEBUG 52#ifdef DEBUG
52#define DBG(fmt...) udbg_printf(fmt) 53#define DBG(fmt...) udbg_printf(fmt)
@@ -286,6 +287,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
286 return 1; 287 return 1;
287} 288}
288 289
290#ifdef CONFIG_XICS
289static inline void smp_xics_do_message(int cpu, int msg) 291static inline void smp_xics_do_message(int cpu, int msg)
290{ 292{
291 set_bit(msg, &xics_ipi_message[cpu].value); 293 set_bit(msg, &xics_ipi_message[cpu].value);
@@ -327,6 +329,37 @@ static void __devinit smp_xics_setup_cpu(int cpu)
327 cpu_clear(cpu, of_spin_map); 329 cpu_clear(cpu, of_spin_map);
328 330
329} 331}
332#endif /* CONFIG_XICS */
333#ifdef CONFIG_BPA_IIC
334static void smp_iic_message_pass(int target, int msg)
335{
336 unsigned int i;
337
338 if (target < NR_CPUS) {
339 iic_cause_IPI(target, msg);
340 } else {
341 for_each_online_cpu(i) {
342 if (target == MSG_ALL_BUT_SELF
343 && i == smp_processor_id())
344 continue;
345 iic_cause_IPI(i, msg);
346 }
347 }
348}
349
350static int __init smp_iic_probe(void)
351{
352 iic_request_IPIs();
353
354 return cpus_weight(cpu_possible_map);
355}
356
357static void __devinit smp_iic_setup_cpu(int cpu)
358{
359 if (cpu != boot_cpuid)
360 iic_setup_cpu();
361}
362#endif /* CONFIG_BPA_IIC */
330 363
331static DEFINE_SPINLOCK(timebase_lock); 364static DEFINE_SPINLOCK(timebase_lock);
332static unsigned long timebase = 0; 365static unsigned long timebase = 0;
@@ -381,14 +414,15 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
381 414
382 return 1; 415 return 1;
383} 416}
384 417#ifdef CONFIG_MPIC
385static struct smp_ops_t pSeries_mpic_smp_ops = { 418static struct smp_ops_t pSeries_mpic_smp_ops = {
386 .message_pass = smp_mpic_message_pass, 419 .message_pass = smp_mpic_message_pass,
387 .probe = smp_mpic_probe, 420 .probe = smp_mpic_probe,
388 .kick_cpu = smp_pSeries_kick_cpu, 421 .kick_cpu = smp_pSeries_kick_cpu,
389 .setup_cpu = smp_mpic_setup_cpu, 422 .setup_cpu = smp_mpic_setup_cpu,
390}; 423};
391 424#endif
425#ifdef CONFIG_XICS
392static struct smp_ops_t pSeries_xics_smp_ops = { 426static struct smp_ops_t pSeries_xics_smp_ops = {
393 .message_pass = smp_xics_message_pass, 427 .message_pass = smp_xics_message_pass,
394 .probe = smp_xics_probe, 428 .probe = smp_xics_probe,
@@ -396,6 +430,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
396 .setup_cpu = smp_xics_setup_cpu, 430 .setup_cpu = smp_xics_setup_cpu,
397 .cpu_bootable = smp_pSeries_cpu_bootable, 431 .cpu_bootable = smp_pSeries_cpu_bootable,
398}; 432};
433#endif
434#ifdef CONFIG_BPA_IIC
435static struct smp_ops_t bpa_iic_smp_ops = {
436 .message_pass = smp_iic_message_pass,
437 .probe = smp_iic_probe,
438 .kick_cpu = smp_pSeries_kick_cpu,
439 .setup_cpu = smp_iic_setup_cpu,
440 .cpu_bootable = smp_pSeries_cpu_bootable,
441};
442#endif
399 443
400/* This is called very early */ 444/* This is called very early */
401void __init smp_init_pSeries(void) 445void __init smp_init_pSeries(void)
@@ -404,10 +448,25 @@ void __init smp_init_pSeries(void)
404 448
405 DBG(" -> smp_init_pSeries()\n"); 449 DBG(" -> smp_init_pSeries()\n");
406 450
407 if (ppc64_interrupt_controller == IC_OPEN_PIC) 451 switch (ppc64_interrupt_controller) {
452#ifdef CONFIG_MPIC
453 case IC_OPEN_PIC:
408 smp_ops = &pSeries_mpic_smp_ops; 454 smp_ops = &pSeries_mpic_smp_ops;
409 else 455 break;
456#endif
457#ifdef CONFIG_XICS
458 case IC_PPC_XIC:
410 smp_ops = &pSeries_xics_smp_ops; 459 smp_ops = &pSeries_xics_smp_ops;
460 break;
461#endif
462#ifdef CONFIG_BPA_IIC
463 case IC_BPA_IIC:
464 smp_ops = &bpa_iic_smp_ops;
465 break;
466#endif
467 default:
468 panic("Invalid interrupt controller");
469 }
411 470
412#ifdef CONFIG_HOTPLUG_CPU 471#ifdef CONFIG_HOTPLUG_CPU
413 smp_ops->cpu_disable = pSeries_cpu_disable; 472 smp_ops->cpu_disable = pSeries_cpu_disable;