diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-11-19 10:35:56 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-12-03 09:19:20 -0500 |
commit | d5b26db2cfcf09f28f4839c8c3484279cd5ea5b3 (patch) | |
tree | 67588db16d8e96596c23dce3f729d050fbb8803d /arch/powerpc/platforms | |
parent | 06b90969a7564fad888f67e9f7f4c3a51a16ef1d (diff) |
powerpc/85xx: Add support for SMP initialization
Added 85xx specifc smp_ops structure. We use ePAPR style boot release
and the MPIC for IPIs at this point.
Additionally added routines for secondary cpu entry and initializtion.
Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Trent Piepho <tpiepho@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/85xx/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/smp.c | 104 |
2 files changed, 106 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index cb3054e1001d..f0798c09980f 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -1,6 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 85xx linux kernel. | 2 | # Makefile for the PowerPC 85xx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_SMP) += smp.o | ||
5 | |||
4 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o | 6 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o |
5 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o | 7 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o |
6 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o | 8 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c new file mode 100644 index 000000000000..d652c713f496 --- /dev/null +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Author: Andy Fleming <afleming@freescale.com> | ||
3 | * Kumar Gala <galak@kernel.crashing.org> | ||
4 | * | ||
5 | * Copyright 2006-2008 Freescale Semiconductor Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/of.h> | ||
18 | |||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/pgtable.h> | ||
21 | #include <asm/page.h> | ||
22 | #include <asm/mpic.h> | ||
23 | #include <asm/cacheflush.h> | ||
24 | |||
25 | #include <sysdev/fsl_soc.h> | ||
26 | |||
27 | extern volatile unsigned long __secondary_hold_acknowledge; | ||
28 | extern void __early_start(void); | ||
29 | |||
30 | #define BOOT_ENTRY_ADDR_UPPER 0 | ||
31 | #define BOOT_ENTRY_ADDR_LOWER 1 | ||
32 | #define BOOT_ENTRY_R3_UPPER 2 | ||
33 | #define BOOT_ENTRY_R3_LOWER 3 | ||
34 | #define BOOT_ENTRY_RESV 4 | ||
35 | #define BOOT_ENTRY_PIR 5 | ||
36 | #define BOOT_ENTRY_R6_UPPER 6 | ||
37 | #define BOOT_ENTRY_R6_LOWER 7 | ||
38 | #define NUM_BOOT_ENTRY 8 | ||
39 | #define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32)) | ||
40 | |||
41 | static void __init | ||
42 | smp_85xx_kick_cpu(int nr) | ||
43 | { | ||
44 | unsigned long flags; | ||
45 | const u64 *cpu_rel_addr; | ||
46 | __iomem u32 *bptr_vaddr; | ||
47 | struct device_node *np; | ||
48 | int n = 0; | ||
49 | |||
50 | WARN_ON (nr < 0 || nr >= NR_CPUS); | ||
51 | |||
52 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); | ||
53 | |||
54 | local_irq_save(flags); | ||
55 | |||
56 | np = of_get_cpu_node(nr, NULL); | ||
57 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); | ||
58 | |||
59 | if (cpu_rel_addr == NULL) { | ||
60 | printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | /* Map the spin table */ | ||
65 | bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY); | ||
66 | |||
67 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); | ||
68 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); | ||
69 | |||
70 | /* Wait a bit for the CPU to ack. */ | ||
71 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) | ||
72 | mdelay(1); | ||
73 | |||
74 | iounmap(bptr_vaddr); | ||
75 | |||
76 | local_irq_restore(flags); | ||
77 | |||
78 | pr_debug("waited %d msecs for CPU #%d.\n", n, nr); | ||
79 | } | ||
80 | |||
81 | static void __init | ||
82 | smp_85xx_setup_cpu(int cpu_nr) | ||
83 | { | ||
84 | mpic_setup_this_cpu(); | ||
85 | |||
86 | /* Clear any pending timer interrupts */ | ||
87 | mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); | ||
88 | |||
89 | /* Enable decrementer interrupt */ | ||
90 | mtspr(SPRN_TCR, TCR_DIE); | ||
91 | } | ||
92 | |||
93 | struct smp_ops_t smp_85xx_ops = { | ||
94 | .message_pass = smp_mpic_message_pass, | ||
95 | .probe = smp_mpic_probe, | ||
96 | .kick_cpu = smp_85xx_kick_cpu, | ||
97 | .setup_cpu = smp_85xx_setup_cpu, | ||
98 | }; | ||
99 | |||
100 | void __init | ||
101 | mpc85xx_smp_init(void) | ||
102 | { | ||
103 | smp_ops = &smp_85xx_ops; | ||
104 | } | ||