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(uint32_t cluster, uint32_t 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(uint32_t cluster, uint32_t 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(uint32_t cluster, uint32_t 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(uint32_t cluster, uint32_t 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(uint32_t cluster, uint32_t 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 SPM_CPU_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(SPM_CPU_PWR_STATUS) & mask) != 0U; 69*91f16700Schasinglulu } 70*91f16700Schasinglulu 71*91f16700Schasinglulu bool spm_get_cluster_powerstate(uint32_t cluster) 72*91f16700Schasinglulu { 73*91f16700Schasinglulu assert(cluster == 0U); 74*91f16700Schasinglulu 75*91f16700Schasinglulu return spm_get_powerstate(MP0_CPUTOP); 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t 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_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1)); 102*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2)); 103*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3)); 104*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4)); 105*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5)); 106*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6)); 107*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7)); 108*91f16700Schasinglulu 109*91f16700Schasinglulu mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 110*91f16700Schasinglulu mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 111*91f16700Schasinglulu mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); 112*91f16700Schasinglulu 113*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); 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(uint32_t cluster, uint32_t cpu) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ 127*91f16700Schasinglulu if (cpu >= 4U) { 128*91f16700Schasinglulu mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); 129*91f16700Schasinglulu } 130*91f16700Schasinglulu 131*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); 132*91f16700Schasinglulu mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 133*91f16700Schasinglulu 134*91f16700Schasinglulu while (!spm_get_cpu_powerstate(cluster, cpu)) { 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* Enable Big CPU Last PC */ 140*91f16700Schasinglulu if (cpu >= 4U) { 141*91f16700Schasinglulu mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3)); 142*91f16700Schasinglulu } 143*91f16700Schasinglulu } 144*91f16700Schasinglulu 145*91f16700Schasinglulu /** 146*91f16700Schasinglulu * Power off a core with specified cluster and core index 147*91f16700Schasinglulu * 148*91f16700Schasinglulu * @cluster: the cluster ID of the CPU which to be powered off 149*91f16700Schasinglulu * @cpu: the CPU ID of the CPU which to be powered off 150*91f16700Schasinglulu */ 151*91f16700Schasinglulu void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu) 152*91f16700Schasinglulu { 153*91f16700Schasinglulu /* Set mp0_spmc_pwr_on_cpuX = 0 */ 154*91f16700Schasinglulu mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu /** 158*91f16700Schasinglulu * Power off a cluster with specified index 159*91f16700Schasinglulu * 160*91f16700Schasinglulu * @cluster: the cluster index which to be powered off 161*91f16700Schasinglulu */ 162*91f16700Schasinglulu void spm_poweroff_cluster(uint32_t cluster) 163*91f16700Schasinglulu { 164*91f16700Schasinglulu /* No need to power on/off cluster on single cluster platform */ 165*91f16700Schasinglulu assert(false); 166*91f16700Schasinglulu } 167*91f16700Schasinglulu 168*91f16700Schasinglulu /** 169*91f16700Schasinglulu * Power on a cluster with specified index 170*91f16700Schasinglulu * 171*91f16700Schasinglulu * @cluster: the cluster index which to be powered on 172*91f16700Schasinglulu */ 173*91f16700Schasinglulu void spm_poweron_cluster(uint32_t cluster) 174*91f16700Schasinglulu { 175*91f16700Schasinglulu /* No need to power on/off cluster on single cluster platform */ 176*91f16700Schasinglulu assert(false); 177*91f16700Schasinglulu } 178