| 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 | |
| 10 | void hpet_init(void); |
| 11 | uint64_t hpet_timestamp_ns(void); |
| 12 | void hpet_program_oneshot(uint64_t future_ms); |
| 13 | uint64_t hpet_timestamp_ms(void); |
| 14 | uint64_t hpet_timestamp_us(void); |
| 15 | |
| 16 | void hpet_disable(void); |
| 17 | void hpet_enable(void); |
| 18 | void hpet_clear_interrupt_status(void); |
| 19 | void 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 |
| 27 | extern uint64_t *hpet_base; |
| 28 | extern uint64_t hpet_timer_count; |
| 29 | extern 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 | |
| 37 | union 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 | |
| 50 | union 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 | |
| 70 | static inline void hpet_write64(uint64_t offset, uint64_t value) { |
| 71 | mmio_write_64(address: (void *) ((uintptr_t) hpet_base + offset), value); |
| 72 | } |
| 73 | |
| 74 | static inline uint64_t hpet_read64(uint64_t offset) { |
| 75 | return mmio_read_64(address: (void *) ((uintptr_t) hpet_base + offset)); |
| 76 | } |
| 77 | |