summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/pm-irq.c
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-01-05 08:44:01 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:42:04 -0800
commitebfa1b0c98bfdf6d2fc4f4e1354f803b02a4a953 (patch)
tree1468261b1506bb4be7f334ff28aee8e75cd37de4 /arch/arm/mach-tegra/pm-irq.c
parent0a35c3362060e8630917f00dfc1be5e977b57897 (diff)
arm: tegra: Add Tegra3 wakeup sources
Original-Change-Id: I77cb790db20cc8c8b67069130c0bc8724ba8934e Reviewed-on: http://git-master/r/15027 Tested-by: Jin Qian <jqian@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Original-Change-Id: I45764ed134dc0be2a21d7641692efb9c847a9b7a Rebase-Id: R0a34fc6fc83145c3720471d359216befb5d0bf5b
Diffstat (limited to 'arch/arm/mach-tegra/pm-irq.c')
-rw-r--r--arch/arm/mach-tegra/pm-irq.c99
1 files changed, 82 insertions, 17 deletions
diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c
index 198f6e379294..5bce13532301 100644
--- a/arch/arm/mach-tegra/pm-irq.c
+++ b/arch/arm/mach-tegra/pm-irq.c
@@ -36,15 +36,21 @@
#define PMC_WAKE_LEVEL 0x10
#define PMC_WAKE_STATUS 0x14
#define PMC_SW_WAKE_STATUS 0x18
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+#define PMC_WAKE2_MASK 0x160
+#define PMC_WAKE2_LEVEL 0x164
+#define PMC_WAKE2_STATUS 0x168
+#define PMC_SW_WAKE2_STATUS 0x16C
+#endif
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-static u32 tegra_lp0_wake_enb;
-static u32 tegra_lp0_wake_level;
-static u32 tegra_lp0_wake_level_any;
+static u64 tegra_lp0_wake_enb;
+static u64 tegra_lp0_wake_level;
+static u64 tegra_lp0_wake_level_any;
static int tegra_prevent_lp0;
-static unsigned int tegra_wake_irq_count[32];
+static unsigned int tegra_wake_irq_count[64];
static bool debug_lp0;
module_param(debug_lp0, bool, S_IRUGO | S_IWUSR);
@@ -65,6 +71,56 @@ static void pmc_32kwritel(u32 val, unsigned long offs)
udelay(130);
}
+static inline void write_pmc_wake_mask(u64 value)
+{
+ writel((u32)value, pmc + PMC_WAKE_MASK);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ __raw_writel((u32)(value >> 32), pmc + PMC_WAKE2_MASK);
+#endif
+}
+
+static inline u64 read_pmc_wake_level(void)
+{
+ u64 reg;
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ reg = readl(pmc + PMC_WAKE_LEVEL);
+#else
+ reg = __raw_readl(pmc + PMC_WAKE_LEVEL);
+ reg |= ((u64)readl(pmc + PMC_WAKE2_LEVEL)) << 32;
+#endif
+ return reg;
+}
+
+static inline void write_pmc_wake_level(u64 value)
+{
+ writel((u32)value, pmc + PMC_WAKE_LEVEL);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ __raw_writel((u32)(value >> 32), pmc + PMC_WAKE2_LEVEL);
+#endif
+}
+
+static inline u64 read_pmc_wake_status(void)
+{
+ u64 reg;
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ reg = readl(pmc + PMC_WAKE_STATUS);
+#else
+ reg = __raw_readl(pmc + PMC_WAKE_STATUS);
+ reg |= ((u64)readl(pmc + PMC_WAKE2_STATUS)) << 32;
+#endif
+ return reg;
+}
+
+static inline void clear_pmc_sw_wake_status(void)
+{
+ pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ pmc_32kwritel(0, PMC_SW_WAKE2_STATUS);
+#endif
+}
+
int tegra_pm_irq_set_wake(int irq, int enable)
{
int wake = tegra_irq_to_wake(irq);
@@ -85,9 +141,9 @@ int tegra_pm_irq_set_wake(int irq, int enable)
}
if (enable)
- tegra_lp0_wake_enb |= 1 << wake;
+ tegra_lp0_wake_enb |= 1ull << wake;
else
- tegra_lp0_wake_enb &= ~(1 << wake);
+ tegra_lp0_wake_enb &= ~(1ull << wake);
return 0;
}
@@ -122,12 +178,11 @@ int tegra_pm_irq_set_wake_type(int irq, int flow_type)
}
/* translate lp0 wake sources back into irqs to catch edge triggered wakeups */
-static void tegra_pm_irq_syscore_resume(void)
+static void tegra_pm_irq_syscore_resume_helper(unsigned long wake_status)
{
int wake;
int irq;
struct irq_desc *desc;
- unsigned long wake_status = readl(pmc + PMC_WAKE_STATUS);
for_each_set_bit(wake, &wake_status, sizeof(wake_status) * 8) {
irq = tegra_wake_to_irq(wake);
@@ -151,16 +206,26 @@ static void tegra_pm_irq_syscore_resume(void)
}
}
+static void tegra_pm_irq_syscore_resume(void)
+{
+ unsigned long long wake_status = read_pmc_wake_status();
+
+ tegra_pm_irq_syscore_resume_helper((unsigned long)wake_status);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ tegra_pm_irq_syscore_resume_helper((unsigned long)(wake_status >> 32));
+#endif
+}
+
/* set up lp0 wake sources */
static int tegra_pm_irq_syscore_suspend(void)
{
u32 temp;
- u32 status;
- u32 lvl;
- u32 wake_level;
- u32 wake_enb;
+ u64 status;
+ u64 lvl;
+ u64 wake_level;
+ u64 wake_enb;
- pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+ clear_pmc_sw_wake_status();
temp = readl(pmc + PMC_CTRL);
temp |= PMC_CTRL_LATCH_WAKEUPS;
@@ -169,9 +234,9 @@ static int tegra_pm_irq_syscore_suspend(void)
temp &= ~PMC_CTRL_LATCH_WAKEUPS;
pmc_32kwritel(temp, PMC_CTRL);
- status = readl(pmc + PMC_SW_WAKE_STATUS);
+ status = read_pmc_wake_status();
- lvl = readl(pmc + PMC_WAKE_LEVEL);
+ lvl = read_pmc_wake_level();
/* flip the wakeup trigger for any-edge triggered pads
* which are currently asserting as wakeups */
@@ -186,9 +251,9 @@ static int tegra_pm_irq_syscore_suspend(void)
wake_enb = 0xffffffff;
}
- writel(wake_level, pmc + PMC_WAKE_LEVEL);
+ write_pmc_wake_level(wake_level);
- writel(wake_enb, pmc + PMC_WAKE_MASK);
+ write_pmc_wake_mask(wake_enb);
return 0;
}