xref: /arm-trusted-firmware/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2020-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 
11*91f16700Schasinglulu #include "platform_def.h"
12*91f16700Schasinglulu #include "pmic_wrap_init.h"
13*91f16700Schasinglulu 
14*91f16700Schasinglulu /* pmic wrap module wait_idle and read polling interval (in microseconds) */
15*91f16700Schasinglulu enum pwrap_polling_interval {
16*91f16700Schasinglulu 	WAIT_IDLE_POLLING_DELAY_US	= 1,
17*91f16700Schasinglulu 	READ_POLLING_DELAY_US		= 2
18*91f16700Schasinglulu };
19*91f16700Schasinglulu 
20*91f16700Schasinglulu static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
21*91f16700Schasinglulu {
22*91f16700Schasinglulu 	uint32_t reg_rdata = 0U, retry;
23*91f16700Schasinglulu 
24*91f16700Schasinglulu 	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
25*91f16700Schasinglulu 		WAIT_IDLE_POLLING_DELAY_US;
26*91f16700Schasinglulu 	while (retry != 0) {
27*91f16700Schasinglulu 		udelay(WAIT_IDLE_POLLING_DELAY_US);
28*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
29*91f16700Schasinglulu 		/* if last read command timeout,clear vldclr bit
30*91f16700Schasinglulu 		 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
31*91f16700Schasinglulu 		 * write:FSM_REQ-->idle
32*91f16700Schasinglulu 		 */
33*91f16700Schasinglulu 		switch (GET_WACS_FSM(reg_rdata)) {
34*91f16700Schasinglulu 		case SWINF_FSM_WFVLDCLR:
35*91f16700Schasinglulu 			mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
36*91f16700Schasinglulu 			INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n");
37*91f16700Schasinglulu 			break;
38*91f16700Schasinglulu 		case SWINF_FSM_WFDLE:
39*91f16700Schasinglulu 			INFO("WACS_FSM = SWINF_FSM_WFDLE\n");
40*91f16700Schasinglulu 			break;
41*91f16700Schasinglulu 		case SWINF_FSM_REQ:
42*91f16700Schasinglulu 			INFO("WACS_FSM = SWINF_FSM_REQ\n");
43*91f16700Schasinglulu 			break;
44*91f16700Schasinglulu 		case SWINF_FSM_IDLE:
45*91f16700Schasinglulu 			goto done;
46*91f16700Schasinglulu 		default:
47*91f16700Schasinglulu 			break;
48*91f16700Schasinglulu 		}
49*91f16700Schasinglulu 		retry--;
50*91f16700Schasinglulu 	};
51*91f16700Schasinglulu 
52*91f16700Schasinglulu done:
53*91f16700Schasinglulu 	if (retry == 0) {
54*91f16700Schasinglulu 		/* timeout */
55*91f16700Schasinglulu 		return E_PWR_WAIT_IDLE_TIMEOUT;
56*91f16700Schasinglulu 	}
57*91f16700Schasinglulu 
58*91f16700Schasinglulu 	return 0U;
59*91f16700Schasinglulu }
60*91f16700Schasinglulu 
61*91f16700Schasinglulu static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
62*91f16700Schasinglulu {
63*91f16700Schasinglulu 	uint32_t reg_rdata = 0U, retry;
64*91f16700Schasinglulu 
65*91f16700Schasinglulu 	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
66*91f16700Schasinglulu 	while (retry != 0) {
67*91f16700Schasinglulu 		udelay(READ_POLLING_DELAY_US);
68*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
69*91f16700Schasinglulu 		if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
70*91f16700Schasinglulu 			break;
71*91f16700Schasinglulu 		}
72*91f16700Schasinglulu 		retry--;
73*91f16700Schasinglulu 	};
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	if (retry == 0) {
76*91f16700Schasinglulu 		/* timeout */
77*91f16700Schasinglulu 		return E_PWR_WAIT_IDLE_TIMEOUT;
78*91f16700Schasinglulu 	}
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	return 0U;
81*91f16700Schasinglulu }
82*91f16700Schasinglulu 
83*91f16700Schasinglulu static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
84*91f16700Schasinglulu 			   uint32_t *rdata, uint32_t init_check)
85*91f16700Schasinglulu {
86*91f16700Schasinglulu 	uint32_t reg_rdata, return_value;
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	if (init_check != 0) {
89*91f16700Schasinglulu 		if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
90*91f16700Schasinglulu 			ERROR("initialization isn't finished\n");
91*91f16700Schasinglulu 			return E_PWR_NOT_INIT_DONE;
92*91f16700Schasinglulu 		}
93*91f16700Schasinglulu 	}
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 	/* Wait for Software Interface FSM state to be IDLE. */
96*91f16700Schasinglulu 	return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
97*91f16700Schasinglulu 					PWRAP_WAIT_IDLE_US);
98*91f16700Schasinglulu 	if (return_value != 0) {
99*91f16700Schasinglulu 		return return_value;
100*91f16700Schasinglulu 	}
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	/* Set the write data */
103*91f16700Schasinglulu 	if (write == 1) {
104*91f16700Schasinglulu 		/* Set the write data. */
105*91f16700Schasinglulu 		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
106*91f16700Schasinglulu 	}
107*91f16700Schasinglulu 
108*91f16700Schasinglulu 	/* Send the command. */
109*91f16700Schasinglulu 	mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
110*91f16700Schasinglulu 
111*91f16700Schasinglulu 	if (write == 0) {
112*91f16700Schasinglulu 		/*
113*91f16700Schasinglulu 		 * Wait for Software Interface FSM state to be WFVLDCLR,
114*91f16700Schasinglulu 		 * read the data and clear the valid flag.
115*91f16700Schasinglulu 		 */
116*91f16700Schasinglulu 		return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
117*91f16700Schasinglulu 						  PWRAP_READ_US);
118*91f16700Schasinglulu 		if (return_value != 0) {
119*91f16700Schasinglulu 			return return_value;
120*91f16700Schasinglulu 		}
121*91f16700Schasinglulu 
122*91f16700Schasinglulu 		if (rdata == NULL) {
123*91f16700Schasinglulu 			return E_PWR_INVALID_ARG;
124*91f16700Schasinglulu 		}
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 		reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
127*91f16700Schasinglulu 		*rdata = reg_rdata;
128*91f16700Schasinglulu 		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
129*91f16700Schasinglulu 	}
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	return return_value;
132*91f16700Schasinglulu }
133*91f16700Schasinglulu 
134*91f16700Schasinglulu /* external API for pmic_wrap user */
135*91f16700Schasinglulu int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
136*91f16700Schasinglulu {
137*91f16700Schasinglulu 	return pwrap_wacs2(0, adr, 0, rdata, 1);
138*91f16700Schasinglulu }
139*91f16700Schasinglulu 
140*91f16700Schasinglulu int32_t pwrap_write(uint32_t adr, uint32_t wdata)
141*91f16700Schasinglulu {
142*91f16700Schasinglulu 	return pwrap_wacs2(1, adr, wdata, 0, 1);
143*91f16700Schasinglulu }
144