1 #include <linux/types.h>
2 #include <linux/init.h>
3 #include <linux/kernel_stat.h>
4 #include <linux/sched.h>
5 #include <linux/spinlock.h>
6 #include <linux/interrupt.h>
7 #include <linux/mc146818rtc.h>
9 #include <linux/timex.h>
11 #include <asm/hardirq.h>
12 #include <asm/div64.h>
16 #include <asm/mc146818-time.h>
17 #include <asm/msc01_ic.h>
19 #include <asm/mips-boards/generic.h>
20 #include <asm/mips-boards/prom.h>
21 #include <asm/mips-boards/simint.h>
24 unsigned long cpu_khz;
27 * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect
29 static unsigned int __init estimate_cpu_frequency(void)
31 unsigned int prid = read_c0_prid() & 0xffff00;
36 * hardwire the board frequency to 12MHz.
39 if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
40 (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
47 local_irq_save(flags);
49 /* Start counter exactly on falling edge of update flag */
50 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
51 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
53 /* Start r4k counter. */
56 /* Read counter exactly on falling edge of update flag */
57 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
58 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
60 count = read_c0_count();
62 /* restore interrupts */
63 local_irq_restore(flags);
66 mips_hpt_frequency = count;
68 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
69 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
72 count += 5000; /* round */
78 void __init plat_time_init(void)
80 unsigned int est_freq, flags;
82 local_irq_save(flags);
84 /* Set Data mode - binary. */
85 CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
87 est_freq = estimate_cpu_frequency();
89 printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
90 (est_freq % 1000000) * 100 / 1000000);
92 cpu_khz = est_freq / 1000;
94 local_irq_restore(flags);
97 static int mips_cpu_timer_irq;
99 static void mips_timer_dispatch(void)
101 do_IRQ(mips_cpu_timer_irq);
105 void __init plat_timer_setup(struct irqaction *irq)
108 set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
109 mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
112 set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
113 mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
116 /* we are using the cpu counter for timer interrupts */
117 setup_irq(mips_cpu_timer_irq, irq);
120 /* irq_desc(riptor) is a global resource, when the interrupt overlaps
121 on seperate cpu's the first one tries to handle the second interrupt.
122 The effect is that the int remains disabled on the second cpu.
123 Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
124 irq_desc[mips_cpu_timer_irq].flags |= IRQ_PER_CPU;
125 set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);