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
pwrap_check_idle(uintptr_t wacs_register,uintptr_t wacs_vldclr_register,uint32_t timeout_us)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
pwrap_check_vldclr(uintptr_t wacs_register,uint32_t timeout_us)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
pwrap_swinf_acc(uint32_t swinf_no,uint32_t cmd,uint32_t write,uint32_t pmifid,uint32_t slvid,uint32_t addr,uint32_t bytecnt,uint32_t wdata,uint32_t * rdata)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
pwrap_read(uint32_t adr,uint32_t * rdata)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
pwrap_write(uint32_t adr,uint32_t wdata)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
pwrap_read_field(uint32_t reg,uint32_t * val,uint32_t mask,uint32_t shift)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
pwrap_write_field(uint32_t reg,uint32_t val,uint32_t mask,uint32_t shift)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
pwrap_read_test(void)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
pwrap_write_test(void)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
pmic_wrap_test(void)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