Commit | Line | Data |
---|---|---|
c78cbf49 | 1 | #include <linux/types.h> |
c78cbf49 RB |
2 | #include <linux/init.h> |
3 | #include <linux/kernel_stat.h> | |
4 | #include <linux/sched.h> | |
5 | #include <linux/spinlock.h> | |
c78cbf49 RB |
6 | #include <linux/interrupt.h> |
7 | #include <linux/mc146818rtc.h> | |
f6e2373a | 8 | #include <linux/smp.h> |
c78cbf49 | 9 | #include <linux/timex.h> |
dd6bfd62 | 10 | |
c78cbf49 | 11 | #include <asm/hardirq.h> |
c78cbf49 RB |
12 | #include <asm/div64.h> |
13 | #include <asm/cpu.h> | |
14 | #include <asm/time.h> | |
dd6bfd62 | 15 | #include <asm/irq.h> |
c78cbf49 RB |
16 | #include <asm/mc146818-time.h> |
17 | #include <asm/msc01_ic.h> | |
18 | ||
19 | #include <asm/mips-boards/generic.h> | |
20 | #include <asm/mips-boards/prom.h> | |
21 | #include <asm/mips-boards/simint.h> | |
c78cbf49 RB |
22 | |
23 | ||
24 | unsigned long cpu_khz; | |
25 | ||
c78cbf49 | 26 | /* |
224dc50e | 27 | * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect |
c78cbf49 RB |
28 | */ |
29 | static unsigned int __init estimate_cpu_frequency(void) | |
30 | { | |
31 | unsigned int prid = read_c0_prid() & 0xffff00; | |
32 | unsigned int count; | |
33 | ||
34 | #if 1 | |
35 | /* | |
36 | * hardwire the board frequency to 12MHz. | |
37 | */ | |
38 | ||
39 | if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) || | |
40 | (prid == (PRID_COMP_MIPS | PRID_IMP_25KF))) | |
41 | count = 12000000; | |
42 | else | |
43 | count = 6000000; | |
44 | #else | |
45 | unsigned int flags; | |
46 | ||
47 | local_irq_save(flags); | |
48 | ||
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)); | |
52 | ||
53 | /* Start r4k counter. */ | |
54 | write_c0_count(0); | |
55 | ||
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)); | |
59 | ||
60 | count = read_c0_count(); | |
61 | ||
62 | /* restore interrupts */ | |
63 | local_irq_restore(flags); | |
64 | #endif | |
65 | ||
66 | mips_hpt_frequency = count; | |
67 | ||
68 | if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && | |
69 | (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) | |
70 | count *= 2; | |
71 | ||
72 | count += 5000; /* round */ | |
73 | count -= count%10000; | |
74 | ||
75 | return count; | |
76 | } | |
77 | ||
c78cbf49 RB |
78 | static int mips_cpu_timer_irq; |
79 | ||
937a8015 | 80 | static void mips_timer_dispatch(void) |
c78cbf49 | 81 | { |
937a8015 | 82 | do_IRQ(mips_cpu_timer_irq); |
c78cbf49 RB |
83 | } |
84 | ||
85 | ||
234fcd14 | 86 | unsigned __cpuinit get_c0_compare_int(void) |
c78cbf49 | 87 | { |
38760d40 | 88 | #ifdef MSC01E_INT_BASE |
c78cbf49 RB |
89 | if (cpu_has_veic) { |
90 | set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); | |
91 | mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; | |
78fe01a5 YY |
92 | |
93 | return mips_cpu_timer_irq; | |
c78cbf49 | 94 | } |
78fe01a5 YY |
95 | #endif |
96 | if (cpu_has_vint) | |
97 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); | |
98 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | |
c78cbf49 | 99 | |
38760d40 RB |
100 | return mips_cpu_timer_irq; |
101 | } | |
c78cbf49 | 102 | |
38760d40 RB |
103 | void __init plat_time_init(void) |
104 | { | |
526a6770 | 105 | unsigned int est_freq; |
38760d40 RB |
106 | |
107 | /* Set Data mode - binary. */ | |
108 | CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); | |
109 | ||
110 | est_freq = estimate_cpu_frequency(); | |
111 | ||
112 | printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, | |
113 | (est_freq % 1000000) * 100 / 1000000); | |
114 | ||
115 | cpu_khz = est_freq / 1000; | |
c78cbf49 | 116 | } |