0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/bcd.h>
0013 #include <linux/i8253.h>
0014 #include <linux/init.h>
0015 #include <linux/irq.h>
0016 #include <linux/kernel.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/kernel_stat.h>
0019 #include <linux/time.h>
0020 #include <linux/ftrace.h>
0021
0022 #include <asm/cpu.h>
0023 #include <asm/mipsregs.h>
0024 #include <asm/io.h>
0025 #include <asm/irq.h>
0026 #include <asm/time.h>
0027 #include <asm/sgialib.h>
0028 #include <asm/sgi/ioc.h>
0029 #include <asm/sgi/hpc3.h>
0030 #include <asm/sgi/ip22.h>
0031
0032 static unsigned long dosample(void)
0033 {
0034 u32 ct0, ct1;
0035 u8 msb;
0036
0037
0038 sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL |
0039 SGINT_TCWORD_MRGEN);
0040 sgint->tcnt2 = SGINT_TCSAMP_COUNTER & 0xff;
0041 sgint->tcnt2 = SGINT_TCSAMP_COUNTER >> 8;
0042
0043
0044 ct0 = read_c0_count();
0045
0046
0047 do {
0048 writeb(SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT, &sgint->tcword);
0049 (void) readb(&sgint->tcnt2);
0050 msb = readb(&sgint->tcnt2);
0051 ct1 = read_c0_count();
0052 } while (msb);
0053
0054
0055 writeb(SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST,
0056 &sgint->tcword);
0057
0058
0059
0060
0061
0062
0063 return (ct1 - ct0) / (500000/HZ) * (500000/HZ);
0064 }
0065
0066
0067
0068
0069 __init void plat_time_init(void)
0070 {
0071 unsigned long r4k_ticks[3];
0072 unsigned long r4k_tick;
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 printk(KERN_INFO "Calibrating system timer... ");
0084 dosample();
0085 dosample();
0086
0087 do {
0088 r4k_ticks[0] = dosample();
0089 } while (!r4k_ticks[0]);
0090 do {
0091 r4k_ticks[1] = dosample();
0092 } while (!r4k_ticks[1]);
0093
0094 if (r4k_ticks[0] != r4k_ticks[1]) {
0095 printk("warning: timer counts differ, retrying... ");
0096 r4k_ticks[2] = dosample();
0097 if (r4k_ticks[2] == r4k_ticks[0]
0098 || r4k_ticks[2] == r4k_ticks[1])
0099 r4k_tick = r4k_ticks[2];
0100 else {
0101 printk("disagreement, using average... ");
0102 r4k_tick = (r4k_ticks[0] + r4k_ticks[1]
0103 + r4k_ticks[2]) / 3;
0104 }
0105 } else
0106 r4k_tick = r4k_ticks[0];
0107
0108 printk("%d [%d.%04d MHz CPU]\n", (int) r4k_tick,
0109 (int) (r4k_tick / (500000 / HZ)),
0110 (int) (r4k_tick % (500000 / HZ)));
0111
0112 mips_hpt_frequency = r4k_tick * HZ;
0113
0114 if (ip22_is_fullhouse())
0115 setup_pit_timer();
0116 }
0117
0118
0119 void __irq_entry indy_8254timer_irq(void)
0120 {
0121 int irq = SGI_8254_0_IRQ;
0122 ULONG cnt;
0123 char c;
0124
0125 irq_enter();
0126 kstat_incr_irq_this_cpu(irq);
0127 printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
0128 ArcRead(0, &c, 1, &cnt);
0129 ArcEnterInteractiveMode();
0130 irq_exit();
0131 }