diff options
Diffstat (limited to 'arch/ppc/platforms/chrp_time.c')
-rw-r--r-- | arch/ppc/platforms/chrp_time.c | 251 |
1 files changed, 0 insertions, 251 deletions
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c deleted file mode 100644 index c8627770af13..000000000000 --- a/arch/ppc/platforms/chrp_time.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
3 | * | ||
4 | * Adapted for PowerPC (PReP) by Gary Thomas | ||
5 | * Modified by Cort Dougan (cort@cs.nmt.edu). | ||
6 | * Copied and modified from arch/i386/kernel/time.c | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/param.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/time.h> | ||
17 | #include <linux/timex.h> | ||
18 | #include <linux/kernel_stat.h> | ||
19 | #include <linux/mc146818rtc.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/bcd.h> | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | #include <asm/nvram.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/sections.h> | ||
27 | #include <asm/time.h> | ||
28 | |||
29 | extern spinlock_t rtc_lock; | ||
30 | |||
31 | static int nvram_as1 = NVRAM_AS1; | ||
32 | static int nvram_as0 = NVRAM_AS0; | ||
33 | static int nvram_data = NVRAM_DATA; | ||
34 | |||
35 | long __init chrp_time_init(void) | ||
36 | { | ||
37 | struct device_node *rtcs; | ||
38 | int base; | ||
39 | |||
40 | rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); | ||
41 | if (rtcs == NULL) | ||
42 | rtcs = find_compatible_devices("rtc", "ds1385-rtc"); | ||
43 | if (rtcs == NULL || rtcs->addrs == NULL) | ||
44 | return 0; | ||
45 | base = rtcs->addrs[0].address; | ||
46 | nvram_as1 = 0; | ||
47 | nvram_as0 = base; | ||
48 | nvram_data = base + 1; | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int chrp_cmos_clock_read(int addr) | ||
54 | { | ||
55 | if (nvram_as1 != 0) | ||
56 | outb(addr>>8, nvram_as1); | ||
57 | outb(addr, nvram_as0); | ||
58 | return (inb(nvram_data)); | ||
59 | } | ||
60 | |||
61 | void chrp_cmos_clock_write(unsigned long val, int addr) | ||
62 | { | ||
63 | if (nvram_as1 != 0) | ||
64 | outb(addr>>8, nvram_as1); | ||
65 | outb(addr, nvram_as0); | ||
66 | outb(val, nvram_data); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Set the hardware clock. -- Cort | ||
72 | */ | ||
73 | int chrp_set_rtc_time(unsigned long nowtime) | ||
74 | { | ||
75 | unsigned char save_control, save_freq_select; | ||
76 | struct rtc_time tm; | ||
77 | |||
78 | spin_lock(&rtc_lock); | ||
79 | to_tm(nowtime, &tm); | ||
80 | |||
81 | save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */ | ||
82 | |||
83 | chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL); | ||
84 | |||
85 | save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */ | ||
86 | |||
87 | chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
88 | |||
89 | tm.tm_year -= 1900; | ||
90 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
91 | BIN_TO_BCD(tm.tm_sec); | ||
92 | BIN_TO_BCD(tm.tm_min); | ||
93 | BIN_TO_BCD(tm.tm_hour); | ||
94 | BIN_TO_BCD(tm.tm_mon); | ||
95 | BIN_TO_BCD(tm.tm_mday); | ||
96 | BIN_TO_BCD(tm.tm_year); | ||
97 | } | ||
98 | chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS); | ||
99 | chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES); | ||
100 | chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS); | ||
101 | chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH); | ||
102 | chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH); | ||
103 | chrp_cmos_clock_write(tm.tm_year,RTC_YEAR); | ||
104 | |||
105 | /* The following flags have to be released exactly in this order, | ||
106 | * otherwise the DS12887 (popular MC146818A clone with integrated | ||
107 | * battery and quartz) will not reset the oscillator and will not | ||
108 | * update precisely 500 ms later. You won't find this mentioned in | ||
109 | * the Dallas Semiconductor data sheets, but who believes data | ||
110 | * sheets anyway ... -- Markus Kuhn | ||
111 | */ | ||
112 | chrp_cmos_clock_write(save_control, RTC_CONTROL); | ||
113 | chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT); | ||
114 | |||
115 | spin_unlock(&rtc_lock); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | unsigned long chrp_get_rtc_time(void) | ||
120 | { | ||
121 | unsigned int year, mon, day, hour, min, sec; | ||
122 | int uip, i; | ||
123 | |||
124 | /* The Linux interpretation of the CMOS clock register contents: | ||
125 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
126 | * RTC registers show the second which has precisely just started. | ||
127 | * Let's hope other operating systems interpret the RTC the same way. | ||
128 | */ | ||
129 | |||
130 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
131 | * is typically written with a precision of 1 jiffy, trying | ||
132 | * to obtain a precision better than a few milliseconds is | ||
133 | * an illusion. Only consistency is interesting, this also | ||
134 | * allows to use the routine for /dev/rtc without a potential | ||
135 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
136 | */ | ||
137 | |||
138 | for ( i = 0; i<1000000; i++) { | ||
139 | uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
140 | sec = chrp_cmos_clock_read(RTC_SECONDS); | ||
141 | min = chrp_cmos_clock_read(RTC_MINUTES); | ||
142 | hour = chrp_cmos_clock_read(RTC_HOURS); | ||
143 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); | ||
144 | mon = chrp_cmos_clock_read(RTC_MONTH); | ||
145 | year = chrp_cmos_clock_read(RTC_YEAR); | ||
146 | uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
147 | if ((uip & RTC_UIP)==0) break; | ||
148 | } | ||
149 | |||
150 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
151 | { | ||
152 | BCD_TO_BIN(sec); | ||
153 | BCD_TO_BIN(min); | ||
154 | BCD_TO_BIN(hour); | ||
155 | BCD_TO_BIN(day); | ||
156 | BCD_TO_BIN(mon); | ||
157 | BCD_TO_BIN(year); | ||
158 | } | ||
159 | if ((year += 1900) < 1970) | ||
160 | year += 100; | ||
161 | return mktime(year, mon, day, hour, min, sec); | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Calibrate the decrementer frequency with the VIA timer 1. | ||
166 | */ | ||
167 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ | ||
168 | |||
169 | /* VIA registers */ | ||
170 | #define RS 0x200 /* skip between registers */ | ||
171 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
172 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
173 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
174 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
175 | #define ACR (11*RS) /* Auxiliary control register */ | ||
176 | #define IFR (13*RS) /* Interrupt flag register */ | ||
177 | |||
178 | /* Bits in ACR */ | ||
179 | #define T1MODE 0xc0 /* Timer 1 mode */ | ||
180 | #define T1MODE_CONT 0x40 /* continuous interrupts */ | ||
181 | |||
182 | /* Bits in IFR and IER */ | ||
183 | #define T1_INT 0x40 /* Timer 1 interrupt */ | ||
184 | |||
185 | static int __init chrp_via_calibrate_decr(void) | ||
186 | { | ||
187 | struct device_node *vias; | ||
188 | volatile unsigned char __iomem *via; | ||
189 | int count = VIA_TIMER_FREQ_6 / 100; | ||
190 | unsigned int dstart, dend; | ||
191 | |||
192 | vias = find_devices("via-cuda"); | ||
193 | if (vias == 0) | ||
194 | vias = find_devices("via"); | ||
195 | if (vias == 0 || vias->n_addrs == 0) | ||
196 | return 0; | ||
197 | via = ioremap(vias->addrs[0].address, vias->addrs[0].size); | ||
198 | |||
199 | /* set timer 1 for continuous interrupts */ | ||
200 | out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); | ||
201 | /* set the counter to a small value */ | ||
202 | out_8(&via[T1CH], 2); | ||
203 | /* set the latch to `count' */ | ||
204 | out_8(&via[T1LL], count); | ||
205 | out_8(&via[T1LH], count >> 8); | ||
206 | /* wait until it hits 0 */ | ||
207 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
208 | ; | ||
209 | dstart = get_dec(); | ||
210 | /* clear the interrupt & wait until it hits 0 again */ | ||
211 | in_8(&via[T1CL]); | ||
212 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
213 | ; | ||
214 | dend = get_dec(); | ||
215 | |||
216 | tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); | ||
217 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); | ||
218 | |||
219 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", | ||
220 | tb_ticks_per_jiffy, dstart - dend); | ||
221 | |||
222 | iounmap(via); | ||
223 | |||
224 | return 1; | ||
225 | } | ||
226 | |||
227 | void __init chrp_calibrate_decr(void) | ||
228 | { | ||
229 | struct device_node *cpu; | ||
230 | unsigned int freq, *fp; | ||
231 | |||
232 | if (chrp_via_calibrate_decr()) | ||
233 | return; | ||
234 | |||
235 | /* | ||
236 | * The cpu node should have a timebase-frequency property | ||
237 | * to tell us the rate at which the decrementer counts. | ||
238 | */ | ||
239 | freq = 16666000; /* hardcoded default */ | ||
240 | cpu = find_type_devices("cpu"); | ||
241 | if (cpu != 0) { | ||
242 | fp = (unsigned int *) | ||
243 | get_property(cpu, "timebase-frequency", NULL); | ||
244 | if (fp != 0) | ||
245 | freq = *fp; | ||
246 | } | ||
247 | printk("time_init: decrementer frequency = %u.%.6u MHz\n", | ||
248 | freq/1000000, freq%1000000); | ||
249 | tb_ticks_per_jiffy = freq / HZ; | ||
250 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
251 | } | ||