1 /* 2 * Copyright (c) 2025, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <drivers/delay_timer.h> 9 #include <lib/mmio.h> 10 #include <lib/spinlock.h> 11 12 #include <mtk_mmap_pool.h> 13 #include "pmic_wrap_init.h" 14 #include "pmic_wrap_v3.h" 15 16 static spinlock_t wrp_lock; 17 18 static uint32_t pwrap_check_idle(uintptr_t wacs_register, uintptr_t wacs_vldclr_register, 19 uint32_t timeout_us) 20 { 21 uint32_t reg_rdata = 0U, retry; 22 23 retry = (timeout_us + PWRAP_POLL_STEP_US) / PWRAP_POLL_STEP_US; 24 while (retry != 0) { 25 udelay(PWRAP_POLL_STEP_US); 26 reg_rdata = mmio_read_32(wacs_register); 27 /* if last read command timeout,clear vldclr bit 28 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR; 29 * write:FSM_REQ-->idle 30 */ 31 switch (GET_WACS_FSM(reg_rdata)) { 32 case SWINF_FSM_WFVLDCLR: 33 mmio_write_32(wacs_vldclr_register, 0x1); 34 INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n"); 35 break; 36 case SWINF_FSM_WFDLE: 37 INFO("WACS_FSM = SWINF_FSM_WFDLE\n"); 38 break; 39 case SWINF_FSM_REQ: 40 INFO("WACS_FSM = SWINF_FSM_REQ\n"); 41 break; 42 case SWINF_FSM_IDLE: 43 goto done; 44 default: 45 break; 46 } 47 retry--; 48 } 49 50 done: 51 if (retry == 0) { 52 /* timeout */ 53 return E_PWR_WAIT_IDLE_TIMEOUT; 54 } 55 56 return 0U; 57 } 58 59 static uint32_t pwrap_check_vldclr(uintptr_t wacs_register, uint32_t timeout_us) 60 { 61 uint32_t reg_rdata = 0U, retry; 62 63 retry = (timeout_us + PWRAP_POLL_STEP_US) / PWRAP_POLL_STEP_US; 64 while (retry != 0) { 65 udelay(PWRAP_POLL_STEP_US); 66 reg_rdata = mmio_read_32(wacs_register); 67 if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) { 68 break; 69 } 70 retry--; 71 } 72 73 if (retry == 0) { 74 /* timeout */ 75 return E_PWR_WAIT_IDLE_TIMEOUT; 76 } 77 78 return 0U; 79 } 80 81 static int32_t pwrap_swinf_acc(uint32_t swinf_no, uint32_t cmd, uint32_t write, 82 uint32_t pmifid, uint32_t slvid, uint32_t addr, 83 uint32_t bytecnt, uint32_t wdata, uint32_t *rdata) 84 { 85 uint32_t reg_rdata = 0x0; 86 int32_t ret = 0x0; 87 88 /* Check argument validation */ 89 if ((swinf_no & ~(0x3)) != 0) 90 return -E_PWR_INVALID_SWINF; 91 if ((cmd & ~(0x3)) != 0) 92 return -E_PWR_INVALID_CMD; 93 if ((write & ~(0x1)) != 0) 94 return -E_PWR_INVALID_RW; 95 if ((pmifid & ~(0x1)) != 0) 96 return -E_PWR_INVALID_PMIFID; 97 if ((slvid & ~(0xf)) != 0) 98 return -E_PWR_INVALID_SLVID; 99 if ((addr & ~(0xffff)) != 0) 100 return -E_PWR_INVALID_ADDR; 101 if ((bytecnt & ~(0x1)) != 0) 102 return -E_PWR_INVALID_BYTECNT; 103 if ((wdata & ~(0xffff)) != 0) 104 return -E_PWR_INVALID_WDAT; 105 106 spin_lock(&wrp_lock); 107 /* Check whether INIT_DONE is set */ 108 if (pmifid == 0) 109 reg_rdata = mmio_read_32((uintptr_t)(&mtk_pwrap->wacs[swinf_no].sta)); 110 111 if (GET_SWINF_INIT_DONE(reg_rdata) != 0x1) { 112 ERROR("[PWRAP] init not finish\n"); 113 ret = -E_PWR_NOT_INIT_DONE; 114 goto end; 115 } 116 117 /* Wait for Software Interface FSM state to be IDLE */ 118 ret = pwrap_check_idle((uintptr_t)(&mtk_pwrap->wacs[swinf_no].sta), 119 (uintptr_t)(&mtk_pwrap->wacs[swinf_no].vldclr), TIMEOUT_WAIT_IDLE); 120 if (ret != 0) { 121 ERROR("[PWRAP] fsm_idle fail\n"); 122 goto end; 123 } 124 125 /* Set the write data */ 126 if (write == 1) { 127 if (pmifid == 0) 128 mmio_write_32((uintptr_t)(&mtk_pwrap->wacs[swinf_no].wdata), wdata); 129 } 130 131 /* Send the command */ 132 if (pmifid == 0) 133 mmio_write_32((uintptr_t)(&mtk_pwrap->wacs[swinf_no].cmd), 134 (cmd << 30) | (write << 29) | (slvid << 24) | (bytecnt << 16) | addr); 135 136 if (write == 0) { 137 if (rdata == NULL) { 138 ERROR("[PWRAP] rdata null\n"); 139 ret = -E_PWR_INVALID_ARG; 140 goto end; 141 } 142 143 /* Wait for Software Interface FSM to be WFVLDCLR */ 144 /* read the data and clear the valid flag */ 145 ret = pwrap_check_vldclr((uintptr_t)(&mtk_pwrap->wacs[swinf_no].sta), TIMEOUT_READ); 146 if (ret != 0) { 147 ERROR("[PWRAP] fsm_vldclr fail\n"); 148 goto end; 149 } 150 151 if (pmifid == 0) { 152 *rdata = mmio_read_32((uintptr_t)(&mtk_pwrap->wacs[swinf_no].rdata)); 153 mmio_write_32((uintptr_t)(&mtk_pwrap->wacs[swinf_no].vldclr), 0x1); 154 } 155 } 156 157 end: 158 spin_unlock(&wrp_lock); 159 if (ret < 0) 160 ERROR("%s fail, ret=%d\n", __func__, ret); 161 return ret; 162 } 163 164 /* external API for pmic_wrap user */ 165 166 int32_t pwrap_read(uint32_t adr, uint32_t *rdata) 167 { 168 return pwrap_swinf_acc(PMIF_SPI_SWINF_NO, DEFAULT_CMD, 0, PMIF_SPI_PMIFID, 169 DEFAULT_SLVID, adr, DEFAULT_BYTECNT, 0x0, rdata); 170 } 171 172 int32_t pwrap_write(uint32_t adr, uint32_t wdata) 173 { 174 return pwrap_swinf_acc(PMIF_SPI_SWINF_NO, DEFAULT_CMD, 1, PMIF_SPI_PMIFID, 175 DEFAULT_SLVID, adr, DEFAULT_BYTECNT, wdata, 0x0); 176 } 177 178 int32_t pwrap_read_field(uint32_t reg, uint32_t *val, uint32_t mask, uint32_t shift) 179 { 180 uint32_t rdata; 181 int32_t ret; 182 183 if (!val) 184 return -E_PWR_INVALID_ARG; 185 ret = pwrap_read(reg, &rdata); 186 if (ret == 0x0) 187 *val = (rdata >> shift) & mask; 188 189 return ret; 190 } 191 192 int32_t pwrap_write_field(uint32_t reg, uint32_t val, uint32_t mask, uint32_t shift) 193 { 194 uint32_t data; 195 int32_t ret; 196 197 ret = pwrap_read(reg, &data); 198 if (ret != 0) 199 return ret; 200 201 data = data & ~(mask << shift); 202 data |= (val << shift); 203 ret = pwrap_write(reg, data); 204 205 return ret; 206 } 207 208 #if PWRAP_DEBUG 209 static int32_t pwrap_read_test(void) 210 { 211 uint32_t rdata = 0; 212 int32_t ret; 213 214 ret = pwrap_read(DEW_READ_TEST, &rdata); 215 if (rdata != DEFAULT_VALUE_READ_TEST) { 216 ERROR("[PWRAP] Read fail,rdata=0x%x,exp=0x5aa5,ret=0x%x\n", rdata, ret); 217 return -E_PWR_READ_TEST_FAIL; 218 } 219 INFO("[PWRAP] Read Test pass,ret=%x\n", ret); 220 return 0; 221 } 222 223 static int32_t pwrap_write_test(void) 224 { 225 uint32_t rdata = 0; 226 int32_t ret; 227 int32_t ret1; 228 229 ret = pwrap_write(DEW_WRITE_TEST, PWRAP_WRITE_TEST_VALUE); 230 ret1 = pwrap_read(DEW_WRITE_TEST, &rdata); 231 if ((rdata != PWRAP_WRITE_TEST_VALUE) || (ret != 0) || (ret1 != 0)) { 232 ERROR("[PWRAP] Write fail,rdata=0x%x,exp=0xa55a,ret=0x%x,ret1=0x%x\n", 233 rdata, ret, ret1); 234 return -E_PWR_WRITE_TEST_FAIL; 235 } 236 INFO("[PWRAP] Write Test pass\n"); 237 return 0; 238 } 239 240 int32_t pmic_wrap_test(void) 241 { 242 int32_t ret; 243 244 INFO("[PWRAP] Read/Write Test start\n"); 245 246 ret = pwrap_read_test(); 247 if (ret != 0) { 248 return ret; 249 } 250 251 ret = pwrap_write_test(); 252 if (ret != 0) { 253 return ret; 254 } 255 INFO("[PWRAP] Read/Write Test done\n"); 256 257 return 0; 258 } 259 #endif 260