xref: /arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2020, MediaTek Inc. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <common/debug.h>
10*91f16700Schasinglulu #include <drivers/delay_timer.h>
11*91f16700Schasinglulu #include <lib/mmio.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <mcucfg.h>
14*91f16700Schasinglulu #include <mtspmc.h>
15*91f16700Schasinglulu #include <mtspmc_private.h>
16*91f16700Schasinglulu 
17*91f16700Schasinglulu 
18*91f16700Schasinglulu void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
19*91f16700Schasinglulu {
20*91f16700Schasinglulu 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
21*91f16700Schasinglulu }
22*91f16700Schasinglulu 
23*91f16700Schasinglulu void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
24*91f16700Schasinglulu {
25*91f16700Schasinglulu 	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
26*91f16700Schasinglulu }
27*91f16700Schasinglulu 
28*91f16700Schasinglulu void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
29*91f16700Schasinglulu {
30*91f16700Schasinglulu 	assert(cluster == 0U);
31*91f16700Schasinglulu 
32*91f16700Schasinglulu 	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
33*91f16700Schasinglulu }
34*91f16700Schasinglulu 
35*91f16700Schasinglulu uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
36*91f16700Schasinglulu {
37*91f16700Schasinglulu 	assert(cluster == 0U);
38*91f16700Schasinglulu 
39*91f16700Schasinglulu 	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
40*91f16700Schasinglulu }
41*91f16700Schasinglulu 
42*91f16700Schasinglulu void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
43*91f16700Schasinglulu {
44*91f16700Schasinglulu 	uint32_t reg;
45*91f16700Schasinglulu 
46*91f16700Schasinglulu 	assert(cluster == 0U);
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	reg = per_cluster(cluster, MCUCFG_INITARCH);
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 	if (arm64) {
51*91f16700Schasinglulu 		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
52*91f16700Schasinglulu 	} else {
53*91f16700Schasinglulu 		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
54*91f16700Schasinglulu 	}
55*91f16700Schasinglulu }
56*91f16700Schasinglulu 
57*91f16700Schasinglulu /**
58*91f16700Schasinglulu  * Return subsystem's power state.
59*91f16700Schasinglulu  *
60*91f16700Schasinglulu  * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state
61*91f16700Schasinglulu  *        of one subsystem.
62*91f16700Schasinglulu  * RETURNS:
63*91f16700Schasinglulu  * 0 (the subsys was powered off)
64*91f16700Schasinglulu  * 1 (the subsys was powered on)
65*91f16700Schasinglulu  */
66*91f16700Schasinglulu bool spm_get_powerstate(uint32_t mask)
67*91f16700Schasinglulu {
68*91f16700Schasinglulu 	return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U;
69*91f16700Schasinglulu }
70*91f16700Schasinglulu 
71*91f16700Schasinglulu bool spm_get_cluster_powerstate(unsigned int cluster)
72*91f16700Schasinglulu {
73*91f16700Schasinglulu 	assert(cluster == 0U);
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	return spm_get_powerstate(BIT(14));
76*91f16700Schasinglulu }
77*91f16700Schasinglulu 
78*91f16700Schasinglulu bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
79*91f16700Schasinglulu {
80*91f16700Schasinglulu 	uint32_t mask = BIT(cpu);
81*91f16700Schasinglulu 
82*91f16700Schasinglulu 	assert(cluster == 0U);
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	return spm_get_powerstate(mask);
85*91f16700Schasinglulu }
86*91f16700Schasinglulu 
87*91f16700Schasinglulu int spmc_init(void)
88*91f16700Schasinglulu {
89*91f16700Schasinglulu 	INFO("SPM: enable CPC mode\n");
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
94*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
95*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
96*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
97*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
98*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
99*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
100*91f16700Schasinglulu 
101*91f16700Schasinglulu 	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
102*91f16700Schasinglulu 	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
103*91f16700Schasinglulu 	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
106*91f16700Schasinglulu 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
107*91f16700Schasinglulu 
108*91f16700Schasinglulu 	return 0;
109*91f16700Schasinglulu }
110*91f16700Schasinglulu 
111*91f16700Schasinglulu /**
112*91f16700Schasinglulu  * Power on a core with specified cluster and core index
113*91f16700Schasinglulu  *
114*91f16700Schasinglulu  * @cluster: the cluster ID of the CPU which to be powered on
115*91f16700Schasinglulu  * @cpu: the CPU ID of the CPU which to be powered on
116*91f16700Schasinglulu  */
117*91f16700Schasinglulu void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
118*91f16700Schasinglulu {
119*91f16700Schasinglulu 	uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR);
120*91f16700Schasinglulu 
121*91f16700Schasinglulu 	/* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
122*91f16700Schasinglulu 	if (cpu >= 4U) {
123*91f16700Schasinglulu 		mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
124*91f16700Schasinglulu 	}
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	mmio_setbits_32(cpu_pwr_con, PWR_ON);
127*91f16700Schasinglulu 
128*91f16700Schasinglulu 	while (!spm_get_cpu_powerstate(cluster, cpu)) {
129*91f16700Schasinglulu 		mmio_clrbits_32(cpu_pwr_con, PWR_ON);
130*91f16700Schasinglulu 		mmio_setbits_32(cpu_pwr_con, PWR_ON);
131*91f16700Schasinglulu 	}
132*91f16700Schasinglulu }
133*91f16700Schasinglulu 
134*91f16700Schasinglulu /**
135*91f16700Schasinglulu  * Power off a core with specified cluster and core index
136*91f16700Schasinglulu  *
137*91f16700Schasinglulu  * @cluster: the cluster ID of the CPU which to be powered off
138*91f16700Schasinglulu  * @cpu: the CPU ID of the CPU which to be powered off
139*91f16700Schasinglulu  */
140*91f16700Schasinglulu void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
141*91f16700Schasinglulu {
142*91f16700Schasinglulu 	/* Set mp0_spmc_pwr_on_cpuX = 0 */
143*91f16700Schasinglulu 	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
144*91f16700Schasinglulu }
145*91f16700Schasinglulu 
146*91f16700Schasinglulu /**
147*91f16700Schasinglulu  * Power off a cluster with specified index
148*91f16700Schasinglulu  *
149*91f16700Schasinglulu  * @cluster: the cluster index which to be powered off
150*91f16700Schasinglulu  */
151*91f16700Schasinglulu void spm_poweroff_cluster(unsigned int cluster)
152*91f16700Schasinglulu {
153*91f16700Schasinglulu 	/* No need to power on/off cluster on single cluster platform */
154*91f16700Schasinglulu 	assert(false);
155*91f16700Schasinglulu }
156*91f16700Schasinglulu 
157*91f16700Schasinglulu /**
158*91f16700Schasinglulu  * Power on a cluster with specified index
159*91f16700Schasinglulu  *
160*91f16700Schasinglulu  * @cluster: the cluster index which to be powered on
161*91f16700Schasinglulu  */
162*91f16700Schasinglulu void spm_poweron_cluster(unsigned int cluster)
163*91f16700Schasinglulu {
164*91f16700Schasinglulu 	/* No need to power on/off cluster on single cluster platform */
165*91f16700Schasinglulu 	assert(false);
166*91f16700Schasinglulu }
167