1/* @title: HPET */
2#pragma once
3#include <compiler.h>
4#include <drivers/mmio.h>
5#include <stdatomic.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <types/types.h>
9
10void hpet_init(void);
11uint64_t hpet_timestamp_ns(void);
12void hpet_program_oneshot(uint64_t future_ms);
13uint64_t hpet_timestamp_ms(void);
14uint64_t hpet_timestamp_us(void);
15
16void hpet_disable(void);
17void hpet_enable(void);
18void hpet_clear_interrupt_status(void);
19void hpet_setup_timer(uint8_t timer_index, irq_t irq_line, bool periodic,
20 bool edge_triggered);
21
22#define HPET_GEN_CAP_ID_OFFSET 0x0
23#define HPET_GEN_CONF_OFFSET 0x10
24#define HPET_GEN_INT_STAT_OFFSET 0x20
25#define HPET_IRQ_BASE 2
26#define HPET_MAIN_COUNTER_OFFSET 0xF0
27extern uint64_t *hpet_base;
28extern uint64_t hpet_timer_count;
29extern uint64_t hpet_fs_per_tick;
30
31#define HPET_TIMER_CONF_OFFSET(num) (0x100 + (num * 0x20))
32#define HPET_TIMER_COMPARATOR_OFFSET(num) (HPET_TIMER_CONF_OFFSET(num) + 0x8)
33#define HPET_CURRENT (smp_core_id() % hpet_timer_count)
34
35#define HPET_IRQ_LINE 2
36
37union hpet_timer_general_capabilities {
38 uint64_t raw;
39 struct {
40 uint64_t rev_id : 7; /* Revision ID */
41 uint64_t num_timers : 5; /* Number of timers */
42 uint64_t counter_size : 1; /* 0 = 32 bits wide, 1 = 64 bits wide */
43 uint64_t reserved : 1;
44 uint64_t leg_rt_cap : 1; /* Legacy replacement route capable */
45 uint64_t vendor_id : 16;
46 uint64_t counter_clock_period : 32;
47 };
48} __packed;
49
50union hpet_timer_config {
51 uint64_t raw;
52 struct {
53 uint64_t reserved0 : 1;
54 uint64_t interrupt_type : 1; /* 0 = edge, 1 = level */
55 uint64_t interrupt_enable : 1; /* 1 = interrupt enabled */
56 uint64_t type : 1; /* 0 = one-shot, 1 = periodic */
57 uint64_t periodic_capable : 1; /* read-only */
58 uint64_t size_capable : 1; /* read-only, 1 = 64-bit capable */
59 uint64_t value_set : 1;
60 uint64_t reserved1 : 1;
61 uint64_t timer_32bit : 1;
62 uint64_t ioapic_route : 5;
63 uint64_t fsb_int_enable : 1;
64 uint64_t fsb_int_delivery : 1;
65 uint64_t reserved2 : 16;
66 uint64_t route_cap : 32;
67 };
68} __packed;
69
70static inline void hpet_write64(uint64_t offset, uint64_t value) {
71 mmio_write_64(address: (void *) ((uintptr_t) hpet_base + offset), value);
72}
73
74static inline uint64_t hpet_read64(uint64_t offset) {
75 return mmio_read_64(address: (void *) ((uintptr_t) hpet_base + offset));
76}
77