summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/cpu_timer_twd.c
diff options
context:
space:
mode:
authorPeng Du <pdu@nvidia.com>2013-07-15 20:40:52 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:37:35 -0700
commit0510763210183aef3f95e06f1461ba0dfe1266bf (patch)
tree1725ae79d023c07e5b3ac1c63a12a2182092eae5 /arch/arm/mach-tegra/cpu_timer_twd.c
parent1f973b1170055afc483061569850f1ee95d91ade (diff)
ARM: tegra: move cpu-based timers out of timer.c
This change cleans up timer.c by pulling out cpu-based timers (ie. arch & twd) into their own files. timer.c now hosts code only for the Tegra SOC timers and common init code. Also relocated deep power down (DPD) code from timer.c to pm.c so that it can be shared by other chip family. Change-Id: I247e514270e5a81a5eb1bde6d7f75692cbede1f0 Signed-off-by: Peng Du <pdu@nvidia.com> Reviewed-on: http://git-master/r/250353 Reviewed-by: Alexander Van Brunt <avanbrunt@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bo Yan <byan@nvidia.com> Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/cpu_timer_twd.c')
-rw-r--r--arch/arm/mach-tegra/cpu_timer_twd.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/cpu_timer_twd.c b/arch/arm/mach-tegra/cpu_timer_twd.c
new file mode 100644
index 000000000000..1bd104a9d564
--- /dev/null
+++ b/arch/arm/mach-tegra/cpu_timer_twd.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arch/mach-tegra/cpu_timer_twd.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@google.com>
+ *
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mach/time.h>
+#include <asm/cputype.h>
+#include <asm/system.h>
+#include <asm/smp_twd.h>
+
+#include <mach/irqs.h>
+
+#include "clock.h"
+#include "iomap.h"
+#include "timer.h"
+
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
+ TEGRA_ARM_PERIF_BASE + 0x600,
+ IRQ_LOCALTIMER);
+static void __iomem *tegra_twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
+
+void __init tegra_cpu_timer_init(void)
+{
+ struct clk *cpu, *twd_clk;
+ int err;
+
+ /* The twd clock is a detached child of the CPU complex clock.
+ Force an update of the twd clock after DVFS has updated the
+ CPU clock rate. */
+
+ twd_clk = tegra_get_clock_by_name("twd");
+ BUG_ON(!twd_clk);
+ cpu = tegra_get_clock_by_name("cpu");
+ err = clk_set_rate(twd_clk, clk_get_rate(cpu));
+
+ if (err)
+ pr_err("Failed to set twd clock rate: %d\n", err);
+ else
+ pr_debug("TWD clock rate: %ld\n", clk_get_rate(twd_clk));
+}
+
+int tegra_twd_get_state(struct tegra_twd_context *context)
+{
+ context->twd_ctrl = readl(tegra_twd_base + TWD_TIMER_CONTROL);
+ context->twd_load = readl(tegra_twd_base + TWD_TIMER_LOAD);
+ context->twd_cnt = readl(tegra_twd_base + TWD_TIMER_COUNTER);
+
+ return 0;
+}
+
+void tegra_twd_suspend(struct tegra_twd_context *context)
+{
+ context->twd_ctrl = readl(tegra_twd_base + TWD_TIMER_CONTROL);
+ context->twd_load = readl(tegra_twd_base + TWD_TIMER_LOAD);
+ if ((context->twd_load == 0) &&
+ (context->twd_ctrl & TWD_TIMER_CONTROL_PERIODIC) &&
+ (context->twd_ctrl & (TWD_TIMER_CONTROL_ENABLE |
+ TWD_TIMER_CONTROL_IT_ENABLE))) {
+ WARN("%s: TWD enabled but counter was 0\n", __func__);
+ context->twd_load = 1;
+ }
+ __raw_writel(0, tegra_twd_base + TWD_TIMER_CONTROL);
+}
+
+void tegra_twd_resume(struct tegra_twd_context *context)
+{
+ BUG_ON((context->twd_load == 0) &&
+ (context->twd_ctrl & TWD_TIMER_CONTROL_PERIODIC) &&
+ (context->twd_ctrl & (TWD_TIMER_CONTROL_ENABLE |
+ TWD_TIMER_CONTROL_IT_ENABLE)));
+ writel(context->twd_load, tegra_twd_base + TWD_TIMER_LOAD);
+ writel(context->twd_ctrl, tegra_twd_base + TWD_TIMER_CONTROL);
+}
+
+void __init tegra_init_late_timer(void)
+{
+ int err;
+
+ if (of_have_populated_dt()) {
+ twd_local_timer_of_register();
+ return;
+ }
+
+ err = twd_local_timer_register(&twd_local_timer);
+ if (err)
+ pr_err("twd_timer_register failed %d\n", err);
+}