/**
 * \file    drv_chip.c
 * \brief   
 * 
 * \par     Copyright (c) 2019 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2019-05-22
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2019-05-22  Original Creation
 * 
 */

#include "drv_chip.h"
#include "utils.h"
#include "sync.h"
#include "drv_rtc.h"

u64_t drv_chip_mcycle_get(void)
{
#if __riscv_xlen == 32
	u32_t low, hi, tmp;

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

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

/**
 *  If user want to do something before drv_chip_reset, please configure this handler
 */
v_func_v_ptr_t g_drv_chip_reset_callback_handler = NULL;

void drv_chip_reset(void)
{
    if (g_drv_chip_reset_callback_handler)
    {
        g_drv_chip_reset_callback_handler();
    }
    drv_reg_set(0x40000004,0xC00);
    rtc_delay_us(200000);
    DRV_REG_FIELD_SET(CHIP_REG_0, CHIP_RST, TRUE);
}


void drv_chip_ctrl_init(void)
{
    drv_chip_pd_ctrl_set(0);
    drv_chip_freq_set(DEFAULT_CHIP_FREQ);
}

// 33MHz    DN/DP=33/1   Default
// 22MHz    DN/DP=22/1
// 16.5MHz  DN/DP=33/2
// 11MHz    DN/DP=22/2
// 7.375MHz DN/DP=59/8
// 5.5MHz   DN/DP=22/4
// 3.625MHz DN/DP=29/8
void drv_chip_freq_set(DRV_CHIP_FREQ_t freq)
{
    volatile u32_t reg_val = DRV_REG_GET(PLL_CFG_REG);
    switch (freq)
    {
        case DRV_CHIP_FREQ_3P625M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,29);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,3);
            break;
        case DRV_CHIP_FREQ_5P5M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,22);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,2);
            break;
        case DRV_CHIP_FREQ_7P375M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,59);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,3);
            break;
        case DRV_CHIP_FREQ_11M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,22);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,1);
            break;
        case DRV_CHIP_FREQ_16P5M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,33);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,1);
            break;
        case DRV_CHIP_FREQ_22M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,22);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,0);
            break;
        case DRV_CHIP_FREQ_29M:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,29);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,0);
            break;
        case DRV_CHIP_FREQ_33M:
        default:
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DN,33);
            SAL_FIELD_SET(reg_val,PLL_CFG_REG,DP,0);
            break;
    }
    sync_enter_critical();
    DRV_REG_SET(PLL_CFG_REG, reg_val);
    scr_rtc_init();
    sync_exit_critical();
}

u32_t drv_chip_freq_get(void)
{
    return ((SYSTEM_SLEEP_CLOCK_FREQ * DRV_REG_FIELD_GET(PLL_CFG_REG,DN)) >> (DRV_REG_FIELD_GET(PLL_CFG_REG,DP))) >> 2;
}

f32_t drv_chip_clock_tick_get(void)
{
    return (1000000000.0) / drv_chip_freq_get();
}

u32_t drv_chip_freq_to_baudrate_get(void)
{
    u32_t std_freq = drv_chip_freq_get();
    switch (std_freq)
    {
        case 3625000UL:
            return 3686400UL;

        case 5500000UL:
            return 5529600UL;

        case 7375000UL:
            return 7372800UL;

        case 11000000UL:
            return 11059200UL;

        case 16500000UL:
            return 16588800UL;

        case 22000000UL:
            return 22118400UL;
        
        case 29000000UL:
            return 29491200UL;

        case 33000000UL:
        default:
            return 33177600UL;
    }
}


