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 
timer_interrupt(int irq,void * dev_id)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 };
64 
65 static const int __initdata divide_rate[] = {1, 2, 4, 8};
66 
h8300_timer_setup(void)67 void __init h8300_timer_setup(void)
68 {
69 	unsigned int div;
70 	unsigned int cnt;
71 
72 	calc_param(cnt, div, divide_rate, 0x10000);
73 
74 	setup_irq(ITUIRQ, &itu_irq);
75 
76 	/* initialize timer */
77 	ctrl_outb(0, TSTR);
78 	ctrl_outb(CCLR0 | div, ITUBASE + TCR);
79 	ctrl_outb(0x01, ITUBASE + TIER);
80 	ctrl_outw(cnt, ITUBASE + GRA);
81 	ctrl_bset(CONFIG_H8300_ITU_CH, TSTR);
82 }
83