Files
banban/ql-config/soc_platform/preboot_boot2/boards/libarom-common/pmic.c
T

970 lines
28 KiB
C

/* -*- C -*- */
/*
* Copyright (c) 2020, ASR microelectronics
* All rights reserved.
*
* cr5 should not invoke interface of pmic, it only be invoked by mcu.
* although BOARD_CRANE include cr5, but no functions will invoke pmic interface from cr5.
*/
#if defined(BOARD_CRANE) || defined(BOARD_CRANEW_MCU)
#include <stdio.h>
#include <stdint.h>
#include "assert.h"
#include "pmic.h"
#include "reg.h"
#include "i2c.h"
#include "cpu.h"
#include "property.h"
/* Log configuration */
#include "log.h"
#define LOG_MODULE "PMIC"
#define LOG_LEVEL LOG_LEVEL_MAIN
#define BUCK_LDO_SWITCH 0x14
#define BUCK4_SW3 (1 << 6)
/*
* PMIC registers are organized by different pages, i.e. Base page and Power
* page. Different interfaces require access to registers on different pages.
* Before calling an interface, the corresponding page needs to be initialized
* using the following method.
*
* Init base page
* pi2c_init(PMIC_BASE_PAGE_ADDR);
* Init power page
* pi2c_init(PMIC_POWER_PAGE_ADDR);
*
* Not initializing register page in each interface is to reduce bin size.
*/
/* Base Page interface */
static void pmic_print_fault_event_info_for_pm803(uint8_t pmic_id);
static void pmic_pre_charge_current_setting(uint8_t pmic_id);
static void pmic_set_crystal(uint8_t pmic_id);
static void pmic_fault_wu_en_enable(void);
static void pmic_set_fault_wu(void);
static void pmic_set_sw_powerdown(void);
/* Power Page interface */
static void pmic_set_buck1_skipmode(uint8_t pmic_id);
static void pmic_set_buck1_vol(uint8_t pmic_id);
#if AROM_VERSION == AROM_VER_2022_11_11_CRANEG_CR5
/* CraenGT */
static void pmic_set_ddr_phy_voltage(uint8_t pmic_id);
#endif
#ifdef BOARD_CRANEW_MCU
static void pmic_LDO_config_for_cranew_mcu_and_pm813s(uint8_t pmic);
#endif
#if AROM_VERSION == AROM_VER_2020_07_30_CRANEGM_A0
/* CraneG/M */
static void pmic_set_ldo7_en_1_6v_for_craneM_and_pm803(uint8_t pmic_id);
#endif
/*---------------------------------------------------------------------------*/
static uint8_t g_pmic_id = PMIC_UNAVAILABLE;
/*---------------------------------------------------------------------------*/
extern void quec_powerkey_check(void);
/*
* default value 75mA, set to 150mA.
*
* base regs: 0x21:
* pm813/pmic813s/pm816: valid
* pm802/pm803 : reserved, blank.
*/
#if AROM_VERSION != AROM_VER_2021_10_16_CRANEL_A0 //cranel裁剪代码,加快开机时间 quectel
static void
pmic_pre_charge_current_setting(uint8_t pmic_id)
{
/* Base page */
switch(pmic_id) {
case PM813:
case PM813S:
case PM816:
LOG_INFO("Set precharge current to 150mA\n");
uint8_t clear_mask = (uint8_t)(~0xF3);
pi2c_clear_then_set_bits(PM813_PRE_CHARGE_CURRENT_SETTING_REG, clear_mask,
PRE_CHARGE_CURRENT_SETTING_150MA);
break;
default:
break;
}
}
/*---------------------------------------------------------------------------*/
#endif
uint8_t
pmic_get_id(void)
{
return g_pmic_id;
}
/*---------------------------------------------------------------------------*/
/*
* preboot set 10pf
* cp will set 20pf after 1s
* pm803 do not have CRYSTAL select bits
*/
#if AROM_VERSION != AROM_VER_2021_10_16_CRANEL_A0 //cranel裁剪代码,加快开机时间 quectel
static void
pmic_set_crystal(uint8_t pmic_id)
{
uint8_t clear_mask = 0;
/* Base page */
switch(pmic_id) {
case PM803:
case PM803L:
case PM807:
case PM806:
break;
case PM813L:
clear_mask = (uint8_t)(~0xF8);
pi2c_clear_then_set_bits(PM813L_RTC_REG_XO, clear_mask, CRYSTAL_10PF_813L);
break;
default:
clear_mask = (uint8_t)(~0x1F);
pi2c_clear_then_set_bits(PM813_RTC_REG_XO, clear_mask, CRYSTAL_10PF);
break;
}
if(clear_mask) {
LOG_INFO("Set crystal 10pf\n");
}
}
#endif
/*---------------------------------------------------------------------------*/
/*
* base reg: 0x1d:
* pm802/803/pm813/pm813S: valid.
* pm802: must disable watchdog by software in preboot;
* pm813: watchdog disabeled defaultly by hardware.
*
*/
void
pmic_setup(void)
{
unsigned char val;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return;
}
/* Init PMIC id */
pmic_init();
uint8_t pmic_id = pmic_get_id();
/* 1. BASE PAGE Configuration */
pi2c_init(PMIC_BASE_PAGE_ADDR);
//It needs to be called after i2c initialization.
#ifdef QUECTEL_PREBOOT_OPT
quec_powerkey_check();
#endif
#if AROM_VERSION != AROM_VER_2021_10_16_CRANEL_A0 //cranel裁剪代码,加快开机时间 quectel
pmic_set_crystal(pmic_id);
pmic_pre_charge_current_setting(pmic_id);
#endif
/* Disable PMIC Watchdog, set bits */
pi2c_clear_then_set_bits(PMIC_WATCHDOG, 0x0, WATCHDOG_WD_DIS);
/* In case of pi2c_read_reg failed */
val = 0;
pi2c_read_reg(PMIC_WATCHDOG, &val);
LOG_INFO("Disabling PMIC watchdog %s\n",
(val & WATCHDOG_WD_DIS) ? "ok" : "failed");
/* pm803 need, before read or write 0xE7 and 0x10 */
pmic_print_fault_event_info_for_pm803(pmic_id);
/* 2. POWER PAGE Configuration */
pi2c_init(PMIC_POWER_PAGE_ADDR);
pmic_set_buck1_vol(pmic_id);
pmic_set_buck1_skipmode(pmic_id);
#if AROM_VERSION == AROM_VER_2020_07_30_CRANEGM_A0
if(CHIP_ID_CRANEM == hw_chip_id()) {
/* CraneM */
/* LOG_PRINT("pmic: cranem\n"); */
pmic_set_ldo7_en_1_6v_for_craneM_and_pm803(pmic_id);
}
#endif
#if AROM_VERSION == AROM_VER_2022_11_11_CRANEG_CR5
/* CraneGT */
/* LOG_PRINT("pmic: cranegt\n"); */
pmic_set_ddr_phy_voltage(pmic_id);
#endif
#if AROM_VERSION != AROM_VER_2021_10_16_CRANEL_A0 //cranel裁剪代码,加快开机时间 quectel
#ifdef QUECTEL_PREBOOT_OPT
//pmic807,射频开关供电与USB供电共用,开关规格书供电最大是3.1V,pmic默认电压是3.1V,有很大风险,将供电电压降到3V
if((CHIP_ID_CRANELG == hw_chip_id())||(CHIP_ID_CRANELRH == hw_chip_id())) {
pmic_set_ldo4_en_3v_for_craneLG_LRH_and_pm807();
}
#endif
#endif
#ifdef BOARD_CRANEW_MCU
pmic_LDO_config_for_cranew_mcu_and_pm813s(pmic_id);
#endif
return;
}
/*---------------------------------------------------------------------------*/
/*
* base reg: 0x10
* pm802/803/pm813/pm813S: valid
* pm802/803/pm806:
* bit 7 6 5 4 3 2 1 0
* | | | fault_wu_log | bat_wu_log | rtc_alarm_wu_log | exton1n_wu_log | onkey_wu_log |
* pm813/pm813S:
*
* |ivbus_detect | fault_wu_log | rtc_alarm_wu_log | bat_wu_log | exton2_wu_log | exton1n_wu_log | onkey_wu_log |
* pm802S:
*
* | fault_wu_log | rtc_alarm_wu_log | bat_wu_log | exton2_wu_log | exton1n_wu_log | onkey_wu_log |
* normal evb board: never connect exton2 or exton1n to GND.
* user special auto test need: temperally connect exton1n to GND.
*
*/
uint8_t
pmic_powerup_get_reason(void)
{
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
LOG_INFO("Fake: pmic_powerup_get_reason: 0x1\n");
return 0x1;
}
uint8_t powerup_reason;
pi2c_init(PMIC_BASE_PAGE_ADDR);
pi2c_read_reg(PM813_PWRUP_LOG_REG1, &powerup_reason);
return powerup_reason;
}
/*---------------------------------------------------------------------------*/
/*
* base reg: 0xe7
* PM802/PM803/PM813/PM813S: valid
*
* PM802 fault_wu_en bit2 is diff with PM803/PMIC813/PMIC813s bit0
*
* Bit 7 6 5 4 3 2 1 0
* PM813
* | fault_wu | | | fault_wu_en |
* PM803/PM813S
* | fault_wu | fault_wu_en |
* PM802/pm802S
* | fault_wu | fault_wu_en | | bat_wu_done |
*/
void
pmic_fault_wu_en_disable(void)
{
unsigned char clear_bits;
uint8_t pmic_id;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return;
}
LOG_INFO("Disable PMIC fault wakeup.\n");
pi2c_init(PMIC_BASE_PAGE_ADDR);
pmic_id = pmic_get_id();
switch(pmic_id) {
case PM802:
case PM802S:
clear_bits = PM802_FAULT_WU_ENABLE_BIT;
break;
default:
clear_bits = PM813_FAULT_WU_ENABLE_BIT;
break;
}
/* Clear bits */
pi2c_clear_then_set_bits(PM813_FAULT_WU_REG, clear_bits, 0x0);
}
/*---------------------------------------------------------------------------*/
static void
pmic_fault_wu_en_enable(void)
{
unsigned char set_bits;
uint8_t pmic_id;
LOG_INFO("Enable PMIC fault wakeup.\n");
/* Base page */
pmic_id = pmic_get_id();
switch(pmic_id) {
case PM802:
case PM802S:
set_bits = PM802_FAULT_WU_ENABLE_BIT;
break;
default:
set_bits = PM813_FAULT_WU_ENABLE_BIT;
break;
}
/* Set bits */
pi2c_clear_then_set_bits(PM813_FAULT_WU_REG, 0x0, set_bits);
}
/*---------------------------------------------------------------------------*/
/*
* base reg: 0xe7
* PM802/PM803/PM813/PM813S: valid
*
* PM802 fault_wu_en bit2 is diff with PM803/PMIC813/PMIC813s bit0
* PM813/PM802 fault_wu bit3 is diff with PM803/PMIC813s bit1
*
* Bit 7 6 5 4 3 2 1 0
* PM813
* | fault_wu | | | fault_wu_en |
* PM803/PM813S
* | fault_wu | fault_wu_en |
* PM802/pm802S
* | fault_wu | fault_wu_en | | bat_wu_done |
*/
static void
pmic_set_fault_wu(void)
{
unsigned char set_bits;
uint8_t pmic_id;
pmic_id = pmic_get_id();
LOG_INFO("Set PMIC fault wakeup.\n");
/* Base page */
switch(pmic_id) {
case PM802:
case PM802S:
case PM813:
case PM813A3:
set_bits = PM813_FAULT_WU_BIT;
break;
default:
set_bits = PM813S_FAULT_WU_BIT;
break;
}
/* Set bits */
pi2c_clear_then_set_bits(PM813_FAULT_WU_REG, 0x0, set_bits);
}
/*---------------------------------------------------------------------------*/
/*
* base reg: 0xd
* PM802/PM803/PM813/PM813S: valid
*
* sw_pdown bit5
* pm802/PM803/PMIC813/PMIC813s: same
*
* Bit 7 6 5 4 3 2 1 0
* pm802/pm802S
* pwr_hold | pmic_reset | sw_pdown | wd_reset |disable_pgood_det | | | wd_mode
* PM803/PMIC813/PMIC813s
* pwr_hold | pmic_reset | sw_pdown | wd_reset |disable_pgood_det | force_i2c_control | | wd_mode
*
*/
static void
pmic_set_sw_powerdown(void)
{
LOG_INFO("Set PMIC powerdown.\n");
/* Base page */
/* Set bits */
pi2c_clear_then_set_bits(PM813_MISC_CFG_REG1, 0x0, PM813_SW_PDOWN);
}
/*---------------------------------------------------------------------------*/
/* only pm803 bug:
* if read or wirte 0xE7, 0xE5 and 0xE6(shutdown reason) are cleared automatically
* so print the value for development step.
*/
static void
pmic_print_fault_event_info_for_pm803(uint8_t pmic_id)
{
uint8_t val;
char buf[4];
/* Base page */
switch(pmic_id) {
case PM803:
case PM803L:
/* save the value to properties because there regs are read to clear */
pi2c_read_reg(PM813_FAULT_EVENT_REG1, &val);
/* Debug log */
/* LOG_PRINT("[BP_0x%x] = 0x%x\n", PM813_FAULT_EVENT_REG1, val); */
snprintf(buf, sizeof(buf), "%d", val);
asr_property_set("bl2.pdreason1", buf);
pi2c_read_reg(PM813_FAULT_EVENT_REG2, &val);
/* Debug log */
/* LOG_PRINT("[BP_0x%x] = 0x%x\n", PM813_FAULT_EVENT_REG2, val); */
snprintf(buf, sizeof(buf), "%d", val);
asr_property_set("bl2.pdreason2", buf);
break;
default:
break;
}
}
/*---------------------------------------------------------------------------*/
#ifndef APPLICATION_PREBOOT
static unsigned restart_cmd_reg, restart_status_reg;
#endif
/*
* PM802/PM803: base reg 0xe8
* PM813/PM813s: base reg 0xe9
* PM802S: base reg 0xcf
*/
void
pmic_init(void)
{
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
/* On FPGA or PZ1 */
g_pmic_id = PMIC_UNAVAILABLE;
return;
}
int retry = 3;
while(retry--) {
pi2c_bus_reset();
pi2c_reset();
pi2c_init(PMIC_BASE_PAGE_ADDR);
if(pi2c_read_reg(PMIC_ID, &g_pmic_id) == 0) {
/* Display the full pmic id register content */
LOG_PRINT("Found PMIC with Id: 0x%x\n", (unsigned)g_pmic_id);
/* Use PID as PMIC id */
g_pmic_id = PMIC_PID(g_pmic_id);
break;
}
}
if(retry < 0) {
/* Can not continue to execute without a valid PMIC id on siliocn */
LOG_ERR("Read PMIC id failed\n");
assert(0);
}
#ifndef APPLICATION_PREBOOT
/* Only used in Boot2 and Flasher */
switch(g_pmic_id) {
case PM802:
case PM803:
restart_cmd_reg = PM802_RTC_SPARE_REG1;
restart_status_reg = PM802_RTC_SPARE_REG1;
break;
case PM802S:
case PM803L:
restart_cmd_reg = PM802S_RTC_SPARE_REG1;
restart_status_reg = PM802S_RTC_SPARE_REG1;
break;
case PM816:
restart_cmd_reg = PM816_RTC_SPARE_REG1;
restart_status_reg = PM816_RTC_SPARE_REG1;
break;
case PM813L:
restart_cmd_reg = PM813L_RTC_SPARE_REG1;
restart_status_reg = PM813L_RTC_SPARE_REG1;
break;
case PM807:
case PM806:
restart_cmd_reg = PM807_RTC_SPARE_REG1;
restart_status_reg = PM807_RTC_SPARE_REG1;
break;
default:
restart_cmd_reg = PM813_RTC_SPARE_REG1;
restart_status_reg = PM813_RTC_SPARE_REG1;
break;
}
#endif
return;
}
/*---------------------------------------------------------------------------*/
#ifndef APPLICATION_PREBOOT
/* Only used in Boot2 and Flasher */
int
pmic_set_restart_status(char reason)
{
uint8_t reg_val;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return 0;
}
pi2c_init(PMIC_BASE_PAGE_ADDR);
pi2c_write_reg(restart_status_reg, reason);
pi2c_read_reg(restart_status_reg, &reg_val);
LOG_INFO("Set restart status = 0x%x\n", reg_val);
return 0;
}
/*---------------------------------------------------------------------------*/
void
pmic_get_restart_cmd(char *r_cmd)
{
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
*r_cmd = RESTART_CMD_NORMAL_POWERON;
/* Debug log */
/* LOG_INFO("FPGA: Get restart cmd = 0x%x\n", (unsigned)*r_cmd); */
return;
}
pi2c_init(PMIC_BASE_PAGE_ADDR);
pi2c_read_reg(restart_cmd_reg, (unsigned char *)r_cmd);
LOG_INFO("Get restart cmd = 0x%x\n", (unsigned)*r_cmd);
}
/*---------------------------------------------------------------------------*/
int
pmic_set_restart_cmd(char cmd)
{
uint8_t reg_val;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return 0;
}
pi2c_init(PMIC_BASE_PAGE_ADDR);
pi2c_write_reg(restart_cmd_reg, cmd);
pi2c_read_reg(restart_cmd_reg, &reg_val);
LOG_INFO("Set restart cmd = 0x%x\n", reg_val);
return 0;
}
#endif /* APPLICATION_PREBOOT */
/*---------------------------------------------------------------------------*/
/* since pm802/802s/pm803 no charger module pmic, so isSysRestartByCharging() will never be "C"(sdk checks power_up_reason register, if charging, set RTC to 'C'),
* so always no usb charging case. If want to support it, need use pmic_set_user_flag().
* only for pm803 craneG:
* If burn complete with 'reboot', Hal_Powerup_Get_Reason() is "N", set pmic_get_user_flag is 0xF in flasher, do normal start
* If burn without reboot, Hal_Powerup_Get_Reason() is "N", pmic_get_user_flag is not 0xF, do charging start.
*
* PM813/PM813s: base reg 0xe8 low 4bits
* PM802/PM802s/PM803: base reg 0xec high 4bits
*/
int
pmic_set_user_flag(char cmd)
{
uint8_t reg_val, pmic_id;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return 0;
}
pmic_id = pmic_get_id();
if((cmd == RESTART_CMD_NORMAL_POWERON) || (cmd == RESTART_CMD_FORCE_NORMAL_POWERON)) {
pi2c_init(PMIC_BASE_PAGE_ADDR);
switch(pmic_id) {
/*case PM802: / * craneM * / */
/*case PM802S: / * craneM * / */
case PM803: /* craneG */
pi2c_read_reg(PM802_REG_FOR_USR_DEF_FLAGS_STR, &reg_val);
reg_val &= ~0xF0;
reg_val |= UI_FLAG_REBOOT << 4;
pi2c_write_reg(PM802_REG_FOR_USR_DEF_FLAGS_STR, reg_val);
break;
default:
break;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
void
pmic_sw_reboot(void)
{
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return;
}
pi2c_init(PMIC_BASE_PAGE_ADDR);
/* each bit should be set separately */
pmic_fault_wu_en_enable();
pmic_set_fault_wu();
pmic_set_sw_powerdown();
}
/*---------------------------------------------------------------------------*/
void
pmic_sw_pdown(void)
{
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return;
}
//QUECTEL ADD CASE FAE-151256
//ASR source code issue, this function needs to be blocked
/*
* Base page is initialized by pmic_fault_wu_en_disable() which is a global
* interface. Skip pi2c_init(PMIC_BASE_PAGE_ADDR) here is to reduce bin size
*/
/* each bit should be set separately */
pmic_fault_wu_en_disable();
pmic_set_sw_powerdown();
}
/*---------------------------------------------------------------------------*/
/*
* crane: 28LP, vol=1.05v
* craneG Z2/A0: 22nm ULP, vol=0.8v
* craneM: 22nm ULP, vol=0.9v
*
* crane:
* defaultly vol = 1.05v
* no matter cpu freq is 416M or 624M, 1.05v can wrok normally.
* When cpu freq is 624M, cpu vol can not ve 1.0v
* if cp load, cpu core voltage: case1: 0xA0, 1.0v, 416M; case2: 0xA4, 1.05v, 624M
*
* power regs: 0x20 & 0x21:
* pm813/pmic813s/pm802/pm803: same
*/
static void
pmic_set_buck1_vol(uint8_t pmic_id)
{
uint8_t val;
unsigned addr;
/* Power page */
/* The DVC must be disabled before setting the cpu core voltage */
if(PM816 == pmic_id) {
/* Disable DVC, clear DVC_ENALE(bit7) */
/* Clear bits */
pi2c_clear_then_set_bits(PM816_DVC_SET_REG, DVC_ENALE, 0x0);
/*
* 1. 0x32(0.98v) for CraneW. But CraneW is not support in the project.
* Default is 0x20, represents 0.8v, CR5 need to set buck1 0.975v,
* weihai only has 0.97v/0.98v, so use 0.98v. Use 0.98v in order to
* prevent the problem the low temperature cann't boot(CraneLH 1606s
* WB8M DRO min). The value will be set back to 0.9V in the CP stage.
*
* 2. 0x20(0.8v) for Watch1.
*/
val = 0x20;
addr = PM816_BUCK1_VOLTAGE_SET_REG;
} else if((PM803L == pmic_id) || (PM807 == pmic_id) || (PM806 == pmic_id)) {
/* PM803L/PM807/PM806 doesn't support DVC */
val = 0xB2; /*0.98v */
addr = PM813_BUCK1_VOLTAGE_SET_REG;
} else if(PM813L == pmic_id) {
/* Disable DVC, clear DVC_ENALE(bit7) */
/* Clear bits */
pi2c_clear_then_set_bits(PM813L_DVC_SET_REG, DVC_ENALE, 0x0);
val = 0x1e; /* 0.975v for CraneLS/CraneGT/CraneLB */
addr = PM813L_BUCK1_VOLTAGE_SET_REG;
} else {
/* Disable DVC, , clear DVC_ENALE(bit7) */
/* Clear bits */
pi2c_clear_then_set_bits(PM813_DVC_SET_REG, DVC_ENALE, 0x0);
/*
* 1. val = 0xA4(1.05v) for Crane. But Crane is not supported in the
* project.
*
* 2. val = 0x9e(0.975v) for all chips except Crane. 0.975v in order to
* prevent the problem the low temperature cann't boot. The value will
* be set back to 0.9v in the CP stage.
*/
val = 0x9e;
addr = PM813_BUCK1_VOLTAGE_SET_REG;
}
/* Set cpu core vlotage
*
* The read value of the register may be different with the written value
* because the bit7(enable bit) is a RO bit in this register, which is
* modified by buck1_en/buck1_sw1_en2 register. Here only the voltage setting
* is changed.
*/
pi2c_write_reg(addr, val);
LOG_INFO("Set cpu core voltage, 0x%x = 0x%x\n", addr, val);
}
/*---------------------------------------------------------------------------*/
/*
* Set PMIC to skip mode
*
* pm813/pmic813s/pm802/pm802s/pm803/pm803l power regs: 0x22[5]
* pm816 power regs: 0x36[4]
*/
static void
pmic_set_buck1_skipmode(uint8_t pmic_id)
{
unsigned addr, clear_bits = 0, set_bits = 0;
LOG_INFO("Set skip mode\n");
/* Power page */
if(PM816 == pmic_id) {
addr = PM816_FSM_BUCK1_REG2;
/* Bit4 = 1, go to pwm */
set_bits = PM816_FSM_BUCK1_GO2PWM;
} else if(PM803L == pmic_id) {
addr = PM803L_FSM_BUCK1_REG5;
/* Bit0 = 0, go to pwm */
clear_bits = PM803L_FSM_BUCK1_GO2PWM;
} else if((PM807 == pmic_id) || (PM806 == pmic_id)) {
addr = PM807_FSM_BUCK1_REG3;
/* Bit0 = 1, go to pwm */
set_bits = PM807_FSM_BUCK1_GO2PWM;
} else if(PM813L == pmic_id) {
addr = PM813L_FSM_BUCK1_REG2;
/* Bit0 = 1, go to pwm */
set_bits = PM813L_FSM_BUCK1_GO2PWM;
} else {
addr = PM803_FSM_BUCK1_REG2;
/* Bit5 = 1, go to pwm */
set_bits = PM803_FSM_BUCK1_GO2PWM;
}
/* Clear or set bits */
pi2c_clear_then_set_bits(addr, clear_bits, set_bits);
}
/*---------------------------------------------------------------------------*/
/*
* PM802/PM802S/PM803: empty
* PMIC813/PMIC813s: power reg 0x8F,
* default val = 0xe(ldo11_disable, 1.8v), update to 0x42(ldo11_enabe, 1.2v)
* Bit 7 6 5 4 3 2 1 0
* | ldo11_en | ldo11_vset[3:0] | dischg_en | pd_ilim
*/
static void
pmic_set_ldo11_en_1_2v_for_PMIC813(void)
{
LOG_INFO("enable ldo11 1.2v\n");
/* Power page */
pi2c_clear_then_set_bits(PM813_LDO11_REG, LDO11_VSET_1_2V_BIT,
(LDO11_ENABLE | LDO11_VSET_1_2V));
}
void
pmic_set_uhs_voltage(void)
{
pi2c_init(PMIC_POWER_PAGE_ADDR);
pmic_set_ldo11_en_1_2v_for_PMIC813();
}
#if AROM_VERSION == AROM_VER_2022_11_11_CRANEG_CR5
/*
* In order to meet the power-on sequence of CraneGT DDR Phy requirements,
* it needs to set 1.2v within 20ms after power-on. Therefore, set LDO11 to
* 1.2v in the preboot stage.
*/
static void
pmic_set_ddr_phy_voltage(uint8_t pmic_id)
{
if(PM813S == pmic_id) {
pmic_set_ldo11_en_1_2v_for_PMIC813();
}
}
#endif
/*---------------------------------------------------------------------------*/
#if AROM_VERSION == AROM_VER_2020_07_30_CRANEGM_A0
/*
* PM803: power reg 0x82 /0x83,
* default val = 0xe(ldo7, 1.2v), update to (ldo7, 1.6v)
*/
static void
pmic_set_ldo7_en_1_6v_for_craneM_and_pm803(uint8_t pmic_id)
{
/* Only for 803 */
if(PM803 != pmic_id) {
return;
}
LOG_INFO("CraneM pm803: set ldo7 sleep/active mode 1.6v\n");
/* Power page */
/* Sleep mode configuraton */
pi2c_clear_then_set_bits(PM803_LDO7_SLEEP_MODE_REG, LDO7_VSET_1_6V_BIT,
LDO7_VSET_1_6V);
/* Sleep mode configuraton */
pi2c_clear_then_set_bits(PM803_LDO7_ACTIVE_MODE_REG, LDO7_VSET_1_6V_BIT,
LDO7_VSET_1_6V);
}
#endif
/*
* PM807: power reg 0x7A,
* default val = 0x8e(ldo4, 3.1v), update to (ldo4, 3.0v)
*/
#ifdef QUECTEL_PREBOOT_OPT
void
pmic_set_ldo4_en_3v_for_craneLG_LRH_and_pm807(void)
{
uint8_t val;
if(hw_platform_type() != HW_PLATFORM_TYPE_SILICON) {
return;
}
uint8_t pmic_id = pmic_get_id();
if(pmic_id == PMIC_UNAVAILABLE) {
return;
}
if(PM807 != PMIC_PID(pmic_id)) {
return;
}
pi2c_init(PMIC_POWER_PAGE_ADDR);
pi2c_read_reg(PM807_LDO4_ACTIVE_MODE_REG, &val);
val = (val & ~PM807_LDO4_VSET_3V_BIT) | PM807_LDO4_VSET_3V;
pi2c_write_reg(PM807_LDO4_ACTIVE_MODE_REG, val);
pi2c_read_reg(PM807_LDO4_ACTIVE_MODE_REG, &val);
LOG_INFO("CraneLG pm807: set ldo4 output setting under active mode 3v: [0x%x] = 0x%x\n", 0x7A, val);
}
#endif
/*---------------------------------------------------------------------------*/
/*
* LDO2 supply power for fuse module (pad: QVPS pin)
* only CraneL pm803 need 1.9v when burn fuse
* PM803: power reg 0x74,
* default val = 0x4(ldo2, 1.8v), update to 0x5 (ldo2, 1.9v)
*/
static void
_pmic_set_fuse_voltage(unsigned int vol)
{
(void)vol;
uint8_t pmic_id = pmic_get_id();
if(PM803 != pmic_id) {
return;
}
/* Power page */
#if ((AROM_VERSION == AROM_VER_2021_10_16_CRANEL_A0) || \
(AROM_VERSION == AROM_VER_2022_11_06_CRANEL_CR5))
if(CHIP_ID_CRANELB != hw_chip_id()) {
/* CraneL, CraneLR/LS/LG/LRH */
/* LOG_PRINT("cranel/lr/ls/lg/lrh\n"); */
LOG_INFO("CraneL pm803: set fuse vol\n");
pi2c_clear_then_set_bits(0x74, 0xF, vol);
}
#endif
}
#ifdef BOARD_CRANEW_MCU
#define PM813S_LDO_1_2_V 0x42
#define PM813S_LDO_1_8_V 0x4E
#define PM813S_LDO_2_8_V 0x6A
#define PM813S_LDO_3_3_V 0x7E
#define PM813S_POWER_LDO1 0x71
#define PM813S_POWER_LDO2 0x74
#define PM813S_POWER_LDO4 0x7A
#define PM813S_POWER_LDO5 0x7D
#define PM813S_POWER_LDO6 0x80
#define PM813S_POWER_LDO7 0x83
#define PM813S_POWER_LDO9 0x89
#define PM813S_POWER_LDO11 0x8F
#define PM813S_POWER_LDO12 0x92
#define PM816_LDO_1_8_V 0x06
#define PM816_LDO_3_3_V 0x0F
#define PM816_POWER_LDO11 0xCF
#define PM816_POWER_LDO12 0xD2
#define PM816_POWER_LDO11_EN 0x12
#define PM816_POWER_LDO12_EN 0x13
#define PM816_POWER_BUCKLDO_CTRL3 0x10
/*
***************************************************************************************
//ldo1, rf, default is off
pi2c_write_reg(PM813S_POWER_LDO1, PM813S_LDO_2_8_V);
pi2c_read_reg(PM813S_POWER_LDO1, &val);
LOG_INFO("Cranew: set ldo1 active mode 2.8v: [0x%x] = 0x%x\n", PM813S_POWER_LDO1, val);
//ldo2, usb, default is on
pi2c_write_reg(PM813S_POWER_LDO2, PM813S_LDO_3_3_V);
pi2c_read_reg(PM813S_POWER_LDO2, &val);
LOG_INFO("Cranew: set ldo2 active mode 3.3v: [0x%x] = 0x%x\n", PM813S_POWER_LDO2, val);
//ldo5, TCXO_SW
pi2c_write_reg(PM813S_POWER_LDO5, PM813S_LDO_1_8_V);
pi2c_read_reg(PM813S_POWER_LDO5, &val);
LOG_INFO("Cranew: set ldo5 active mode 1.8v: [0x%x] = 0x%x\n", PM813S_POWER_LDO5, val);
//ldo6, AVDD18_AP, default is on
pi2c_write_reg(PM813S_POWER_LDO6, PM813S_LDO_1_8_V);
pi2c_read_reg(PM813S_POWER_LDO6, &val);
LOG_INFO("Cranew: set ldo6 active mode 1.8v: [0x%x] = 0x%x\n", PM813S_POWER_LDO6, val);
//ldo7, RF_1P8V, default is on
pi2c_write_reg(PM813S_POWER_LDO7, PM813S_LDO_1_8_V);
pi2c_read_reg(PM813S_POWER_LDO7, &val);
LOG_INFO("Cranew: set ldo7 active mode 1.8v: [0x%x] = 0x%x\n", PM813S_POWER_LDO7, val);
//ldo11, VRF_1P2V_SW, default is off
pi2c_write_reg(PM813S_POWER_LDO11, PM813S_LDO_1_2_V);
pi2c_read_reg(PM813S_POWER_LDO11, &val);
LOG_INFO("Cranew: set ldo11 active mode 1.2v: [0x%x] = 0x%x\n", PM813S_POWER_LDO11, val);
//ldo12, AVDD peripheral, default is off
pi2c_write_reg(PM813S_POWER_LDO12, PM813S_LDO_2_8_V);
pi2c_read_reg(PM813S_POWER_LDO12, &val);
LOG_INFO("Cranew: set ldo12 active mode 2.8v: [0x%x] = 0x%x\n", PM813S_POWER_LDO12, val);
***************************************************************************************
* emmc, default ldo4 and ldo9 is off, need on. if ldo off, emmc cmd1 will no response.
*/
static void
pmic_LDO_config_for_cranew_mcu_and_pm813s(uint8_t pmic_id)
{
unsigned char val;
if(PM813S == pmic_id) {
/*ldo4, VDD emmc, default is off, active it in preboot. */
val = PM813S_LDO_3_3_V;
pi2c_write_reg(PM813S_POWER_LDO4, val);
/* No need to read back for debugging log */
LOG_INFO("Cranew: set ldo4 active mode 3.3v: 0x%x = 0x%x\n", PM813S_POWER_LDO4, val);
/*ldo9, VIO emmc, default is off, active it in preboot. */
val = PM813S_LDO_1_8_V;
pi2c_write_reg(PM813S_POWER_LDO9, val);
/* No need to read back for debugging log */
LOG_INFO("Cranew: set ldo9 active mode 1.8v: 0x%x = 0x%x\n", PM813S_POWER_LDO9, val);
}
#if 0
/* weihai B1, BT/BLE 1.2v AVDD and PA is off by default, for BT test, temperally enable buck4_sw4 */
else if(PM816 == pmic_id) {
pi2c_read_reg(PM816_POWER_BUCKLDO_CTRL3, &val);
pi2c_write_reg(PM816_POWER_BUCKLDO_CTRL3, (val | (1 << 6))); /*enable buck4_sw4 for BT */
pi2c_read_reg(PM816_POWER_BUCKLDO_CTRL3, &val);
LOG_INFO("Fulmar: set buck4_sw4 on: [0x%x] = 0x%x\n", PM816_POWER_BUCKLDO_CTRL3, val);
}
#endif
#if 0 /*for PM816 , ldo11 and ldo12, already enbaled in OTP, don't need set again */
else { /*PM816 */
/*ldo12, VDD emmc, active it in preboot if it's off by default. */
pi2c_write_reg(PM816_POWER_LDO12, PM816_LDO_3_3_V);
pi2c_read_reg(PM816_POWER_LDO12, &val);
LOG_INFO("Cranew: set ldo12 active mode 3.3v: [0x%x] = 0x%x\n", PM816_POWER_LDO12, val);
/*ldo11, VIO emmc, active it in preboot if it's off by default. */
pi2c_write_reg(PM816_POWER_LDO11, PM816_LDO_1_8_V);
pi2c_read_reg(PM816_POWER_LDO11, &val);
LOG_INFO("Cranew: set ldo11 active mode 1.8v: [0x%x] = 0x%x\n", PM816_POWER_LDO11, val);
pi2c_read_reg(PM816_POWER_LDO12_EN, &val);
pi2c_write_reg(PM816_POWER_LDO12_EN, (val | (1 << 0))); /*enable LDO12 */
pi2c_read_reg(PM816_POWER_LDO11_EN, &val);
pi2c_write_reg(PM816_POWER_LDO11_EN, (val | (1 << 7))); /*enable LDO11 */
}
#endif
return;
}
#endif /* BOARD_CRANEW_MCU */
/*---------------------------------------------------------------------------*/
void
pmic_set_fuse_voltage(void)
{
pi2c_init(PMIC_POWER_PAGE_ADDR);
_pmic_set_fuse_voltage(PM803_LDO_2_VOL_1_9V);
}
/*---------------------------------------------------------------------------*/
void
pmic_restore_fuse_voltage(void)
{
pi2c_init(PMIC_POWER_PAGE_ADDR);
_pmic_set_fuse_voltage(PM803_LDO_2_VOL_1_8V);
}
#endif