xref: /arm-trusted-firmware/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <common/debug.h>
8*91f16700Schasinglulu #include <drivers/delay_timer.h>
9*91f16700Schasinglulu #include <lib/mmio.h>
10*91f16700Schasinglulu #include <platform_def.h>
11*91f16700Schasinglulu #include <pmic_wrap_init.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu /* pmic wrap module wait_idle and read polling interval (in microseconds) */
14*91f16700Schasinglulu enum {
15*91f16700Schasinglulu 	WAIT_IDLE_POLLING_DELAY_US	= 1,
16*91f16700Schasinglulu 	READ_POLLING_DELAY_US		= 2
17*91f16700Schasinglulu };
18*91f16700Schasinglulu 
19*91f16700Schasinglulu static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
20*91f16700Schasinglulu 					   void *wacs_register,
21*91f16700Schasinglulu 					   void *wacs_vldclr_register,
22*91f16700Schasinglulu 					   uint32_t *read_reg)
23*91f16700Schasinglulu {
24*91f16700Schasinglulu 	uint32_t reg_rdata;
25*91f16700Schasinglulu 	uint32_t retry;
26*91f16700Schasinglulu 
27*91f16700Schasinglulu 	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
28*91f16700Schasinglulu 		WAIT_IDLE_POLLING_DELAY_US;
29*91f16700Schasinglulu 
30*91f16700Schasinglulu 	do {
31*91f16700Schasinglulu 		udelay(WAIT_IDLE_POLLING_DELAY_US);
32*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
33*91f16700Schasinglulu 		/* if last read command timeout,clear vldclr bit
34*91f16700Schasinglulu 		 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
35*91f16700Schasinglulu 		 * write:FSM_REQ-->idle
36*91f16700Schasinglulu 		 */
37*91f16700Schasinglulu 		switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
38*91f16700Schasinglulu 			RDATA_WACS_FSM_MASK)) {
39*91f16700Schasinglulu 		case WACS_FSM_WFVLDCLR:
40*91f16700Schasinglulu 			mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
41*91f16700Schasinglulu 			ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
42*91f16700Schasinglulu 			break;
43*91f16700Schasinglulu 		case WACS_FSM_WFDLE:
44*91f16700Schasinglulu 			ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
45*91f16700Schasinglulu 			break;
46*91f16700Schasinglulu 		case WACS_FSM_REQ:
47*91f16700Schasinglulu 			ERROR("WACS_FSM = WACS_FSM_REQ\n");
48*91f16700Schasinglulu 			break;
49*91f16700Schasinglulu 		case WACS_FSM_IDLE:
50*91f16700Schasinglulu 			goto done;
51*91f16700Schasinglulu 		default:
52*91f16700Schasinglulu 			break;
53*91f16700Schasinglulu 		}
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 		retry--;
56*91f16700Schasinglulu 	} while (retry);
57*91f16700Schasinglulu 
58*91f16700Schasinglulu done:
59*91f16700Schasinglulu 	if (!retry)	/* timeout */
60*91f16700Schasinglulu 		return E_PWR_WAIT_IDLE_TIMEOUT;
61*91f16700Schasinglulu 
62*91f16700Schasinglulu 	if (read_reg)
63*91f16700Schasinglulu 		*read_reg = reg_rdata;
64*91f16700Schasinglulu 	return 0;
65*91f16700Schasinglulu }
66*91f16700Schasinglulu 
67*91f16700Schasinglulu static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
68*91f16700Schasinglulu 					    void *wacs_register,
69*91f16700Schasinglulu 					    uint32_t *read_reg)
70*91f16700Schasinglulu {
71*91f16700Schasinglulu 	uint32_t reg_rdata;
72*91f16700Schasinglulu 	uint32_t retry;
73*91f16700Schasinglulu 
74*91f16700Schasinglulu 	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
75*91f16700Schasinglulu 
76*91f16700Schasinglulu 	do {
77*91f16700Schasinglulu 		udelay(READ_POLLING_DELAY_US);
78*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 		if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
81*91f16700Schasinglulu 		    == WACS_FSM_WFVLDCLR)
82*91f16700Schasinglulu 			break;
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 		retry--;
85*91f16700Schasinglulu 	} while (retry);
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	if (!retry) {	/* timeout */
88*91f16700Schasinglulu 		ERROR("timeout when waiting for idle\n");
89*91f16700Schasinglulu 		return E_PWR_WAIT_IDLE_TIMEOUT_READ;
90*91f16700Schasinglulu 	}
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	if (read_reg)
93*91f16700Schasinglulu 		*read_reg = reg_rdata;
94*91f16700Schasinglulu 	return 0;
95*91f16700Schasinglulu }
96*91f16700Schasinglulu 
97*91f16700Schasinglulu static int32_t pwrap_wacs2(uint32_t write,
98*91f16700Schasinglulu 		    uint32_t adr,
99*91f16700Schasinglulu 		    uint32_t wdata,
100*91f16700Schasinglulu 		    uint32_t *rdata,
101*91f16700Schasinglulu 		    uint32_t init_check)
102*91f16700Schasinglulu {
103*91f16700Schasinglulu 	uint32_t reg_rdata = 0;
104*91f16700Schasinglulu 	uint32_t wacs_write = 0;
105*91f16700Schasinglulu 	uint32_t wacs_adr = 0;
106*91f16700Schasinglulu 	uint32_t wacs_cmd = 0;
107*91f16700Schasinglulu 	uint32_t return_value = 0;
108*91f16700Schasinglulu 
109*91f16700Schasinglulu 	if (init_check) {
110*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
111*91f16700Schasinglulu 		/* Prevent someone to used pwrap before pwrap init */
112*91f16700Schasinglulu 		if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
113*91f16700Schasinglulu 		    RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
114*91f16700Schasinglulu 			ERROR("initialization isn't finished\n");
115*91f16700Schasinglulu 			return E_PWR_NOT_INIT_DONE;
116*91f16700Schasinglulu 		}
117*91f16700Schasinglulu 	}
118*91f16700Schasinglulu 	reg_rdata = 0;
119*91f16700Schasinglulu 	/* Check IDLE in advance */
120*91f16700Schasinglulu 	return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
121*91f16700Schasinglulu 				&mtk_pwrap->wacs2_rdata,
122*91f16700Schasinglulu 				&mtk_pwrap->wacs2_vldclr,
123*91f16700Schasinglulu 				0);
124*91f16700Schasinglulu 	if (return_value != 0) {
125*91f16700Schasinglulu 		ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
126*91f16700Schasinglulu 		goto FAIL;
127*91f16700Schasinglulu 	}
128*91f16700Schasinglulu 	wacs_write = write << 31;
129*91f16700Schasinglulu 	wacs_adr = (adr >> 1) << 16;
130*91f16700Schasinglulu 	wacs_cmd = wacs_write | wacs_adr | wdata;
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
133*91f16700Schasinglulu 	if (write == 0) {
134*91f16700Schasinglulu 		if (rdata == NULL) {
135*91f16700Schasinglulu 			ERROR("rdata is a NULL pointer\n");
136*91f16700Schasinglulu 			return_value = E_PWR_INVALID_ARG;
137*91f16700Schasinglulu 			goto FAIL;
138*91f16700Schasinglulu 		}
139*91f16700Schasinglulu 		return_value = wait_for_state_ready(TIMEOUT_READ,
140*91f16700Schasinglulu 					&mtk_pwrap->wacs2_rdata,
141*91f16700Schasinglulu 					&reg_rdata);
142*91f16700Schasinglulu 		if (return_value != 0) {
143*91f16700Schasinglulu 			ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
144*91f16700Schasinglulu 				 return_value);
145*91f16700Schasinglulu 			goto FAIL;
146*91f16700Schasinglulu 		}
147*91f16700Schasinglulu 		*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
148*91f16700Schasinglulu 			  & RDATA_WACS_RDATA_MASK);
149*91f16700Schasinglulu 		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
150*91f16700Schasinglulu 	}
151*91f16700Schasinglulu FAIL:
152*91f16700Schasinglulu 	return return_value;
153*91f16700Schasinglulu }
154*91f16700Schasinglulu 
155*91f16700Schasinglulu /* external API for pmic_wrap user */
156*91f16700Schasinglulu 
157*91f16700Schasinglulu int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
158*91f16700Schasinglulu {
159*91f16700Schasinglulu 	return pwrap_wacs2(0, adr, 0, rdata, 1);
160*91f16700Schasinglulu }
161*91f16700Schasinglulu 
162*91f16700Schasinglulu int32_t pwrap_write(uint32_t adr, uint32_t wdata)
163*91f16700Schasinglulu {
164*91f16700Schasinglulu 	return pwrap_wacs2(1, adr, wdata, 0, 1);
165*91f16700Schasinglulu }
166