64 lines
1.6 KiB
C
64 lines
1.6 KiB
C
#include <assert.h>
|
|
#include <rtc.h>
|
|
#include <stdint.h>
|
|
|
|
#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);
|
|
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;
|
|
}
|