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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|