1 /*
2 * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <errno.h>
8
9 #include <common/debug.h>
10
11 #include <drivers/pmic/pmic_shutdown_cfg.h>
12 #include <drivers/spmi/spmi_common.h>
13 #include <drivers/spmi_api.h>
14 #include <lib/mtk_init/mtk_init.h>
15
16 #define MASTER_ID SPMI_MASTER_1
17
18 #ifndef MT8678_PMIC_SUPPORT
19 /* MT6316 will automatically disable wdt in poffs */
20 #define MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR 0x408
21 #define MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_MASK 0x1
22 #define MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT 1
23 #else
24 /* MT6319 will automatically disable wdt in poffs */
25 #define MT6319_TOP_RST_MISC_CLR 0x128
26 #define MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR 0x138
27 #define MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_MASK 0x1
28 #define MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT 2
29 #endif
30
31 #define MT6373_TOP_RST_MISC1_CLR 0x13B
32 #define MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR 0x408
33 #define MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_MASK 0x1
34 #define MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT 1
35
36 #define MT6685_TOP_RST_MISC_CLR 0x129
37 #define MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR 0x408
38 #define MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_MASK 0x1
39 #define MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT 1
40
41 struct spmi_device *sdev_arr[SPMI_MAX_SLAVE_ID];
42
43 struct cfg_t {
44 uint8_t slvid;
45 uint32_t addr;
46 uint32_t shutdown_src_addr;
47 uint32_t shutdown_src_mask;
48 uint32_t shutdown_src_shift;
49 uint8_t val;
50 };
51
52 #ifndef MT8678_PMIC_SUPPORT
53 static const struct cfg_t cfg_arr[] = {
54 {
55 .slvid = SPMI_SLAVE_6,
56 .addr = 0,
57 .shutdown_src_addr = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
58 .shutdown_src_mask = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
59 .shutdown_src_shift = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
60 .val = 0x1
61 }, {
62 .slvid = SPMI_SLAVE_7,
63 .addr = 0,
64 .shutdown_src_addr = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
65 .shutdown_src_mask = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
66 .shutdown_src_shift = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
67 .val = 0x1
68 }, {
69 .slvid = SPMI_SLAVE_8,
70 .addr = 0,
71 .shutdown_src_addr = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
72 .shutdown_src_mask = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
73 .shutdown_src_shift = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
74 .val = 0x1
75 }, {
76 .slvid = SPMI_SLAVE_15,
77 .addr = 0,
78 .shutdown_src_addr = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
79 .shutdown_src_mask = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
80 .shutdown_src_shift = MT6316_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
81 .val = 0x1
82 }, {
83 .slvid = SPMI_SLAVE_5,
84 .addr = MT6373_TOP_RST_MISC1_CLR,
85 .shutdown_src_addr = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
86 .shutdown_src_mask = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
87 .shutdown_src_shift = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
88 .val = 0x1
89 }, {
90 .slvid = SPMI_SLAVE_9,
91 .addr = MT6685_TOP_RST_MISC_CLR,
92 .shutdown_src_addr = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
93 .shutdown_src_mask = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
94 .shutdown_src_shift = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
95 .val = 0x1
96 }
97 };
98 #else /* MT8678_PMIC_SUPPORT */
99 static const struct cfg_t cfg_arr[] = {
100 {
101 .slvid = SPMI_SLAVE_6,
102 .addr = MT6319_TOP_RST_MISC_CLR,
103 .shutdown_src_addr = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
104 .shutdown_src_mask = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
105 .shutdown_src_shift = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
106 .val = 0x1
107 }, {
108 .slvid = SPMI_SLAVE_7,
109 .addr = MT6319_TOP_RST_MISC_CLR,
110 .shutdown_src_addr = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
111 .shutdown_src_mask = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
112 .shutdown_src_shift = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
113 .val = 0x1
114 }, {
115 .slvid = SPMI_SLAVE_8,
116 .addr = MT6319_TOP_RST_MISC_CLR,
117 .shutdown_src_addr = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
118 .shutdown_src_mask = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
119 .shutdown_src_shift = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
120 .val = 0x1
121 }, {
122 .slvid = SPMI_SLAVE_15,
123 .addr = MT6319_TOP_RST_MISC_CLR,
124 .shutdown_src_addr = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
125 .shutdown_src_mask = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
126 .shutdown_src_shift = MT6319_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
127 .val = 0x1
128 }, {
129 .slvid = SPMI_SLAVE_5,
130 .addr = MT6373_TOP_RST_MISC1_CLR,
131 .shutdown_src_addr = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
132 .shutdown_src_mask = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
133 .shutdown_src_shift = MT6373_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
134 .val = 0x1
135 }, {
136 .slvid = SPMI_SLAVE_9,
137 .addr = MT6685_TOP_RST_MISC_CLR,
138 .shutdown_src_addr = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_ADDR,
139 .shutdown_src_mask = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_MASK,
140 .shutdown_src_shift = MT6685_PMIC_RG_SHUTDOWN_SRC_SEL_SHIFT,
141 .val = 0x1
142 }
143 };
144 #endif /* MT8678_PMIC_SUPPORT */
145
146 #define MT6316_TOP_ANA_KEY 0x3AA
147 #define MT6316_PMIC_RG_VI075_SINK_CUR_ADDR 0x994
148 #define MT6316_PMIC_RG_VI075_SINK_CUR_MASK 0xF
149 #define MT6316_PMIC_RG_VI075_SINK_CUR_SHIFT 4
150 #define MT6316_PMIC_RG_PSEQ_ELR_RSV2_ADDR 0xA2C
151 #define MT6316_PMIC_RG_PSEQ_ELR_RSV2_MASK 0x7
152 #define MT6316_PMIC_RG_PSEQ_ELR_RSV2_SHIFT 5
153 #define PSEQ_ELR_RSV2_VAL_MASK_1 0x3
154 #define PSEQ_ELR_RSV2_VAL_MASK_2 0x1
155 #define VI075_SINK_CUR_SOURCE_1 0x5
156 #define VI075_SINK_CUR_SOURCE_2 0
157 #define VI075_SINK_CUR_SOURCE_3 0xB
158 #define ARRAY_LENGTH_MAX 2
159
160 #ifndef MT8678_PMIC_SUPPORT
mt6316_key_lock_check(struct spmi_device * mt6316_dev,uint16_t key)161 static void mt6316_key_lock_check(struct spmi_device *mt6316_dev, uint16_t key)
162 {
163 int i, ret;
164 uint16_t rdata;
165 uint8_t work_val[ARRAY_LENGTH_MAX];
166 uint8_t wdata[ARRAY_LENGTH_MAX];
167
168 for (i = 0; i < 2; i++) {
169 ret = spmi_ext_register_readl(mt6316_dev, key, &work_val[0], 2);
170 if (ret < 0) {
171 INFO("[%s]: read fail, addr = 0x%x, ret = %d\n"
172 , __func__, key, ret);
173 i = 0;
174 continue;
175 }
176 rdata = work_val[0] | (work_val[1] << 8);
177
178 if (rdata != 0) {
179 INFO("[%s] lock fail, addr = 0x%x, rdata = 0x%x.\n"
180 , __func__, key, rdata);
181 wdata[0] = 0;
182 wdata[1] = 0;
183 spmi_ext_register_writel(mt6316_dev, key, &wdata[0], 2);
184 i = 0;
185 }
186 }
187 }
188
wk_vio075_sink_cur(struct spmi_device * mt6316_dev,unsigned char en_seq_off)189 static void wk_vio075_sink_cur(struct spmi_device *mt6316_dev, unsigned char en_seq_off)
190 {
191 uint8_t rval, wval;
192 int ret;
193 uint8_t buf[ARRAY_LENGTH_MAX];
194
195 ret = spmi_ext_register_readl(mt6316_dev, MT6316_PMIC_RG_PSEQ_ELR_RSV2_ADDR, &rval, 1);
196 if (ret < 0)
197 return;
198 rval = (rval >> MT6316_PMIC_RG_PSEQ_ELR_RSV2_SHIFT) & MT6316_PMIC_RG_PSEQ_ELR_RSV2_MASK;
199
200 if (!(rval & PSEQ_ELR_RSV2_VAL_MASK_1)) {
201 wval = VI075_SINK_CUR_SOURCE_1;
202 } else if (rval & PSEQ_ELR_RSV2_VAL_MASK_2) {
203 if (en_seq_off)
204 wval = VI075_SINK_CUR_SOURCE_2;
205 else
206 wval = VI075_SINK_CUR_SOURCE_3;
207 } else {
208 wval = VI075_SINK_CUR_SOURCE_2;
209 }
210
211 buf[0] = 0xDC;
212 buf[1] = 0xF1;
213 spmi_ext_register_writel(mt6316_dev,
214 MT6316_TOP_ANA_KEY,
215 &buf[0], 2); /* unlock TOP_ANA key */
216 spmi_ext_register_writel_field(mt6316_dev,
217 MT6316_PMIC_RG_VI075_SINK_CUR_ADDR, wval,
218 MT6316_PMIC_RG_VI075_SINK_CUR_MASK,
219 MT6316_PMIC_RG_VI075_SINK_CUR_SHIFT);
220 buf[0] = 0;
221 buf[1] = 0;
222 spmi_ext_register_writel(mt6316_dev,
223 MT6316_TOP_ANA_KEY,
224 &buf[0], 2); /* lock TOP_ANA key */
225 mt6316_key_lock_check(mt6316_dev, MT6316_TOP_ANA_KEY);
226 }
227 #endif
228
pmic_shutdown_cfg_init(void)229 static int pmic_shutdown_cfg_init(void)
230 {
231 uint8_t i, slvid;
232
233 for (i = 0; i < ARRAY_SIZE(cfg_arr); i++) {
234 slvid = cfg_arr[i].slvid;
235 if (sdev_arr[slvid] != NULL)
236 continue;
237 sdev_arr[slvid] = get_spmi_device(MASTER_ID, slvid);
238 if (!sdev_arr[slvid])
239 return -ENODEV;
240 }
241 return 0;
242 }
243 MTK_PLAT_SETUP_0_INIT(pmic_shutdown_cfg_init);
244
pmic_shutdown_cfg(void)245 int pmic_shutdown_cfg(void)
246 {
247 int ret;
248 uint8_t i, slvid;
249 uint32_t addr;
250 uint8_t val;
251
252 for (i = 0; i < ARRAY_SIZE(cfg_arr); i++) {
253 slvid = cfg_arr[i].slvid;
254 if (!sdev_arr[slvid])
255 return -ENODEV;
256 /* mt6316 vio075 sink current adjustment */
257 if ((slvid >= SPMI_SLAVE_6 && slvid <= SPMI_SLAVE_8) || slvid == SPMI_SLAVE_15)
258 wk_vio075_sink_cur(sdev_arr[slvid], 1);
259 addr = cfg_arr[i].addr;
260 val = cfg_arr[i].val;
261 /* Disable WDTRSTB_EN */
262 if (addr) {
263 ret = spmi_ext_register_writel(sdev_arr[slvid], addr, &val, 1);
264 if (ret < 0)
265 return ret;
266 }
267
268 /* set RG_SHUTDOWN_SRC_SEL to 1, shutdown PMIC by SPMI command */
269 spmi_ext_register_writel_field(sdev_arr[slvid],
270 cfg_arr[i].shutdown_src_addr, 1,
271 cfg_arr[i].shutdown_src_mask,
272 cfg_arr[i].shutdown_src_shift);
273 }
274 return 1; /* 1: use spmi_command_shutdown API */
275 }
276
277 /* shutdown PMIC by SPMI command */
spmi_shutdown(void)278 int spmi_shutdown(void)
279 {
280 struct spmi_device *mt6363_sdev = get_spmi_device(SPMI_MASTER_1, SPMI_SLAVE_4);
281
282 if (!mt6363_sdev)
283 return -ENODEV;
284
285 /* set RG_SHUTDOWN_SRC_SEL to 1 */
286 spmi_ext_register_writel_field(mt6363_sdev, 0x408, 1, 0x1, 1);
287 spmi_command_shutdown(SPMI_MASTER_P_1, mt6363_sdev, 0x800);
288 spmi_command_shutdown(SPMI_MASTER_1, mt6363_sdev, 0x800);
289
290 return 0;
291 }
292