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