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 47static 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 54static struct irqaction timer16_irq = { 55 .name = "timer-16", 56 .handler = timer_interrupt, 57 .flags = IRQF_DISABLED | IRQF_TIMER, 58}; 59 60static const int __initdata divide_rate[] = {1, 2, 4, 8}; 61 62void __init h8300_timer_setup(void) 63{ 64 unsigned int div; 65 unsigned int cnt; 66 67 calc_param(cnt, div, divide_rate, 0x10000); 68 69 setup_irq(_16IRQ, &timer16_irq); 70 71 /* initialize timer */ 72 ctrl_outb(0, TSTR); 73 ctrl_outb(CCLR0 | div, _16BASE + TCR); 74 ctrl_outw(cnt, _16BASE + GRA); 75 ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA); 76 ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR); 77} 78