diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-headsmp.S | 38 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-smp.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap4-common.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 2 |
6 files changed, 84 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index 7045e4d61ac3..70993a9fcb50 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h | |||
@@ -275,6 +275,7 @@ static inline void __iomem *omap4_get_scu_base(void) | |||
275 | #endif | 275 | #endif |
276 | 276 | ||
277 | extern void __init gic_init_irq(void); | 277 | extern void __init gic_init_irq(void); |
278 | extern void gic_dist_disable(void); | ||
278 | extern void omap_smc1(u32 fn, u32 arg); | 279 | extern void omap_smc1(u32 fn, u32 arg); |
279 | extern void __iomem *omap4_get_sar_ram_base(void); | 280 | extern void __iomem *omap4_get_sar_ram_base(void); |
280 | extern void omap_do_wfi(void); | 281 | extern void omap_do_wfi(void); |
@@ -282,6 +283,7 @@ extern void omap_do_wfi(void); | |||
282 | #ifdef CONFIG_SMP | 283 | #ifdef CONFIG_SMP |
283 | /* Needed for secondary core boot */ | 284 | /* Needed for secondary core boot */ |
284 | extern void omap_secondary_startup(void); | 285 | extern void omap_secondary_startup(void); |
286 | extern void omap_secondary_startup_4460(void); | ||
285 | extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); | 287 | extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); |
286 | extern void omap_auxcoreboot_addr(u32 cpu_addr); | 288 | extern void omap_auxcoreboot_addr(u32 cpu_addr); |
287 | extern u32 omap_read_auxcoreboot0(void); | 289 | extern u32 omap_read_auxcoreboot0(void); |
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index 502e3135aad3..0ea09faf327b 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/linkage.h> | 18 | #include <linux/linkage.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | 20 | ||
21 | #include "omap44xx.h" | ||
22 | |||
21 | __CPUINIT | 23 | __CPUINIT |
22 | 24 | ||
23 | /* Physical address needed since MMU not enabled yet on secondary core */ | 25 | /* Physical address needed since MMU not enabled yet on secondary core */ |
@@ -64,3 +66,39 @@ hold: ldr r12,=0x103 | |||
64 | b secondary_startup | 66 | b secondary_startup |
65 | ENDPROC(omap_secondary_startup) | 67 | ENDPROC(omap_secondary_startup) |
66 | 68 | ||
69 | ENTRY(omap_secondary_startup_4460) | ||
70 | hold_2: ldr r12,=0x103 | ||
71 | dsb | ||
72 | smc #0 @ read from AuxCoreBoot0 | ||
73 | mov r0, r0, lsr #9 | ||
74 | mrc p15, 0, r4, c0, c0, 5 | ||
75 | and r4, r4, #0x0f | ||
76 | cmp r0, r4 | ||
77 | bne hold_2 | ||
78 | |||
79 | /* | ||
80 | * GIC distributor control register has changed between | ||
81 | * CortexA9 r1pX and r2pX. The Control Register secure | ||
82 | * banked version is now composed of 2 bits: | ||
83 | * bit 0 == Secure Enable | ||
84 | * bit 1 == Non-Secure Enable | ||
85 | * The Non-Secure banked register has not changed | ||
86 | * Because the ROM Code is based on the r1pX GIC, the CPU1 | ||
87 | * GIC restoration will cause a problem to CPU0 Non-Secure SW. | ||
88 | * The workaround must be: | ||
89 | * 1) Before doing the CPU1 wakeup, CPU0 must disable | ||
90 | * the GIC distributor | ||
91 | * 2) CPU1 must re-enable the GIC distributor on | ||
92 | * it's wakeup path. | ||
93 | */ | ||
94 | ldr r1, =OMAP44XX_GIC_DIST_BASE | ||
95 | ldr r0, [r1] | ||
96 | orr r0, #1 | ||
97 | str r0, [r1] | ||
98 | |||
99 | /* | ||
100 | * we've been released from the wait loop,secondary_stack | ||
101 | * should now contain the SVC stack for this core | ||
102 | */ | ||
103 | b secondary_startup | ||
104 | ENDPROC(omap_secondary_startup_4460) | ||
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index ff4e6a0e9c7c..c8bc3ad85f68 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c | |||
@@ -67,6 +67,7 @@ struct omap4_cpu_pm_info { | |||
67 | void __iomem *scu_sar_addr; | 67 | void __iomem *scu_sar_addr; |
68 | void __iomem *wkup_sar_addr; | 68 | void __iomem *wkup_sar_addr; |
69 | void __iomem *l2x0_sar_addr; | 69 | void __iomem *l2x0_sar_addr; |
70 | void (*secondary_startup)(void); | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); | 73 | static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); |
@@ -299,6 +300,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
299 | int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) | 300 | int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) |
300 | { | 301 | { |
301 | unsigned int cpu_state = 0; | 302 | unsigned int cpu_state = 0; |
303 | struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); | ||
302 | 304 | ||
303 | if (omap_rev() == OMAP4430_REV_ES1_0) | 305 | if (omap_rev() == OMAP4430_REV_ES1_0) |
304 | return -ENXIO; | 306 | return -ENXIO; |
@@ -308,7 +310,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) | |||
308 | 310 | ||
309 | clear_cpu_prev_pwrst(cpu); | 311 | clear_cpu_prev_pwrst(cpu); |
310 | set_cpu_next_pwrst(cpu, power_state); | 312 | set_cpu_next_pwrst(cpu, power_state); |
311 | set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup)); | 313 | set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); |
312 | scu_pwrst_prepare(cpu, power_state); | 314 | scu_pwrst_prepare(cpu, power_state); |
313 | 315 | ||
314 | /* | 316 | /* |
@@ -359,6 +361,11 @@ int __init omap4_mpuss_init(void) | |||
359 | pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; | 361 | pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; |
360 | pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; | 362 | pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; |
361 | pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; | 363 | pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; |
364 | if (cpu_is_omap446x()) | ||
365 | pm_info->secondary_startup = omap_secondary_startup_4460; | ||
366 | else | ||
367 | pm_info->secondary_startup = omap_secondary_startup; | ||
368 | |||
362 | pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); | 369 | pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); |
363 | if (!pm_info->pwrdm) { | 370 | if (!pm_info->pwrdm) { |
364 | pr_err("Lookup failed for CPU1 pwrdm\n"); | 371 | pr_err("Lookup failed for CPU1 pwrdm\n"); |
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 4d05fa8a4e48..7d9c0e3fedc4 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "iomap.h" | 32 | #include "iomap.h" |
33 | #include "common.h" | 33 | #include "common.h" |
34 | #include "clockdomain.h" | 34 | #include "clockdomain.h" |
35 | #include "pm.h" | ||
35 | 36 | ||
36 | #define CPU_MASK 0xff0ffff0 | 37 | #define CPU_MASK 0xff0ffff0 |
37 | #define CPU_CORTEX_A9 0x410FC090 | 38 | #define CPU_CORTEX_A9 0x410FC090 |
@@ -118,6 +119,24 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * | |||
118 | * 4.3.4.2 Power States of CPU0 and CPU1 | 119 | * 4.3.4.2 Power States of CPU0 and CPU1 |
119 | */ | 120 | */ |
120 | if (booted) { | 121 | if (booted) { |
122 | /* | ||
123 | * GIC distributor control register has changed between | ||
124 | * CortexA9 r1pX and r2pX. The Control Register secure | ||
125 | * banked version is now composed of 2 bits: | ||
126 | * bit 0 == Secure Enable | ||
127 | * bit 1 == Non-Secure Enable | ||
128 | * The Non-Secure banked register has not changed | ||
129 | * Because the ROM Code is based on the r1pX GIC, the CPU1 | ||
130 | * GIC restoration will cause a problem to CPU0 Non-Secure SW. | ||
131 | * The workaround must be: | ||
132 | * 1) Before doing the CPU1 wakeup, CPU0 must disable | ||
133 | * the GIC distributor | ||
134 | * 2) CPU1 must re-enable the GIC distributor on | ||
135 | * it's wakeup path. | ||
136 | */ | ||
137 | if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) | ||
138 | gic_dist_disable(); | ||
139 | |||
121 | clkdm_wakeup(cpu1_clkdm); | 140 | clkdm_wakeup(cpu1_clkdm); |
122 | clkdm_allow_idle(cpu1_clkdm); | 141 | clkdm_allow_idle(cpu1_clkdm); |
123 | } else { | 142 | } else { |
@@ -138,7 +157,14 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * | |||
138 | 157 | ||
139 | static void __init wakeup_secondary(void) | 158 | static void __init wakeup_secondary(void) |
140 | { | 159 | { |
160 | void *startup_addr = omap_secondary_startup; | ||
141 | void __iomem *base = omap_get_wakeupgen_base(); | 161 | void __iomem *base = omap_get_wakeupgen_base(); |
162 | |||
163 | if (cpu_is_omap446x()) { | ||
164 | startup_addr = omap_secondary_startup_4460; | ||
165 | pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD; | ||
166 | } | ||
167 | |||
142 | /* | 168 | /* |
143 | * Write the address of secondary startup routine into the | 169 | * Write the address of secondary startup routine into the |
144 | * AuxCoreBoot1 where ROM code will jump and start executing | 170 | * AuxCoreBoot1 where ROM code will jump and start executing |
@@ -146,7 +172,7 @@ static void __init wakeup_secondary(void) | |||
146 | * A barrier is added to ensure that write buffer is drained | 172 | * A barrier is added to ensure that write buffer is drained |
147 | */ | 173 | */ |
148 | if (omap_secure_apis_support()) | 174 | if (omap_secure_apis_support()) |
149 | omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup)); | 175 | omap_auxcoreboot_addr(virt_to_phys(startup_addr)); |
150 | else | 176 | else |
151 | __raw_writel(virt_to_phys(omap5_secondary_startup), | 177 | __raw_writel(virt_to_phys(omap5_secondary_startup), |
152 | base + OMAP_AUX_CORE_BOOT_1); | 178 | base + OMAP_AUX_CORE_BOOT_1); |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index e1f289748c5d..72cf396a0fc2 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
@@ -41,6 +41,7 @@ static void __iomem *l2cache_base; | |||
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | static void __iomem *sar_ram_base; | 43 | static void __iomem *sar_ram_base; |
44 | static void __iomem *gic_dist_base_addr; | ||
44 | 45 | ||
45 | #ifdef CONFIG_OMAP4_ERRATA_I688 | 46 | #ifdef CONFIG_OMAP4_ERRATA_I688 |
46 | /* Used to implement memory barrier on DRAM path */ | 47 | /* Used to implement memory barrier on DRAM path */ |
@@ -95,7 +96,6 @@ void __init omap_barriers_init(void) | |||
95 | void __init gic_init_irq(void) | 96 | void __init gic_init_irq(void) |
96 | { | 97 | { |
97 | void __iomem *omap_irq_base; | 98 | void __iomem *omap_irq_base; |
98 | void __iomem *gic_dist_base_addr; | ||
99 | 99 | ||
100 | /* Static mapping, never released */ | 100 | /* Static mapping, never released */ |
101 | gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); | 101 | gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); |
@@ -110,6 +110,12 @@ void __init gic_init_irq(void) | |||
110 | gic_init(0, 29, gic_dist_base_addr, omap_irq_base); | 110 | gic_init(0, 29, gic_dist_base_addr, omap_irq_base); |
111 | } | 111 | } |
112 | 112 | ||
113 | void gic_dist_disable(void) | ||
114 | { | ||
115 | if (gic_dist_base_addr) | ||
116 | __raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL); | ||
117 | } | ||
118 | |||
113 | #ifdef CONFIG_CACHE_L2X0 | 119 | #ifdef CONFIG_CACHE_L2X0 |
114 | 120 | ||
115 | void __iomem *omap4_get_l2cache_base(void) | 121 | void __iomem *omap4_get_l2cache_base(void) |
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index f76a0d0f839f..fc3c96d5e013 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h | |||
@@ -102,6 +102,8 @@ extern void enable_omap3630_toggle_l2_on_restore(void); | |||
102 | static inline void enable_omap3630_toggle_l2_on_restore(void) { } | 102 | static inline void enable_omap3630_toggle_l2_on_restore(void) { } |
103 | #endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ | 103 | #endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ |
104 | 104 | ||
105 | #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0) | ||
106 | |||
105 | #if defined(CONFIG_ARCH_OMAP4) | 107 | #if defined(CONFIG_ARCH_OMAP4) |
106 | extern u16 pm44xx_errata; | 108 | extern u16 pm44xx_errata; |
107 | #define IS_PM44XX_ERRATUM(id) (pm44xx_errata & (id)) | 109 | #define IS_PM44XX_ERRATUM(id) (pm44xx_errata & (id)) |