293 lines
7.3 KiB
C
293 lines
7.3 KiB
C
#include "asm/power_interface.h"
|
||
#include "asm/adc_api.h"
|
||
#include "app_config.h"
|
||
#include "includes.h"
|
||
#include "stdlib.h"
|
||
|
||
__attribute__((noinline))
|
||
AT(.volatile_ram_code)
|
||
static u8 wiovdd_trim(u8 trim, s16 *adc_wiovdd_voltage)
|
||
{
|
||
u32 wiovdd_lev = 7;
|
||
u32 miovdd_lev = 0;
|
||
P33_CON_SET(P3_ANA_CON5, 3, 3, wiovdd_lev);
|
||
delay(215);//延时50us
|
||
P33_CON_SET(P3_ANA_CON5, 0, 3, miovdd_lev);
|
||
delay(430);
|
||
|
||
if (trim) {
|
||
for (; wiovdd_lev > 3; wiovdd_lev--) {
|
||
P33_CON_SET(P3_ANA_CON5, 3, 3, wiovdd_lev);
|
||
delay(700);//延时50us
|
||
adc_wiovdd_voltage[wiovdd_lev] = get_vddio_voltage();;
|
||
}
|
||
|
||
for (int i = 3; i >= 0; i--) {
|
||
adc_wiovdd_voltage[i] = adc_wiovdd_voltage[i + 1] - 200;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
__attribute__((noinline))
|
||
AT(.volatile_ram_code)
|
||
u8 miovdd_trim(u8 trim, s16 *adc_miovdd_voltage)
|
||
{
|
||
u32 wiovdd_lev = 0;
|
||
u32 miovdd_lev = 7;
|
||
P33_CON_SET(P3_ANA_CON5, 0, 3, miovdd_lev);
|
||
delay(430);
|
||
P33_CON_SET(P3_ANA_CON5, 3, 3, wiovdd_lev);
|
||
delay(215);//延时50us
|
||
|
||
if (trim) {
|
||
for (; miovdd_lev > 3; miovdd_lev--) {
|
||
P33_CON_SET(P3_ANA_CON5, 0, 3, miovdd_lev);
|
||
delay(700);//延时50us
|
||
adc_miovdd_voltage[miovdd_lev] = get_vddio_voltage();;
|
||
}
|
||
|
||
for (int i = 3; i >= 0; i--) {
|
||
adc_miovdd_voltage[i] = adc_miovdd_voltage[i + 1] - 200;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
__attribute__((noinline))
|
||
AT(.volatile_ram_code)
|
||
u32 iovdd_trim(u8 trim, u8 *miovdd_lev, u8 *wiovdd_lev)
|
||
{
|
||
|
||
const u32 m_iovdd_lev = P3_ANA_CON5 & 0xf;
|
||
if (trim == 0) {
|
||
return 1;
|
||
}
|
||
|
||
u32 check_vbat = get_vdd_voltage(AD_CH_VBAT) * 4;
|
||
printf("check_vbat = %d\n", check_vbat);
|
||
if (check_vbat < 3700) {
|
||
printf("%s %d\n", __func__, __LINE__);
|
||
*miovdd_lev = m_iovdd_lev | BIT(7);
|
||
*wiovdd_lev = m_iovdd_lev | BIT(7);
|
||
return 0;
|
||
}
|
||
local_irq_disable();
|
||
|
||
const u32 lvd_con = P3_VLVD_CON;
|
||
P3_VLVD_CON &= ~BIT(2);
|
||
delay(100);
|
||
P3_VLVD_CON &= ~BIT(0); //关闭lvd
|
||
|
||
s16 adc_wiovdd_voltage[8];
|
||
s16 adc_miovdd_voltage[8];
|
||
|
||
miovdd_trim(trim, adc_miovdd_voltage);
|
||
wiovdd_trim(trim, adc_wiovdd_voltage);
|
||
|
||
if (lvd_con & BIT(0)) {
|
||
P3_VLVD_CON |= BIT(0);//en
|
||
delay(3);
|
||
P3_VLVD_CON |= BIT(2);//oe
|
||
}
|
||
|
||
local_irq_enable();
|
||
|
||
int miovdd_voltage = m_iovdd_lev * 200 + 2000;
|
||
u32 min_diff = -1;
|
||
int mlev = 0;
|
||
|
||
for (int i = 7; i >= 0; i--) {
|
||
u32 diff = abs(miovdd_voltage - adc_miovdd_voltage[i]);
|
||
if (diff < min_diff) {
|
||
mlev = i;
|
||
min_diff = diff;
|
||
}
|
||
}
|
||
*miovdd_lev = mlev;
|
||
|
||
u32 wlev = 0;
|
||
min_diff = -1;
|
||
for (int i = 7; i >= 0; i--) {
|
||
u32 diff = abs(adc_miovdd_voltage[mlev] - adc_wiovdd_voltage[i]);
|
||
if (diff < min_diff) {
|
||
wlev = i;
|
||
min_diff = diff;
|
||
}
|
||
}
|
||
|
||
*wiovdd_lev = wlev;
|
||
|
||
|
||
for (u8 i = 0; i < 8; i++) {
|
||
printf("adc_wiovdd_voltage[%d] = %d\n", i, adc_wiovdd_voltage[i]);
|
||
printf("adc_miovdd_voltage[%d] = %d\n", i, adc_miovdd_voltage[i]);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static u8 wvdd_trim(u8 trim)
|
||
{
|
||
u8 wvdd_lev = 0;
|
||
wvdd_lev = 0;
|
||
int v = 0;
|
||
u8 err = 0;
|
||
|
||
if (trim) {
|
||
|
||
v = get_wvdd_level_trim();
|
||
if (v == 0) {
|
||
//0.65v
|
||
wvdd_lev = 0b0011;
|
||
} else if (v == 1) {
|
||
//0.7v
|
||
wvdd_lev = 0b0100;
|
||
} else if (v == 2) {
|
||
//0.75v
|
||
wvdd_lev = 0b0101;
|
||
} else {
|
||
//0.8v
|
||
//wvdd_lev = 0b0110;
|
||
WVDD_VOL_SEL(wvdd_lev);
|
||
WVDD_LOAD_EN(1);
|
||
WLDO06_EN(1);
|
||
delay(2000);//1ms
|
||
do {
|
||
WVDD_VOL_SEL(wvdd_lev);
|
||
delay(2000);//1ms * n
|
||
v = get_vdd_voltage(AD_CH_WVDD);
|
||
if (v > WVDD_VOL_TRIM) {
|
||
break;
|
||
}
|
||
wvdd_lev ++;
|
||
} while (wvdd_lev < WVDD_LEVEL_MAX);
|
||
WVDD_LOAD_EN(0);
|
||
WLDO06_EN(0);
|
||
|
||
u8 min = (WVDD_VOL_TRIM - WVDD_VOL_MIN) / WVDD_VOL_STEP - 2;
|
||
u8 max = (WVDD_VOL_TRIM - WVDD_VOL_MIN) / WVDD_VOL_STEP + 2;
|
||
if (!(wvdd_lev >= min && wvdd_lev <= max)) {
|
||
wvdd_lev = WVDD_LEVEL_DEFAULT;
|
||
err = 1;
|
||
}
|
||
}
|
||
|
||
//update_wvdd_trim_level(wvdd_lev);
|
||
} else {
|
||
wvdd_lev = get_wvdd_trim_level();
|
||
}
|
||
|
||
printf("trim: %d, wvdd_lev: %d, v: %d, err: %d\n", trim, wvdd_lev, v, err);
|
||
|
||
M2P_WDVDD = wvdd_lev;
|
||
|
||
if (err) {
|
||
return WVDD_LEVEL_ERR;
|
||
}
|
||
|
||
return wvdd_lev;
|
||
}
|
||
|
||
static u8 pvdd_trim(u8 trim)
|
||
{
|
||
/* return 0; */
|
||
u32 v = 0;
|
||
u8 lev_high_now = PVDD_LEVEL_DEFAULT;
|
||
u8 err = 0;
|
||
|
||
if (trim) {
|
||
PVDD_LEVEL_HIGH_NOW(PVDD_LEVEL_REF);
|
||
delay(2000);//1ms
|
||
v = get_vdd_voltage(AD_CH_PVDD);//adc_get_voltage_preemption(AD_CH_PVDD);
|
||
|
||
if ((v < (PVDD_VOL_REF - 2 * PVDD_VOL_STEP)) || (v > (PVDD_VOL_REF + 2 * PVDD_VOL_STEP))) {
|
||
lev_high_now = PVDD_LEVEL_DEFAULT;
|
||
M2P_PVDD_LEVEL_SLEEP_TRIM = PVDD_LEVEL_SLEEP;
|
||
err = 1;
|
||
|
||
} else {
|
||
M2P_PVDD_LEVEL_SLEEP_TRIM = (PVDD_LEVEL_REF - (v - PVDD_VOL_SLEEP) / PVDD_VOL_STEP);
|
||
lev_high_now = M2P_PVDD_LEVEL_SLEEP_TRIM + (PVDD_VOL_HIGH_NOW - PVDD_VOL_SLEEP) / PVDD_VOL_STEP;
|
||
|
||
}
|
||
} else {
|
||
lev_high_now = get_pvdd_trim_level();
|
||
M2P_PVDD_LEVEL_SLEEP_TRIM = get_pvdd_level() - (PVDD_VOL_HIGH_NOW - PVDD_VOL_SLEEP) / PVDD_VOL_STEP;
|
||
}
|
||
|
||
#if (!PMU_NEW_FLOW)
|
||
if (get_pvdd_dcdc_cfg()) {
|
||
//外接dcdc,pvdd配置为3档
|
||
lev_high_now = 3;
|
||
|
||
}
|
||
#endif
|
||
|
||
PVDD_LEVEL_HIGH_NOW(lev_high_now);
|
||
delay(2000);
|
||
PVDD_AUTO_PRD(0x3);
|
||
PVDD_LEVEL_AUTO(0x1);
|
||
PVDD_LEVEL_LOW(M2P_WDVDD);
|
||
|
||
#if PMU_NEW_FLOW
|
||
if (get_pvdd_dcdc_cfg()) {
|
||
power_set_pvdd_mode(PWR_PVDD_DCDC);
|
||
}
|
||
#endif
|
||
|
||
printf("trim: %d, pvdd_vol_ref: %d, pvdd_level_high_now_trim: %d, pvdd_level_sleep_trim: %d, pvdd_level_lev_l_trim: %d, err: %d\n", \
|
||
trim, v, lev_high_now, M2P_PVDD_LEVEL_SLEEP_TRIM, M2P_WDVDD, err);
|
||
cap_rch_enable();
|
||
|
||
if (err) {
|
||
return PVDD_LEVEL_ERR;
|
||
}
|
||
|
||
return lev_high_now;
|
||
}
|
||
|
||
void volatage_trim_init()
|
||
{
|
||
/* trim wvdd */
|
||
printf("lvd_con = 0x%x\n", P3_VLVD_CON);
|
||
u8 trim = load_pmu_trim_value_from_vm();
|
||
u8 wvdd_lev = 0;
|
||
u8 pvdd_lev = 0;
|
||
|
||
extern bool vm_need_recover(void);
|
||
if (vm_need_recover()) { // 升级完后重新trim
|
||
trim = 0xff;
|
||
}
|
||
|
||
printf("trim = 0x%x\n", trim);
|
||
|
||
wvdd_lev = wvdd_trim((trim & TRIM_WVDD) ? 1 : 0);
|
||
pvdd_lev = pvdd_trim((trim & TRIM_PVDD) ? 1 : 0);
|
||
|
||
u8 miovdd_lev = 0;
|
||
u8 wiovdd_lev = 0;
|
||
if (trim & TRIM_IOVDD) {
|
||
u8 trim_succ = iovdd_trim(trim, &miovdd_lev, &wiovdd_lev);
|
||
} else {
|
||
miovdd_lev = get_miovdd_trim_level();
|
||
wiovdd_lev = get_wiovdd_trim_level();
|
||
}
|
||
|
||
if (trim) {
|
||
if ((wvdd_lev != WVDD_LEVEL_ERR) && (pvdd_lev != PVDD_LEVEL_ERR)) {
|
||
store_pmu_trim_value_to_vm(wvdd_lev, pvdd_lev, miovdd_lev, wiovdd_lev);
|
||
}
|
||
}
|
||
|
||
printf("miovdd_lev = %x\n", miovdd_lev);
|
||
printf("wiovdd_lev = %x\n", wiovdd_lev);
|
||
|
||
P33_CON_SET(P3_ANA_CON5, 0, 3, miovdd_lev);
|
||
P33_CON_SET(P3_ANA_CON5, 3, 3, 0);
|
||
}
|
||
|
||
|