xref: /rk3399_ARM-atf/plat/mediatek/mt8195/drivers/spmc/mtspmc.c (revision a92b02566e23ca73f9874555335dc6b19f0f242c)
10d82eff6SJames Liao /*
20d82eff6SJames Liao  * Copyright (c) 2020, MediaTek Inc. All rights reserved.
30d82eff6SJames Liao  *
40d82eff6SJames Liao  * SPDX-License-Identifier: BSD-3-Clause
50d82eff6SJames Liao  */
60d82eff6SJames Liao 
70d82eff6SJames Liao #include <assert.h>
80d82eff6SJames Liao 
90d82eff6SJames Liao #include <common/debug.h>
100d82eff6SJames Liao #include <drivers/delay_timer.h>
110d82eff6SJames Liao #include <lib/mmio.h>
120d82eff6SJames Liao 
130d82eff6SJames Liao #include <mcucfg.h>
140d82eff6SJames Liao #include <mtspmc.h>
150d82eff6SJames Liao #include <mtspmc_private.h>
160d82eff6SJames Liao 
170d82eff6SJames Liao 
mcucfg_disable_gic_wakeup(unsigned int cluster,unsigned int cpu)18*fe985428SJames Liao void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
190d82eff6SJames Liao {
200d82eff6SJames Liao 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
210d82eff6SJames Liao }
220d82eff6SJames Liao 
mcucfg_enable_gic_wakeup(unsigned int cluster,unsigned int cpu)23*fe985428SJames Liao void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
240d82eff6SJames Liao {
250d82eff6SJames Liao 	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
260d82eff6SJames Liao }
270d82eff6SJames Liao 
mcucfg_set_bootaddr(unsigned int cluster,unsigned int cpu,uintptr_t bootaddr)28*fe985428SJames Liao void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
290d82eff6SJames Liao {
300d82eff6SJames Liao 	assert(cluster == 0U);
310d82eff6SJames Liao 
320d82eff6SJames Liao 	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
330d82eff6SJames Liao }
340d82eff6SJames Liao 
mcucfg_get_bootaddr(unsigned int cluster,unsigned int cpu)35*fe985428SJames Liao uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
360d82eff6SJames Liao {
370d82eff6SJames Liao 	assert(cluster == 0U);
380d82eff6SJames Liao 
390d82eff6SJames Liao 	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
400d82eff6SJames Liao }
410d82eff6SJames Liao 
mcucfg_init_archstate(unsigned int cluster,unsigned int cpu,bool arm64)42*fe985428SJames Liao void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
430d82eff6SJames Liao {
440d82eff6SJames Liao 	uint32_t reg;
450d82eff6SJames Liao 
460d82eff6SJames Liao 	assert(cluster == 0U);
470d82eff6SJames Liao 
480d82eff6SJames Liao 	reg = per_cluster(cluster, MCUCFG_INITARCH);
490d82eff6SJames Liao 
500d82eff6SJames Liao 	if (arm64) {
510d82eff6SJames Liao 		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
520d82eff6SJames Liao 	} else {
530d82eff6SJames Liao 		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
540d82eff6SJames Liao 	}
550d82eff6SJames Liao }
560d82eff6SJames Liao 
570d82eff6SJames Liao /**
580d82eff6SJames Liao  * Return subsystem's power state.
590d82eff6SJames Liao  *
60*fe985428SJames Liao  * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state
610d82eff6SJames Liao  *        of one subsystem.
620d82eff6SJames Liao  * RETURNS:
630d82eff6SJames Liao  * 0 (the subsys was powered off)
640d82eff6SJames Liao  * 1 (the subsys was powered on)
650d82eff6SJames Liao  */
spm_get_powerstate(uint32_t mask)660d82eff6SJames Liao bool spm_get_powerstate(uint32_t mask)
670d82eff6SJames Liao {
68*fe985428SJames Liao 	return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U;
690d82eff6SJames Liao }
700d82eff6SJames Liao 
spm_get_cluster_powerstate(unsigned int cluster)71*fe985428SJames Liao bool spm_get_cluster_powerstate(unsigned int cluster)
720d82eff6SJames Liao {
730d82eff6SJames Liao 	assert(cluster == 0U);
740d82eff6SJames Liao 
75*fe985428SJames Liao 	return spm_get_powerstate(BIT(14));
760d82eff6SJames Liao }
770d82eff6SJames Liao 
spm_get_cpu_powerstate(unsigned int cluster,unsigned int cpu)78*fe985428SJames Liao bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
790d82eff6SJames Liao {
800d82eff6SJames Liao 	uint32_t mask = BIT(cpu);
810d82eff6SJames Liao 
820d82eff6SJames Liao 	assert(cluster == 0U);
830d82eff6SJames Liao 
840d82eff6SJames Liao 	return spm_get_powerstate(mask);
850d82eff6SJames Liao }
860d82eff6SJames Liao 
spmc_init(void)870d82eff6SJames Liao int spmc_init(void)
880d82eff6SJames Liao {
890d82eff6SJames Liao 	INFO("SPM: enable CPC mode\n");
900d82eff6SJames Liao 
910d82eff6SJames Liao 	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
920d82eff6SJames Liao 
930d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
940d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
950d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
960d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
970d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
980d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
990d82eff6SJames Liao 	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
1000d82eff6SJames Liao 
1010d82eff6SJames Liao 	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
1020d82eff6SJames Liao 	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
1030d82eff6SJames Liao 	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
1040d82eff6SJames Liao 
1050d82eff6SJames Liao 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
106*fe985428SJames Liao 	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
1070d82eff6SJames Liao 
1080d82eff6SJames Liao 	return 0;
1090d82eff6SJames Liao }
1100d82eff6SJames Liao 
1110d82eff6SJames Liao /**
1120d82eff6SJames Liao  * Power on a core with specified cluster and core index
1130d82eff6SJames Liao  *
1140d82eff6SJames Liao  * @cluster: the cluster ID of the CPU which to be powered on
1150d82eff6SJames Liao  * @cpu: the CPU ID of the CPU which to be powered on
1160d82eff6SJames Liao  */
spm_poweron_cpu(unsigned int cluster,unsigned int cpu)117*fe985428SJames Liao void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
1180d82eff6SJames Liao {
119*fe985428SJames Liao 	uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR);
120*fe985428SJames Liao 
1210d82eff6SJames Liao 	/* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
1220d82eff6SJames Liao 	if (cpu >= 4U) {
1230d82eff6SJames Liao 		mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
1240d82eff6SJames Liao 	}
1250d82eff6SJames Liao 
126*fe985428SJames Liao 	mmio_setbits_32(cpu_pwr_con, PWR_ON);
1270d82eff6SJames Liao 
1280d82eff6SJames Liao 	while (!spm_get_cpu_powerstate(cluster, cpu)) {
129*fe985428SJames Liao 		mmio_clrbits_32(cpu_pwr_con, PWR_ON);
130*fe985428SJames Liao 		mmio_setbits_32(cpu_pwr_con, PWR_ON);
1310d82eff6SJames Liao 	}
1320d82eff6SJames Liao }
1330d82eff6SJames Liao 
1340d82eff6SJames Liao /**
1350d82eff6SJames Liao  * Power off a core with specified cluster and core index
1360d82eff6SJames Liao  *
1370d82eff6SJames Liao  * @cluster: the cluster ID of the CPU which to be powered off
1380d82eff6SJames Liao  * @cpu: the CPU ID of the CPU which to be powered off
1390d82eff6SJames Liao  */
spm_poweroff_cpu(unsigned int cluster,unsigned int cpu)140*fe985428SJames Liao void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
1410d82eff6SJames Liao {
1420d82eff6SJames Liao 	/* Set mp0_spmc_pwr_on_cpuX = 0 */
1430d82eff6SJames Liao 	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
1440d82eff6SJames Liao }
1450d82eff6SJames Liao 
1460d82eff6SJames Liao /**
1470d82eff6SJames Liao  * Power off a cluster with specified index
1480d82eff6SJames Liao  *
1490d82eff6SJames Liao  * @cluster: the cluster index which to be powered off
1500d82eff6SJames Liao  */
spm_poweroff_cluster(unsigned int cluster)151*fe985428SJames Liao void spm_poweroff_cluster(unsigned int cluster)
1520d82eff6SJames Liao {
1530d82eff6SJames Liao 	/* No need to power on/off cluster on single cluster platform */
1540d82eff6SJames Liao 	assert(false);
1550d82eff6SJames Liao }
1560d82eff6SJames Liao 
1570d82eff6SJames Liao /**
1580d82eff6SJames Liao  * Power on a cluster with specified index
1590d82eff6SJames Liao  *
1600d82eff6SJames Liao  * @cluster: the cluster index which to be powered on
1610d82eff6SJames Liao  */
spm_poweron_cluster(unsigned int cluster)162*fe985428SJames Liao void spm_poweron_cluster(unsigned int cluster)
1630d82eff6SJames Liao {
1640d82eff6SJames Liao 	/* No need to power on/off cluster on single cluster platform */
1650d82eff6SJames Liao 	assert(false);
1660d82eff6SJames Liao }
167