Files
99_7018_lmx/cpu/br28/power/power_trim.c
2025-10-29 13:10:02 +08:00

293 lines
7.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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()) {
//外接dcdcpvdd配置为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);
}