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 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 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 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 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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