Commit 247c445c authored by Santosh Shilimkar's avatar Santosh Shilimkar

ARM: OMAP5: Add the WakeupGen IP updates

OMAP4 and OMAP5 share same WakeupGen IP with below few udpates on OMAP5.
- Additional 32 interrupt support is added w.r.t OMAP4 design.
- The AUX CORE boot registers are now made accessible from non-secure SW.
- SAR offset are changed and PTMSYNC* registers are removed from SAR.

Patch updates the WakeupGen code accordingly.
Signed-off-by: default avatarR Sricharan <r.sricharan@ti.com>
Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
parent e17933c2
...@@ -11,15 +11,20 @@ ...@@ -11,15 +11,20 @@
#ifndef OMAP_ARCH_WAKEUPGEN_H #ifndef OMAP_ARCH_WAKEUPGEN_H
#define OMAP_ARCH_WAKEUPGEN_H #define OMAP_ARCH_WAKEUPGEN_H
/* OMAP4 and OMAP5 has same base address */
#define OMAP_WKUPGEN_BASE 0x48281000
#define OMAP_WKG_CONTROL_0 0x00 #define OMAP_WKG_CONTROL_0 0x00
#define OMAP_WKG_ENB_A_0 0x10 #define OMAP_WKG_ENB_A_0 0x10
#define OMAP_WKG_ENB_B_0 0x14 #define OMAP_WKG_ENB_B_0 0x14
#define OMAP_WKG_ENB_C_0 0x18 #define OMAP_WKG_ENB_C_0 0x18
#define OMAP_WKG_ENB_D_0 0x1c #define OMAP_WKG_ENB_D_0 0x1c
#define OMAP_WKG_ENB_E_0 0x20
#define OMAP_WKG_ENB_A_1 0x410 #define OMAP_WKG_ENB_A_1 0x410
#define OMAP_WKG_ENB_B_1 0x414 #define OMAP_WKG_ENB_B_1 0x414
#define OMAP_WKG_ENB_C_1 0x418 #define OMAP_WKG_ENB_C_1 0x418
#define OMAP_WKG_ENB_D_1 0x41c #define OMAP_WKG_ENB_D_1 0x41c
#define OMAP_WKG_ENB_E_1 0x420
#define OMAP_AUX_CORE_BOOT_0 0x800 #define OMAP_AUX_CORE_BOOT_0 0x800
#define OMAP_AUX_CORE_BOOT_1 0x804 #define OMAP_AUX_CORE_BOOT_1 0x804
#define OMAP_PTMSYNCREQ_MASK 0xc00 #define OMAP_PTMSYNCREQ_MASK 0xc00
...@@ -28,4 +33,6 @@ ...@@ -28,4 +33,6 @@
#define OMAP_TIMESTAMPCYCLEHI 0xc0c #define OMAP_TIMESTAMPCYCLEHI 0xc0c
extern int __init omap_wakeupgen_init(void); extern int __init omap_wakeupgen_init(void);
extern void __iomem *omap_get_wakeupgen_base(void);
extern int omap_secure_apis_support(void);
#endif #endif
...@@ -17,8 +17,10 @@ ...@@ -17,8 +17,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <mach/omap-wakeupgen.h>
#include "common.h" #include "common.h"
...@@ -35,7 +37,8 @@ int platform_cpu_kill(unsigned int cpu) ...@@ -35,7 +37,8 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void __ref platform_cpu_die(unsigned int cpu) void __ref platform_cpu_die(unsigned int cpu)
{ {
unsigned int this_cpu; unsigned int boot_cpu = 0;
void __iomem *base = omap_get_wakeupgen_base();
flush_cache_all(); flush_cache_all();
dsb(); dsb();
...@@ -43,16 +46,27 @@ void __ref platform_cpu_die(unsigned int cpu) ...@@ -43,16 +46,27 @@ void __ref platform_cpu_die(unsigned int cpu)
/* /*
* we're ready for shutdown now, so do it * we're ready for shutdown now, so do it
*/ */
if (omap_secure_apis_support()) {
if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
pr_err("Secure clear status failed\n"); pr_err("Secure clear status failed\n");
} else {
__raw_writel(0, base + OMAP_AUX_CORE_BOOT_0);
}
for (;;) { for (;;) {
/* /*
* Enter into low power state * Enter into low power state
*/ */
omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
this_cpu = smp_processor_id();
if (omap_read_auxcoreboot0() == this_cpu) { if (omap_secure_apis_support())
boot_cpu = omap_read_auxcoreboot0();
else
boot_cpu =
__raw_readl(base + OMAP_AUX_CORE_BOOT_0) >> 5;
if (boot_cpu == smp_processor_id()) {
/* /*
* OK, proper wakeup, we're done * OK, proper wakeup, we're done
*/ */
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/omap-secure.h> #include <mach/omap-secure.h>
#include <mach/omap-wakeupgen.h>
#include <asm/cputype.h>
#include "iomap.h" #include "iomap.h"
#include "common.h" #include "common.h"
...@@ -73,6 +75,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -73,6 +75,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{ {
static struct clockdomain *cpu1_clkdm; static struct clockdomain *cpu1_clkdm;
static bool booted; static bool booted;
void __iomem *base = omap_get_wakeupgen_base();
/* /*
* Set synchronisation state between this boot processor * Set synchronisation state between this boot processor
* and the secondary one * and the secondary one
...@@ -85,7 +89,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -85,7 +89,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
* the AuxCoreBoot1 register is updated with cpu state * the AuxCoreBoot1 register is updated with cpu state
* A barrier is added to ensure that write buffer is drained * A barrier is added to ensure that write buffer is drained
*/ */
if (omap_secure_apis_support())
omap_modify_auxcoreboot0(0x200, 0xfffffdff); omap_modify_auxcoreboot0(0x200, 0xfffffdff);
else
__raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);
flush_cache_all(); flush_cache_all();
smp_wmb(); smp_wmb();
...@@ -124,13 +132,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -124,13 +132,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init wakeup_secondary(void) static void __init wakeup_secondary(void)
{ {
void __iomem *base = omap_get_wakeupgen_base();
/* /*
* Write the address of secondary startup routine into the * Write the address of secondary startup routine into the
* AuxCoreBoot1 where ROM code will jump and start executing * AuxCoreBoot1 where ROM code will jump and start executing
* on secondary core once out of WFE * on secondary core once out of WFE
* A barrier is added to ensure that write buffer is drained * A barrier is added to ensure that write buffer is drained
*/ */
if (omap_secure_apis_support())
omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup)); omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
else
__raw_writel(virt_to_phys(omap5_secondary_startup),
base + OMAP_AUX_CORE_BOOT_1);
smp_wmb(); smp_wmb();
/* /*
......
...@@ -33,18 +33,23 @@ ...@@ -33,18 +33,23 @@
#include "omap4-sar-layout.h" #include "omap4-sar-layout.h"
#include "common.h" #include "common.h"
#define NR_REG_BANKS 4 #define MAX_NR_REG_BANKS 5
#define MAX_IRQS 128 #define MAX_IRQS 160
#define WKG_MASK_ALL 0x00000000 #define WKG_MASK_ALL 0x00000000
#define WKG_UNMASK_ALL 0xffffffff #define WKG_UNMASK_ALL 0xffffffff
#define CPU_ENA_OFFSET 0x400 #define CPU_ENA_OFFSET 0x400
#define CPU0_ID 0x0 #define CPU0_ID 0x0
#define CPU1_ID 0x1 #define CPU1_ID 0x1
#define OMAP4_NR_BANKS 4
#define OMAP4_NR_IRQS 128
static void __iomem *wakeupgen_base; static void __iomem *wakeupgen_base;
static void __iomem *sar_base; static void __iomem *sar_base;
static DEFINE_SPINLOCK(wakeupgen_lock); static DEFINE_SPINLOCK(wakeupgen_lock);
static unsigned int irq_target_cpu[NR_IRQS]; static unsigned int irq_target_cpu[NR_IRQS];
static unsigned int irq_banks = MAX_NR_REG_BANKS;
static unsigned int max_irqs = MAX_IRQS;
static unsigned int omap_secure_apis;
/* /*
* Static helper functions. * Static helper functions.
...@@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d) ...@@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d)
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks); static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
static void _wakeupgen_save_masks(unsigned int cpu) static void _wakeupgen_save_masks(unsigned int cpu)
{ {
u8 i; u8 i;
for (i = 0; i < NR_REG_BANKS; i++) for (i = 0; i < irq_banks; i++)
per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu); per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu);
} }
...@@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu) ...@@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu)
{ {
u8 i; u8 i;
for (i = 0; i < NR_REG_BANKS; i++) for (i = 0; i < irq_banks; i++)
wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu); wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
} }
...@@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg) ...@@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
{ {
u8 i; u8 i;
for (i = 0; i < NR_REG_BANKS; i++) for (i = 0; i < irq_banks; i++)
wakeupgen_writel(reg, i, cpu); wakeupgen_writel(reg, i, cpu);
} }
...@@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set) ...@@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
#endif #endif
#ifdef CONFIG_CPU_PM #ifdef CONFIG_CPU_PM
/* static inline void omap4_irq_save_context(void)
* Save WakeupGen interrupt context in SAR BANK3. Restore is done by
* ROM code. WakeupGen IP is integrated along with GIC to manage the
* interrupt wakeups from CPU low power states. It manages
* masking/unmasking of Shared peripheral interrupts(SPI). So the
* interrupt enable/disable control should be in sync and consistent
* at WakeupGen and GIC so that interrupts are not lost.
*/
static void irq_save_context(void)
{ {
u32 i, val; u32 i, val;
if (omap_rev() == OMAP4430_REV_ES1_0) if (omap_rev() == OMAP4430_REV_ES1_0)
return; return;
if (!sar_base) for (i = 0; i < irq_banks; i++) {
sar_base = omap4_get_sar_ram_base();
for (i = 0; i < NR_REG_BANKS; i++) {
/* Save the CPUx interrupt mask for IRQ 0 to 127 */ /* Save the CPUx interrupt mask for IRQ 0 to 127 */
val = wakeupgen_readl(i, 0); val = wakeupgen_readl(i, 0);
sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i); sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
...@@ -254,6 +248,53 @@ static void irq_save_context(void) ...@@ -254,6 +248,53 @@ static void irq_save_context(void)
val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
val |= SAR_BACKUP_STATUS_WAKEUPGEN; val |= SAR_BACKUP_STATUS_WAKEUPGEN;
__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
}
static inline void omap5_irq_save_context(void)
{
u32 i, val;
for (i = 0; i < irq_banks; i++) {
/* Save the CPUx interrupt mask for IRQ 0 to 159 */
val = wakeupgen_readl(i, 0);
sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i);
val = wakeupgen_readl(i, 1);
sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i);
sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
}
/* Save AuxBoot* registers */
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET);
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET);
/* Set the Backup Bit Mask status */
val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
val |= SAR_BACKUP_STATUS_WAKEUPGEN;
__raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
}
/*
* Save WakeupGen interrupt context in SAR BANK3. Restore is done by
* ROM code. WakeupGen IP is integrated along with GIC to manage the
* interrupt wakeups from CPU low power states. It manages
* masking/unmasking of Shared peripheral interrupts(SPI). So the
* interrupt enable/disable control should be in sync and consistent
* at WakeupGen and GIC so that interrupts are not lost.
*/
static void irq_save_context(void)
{
if (!sar_base)
sar_base = omap4_get_sar_ram_base();
if (soc_is_omap54xx())
omap5_irq_save_context();
else
omap4_irq_save_context();
} }
/* /*
...@@ -262,9 +303,14 @@ static void irq_save_context(void) ...@@ -262,9 +303,14 @@ static void irq_save_context(void)
static void irq_sar_clear(void) static void irq_sar_clear(void)
{ {
u32 val; u32 val;
val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); u32 offset = SAR_BACKUP_STATUS_OFFSET;
if (soc_is_omap54xx())
offset = OMAP5_SAR_BACKUP_STATUS_OFFSET;
val = __raw_readl(sar_base + offset);
val &= ~SAR_BACKUP_STATUS_WAKEUPGEN; val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); __raw_writel(val, sar_base + offset);
} }
/* /*
...@@ -336,6 +382,8 @@ static struct notifier_block irq_notifier_block = { ...@@ -336,6 +382,8 @@ static struct notifier_block irq_notifier_block = {
static void __init irq_pm_init(void) static void __init irq_pm_init(void)
{ {
/* FIXME: Remove this when MPU OSWR support is added */
if (!soc_is_omap54xx())
cpu_pm_register_notifier(&irq_notifier_block); cpu_pm_register_notifier(&irq_notifier_block);
} }
#else #else
...@@ -343,6 +391,16 @@ static void __init irq_pm_init(void) ...@@ -343,6 +391,16 @@ static void __init irq_pm_init(void)
{} {}
#endif #endif
void __iomem *omap_get_wakeupgen_base(void)
{
return wakeupgen_base;
}
int omap_secure_apis_support(void)
{
return omap_secure_apis;
}
/* /*
* Initialise the wakeupgen module. * Initialise the wakeupgen module.
*/ */
...@@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void) ...@@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void)
} }
/* Static mapping, never released */ /* Static mapping, never released */
wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K); wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
if (WARN_ON(!wakeupgen_base)) if (WARN_ON(!wakeupgen_base))
return -ENOMEM; return -ENOMEM;
if (cpu_is_omap44xx()) {
irq_banks = OMAP4_NR_BANKS;
max_irqs = OMAP4_NR_IRQS;
omap_secure_apis = 1;
}
/* Clear all IRQ bitmasks at wakeupGen level */ /* Clear all IRQ bitmasks at wakeupGen level */
for (i = 0; i < NR_REG_BANKS; i++) { for (i = 0; i < irq_banks; i++) {
wakeupgen_writel(0, i, CPU0_ID); wakeupgen_writel(0, i, CPU0_ID);
wakeupgen_writel(0, i, CPU1_ID); wakeupgen_writel(0, i, CPU1_ID);
} }
...@@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void) ...@@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void)
*/ */
/* Associate all the IRQs to boot CPU like GIC init does. */ /* Associate all the IRQs to boot CPU like GIC init does. */
for (i = 0; i < NR_IRQS; i++) for (i = 0; i < max_irqs; i++)
irq_target_cpu[i] = boot_cpu; irq_target_cpu[i] = boot_cpu;
irq_hotplug_init(); irq_hotplug_init();
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#define OMAP_ARCH_OMAP4_SAR_LAYOUT_H #define OMAP_ARCH_OMAP4_SAR_LAYOUT_H
/* /*
* SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE * SAR BANK offsets from base address OMAP44XX/54XX_SAR_RAM_BASE
*/ */
#define SAR_BANK1_OFFSET 0x0000 #define SAR_BANK1_OFFSET 0x0000
#define SAR_BANK2_OFFSET 0x1000 #define SAR_BANK2_OFFSET 0x1000
...@@ -47,4 +47,14 @@ ...@@ -47,4 +47,14 @@
#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0) #define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0)
#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10 #define SAR_BACKUP_STATUS_WAKEUPGEN 0x10
/* WakeUpGen save restore offset from OMAP54XX_SAR_RAM_BASE */
#define OMAP5_WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x8d4)
#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x8e8)
#define OMAP5_WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x8fc)
#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x910)
#define OMAP5_AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x924)
#define OMAP5_AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x928)
#define OMAP5_AMBA_IF_MODE_OFFSET (SAR_BANK3_OFFSET + 0x92c)
#define OMAP5_SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x800)
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment