diff options
-rw-r--r-- | arch/h8300/kernel/timer/Makefile | 6 | ||||
-rw-r--r-- | arch/h8300/kernel/timer/itu.c | 83 | ||||
-rw-r--r-- | arch/h8300/kernel/timer/timer16.c | 78 | ||||
-rw-r--r-- | arch/h8300/kernel/timer/timer8.c | 103 | ||||
-rw-r--r-- | arch/h8300/kernel/timer/tpu.c | 102 | ||||
-rw-r--r-- | include/asm-h8300/timer.h | 25 |
6 files changed, 397 insertions, 0 deletions
diff --git a/arch/h8300/kernel/timer/Makefile b/arch/h8300/kernel/timer/Makefile new file mode 100644 index 000000000000..bef0510ea6ad --- /dev/null +++ b/arch/h8300/kernel/timer/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # h8300 internal timer handler | ||
2 | |||
3 | obj-$(CONFIG_H8300_TIMER8) := timer8.o | ||
4 | obj-$(CONFIG_H8300_TIMER16) := timer16.o | ||
5 | obj-$(CONFIG_H8300_ITU) := itu.o | ||
6 | obj-$(CONFIG_H8300_TPU) := tpu.o | ||
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c new file mode 100644 index 000000000000..d1c926596b08 --- /dev/null +++ b/arch/h8300/kernel/timer/itu.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/timer/itu.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourcefoge.jp> | ||
5 | * | ||
6 | * ITU Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/errno.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/timex.h> | ||
19 | |||
20 | #include <asm/segment.h> | ||
21 | #include <asm/io.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/regs306x.h> | ||
24 | |||
25 | #if CONFIG_H8300_ITU_CH == 0 | ||
26 | #define ITUBASE 0xffff64 | ||
27 | #define ITUIRQ 24 | ||
28 | #elif CONFIG_H8300_ITU_CH == 1 | ||
29 | #define ITUBASE 0xffff6e | ||
30 | #define ITUIRQ 28 | ||
31 | #elif CONFIG_H8300_ITU_CH == 2 | ||
32 | #define ITUBASE 0xffff78 | ||
33 | #define ITUIRQ 32 | ||
34 | #elif CONFIG_H8300_ITU_CH == 3 | ||
35 | #define ITUBASE 0xffff82 | ||
36 | #define ITUIRQ 36 | ||
37 | #elif CONFIG_H8300_ITU_CH == 4 | ||
38 | #define ITUBASE 0xffff92 | ||
39 | #define ITUIRQ 40 | ||
40 | #else | ||
41 | #error Unknown timer channel. | ||
42 | #endif | ||
43 | |||
44 | #define TCR 0 | ||
45 | #define TIOR 1 | ||
46 | #define TIER 2 | ||
47 | #define TSR 3 | ||
48 | #define TCNT 4 | ||
49 | #define GRA 6 | ||
50 | #define GRB 8 | ||
51 | |||
52 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
53 | { | ||
54 | h8300_timer_tick(); | ||
55 | ctrl_bclr(IMFA, ITUBASE + TSR); | ||
56 | return IRQ_HANDLED; | ||
57 | } | ||
58 | |||
59 | static struct irqaction itu_irq = { | ||
60 | .name = "itu", | ||
61 | .handler = timer_interrupt, | ||
62 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
63 | .mask = CPU_MASK_NONE, | ||
64 | }; | ||
65 | |||
66 | static const int __initdata divide_rate[] = {1, 2, 4, 8}; | ||
67 | |||
68 | void __init h8300_timer_setup(void) | ||
69 | { | ||
70 | unsigned int div; | ||
71 | unsigned int cnt; | ||
72 | |||
73 | calc_param(cnt, div, divide_rate, 0x10000); | ||
74 | |||
75 | setup_irq(ITUIRQ, &itu_irq); | ||
76 | |||
77 | /* initalize timer */ | ||
78 | ctrl_outb(0, TSTR); | ||
79 | ctrl_outb(CCLR0 | div, ITUBASE + TCR); | ||
80 | ctrl_outb(0x01, ITUBASE + TIER); | ||
81 | ctrl_outw(cnt, ITUBASE + GRA); | ||
82 | ctrl_bset(CONFIG_H8300_ITU_CH, TSTR); | ||
83 | } | ||
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c new file mode 100644 index 000000000000..e14271b72119 --- /dev/null +++ b/arch/h8300/kernel/timer/timer16.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/timer/timer16.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourcefoge.jp> | ||
5 | * | ||
6 | * 16bit Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/errno.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/timex.h> | ||
19 | |||
20 | #include <asm/segment.h> | ||
21 | #include <asm/io.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/regs306x.h> | ||
24 | |||
25 | /* 16bit timer */ | ||
26 | #if CONFIG_H8300_TIMER16_CH == 0 | ||
27 | #define _16BASE 0xffff78 | ||
28 | #define _16IRQ 24 | ||
29 | #elif CONFIG_H8300_TIMER16_CH == 1 | ||
30 | #define _16BASE 0xffff80 | ||
31 | #define _16IRQ 28 | ||
32 | #elif CONFIG_H8300_TIMER16_CH == 2 | ||
33 | #define _16BASE 0xffff88 | ||
34 | #define _16IRQ 32 | ||
35 | #else | ||
36 | #error Unknown timer channel. | ||
37 | #endif | ||
38 | |||
39 | #define TCR 0 | ||
40 | #define TIOR 1 | ||
41 | #define TCNT 2 | ||
42 | #define GRA 4 | ||
43 | #define GRB 6 | ||
44 | |||
45 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*10000 /* Timer input freq. */ | ||
46 | |||
47 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
48 | { | ||
49 | h8300_timer_tick(); | ||
50 | ctrl_bclr(CONFIG_H8300_TIMER16_CH, TISRA); | ||
51 | return IRQ_HANDLED; | ||
52 | } | ||
53 | |||
54 | static struct irqaction timer16_irq = { | ||
55 | .name = "timer-16", | ||
56 | .handler = timer_interrupt, | ||
57 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
58 | .mask = CPU_MASK_NONE, | ||
59 | }; | ||
60 | |||
61 | static const int __initdata divide_rate[] = {1, 2, 4, 8}; | ||
62 | |||
63 | void __init h8300_timer_setup(void) | ||
64 | { | ||
65 | unsigned int div; | ||
66 | unsigned int cnt; | ||
67 | |||
68 | calc_param(cnt, div, divide_rate, 0x10000); | ||
69 | |||
70 | setup_irq(_16IRQ, &timer16_irq); | ||
71 | |||
72 | /* initalize timer */ | ||
73 | ctrl_outb(0, TSTR); | ||
74 | ctrl_outb(CCLR0 | div, _16BASE + TCR); | ||
75 | ctrl_outw(cnt, _16BASE + GRA); | ||
76 | ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA); | ||
77 | ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR); | ||
78 | } | ||
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c new file mode 100644 index 000000000000..0556d7c7bea6 --- /dev/null +++ b/arch/h8300/kernel/timer/timer8.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/cpu/timer/timer8.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourcefoge.jp> | ||
5 | * | ||
6 | * 8bit Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/errno.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/profile.h> | ||
19 | |||
20 | #include <asm/io.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/timer.h> | ||
23 | #if defined(CONFIG_CPU_H8300H) | ||
24 | #include <asm/regs306x.h> | ||
25 | #endif | ||
26 | #if defined(CONFIG_CPU_H8S) | ||
27 | #include <asm/regs267x.h> | ||
28 | #endif | ||
29 | |||
30 | /* 8bit timer x2 */ | ||
31 | #define CMFA 6 | ||
32 | |||
33 | #if defined(CONFIG_H8300_TIMER8_CH0) | ||
34 | #define _8BASE _8TCR0 | ||
35 | #ifdef CONFIG_CPU_H8300H | ||
36 | #define _8IRQ 36 | ||
37 | #endif | ||
38 | #ifdef CONFIG_CPU_H8S | ||
39 | #define _8IRQ 72 | ||
40 | #endif | ||
41 | #elif defined(CONFIG_H8300_TIMER8_CH2) | ||
42 | #ifdef CONFIG_CPU_H8300H | ||
43 | #define _8BASE _8TCR2 | ||
44 | #define _8IRQ 40 | ||
45 | #endif | ||
46 | #endif | ||
47 | |||
48 | #ifndef _8BASE | ||
49 | #error Unknown timer channel. | ||
50 | #endif | ||
51 | |||
52 | #define _8TCR 0 | ||
53 | #define _8TCSR 2 | ||
54 | #define TCORA 4 | ||
55 | #define TCORB 6 | ||
56 | #define _8TCNT 8 | ||
57 | |||
58 | #define CMIEA 0x40 | ||
59 | #define CCLR_CMA 0x08 | ||
60 | #define CKS2 0x04 | ||
61 | |||
62 | /* | ||
63 | * timer_interrupt() needs to keep up the real-time clock, | ||
64 | * as well as call the "do_timer()" routine every clocktick | ||
65 | */ | ||
66 | |||
67 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
68 | { | ||
69 | h8300_timer_tick(); | ||
70 | ctrl_bclr(CMFA, _8BASE + _8TCSR); | ||
71 | return IRQ_HANDLED; | ||
72 | } | ||
73 | |||
74 | static struct irqaction timer8_irq = { | ||
75 | .name = "timer-8", | ||
76 | .handler = timer_interrupt, | ||
77 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
78 | .mask = CPU_MASK_NONE, | ||
79 | }; | ||
80 | |||
81 | static const int __initdata divide_rate[] = {8, 64, 8192}; | ||
82 | |||
83 | void __init h8300_timer_setup(void) | ||
84 | { | ||
85 | unsigned int div; | ||
86 | unsigned int cnt; | ||
87 | |||
88 | calc_param(cnt, div, divide_rate, 0x10000); | ||
89 | div++; | ||
90 | |||
91 | setup_irq(_8IRQ, &timer8_irq); | ||
92 | |||
93 | #if defined(CONFIG_CPU_H8S) | ||
94 | /* Timer module enable */ | ||
95 | ctrl_bclr(0, MSTPCRL) | ||
96 | #endif | ||
97 | |||
98 | /* initalize timer */ | ||
99 | ctrl_outw(cnt, _8BASE + TCORA); | ||
100 | ctrl_outw(0x0000, _8BASE + _8TCSR); | ||
101 | ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div, | ||
102 | _8BASE + _8TCR); | ||
103 | } | ||
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c new file mode 100644 index 000000000000..df7f453a9673 --- /dev/null +++ b/arch/h8300/kernel/timer/tpu.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/timer/tpu.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * TPU Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/timex.h> | ||
20 | |||
21 | #include <asm/segment.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/regs267x.h> | ||
25 | |||
26 | /* TPU */ | ||
27 | #if CONFIG_H8300_TPU_CH == 0 | ||
28 | #define TPUBASE 0xffffd0 | ||
29 | #define TPUIRQ 40 | ||
30 | #elif CONFIG_H8300_TPU_CH == 1 | ||
31 | #define TPUBASE 0xffffe0 | ||
32 | #define TPUIRQ 48 | ||
33 | #elif CONFIG_H8300_TPU_CH == 2 | ||
34 | #define TPUBASE 0xfffff0 | ||
35 | #define TPUIRQ 52 | ||
36 | #elif CONFIG_H8300_TPU_CH == 3 | ||
37 | #define TPUBASE 0xfffe80 | ||
38 | #define TPUIRQ 56 | ||
39 | #elif CONFIG_H8300_TPU_CH == 4 | ||
40 | #define TPUBASE 0xfffe90 | ||
41 | #define TPUIRQ 64 | ||
42 | #else | ||
43 | #error Unknown timer channel. | ||
44 | #endif | ||
45 | |||
46 | #define _TCR 0 | ||
47 | #define _TMDR 1 | ||
48 | #define _TIOR 2 | ||
49 | #define _TIER 4 | ||
50 | #define _TSR 5 | ||
51 | #define _TCNT 6 | ||
52 | #define _GRA 8 | ||
53 | #define _GRB 10 | ||
54 | |||
55 | #define CCLR0 0x20 | ||
56 | |||
57 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
58 | { | ||
59 | h8300_timer_tick(); | ||
60 | ctrl_bclr(0, TPUBASE + _TSR); | ||
61 | return IRQ_HANDLED; | ||
62 | } | ||
63 | |||
64 | static struct irqaction tpu_irq = { | ||
65 | .name = "tpu", | ||
66 | .handler = timer_interrupt, | ||
67 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
68 | .mask = CPU_MASK_NONE, | ||
69 | }; | ||
70 | |||
71 | const static int __initdata divide_rate[] = { | ||
72 | #if CONFIG_H8300_TPU_CH == 0 | ||
73 | 1,4,16,64,0,0,0,0, | ||
74 | #elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5) | ||
75 | 1,4,16,64,0,0,256,0, | ||
76 | #elif (CONFIG_H8300_TPU_CH == 2) || (CONFIG_H8300_TPU_CH == 4) | ||
77 | 1,4,16,64,0,0,0,1024, | ||
78 | #elif CONFIG_H8300_TPU_CH == 3 | ||
79 | 1,4,16,64,0,1024,256,4096, | ||
80 | #endif | ||
81 | }; | ||
82 | |||
83 | void __init h8300_timer_setup(void) | ||
84 | { | ||
85 | unsigned int cnt; | ||
86 | unsigned int div; | ||
87 | |||
88 | calc_param(cnt, div, divide_rate, 0x10000); | ||
89 | |||
90 | setup_irq(TPUIRQ, &tpu_irq); | ||
91 | |||
92 | /* TPU module enabled */ | ||
93 | ctrl_bclr(3, MSTPCRH); | ||
94 | |||
95 | ctrl_outb(0, TSTR); | ||
96 | ctrl_outb(CCLR0 | div, TPUBASE + _TCR); | ||
97 | ctrl_outb(0, TPUBASE + _TMDR); | ||
98 | ctrl_outw(0, TPUBASE + _TIOR); | ||
99 | ctrl_outb(0x01, TPUBASE + _TIER); | ||
100 | ctrl_outw(cnt, TPUBASE + _GRA); | ||
101 | ctrl_bset(CONFIG_H8300_TPU_CH, TSTR); | ||
102 | } | ||
diff --git a/include/asm-h8300/timer.h b/include/asm-h8300/timer.h new file mode 100644 index 000000000000..def80464d38f --- /dev/null +++ b/include/asm-h8300/timer.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __H8300_TIMER_H | ||
2 | #define __H8300_TIMER_H | ||
3 | |||
4 | void h8300_timer_tick(void); | ||
5 | void h8300_timer_setup(void); | ||
6 | void h8300_gettod(unsigned int *year, unsigned int *mon, unsigned int *day, | ||
7 | unsigned int *hour, unsigned int *min, unsigned int *sec); | ||
8 | |||
9 | #define TIMER_FREQ (CONFIG_CPU_CLOCK*10000) /* Timer input freq. */ | ||
10 | |||
11 | #define calc_param(cnt, div, rate, limit) \ | ||
12 | do { \ | ||
13 | cnt = TIMER_FREQ / HZ; \ | ||
14 | for (div = 0; div < ARRAY_SIZE(divide_rate); div++) { \ | ||
15 | if (rate[div] == 0) \ | ||
16 | continue; \ | ||
17 | if ((cnt / rate[div]) > limit) \ | ||
18 | break; \ | ||
19 | } \ | ||
20 | if (div == ARRAY_SIZE(divide_rate)) \ | ||
21 | panic("Timer counter overflow"); \ | ||
22 | cnt /= divide_rate[div]; \ | ||
23 | } while(0) | ||
24 | |||
25 | #endif | ||