1 /* 2 * Copyright (c) 2020, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <common/debug.h> 10 #include <drivers/delay_timer.h> 11 #include <lib/mmio.h> 12 13 #include <mcucfg.h> 14 #include <mtspmc.h> 15 #include <mtspmc_private.h> 16 17 18 void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu) 19 { 20 mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); 21 } 22 23 void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu) 24 { 25 mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); 26 } 27 28 void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr) 29 { 30 assert(cluster == 0U); 31 32 mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); 33 } 34 35 uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu) 36 { 37 assert(cluster == 0U); 38 39 return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); 40 } 41 42 void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64) 43 { 44 uint32_t reg; 45 46 assert(cluster == 0U); 47 48 reg = per_cluster(cluster, MCUCFG_INITARCH); 49 50 if (arm64) { 51 mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); 52 } else { 53 mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); 54 } 55 } 56 57 /** 58 * Return subsystem's power state. 59 * 60 * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state 61 * of one subsystem. 62 * RETURNS: 63 * 0 (the subsys was powered off) 64 * 1 (the subsys was powered on) 65 */ 66 bool spm_get_powerstate(uint32_t mask) 67 { 68 return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U; 69 } 70 71 bool spm_get_cluster_powerstate(unsigned int cluster) 72 { 73 assert(cluster == 0U); 74 75 return spm_get_powerstate(BIT(14)); 76 } 77 78 bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu) 79 { 80 uint32_t mask = BIT(cpu); 81 82 assert(cluster == 0U); 83 84 return spm_get_powerstate(mask); 85 } 86 87 int spmc_init(void) 88 { 89 INFO("SPM: enable CPC mode\n"); 90 91 mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); 92 93 mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); 94 mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); 95 mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); 96 mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); 97 mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); 98 mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); 99 mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); 100 101 mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 102 mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 103 mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); 104 105 mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); 106 mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN); 107 108 return 0; 109 } 110 111 /** 112 * Power on a core with specified cluster and core index 113 * 114 * @cluster: the cluster ID of the CPU which to be powered on 115 * @cpu: the CPU ID of the CPU which to be powered on 116 */ 117 void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) 118 { 119 uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR); 120 121 /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ 122 if (cpu >= 4U) { 123 mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); 124 } 125 126 mmio_setbits_32(cpu_pwr_con, PWR_ON); 127 128 while (!spm_get_cpu_powerstate(cluster, cpu)) { 129 mmio_clrbits_32(cpu_pwr_con, PWR_ON); 130 mmio_setbits_32(cpu_pwr_con, PWR_ON); 131 } 132 } 133 134 /** 135 * Power off a core with specified cluster and core index 136 * 137 * @cluster: the cluster ID of the CPU which to be powered off 138 * @cpu: the CPU ID of the CPU which to be powered off 139 */ 140 void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) 141 { 142 /* Set mp0_spmc_pwr_on_cpuX = 0 */ 143 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 144 } 145 146 /** 147 * Power off a cluster with specified index 148 * 149 * @cluster: the cluster index which to be powered off 150 */ 151 void spm_poweroff_cluster(unsigned int cluster) 152 { 153 /* No need to power on/off cluster on single cluster platform */ 154 assert(false); 155 } 156 157 /** 158 * Power on a cluster with specified index 159 * 160 * @cluster: the cluster index which to be powered on 161 */ 162 void spm_poweron_cluster(unsigned int cluster) 163 { 164 /* No need to power on/off cluster on single cluster platform */ 165 assert(false); 166 } 167