diff options
Diffstat (limited to 'arch/arm/mach-tegra/timer.c')
-rw-r--r-- | arch/arm/mach-tegra/timer.c | 78 |
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 | ||
56 | static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); | 54 | static void __iomem *timer_reg_base; |
57 | static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); | 55 | static void __iomem *rtc_base; |
58 | 56 | ||
59 | static struct timespec persistent_ts; | 57 | static struct timespec persistent_ts; |
60 | static u64 persistent_ms, last_persistent_ms; | 58 | static 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 | 161 | static const struct of_device_id timer_match[] __initconst = { |
165 | static 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 | ||
169 | static void __init tegra_twd_init(void) | 166 | static 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 | ||
179 | static void __init tegra_init_timer(void) | 171 | static 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 | ||