/**************************************************************************//**
|
* @file system_PanSeries.c
|
* @version V1.00
|
* @brief Panchip series SoC system clock init code and assert handler
|
* @note
|
* Copyright (C) 2020 Panchip Technology Corp. All rights reserved.
|
*****************************************************************************/
|
#include "PanSeries.h"
|
#include "pan_clk.h"
|
#include "pan_fmc.h"
|
#include "pan_sys.h"
|
#include "pan_efuse.h"
|
|
/*
|
* Global variables defined here should be used after RAM RW/ZI data init.
|
*/
|
uint32_t SystemCoreClock;
|
bool isFtDataValid = true;
|
float SocTemperature = 22; /* Treat default SoC temperature as 22 C */
|
/*
|
* Global variables here to be used in SystemInit() function should reside
|
* in flash, since RAM RW/ZI data are not initialized at that time.
|
*/
|
const uint32_t PanFlashLineMode = CONFIG_FLASH_LINE_MODE;
|
const bool PanFlashEnhanceEnable = false;
|
uint32_t vec_remap_adr = 0x20007000;
|
|
/**
|
* @brief Setup the microcontroller system
|
* Initialize the Embedded Flash Interface and other modules which should
|
* be init in early boot stage.
|
* @param None
|
* @retval None
|
*/
|
void SystemInit(void)
|
{
|
ANA->CPU_ADDR_REMAP_CTRL =0;
|
|
// Speed up flash clock from default 16MHz to 32MHz
|
CLK_SetFlashClkDiv(CLK_FLASH_CLKDIV_1);
|
// Switch flash to 4-Line mode
|
FMC_SetFlashMode(FLCTL, PanFlashLineMode, PanFlashEnhanceEnable);
|
// Init I-Cache
|
InitIcache(FLCTL, PanFlashLineMode);
|
|
#ifndef SYNC_3V_REG_MANUALLY
|
// Auto sync value to 3v registers
|
// Note that this auto-sync mechanism works for all registers needed
|
// doing 3v sync except Px_DINOFF regs for P46/P47/P56 in GPIO module.
|
CLK_Set3vSyncAuto();
|
#endif
|
|
#if CONFIG_SOC_DCDC_PAN1070
|
uint32_t tmpreg = ANA->LP_BUCK_3V;
|
// Increase buck default output voltage
|
tmpreg &= (~ANAC_BUCK_VOUT_Msk_3v);
|
tmpreg |= 0x6 << ANAC_BUCK_VOUT_Pos_3v;
|
// Enable DCDC-LDO auto switching when SoC vbat voltage drop off to about 1.8v and then uprise again
|
tmpreg |= ANAC_BUCK_VOL_LIMIT_EN_Msk_3v;
|
// Enable buck output
|
tmpreg &= ~0x1;
|
ANA->LP_BUCK_3V = tmpreg;
|
#endif
|
|
// Disable eFuse VDD for power saving purpose
|
EFUSE->EF_VDD = 0;
|
// Clear the internal XOCAP trim of XTH and we prefer to use the external capacitor instead
|
CLK->XTH_CTRL &= ~CLK_XTHCTL_XO_CAP_SEL_Msk;
|
// Disable SW pull-down res to avoid high power leakage in low temperature
|
ANA->LP_SW &= ~ANAC_HP_DVDD_PD_Msk;
|
// Forcely reset GPIO debounce clk source to AHB before configure db cycle
|
GPIO_DB->DBCTL &= ~GP_DBCTL_DBCLKSRC_Msk;
|
// Other optimization configs (From task 4372)
|
ANA->LP_PTAT_POLY |= ANAC_PTAT_TMP_TRIM_Msk;
|
CLK->XTL_CTRL_3V = (CLK->XTL_CTRL_3V & ~CLK_XTLCTL_CORE_BIAS_Msk_3v) | (0x7u << CLK_XTLCTL_CORE_BIAS_Pos_3v);
|
}
|
|
/**
|
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
* The SystemCoreClock variable contains the core clock (HCLK), it can
|
* be used by the user application to setup the SysTick timer or configure
|
* other parameters.
|
*
|
* @note Each time the core clock (HCLK) changes, this function must be called
|
* to update SystemCoreClock variable value. Otherwise, any configuration
|
* based on this variable will be incorrect.
|
*
|
* @param None
|
* @retval None
|
*/
|
void SystemCoreClockUpdate(void)
|
{
|
|
#ifdef FPGA_MODE
|
//Fixed 32M System Clock on FPGA
|
SystemCoreClock = FREQ_32MHZ;
|
#else
|
uint32_t div = 0;
|
uint32_t freq_out = 0;
|
div = (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_AHB_DIV_Msk) >> CLK_TOPCTL_AHB_DIV_Pos;
|
if(div == 0)
|
div = 1;
|
else
|
div += 1;
|
|
if(CLK->CLK_TOP_CTRL_3V & CLK_SYS_SRCSEL_DPLL){
|
freq_out = (CLK->DPLL_CTRL & CLK_DPLLCTL_FREQ_OUT_Msk);
|
if(freq_out == CLK_DPLL_OUT_64M){
|
SystemCoreClock = FREQ_64MHZ / div;
|
}
|
else{
|
SystemCoreClock = FREQ_48MHZ / div;
|
}
|
}
|
else{
|
SystemCoreClock = FREQ_32MHZ / div;
|
}
|
#endif
|
}
|
|
static bool HwParamDataVerify(OTP_STRUCT_T *p_opt)
|
{
|
uint8_t calc_checksum = 0;
|
|
for (size_t i = 0x1E; i < 0x7B; i++)
|
{
|
calc_checksum += p_opt->d8[i];
|
}
|
|
if (calc_checksum != p_opt->m.ft_checksum)
|
{
|
return false; // Calib data checksum failed
|
}
|
|
if (p_opt->m.ft_version >= 2)
|
{
|
calc_checksum = 0;
|
for (size_t i = 0x80; i < 0xFF; i++)
|
{
|
calc_checksum += p_opt->d8[i];
|
}
|
|
if (calc_checksum != p_opt->m_v2.ft_checksum2)
|
{
|
return false; // Calib data checksum2 failed
|
}
|
}
|
|
return true;
|
}
|
|
__WEAK void ADC_SetCalirationParams(OTP_STRUCT_T *otp)
|
{
|
return;
|
}
|
|
__WEAK void PW_ParamsSet(OTP_STRUCT_T *otp)
|
{
|
return;
|
}
|
|
bool SystemHwParamLoader(OTP_STRUCT_T *otp)
|
{
|
/*
|
* NOTE: We should make sure flash enhance mode is disabled before read
|
* data from flash.
|
*/
|
FMC_GetFlashUniqueId(FLCTL);
|
FMC_GetFlashJedecId(FLCTL);
|
FMC_SetFlashCapacity(FLCTL);
|
FMC_ReadInfoArea(FLCTL, 0x0, CMD_DREAD, (uint8_t *)otp, sizeof(OTP_STRUCT_T));
|
|
if (!HwParamDataVerify(otp))
|
{
|
/* Mark chip as NoFT */
|
isFtDataValid = false;
|
/* Exit if Hw Parameter Data Checking Failed */
|
memset(&otp->d8[0x00], 0x00, sizeof(OTP_STRUCT_T)); // clear the global otp structure
|
return false;
|
}
|
|
// Note:
|
// 1. Clock XTH and XTL may need Board-Level calibration on customers MP stage
|
// 2. ADC calibration data is loaded when calling ADC APIs (e.g. ADC_Init(), ADC_OutputVoltage(), ..)
|
ANA->LP_PTAT_POLY = (ANA->LP_PTAT_POLY & ~(0x7u << 3) & ~(0x7u << 16)) | (otp->m.pmu_vbg_trim << 3) | (otp->m.ipoly_trim << 16);
|
ANA->LP_HP_LDO = (ANA->LP_HP_LDO & ~(0xFu << 3) & ~(0x7u << 20)) | (otp->m.hp_ldo_trim << 3) | (otp->m.flash_ldo_trim << 20);
|
ANA->LP_LP_LDO_3V = (ANA->LP_LP_LDO_3V & ~(0xFu << 1) & ~(0xFu << 17)) | (otp->m.lpl_ldo_trim << 1) | (otp->m.lph_ldo_trim << 17);
|
ANA->LP_ANA_LDO = (ANA->LP_ANA_LDO & ~(0xFu << 3)) | (otp->m.ana_ldo_trim << 3);
|
ANA->ANA_RFFE_LDO = (ANA->ANA_RFFE_LDO & ~(0xFu << 3)) | (otp->m.rffe_ldo_trim << 3);
|
ANA->LP_FSYN_LDO = (ANA->LP_FSYN_LDO & ~(0xFu << 3)) | (otp->m.fsyn_ldo_trim << 3);
|
ANA->ANA_ADC_LDO = (ANA->ANA_ADC_LDO & ~(0xFu << 3)) | (otp->m.adc_ldo_trim << 3);
|
ANA->ANA_VCO_LDO = (ANA->ANA_VCO_LDO & ~(0xFu << 3)) | (otp->m.vco_ldo_trim << 3);
|
ANA->ANA_MISC_3V = (ANA->ANA_MISC_3V & ~(0x7u << 0)) | (otp->m.bod_vref_trim << 0);
|
CLK->RCH_CTRL = (CLK->RCH_CTRL & ~(0xFFu << 8)) | (otp->m.rch_trim << 8);
|
CLK->RCL_CTRL_3V = (CLK->RCL_CTRL_3V & ~(0xFFFu << 4)) | (otp->m.rcl_coarse_trim << 4) | (otp->m.rcl_fine_trim << 8);
|
otp->m.buck_imax_cal_trim = (otp->m.buck_imax_cal_trim + 4 > 0x1F) ? 0x1F : (otp->m.buck_imax_cal_trim + 4);
|
ANA->ANA_RESERVED_3V = (ANA->ANA_RESERVED_3V & ~(0x1u << 21)) | ((otp->m.buck_out_trim & 0x1u) << 21); // lsb of buck vout trim code
|
ANA->LP_BUCK_3V = (ANA->LP_BUCK_3V & ~(0xFu << 2) & ~(0x1Fu << 9) & ~(0x1Fu << 14))
|
| ((otp->m.buck_out_trim >> 1) << 2) | (otp->m.buck_imax_cal_trim << 9) | (otp->m.buck_zero_cal_trim << 14);
|
ANA->ANA_DFT = (ANA->ANA_DFT & ~(0xFFu << 24)) | (otp->m.battery_trim << 24);
|
|
if (otp->m.ft_version >= 2)
|
{
|
if (otp->m.ft_version < 4)
|
{
|
otp->m_v2.lph_ldo_vref_trim++;
|
if (otp->m_v2.lph_ldo_vref_trim > 7)
|
{
|
otp->m_v2.lph_ldo_vref_trim = 7;
|
}
|
}
|
ANA->LP_LP_LDO_3V = (ANA->LP_LP_LDO_3V & ~(0x7u << 21)) | (otp->m_v2.lph_ldo_vref_trim << 21);
|
ANA->ANA_RESERVED_3V |= (0x1u << 24); // LPLDOH enhance mode (default enabled, coordinate with lph vref trim)
|
if (otp->m.ft_version >= 7)
|
{
|
// Start from this ft version, we change LPLDOH calibrate flow to MODE2 (indtead of MODE1 with enhance mode),
|
// hence we should switch LPLDOH to MODE2 before we use it.
|
// Note that lph_ldo_trim would take no effect anymore when we switch LPLDOH to MODE2
|
ANA->LP_LP_LDO_3V |= ANAC_LPLDO_H_MODE_SEL_Msk_3v;
|
}
|
}
|
|
if (otp->m.ft_version >= 6)
|
{
|
ANA->LP_PTAT_POLY = (ANA->LP_PTAT_POLY & ~(0x3u << 1)) | (otp->m_v2.ptat_temp_trim << 1);
|
CLK->XTL_CTRL_3V = (CLK->XTL_CTRL_3V & ~(0x7u << 4)) | (otp->m_v2.xtl_core << 4);
|
CLK->XTH_CTRL = (CLK->XTH_CTRL & ~(0x1u << 10)) | (otp->m_v2.xth_icore << 10);
|
CLK->RCH_CTRL = (CLK->RCH_CTRL & ~(0x3u << 4)) | (otp->m_v2.rch_bias << 4);
|
CLK->DPLL_CTRL = (CLK->DPLL_CTRL & ~(0x3u << 4) & ~(0x3u << 6) & ~(0x7u << 8) & ~(0x3u << 11))
|
| (otp->m_v2.dpll_icp_bias << 4) | (otp->m_v2.dpll_icp_ctrl << 6) | (otp->m_v2.dpll_kvco_ctrl << 8) | (otp->m_v2.dpll_vco_freq_trim << 11);
|
}
|
|
/*
|
* Storing adc params related calibration. if adc symbol is not linked,
|
* this function would be handled as weak function.
|
*/
|
ADC_SetCalirationParams(otp);
|
|
/*
|
* Storing power params related calibration.
|
*/
|
PW_ParamsSet(otp);
|
|
#ifdef SYNC_3V_REG_MANUALLY
|
CLK_Wait3vSyncReady();
|
#endif
|
|
return true;
|
}
|
|
|
#if USE_ASSERT
|
|
/**
|
* @brief Assert Error Message
|
*
|
* @param[in] file the source file name
|
* @param[in] line line number
|
*
|
* @return None
|
*
|
* @details The function prints the source file name and line number where
|
* the ASSERT_PARAM() error occurs, and then stops in an infinite loop.
|
*/
|
void AssertError(uint8_t * file, uint32_t line)
|
{
|
|
SYS_DBG(" wrong parameters.\r\n", file, line);
|
|
/* Infinite loop */
|
while(1) ;
|
}
|
#endif
|