#ifndef ARMCLOCK_H #define ARMCLOCK_H #include #include "global.h" #define ARMCLK_LOAD (ARM_BASE + 0x400) #define ARMCLK_VALUE (ARM_BASE + 0x404) #define ARMCLK_CONTROL (ARM_BASE + 0x408) #define ARMCLK_IRQ_CLR_ACK (ARM_BASE + 0x40C) #define ARMCLK_RAW_IRQ (ARM_BASE + 0x410) #define ARMCLK_MASKED_IRQ (ARM_BASE + 0x414) #define ARMCLK_RELOAD (ARM_BASE + 0x418) #define ARMCLK_PRE_DRIVER (ARM_BASE + 0x41C) #define ARMCLK_FREE_RUNNING_COUNTER (ARM_BASE + 0x420) typedef union armclk_control { uint32_t raw; struct { uint32_t one_shot_mode : 1; // bit 0; unused in RPi uint32_t counter_23bit : 1; // bit 1 uint32_t pre_scale : 2; // bits 3:2 uint32_t bit_4 : 1; // bit 4 uint32_t interrupt_enable : 1; // bit 5 uint32_t periodic_mode : 1; // bit 6; unused in RPi uint32_t timer_enable : 1; // bit 7 uint32_t halt_in_debug : 1; // bit 8 uint32_t free_running_enable : 1; // bit 9 uint32_t bits_15_10 : 6; // bits 15:10 uint32_t free_running_pre_scaler : 8; // bits 23:16 uint32_t bits_31_24 : 8; // bits 31:24 } fields; } armclk_control_t; static inline void armclk_init(void) { armclk_control_t ctrl = (armclk_control_t) (uint32_t) 0; ctrl.fields.timer_enable = 1; ctrl.fields.interrupt_enable = 1; ctrl.fields.counter_23bit = 1; wr32(ARMCLK_CONTROL, ctrl.raw); } static inline void armclk_enable_timer_irq(void) { armclk_control_t ctrl = (armclk_control_t) rd32(ARMCLK_CONTROL); ctrl.fields.interrupt_enable = 1; wr32(ARMCLK_CONTROL, ctrl.raw); wr32(ARM_ENABLE_BASIC_IRQS, 1); } static inline void armclk_disable_timer_irq(void) { armclk_control_t ctrl = (armclk_control_t) rd32(ARMCLK_CONTROL); ctrl.fields.interrupt_enable = 0; wr32(ARMCLK_CONTROL, ctrl.raw); wr32(ARM_DISABLE_BASIC_IRQS, 1); } static inline void armclk_irq_settimeout(uint32_t timeout) { wr32(ARMCLK_IRQ_CLR_ACK, 0); wr32(ARMCLK_LOAD, timeout); } static inline _Bool armclk_irq_pending(void) { return rd32(ARM_IRQ_BASIC_PENDING) & 1; } #endif // ARMCLOCK_H