14 #include "rv_timer_regs.h"
16 static_assert(RV_TIMER_PARAM_N_HARTS > 0,
17 "RV Timer must support at least one hart.");
18 static_assert(RV_TIMER_PARAM_N_TIMERS > 0,
19 "RV Timer must support at least one timer per hart.");
31 static const ptrdiff_t kHartRegisterSpacing = 0x100;
37 static ptrdiff_t reg_for_hart(uint32_t hart, ptrdiff_t reg_offset) {
38 return kHartRegisterSpacing * (ptrdiff_t)hart + reg_offset;
44 static uint64_t euclidean_gcd(uint64_t a, uint64_t b) {
55 uint64_t clock_freq, uint64_t counter_freq,
66 uint64_t gcd = euclidean_gcd(clock_freq, counter_freq);
68 uint64_t prescale =
udiv64_slow(clock_freq, gcd, NULL) - 1;
69 uint64_t step =
udiv64_slow(counter_freq, gcd, NULL);
71 if (prescale > RV_TIMER_CFG0_PRESCALE_MASK ||
72 step > RV_TIMER_CFG0_STEP_MASK) {
85 if (timer == NULL || hart_id >= RV_TIMER_PARAM_N_HARTS) {
89 uint32_t config_value = 0;
91 config_value, RV_TIMER_CFG0_PRESCALE_FIELD, params.
prescale);
95 reg_for_hart(hart_id, RV_TIMER_CFG0_REG_OFFSET),
104 if (timer == NULL || hart_id >= RV_TIMER_PARAM_N_HARTS) {
111 RV_TIMER_CTRL_REG_OFFSET, hart_id);
115 RV_TIMER_CTRL_REG_OFFSET, hart_id);
125 uint32_t hart_id, uint64_t *out) {
126 if (timer == NULL || out == NULL || hart_id >= RV_TIMER_PARAM_N_HARTS) {
135 uint32_t upper = mmio_region_read32(
137 reg_for_hart(hart_id, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET));
138 uint32_t lower = mmio_region_read32(
140 reg_for_hart(hart_id, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET));
142 uint32_t overflow_check = mmio_region_read32(
144 reg_for_hart(hart_id, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET));
146 if (upper == overflow_check) {
147 *out = (((uint64_t)upper) << 32) | lower;
154 uint32_t hart_id, uint64_t count) {
155 if (timer == NULL || hart_id >= RV_TIMER_PARAM_N_HARTS) {
161 mmio_region_read32(timer->
base_addr, RV_TIMER_CTRL_REG_OFFSET);
163 mmio_region_write32(timer->
base_addr, RV_TIMER_CTRL_REG_OFFSET,
167 uint32_t lower_count = (uint32_t)count;
168 uint32_t upper_count = count >> 32;
170 reg_for_hart(hart_id, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET),
173 reg_for_hart(hart_id, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET),
177 mmio_region_write32(timer->
base_addr, RV_TIMER_CTRL_REG_OFFSET, ctrl_reg);
183 uint32_t comp_id, uint64_t threshold) {
184 if (timer == NULL || hart_id >= RV_TIMER_PARAM_N_HARTS ||
185 comp_id >= RV_TIMER_PARAM_N_TIMERS) {
189 uint32_t lower = (uint32_t)threshold;
190 uint32_t upper = threshold >> 32;
192 ptrdiff_t lower_reg =
193 reg_for_hart(hart_id, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) +
194 (ptrdiff_t)(
sizeof(uint64_t) * comp_id);
195 ptrdiff_t upper_reg =
196 reg_for_hart(hart_id, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) +
197 (ptrdiff_t)(
sizeof(uint64_t) * comp_id);
202 mmio_region_write32(timer->
base_addr, upper_reg, UINT32_MAX);
205 mmio_region_write32(timer->
base_addr, lower_reg, lower);
207 mmio_region_write32(timer->
base_addr, upper_reg, upper);
218 mmio_region_write32(timer->
base_addr, RV_TIMER_CTRL_REG_OFFSET, 0x0);
220 for (uint32_t hart_id = 0; hart_id < RV_TIMER_PARAM_N_HARTS; ++hart_id) {
222 ptrdiff_t irq_status =
223 reg_for_hart(hart_id, RV_TIMER_INTR_STATE0_REG_OFFSET);
224 ptrdiff_t irq_enable =
225 reg_for_hart(hart_id, RV_TIMER_INTR_ENABLE0_REG_OFFSET);
226 mmio_region_write32(timer->
base_addr, irq_enable, 0x0);
227 mmio_region_write32(timer->
base_addr, irq_status, UINT32_MAX);
230 for (uint32_t comp_id = 0; comp_id < RV_TIMER_PARAM_N_TIMERS; ++comp_id) {
241 reg_for_hart(hart_id, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
244 reg_for_hart(hart_id, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);