arm-trusted-firmware/plat/mediatek/drivers/pmic/pmic_psc.c
Hope Wang d4e6f98d7f feat(mt8196): add PMIC driver
1. Add PMIC shutdown API
2. Add PMIC low power settings

Change-Id: I634a60fa3e2a74a6031df9fe59e2f52956ef7114
Signed-off-by: Hope Wang <hope.wang@mediatek.corp-partner.google.com>
2025-01-22 11:50:47 +08:00

117 lines
2.4 KiB
C

/*
* Copyright (c) 2025, Mediatek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <common/debug.h>
#include <drivers/pmic/pmic_psc.h>
#ifdef CONFIG_MTK_PMIC_SHUTDOWN_CFG
#include <drivers/pmic/pmic_shutdown_cfg.h>
#endif
#define ERR_INVALID_ARGS -EINVAL
#define ERR_NOT_CONFIGURED -ENODEV
static const struct pmic_psc_config *pmic_psc;
static uint32_t read_pmic_psc_reg(enum pmic_psc_reg_name reg_name)
{
uint32_t val = 0;
const struct pmic_psc_reg *reg;
if (reg_name >= pmic_psc->reg_size)
return 0;
reg = &pmic_psc->regs[reg_name];
pmic_psc->read_field(reg->reg_addr, &val, reg->reg_mask, reg->reg_shift);
return val;
}
static int set_pmic_psc_reg(enum pmic_psc_reg_name reg_name)
{
const struct pmic_psc_reg *reg;
if (reg_name >= pmic_psc->reg_size)
return ERR_INVALID_ARGS;
reg = &pmic_psc->regs[reg_name];
pmic_psc->write_field(reg->reg_addr, 1, reg->reg_mask, reg->reg_shift);
return 0;
}
static int clr_pmic_psc_reg(enum pmic_psc_reg_name reg_name)
{
const struct pmic_psc_reg *reg;
if (reg_name >= pmic_psc->reg_size)
return ERR_INVALID_ARGS;
reg = &pmic_psc->regs[reg_name];
pmic_psc->write_field(reg->reg_addr, 0, reg->reg_mask, reg->reg_shift);
return 0;
}
int enable_pmic_smart_reset(bool enable)
{
if (!pmic_psc)
return ERR_NOT_CONFIGURED;
if (enable)
set_pmic_psc_reg(RG_SMART_RST_MODE);
else
clr_pmic_psc_reg(RG_SMART_RST_MODE);
return 0;
}
int enable_pmic_smart_reset_shutdown(bool enable)
{
if (!pmic_psc)
return ERR_NOT_CONFIGURED;
if (enable)
set_pmic_psc_reg(RG_SMART_RST_SDN_EN);
else
clr_pmic_psc_reg(RG_SMART_RST_SDN_EN);
return 0;
}
int platform_cold_reset(void)
{
if (!pmic_psc)
return ERR_NOT_CONFIGURED;
/* Some PMICs may not support cold reset */
if (!pmic_psc->regs[RG_CRST].reg_addr)
return ERR_NOT_CONFIGURED;
set_pmic_psc_reg(RG_CRST);
return 0;
}
int platform_power_hold(bool hold)
{
int use_spmi_cmd_sdn = 0;
if (!pmic_psc)
return ERR_NOT_CONFIGURED;
if (hold)
set_pmic_psc_reg(RG_PWRHOLD);
else {
#ifdef CONFIG_MTK_PMIC_SHUTDOWN_CFG
use_spmi_cmd_sdn = pmic_shutdown_cfg();
#endif
if (use_spmi_cmd_sdn == 1)
spmi_shutdown();
else
clr_pmic_psc_reg(RG_PWRHOLD);
}
return 0;
}
int pmic_psc_register(const struct pmic_psc_config *psc)
{
if (!psc || !psc->regs || !psc->read_field || !psc->write_field)
return ERR_INVALID_ARGS;
pmic_psc = psc;
INFO("POWER_HOLD=0x%x\n", read_pmic_psc_reg(RG_PWRHOLD));
return 0;
}