xref: /rk3399_ARM-atf/plat/mediatek/drivers/pmic/pmic_psc.c (revision cf2df874cd09305ac7282fadb0fef6be597dfffb)
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 
read_pmic_psc_reg(enum pmic_psc_reg_name reg_name)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 
set_pmic_psc_reg(enum pmic_psc_reg_name reg_name)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 
clr_pmic_psc_reg(enum pmic_psc_reg_name reg_name)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 
enable_pmic_smart_reset(bool enable)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 
enable_pmic_smart_reset_shutdown(bool enable)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 
platform_cold_reset(void)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 
platform_power_hold(bool hold)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 
pmic_psc_register(const struct pmic_psc_config * psc)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