* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / sparc64 / kernel / time.c
blob60d5e4a5fad72adbc91ba691aa37a2279a43f721
1 /* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $
2 * time.c: UltraSparc timer and TOD clock support.
4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 * Based largely on code which is:
9 * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
12 #include <linux/config.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/param.h>
17 #include <linux/string.h>
18 #include <linux/mm.h>
19 #include <linux/interrupt.h>
20 #include <linux/timex.h>
21 #include <linux/init.h>
22 #include <linux/ioport.h>
24 #include <asm/oplib.h>
25 #include <asm/mostek.h>
26 #include <asm/timer.h>
27 #include <asm/irq.h>
28 #include <asm/io.h>
29 #include <asm/sbus.h>
30 #include <asm/fhc.h>
31 #include <asm/pbm.h>
32 #include <asm/ebus.h>
34 extern rwlock_t xtime_lock;
36 unsigned long mstk48t02_regs = 0UL;
37 static unsigned long mstk48t08_regs = 0UL;
38 static unsigned long mstk48t59_regs = 0UL;
40 static int set_rtc_mmss(unsigned long);
42 /* timer_interrupt() needs to keep up the real-time clock,
43 * as well as call the "do_timer()" routine every clocktick
45 * NOTE: On SUN5 systems the ticker interrupt comes in using 2
46 * interrupts, one at level14 and one with softint bit 0.
48 unsigned long timer_tick_offset;
49 static unsigned long timer_tick_compare;
50 static unsigned long timer_ticks_per_usec_quotient;
52 static __inline__ void timer_check_rtc(void)
54 /* last time the cmos clock got updated */
55 static long last_rtc_update=0;
57 /* Determine when to update the Mostek clock. */
58 if ((time_status & STA_UNSYNC) == 0 &&
59 xtime.tv_sec > last_rtc_update + 660 &&
60 xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
61 xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
62 if (set_rtc_mmss(xtime.tv_sec) == 0)
63 last_rtc_update = xtime.tv_sec;
64 else
65 last_rtc_update = xtime.tv_sec - 600;
66 /* do it again in 60 s */
70 static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
72 unsigned long ticks;
74 write_lock(&xtime_lock);
76 do {
77 do_timer(regs);
79 __asm__ __volatile__("
80 rd %%tick_cmpr, %0
81 add %0, %2, %0
82 wr %0, 0, %%tick_cmpr
83 rd %%tick, %1"
84 : "=&r" (timer_tick_compare), "=r" (ticks)
85 : "r" (timer_tick_offset));
86 } while (ticks >= timer_tick_compare);
88 timer_check_rtc();
90 write_unlock(&xtime_lock);
93 #ifdef __SMP__
94 void timer_tick_interrupt(struct pt_regs *regs)
96 write_lock(&xtime_lock);
98 do_timer(regs);
101 * Only keep timer_tick_offset uptodate, but don't set TICK_CMPR.
103 __asm__ __volatile__("
104 rd %%tick_cmpr, %0
105 add %0, %1, %0"
106 : "=&r" (timer_tick_compare)
107 : "r" (timer_tick_offset));
109 timer_check_rtc();
111 write_unlock(&xtime_lock);
113 #endif
115 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
116 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
117 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
119 * [For the Julian calendar (which was used in Russia before 1917,
120 * Britain & colonies before 1752, anywhere else before 1582,
121 * and is still in use by some communities) leave out the
122 * -year/100+year/400 terms, and add 10.]
124 * This algorithm was first published by Gauss (I think).
126 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
127 * machines were long is 32-bit! (However, as time_t is signed, we
128 * will already get problems at other places on 2038-01-19 03:14:08)
130 static inline unsigned long mktime(unsigned int year, unsigned int mon,
131 unsigned int day, unsigned int hour,
132 unsigned int min, unsigned int sec)
134 if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
135 mon += 12; /* Puts Feb last since it has leap day */
136 year -= 1;
138 return (((
139 (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
140 year*365 - 719499
141 )*24 + hour /* now have hours */
142 )*60 + min /* now have minutes */
143 )*60 + sec; /* finally seconds */
146 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
147 static void __init kick_start_clock(void)
149 unsigned long regs = mstk48t02_regs;
150 u8 sec, tmp;
151 int i, count;
153 prom_printf("CLOCK: Clock was stopped. Kick start ");
155 /* Turn on the kick start bit to start the oscillator. */
156 tmp = mostek_read(regs + MOSTEK_CREG);
157 tmp |= MSTK_CREG_WRITE;
158 mostek_write(regs + MOSTEK_CREG, tmp);
159 tmp = mostek_read(regs + MOSTEK_SEC);
160 tmp &= ~MSTK_STOP;
161 mostek_write(regs + MOSTEK_SEC, tmp);
162 tmp = mostek_read(regs + MOSTEK_HOUR);
163 tmp |= MSTK_KICK_START;
164 mostek_write(regs + MOSTEK_HOUR, tmp);
165 tmp = mostek_read(regs + MOSTEK_CREG);
166 tmp &= ~MSTK_CREG_WRITE;
167 mostek_write(regs + MOSTEK_CREG, tmp);
169 /* Delay to allow the clock oscillator to start. */
170 sec = MSTK_REG_SEC(regs);
171 for (i = 0; i < 3; i++) {
172 while (sec == MSTK_REG_SEC(regs))
173 for (count = 0; count < 100000; count++)
174 /* nothing */ ;
175 prom_printf(".");
176 sec = MSTK_REG_SEC(regs);
178 prom_printf("\n");
180 /* Turn off kick start and set a "valid" time and date. */
181 tmp = mostek_read(regs + MOSTEK_CREG);
182 tmp |= MSTK_CREG_WRITE;
183 mostek_write(regs + MOSTEK_CREG, tmp);
184 tmp = mostek_read(regs + MOSTEK_HOUR);
185 tmp &= ~MSTK_KICK_START;
186 mostek_write(regs + MOSTEK_HOUR, tmp);
187 MSTK_SET_REG_SEC(regs,0);
188 MSTK_SET_REG_MIN(regs,0);
189 MSTK_SET_REG_HOUR(regs,0);
190 MSTK_SET_REG_DOW(regs,5);
191 MSTK_SET_REG_DOM(regs,1);
192 MSTK_SET_REG_MONTH(regs,8);
193 MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
194 tmp = mostek_read(regs + MOSTEK_CREG);
195 tmp &= ~MSTK_CREG_WRITE;
196 mostek_write(regs + MOSTEK_CREG, tmp);
198 /* Ensure the kick start bit is off. If it isn't, turn it off. */
199 while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {
200 prom_printf("CLOCK: Kick start still on!\n");
201 tmp = mostek_read(regs + MOSTEK_CREG);
202 tmp |= MSTK_CREG_WRITE;
203 mostek_write(regs + MOSTEK_CREG, tmp);
205 tmp = mostek_read(regs + MOSTEK_HOUR);
206 tmp &= ~MSTK_KICK_START;
207 mostek_write(regs + MOSTEK_HOUR, tmp);
209 tmp = mostek_read(regs + MOSTEK_CREG);
210 tmp &= ~MSTK_CREG_WRITE;
211 mostek_write(regs + MOSTEK_CREG, tmp);
214 prom_printf("CLOCK: Kick start procedure successful.\n");
217 /* Return nonzero if the clock chip battery is low. */
218 static int __init has_low_battery(void)
220 unsigned long regs = mstk48t02_regs;
221 u8 data1, data2;
223 data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */
224 mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */
225 data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */
226 mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */
228 return (data1 == data2); /* Was the write blocked? */
232 /* Probe for the real time clock chip. */
233 static void __init set_system_time(void)
235 unsigned int year, mon, day, hour, min, sec;
236 unsigned long mregs = mstk48t02_regs;
237 u8 tmp;
239 do_get_fast_time = do_gettimeofday;
241 if(!mregs) {
242 prom_printf("Something wrong, clock regs not mapped yet.\n");
243 prom_halt();
246 tmp = mostek_read(mregs + MOSTEK_CREG);
247 tmp |= MSTK_CREG_READ;
248 mostek_write(mregs + MOSTEK_CREG, tmp);
250 sec = MSTK_REG_SEC(mregs);
251 min = MSTK_REG_MIN(mregs);
252 hour = MSTK_REG_HOUR(mregs);
253 day = MSTK_REG_DOM(mregs);
254 mon = MSTK_REG_MONTH(mregs);
255 year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
256 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
257 xtime.tv_usec = 0;
259 tmp = mostek_read(mregs + MOSTEK_CREG);
260 tmp &= ~MSTK_CREG_READ;
261 mostek_write(mregs + MOSTEK_CREG, tmp);
264 void __init clock_probe(void)
266 struct linux_prom_registers clk_reg[2];
267 char model[128];
268 int node, busnd = -1, err;
269 unsigned long flags;
270 #ifdef CONFIG_PCI
271 struct linux_ebus *ebus = 0;
272 #endif
274 __save_and_cli(flags);
276 if(central_bus != NULL) {
277 busnd = central_bus->child->prom_node;
279 #ifdef CONFIG_PCI
280 else if (ebus_chain != NULL) {
281 ebus = ebus_chain;
282 busnd = ebus->prom_node;
284 #endif
285 else {
286 busnd = SBus_chain->prom_node;
289 if(busnd == -1) {
290 prom_printf("clock_probe: problem, cannot find bus to search.\n");
291 prom_halt();
294 node = prom_getchild(busnd);
296 while(1) {
297 if (!node)
298 model[0] = 0;
299 else
300 prom_getstring(node, "model", model, sizeof(model));
301 if(strcmp(model, "mk48t02") &&
302 strcmp(model, "mk48t08") &&
303 strcmp(model, "mk48t59")) {
304 if (node)
305 node = prom_getsibling(node);
306 #ifdef CONFIG_PCI
307 while ((node == 0) && ebus) {
308 ebus = ebus->next;
309 if (ebus) {
310 busnd = ebus->prom_node;
311 node = prom_getchild(busnd);
314 #endif
315 if(node == 0) {
316 prom_printf("clock_probe: Cannot find timer chip\n");
317 prom_halt();
319 continue;
322 err = prom_getproperty(node, "reg", (char *)clk_reg,
323 sizeof(clk_reg));
324 if(err == -1) {
325 prom_printf("clock_probe: Cannot get Mostek reg property\n");
326 prom_halt();
329 if(central_bus) {
330 prom_apply_fhc_ranges(central_bus->child, clk_reg, 1);
331 prom_apply_central_ranges(central_bus, clk_reg, 1);
333 #ifdef CONFIG_PCI
334 else if (ebus_chain) {
335 struct linux_ebus_device *edev;
337 for_each_ebusdev(edev, ebus)
338 if (edev->prom_node == node)
339 break;
340 if (!edev) {
341 prom_printf("%s: Mostek not probed by EBUS\n",
342 __FUNCTION__);
343 prom_halt();
346 mstk48t59_regs = edev->resource[0].start;
347 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
348 break;
350 #endif
351 else {
352 prom_adjust_regs(clk_reg, 1,
353 SBus_chain->sbus_ranges,
354 SBus_chain->num_sbus_ranges);
357 if(model[5] == '0' && model[6] == '2') {
358 mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
359 (((u64)clk_reg[0].which_io)<<32UL));
360 } else if(model[5] == '0' && model[6] == '8') {
361 mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
362 (((u64)clk_reg[0].which_io)<<32UL));
363 mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
364 } else {
365 mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
366 (((u64)clk_reg[0].which_io)<<32UL));
367 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
369 break;
372 /* Report a low battery voltage condition. */
373 if (has_low_battery())
374 prom_printf("NVRAM: Low battery voltage!\n");
376 /* Kick start the clock if it is completely stopped. */
377 if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
378 kick_start_clock();
380 set_system_time();
382 __restore_flags(flags);
385 #ifndef BCD_TO_BIN
386 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
387 #endif
389 #ifndef BIN_TO_BCD
390 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
391 #endif
393 extern void init_timers(void (*func)(int, void *, struct pt_regs *),
394 unsigned long *);
396 void __init time_init(void)
398 /* clock_probe() is now done at end of [se]bus_init on sparc64
399 * so that sbus, fhc and ebus bus information is probed and
400 * available.
402 unsigned long clock;
404 init_timers(timer_interrupt, &clock);
405 timer_tick_offset = clock / HZ;
406 timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020));
409 static __inline__ unsigned long do_gettimeoffset(void)
411 unsigned long ticks;
413 __asm__ __volatile__("
414 rd %%tick, %%g1
415 add %1, %%g1, %0
416 sub %0, %2, %0
418 : "=r" (ticks)
419 : "r" (timer_tick_offset), "r" (timer_tick_compare)
420 : "g1", "g2");
422 return (ticks * timer_ticks_per_usec_quotient) >> 32UL;
425 /* This need not obtain the xtime_lock as it is coded in
426 * an implicitly SMP safe way already.
428 void do_gettimeofday(struct timeval *tv)
430 /* Load doubles must be used on xtime so that what we get
431 * is guarenteed to be atomic, this is why we can run this
432 * with interrupts on full blast. Don't touch this... -DaveM
434 * Note with time_t changes to the timeval type, I must now use
435 * nucleus atomic quad 128-bit loads.
437 __asm__ __volatile__("
438 sethi %hi(timer_tick_offset), %g3
439 sethi %hi(xtime), %g2
440 sethi %hi(timer_tick_compare), %g1
441 ldx [%g3 + %lo(timer_tick_offset)], %g3
442 or %g2, %lo(xtime), %g2
443 or %g1, %lo(timer_tick_compare), %g1
444 1: ldda [%g2] 0x24, %o4
445 rd %tick, %o1
446 ldx [%g1], %g7
447 ldda [%g2] 0x24, %o2
448 xor %o4, %o2, %o2
449 xor %o5, %o3, %o3
450 orcc %o2, %o3, %g0
451 bne,pn %xcc, 1b
452 sethi %hi(lost_ticks), %o2
453 sethi %hi(timer_ticks_per_usec_quotient), %o3
454 ldx [%o2 + %lo(lost_ticks)], %o2
455 add %g3, %o1, %o1
456 ldx [%o3 + %lo(timer_ticks_per_usec_quotient)], %o3
457 sub %o1, %g7, %o1
458 mulx %o3, %o1, %o1
459 brz,pt %o2, 1f
460 srlx %o1, 32, %o1
461 sethi %hi(10000), %g2
462 or %g2, %lo(10000), %g2
463 add %o1, %g2, %o1
464 1: sethi %hi(1000000), %o2
465 srlx %o5, 32, %o5
466 or %o2, %lo(1000000), %o2
467 add %o5, %o1, %o5
468 cmp %o5, %o2
469 bl,a,pn %xcc, 1f
470 stx %o4, [%o0 + 0x0]
471 add %o4, 0x1, %o4
472 sub %o5, %o2, %o5
473 stx %o4, [%o0 + 0x0]
474 1: st %o5, [%o0 + 0x8]");
477 void do_settimeofday(struct timeval *tv)
479 write_lock_irq(&xtime_lock);
481 tv->tv_usec -= do_gettimeoffset();
482 if(tv->tv_usec < 0) {
483 tv->tv_usec += 1000000;
484 tv->tv_sec--;
487 xtime = *tv;
488 time_adjust = 0; /* stop active adjtime() */
489 time_status |= STA_UNSYNC;
490 time_maxerror = NTP_PHASE_LIMIT;
491 time_esterror = NTP_PHASE_LIMIT;
493 write_unlock_irq(&xtime_lock);
496 static int set_rtc_mmss(unsigned long nowtime)
498 int real_seconds, real_minutes, mostek_minutes;
499 unsigned long regs = mstk48t02_regs;
500 u8 tmp;
502 /* Not having a register set can lead to trouble. */
503 if (!regs)
504 return -1;
506 /* Read the current RTC minutes. */
507 tmp = mostek_read(regs + MOSTEK_CREG);
508 tmp |= MSTK_CREG_READ;
509 mostek_write(regs + MOSTEK_CREG, tmp);
511 mostek_minutes = MSTK_REG_MIN(regs);
513 tmp = mostek_read(regs + MOSTEK_CREG);
514 tmp &= ~MSTK_CREG_READ;
515 mostek_write(regs + MOSTEK_CREG, tmp);
518 * since we're only adjusting minutes and seconds,
519 * don't interfere with hour overflow. This avoids
520 * messing with unknown time zones but requires your
521 * RTC not to be off by more than 15 minutes
523 real_seconds = nowtime % 60;
524 real_minutes = nowtime / 60;
525 if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
526 real_minutes += 30; /* correct for half hour time zone */
527 real_minutes %= 60;
529 if (abs(real_minutes - mostek_minutes) < 30) {
530 tmp = mostek_read(regs + MOSTEK_CREG);
531 tmp |= MSTK_CREG_WRITE;
532 mostek_write(regs + MOSTEK_CREG, tmp);
534 MSTK_SET_REG_SEC(regs,real_seconds);
535 MSTK_SET_REG_MIN(regs,real_minutes);
537 tmp = mostek_read(regs + MOSTEK_CREG);
538 tmp &= ~MSTK_CREG_WRITE;
539 mostek_write(regs + MOSTEK_CREG, tmp);
540 } else
541 return -1;
543 return 0;