Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 281871
b: refs/heads/master
c: 0f3cf2e
h: refs/heads/master
i:
  281869: 5c405c6
  281867: e489908
  281863: 1c700f9
  281855: 96046de
v: v3
  • Loading branch information
Santosh Shilimkar authored and Kevin Hilman committed Dec 8, 2011
1 parent 0ca838b commit 558bf99
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: da82ce57a45ac2f295415ed487b9aec051db4f7f
refs/heads/master: 0f3cf2ec81aeb4747624954bae2cc8decc48e12f
131 changes: 131 additions & 0 deletions trunk/arch/arm/mach-omap2/omap-wakeupgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/cpu_pm.h>

#include <asm/hardware/gic.h>

#include <mach/omap-wakeupgen.h>
#include <mach/omap-secure.h>

#include "omap4-sar-layout.h"
#include "common.h"

#define NR_REG_BANKS 4
#define MAX_IRQS 128
Expand All @@ -36,6 +42,7 @@
#define CPU1_ID 0x1

static void __iomem *wakeupgen_base;
static void __iomem *sar_base;
static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks);
static DEFINE_SPINLOCK(wakeupgen_lock);
static unsigned int irq_target_cpu[NR_IRQS];
Expand All @@ -55,6 +62,11 @@ static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu)
(cpu * CPU_ENA_OFFSET) + (idx * 4));
}

static inline void sar_writel(u32 val, u32 offset, u8 idx)
{
__raw_writel(val, sar_base + offset + (idx * 4));
}

static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
{
u8 i;
Expand Down Expand Up @@ -180,6 +192,93 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
spin_unlock_irqrestore(&wakeupgen_lock, flags);
}

#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)
{
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++) {
/* Save the CPUx interrupt mask for IRQ 0 to 127 */
val = wakeupgen_readl(i, 0);
sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
val = wakeupgen_readl(i, 1);
sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);

/*
* Disable the secure interrupts for CPUx. The restore
* code blindly restores secure and non-secure interrupt
* masks from SAR RAM. Secure interrupts are not suppose
* to be enabled from HLOS. So overwrite the SAR location
* so that the secure interrupt remains disabled.
*/
sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
}

/* Save AuxBoot* registers */
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

/* Save SyncReq generation logic */
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);

/* Save SyncReq generation logic */
val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
__raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET);
val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
__raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET);

/* Set the Backup Bit Mask status */
val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
val |= SAR_BACKUP_STATUS_WAKEUPGEN;
__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
}

/*
* Clear WakeupGen SAR backup status.
*/
void irq_sar_clear(void)
{
u32 val;
val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
__raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
}

/*
* Save GIC and Wakeupgen interrupt context using secure API
* for HS/EMU devices.
*/
static void irq_save_secure_context(void)
{
u32 ret;
ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
FLAG_START_CRITICAL,
0, 0, 0, 0, 0);
if (ret != API_HAL_RET_VALUE_OK)
pr_err("GIC and Wakeupgen context save failed\n");
}
#endif

#ifdef CONFIG_HOTPLUG_CPU
static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
Expand Down Expand Up @@ -210,6 +309,37 @@ static void __init irq_hotplug_init(void)
{}
#endif

#ifdef CONFIG_CPU_PM
static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{
switch (cmd) {
case CPU_CLUSTER_PM_ENTER:
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
irq_save_context();
else
irq_save_secure_context();
break;
case CPU_CLUSTER_PM_EXIT:
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
irq_sar_clear();
break;
}
return NOTIFY_OK;
}

static struct notifier_block irq_notifier_block = {
.notifier_call = irq_notifier,
};

static void __init irq_pm_init(void)
{
cpu_pm_register_notifier(&irq_notifier_block);
}
#else
static void __init irq_pm_init(void)
{}
#endif

/*
* Initialise the wakeupgen module.
*/
Expand Down Expand Up @@ -253,6 +383,7 @@ int __init omap_wakeupgen_init(void)
irq_target_cpu[i] = boot_cpu;

irq_hotplug_init();
irq_pm_init();

return 0;
}
15 changes: 15 additions & 0 deletions trunk/arch/arm/mach-omap2/omap4-sar-layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,19 @@
#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08

#define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500)
#define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504)
#define SAR_SECRAM_SAVED_AT_OFFSET (SAR_BANK3_OFFSET + 0x508)

/* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
#define WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x684)
#define WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x694)
#define WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6a4)
#define WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6b4)
#define AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x6c4)
#define AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x6c8)
#define PTMSYNCREQ_MASK_OFFSET (SAR_BANK3_OFFSET + 0x6cc)
#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0)
#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10

#endif

0 comments on commit 558bf99

Please sign in to comment.