diff options
Diffstat (limited to 'src/clock')
-rw-r--r-- | src/clock/armclock.h | 76 | ||||
-rw-r--r-- | src/clock/bcmclock.h | 35 |
2 files changed, 111 insertions, 0 deletions
diff --git a/src/clock/armclock.h b/src/clock/armclock.h new file mode 100644 index 0000000..0d83fc2 --- /dev/null +++ b/src/clock/armclock.h @@ -0,0 +1,76 @@ +#ifndef ARMCLOCK_H +#define ARMCLOCK_H + +#include <stdint.h> + +#include "../global.h" +#include "../interrupts/interrupts.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 diff --git a/src/clock/bcmclock.h b/src/clock/bcmclock.h new file mode 100644 index 0000000..d08912b --- /dev/null +++ b/src/clock/bcmclock.h @@ -0,0 +1,35 @@ +#ifndef BCMCLOCK_H +#define BCMCLOCK_H + +#include <stdint.h> +#include "../interrupts/interrupts.h" +#include "../global.h" + +#define ST_BASE (PERIF_BASE + 0x3000) // System Timer + +#define ST_CS (ST_BASE + 0x0) // System Timer Control/Status +#define ST_CLO (ST_BASE + 0x4) // System Timer Counter Lower 32 bits +#define ST_CHI (ST_BASE + 0x8) // System Timer Counter Higher 32 bits +#define ST_C0 (ST_BASE + 0xC) // System Timer Compare 0 +#define ST_C1 (ST_BASE + 0x10) // System Timer Compare 1 +#define ST_C2 (ST_BASE + 0x14) // System Timer Compare 2 +#define ST_C3 (ST_BASE + 0x18) // System Timer Compare 3 + +static inline void bcmclk_enable_timer_irq(void) +{ + wr32(ARM_ENABLE_IRQS_1, 1 << 3); +} + +static inline void bcmclk_disable_timer_irq(void) +{ + wr32(ARM_DISABLE_IRQS_1, 1 << 3); +} + +static inline void bcmclk_irq_settimeout(uint32_t timeout) +{ + uint32_t clock_now = rd32(ST_CLO); + wr32(ST_C3, clock_now + timeout); + wr32(ST_CS, 1 << 3); +} + +#endif // BCMCLOCK_H |