summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/timer-t2.c
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@nvidia.com>2011-07-25 14:34:22 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:46:54 -0800
commit57110c69e55510ff6157511080f4364bbb88a509 (patch)
treeb36cf5334133f1c91e1707c237ce5ad4280a8751 /arch/arm/mach-tegra/timer-t2.c
parent51fd52a75de1c106104fb9ea655a9972e386d507 (diff)
ARM: tegra2: Update LP2 timers
Clean up conditionals for LP2 timers Register an interrupt handler for the LP2 timer Change-Id: I6ee6b6971f45f33d5d9295a462778af1d1c9843b Signed-off-by: Scott Williams <scwilliams@nvidia.com> DW: Split into logical changes Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R6cec04d1c66dc3af22cb9ab7afe0dffaba891cea
Diffstat (limited to 'arch/arm/mach-tegra/timer-t2.c')
-rw-r--r--arch/arm/mach-tegra/timer-t2.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/arch/arm/mach-tegra/timer-t2.c b/arch/arm/mach-tegra/timer-t2.c
index d433133474bc..f91528594371 100644
--- a/arch/arm/mach-tegra/timer-t2.c
+++ b/arch/arm/mach-tegra/timer-t2.c
@@ -40,6 +40,14 @@
#include "clock.h"
#include "timer.h"
+/*
+ * Timers usage:
+ * TMR1 - Free.
+ * TMR2 - used by AVP.
+ * TMR3 - used as general CPU timer.
+ * TMR4 - used for LP2 wakeup.
+*/
+
#define TIMER1_OFFSET (TEGRA_TMR1_BASE-TEGRA_TMR1_BASE)
#define TIMER2_OFFSET (TEGRA_TMR2_BASE-TEGRA_TMR1_BASE)
#define TIMER3_OFFSET (TEGRA_TMR3_BASE-TEGRA_TMR1_BASE)
@@ -53,9 +61,41 @@
static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
+#ifdef CONFIG_PM_SLEEP
+static irqreturn_t tegra_lp2wake_interrupt(int irq, void *dev_id)
+{
+ timer_writel(1<<30, TIMER4_OFFSET + TIMER_PCR);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction tegra_lp2wake_irq = {
+ .name = "timer_lp2wake",
+ .flags = IRQF_DISABLED,
+ .handler = tegra_lp2wake_interrupt,
+ .dev_id = NULL,
+ .irq = INT_TMR4,
+};
+
+void tegra2_lp2_set_trigger(unsigned long cycles)
+{
+ timer_writel(0, TIMER4_OFFSET + TIMER_PTV);
+ if (cycles) {
+ u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
+ timer_writel(reg, TIMER4_OFFSET + TIMER_PTV);
+ }
+}
+EXPORT_SYMBOL(tegra2_lp2_set_trigger);
+
+unsigned long tegra2_lp2_timer_remain(void)
+{
+ return timer_readl(TIMER4_OFFSET + TIMER_PCR) & 0x1ffffffful;
+}
+#endif
+
void __init tegra2_init_timer(u32 *offset, int *irq)
{
unsigned long rate = clk_measure_input_freq();
+ int ret;
switch (rate) {
case 12000000:
@@ -74,21 +114,14 @@ void __init tegra2_init_timer(u32 *offset, int *irq)
WARN(1, "Unknown clock rate");
}
- *offset = TIMER3_OFFSET;
- *irq = INT_TMR3;
-}
-
-void tegra2_lp2_set_trigger(unsigned long cycles)
-{
- timer_writel(0, TIMER4_OFFSET + TIMER_PTV);
- if (cycles) {
- u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
- timer_writel(reg, TIMER4_OFFSET + TIMER_PTV);
+#ifdef CONFIG_PM_SLEEP
+ ret = setup_irq(tegra_lp2wake_irq.irq, &tegra_lp2wake_irq);
+ if (ret) {
+ pr_err("Failed to register LP2 timer IRQ: %d\n", ret);
+ BUG();
}
-}
-EXPORT_SYMBOL(tegra2_lp2_set_trigger);
+#endif
-unsigned long tegra2_lp2_timer_remain(void)
-{
- return timer_readl(TIMER4_OFFSET + TIMER_PCR) & 0x1ffffffful;
+ *offset = TIMER3_OFFSET;
+ *irq = INT_TMR3;
}