2 * Copyright 2007, François Revol, revol@free.fr.
3 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>. All rights reserved.
4 * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de
5 * Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
7 * Distributed under the terms of the MIT License.
10 #include <arch/real_time_clock.h>
12 #include <arch_platform.h>
13 #include <boot/kernel_args.h>
14 #include <real_time_clock.h>
15 #include <real_time_data.h>
36 numh
= (bcd
& 0xf0) >> 4;
38 return numh
* 10 + numl
;
43 int_to_bcd(uint32 number
)
54 return (high
<< 4) | low
;
59 same_time(const cmos_time
*time1
, const cmos_time
*time2
)
61 return time1
->second
== time2
->second
62 && time1
->minute
== time2
->minute
63 && time1
->hour
== time2
->hour
64 && time1
->day
== time2
->day
65 && time1
->month
== time2
->month
66 && time1
->year
== time2
->year
67 && time1
->century
== time2
->century
;
74 return M68KPlatform::Default()->ReadRTCReg(addr
);
79 cmos_write(uint8 addr
, uint8 data
)
81 M68KPlatform::Default()->WriteRTCReg(addr
, data
);
86 set_24_hour_mode(void)
90 status_b
= cmos_read(0x0b);
92 cmos_write(0x0b, status_b
);
97 read_cmos_clock(cmos_time
*cmos
)
101 cmos
->century
= cmos_read(0x32);
102 cmos
->year
= cmos_read(0x09);
103 cmos
->month
= cmos_read(0x08);
104 cmos
->day
= cmos_read(0x07);
105 cmos
->hour
= cmos_read(0x04);
106 cmos
->minute
= cmos_read(0x02);
107 cmos
->second
= cmos_read(0x00);
112 write_cmos_clock(cmos_time
*cmos
)
116 cmos_write(0x32, cmos
->century
);
117 cmos_write(0x09, cmos
->year
);
118 cmos_write(0x08, cmos
->month
);
119 cmos_write(0x07, cmos
->day
);
120 cmos_write(0x04, cmos
->hour
);
121 cmos_write(0x02, cmos
->minute
);
122 cmos_write(0x00, cmos
->second
);
127 cmos_to_secs(const cmos_time
*cmos
)
130 t
.tm_year
= bcd_to_int(cmos
->century
) * 100 + bcd_to_int(cmos
->year
)
131 - RTC_EPOCH_BASE_YEAR
;
132 t
.tm_mon
= bcd_to_int(cmos
->month
) - 1;
133 t
.tm_mday
= bcd_to_int(cmos
->day
);
134 t
.tm_hour
= bcd_to_int(cmos
->hour
);
135 t
.tm_min
= bcd_to_int(cmos
->minute
);
136 t
.tm_sec
= bcd_to_int(cmos
->second
);
138 return rtc_tm_to_secs(&t
);
143 secs_to_cmos(uint32 seconds
, cmos_time
*cmos
)
148 rtc_secs_to_tm(seconds
, &t
);
150 wholeYear
= t
.tm_year
+ RTC_EPOCH_BASE_YEAR
;
152 cmos
->century
= int_to_bcd(wholeYear
/ 100);
153 cmos
->year
= int_to_bcd(wholeYear
% 100);
154 cmos
->month
= int_to_bcd(t
.tm_mon
+ 1);
155 cmos
->day
= int_to_bcd(t
.tm_mday
);
156 cmos
->hour
= int_to_bcd(t
.tm_hour
);
157 cmos
->minute
= int_to_bcd(t
.tm_min
);
158 cmos
->second
= int_to_bcd(t
.tm_sec
);
166 static spinlock sSetArchDataLock
;
169 arch_rtc_init(kernel_args
*args
, struct real_time_data
*data
)
171 // init the platform RTC service
172 status_t error
= M68KPlatform::Default()->InitRTC(args
, data
);
176 // init the arch specific part of the real_time_data
177 data
->arch_data
.data
[0].system_time_offset
= 0;
178 // cvFactor = 2^32 * 1000000 / tbFreq
179 // => (tb * cvFactor) >> 32 = (tb * 2^32 * 1000000 / tbFreq) >> 32
180 // = tb / tbFreq * 1000000 = time in us
181 data
->arch_data
.system_time_conversion_factor
182 = uint32((uint64(1) << 32) * 1000000
183 / args
->arch_args
.time_base_frequency
);
184 data
->arch_data
.version
= 0;
187 B_INITIALIZE_SPINLOCK(&sSetArchDataLock
);
189 // init system_time() conversion factor
190 __m68k_setup_system_time(&data
->arch_data
.system_time_conversion_factor
);
197 arch_rtc_get_hw_time(void)
199 return M68KPlatform::Default()->GetHardwareRTC();
204 arch_rtc_set_hw_time(uint32 seconds
)
206 M68KPlatform::Default()->SetHardwareRTC(seconds
);
211 arch_rtc_set_system_time_offset(struct real_time_data
*data
, bigtime_t offset
)
213 cpu_status state
= disable_interrupts();
214 acquire_spinlock(&sSetArchDataLock
);
216 int32 version
= data
->arch_data
.version
+ 1;
217 data
->arch_data
.data
[version
% 2].system_time_offset
= offset
;
218 data
->arch_data
.version
= version
;
220 release_spinlock(&sSetArchDataLock
);
221 restore_interrupts(state
);
226 arch_rtc_get_system_time_offset(struct real_time_data
*data
)
231 version
= data
->arch_data
.version
;
232 offset
= data
->arch_data
.data
[version
% 2].system_time_offset
;
233 } while (version
!= data
->arch_data
.version
);