2 * IP32 timer calibration
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
8 * Copyright (C) 2001 Keith M Wesolowski
10 #include <linux/bcd.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/param.h>
16 #include <linux/string.h>
17 #include <linux/interrupt.h>
18 #include <linux/kernel_stat.h>
19 #include <linux/mc146818rtc.h>
20 #include <linux/timex.h>
22 #include <asm/mipsregs.h>
23 #include <asm/param.h>
24 #include <asm/ip32/crime.h>
25 #include <asm/ip32/ip32_ints.h>
26 #include <asm/bootinfo.h>
28 #include <asm/mipsregs.h>
32 extern volatile unsigned long wall_jiffies
;
36 /* Cycle counter value at the previous timer interrupt.. */
37 static unsigned int timerhi
, timerlo
;
39 /* An arbitrary time; this can be decreased if reliability looks good */
41 #define PER_MHZ (1000000 / 2 / HZ)
43 * Change this if you have some constant time drift
45 #define USECS_PER_JIFFY (1000000/HZ)
48 static irqreturn_t
cc_timer_interrupt(int irq
, void *dev_id
, struct pt_regs
* regs
);
50 void __init
ip32_timer_setup (struct irqaction
*irq
)
57 irq
->handler
= cc_timer_interrupt
;
59 printk("Calibrating system timer... ");
61 crime_time
= crime_read_64(CRIME_TIME
) & CRIME_TIME_MASK
;
62 cc_tick
= read_c0_count();
64 while ((crime_read_64 (CRIME_TIME
) & CRIME_TIME_MASK
) - crime_time
65 < WAIT_MS
* 1000000 / CRIME_NS_PER_TICK
)
67 cc_tick
= read_c0_count() - cc_tick
;
68 cc_interval
= cc_tick
/ HZ
* (1000 / WAIT_MS
);
70 * The round-off seems unnecessary; in testing, the error of the
71 * above procedure is < 100 ticks, which means it gets filtered
72 * out by the HZ adjustment.
74 cc_interval
= (cc_interval
/ PER_MHZ
) * PER_MHZ
;
76 printk("%d MHz CPU detected\n", (int) (cc_interval
/ PER_MHZ
));
78 setup_irq (CLOCK_IRQ
, irq
);
79 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
80 /* Set ourselves up for future interrupts */
81 write_c0_compare(read_c0_count() + cc_interval
);
82 change_c0_status(ST0_IM
, ALLINTS
);
86 static irqreturn_t
cc_timer_interrupt(int irq
, void *dev_id
, struct pt_regs
* regs
)
91 * The cycle counter is only 32 bit which is good for about
92 * a minute at current count rates of upto 150MHz or so.
94 count
= read_c0_count();
95 timerhi
+= (count
< timerlo
); /* Wrap around */
98 write_c0_compare((u32
) (count
+ cc_interval
));
99 kstat_this_cpu
.irqs
[irq
]++;
104 * If jiffies has overflowed in this timer_interrupt we must
105 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
106 * quotient calc still valid. -arca
108 timerhi
= timerlo
= 0;
113 void __init
ip32_time_init(void)
115 unsigned int epoch
= 0, year
, mon
, day
, hour
, min
, sec
;
118 /* The Linux interpretation of the CMOS clock register contents:
119 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
120 * RTC registers show the second which has precisely just started.
121 * Let's hope other operating systems interpret the RTC the same way.
123 /* read RTC exactly on falling edge of update flag */
124 for (i
= 0 ; i
< 1000000 ; i
++) /* may take up to 1 second... */
125 if (CMOS_READ(RTC_FREQ_SELECT
) & RTC_UIP
)
127 for (i
= 0 ; i
< 1000000 ; i
++) /* must try at least 2.228 ms */
128 if (!(CMOS_READ(RTC_FREQ_SELECT
) & RTC_UIP
))
130 do { /* Isn't this overkill ? UIP above should guarantee consistency */
131 sec
= CMOS_READ(RTC_SECONDS
);
132 min
= CMOS_READ(RTC_MINUTES
);
133 hour
= CMOS_READ(RTC_HOURS
);
134 day
= CMOS_READ(RTC_DAY_OF_MONTH
);
135 mon
= CMOS_READ(RTC_MONTH
);
136 year
= CMOS_READ(RTC_YEAR
);
137 } while (sec
!= CMOS_READ(RTC_SECONDS
));
138 if (!(CMOS_READ(RTC_CONTROL
) & RTC_DM_BINARY
) || RTC_ALWAYS_BCD
) {
141 hour
= BCD2BIN(hour
);
144 year
= BCD2BIN(year
);
147 /* Attempt to guess the epoch. This is the same heuristic as in
148 * rtc.c so no stupid things will happen to timekeeping. Who knows,
149 * maybe Ultrix also uses 1952 as epoch ...
151 if (year
> 10 && year
< 44)
157 write_seqlock_irq(&xtime_lock
);
158 xtime
.tv_sec
= mktime(year
, mon
, day
, hour
, min
, sec
);
160 write_sequnlock_irq(&xtime_lock
);