diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap-smp.c')
-rw-r--r-- | arch/arm/mach-omap2/omap-smp.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index e99bc6cd471..c1bf3ef0ba0 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c | |||
@@ -24,17 +24,37 @@ | |||
24 | #include <asm/hardware/gic.h> | 24 | #include <asm/hardware/gic.h> |
25 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <mach/omap-secure.h> | ||
27 | 28 | ||
28 | #include "common.h" | 29 | #include "common.h" |
29 | 30 | ||
31 | #include "clockdomain.h" | ||
32 | |||
30 | /* SCU base address */ | 33 | /* SCU base address */ |
31 | static void __iomem *scu_base; | 34 | static void __iomem *scu_base; |
32 | 35 | ||
33 | static DEFINE_SPINLOCK(boot_lock); | 36 | static DEFINE_SPINLOCK(boot_lock); |
34 | 37 | ||
38 | void __iomem *omap4_get_scu_base(void) | ||
39 | { | ||
40 | return scu_base; | ||
41 | } | ||
42 | |||
35 | void __cpuinit platform_secondary_init(unsigned int cpu) | 43 | void __cpuinit platform_secondary_init(unsigned int cpu) |
36 | { | 44 | { |
37 | /* | 45 | /* |
46 | * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device. | ||
47 | * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA | ||
48 | * init and for CPU1, a secure PPA API provided. CPU0 must be ON | ||
49 | * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+. | ||
50 | * OMAP443X GP devices- SMP bit isn't accessible. | ||
51 | * OMAP446X GP devices - SMP bit access is enabled on both CPUs. | ||
52 | */ | ||
53 | if (cpu_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) | ||
54 | omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX, | ||
55 | 4, 0, 0, 0, 0, 0); | ||
56 | |||
57 | /* | ||
38 | * If any interrupts are already enabled for the primary | 58 | * If any interrupts are already enabled for the primary |
39 | * core (e.g. timer irq), then they will not have been enabled | 59 | * core (e.g. timer irq), then they will not have been enabled |
40 | * for us: do so | 60 | * for us: do so |
@@ -50,6 +70,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
50 | 70 | ||
51 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | 71 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) |
52 | { | 72 | { |
73 | static struct clockdomain *cpu1_clkdm; | ||
74 | static bool booted; | ||
53 | /* | 75 | /* |
54 | * Set synchronisation state between this boot processor | 76 | * Set synchronisation state between this boot processor |
55 | * and the secondary one | 77 | * and the secondary one |
@@ -65,6 +87,29 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
65 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); | 87 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); |
66 | flush_cache_all(); | 88 | flush_cache_all(); |
67 | smp_wmb(); | 89 | smp_wmb(); |
90 | |||
91 | if (!cpu1_clkdm) | ||
92 | cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); | ||
93 | |||
94 | /* | ||
95 | * The SGI(Software Generated Interrupts) are not wakeup capable | ||
96 | * from low power states. This is known limitation on OMAP4 and | ||
97 | * needs to be worked around by using software forced clockdomain | ||
98 | * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to | ||
99 | * software force wakeup. The clockdomain is then put back to | ||
100 | * hardware supervised mode. | ||
101 | * More details can be found in OMAP4430 TRM - Version J | ||
102 | * Section : | ||
103 | * 4.3.4.2 Power States of CPU0 and CPU1 | ||
104 | */ | ||
105 | if (booted) { | ||
106 | clkdm_wakeup(cpu1_clkdm); | ||
107 | clkdm_allow_idle(cpu1_clkdm); | ||
108 | } else { | ||
109 | dsb_sev(); | ||
110 | booted = true; | ||
111 | } | ||
112 | |||
68 | gic_raise_softirq(cpumask_of(cpu), 1); | 113 | gic_raise_softirq(cpumask_of(cpu), 1); |
69 | 114 | ||
70 | /* | 115 | /* |