1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <platsupport/arch/tsc.h> 14#include <utils/time.h> 15#include <stdio.h> 16 17#define WAIT_SECONDS 2ull 18#define WAIT_NS (NS_IN_S * WAIT_SECONDS) /* 2 seconds in nano seconds to wait for */ 19 20uint64_t tsc_freq_hint = 0; 21 22uint64_t tsc_calculate_frequency_hpet(const hpet_t *hpet) 23{ 24 if (tsc_freq_hint) { 25 return tsc_freq_hint; 26 } 27 uint64_t tsc_start = rdtsc_pure(); 28 uint64_t hpet_start = hpet_get_time(hpet); 29 /* spin until WAIT_NS has passed */ 30 while (hpet_get_time(hpet) - hpet_start < WAIT_NS); 31 uint64_t tsc_end = rdtsc_pure(); 32 return (tsc_end - tsc_start) / WAIT_SECONDS; 33} 34 35uint64_t tsc_calculate_frequency_pit(pit_t *pit) 36{ 37 if (tsc_freq_hint) { 38 return tsc_freq_hint; 39 } 40 /* the PIT should be able to set a timeout for 50 ms */ 41 uint64_t wait_ns = 50 * NS_IN_MS; 42 43 int UNUSED error = pit_set_timeout(pit, wait_ns, true); 44 assert(error == 0); 45 46 uint64_t start_time = rdtsc_pure(); 47 uint64_t last_absolute = 0; 48 uint64_t total_observed = 0; 49 uint64_t time_offset = pit_get_time(pit); 50 uint64_t last_time = time_offset; 51 52 while (total_observed + last_absolute < WAIT_NS) { 53 uint64_t current_time = pit_get_time(pit); 54 if (current_time > last_time) { 55 total_observed += wait_ns; 56 } 57 last_absolute = wait_ns - current_time + time_offset; 58 last_time = current_time; 59 } 60 uint64_t end_time = rdtsc_pure(); 61 /* well that was a fucking trial. Now hopefully we got something sane */ 62 return (end_time - start_time) / WAIT_SECONDS; 63} 64