ARM: OMAP5: Add the WakeupGen IP updates
authorSantosh Shilimkar <santosh.shilimkar@ti.com>
Wed, 9 May 2012 15:08:35 +0000 (20:38 +0530)
committerSantosh Shilimkar <santosh.shilimkar@ti.com>
Mon, 9 Jul 2012 13:44:39 +0000 (19:14 +0530)
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: R Sricharan <r.sricharan@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap4-sar-layout.h

index 548de90..b0fd16f 100644 (file)
 #ifndef 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_ENB_A_0                       0x10
 #define OMAP_WKG_ENB_B_0                       0x14
 #define OMAP_WKG_ENB_C_0                       0x18
 #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_B_1                       0x414
 #define OMAP_WKG_ENB_C_1                       0x418
 #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_1                   0x804
 #define OMAP_PTMSYNCREQ_MASK                   0xc00
@@ -28,4 +33,6 @@
 #define OMAP_TIMESTAMPCYCLEHI                  0xc0c
 
 extern int __init omap_wakeupgen_init(void);
+extern void __iomem *omap_get_wakeupgen_base(void);
+extern int omap_secure_apis_support(void);
 #endif
index 56c345b..414083b 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <mach/omap-wakeupgen.h>
 
 #include "common.h"
 
@@ -35,7 +37,8 @@ int platform_cpu_kill(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();
        dsb();
@@ -43,16 +46,27 @@ void __ref platform_cpu_die(unsigned int cpu)
        /*
         * we're ready for shutdown now, so do it
         */
-       if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
-               pr_err("Secure clear status failed\n");
+       if (omap_secure_apis_support()) {
+               if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
+                       pr_err("Secure clear status failed\n");
+       } else {
+               __raw_writel(0, base + OMAP_AUX_CORE_BOOT_0);
+       }
+
 
        for (;;) {
                /*
                 * Enter into low power state
                 */
                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
                         */
index deffbf1..badfe39 100644 (file)
@@ -26,6 +26,8 @@
 
 #include <mach/hardware.h>
 #include <mach/omap-secure.h>
+#include <mach/omap-wakeupgen.h>
+#include <asm/cputype.h>
 
 #include "iomap.h"
 #include "common.h"
@@ -73,6 +75,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        static struct clockdomain *cpu1_clkdm;
        static bool booted;
+       void __iomem *base = omap_get_wakeupgen_base();
+
        /*
         * Set synchronisation state between this boot processor
         * and the secondary one
@@ -85,7 +89,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * the AuxCoreBoot1 register is updated with cpu state
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       if (omap_secure_apis_support())
+               omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       else
+               __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);
+
        flush_cache_all();
        smp_wmb();
 
@@ -124,13 +132,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
+       void __iomem *base = omap_get_wakeupgen_base();
+
        /*
         * Write the address of secondary startup routine into the
         * AuxCoreBoot1 where ROM code will jump and start executing
         * on secondary core once out of WFE
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+       if (omap_secure_apis_support())
+               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();
 
        /*
index d811c77..05fdebf 100644 (file)
 #include "omap4-sar-layout.h"
 #include "common.h"
 
-#define NR_REG_BANKS           4
-#define MAX_IRQS               128
+#define MAX_NR_REG_BANKS       5
+#define MAX_IRQS               160
 #define WKG_MASK_ALL           0x00000000
 #define WKG_UNMASK_ALL         0xffffffff
 #define CPU_ENA_OFFSET         0x400
 #define CPU0_ID                        0x0
 #define CPU1_ID                        0x1
+#define OMAP4_NR_BANKS         4
+#define OMAP4_NR_IRQS          128
 
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 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.
@@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d)
 }
 
 #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)
 {
        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);
 }
 
@@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu)
 {
        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);
 }
 
@@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                wakeupgen_writel(reg, i, cpu);
 }
 
@@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
 #endif
 
 #ifdef CONFIG_CPU_PM
-/*
- * 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)
+static inline void omap4_irq_save_context(void)
 {
        u32 i, val;
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                return;
 
-       if (!sar_base)
-               sar_base = omap4_get_sar_ram_base();
-
-       for (i = 0; i < NR_REG_BANKS; i++) {
+       for (i = 0; i < irq_banks; i++) {
                /* Save the CPUx interrupt mask for IRQ 0 to 127 */
                val = wakeupgen_readl(i, 0);
                sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
@@ -254,6 +248,53 @@ static void irq_save_context(void)
        val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
        val |= SAR_BACKUP_STATUS_WAKEUPGEN;
        __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)
 static void irq_sar_clear(void)
 {
        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;
-       __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
+       __raw_writel(val, sar_base + offset);
 }
 
 /*
@@ -336,13 +382,25 @@ static struct notifier_block irq_notifier_block = {
 
 static void __init irq_pm_init(void)
 {
-       cpu_pm_register_notifier(&irq_notifier_block);
+       /* FIXME: Remove this when MPU OSWR support is added */
+       if (!soc_is_omap54xx())
+               cpu_pm_register_notifier(&irq_notifier_block);
 }
 #else
 static void __init irq_pm_init(void)
 {}
 #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.
  */
@@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void)
        }
 
        /* 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))
                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 */
-       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, CPU1_ID);
        }
@@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void)
         */
 
        /* 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_hotplug_init();
index fe5b545..e170fe8 100644 (file)
@@ -12,7 +12,7 @@
 #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_BANK2_OFFSET               0x1000
 #define PTMSYNCREQ_EN_OFFSET                   (SAR_BANK3_OFFSET + 0x6d0)
 #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