diff options
Diffstat (limited to 'arch/mips/ite-boards/generic/time.c')
-rw-r--r-- | arch/mips/ite-boards/generic/time.c | 249 |
1 files changed, 0 insertions, 249 deletions
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c deleted file mode 100644 index 3dc55569ff7f..000000000000 --- a/arch/mips/ite-boards/generic/time.c +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * Copyright (C) 2003 MontaVista Software Inc. | ||
6 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
7 | * | ||
8 | * ######################################################################## | ||
9 | * | ||
10 | * This program is free software; you can distribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License (Version 2) as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
17 | * for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
22 | * | ||
23 | * ######################################################################## | ||
24 | * | ||
25 | * Setting up the clock on the MIPS boards. | ||
26 | */ | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/kernel_stat.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/time.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/mc146818rtc.h> | ||
33 | |||
34 | #include <asm/time.h> | ||
35 | #include <asm/mipsregs.h> | ||
36 | #include <asm/ptrace.h> | ||
37 | #include <asm/it8172/it8172.h> | ||
38 | #include <asm/it8172/it8172_int.h> | ||
39 | #include <asm/debug.h> | ||
40 | |||
41 | #define IT8172_RTC_ADR_REG (IT8172_PCI_IO_BASE + IT_RTC_BASE) | ||
42 | #define IT8172_RTC_DAT_REG (IT8172_RTC_ADR_REG + 1) | ||
43 | #define IT8172_RTC_CENTURY_REG (IT8172_PCI_IO_BASE + IT_RTC_CENTURY) | ||
44 | |||
45 | static volatile char *rtc_adr_reg = (char*)KSEG1ADDR(IT8172_RTC_ADR_REG); | ||
46 | static volatile char *rtc_dat_reg = (char*)KSEG1ADDR(IT8172_RTC_DAT_REG); | ||
47 | static volatile char *rtc_century_reg = (char*)KSEG1ADDR(IT8172_RTC_CENTURY_REG); | ||
48 | |||
49 | unsigned char it8172_rtc_read_data(unsigned long addr) | ||
50 | { | ||
51 | unsigned char retval; | ||
52 | |||
53 | *rtc_adr_reg = addr; | ||
54 | retval = *rtc_dat_reg; | ||
55 | return retval; | ||
56 | } | ||
57 | |||
58 | void it8172_rtc_write_data(unsigned char data, unsigned long addr) | ||
59 | { | ||
60 | *rtc_adr_reg = addr; | ||
61 | *rtc_dat_reg = data; | ||
62 | } | ||
63 | |||
64 | #undef CMOS_READ | ||
65 | #undef CMOS_WRITE | ||
66 | #define CMOS_READ(addr) it8172_rtc_read_data(addr) | ||
67 | #define CMOS_WRITE(data, addr) it8172_rtc_write_data(data, addr) | ||
68 | |||
69 | static unsigned char saved_control; /* remember rtc control reg */ | ||
70 | static inline int rtc_24h(void) { return saved_control & RTC_24H; } | ||
71 | static inline int rtc_dm_binary(void) { return saved_control & RTC_DM_BINARY; } | ||
72 | |||
73 | static inline unsigned char | ||
74 | bin_to_hw(unsigned char c) | ||
75 | { | ||
76 | if (rtc_dm_binary()) | ||
77 | return c; | ||
78 | else | ||
79 | return ((c/10) << 4) + (c%10); | ||
80 | } | ||
81 | |||
82 | static inline unsigned char | ||
83 | hw_to_bin(unsigned char c) | ||
84 | { | ||
85 | if (rtc_dm_binary()) | ||
86 | return c; | ||
87 | else | ||
88 | return (c>>4)*10 + (c &0xf); | ||
89 | } | ||
90 | |||
91 | /* 0x80 bit indicates pm in 12-hour format */ | ||
92 | static inline unsigned char | ||
93 | hour_bin_to_hw(unsigned char c) | ||
94 | { | ||
95 | if (rtc_24h()) | ||
96 | return bin_to_hw(c); | ||
97 | if (c >= 12) | ||
98 | return 0x80 | bin_to_hw((c==12)?12:c-12); /* 12 is 12pm */ | ||
99 | else | ||
100 | return bin_to_hw((c==0)?12:c); /* 0 is 12 AM, not 0 am */ | ||
101 | } | ||
102 | |||
103 | static inline unsigned char | ||
104 | hour_hw_to_bin(unsigned char c) | ||
105 | { | ||
106 | unsigned char tmp = hw_to_bin(c&0x3f); | ||
107 | if (rtc_24h()) | ||
108 | return tmp; | ||
109 | if (c & 0x80) | ||
110 | return (tmp==12)?12:tmp+12; /* 12pm is 12, not 24 */ | ||
111 | else | ||
112 | return (tmp==12)?0:tmp; /* 12am is 0 */ | ||
113 | } | ||
114 | |||
115 | static unsigned long r4k_offset; /* Amount to increment compare reg each time */ | ||
116 | static unsigned long r4k_cur; /* What counter should be at next timer irq */ | ||
117 | extern unsigned int mips_hpt_frequency; | ||
118 | |||
119 | /* | ||
120 | * Figure out the r4k offset, the amount to increment the compare | ||
121 | * register for each time tick. | ||
122 | * Use the RTC to calculate offset. | ||
123 | */ | ||
124 | static unsigned long __init cal_r4koff(void) | ||
125 | { | ||
126 | unsigned int flags; | ||
127 | |||
128 | local_irq_save(flags); | ||
129 | |||
130 | /* Start counter exactly on falling edge of update flag */ | ||
131 | while (CMOS_READ(RTC_REG_A) & RTC_UIP); | ||
132 | while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); | ||
133 | |||
134 | /* Start r4k counter. */ | ||
135 | write_c0_count(0); | ||
136 | |||
137 | /* Read counter exactly on falling edge of update flag */ | ||
138 | while (CMOS_READ(RTC_REG_A) & RTC_UIP); | ||
139 | while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); | ||
140 | |||
141 | mips_hpt_frequency = read_c0_count(); | ||
142 | |||
143 | /* restore interrupts */ | ||
144 | local_irq_restore(flags); | ||
145 | |||
146 | return (mips_hpt_frequency / HZ); | ||
147 | } | ||
148 | |||
149 | static unsigned long | ||
150 | it8172_rtc_get_time(void) | ||
151 | { | ||
152 | unsigned int year, mon, day, hour, min, sec; | ||
153 | unsigned int flags; | ||
154 | |||
155 | /* avoid update-in-progress. */ | ||
156 | for (;;) { | ||
157 | local_irq_save(flags); | ||
158 | if (! (CMOS_READ(RTC_REG_A) & RTC_UIP)) | ||
159 | break; | ||
160 | /* don't hold intr closed all the time */ | ||
161 | local_irq_restore(flags); | ||
162 | } | ||
163 | |||
164 | /* Read regs. */ | ||
165 | sec = hw_to_bin(CMOS_READ(RTC_SECONDS)); | ||
166 | min = hw_to_bin(CMOS_READ(RTC_MINUTES)); | ||
167 | hour = hour_hw_to_bin(CMOS_READ(RTC_HOURS)); | ||
168 | day = hw_to_bin(CMOS_READ(RTC_DAY_OF_MONTH)); | ||
169 | mon = hw_to_bin(CMOS_READ(RTC_MONTH)); | ||
170 | year = hw_to_bin(CMOS_READ(RTC_YEAR)) + | ||
171 | hw_to_bin(*rtc_century_reg) * 100; | ||
172 | |||
173 | /* restore interrupts */ | ||
174 | local_irq_restore(flags); | ||
175 | |||
176 | return mktime(year, mon, day, hour, min, sec); | ||
177 | } | ||
178 | |||
179 | static int | ||
180 | it8172_rtc_set_time(unsigned long t) | ||
181 | { | ||
182 | struct rtc_time tm; | ||
183 | unsigned int flags; | ||
184 | |||
185 | /* convert */ | ||
186 | to_tm(t, &tm); | ||
187 | |||
188 | /* avoid update-in-progress. */ | ||
189 | for (;;) { | ||
190 | local_irq_save(flags); | ||
191 | if (! (CMOS_READ(RTC_REG_A) & RTC_UIP)) | ||
192 | break; | ||
193 | /* don't hold intr closed all the time */ | ||
194 | local_irq_restore(flags); | ||
195 | } | ||
196 | |||
197 | *rtc_century_reg = bin_to_hw(tm.tm_year/100); | ||
198 | CMOS_WRITE(bin_to_hw(tm.tm_sec), RTC_SECONDS); | ||
199 | CMOS_WRITE(bin_to_hw(tm.tm_min), RTC_MINUTES); | ||
200 | CMOS_WRITE(hour_bin_to_hw(tm.tm_hour), RTC_HOURS); | ||
201 | CMOS_WRITE(bin_to_hw(tm.tm_mday), RTC_DAY_OF_MONTH); | ||
202 | CMOS_WRITE(bin_to_hw(tm.tm_mon+1), RTC_MONTH); /* tm_mon starts from 0 */ | ||
203 | CMOS_WRITE(bin_to_hw(tm.tm_year%100), RTC_YEAR); | ||
204 | |||
205 | /* restore interrupts */ | ||
206 | local_irq_restore(flags); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | void __init it8172_time_init(void) | ||
212 | { | ||
213 | unsigned int est_freq, flags; | ||
214 | |||
215 | local_irq_save(flags); | ||
216 | |||
217 | saved_control = CMOS_READ(RTC_CONTROL); | ||
218 | |||
219 | printk("calculating r4koff... "); | ||
220 | r4k_offset = cal_r4koff(); | ||
221 | printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); | ||
222 | |||
223 | est_freq = 2*r4k_offset*HZ; | ||
224 | est_freq += 5000; /* round */ | ||
225 | est_freq -= est_freq%10000; | ||
226 | printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, | ||
227 | (est_freq%1000000)*100/1000000); | ||
228 | |||
229 | local_irq_restore(flags); | ||
230 | |||
231 | rtc_mips_get_time = it8172_rtc_get_time; | ||
232 | rtc_mips_set_time = it8172_rtc_set_time; | ||
233 | } | ||
234 | |||
235 | #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) | ||
236 | |||
237 | void __init plat_timer_setup(struct irqaction *irq) | ||
238 | { | ||
239 | puts("timer_setup\n"); | ||
240 | put32(NR_IRQS); | ||
241 | puts(""); | ||
242 | /* we are using the cpu counter for timer interrupts */ | ||
243 | setup_irq(MIPS_CPU_TIMER_IRQ, irq); | ||
244 | |||
245 | /* to generate the first timer interrupt */ | ||
246 | r4k_cur = (read_c0_count() + r4k_offset); | ||
247 | write_c0_compare(r4k_cur); | ||
248 | set_c0_status(ALLINTS); | ||
249 | } | ||