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