diff options
Diffstat (limited to 'arch/arm/mach-nuc93x/time.c')
-rw-r--r-- | arch/arm/mach-nuc93x/time.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/arch/arm/mach-nuc93x/time.c b/arch/arm/mach-nuc93x/time.c new file mode 100644 index 000000000000..2f90f9dc6e30 --- /dev/null +++ b/arch/arm/mach-nuc93x/time.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-nuc93x/time.c | ||
3 | * | ||
4 | * Copyright (c) 2009 Nuvoton technology corporation. | ||
5 | * | ||
6 | * Wan ZongShun <mcuos.com@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/leds.h> | ||
23 | |||
24 | #include <asm/mach-types.h> | ||
25 | #include <asm/mach/irq.h> | ||
26 | #include <asm/mach/time.h> | ||
27 | |||
28 | #include <mach/system.h> | ||
29 | #include <mach/map.h> | ||
30 | #include <mach/regs-timer.h> | ||
31 | |||
32 | #define RESETINT 0x01 | ||
33 | #define PERIOD (0x01 << 27) | ||
34 | #define ONESHOT (0x00 << 27) | ||
35 | #define COUNTEN (0x01 << 30) | ||
36 | #define INTEN (0x01 << 29) | ||
37 | |||
38 | #define TICKS_PER_SEC 100 | ||
39 | #define PRESCALE 0x63 /* Divider = prescale + 1 */ | ||
40 | |||
41 | unsigned int timer0_load; | ||
42 | |||
43 | static unsigned long nuc93x_gettimeoffset(void) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | /*IRQ handler for the timer*/ | ||
49 | |||
50 | static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id) | ||
51 | { | ||
52 | timer_tick(); | ||
53 | __raw_writel(0x01, REG_TISR); /* clear TIF0 */ | ||
54 | return IRQ_HANDLED; | ||
55 | } | ||
56 | |||
57 | static struct irqaction nuc93x_timer_irq = { | ||
58 | .name = "nuc93x Timer Tick", | ||
59 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | ||
60 | .handler = nuc93x_timer_interrupt, | ||
61 | }; | ||
62 | |||
63 | /*Set up timer reg.*/ | ||
64 | |||
65 | static void nuc93x_timer_setup(void) | ||
66 | { | ||
67 | struct clk *ck_ext = clk_get(NULL, "ext"); | ||
68 | struct clk *ck_timer = clk_get(NULL, "timer"); | ||
69 | unsigned int rate, val = 0; | ||
70 | |||
71 | BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer)); | ||
72 | |||
73 | clk_enable(ck_timer); | ||
74 | rate = clk_get_rate(ck_ext); | ||
75 | clk_put(ck_ext); | ||
76 | rate = rate / (PRESCALE + 0x01); | ||
77 | |||
78 | /* set a known state */ | ||
79 | __raw_writel(0x00, REG_TCSR0); | ||
80 | __raw_writel(RESETINT, REG_TISR); | ||
81 | |||
82 | timer0_load = (rate / TICKS_PER_SEC); | ||
83 | __raw_writel(timer0_load, REG_TICR0); | ||
84 | |||
85 | val |= (PERIOD | COUNTEN | INTEN | PRESCALE);; | ||
86 | __raw_writel(val, REG_TCSR0); | ||
87 | |||
88 | } | ||
89 | |||
90 | static void __init nuc93x_timer_init(void) | ||
91 | { | ||
92 | nuc93x_timer_setup(); | ||
93 | setup_irq(IRQ_TIMER0, &nuc93x_timer_irq); | ||
94 | } | ||
95 | |||
96 | struct sys_timer nuc93x_timer = { | ||
97 | .init = nuc93x_timer_init, | ||
98 | .offset = nuc93x_gettimeoffset, | ||
99 | .resume = nuc93x_timer_setup | ||
100 | }; | ||