1*d4e6f98dSHope Wang /* 2*d4e6f98dSHope Wang * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3*d4e6f98dSHope Wang * 4*d4e6f98dSHope Wang * SPDX-License-Identifier: BSD-3-Clause 5*d4e6f98dSHope Wang */ 6*d4e6f98dSHope Wang 7*d4e6f98dSHope Wang #include <errno.h> 8*d4e6f98dSHope Wang 9*d4e6f98dSHope Wang #include <common/debug.h> 10*d4e6f98dSHope Wang #include <drivers/pmic/pmic_psc.h> 11*d4e6f98dSHope Wang #ifdef CONFIG_MTK_PMIC_SHUTDOWN_CFG 12*d4e6f98dSHope Wang #include <drivers/pmic/pmic_shutdown_cfg.h> 13*d4e6f98dSHope Wang #endif 14*d4e6f98dSHope Wang 15*d4e6f98dSHope Wang #define ERR_INVALID_ARGS -EINVAL 16*d4e6f98dSHope Wang #define ERR_NOT_CONFIGURED -ENODEV 17*d4e6f98dSHope Wang 18*d4e6f98dSHope Wang static const struct pmic_psc_config *pmic_psc; 19*d4e6f98dSHope Wang 20*d4e6f98dSHope Wang static uint32_t read_pmic_psc_reg(enum pmic_psc_reg_name reg_name) 21*d4e6f98dSHope Wang { 22*d4e6f98dSHope Wang uint32_t val = 0; 23*d4e6f98dSHope Wang const struct pmic_psc_reg *reg; 24*d4e6f98dSHope Wang 25*d4e6f98dSHope Wang if (reg_name >= pmic_psc->reg_size) 26*d4e6f98dSHope Wang return 0; 27*d4e6f98dSHope Wang 28*d4e6f98dSHope Wang reg = &pmic_psc->regs[reg_name]; 29*d4e6f98dSHope Wang pmic_psc->read_field(reg->reg_addr, &val, reg->reg_mask, reg->reg_shift); 30*d4e6f98dSHope Wang return val; 31*d4e6f98dSHope Wang } 32*d4e6f98dSHope Wang 33*d4e6f98dSHope Wang static int set_pmic_psc_reg(enum pmic_psc_reg_name reg_name) 34*d4e6f98dSHope Wang { 35*d4e6f98dSHope Wang const struct pmic_psc_reg *reg; 36*d4e6f98dSHope Wang 37*d4e6f98dSHope Wang if (reg_name >= pmic_psc->reg_size) 38*d4e6f98dSHope Wang return ERR_INVALID_ARGS; 39*d4e6f98dSHope Wang 40*d4e6f98dSHope Wang reg = &pmic_psc->regs[reg_name]; 41*d4e6f98dSHope Wang pmic_psc->write_field(reg->reg_addr, 1, reg->reg_mask, reg->reg_shift); 42*d4e6f98dSHope Wang return 0; 43*d4e6f98dSHope Wang } 44*d4e6f98dSHope Wang 45*d4e6f98dSHope Wang static int clr_pmic_psc_reg(enum pmic_psc_reg_name reg_name) 46*d4e6f98dSHope Wang { 47*d4e6f98dSHope Wang const struct pmic_psc_reg *reg; 48*d4e6f98dSHope Wang 49*d4e6f98dSHope Wang if (reg_name >= pmic_psc->reg_size) 50*d4e6f98dSHope Wang return ERR_INVALID_ARGS; 51*d4e6f98dSHope Wang 52*d4e6f98dSHope Wang reg = &pmic_psc->regs[reg_name]; 53*d4e6f98dSHope Wang pmic_psc->write_field(reg->reg_addr, 0, reg->reg_mask, reg->reg_shift); 54*d4e6f98dSHope Wang return 0; 55*d4e6f98dSHope Wang } 56*d4e6f98dSHope Wang 57*d4e6f98dSHope Wang int enable_pmic_smart_reset(bool enable) 58*d4e6f98dSHope Wang { 59*d4e6f98dSHope Wang if (!pmic_psc) 60*d4e6f98dSHope Wang return ERR_NOT_CONFIGURED; 61*d4e6f98dSHope Wang if (enable) 62*d4e6f98dSHope Wang set_pmic_psc_reg(RG_SMART_RST_MODE); 63*d4e6f98dSHope Wang else 64*d4e6f98dSHope Wang clr_pmic_psc_reg(RG_SMART_RST_MODE); 65*d4e6f98dSHope Wang return 0; 66*d4e6f98dSHope Wang } 67*d4e6f98dSHope Wang 68*d4e6f98dSHope Wang int enable_pmic_smart_reset_shutdown(bool enable) 69*d4e6f98dSHope Wang { 70*d4e6f98dSHope Wang if (!pmic_psc) 71*d4e6f98dSHope Wang return ERR_NOT_CONFIGURED; 72*d4e6f98dSHope Wang if (enable) 73*d4e6f98dSHope Wang set_pmic_psc_reg(RG_SMART_RST_SDN_EN); 74*d4e6f98dSHope Wang else 75*d4e6f98dSHope Wang clr_pmic_psc_reg(RG_SMART_RST_SDN_EN); 76*d4e6f98dSHope Wang return 0; 77*d4e6f98dSHope Wang } 78*d4e6f98dSHope Wang 79*d4e6f98dSHope Wang int platform_cold_reset(void) 80*d4e6f98dSHope Wang { 81*d4e6f98dSHope Wang if (!pmic_psc) 82*d4e6f98dSHope Wang return ERR_NOT_CONFIGURED; 83*d4e6f98dSHope Wang /* Some PMICs may not support cold reset */ 84*d4e6f98dSHope Wang if (!pmic_psc->regs[RG_CRST].reg_addr) 85*d4e6f98dSHope Wang return ERR_NOT_CONFIGURED; 86*d4e6f98dSHope Wang set_pmic_psc_reg(RG_CRST); 87*d4e6f98dSHope Wang return 0; 88*d4e6f98dSHope Wang } 89*d4e6f98dSHope Wang 90*d4e6f98dSHope Wang int platform_power_hold(bool hold) 91*d4e6f98dSHope Wang { 92*d4e6f98dSHope Wang int use_spmi_cmd_sdn = 0; 93*d4e6f98dSHope Wang 94*d4e6f98dSHope Wang if (!pmic_psc) 95*d4e6f98dSHope Wang return ERR_NOT_CONFIGURED; 96*d4e6f98dSHope Wang if (hold) 97*d4e6f98dSHope Wang set_pmic_psc_reg(RG_PWRHOLD); 98*d4e6f98dSHope Wang else { 99*d4e6f98dSHope Wang #ifdef CONFIG_MTK_PMIC_SHUTDOWN_CFG 100*d4e6f98dSHope Wang use_spmi_cmd_sdn = pmic_shutdown_cfg(); 101*d4e6f98dSHope Wang #endif 102*d4e6f98dSHope Wang if (use_spmi_cmd_sdn == 1) 103*d4e6f98dSHope Wang spmi_shutdown(); 104*d4e6f98dSHope Wang else 105*d4e6f98dSHope Wang clr_pmic_psc_reg(RG_PWRHOLD); 106*d4e6f98dSHope Wang } 107*d4e6f98dSHope Wang return 0; 108*d4e6f98dSHope Wang } 109*d4e6f98dSHope Wang 110*d4e6f98dSHope Wang int pmic_psc_register(const struct pmic_psc_config *psc) 111*d4e6f98dSHope Wang { 112*d4e6f98dSHope Wang if (!psc || !psc->regs || !psc->read_field || !psc->write_field) 113*d4e6f98dSHope Wang return ERR_INVALID_ARGS; 114*d4e6f98dSHope Wang pmic_psc = psc; 115*d4e6f98dSHope Wang INFO("POWER_HOLD=0x%x\n", read_pmic_psc_reg(RG_PWRHOLD)); 116*d4e6f98dSHope Wang return 0; 117*d4e6f98dSHope Wang } 118