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
14static spinlock sSetArchDataLock;
15
16status_t
17arch_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	sSetArchDataLock = 0;
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
44uint32
45arch_rtc_get_hw_time(void)
46{
47	return PPCPlatform::Default()->GetHardwareRTC();
48}
49
50
51void
52arch_rtc_set_hw_time(uint32 seconds)
53{
54	PPCPlatform::Default()->SetHardwareRTC(seconds);
55}
56
57
58void
59arch_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
73bigtime_t
74arch_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