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