xref: /rk3399_ARM-atf/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v3.c (revision 52c47c174fadb9e1398af41e9bbf290af314e8ec)
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