xref: /arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2021, 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 #include <plat/common/platform.h>
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 	/* Clear cpu's cpc sw hint */
27*91f16700Schasinglulu 	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
28*91f16700Schasinglulu }
29*91f16700Schasinglulu 
30*91f16700Schasinglulu void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
31*91f16700Schasinglulu {
32*91f16700Schasinglulu 	assert(cluster == 0U);
33*91f16700Schasinglulu 
34*91f16700Schasinglulu 	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
35*91f16700Schasinglulu }
36*91f16700Schasinglulu 
37*91f16700Schasinglulu uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
38*91f16700Schasinglulu {
39*91f16700Schasinglulu 	assert(cluster == 0U);
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
42*91f16700Schasinglulu }
43*91f16700Schasinglulu 
44*91f16700Schasinglulu void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
45*91f16700Schasinglulu {
46*91f16700Schasinglulu 	uint32_t reg;
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	assert(cluster == 0U);
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 	reg = per_cluster(cluster, MCUCFG_INITARCH);
51*91f16700Schasinglulu 
52*91f16700Schasinglulu 	if (arm64) {
53*91f16700Schasinglulu 		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
54*91f16700Schasinglulu 	} else {
55*91f16700Schasinglulu 		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
56*91f16700Schasinglulu 	}
57*91f16700Schasinglulu }
58*91f16700Schasinglulu 
59*91f16700Schasinglulu /*
60*91f16700Schasinglulu  * Return subsystem's power state.
61*91f16700Schasinglulu  *
62*91f16700Schasinglulu  * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
63*91f16700Schasinglulu  *        of one subsystem.
64*91f16700Schasinglulu  * RETURNS:
65*91f16700Schasinglulu  * 0 (the subsys was powered off)
66*91f16700Schasinglulu  * 1 (the subsys was powered on)
67*91f16700Schasinglulu  */
68*91f16700Schasinglulu bool spm_get_powerstate(uint32_t mask)
69*91f16700Schasinglulu {
70*91f16700Schasinglulu 	return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask);
71*91f16700Schasinglulu }
72*91f16700Schasinglulu 
73*91f16700Schasinglulu bool spm_get_cluster_powerstate(unsigned int cluster)
74*91f16700Schasinglulu {
75*91f16700Schasinglulu 	assert(cluster == 0U);
76*91f16700Schasinglulu 
77*91f16700Schasinglulu 	return spm_get_powerstate(MP0_CPUTOP);
78*91f16700Schasinglulu }
79*91f16700Schasinglulu 
80*91f16700Schasinglulu bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
81*91f16700Schasinglulu {
82*91f16700Schasinglulu 	uint32_t mask = BIT(cpu);
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	assert(cluster == 0U);
85*91f16700Schasinglulu 
86*91f16700Schasinglulu 	return spm_get_powerstate(mask);
87*91f16700Schasinglulu }
88*91f16700Schasinglulu 
89*91f16700Schasinglulu int spmc_init(void)
90*91f16700Schasinglulu {
91*91f16700Schasinglulu 	unsigned int cpu = plat_my_core_pos();
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 
94*91f16700Schasinglulu 	INFO("SPM: enable CPC mode\n");
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
97*91f16700Schasinglulu 
98*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
99*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
100*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
101*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
102*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
103*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
104*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
105*91f16700Schasinglulu 
106*91f16700Schasinglulu 	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
107*91f16700Schasinglulu 	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
108*91f16700Schasinglulu 	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
109*91f16700Schasinglulu 
110*91f16700Schasinglulu 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 	/* Clear bootup cpu's cpc sw hint */
113*91f16700Schasinglulu 	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	return 0;
116*91f16700Schasinglulu }
117*91f16700Schasinglulu 
118*91f16700Schasinglulu /*
119*91f16700Schasinglulu  * Power on a core with specified cluster and core index
120*91f16700Schasinglulu  *
121*91f16700Schasinglulu  * @cluster: the cluster ID of the CPU which to be powered on
122*91f16700Schasinglulu  * @cpu: the CPU ID of the CPU which to be powered on
123*91f16700Schasinglulu  */
124*91f16700Schasinglulu void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
125*91f16700Schasinglulu {
126*91f16700Schasinglulu 	/* info CPC that CPU hotplug on */
127*91f16700Schasinglulu 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
128*91f16700Schasinglulu 
129*91f16700Schasinglulu 	/* Set mp0_spmc_pwr_on_cpuX = 1 */
130*91f16700Schasinglulu 	mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	/* wait for power on ack */
133*91f16700Schasinglulu 	while (!spm_get_cpu_powerstate(cluster, cpu))
134*91f16700Schasinglulu 		;
135*91f16700Schasinglulu 
136*91f16700Schasinglulu 	/* info CPC that CPU hotplug off */
137*91f16700Schasinglulu 	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
138*91f16700Schasinglulu }
139*91f16700Schasinglulu 
140*91f16700Schasinglulu /*
141*91f16700Schasinglulu  * Power off a core with specified cluster and core index
142*91f16700Schasinglulu  *
143*91f16700Schasinglulu  * @cluster: the cluster ID of the CPU which to be powered off
144*91f16700Schasinglulu  * @cpu: the CPU ID of the CPU which to be powered off
145*91f16700Schasinglulu  */
146*91f16700Schasinglulu void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
147*91f16700Schasinglulu {
148*91f16700Schasinglulu 	/* Set mp0_spmc_pwr_on_cpuX = 0 */
149*91f16700Schasinglulu 	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
150*91f16700Schasinglulu }
151*91f16700Schasinglulu 
152*91f16700Schasinglulu /*
153*91f16700Schasinglulu  * Power off a cluster with specified index
154*91f16700Schasinglulu  *
155*91f16700Schasinglulu  * @cluster: the cluster index which to be powered off
156*91f16700Schasinglulu  */
157*91f16700Schasinglulu void spm_poweroff_cluster(unsigned int cluster)
158*91f16700Schasinglulu {
159*91f16700Schasinglulu 	/* No need to power on/off cluster on single cluster platform */
160*91f16700Schasinglulu 	assert(false);
161*91f16700Schasinglulu }
162*91f16700Schasinglulu 
163*91f16700Schasinglulu /*
164*91f16700Schasinglulu  * Power on a cluster with specified index
165*91f16700Schasinglulu  *
166*91f16700Schasinglulu  * @cluster: the cluster index which to be powered on
167*91f16700Schasinglulu  */
168*91f16700Schasinglulu void spm_poweron_cluster(unsigned int cluster)
169*91f16700Schasinglulu {
170*91f16700Schasinglulu 	/* No need to power on/off cluster on single cluster platform */
171*91f16700Schasinglulu 	assert(false);
172*91f16700Schasinglulu }
173