/**
 * \file    drv_rtc.c
 * \brief   RTC init driver
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-19
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-19  Original Creation
 * 
 */

#include "drv_rtc.h"
#include "drv_chip.h"

#if 0

sys_tick32_t rtc_current32(void)
{
	sys_tick32_t t;

	asm volatile ("rdtime %0" : "=r" (t));

	return t;
}

sys_tick64_t rtc_current64(void)
{
#if __riscv_xlen == 32
	uint32_t low, hi, tmp;

	asm volatile (
		"1: rdtimeh %0;"
		"rdtime %1;"
		"rdtimeh %2;"
		"bne %0, %2, 1b"
		: "=&r" (hi), "=&r" (low), "=&r" (tmp));
	return ((uint64_t)hi << 32) | low;
#else //  __riscv_xlen == 32
	sys_tick_t t;

	asm volatile ("rdtime %0" : "=r" (t));
	return t;
#endif // __riscv_xlen == 32
}

#endif

long ticks2ms(sys_tick_t t)
{
    return t / (PLF_RTC_TIMEBASE / 1000);
}

sys_tick_t ms2ticks(long t)
{
    return t * PLF_RTC_TIMEBASE / 1000;
}

void rtc_delay_us(unsigned us)
{
    sys_tick_t t = now();
#if PLF_RTC_TIMEBASE != 1000000
    sys_tick_t ticks = us * (PLF_RTC_TIMEBASE / 976) / 1024;
#else
    sys_tick_t ticks = us;
#endif
    do ; while ((now() - t) < ticks);
}

void scr_rtc_setcmp(uint64_t when)
{
#if __riscv_xlen == 32
    *(volatile uint32_t*)SCR_RTC_MTIMECMPH = 0xffffffff;
    *(volatile uint32_t*)SCR_RTC_MTIMECMP = (uint32_t)when;
    *(volatile uint32_t*)SCR_RTC_MTIMECMPH = (uint32_t)(when >> 32);
#else //  __riscv_xlen == 32
    *(volatile uint64_t*)SCR_RTC_MTIMECMP = when;
#endif //  __riscv_xlen == 32
}

void scr_rtc_init(void)
{
    // configure RTC timebase (divisor) and reset time counters
    *(volatile uint32_t*)SCR_RTC_CTL = 0;
#if __riscv_xlen == 32
    *(volatile uint32_t*)SCR_RTC_MTIME = 0;
    *(volatile uint32_t*)SCR_RTC_MTIMEH = 0;
#else // __riscv_xlen == 32
    *(volatile uint64_t*)SCR_RTC_MTIME = 0;
#endif // __riscv_xlen == 32
#if __riscv_xlen == 32
    *(volatile uint32_t*)SCR_RTC_MTIMECMPH = 0xffffffff;
    *(volatile uint32_t*)SCR_RTC_MTIMECMP = 0xffffffff;
#else // __riscv_xlen == 32
    *(volatile uint64_t*)SCR_RTC_MTIMECMP = 0xffffffffffffffff;
#endif // __riscv_xlen == 32
    //*(volatile uint32_t*)SCR_RTC_DIVIDER = RTC_TIMEBASE_DIVISOR;
    *(volatile uint32_t*)SCR_RTC_DIVIDER = ((drv_chip_freq_get()) / (PLF_RTC_TIMEBASE) - 1);
    *(volatile uint32_t*)SCR_RTC_CTL = SCR_RTC_CTL_EN | SCR_RTC_CTL_SRC;
}

void delay_ms(unsigned ms)
{
    sys_tick_t t = now();
#if PLF_RTC_TIMEBASE != 1000000
    sys_tick_t ticks = ms * 1000 * (PLF_RTC_TIMEBASE / 976) / 1024;
#else
    sys_tick_t ticks = ms * 1000;
#endif
    do ; while ((now() - t) < ticks);
}

uint32_t now_seconds()
{
    return now() / 1000;
}

