#include #include #include #define VIRT_RTC_BASE 0x0101000UL #define VIRT_RTC_SIZE 0x1000 #define RTC_TIME_LOW 0x00 #define RTC_TIME_HIGH 0x04 #define RTC_ALARM_LOW 0x08 #define RTC_ALARM_HIGH 0x0c #define RTC_ALARM_STATUS 0x18 #define RTC_CLEAR_ALARM 0x14 #define RTC_IRQ_ENABLED 0x10 #define RTC_IRQ_CLEAR 0x1c #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 = 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) { 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) { /* 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 = GF_REG32(RTC_ALARM_LOW); uint32_t high = GF_REG32(RTC_ALARM_HIGH); return ((uint64_t)high << 32) | low; } uint32_t rtc_alarm_status(void) { 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; }