aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/timer.c')
-rw-r--r--arch/arm/mach-tegra/timer.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 6ff503536512..e4863f3e9ee7 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -26,16 +26,14 @@
26#include <linux/clocksource.h> 26#include <linux/clocksource.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
29 31
30#include <asm/mach/time.h> 32#include <asm/mach/time.h>
31#include <asm/smp_twd.h> 33#include <asm/smp_twd.h>
32#include <asm/sched_clock.h> 34#include <asm/sched_clock.h>
33 35
34#include <mach/irqs.h>
35
36#include "board.h" 36#include "board.h"
37#include "clock.h"
38#include "iomap.h"
39 37
40#define RTC_SECONDS 0x08 38#define RTC_SECONDS 0x08
41#define RTC_SHADOW_SECONDS 0x0c 39#define RTC_SHADOW_SECONDS 0x0c
@@ -53,8 +51,8 @@
53#define TIMER_PTV 0x0 51#define TIMER_PTV 0x0
54#define TIMER_PCR 0x4 52#define TIMER_PCR 0x4
55 53
56static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); 54static void __iomem *timer_reg_base;
57static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); 55static void __iomem *rtc_base;
58 56
59static struct timespec persistent_ts; 57static struct timespec persistent_ts;
60static u64 persistent_ms, last_persistent_ms; 58static u64 persistent_ms, last_persistent_ms;
@@ -158,40 +156,66 @@ static struct irqaction tegra_timer_irq = {
158 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, 156 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
159 .handler = tegra_timer_interrupt, 157 .handler = tegra_timer_interrupt,
160 .dev_id = &tegra_clockevent, 158 .dev_id = &tegra_clockevent,
161 .irq = INT_TMR3,
162}; 159};
163 160
164#ifdef CONFIG_HAVE_ARM_TWD 161static const struct of_device_id timer_match[] __initconst = {
165static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 162 { .compatible = "nvidia,tegra20-timer" },
166 TEGRA_ARM_PERIF_BASE + 0x600, 163 {}
167 IRQ_LOCALTIMER); 164};
168 165
169static void __init tegra_twd_init(void) 166static const struct of_device_id rtc_match[] __initconst = {
170{ 167 { .compatible = "nvidia,tegra20-rtc" },
171 int err = twd_local_timer_register(&twd_local_timer); 168 {}
172 if (err) 169};
173 pr_err("twd_local_timer_register failed %d\n", err);
174}
175#else
176#define tegra_twd_init() do {} while(0)
177#endif
178 170
179static void __init tegra_init_timer(void) 171static void __init tegra_init_timer(void)
180{ 172{
173 struct device_node *np;
181 struct clk *clk; 174 struct clk *clk;
182 unsigned long rate; 175 unsigned long rate;
183 int ret; 176 int ret;
184 177
178 np = of_find_matching_node(NULL, timer_match);
179 if (!np) {
180 pr_err("Failed to find timer DT node\n");
181 BUG();
182 }
183
184 timer_reg_base = of_iomap(np, 0);
185 if (!timer_reg_base) {
186 pr_err("Can't map timer registers");
187 BUG();
188 }
189
190 tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
191 if (tegra_timer_irq.irq <= 0) {
192 pr_err("Failed to map timer IRQ\n");
193 BUG();
194 }
195
185 clk = clk_get_sys("timer", NULL); 196 clk = clk_get_sys("timer", NULL);
186 if (IS_ERR(clk)) { 197 if (IS_ERR(clk)) {
187 pr_warn("Unable to get timer clock." 198 pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
188 " Assuming 12Mhz input clock.\n");
189 rate = 12000000; 199 rate = 12000000;
190 } else { 200 } else {
191 clk_prepare_enable(clk); 201 clk_prepare_enable(clk);
192 rate = clk_get_rate(clk); 202 rate = clk_get_rate(clk);
193 } 203 }
194 204
205 of_node_put(np);
206
207 np = of_find_matching_node(NULL, rtc_match);
208 if (!np) {
209 pr_err("Failed to find RTC DT node\n");
210 BUG();
211 }
212
213 rtc_base = of_iomap(np, 0);
214 if (!rtc_base) {
215 pr_err("Can't map RTC registers");
216 BUG();
217 }
218
195 /* 219 /*
196 * rtc registers are used by read_persistent_clock, keep the rtc clock 220 * rtc registers are used by read_persistent_clock, keep the rtc clock
197 * enabled 221 * enabled
@@ -202,6 +226,8 @@ static void __init tegra_init_timer(void)
202 else 226 else
203 clk_prepare_enable(clk); 227 clk_prepare_enable(clk);
204 228
229 of_node_put(np);
230
205 switch (rate) { 231 switch (rate) {
206 case 12000000: 232 case 12000000:
207 timer_writel(0x000b, TIMERUS_USEC_CFG); 233 timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -223,13 +249,13 @@ static void __init tegra_init_timer(void)
223 249
224 if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, 250 if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
225 "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { 251 "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
226 printk(KERN_ERR "Failed to register clocksource\n"); 252 pr_err("Failed to register clocksource\n");
227 BUG(); 253 BUG();
228 } 254 }
229 255
230 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); 256 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
231 if (ret) { 257 if (ret) {
232 printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); 258 pr_err("Failed to register timer IRQ: %d\n", ret);
233 BUG(); 259 BUG();
234 } 260 }
235 261
@@ -241,7 +267,9 @@ static void __init tegra_init_timer(void)
241 tegra_clockevent.cpumask = cpu_all_mask; 267 tegra_clockevent.cpumask = cpu_all_mask;
242 tegra_clockevent.irq = tegra_timer_irq.irq; 268 tegra_clockevent.irq = tegra_timer_irq.irq;
243 clockevents_register_device(&tegra_clockevent); 269 clockevents_register_device(&tegra_clockevent);
244 tegra_twd_init(); 270#ifdef CONFIG_HAVE_ARM_TWD
271 twd_local_timer_of_register();
272#endif
245 register_persistent_clock(NULL, tegra_read_persistent_clock); 273 register_persistent_clock(NULL, tegra_read_persistent_clock);
246} 274}
247 275