1 /*
2  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <common/debug.h>
8 #include <drivers/delay_timer.h>
9 #include <lib/mmio.h>
10 
11 #include <mt8173_def.h>
12 #include <mtcmos.h>
13 #include <spm.h>
14 #include <spm_mcdi.h>
15 
16 enum {
17 	SRAM_ISOINT_B	= 1U << 6,
18 	SRAM_CKISO	= 1U << 5,
19 	PWR_CLK_DIS	= 1U << 4,
20 	PWR_ON_2ND	= 1U << 3,
21 	PWR_ON		= 1U << 2,
22 	PWR_ISO		= 1U << 1,
23 	PWR_RST_B	= 1U << 0
24 };
25 
26 enum {
27 	L1_PDN_ACK	= 1U << 8,
28 	L1_PDN		= 1U << 0
29 };
30 
31 enum {
32 	LITTLE_CPU3	= 1U << 12,
33 	LITTLE_CPU2	= 1U << 11,
34 	LITTLE_CPU1	= 1U << 10,
35 };
36 
37 enum {
38 	SRAM_PDN           = 0xf << 8,
39 	DIS_SRAM_ACK       = 0x1 << 12,
40 	AUD_SRAM_ACK       = 0xf << 12,
41 };
42 
43 enum {
44 	DIS_PWR_STA_MASK   = 0x1 << 3,
45 	AUD_PWR_STA_MASK   = 0x1 << 24,
46 };
47 
48 #define SPM_VDE_PWR_CON				0x0210
49 #define SPM_MFG_PWR_CON				0x0214
50 #define SPM_VEN_PWR_CON				0x0230
51 #define SPM_ISP_PWR_CON				0x0238
52 #define SPM_DIS_PWR_CON				0x023c
53 #define SPM_VEN2_PWR_CON			0x0298
54 #define SPM_AUDIO_PWR_CON			0x029c
55 #define SPM_MFG_2D_PWR_CON			0x02c0
56 #define SPM_MFG_ASYNC_PWR_CON			0x02c4
57 #define SPM_USB_PWR_CON				0x02cc
58 
59 #define MTCMOS_CTRL_SUCCESS			0
60 #define MTCMOS_CTRL_ERROR			-1
61 
62 #define MTCMOS_CTRL_EN				(0x1 << 18)
63 
64 #define VDE_PWR_ON				0
65 #define VEN_PWR_ON				1
66 #define ISP_PWR_ON				2
67 #define DIS_PWR_ON				3
68 #define VEN2_PWR_ON				4
69 #define AUDIO_PWR_ON				5
70 #define MFG_ASYNC_PWR_ON			6
71 #define MFG_2D_PWR_ON				7
72 #define MFG_PWR_ON				8
73 #define USB_PWR_ON				9
74 
75 #define VDE_PWR_OFF				10
76 #define VEN_PWR_OFF				11
77 #define ISP_PWR_OFF				12
78 #define DIS_PWR_OFF				13
79 #define VEN2_PWR_OFF				14
80 #define AUDIO_PWR_OFF				15
81 #define MFG_ASYNC_PWR_OFF			16
82 #define MFG_2D_PWR_OFF				17
83 #define MFG_PWR_OFF				18
84 #define USB_PWR_OFF				19
85 
86 #define VDE_PWR_CON_PWR_STA			7
87 #define VEN_PWR_CON_PWR_STA			21
88 #define ISP_PWR_CON_PWR_STA			5
89 #define DIS_PWR_CON_PWR_STA			3
90 #define VEN2_PWR_CON_PWR_STA			20
91 #define AUDIO_PWR_CON_PWR_STA			24
92 #define MFG_ASYNC_PWR_CON_PWR_STA		23
93 #define MFG_2D_PWR_CON_PWR_STA			22
94 #define MFG_PWR_CON_PWR_STA			4
95 #define USB_PWR_CON_PWR_STA			25
96 
97 /*
98  * Timeout if the ack is not signled after 1 second.
99  * According to designer, one mtcmos operation should be done
100  * around 10us.
101  */
102 #define MTCMOS_ACK_POLLING_MAX_COUNT			10000
103 #define MTCMOS_ACK_POLLING_INTERVAL			10
104 
mtcmos_ctrl_little_off(unsigned int linear_id)105 static void mtcmos_ctrl_little_off(unsigned int linear_id)
106 {
107 	uint32_t reg_pwr_con;
108 	uint32_t reg_l1_pdn;
109 	uint32_t bit_cpu;
110 
111 	switch (linear_id) {
112 	case 1:
113 		reg_pwr_con = SPM_CA7_CPU1_PWR_CON;
114 		reg_l1_pdn = SPM_CA7_CPU1_L1_PDN;
115 		bit_cpu = LITTLE_CPU1;
116 		break;
117 	case 2:
118 		reg_pwr_con = SPM_CA7_CPU2_PWR_CON;
119 		reg_l1_pdn = SPM_CA7_CPU2_L1_PDN;
120 		bit_cpu = LITTLE_CPU2;
121 		break;
122 	case 3:
123 		reg_pwr_con = SPM_CA7_CPU3_PWR_CON;
124 		reg_l1_pdn = SPM_CA7_CPU3_L1_PDN;
125 		bit_cpu = LITTLE_CPU3;
126 		break;
127 	default:
128 		/* should never come to here */
129 		return;
130 	}
131 
132 	/* enable register control */
133 	mmio_write_32(SPM_POWERON_CONFIG_SET,
134 			(SPM_PROJECT_CODE << 16) | (1U << 0));
135 
136 	mmio_setbits_32(reg_pwr_con, PWR_ISO);
137 	mmio_setbits_32(reg_pwr_con, SRAM_CKISO);
138 	mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B);
139 	mmio_setbits_32(reg_l1_pdn, L1_PDN);
140 
141 	while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK))
142 		continue;
143 
144 	mmio_clrbits_32(reg_pwr_con, PWR_RST_B);
145 	mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS);
146 	mmio_clrbits_32(reg_pwr_con, PWR_ON);
147 	mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND);
148 
149 	while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) ||
150 	       (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu))
151 		continue;
152 }
153 
mtcmos_little_cpu_off(void)154 void mtcmos_little_cpu_off(void)
155 {
156 	/* turn off little cpu 1 - 3 */
157 	mtcmos_ctrl_little_off(1);
158 	mtcmos_ctrl_little_off(2);
159 	mtcmos_ctrl_little_off(3);
160 }
161 
wait_mtcmos_ack(uint32_t on,uint32_t pwr_ctrl,uint32_t spm_pwr_sta)162 uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta)
163 {
164 	int i = 0;
165 	uint32_t cmp, pwr_sta, pwr_sta_2nd;
166 
167 	while (1) {
168 		cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl;
169 		pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1;
170 		pwr_sta_2nd =
171 			(mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1;
172 		if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) {
173 			mmio_write_32(SPM_PCM_RESERVE2, 0);
174 			return MTCMOS_CTRL_SUCCESS;
175 		}
176 		udelay(MTCMOS_ACK_POLLING_INTERVAL);
177 		i++;
178 		if (i > MTCMOS_ACK_POLLING_MAX_COUNT) {
179 			INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n"
180 				"SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n"
181 				"SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n"
182 				"SPM_PCM_PASR_DPD_3 = 0x%x\n",
183 				on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE),
184 				mmio_read_32(SPM_PCM_RESERVE2),
185 				mmio_read_32(SPM_PWR_STATUS),
186 				mmio_read_32(SPM_PWR_STATUS_2ND),
187 				mmio_read_32(SPM_PCM_PASR_DPD_3));
188 			mmio_write_32(SPM_PCM_RESERVE2, 0);
189 			return MTCMOS_CTRL_ERROR;
190 		}
191 	}
192 }
193 
mtcmos_non_cpu_ctrl(uint32_t on,uint32_t mtcmos_num)194 uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num)
195 {
196 	uint32_t ret = MTCMOS_CTRL_SUCCESS;
197 	uint32_t power_on;
198 	uint32_t power_off;
199 	uint32_t power_ctrl;
200 	uint32_t power_status;
201 
202 	spm_lock_get();
203 	spm_mcdi_prepare_for_mtcmos();
204 	mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN);
205 
206 	switch (mtcmos_num) {
207 	case SPM_VDE_PWR_CON:
208 		power_on = VDE_PWR_ON;
209 		power_off = VDE_PWR_OFF;
210 		power_status = VDE_PWR_CON_PWR_STA;
211 		break;
212 	case SPM_MFG_PWR_CON:
213 		power_on = MFG_PWR_ON;
214 		power_off = MFG_PWR_OFF;
215 		power_status = MFG_PWR_CON_PWR_STA;
216 		break;
217 	case SPM_VEN_PWR_CON:
218 		power_on = VEN_PWR_ON;
219 		power_off = VEN_PWR_OFF;
220 		power_status = VEN_PWR_CON_PWR_STA;
221 		break;
222 	case SPM_ISP_PWR_CON:
223 		power_on = ISP_PWR_ON;
224 		power_off = ISP_PWR_OFF;
225 		power_status = ISP_PWR_CON_PWR_STA;
226 		break;
227 	case SPM_DIS_PWR_CON:
228 		power_on = DIS_PWR_ON;
229 		power_off = DIS_PWR_OFF;
230 		power_status = DIS_PWR_CON_PWR_STA;
231 		break;
232 	case SPM_VEN2_PWR_CON:
233 		power_on = VEN2_PWR_ON;
234 		power_off = VEN2_PWR_OFF;
235 		power_status = VEN2_PWR_CON_PWR_STA;
236 		break;
237 	case SPM_AUDIO_PWR_CON:
238 		power_on = AUDIO_PWR_ON;
239 		power_off = AUDIO_PWR_OFF;
240 		power_status = AUDIO_PWR_CON_PWR_STA;
241 		break;
242 	case SPM_MFG_2D_PWR_CON:
243 		power_on = MFG_2D_PWR_ON;
244 		power_off = MFG_2D_PWR_OFF;
245 		power_status = MFG_2D_PWR_CON_PWR_STA;
246 		break;
247 	case SPM_MFG_ASYNC_PWR_CON:
248 		power_on = MFG_ASYNC_PWR_ON;
249 		power_off = MFG_ASYNC_PWR_OFF;
250 		power_status = MFG_ASYNC_PWR_CON_PWR_STA;
251 		break;
252 	case SPM_USB_PWR_CON:
253 		power_on = USB_PWR_ON;
254 		power_off = USB_PWR_OFF;
255 		power_status = USB_PWR_CON_PWR_STA;
256 		break;
257 	default:
258 		ret = MTCMOS_CTRL_ERROR;
259 		INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret);
260 		break;
261 	}
262 	if (ret == MTCMOS_CTRL_SUCCESS) {
263 		power_ctrl = on ? (1 << power_on) : (1 << power_off);
264 		mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl);
265 		ret = wait_mtcmos_ack(on, power_ctrl, power_status);
266 		VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n",
267 			power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret);
268 	}
269 
270 	mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN);
271 	spm_lock_release();
272 
273 	return ret;
274 }
275