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 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 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 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 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 */ 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