This commit is contained in:
Imbus 2025-10-30 22:36:50 +01:00
parent 623f3e8335
commit 3e94e11212
2 changed files with 43 additions and 29 deletions

View file

@ -1,3 +1,6 @@
#include "stdio.h"
#include <assert.h>
#include <rtc.h>
#include <stdint.h>
#define VIRT_RTC_BASE 0x0101000UL
@ -8,49 +11,55 @@
#define RTC_ALARM_LOW 0x08
#define RTC_ALARM_HIGH 0x0c
#define RTC_IRQ_ENABLED 0x10
#define RTC_CLEAR_ALARM 0x14
#define RTC_ALARM_STATUS 0x18
#define RTC_CLEAR_INTERRUPT 0x1c
#define RTC_ALARM_STATUS 0x18
#define RTC_CLEAR_ALARM 0x14
static inline uint32_t mmio_read32(uintptr_t addr) {
return *(volatile uint32_t *)addr;
}
#define RTC_IRQ_ENABLED 0x10
#define RTC_IRQ_CLEAR 0x1c
static inline void mmio_write32(uintptr_t addr, uint32_t value) {
*(volatile uint32_t *)addr = value;
}
#define REG32(addr) (*((volatile uint32_t *)(addr)))
#define REG64(addr) (*((volatile uint64_t *)(addr)))
#define GF_REG32(offset) (REG32(VIRT_RTC_BASE + offset))
#define GF_REG64(offset) (REG64(VIRT_RTC_BASE + offset))
/* Read the current time of the RTC */
uint64_t rtc_time_read(void) {
uint32_t low = mmio_read32(VIRT_RTC_BASE + RTC_TIME_LOW);
uint32_t high = mmio_read32(VIRT_RTC_BASE + RTC_TIME_HIGH);
uint32_t low = GF_REG32(RTC_TIME_LOW); // mmio_read32(VIRT_RTC_BASE + RTC_TIME_LOW);
uint32_t high = GF_REG32(RTC_TIME_HIGH);
return ((uint64_t)high << 32) | low;
}
/* Set the time of the RTC */
void rtc_time_set(uint64_t ns) {
mmio_write32(VIRT_RTC_BASE + RTC_TIME_LOW, ns);
mmio_write32(VIRT_RTC_BASE + RTC_TIME_HIGH, ns);
GF_REG32(RTC_TIME_HIGH) = ns >> 32;
GF_REG32(RTC_TIME_LOW) = ns & 0xFFFFFFFF;
}
/* Set the alarm. this will automatically enable it. */
void rtc_alarm_set(uint64_t ns) {
mmio_write32(VIRT_RTC_BASE + RTC_ALARM_HIGH, ns >> 32);
mmio_write32(VIRT_RTC_BASE + RTC_ALARM_LOW, ns & 0xffffffff);
/* Order matters here, low write starts the alarm */
GF_REG32(RTC_ALARM_HIGH) = ns >> 32;
GF_REG32(RTC_ALARM_LOW) = ns & 0xFFFFFFFF;
}
uint64_t rtc_alarm_read(void) {
uint32_t low = mmio_read32(VIRT_RTC_BASE + RTC_ALARM_LOW);
uint32_t high = mmio_read32(VIRT_RTC_BASE + RTC_ALARM_HIGH);
uint32_t low = GF_REG32(RTC_ALARM_LOW);
uint32_t high = GF_REG32(RTC_ALARM_HIGH);
return ((uint64_t)high << 32) | low;
}
void rtc_alarm_enable(void) {
mmio_write32(VIRT_RTC_BASE + RTC_IRQ_ENABLED, 1);
}
void rtc_alarm_disable(void) {
mmio_write32(VIRT_RTC_BASE + RTC_IRQ_ENABLED, 0);
}
uint32_t rtc_alarm_status(void) {
return mmio_read32(VIRT_RTC_BASE + RTC_IRQ_ENABLED);
return GF_REG32(RTC_ALARM_STATUS) & 0x1;
}
void rtc_alarm_clear(void) {
GF_REG32(RTC_CLEAR_ALARM) = 1;
}
void rtc_irq_clear(void) {
GF_REG32(RTC_IRQ_CLEAR) = 1;
}
uint32_t rtc_irq_enabled(void) {
return GF_REG32(RTC_IRQ_ENABLED) & 0x1;
}

View file

@ -3,6 +3,9 @@
#include <stdint.h>
#define MS_TO_NS(ms) ((uint64_t)(ms) * 1000ULL * 1000ULL)
#define NS_TO_MS(ms) ((uint64_t)(ms) / (1000ULL * 1000ULL))
struct rtc_class_ops {
uint64_t (*read_time)(void);
void (*set_time)(uint64_t);
@ -16,8 +19,10 @@ void rtc_time_set(uint64_t ns);
void rtc_alarm_set(uint64_t ns);
uint64_t rtc_alarm_read(void);
void rtc_alarm_enable(void);
void rtc_alarm_disable(void);
uint32_t rtc_alarm_status(void);
void rtc_alarm_clear(void);
void rtc_irq_clear(void);
uint32_t rtc_irq_enabled(void);
#endif // RTC_H