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(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 } 27*91f16700Schasinglulu 28*91f16700Schasinglulu void mcucfg_set_bootaddr(unsigned int cluster, unsigned int 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(unsigned int cluster, unsigned int 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(unsigned int cluster, unsigned int 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 MCUCFG_CPC_SPMC_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(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U; 69*91f16700Schasinglulu } 70*91f16700Schasinglulu 71*91f16700Schasinglulu bool spm_get_cluster_powerstate(unsigned int cluster) 72*91f16700Schasinglulu { 73*91f16700Schasinglulu assert(cluster == 0U); 74*91f16700Schasinglulu 75*91f16700Schasinglulu return spm_get_powerstate(BIT(14)); 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int 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_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 102*91f16700Schasinglulu mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 103*91f16700Schasinglulu mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); 104*91f16700Schasinglulu 105*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); 106*91f16700Schasinglulu mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN); 107*91f16700Schasinglulu 108*91f16700Schasinglulu return 0; 109*91f16700Schasinglulu } 110*91f16700Schasinglulu 111*91f16700Schasinglulu /** 112*91f16700Schasinglulu * Power on a core with specified cluster and core index 113*91f16700Schasinglulu * 114*91f16700Schasinglulu * @cluster: the cluster ID of the CPU which to be powered on 115*91f16700Schasinglulu * @cpu: the CPU ID of the CPU which to be powered on 116*91f16700Schasinglulu */ 117*91f16700Schasinglulu void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) 118*91f16700Schasinglulu { 119*91f16700Schasinglulu uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR); 120*91f16700Schasinglulu 121*91f16700Schasinglulu /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ 122*91f16700Schasinglulu if (cpu >= 4U) { 123*91f16700Schasinglulu mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); 124*91f16700Schasinglulu } 125*91f16700Schasinglulu 126*91f16700Schasinglulu mmio_setbits_32(cpu_pwr_con, PWR_ON); 127*91f16700Schasinglulu 128*91f16700Schasinglulu while (!spm_get_cpu_powerstate(cluster, cpu)) { 129*91f16700Schasinglulu mmio_clrbits_32(cpu_pwr_con, PWR_ON); 130*91f16700Schasinglulu mmio_setbits_32(cpu_pwr_con, PWR_ON); 131*91f16700Schasinglulu } 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu /** 135*91f16700Schasinglulu * Power off a core with specified cluster and core index 136*91f16700Schasinglulu * 137*91f16700Schasinglulu * @cluster: the cluster ID of the CPU which to be powered off 138*91f16700Schasinglulu * @cpu: the CPU ID of the CPU which to be powered off 139*91f16700Schasinglulu */ 140*91f16700Schasinglulu void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) 141*91f16700Schasinglulu { 142*91f16700Schasinglulu /* Set mp0_spmc_pwr_on_cpuX = 0 */ 143*91f16700Schasinglulu mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu /** 147*91f16700Schasinglulu * Power off a cluster with specified index 148*91f16700Schasinglulu * 149*91f16700Schasinglulu * @cluster: the cluster index which to be powered off 150*91f16700Schasinglulu */ 151*91f16700Schasinglulu void spm_poweroff_cluster(unsigned int cluster) 152*91f16700Schasinglulu { 153*91f16700Schasinglulu /* No need to power on/off cluster on single cluster platform */ 154*91f16700Schasinglulu assert(false); 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu /** 158*91f16700Schasinglulu * Power on a cluster with specified index 159*91f16700Schasinglulu * 160*91f16700Schasinglulu * @cluster: the cluster index which to be powered on 161*91f16700Schasinglulu */ 162*91f16700Schasinglulu void spm_poweron_cluster(unsigned int cluster) 163*91f16700Schasinglulu { 164*91f16700Schasinglulu /* No need to power on/off cluster on single cluster platform */ 165*91f16700Schasinglulu assert(false); 166*91f16700Schasinglulu } 167