/* * Copyright (c) 2025, Mediatek Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #ifdef CONFIG_MTK_PMIC_SHUTDOWN_CFG #include #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; }