970 lines
28 KiB
C
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, ®_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, ®_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, ®_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
|