1 /*
2  * linux/include/asm-arm/arch-shark/time.h
3  *
4  * by Alexander Schulz
5  *
6  * Uses the real time clock because you can't run
7  * the timer with level triggered interrupts and
8  * you can't run the shark with edge triggered
9  * inetrrupts (loses ints and hangs).
10  *
11  * derived from linux/drivers/char/rtc.c and:
12  * linux/include/asm-arm/arch-ebsa110/time.h
13  * Copyright (c) 1996,1997,1998 Russell King.
14  */
15 
16 #include <asm/leds.h>
17 #include <linux/mc146818rtc.h>
18 
19 #define IRQ_TIMER 8
20 
21 extern void get_rtc_time(struct rtc_time *rtc_tm);
22 extern void set_rtc_irq_bit(unsigned char bit);
23 extern unsigned long epoch;
24 
timer_interrupt(int irq,void * dev_id,struct pt_regs * regs)25 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
26 {
27 
28 	CMOS_READ(RTC_INTR_FLAGS);
29 
30 	do_leds();
31 
32 	{
33 #ifdef DIVISOR
34 		static unsigned int divisor;
35 
36 		if (divisor-- == 0) {
37 			divisor = DIVISOR - 1;
38 #else
39 		{
40 #endif
41 			do_timer(regs);
42 		}
43 	}
44 }
45 
46 /*
47  * Set up timer interrupt, and return the current time in seconds.
48  */
49 static inline void setup_timer(void)
50 {
51         struct rtc_time r_time;
52         unsigned long flags;
53 	int tmp = 0;
54 	unsigned char val;
55 
56         /*
57 	 * Set the clock to 128 Hz, we already have a valid
58 	 * vector now:
59 	 */
60 
61 	while (HZ > (1<<tmp))
62 	  tmp++;
63 
64 	/*
65 	 * Check that the input was really a power of 2.
66 	 */
67 	if (HZ != (1<<tmp))
68 	  panic("Please set HZ to a power of 2!");
69 
70 	save_flags(flags);
71 	cli();
72 	val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
73 	val |= (16 - tmp);
74 	CMOS_WRITE(val, RTC_FREQ_SELECT);
75 	restore_flags(flags);
76 	set_rtc_irq_bit(RTC_PIE);
77 
78 	get_rtc_time(&r_time);
79 	xtime.tv_sec = mktime(r_time.tm_year+epoch, r_time.tm_mon+1, r_time.tm_mday,
80 			      r_time.tm_hour, r_time.tm_min, r_time.tm_sec);
81 
82 	timer_irq.handler = timer_interrupt;
83 	setup_arm_irq(IRQ_TIMER, &timer_irq);
84 }
85