1 /* 2 * Copyright (c) 2019, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <arch_helpers.h> 9 #include <cortex_a53.h> 10 #include <cortex_a73.h> 11 #include <common/debug.h> 12 #include <lib/mmio.h> 13 #include <platform_def.h> 14 #include <mcucfg.h> 15 #include <spm.h> 16 #include <drivers/delay_timer.h> 17 #include <mtspmc.h> 18 19 #include "mtspmc_private.h" 20 21 22 static void set_retention(int cluster, int tick) 23 { 24 uint64_t cpuectlr; 25 26 if (cluster) 27 cpuectlr = read_a73_cpuectlr_el1(); 28 else 29 cpuectlr = read_a53_cpuectlr_el1(); 30 31 cpuectlr &= ~0x7ULL; 32 cpuectlr |= tick & 0x7; 33 34 if (cluster) 35 write_a73_cpuectlr_el1(cpuectlr); 36 else 37 write_a53_cpuectlr_el1(cpuectlr); 38 } 39 40 void spm_enable_cpu_auto_off(int cluster, int cpu) 41 { 42 uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK); 43 44 set_retention(cluster, 1); 45 mmio_clrbits_32(reg, SW_NO_WAIT_Q); 46 } 47 48 void spm_disable_cpu_auto_off(int cluster, int cpu) 49 { 50 uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK); 51 52 mmio_setbits_32(reg, SW_NO_WAIT_Q); 53 set_retention(cluster, 0); 54 } 55 56 void spm_set_cpu_power_off(int cluster, int cpu) 57 { 58 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); 59 } 60 61 void spm_enable_cluster_auto_off(int cluster) 62 { 63 assert(cluster); 64 65 mmio_clrbits_32(MCUCFG_MP2_SPMC, SW_NO_WAIT_Q); 66 mmio_clrbits_32(MCUCFG_MP2_COQ, BIT(0)); 67 68 mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, MP1_SPMC_SRAM_DORMANT_EN); 69 70 mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); 71 } 72 73 void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr) 74 { 75 uintptr_t reg; 76 const uintptr_t mp2_bootreg[] = { 77 MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1, 78 MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 }; 79 80 if (cluster) { 81 assert(cpu >= 0 && cpu < 4); 82 reg = mp2_bootreg[cpu]; 83 } else { 84 reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR); 85 } 86 87 mmio_write_32(reg, bootaddr); 88 } 89 90 uintptr_t mcucfg_get_bootaddr(int cluster, int cpu) 91 { 92 uintptr_t reg; 93 const uintptr_t mp2_bootreg[] = { 94 MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1, 95 MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 }; 96 97 if (cluster) { 98 assert(cpu >= 0 && cpu < 4); 99 reg = mp2_bootreg[cpu]; 100 } else { 101 reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR); 102 } 103 104 return mmio_read_32(reg); 105 } 106 107 void mcucfg_init_archstate(int cluster, int cpu, int arm64) 108 { 109 uintptr_t reg; 110 int i; 111 112 reg = per_cluster(cluster, MCUCFG_INITARCH); 113 i = cluster ? 16 : 12; 114 115 mmio_setbits_32(reg, (arm64 & 1) << (i + cpu)); 116 } 117 118 /** 119 * Return power state of specified subsystem 120 * 121 * @mask: mask to SPM_PWR_STATUS to query the power state 122 * of one subsystem. 123 * RETURNS: 124 * 0 (the subsys was powered off) 125 * 1 (the subsys was powered on) 126 */ 127 int spm_get_powerstate(uint32_t mask) 128 { 129 return mmio_read_32(SPM_PWR_STATUS) & mask; 130 } 131 132 int spm_get_cluster_powerstate(int cluster) 133 { 134 uint32_t mask; 135 136 mask = cluster ? PWR_STATUS_MP1_CPUTOP : PWR_STATUS_MP0_CPUTOP; 137 138 return spm_get_powerstate(mask); 139 } 140 141 int spm_get_cpu_powerstate(int cluster, int cpu) 142 { 143 uint32_t i; 144 145 /* 146 * a quick way to specify the mask of cpu[0-3]/cpu[4-7] in PWR_STATUS 147 * register which are the BITS[9:12](MP0_CPU0~3) and 148 * BITS[16:19](MP1_CPU0~3) 149 */ 150 i = (cluster) ? 16 : 9; 151 i = 1 << (i + cpu); 152 153 return spm_get_powerstate(i); 154 } 155 156 int spmc_init(void) 157 { 158 /* enable SPM register control */ 159 mmio_write_32(SPM_POWERON_CONFIG_EN, 160 PROJECT_CODE | MD_BCLK_CG_EN | BCLK_CG_EN); 161 162 #if SPMC_MODE == 1 163 INFO("SPM: enable SPMC mode\n"); 164 165 /* 0: SPMC mode 1: Legacy mode */ 166 mmio_write_32(SPM_BYPASS_SPMC, 0); 167 168 mmio_clrbits_32(per_cluster(0, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND); 169 170 mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 171 mmio_clrbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 172 mmio_clrbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 173 mmio_clrbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 174 175 mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 176 mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 177 mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 178 #endif 179 180 mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND); 181 mmio_setbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_RST_B); 182 mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_CLK_DIS); 183 184 mmio_clrbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 185 mmio_clrbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 186 mmio_clrbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 187 mmio_clrbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 188 189 mmio_setbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 190 mmio_setbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 191 mmio_setbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 192 mmio_setbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 193 194 return 0; 195 } 196 197 /** 198 * Power on a core with specified cluster and core index 199 * 200 * @cluster: the cluster ID of the CPU which to be powered on 201 * @cpu: the CPU ID of the CPU which to be powered on 202 */ 203 void spm_poweron_cpu(int cluster, int cpu) 204 { 205 INFO("spmc: power on core %d.%d\n", cluster, cpu); 206 207 /* STA_POWER_ON */ 208 /* Start to turn on MP0_CPU0 */ 209 210 /* Set PWR_RST_B = 1 */ 211 mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 212 213 /* Set PWR_ON = 1 */ 214 mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); 215 216 /* Wait until MP0_CPU0_PWR_STA_MASK = 1 */ 217 while (!spm_get_cpu_powerstate(cluster, cpu)) 218 ; 219 220 /* Finish to turn on MP0_CPU0 */ 221 INFO("spmc: power on core %d.%d successfully\n", cluster, cpu); 222 } 223 224 /** 225 * Power off a core with specified cluster and core index 226 * 227 * @cluster: the cluster ID of the CPU which to be powered off 228 * @cpu: the CPU ID of the CPU which to be powered off 229 */ 230 void spm_poweroff_cpu(int cluster, int cpu) 231 { 232 INFO("spmc: power off core %d.%d\n", cluster, cpu); 233 234 /* Start to turn off MP0_CPU0 */ 235 /* Set PWR_ON_2ND = 0 */ 236 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND); 237 238 /* Set PWR_ON = 0 */ 239 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON); 240 241 /* Wait until MP0_CPU0_PWR_STA_MASK = 0 */ 242 while (spm_get_cpu_powerstate(cluster, cpu)) 243 ; 244 245 /* Set PWR_RST_B = 0 */ 246 mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B); 247 248 /* Finish to turn off MP0_CPU0 */ 249 INFO("spmc: power off core %d.%d successfully\n", cluster, cpu); 250 } 251 252 /** 253 * Power off a cluster with specified index 254 * 255 * @cluster: the cluster index which to be powered off 256 */ 257 void spm_poweroff_cluster(int cluster) 258 { 259 uint32_t mask; 260 uint32_t pwr_rst_ctl; 261 262 INFO("spmc: power off cluster %d\n", cluster); 263 264 /* Start to turn off MP0_CPUTOP */ 265 /* Set bus protect - step1 : 0 */ 266 mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK : 267 MP0_CPUTOP_PROT_STEP1_0_MASK; 268 mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_SET, mask); 269 270 while ((mmio_read_32(INFRA_TOPAXI_PROTECTEN_STA1_1) & mask) != mask) 271 ; 272 273 /* Set PWR_ON_2ND = 0 */ 274 mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), 275 PWRCTRL_PWR_ON_2ND); 276 277 /* SPMC_DORMANT_ENABLE[0]=0 */ 278 mask = (cluster) ? MP1_SPMC_SRAM_DORMANT_EN : MP0_SPMC_SRAM_DORMANT_EN; 279 mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, mask); 280 281 /* Set PWR_ON = 0" */ 282 mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); 283 284 /* Wait until MP0_CPUTOP_PWR_STA_MASK = 0 */ 285 while (spm_get_cluster_powerstate(cluster)) 286 ; 287 288 /* NOTE 289 * Following flow only for BIG core cluster. It was from 290 * application note but not covered in mtcmos_ctrl.c 291 */ 292 if (cluster) { 293 pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL); 294 mmio_write_32(MCUCFG_MP2_PWR_RST_CTL, 295 (pwr_rst_ctl & ~SW_RST_B) | TOPAON_APB_MASK); 296 } 297 298 /* CPU_EXT_BUCK_ISO[0]=1 */ 299 if (cluster) 300 mmio_setbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO); 301 302 /* Finish to turn off MP0_CPUTOP */ 303 INFO("spmc: power off cluster %d successfully\n", cluster); 304 } 305 306 /** 307 * Power on a cluster with specified index 308 * 309 * @cluster: the cluster index which to be powered on 310 */ 311 void spm_poweron_cluster(int cluster) 312 { 313 uint32_t mask; 314 uint32_t pwr_rst_ctl; 315 316 INFO("spmc: power on cluster %d\n", cluster); 317 318 /* Start to turn on MP1_CPUTOP */ 319 320 /* NOTE 321 * Following flow only for BIG core cluster. It was from 322 * application note but not covered in mtcmos_ctrl.c 323 */ 324 if (cluster) { 325 mmio_clrbits_32(MCUCFG_MP2_PWR_RST_CTL, SW_RST_B); 326 327 /* CPU_EXT_BUCK_ISO[1]=0 */ 328 /* Set mp<n>_vproc_ext_off to 0 to release vproc isolation control */ 329 mmio_clrbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO); 330 331 /* NOTE 332 * Following flow only for BIG core cluster. It was from 333 * application note but not covered in mtcmos_ctrl.c 334 */ 335 pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL); 336 mmio_write_32(MCUCFG_MP2_PWR_RST_CTL, 337 (pwr_rst_ctl | SW_RST_B) & ~TOPAON_APB_MASK); 338 } 339 340 /* Set PWR_ON_2ND = 0 */ 341 mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), 342 PWRCTRL_PWR_ON_2ND); 343 344 /* Set PWR_RST_B = 1 */ 345 mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), 346 PWRCTRL_PWR_RST_B); 347 348 /* Set PWR_CLK_DIS = 0 */ 349 mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), 350 PWRCTRL_PWR_CLK_DIS); 351 352 /* Set PWR_ON = 1 */ 353 mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON); 354 355 /* Wait until MP1_CPUTOP_PWR_STA_MASK = 1 */ 356 while (!spm_get_cluster_powerstate(cluster)) 357 ; 358 359 /* Release bus protect - step1 : 0 */ 360 mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK : 361 MP0_CPUTOP_PROT_STEP1_0_MASK; 362 mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_CLR, mask); 363 364 /* Finish to turn on MP1_CPUTOP */ 365 INFO("spmc: power on cluster %d successfully\n", cluster); 366 } 367