xref: /haiku/src/system/kernel/arch/ppc/arch_real_time_clock.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include <arch/real_time_clock.h>
7 
8 #include <arch_platform.h>
9 #include <boot/kernel_args.h>
10 #include <real_time_data.h>
11 #include <smp.h>
12 
13 
14 static spinlock sSetArchDataLock;
15 
16 status_t
17 arch_rtc_init(kernel_args *args, struct real_time_data *data)
18 {
19 	// init the platform RTC service
20 	status_t error = PPCPlatform::Default()->InitRTC(args, data);
21 	if (error != B_OK)
22 		return error;
23 
24 	// init the arch specific part of the real_time_data
25 	data->arch_data.data[0].system_time_offset = 0;
26 	// cvFactor = 2^32 * 1000000 / tbFreq
27 	// => (tb * cvFactor) >> 32 = (tb * 2^32 * 1000000 / tbFreq) >> 32
28 	//    = tb / tbFreq * 1000000 = time in us
29 	data->arch_data.system_time_conversion_factor
30 		= uint32((uint64(1) << 32) * 1000000
31 			/ args->arch_args.time_base_frequency);
32 	data->arch_data.version = 0;
33 
34 	// init spinlock
35 	B_INITIALIZE_SPINLOCK(&sSetArchDataLock);
36 
37 	// init system_time() conversion factor
38 	__ppc_setup_system_time(&data->arch_data.system_time_conversion_factor);
39 
40 	return B_OK;
41 }
42 
43 
44 uint32
45 arch_rtc_get_hw_time(void)
46 {
47 	return PPCPlatform::Default()->GetHardwareRTC();
48 }
49 
50 
51 void
52 arch_rtc_set_hw_time(uint32 seconds)
53 {
54 	PPCPlatform::Default()->SetHardwareRTC(seconds);
55 }
56 
57 
58 void
59 arch_rtc_set_system_time_offset(struct real_time_data *data, bigtime_t offset)
60 {
61 	cpu_status state = disable_interrupts();
62 	acquire_spinlock(&sSetArchDataLock);
63 
64 	int32 version = data->arch_data.version + 1;
65 	data->arch_data.data[version % 2].system_time_offset = offset;
66 	data->arch_data.version = version;
67 
68 	release_spinlock(&sSetArchDataLock);
69 	restore_interrupts(state);
70 }
71 
72 
73 bigtime_t
74 arch_rtc_get_system_time_offset(struct real_time_data *data)
75 {
76 	int32 version;
77 	bigtime_t offset;
78 	do {
79 		version = data->arch_data.version;
80 		offset = data->arch_data.data[version % 2].system_time_offset;
81 	} while (version != data->arch_data.version);
82 
83 	return offset;
84 }
85