uboot/arch/x86/lib/tsc_timer.c
<<
>>
Prefs
   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