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