1/* 2 * Copyright (c) 2012 The Chromium OS Authors. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7#include <common.h> 8#include <malloc.h> 9#include <asm/io.h> 10#include <asm/i8254.h> 11#include <asm/ibmpc.h> 12#include <asm/msr.h> 13#include <asm/u-boot-x86.h> 14 15DECLARE_GLOBAL_DATA_PTR; 16 17void timer_set_base(u64 base) 18{ 19 gd->arch.tsc_base = base; 20} 21 22/* 23 * Get the number of CPU time counter ticks since it was read first time after 24 * restart. This yields a free running counter guaranteed to take almost 6 25 * years to wrap around even at 100GHz clock rate. 26 */ 27u64 __attribute__((no_instrument_function)) get_ticks(void) 28{ 29 u64 now_tick = rdtsc(); 30 31 /* We assume that 0 means the base hasn't been set yet */ 32 if (!gd->arch.tsc_base) 33 panic("No tick base available"); 34 return now_tick - gd->arch.tsc_base; 35} 36 37#define PLATFORM_INFO_MSR 0xce 38 39/* Get the speed of the TSC timer in MHz */ 40unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) 41{ 42 u32 ratio; 43 u64 platform_info = native_read_msr(PLATFORM_INFO_MSR); 44 45 /* 100MHz times Max Non Turbo ratio */ 46 ratio = (platform_info >> 8) & 0xff; 47 return 100 * ratio; 48} 49 50unsigned long get_tbclk(void) 51{ 52 return get_tbclk_mhz() * 1000 * 1000; 53} 54 55static ulong get_ms_timer(void) 56{ 57 return (get_ticks() * 1000) / get_tbclk(); 58} 59 60ulong get_timer(ulong base) 61{ 62 return get_ms_timer() - base; 63} 64 65ulong __attribute__((no_instrument_function)) timer_get_us(void) 66{ 67 return get_ticks() / get_tbclk_mhz(); 68} 69 70ulong timer_get_boot_us(void) 71{ 72 return timer_get_us(); 73} 74 75void __udelay(unsigned long usec) 76{ 77 u64 now = get_ticks(); 78 u64 stop; 79 80 stop = now + usec * get_tbclk_mhz(); 81 82 while ((int64_t)(stop - get_ticks()) > 0) 83 ; 84} 85 86int timer_init(void) 87{ 88#ifdef CONFIG_SYS_PCAT_TIMER 89 /* Set up the PCAT timer if required */ 90 pcat_timer_init(); 91#endif 92 93 return 0; 94} 95