diff options
Diffstat (limited to 'arch/powerpc/platforms/86xx/mpc86xx_smp.c')
-rw-r--r-- | arch/powerpc/platforms/86xx/mpc86xx_smp.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c new file mode 100644 index 00000000000..944ec4b7141 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Author: Xianghua Xiao <x.xiao@freescale.com> | ||
3 | * Zhang Wei <wei.zhang@freescale.com> | ||
4 | * | ||
5 | * Copyright 2006 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/config.h> | ||
14 | #include <linux/stddef.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | |||
19 | #include <asm/pgtable.h> | ||
20 | #include <asm/page.h> | ||
21 | #include <asm/pci-bridge.h> | ||
22 | #include <asm-powerpc/mpic.h> | ||
23 | #include <asm/mpc86xx.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | |||
26 | #include <sysdev/fsl_soc.h> | ||
27 | |||
28 | #include "mpc86xx.h" | ||
29 | |||
30 | extern void __secondary_start_mpc86xx(void); | ||
31 | extern unsigned long __secondary_hold_acknowledge; | ||
32 | |||
33 | |||
34 | static void __init | ||
35 | smp_86xx_release_core(int nr) | ||
36 | { | ||
37 | void *mcm_vaddr; | ||
38 | unsigned long vaddr, pcr; | ||
39 | |||
40 | if (nr < 0 || nr >= NR_CPUS) | ||
41 | return; | ||
42 | |||
43 | /* | ||
44 | * Startup Core #nr. | ||
45 | */ | ||
46 | mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, | ||
47 | MPC86xx_MCM_SIZE); | ||
48 | vaddr = (unsigned long)mcm_vaddr + MCM_PORT_CONFIG_OFFSET; | ||
49 | pcr = in_be32((volatile unsigned *)vaddr); | ||
50 | pcr |= 1 << (nr + 24); | ||
51 | out_be32((volatile unsigned *)vaddr, pcr); | ||
52 | } | ||
53 | |||
54 | |||
55 | static void __init | ||
56 | smp_86xx_kick_cpu(int nr) | ||
57 | { | ||
58 | unsigned int save_vector; | ||
59 | unsigned long target, flags; | ||
60 | int n = 0; | ||
61 | volatile unsigned int *vector | ||
62 | = (volatile unsigned int *)(KERNELBASE + 0x100); | ||
63 | |||
64 | if (nr < 0 || nr >= NR_CPUS) | ||
65 | return; | ||
66 | |||
67 | pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr); | ||
68 | |||
69 | local_irq_save(flags); | ||
70 | local_irq_disable(); | ||
71 | |||
72 | /* Save reset vector */ | ||
73 | save_vector = *vector; | ||
74 | |||
75 | /* Setup fake reset vector to call __secondary_start_mpc86xx. */ | ||
76 | target = (unsigned long) __secondary_start_mpc86xx; | ||
77 | create_branch((unsigned long)vector, target, BRANCH_SET_LINK); | ||
78 | |||
79 | /* Kick that CPU */ | ||
80 | smp_86xx_release_core(nr); | ||
81 | |||
82 | /* Wait a bit for the CPU to take the exception. */ | ||
83 | while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000)) | ||
84 | mdelay(1); | ||
85 | |||
86 | /* Restore the exception vector */ | ||
87 | *vector = save_vector; | ||
88 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); | ||
89 | |||
90 | local_irq_restore(flags); | ||
91 | |||
92 | pr_debug("wait CPU #%d for %d msecs.\n", nr, n); | ||
93 | } | ||
94 | |||
95 | |||
96 | static void __init | ||
97 | smp_86xx_setup_cpu(int cpu_nr) | ||
98 | { | ||
99 | mpic_setup_this_cpu(); | ||
100 | } | ||
101 | |||
102 | |||
103 | struct smp_ops_t smp_86xx_ops = { | ||
104 | .message_pass = smp_mpic_message_pass, | ||
105 | .probe = smp_mpic_probe, | ||
106 | .kick_cpu = smp_86xx_kick_cpu, | ||
107 | .setup_cpu = smp_86xx_setup_cpu, | ||
108 | .take_timebase = smp_generic_take_timebase, | ||
109 | .give_timebase = smp_generic_give_timebase, | ||
110 | }; | ||
111 | |||
112 | |||
113 | void __init | ||
114 | mpc86xx_smp_init(void) | ||
115 | { | ||
116 | smp_ops = &smp_86xx_ops; | ||
117 | } | ||