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