coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
apic_timer.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <console/console.h>
5 #include <delay.h>
6 #include <thread.h>
7 #include <cpu/x86/lapic.h>
8 
9 void init_timer(void)
10 {
11  /* Set the APIC timer to no interrupts and periodic mode */
13 
14  /* Set the divider to 1, no divider */
16 
17  /* Set the initial counter to 0xffffffff */
18  lapic_write(LAPIC_TMICT, 0xffffffff);
19 }
20 
21 void udelay(u32 usecs)
22 {
23  u32 start, value, ticks, timer_fsb;
24 
25  if (!thread_yield_microseconds(usecs))
26  return;
27 
29  if (!timer_fsb || (lapic_read(LAPIC_LVTT) &
32  init_timer();
34  }
35 
36  /* Calculate the number of ticks to run, our FSB runs at timer_fsb Mhz
37  */
38  ticks = usecs * timer_fsb;
39  start = lapic_read(LAPIC_TMCCT);
40  do {
42  } while ((start - value) < ticks);
43 }
44 
45 #if CONFIG(LAPIC_MONOTONIC_TIMER)
46 #include <timer.h>
47 
48 static struct monotonic_counter {
49  int initialized;
50  struct mono_time time;
52 } mono_counter;
53 
54 void timer_monotonic_get(struct mono_time *mt)
55 {
56  uint32_t current_tick;
57  uint32_t usecs_elapsed;
59 
61  init_timer();
63  /* An FSB frequency of 200Mhz provides a 20 second polling
64  * interval between timer_monotonic_get() calls before wrap
65  * around occurs. */
66  if (timer_fsb > 200)
68  "apic timer freq (%d) may be too fast.\n",
69  timer_fsb);
72  }
73 
75  current_tick = lapic_read(LAPIC_TMCCT);
76  /* Note that the APIC timer counts down. */
77  usecs_elapsed = (mono_counter.last_value - current_tick) / timer_fsb;
78 
79  /* Update current time and tick values only if a full tick occurred. */
80  if (usecs_elapsed) {
81  mono_time_add_usecs(&mono_counter.time, usecs_elapsed);
82  mono_counter.last_value = current_tick;
83  }
84 
85  /* Save result. */
86  *mt = mono_counter.time;
87 }
88 #endif
void udelay(u32 usecs)
Definition: apic_timer.c:21
void init_timer(void)
Definition: apic_timer.c:9
pte_t value
Definition: mmu.c:91
void timer_monotonic_get(struct mono_time *mt)
Definition: arch_timer.c:6
#define printk(level,...)
Definition: stdlib.h:16
static u32 timer_fsb
Definition: fsb.c:12
u32 get_timer_fsb(void)
Definition: fsb.c:109
static void mono_time_add_usecs(struct mono_time *mt, long us)
Definition: timer.h:65
static __always_inline void lapic_write(unsigned int reg, uint32_t v)
Definition: lapic.h:83
static __always_inline uint32_t lapic_read(unsigned int reg)
Definition: lapic.h:75
#define LAPIC_TMCCT
Definition: lapic_def.h:83
#define LAPIC_TDCR
Definition: lapic_def.h:84
#define LAPIC_TMICT
Definition: lapic_def.h:82
#define LAPIC_LVTT
Definition: lapic_def.h:55
#define LAPIC_LVT_TIMER_PERIODIC
Definition: lapic_def.h:64
#define LAPIC_TDR_DIV_1
Definition: lapic_def.h:86
#define LAPIC_LVT_MASKED
Definition: lapic_def.h:65
int thread_yield_microseconds(unsigned int microsecs)
Definition: thread.c:342
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
static struct monotonic_counter mono_counter
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
uint64_t last_value
Definition: arch_timer.c:17
struct mono_time time
Definition: arch_timer.c:16