1 /* 2 * Copyright (c) 2021, 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 #include <plat/common/platform.h> 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 /* Clear cpu's cpc sw hint */ 27 mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); 28 } 29 30 void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr) 31 { 32 assert(cluster == 0U); 33 34 mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); 35 } 36 37 uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu) 38 { 39 assert(cluster == 0U); 40 41 return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); 42 } 43 44 void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64) 45 { 46 uint32_t reg; 47 48 assert(cluster == 0U); 49 50 reg = per_cluster(cluster, MCUCFG_INITARCH); 51 52 if (arm64) { 53 mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); 54 } else { 55 mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); 56 } 57 } 58 59 /* 60 * Return subsystem's power state. 61 * 62 * @mask: mask to SPM_CPU_PWR_STATUS to query the power state 63 * of one subsystem. 64 * RETURNS: 65 * 0 (the subsys was powered off) 66 * 1 (the subsys was powered on) 67 */ 68 bool spm_get_powerstate(uint32_t mask) 69 { 70 return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask); 71 } 72 73 bool spm_get_cluster_powerstate(unsigned int cluster) 74 { 75 assert(cluster == 0U); 76 77 return spm_get_powerstate(MP0_CPUTOP); 78 } 79 80 bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu) 81 { 82 uint32_t mask = BIT(cpu); 83 84 assert(cluster == 0U); 85 86 return spm_get_powerstate(mask); 87 } 88 89 int spmc_init(void) 90 { 91 unsigned int cpu = plat_my_core_pos(); 92 93 94 INFO("SPM: enable CPC mode\n"); 95 96 mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); 97 98 mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); 99 mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); 100 mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); 101 mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); 102 mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); 103 mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); 104 mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); 105 106 mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); 107 mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); 108 mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); 109 110 mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); 111 112 /* Clear bootup cpu's cpc sw hint */ 113 mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); 114 115 return 0; 116 } 117 118 /* 119 * Power on a core with specified cluster and core index 120 * 121 * @cluster: the cluster ID of the CPU which to be powered on 122 * @cpu: the CPU ID of the CPU which to be powered on 123 */ 124 void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) 125 { 126 /* info CPC that CPU hotplug on */ 127 mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); 128 129 /* Set mp0_spmc_pwr_on_cpuX = 1 */ 130 mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 131 132 /* wait for power on ack */ 133 while (!spm_get_cpu_powerstate(cluster, cpu)) 134 ; 135 136 /* info CPC that CPU hotplug off */ 137 mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN); 138 } 139 140 /* 141 * Power off a core with specified cluster and core index 142 * 143 * @cluster: the cluster ID of the CPU which to be powered off 144 * @cpu: the CPU ID of the CPU which to be powered off 145 */ 146 void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) 147 { 148 /* Set mp0_spmc_pwr_on_cpuX = 0 */ 149 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); 150 } 151 152 /* 153 * Power off a cluster with specified index 154 * 155 * @cluster: the cluster index which to be powered off 156 */ 157 void spm_poweroff_cluster(unsigned int cluster) 158 { 159 /* No need to power on/off cluster on single cluster platform */ 160 assert(false); 161 } 162 163 /* 164 * Power on a cluster with specified index 165 * 166 * @cluster: the cluster index which to be powered on 167 */ 168 void spm_poweron_cluster(unsigned int cluster) 169 { 170 /* No need to power on/off cluster on single cluster platform */ 171 assert(false); 172 } 173