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