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