308 lines
11 KiB
C
Executable File
308 lines
11 KiB
C
Executable File
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
/* os shim includes */
|
|
#include "os_types.h"
|
|
#include "hw_reg_api.h"
|
|
#include "pmu_rf.h"
|
|
|
|
void pmu_enable(uint32_t module)
|
|
{
|
|
volatile uint32_t delay = 100;
|
|
uint32_t i = 0;
|
|
uint32_t tmp;
|
|
//enable module;
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_CLK_ENABLE_ADDR);
|
|
if(tmp & (1<< module))
|
|
return;
|
|
tmp |= (1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_CLK_ENABLE_ADDR, tmp);
|
|
|
|
//soft reset module;
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp |= (1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
|
|
//delay
|
|
for(i = 0; i < delay; i++);
|
|
|
|
//reset done
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp &= ~(1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
}
|
|
|
|
void pmu_disable(uint32_t module)
|
|
{
|
|
volatile uint32_t delay = 100;
|
|
uint32_t i = 0;
|
|
uint32_t tmp;
|
|
if(module < 32){
|
|
//enable module;
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_CLK_ENABLE_ADDR);
|
|
tmp &= ~(1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_CLK_ENABLE_ADDR, tmp);
|
|
|
|
//soft reset module;
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp |= (1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
|
|
//delay
|
|
for(i = 0; i < delay; i++);
|
|
|
|
//reset done
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp &= ~(1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
}
|
|
}
|
|
|
|
void pmu_clk_set(uint32_t clk_sel)
|
|
{
|
|
(void)clk_sel;
|
|
/* The PMU clock configuration is completed during hardware initialization
|
|
* and will not be modified later. Refer to clk_pmu_clk_set().
|
|
*/
|
|
}
|
|
|
|
void pmu_bpll_calibration_binary_search()
|
|
{
|
|
uint32_t tmp;
|
|
// calibration bpll
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_READY_MANU, tmp, 0);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_RESTART, tmp, 0);
|
|
REG_FIELD_SET(VCO_CALIB_PRECISION_CYCLE_NUM, tmp, 4000);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR, tmp);
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_EN, tmp, 1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR, tmp);
|
|
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
REG_FIELD_SET(VCO_CALIB_SOFT_RST, tmp, 1);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
REG_FIELD_SET(VCO_CALIB_SOFT_RST, tmp, 0);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG1_ADDR);
|
|
REG_FIELD_SET(VCO_CALIB_CODE_SWH_WAIT_CN, tmp, 200);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG1_ADDR, tmp);
|
|
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_EN, tmp, 0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR, tmp);
|
|
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_RESTART, tmp, 1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR, tmp);
|
|
|
|
while(1) {
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_VCO_CFG1_ADDR);
|
|
if(REG_FIELD_GET(PLL_VCO_CALIB_READY, tmp)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void pmu_bpll_calibration()
|
|
{
|
|
uint32_t tmp;
|
|
uint8_t code_result=0;
|
|
uint32_t comp_result=0;
|
|
uint32_t diff_result=0xffff;
|
|
uint32_t precison_value=2500;
|
|
uint32_t fb_cnt=0;
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(VCO_CALIB_PRECISION_CYCLE_NUM,tmp,precison_value);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_READY_MANU,tmp,0);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_EN,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG1_ADDR);
|
|
REG_FIELD_SET(VCO_CALIB_CODE_SWH_WAIT_CN,tmp,100);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG1_ADDR,tmp);
|
|
|
|
for(uint8_t i=0;i<64;i++) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_CAL,tmp,i);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG1_ADDR);
|
|
REG_FIELD_SET(VCO_PLL_FB_CNT_CLR,tmp,1);
|
|
REG_FIELD_SET(VCO_CALIB_DONE_CLR,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG1_ADDR,tmp);
|
|
REG_FIELD_SET(VCO_PLL_FB_CNT_CLR,tmp,0);
|
|
REG_FIELD_SET(VCO_CALIB_DONE_CLR,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG1_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_RESTART,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_RESTART,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
|
|
while (1) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG1_ADDR);
|
|
if (REG_FIELD_GET(VCO_CALIB_DONE,tmp)) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG2_ADDR);
|
|
fb_cnt = (tmp>>4) & 0xffff;
|
|
comp_result = (fb_cnt > precison_value) ? \
|
|
(fb_cnt-precison_value) : (precison_value-fb_cnt);
|
|
if (comp_result <= diff_result) {
|
|
code_result=i;
|
|
diff_result=comp_result;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_READY_MANU,tmp,0);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_EN,tmp,1);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_MANU_CAL,tmp,code_result);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_VCO_CFG0_ADDR);
|
|
REG_FIELD_SET(PLL_VCO_CALIB_READY_MANU,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_VCO_CFG0_ADDR,tmp);
|
|
}
|
|
|
|
|
|
void pmu_mpll_calibration_binary_search()
|
|
{
|
|
uint32_t tmp;
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_READY_MANU,tmp,0);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_RESTART,tmp,0);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_PRECISION_CYCLE_NUM, tmp, 4000);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_EN,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_SOFT_RST,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR,tmp);
|
|
tmp=PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_SOFT_RST,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_CODE_SWH_WAIT_CN, tmp, 200);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_EN,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_RESTART,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
while(1) {
|
|
tmp = PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR);
|
|
if(REG_FIELD_GET(MIPIPLL_VCO_CALIB_READY, tmp)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void pmu_mpll_calibration()
|
|
{
|
|
uint32_t tmp;
|
|
uint8_t code_result=0;
|
|
uint32_t comp_result=0;
|
|
uint32_t diff_result=0xffff;
|
|
uint32_t precison_value=2500;
|
|
uint32_t fb_cnt=0;
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_PRECISION_CYCLE_NUM,tmp,precison_value);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_READY_MANU,tmp,0);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_EN,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_CODE_SWH_WAIT_CN,tmp,100);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR,tmp);
|
|
|
|
for(uint8_t i=0;i<64;i++) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_CAL,tmp,i);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR);
|
|
REG_FIELD_SET(MIPIVCO_PLL_FB_CNT_CLR,tmp,1);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_DONE_CLR,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR,tmp);
|
|
REG_FIELD_SET(MIPIVCO_PLL_FB_CNT_CLR,tmp,0);
|
|
REG_FIELD_SET(MIPIVCO_CALIB_DONE_CLR,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_RESTART,tmp,0);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_RESTART,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
while (1) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG1_ADDR);
|
|
if (REG_FIELD_GET(MIPIVCO_CALIB_DONE,tmp)) {
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG2_ADDR);
|
|
fb_cnt = (tmp>>4) & 0xffff;
|
|
comp_result = (fb_cnt > precison_value) ? \
|
|
(fb_cnt-precison_value) : (precison_value-fb_cnt);
|
|
if (comp_result <= diff_result) {
|
|
code_result=i;
|
|
diff_result=comp_result;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_READY_MANU,tmp,0);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_EN,tmp,1);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_MANU_CAL,tmp,code_result);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
|
|
tmp=PMU_RF_READ_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR);
|
|
REG_FIELD_SET(MIPIPLL_VCO_CALIB_READY_MANU,tmp,1);
|
|
PMU_RF_WRITE_REG(CFG_CALIB_MIPIVCO_CFG0_ADDR,tmp);
|
|
}
|
|
|
|
void pmu_soft_reset(uint32_t module)
|
|
{
|
|
volatile uint32_t delay = 100;
|
|
uint32_t tmp;
|
|
|
|
//soft reset module;
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp |= (1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
|
|
//delay
|
|
for(uint32_t i = 0; i < delay; i++);
|
|
|
|
//reset done
|
|
tmp = PMU_RF_READ_REG(CFG_PMU_SOFT_RESET_ADDR);
|
|
tmp &= ~(1<< module);
|
|
PMU_RF_WRITE_REG(CFG_PMU_SOFT_RESET_ADDR, tmp);
|
|
}
|