1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <stdio.h> 14#include <assert.h> 15#include <errno.h> 16 17#include <utils/util.h> 18#include <utils/time.h> 19 20#include <platsupport/plat/rtc.h> 21 22#define HIKEY_RTCCR_ENABLE_SHIFT (0) 23 24typedef volatile struct rtc_regs { 25 uint32_t rtcdr; /* Data reg: RO: returns current value of 1Hz upcounter */ 26 uint32_t rtcmr; /* Comparison reg: RW: for the alarm (irq) feature. 27 * Generates an IRQ when rtcmr == rtcdr. 28 * Don't care: we don't use the alarm feature. 29 */ 30 uint32_t rtclr; /* Load reg: RW: the initial value of the upcounter. */ 31 uint32_t rtccr; /* Control reg: literally only has an enable bit (bit 0) 32 * and that's it. Absolute control. 33 */ 34 uint32_t rtcimsc; /* Interrupt mask reg: Don't care. we don't use the alarm 35 * feature. 36 */ 37 uint32_t rtcris; /* Raw Interrupt status reg: don't care. */ 38 uint32_t rtcmis; /* Masked interrupt status reg: don't care. */ 39 uint32_t rtcicr; /* interrupt clear reg: don't care. */ 40} rtc_regs_t; 41 42static inline rtc_regs_t * 43rtc_get_regs(rtc_t *rtc) 44{ 45 assert(rtc != NULL); 46 assert(rtc->vaddr != NULL); 47 return rtc->vaddr; 48} 49 50int rtc_start(rtc_t *rtc) 51{ 52 rtc_regs_t *regs = rtc_get_regs(rtc); 53 54 /* We set the initial value of the upcounter to 0 when 55 * initializing, because we have no reason to use any 56 * other value, and because we have no guarantee that 57 * it starts at a sensibly low value if not explicitly set. 58 */ 59 regs->rtclr = 0; 60 regs->rtccr = BIT(HIKEY_RTCCR_ENABLE_SHIFT); 61 return 0; 62} 63 64int rtc_stop(rtc_t *rtc) 65{ 66 rtc_regs_t *regs = rtc_get_regs(rtc); 67 regs->rtccr = 0; 68 return 0; 69} 70 71uint32_t rtc_get_time(rtc_t *rtc) 72{ 73 rtc_regs_t *regs = rtc_get_regs(rtc); 74 return regs->rtcdr; 75} 76 77int rtc_init(rtc_t *rtc, rtc_config_t config) 78{ 79 if (config.id < RTC0 || config.id > RTC1) { 80 ZF_LOGE("Invalid timer device ID for a hikey RTC timer."); 81 return EINVAL; 82 } 83 84 if (config.vaddr == NULL) { 85 ZF_LOGE("Vaddr of the mapped RTC device register frame is required."); 86 return EINVAL; 87 } 88 89 rtc->vaddr = config.vaddr; 90 return 0; 91} 92