Blame view
arch/mips/dec/time.c
4.22 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 |
* Copyright (C) 1991, 1992, 1995 Linus Torvalds * Copyright (C) 2000, 2003 Maciej W. Rozycki * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * */ #include <linux/bcd.h> |
1da177e4c Linux-2.6.12-rc2 |
10 |
#include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
11 |
#include <linux/mc146818rtc.h> |
1da177e4c Linux-2.6.12-rc2 |
12 |
#include <linux/param.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
14 15 16 |
#include <asm/cpu-features.h> #include <asm/ds1287.h> #include <asm/time.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 |
#include <asm/dec/interrupts.h> #include <asm/dec/ioasic.h> |
1da177e4c Linux-2.6.12-rc2 |
19 |
#include <asm/dec/machtype.h> |
d4f587c67 timekeeping: Incr... |
20 |
void read_persistent_clock(struct timespec *ts) |
1da177e4c Linux-2.6.12-rc2 |
21 22 |
{ unsigned int year, mon, day, hour, min, sec, real_year; |
53c2df2f4 Use rtc_lock to p... |
23 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
53c2df2f4 Use rtc_lock to p... |
25 |
spin_lock_irqsave(&rtc_lock, flags); |
ddcabb4fc [PATCH] RTC: Remo... |
26 |
|
1da177e4c Linux-2.6.12-rc2 |
27 28 29 30 31 32 33 |
do { sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); |
ddcabb4fc [PATCH] RTC: Remo... |
34 35 36 37 38 39 |
/* * The PROM will reset the year to either '72 or '73. * Therefore we store the real year separately, in one * of unused BBU RAM locations. */ real_year = CMOS_READ(RTC_DEC_YEAR); |
1da177e4c Linux-2.6.12-rc2 |
40 |
} while (sec != CMOS_READ(RTC_SECONDS)); |
ddcabb4fc [PATCH] RTC: Remo... |
41 42 |
spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
43 |
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
02112dbc9 mips: use bcd2bin... |
44 45 46 47 48 49 |
sec = bcd2bin(sec); min = bcd2bin(min); hour = bcd2bin(hour); day = bcd2bin(day); mon = bcd2bin(mon); year = bcd2bin(year); |
1da177e4c Linux-2.6.12-rc2 |
50 |
} |
ddcabb4fc [PATCH] RTC: Remo... |
51 |
|
1da177e4c Linux-2.6.12-rc2 |
52 |
year += real_year - 72 + 2000; |
d4f587c67 timekeeping: Incr... |
53 54 |
ts->tv_sec = mktime(year, mon, day, hour, min, sec); ts->tv_nsec = 0; |
1da177e4c Linux-2.6.12-rc2 |
55 56 57 |
} /* |
4b550488f [MIPS] Deforest t... |
58 |
* In order to set the CMOS clock precisely, rtc_mips_set_mmss has to |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 62 63 |
* be called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will * jump to the next second precisely 500 ms later. Check the Dallas * DS1287 data sheet for details. */ |
4b550488f [MIPS] Deforest t... |
64 |
int rtc_mips_set_mmss(unsigned long nowtime) |
1da177e4c Linux-2.6.12-rc2 |
65 66 67 68 |
{ int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; |
53c2df2f4 Use rtc_lock to p... |
69 70 |
/* irq are locally disabled here */ spin_lock(&rtc_lock); |
1da177e4c Linux-2.6.12-rc2 |
71 72 73 74 75 76 77 78 79 80 |
/* tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); /* stop and reset prescaler */ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
02112dbc9 mips: use bcd2bin... |
81 |
cmos_minutes = bcd2bin(cmos_minutes); |
1da177e4c Linux-2.6.12-rc2 |
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
/* * since we're only adjusting minutes and seconds, * don't interfere with hour overflow. This avoids * messing with unknown time zones but requires your * RTC not to be off by more than 15 minutes */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) real_minutes += 30; /* correct for half hour time zone */ real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
02112dbc9 mips: use bcd2bin... |
97 98 |
real_seconds = bin2bcd(real_seconds); real_minutes = bin2bcd(real_minutes); |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 102 |
} CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); } else { |
3e5c12409 set_rtc_mmss: sho... |
103 |
printk_once(KERN_NOTICE |
1da177e4c Linux-2.6.12-rc2 |
104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
"set_rtc_mmss: can't update from %d to %d ", cmos_minutes, real_minutes); retval = -1; } /* The following flags have to be released exactly in this order, * otherwise the DS1287 will not reset the oscillator and will not * update precisely 500 ms later. You won't find this mentioned * in the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
53c2df2f4 Use rtc_lock to p... |
118 |
spin_unlock(&rtc_lock); |
1da177e4c Linux-2.6.12-rc2 |
119 120 121 |
return retval; } |
6457d9fc3 [MIPS] DS1287: Ad... |
122 |
void __init plat_time_init(void) |
1da177e4c Linux-2.6.12-rc2 |
123 |
{ |
6457d9fc3 [MIPS] DS1287: Ad... |
124 125 |
u32 start, end; int i = HZ / 10; |
1da177e4c Linux-2.6.12-rc2 |
126 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
127 128 |
/* Set up the rate of periodic DS1287 interrupts. */ ds1287_set_base_clock(HZ); |
1da177e4c Linux-2.6.12-rc2 |
129 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
130 131 132 |
if (cpu_has_counter) { while (!ds1287_timer_state()) ; |
1da177e4c Linux-2.6.12-rc2 |
133 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
134 |
start = read_c0_count(); |
1da177e4c Linux-2.6.12-rc2 |
135 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
136 137 138 139 140 |
while (i--) while (!ds1287_timer_state()) ; end = read_c0_count(); |
1da177e4c Linux-2.6.12-rc2 |
141 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
142 143 144 145 146 |
mips_hpt_frequency = (end - start) * 10; printk(KERN_INFO "MIPS counter frequency %dHz ", mips_hpt_frequency); } else if (IOASIC) |
1da177e4c Linux-2.6.12-rc2 |
147 |
/* For pre-R4k systems we use the I/O ASIC's counter. */ |
4247417d8 [MIPS] add DECsta... |
148 |
dec_ioasic_clocksource_init(); |
1da177e4c Linux-2.6.12-rc2 |
149 |
|
6457d9fc3 [MIPS] DS1287: Ad... |
150 |
ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); |
1da177e4c Linux-2.6.12-rc2 |
151 |
} |