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