1 /* 2 * Copyright (C) 2018 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * https://spdx.org/licenses 6 */ 7 8 #include <assert.h> 9 10 #include <common/debug.h> 11 #include <drivers/arm/gicv2.h> 12 #include <drivers/console.h> 13 #include <drivers/delay_timer.h> 14 #include <drivers/marvell/cache_llc.h> 15 #include <lib/bakery_lock.h> 16 #include <lib/mmio.h> 17 #include <plat/common/platform.h> 18 19 #include <armada_common.h> 20 #include <marvell_pm.h> 21 #include <mss_pm_ipc.h> 22 #include <plat_marvell.h> 23 #include <plat_pm_trace.h> 24 25 #define MVEBU_PRIVATE_UID_REG 0x30 26 #define MVEBU_RFU_GLOBL_SW_RST 0x84 27 #define MVEBU_CCU_RVBAR(cpu) (MVEBU_REGS_BASE + 0x640 + (cpu * 4)) 28 #define MVEBU_CCU_CPU_UN_RESET(cpu) (MVEBU_REGS_BASE + 0x650 + (cpu * 4)) 29 30 #define MPIDR_CPU_GET(mpidr) ((mpidr) & MPIDR_CPU_MASK) 31 #define MPIDR_CLUSTER_GET(mpidr) MPIDR_AFFLVL1_VAL((mpidr)) 32 33 #define MVEBU_GPIO_MASK(index) (1 << (index % 32)) 34 #define MVEBU_MPP_MASK(index) (0xF << (4 * (index % 8))) 35 #define MVEBU_GPIO_VALUE(index, value) (value << (index % 32)) 36 37 #define MVEBU_USER_CMD_0_REG (MVEBU_DRAM_MAC_BASE + 0x20) 38 #define MVEBU_USER_CMD_CH0_OFFSET 28 39 #define MVEBU_USER_CMD_CH0_MASK (1 << MVEBU_USER_CMD_CH0_OFFSET) 40 #define MVEBU_USER_CMD_CH0_EN (1 << MVEBU_USER_CMD_CH0_OFFSET) 41 #define MVEBU_USER_CMD_CS_OFFSET 24 42 #define MVEBU_USER_CMD_CS_MASK (0xF << MVEBU_USER_CMD_CS_OFFSET) 43 #define MVEBU_USER_CMD_CS_ALL (0xF << MVEBU_USER_CMD_CS_OFFSET) 44 #define MVEBU_USER_CMD_SR_OFFSET 6 45 #define MVEBU_USER_CMD_SR_MASK (0x3 << MVEBU_USER_CMD_SR_OFFSET) 46 #define MVEBU_USER_CMD_SR_ENTER (0x1 << MVEBU_USER_CMD_SR_OFFSET) 47 #define MVEBU_MC_PWR_CTRL_REG (MVEBU_DRAM_MAC_BASE + 0x54) 48 #define MVEBU_MC_AC_ON_DLY_OFFSET 8 49 #define MVEBU_MC_AC_ON_DLY_MASK (0xF << MVEBU_MC_AC_ON_DLY_OFFSET) 50 #define MVEBU_MC_AC_ON_DLY_DEF_VAR (8 << MVEBU_MC_AC_ON_DLY_OFFSET) 51 #define MVEBU_MC_AC_OFF_DLY_OFFSET 4 52 #define MVEBU_MC_AC_OFF_DLY_MASK (0xF << MVEBU_MC_AC_OFF_DLY_OFFSET) 53 #define MVEBU_MC_AC_OFF_DLY_DEF_VAR (0xC << MVEBU_MC_AC_OFF_DLY_OFFSET) 54 #define MVEBU_MC_PHY_AUTO_OFF_OFFSET 0 55 #define MVEBU_MC_PHY_AUTO_OFF_MASK (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET) 56 #define MVEBU_MC_PHY_AUTO_OFF_EN (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET) 57 58 /* this lock synchronize AP multiple cores execution with MSS */ 59 DEFINE_BAKERY_LOCK(pm_sys_lock); 60 61 /* Weak definitions may be overridden in specific board */ 62 #pragma weak plat_marvell_get_pm_cfg 63 64 /* AP806 CPU power down /power up definitions */ 65 enum CPU_ID { 66 CPU0, 67 CPU1, 68 CPU2, 69 CPU3 70 }; 71 72 #define REG_WR_VALIDATE_TIMEOUT (2000) 73 74 #define FEATURE_DISABLE_STATUS_REG \ 75 (MVEBU_REGS_BASE + 0x6F8230) 76 #define FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET 4 77 #define FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK \ 78 (0x1 << FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET) 79 80 #ifdef MVEBU_SOC_AP807 81 #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1 82 #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0 83 #else 84 #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0 85 #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31 86 #endif 87 88 #define PWRC_CPUN_CR_REG(cpu_id) \ 89 (MVEBU_REGS_BASE + 0x680000 + (cpu_id * 0x10)) 90 #define PWRC_CPUN_CR_PWR_DN_RQ_MASK \ 91 (0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET) 92 #define PWRC_CPUN_CR_ISO_ENABLE_OFFSET 16 93 #define PWRC_CPUN_CR_ISO_ENABLE_MASK \ 94 (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET) 95 #define PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK \ 96 (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET) 97 98 #define CCU_B_PRCRN_REG(cpu_id) \ 99 (MVEBU_REGS_BASE + 0x1A50 + \ 100 ((cpu_id / 2) * (0x400)) + ((cpu_id % 2) * 4)) 101 #define CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET 0 102 #define CCU_B_PRCRN_CPUPORESET_STATIC_MASK \ 103 (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET) 104 105 /* power switch fingers */ 106 #define AP807_PWRC_LDO_CR0_REG \ 107 (MVEBU_REGS_BASE + 0x680000 + 0x100) 108 #define AP807_PWRC_LDO_CR0_OFFSET 16 109 #define AP807_PWRC_LDO_CR0_MASK \ 110 (0xff << AP807_PWRC_LDO_CR0_OFFSET) 111 #define AP807_PWRC_LDO_CR0_VAL 0xfc 112 113 /* 114 * Power down CPU: 115 * Used to reduce power consumption, and avoid SoC unnecessary temperature rise. 116 */ 117 static int plat_marvell_cpu_powerdown(int cpu_id) 118 { 119 uint32_t reg_val; 120 int exit_loop = REG_WR_VALIDATE_TIMEOUT; 121 122 INFO("Powering down CPU%d\n", cpu_id); 123 124 /* 1. Isolation enable */ 125 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 126 reg_val |= 0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET; 127 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 128 129 /* 2. Read and check Isolation enabled - verify bit set to 1 */ 130 do { 131 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 132 exit_loop--; 133 } while (!(reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) && 134 exit_loop > 0); 135 136 /* 3. Switch off CPU power */ 137 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 138 reg_val &= ~PWRC_CPUN_CR_PWR_DN_RQ_MASK; 139 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 140 141 /* 4. Read and check Switch Off - verify bit set to 0 */ 142 exit_loop = REG_WR_VALIDATE_TIMEOUT; 143 do { 144 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 145 exit_loop--; 146 } while (reg_val & PWRC_CPUN_CR_PWR_DN_RQ_MASK && exit_loop > 0); 147 148 if (exit_loop <= 0) 149 goto cpu_poweroff_error; 150 151 /* 5. De-Assert power ready */ 152 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 153 reg_val &= ~PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK; 154 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 155 156 /* 6. Assert CPU POR reset */ 157 reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); 158 reg_val &= ~CCU_B_PRCRN_CPUPORESET_STATIC_MASK; 159 mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val); 160 161 /* 7. Read and poll on Validate the CPU is out of reset */ 162 exit_loop = REG_WR_VALIDATE_TIMEOUT; 163 do { 164 reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); 165 exit_loop--; 166 } while (reg_val & CCU_B_PRCRN_CPUPORESET_STATIC_MASK && exit_loop > 0); 167 168 if (exit_loop <= 0) 169 goto cpu_poweroff_error; 170 171 INFO("Successfully powered down CPU%d\n", cpu_id); 172 173 return 0; 174 175 cpu_poweroff_error: 176 ERROR("ERROR: Can't power down CPU%d\n", cpu_id); 177 return -1; 178 } 179 180 /* 181 * Power down CPUs 1-3 at early boot stage, 182 * to reduce power consumption and SoC temperature. 183 * This is triggered by BLE prior to DDR initialization. 184 * 185 * Note: 186 * All CPUs will be powered up by plat_marvell_cpu_powerup on Linux boot stage, 187 * which is triggered by PSCI ops (pwr_domain_on). 188 */ 189 int plat_marvell_early_cpu_powerdown(void) 190 { 191 uint32_t cpu_cluster_status = 192 mmio_read_32(FEATURE_DISABLE_STATUS_REG) & 193 FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK; 194 /* if cpu_cluster_status bit is set, 195 * that means we have only single cluster 196 */ 197 int cluster_count = cpu_cluster_status ? 1 : 2; 198 199 INFO("Powering off unused CPUs\n"); 200 201 /* CPU1 is in AP806 cluster-0, which always exists, so power it down */ 202 if (plat_marvell_cpu_powerdown(CPU1) == -1) 203 return -1; 204 205 /* 206 * CPU2-3 are in AP806 2nd cluster (cluster-1), 207 * which doesn't exists in dual-core systems. 208 * so need to check if we have dual-core (single cluster) 209 * or quad-code (2 clusters) 210 */ 211 if (cluster_count == 2) { 212 /* CPU2-3 are part of 2nd cluster */ 213 if (plat_marvell_cpu_powerdown(CPU2) == -1) 214 return -1; 215 if (plat_marvell_cpu_powerdown(CPU3) == -1) 216 return -1; 217 } 218 219 return 0; 220 } 221 222 /* 223 * Power up CPU - part of Linux boot stage 224 */ 225 static int plat_marvell_cpu_powerup(u_register_t mpidr) 226 { 227 uint32_t reg_val; 228 int cpu_id = MPIDR_CPU_GET(mpidr), 229 cluster = MPIDR_CLUSTER_GET(mpidr); 230 int exit_loop = REG_WR_VALIDATE_TIMEOUT; 231 232 /* calculate absolute CPU ID */ 233 cpu_id = cluster * PLAT_MARVELL_CLUSTER_CORE_COUNT + cpu_id; 234 235 INFO("Powering on CPU%d\n", cpu_id); 236 237 #ifdef MVEBU_SOC_AP807 238 /* Activate 2 power switch fingers */ 239 reg_val = mmio_read_32(AP807_PWRC_LDO_CR0_REG); 240 reg_val &= ~(AP807_PWRC_LDO_CR0_MASK); 241 reg_val |= (AP807_PWRC_LDO_CR0_VAL << AP807_PWRC_LDO_CR0_OFFSET); 242 mmio_write_32(AP807_PWRC_LDO_CR0_REG, reg_val); 243 udelay(100); 244 #endif 245 246 /* 1. Switch CPU power ON */ 247 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 248 reg_val |= 0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET; 249 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 250 251 /* 2. Wait for CPU on, up to 100 uSec: */ 252 udelay(100); 253 254 /* 3. Assert power ready */ 255 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 256 reg_val |= 0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET; 257 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 258 259 /* 4. Read & Validate power ready 260 * used in order to generate 16 Host CPU cycles 261 */ 262 do { 263 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 264 exit_loop--; 265 } while (!(reg_val & (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)) && 266 exit_loop > 0); 267 268 if (exit_loop <= 0) 269 goto cpu_poweron_error; 270 271 /* 5. Isolation disable */ 272 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 273 reg_val &= ~PWRC_CPUN_CR_ISO_ENABLE_MASK; 274 mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val); 275 276 /* 6. Read and check Isolation enabled - verify bit set to 1 */ 277 exit_loop = REG_WR_VALIDATE_TIMEOUT; 278 do { 279 reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id)); 280 exit_loop--; 281 } while ((reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) && 282 exit_loop > 0); 283 284 /* 7. De Assert CPU POR reset & Core reset */ 285 reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); 286 reg_val |= 0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET; 287 mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val); 288 289 /* 8. Read & Validate CPU POR reset */ 290 exit_loop = REG_WR_VALIDATE_TIMEOUT; 291 do { 292 reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id)); 293 exit_loop--; 294 } while (!(reg_val & (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)) && 295 exit_loop > 0); 296 297 if (exit_loop <= 0) 298 goto cpu_poweron_error; 299 300 INFO("Successfully powered on CPU%d\n", cpu_id); 301 302 return 0; 303 304 cpu_poweron_error: 305 ERROR("ERROR: Can't power up CPU%d\n", cpu_id); 306 return -1; 307 } 308 309 static int plat_marvell_cpu_on(u_register_t mpidr) 310 { 311 int cpu_id; 312 int cluster; 313 314 /* Set barierr */ 315 dsbsy(); 316 317 /* Get cpu number - use CPU ID */ 318 cpu_id = MPIDR_CPU_GET(mpidr); 319 320 /* Get cluster number - use affinity level 1 */ 321 cluster = MPIDR_CLUSTER_GET(mpidr); 322 323 /* Set CPU private UID */ 324 mmio_write_32(MVEBU_REGS_BASE + MVEBU_PRIVATE_UID_REG, cluster + 0x4); 325 326 /* Set the cpu start address to BL1 entry point (align to 0x10000) */ 327 mmio_write_32(MVEBU_CCU_RVBAR(cpu_id), 328 PLAT_MARVELL_CPU_ENTRY_ADDR >> 16); 329 330 /* Get the cpu out of reset */ 331 mmio_write_32(MVEBU_CCU_CPU_UN_RESET(cpu_id), 0x10001); 332 333 return 0; 334 } 335 336 /***************************************************************************** 337 * A8K handler called to check the validity of the power state 338 * parameter. 339 ***************************************************************************** 340 */ 341 static int a8k_validate_power_state(unsigned int power_state, 342 psci_power_state_t *req_state) 343 { 344 int pstate = psci_get_pstate_type(power_state); 345 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 346 int i; 347 348 if (pwr_lvl > PLAT_MAX_PWR_LVL) 349 return PSCI_E_INVALID_PARAMS; 350 351 /* Sanity check the requested state */ 352 if (pstate == PSTATE_TYPE_STANDBY) { 353 /* 354 * It's possible to enter standby only on power level 0 355 * Ignore any other power level. 356 */ 357 if (pwr_lvl != MARVELL_PWR_LVL0) 358 return PSCI_E_INVALID_PARAMS; 359 360 req_state->pwr_domain_state[MARVELL_PWR_LVL0] = 361 MARVELL_LOCAL_STATE_RET; 362 } else { 363 for (i = MARVELL_PWR_LVL0; i <= pwr_lvl; i++) 364 req_state->pwr_domain_state[i] = 365 MARVELL_LOCAL_STATE_OFF; 366 } 367 368 /* 369 * We expect the 'state id' to be zero. 370 */ 371 if (psci_get_pstate_id(power_state)) 372 return PSCI_E_INVALID_PARAMS; 373 374 return PSCI_E_SUCCESS; 375 } 376 377 /***************************************************************************** 378 * A8K handler called when a CPU is about to enter standby. 379 ***************************************************************************** 380 */ 381 static void a8k_cpu_standby(plat_local_state_t cpu_state) 382 { 383 if (!is_pm_fw_running()) { 384 ERROR("%s: needs to be implemented\n", __func__); 385 panic(); 386 } 387 } 388 389 /***************************************************************************** 390 * A8K handler called when a power domain is about to be turned on. The 391 * mpidr determines the CPU to be turned on. 392 ***************************************************************************** 393 */ 394 static int a8k_pwr_domain_on(u_register_t mpidr) 395 { 396 /* Power up CPU (CPUs 1-3 are powered off at start of BLE) */ 397 plat_marvell_cpu_powerup(mpidr); 398 399 if (is_pm_fw_running()) { 400 unsigned int target = 401 ((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2)); 402 403 /* 404 * pm system synchronization - used to synchronize 405 * multiple core access to MSS 406 */ 407 bakery_lock_get(&pm_sys_lock); 408 409 /* send CPU ON IPC Message to MSS */ 410 mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0); 411 412 /* trigger IPC message to MSS */ 413 mss_pm_ipc_msg_trigger(); 414 415 /* pm system synchronization */ 416 bakery_lock_release(&pm_sys_lock); 417 418 /* trace message */ 419 PM_TRACE(TRACE_PWR_DOMAIN_ON | target); 420 } else { 421 /* proprietary CPU ON exection flow */ 422 plat_marvell_cpu_on(mpidr); 423 } 424 425 return 0; 426 } 427 428 /***************************************************************************** 429 * A8K handler called to validate the entry point. 430 ***************************************************************************** 431 */ 432 static int a8k_validate_ns_entrypoint(uintptr_t entrypoint) 433 { 434 return PSCI_E_SUCCESS; 435 } 436 437 /***************************************************************************** 438 * A8K handler called when a power domain is about to be turned off. The 439 * target_state encodes the power state that each level should transition to. 440 ***************************************************************************** 441 */ 442 static void a8k_pwr_domain_off(const psci_power_state_t *target_state) 443 { 444 if (is_pm_fw_running()) { 445 unsigned int idx = plat_my_core_pos(); 446 447 /* Prevent interrupts from spuriously waking up this cpu */ 448 gicv2_cpuif_disable(); 449 450 /* pm system synchronization - used to synchronize multiple 451 * core access to MSS 452 */ 453 bakery_lock_get(&pm_sys_lock); 454 455 /* send CPU OFF IPC Message to MSS */ 456 mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state); 457 458 /* trigger IPC message to MSS */ 459 mss_pm_ipc_msg_trigger(); 460 461 /* pm system synchronization */ 462 bakery_lock_release(&pm_sys_lock); 463 464 /* trace message */ 465 PM_TRACE(TRACE_PWR_DOMAIN_OFF); 466 } else { 467 INFO("%s: is not supported without SCP\n", __func__); 468 } 469 } 470 471 /* Get PM config to power off the SoC */ 472 void *plat_marvell_get_pm_cfg(void) 473 { 474 return NULL; 475 } 476 477 /* 478 * This function should be called on restore from 479 * "suspend to RAM" state when the execution flow 480 * has to bypass BootROM image to RAM copy and speed up 481 * the system recovery 482 * 483 */ 484 static void plat_marvell_exit_bootrom(void) 485 { 486 marvell_exit_bootrom(PLAT_MARVELL_TRUSTED_ROM_BASE); 487 } 488 489 /* 490 * Prepare for the power off of the system via GPIO 491 */ 492 static void plat_marvell_power_off_gpio(struct power_off_method *pm_cfg, 493 register_t *gpio_addr, 494 register_t *gpio_data) 495 { 496 unsigned int gpio; 497 unsigned int idx; 498 unsigned int shift; 499 unsigned int reg; 500 unsigned int addr; 501 gpio_info_t *info; 502 unsigned int tog_bits; 503 504 assert((pm_cfg->cfg.gpio.pin_count < PMIC_GPIO_MAX_NUMBER) && 505 (pm_cfg->cfg.gpio.step_count < PMIC_GPIO_MAX_TOGGLE_STEP)); 506 507 /* Prepare GPIOs for PMIC */ 508 for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) { 509 info = &pm_cfg->cfg.gpio.info[gpio]; 510 /* Set PMIC GPIO to output mode */ 511 reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT_EN( 512 info->cp_index, info->gpio_index)); 513 mmio_write_32(MVEBU_CP_GPIO_DATA_OUT_EN( 514 info->cp_index, info->gpio_index), 515 reg & ~MVEBU_GPIO_MASK(info->gpio_index)); 516 517 /* Set the appropriate MPP to GPIO mode */ 518 reg = mmio_read_32(MVEBU_PM_MPP_REGS(info->cp_index, 519 info->gpio_index)); 520 mmio_write_32(MVEBU_PM_MPP_REGS(info->cp_index, 521 info->gpio_index), 522 reg & ~MVEBU_MPP_MASK(info->gpio_index)); 523 } 524 525 /* Wait for MPP & GPIO pre-configurations done */ 526 mdelay(pm_cfg->cfg.gpio.delay_ms); 527 528 /* Toggle the GPIO values, and leave final step to be triggered 529 * after DDR self-refresh is enabled 530 */ 531 for (idx = 0; idx < pm_cfg->cfg.gpio.step_count; idx++) { 532 tog_bits = pm_cfg->cfg.gpio.seq[idx]; 533 534 /* The GPIOs must be within same GPIO register, 535 * thus could get the original value by first GPIO 536 */ 537 info = &pm_cfg->cfg.gpio.info[0]; 538 reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT( 539 info->cp_index, info->gpio_index)); 540 addr = MVEBU_CP_GPIO_DATA_OUT(info->cp_index, info->gpio_index); 541 542 for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) { 543 shift = pm_cfg->cfg.gpio.info[gpio].gpio_index % 32; 544 if (GPIO_LOW == (tog_bits & (1 << gpio))) 545 reg &= ~(1 << shift); 546 else 547 reg |= (1 << shift); 548 } 549 550 /* Set the GPIO register, for last step just store 551 * register address and values to system registers 552 */ 553 if (idx < pm_cfg->cfg.gpio.step_count - 1) { 554 mmio_write_32(MVEBU_CP_GPIO_DATA_OUT( 555 info->cp_index, info->gpio_index), reg); 556 mdelay(pm_cfg->cfg.gpio.delay_ms); 557 } else { 558 /* Save GPIO register and address values for 559 * finishing the power down operation later 560 */ 561 *gpio_addr = addr; 562 *gpio_data = reg; 563 } 564 } 565 } 566 567 /* 568 * Prepare for the power off of the system 569 */ 570 static void plat_marvell_power_off_prepare(struct power_off_method *pm_cfg, 571 register_t *addr, register_t *data) 572 { 573 switch (pm_cfg->type) { 574 case PMIC_GPIO: 575 plat_marvell_power_off_gpio(pm_cfg, addr, data); 576 break; 577 default: 578 break; 579 } 580 } 581 582 /***************************************************************************** 583 * A8K handler called when a power domain is about to be suspended. The 584 * target_state encodes the power state that each level should transition to. 585 ***************************************************************************** 586 */ 587 static void a8k_pwr_domain_suspend(const psci_power_state_t *target_state) 588 { 589 if (is_pm_fw_running()) { 590 unsigned int idx; 591 592 /* Prevent interrupts from spuriously waking up this cpu */ 593 gicv2_cpuif_disable(); 594 595 idx = plat_my_core_pos(); 596 597 /* pm system synchronization - used to synchronize multiple 598 * core access to MSS 599 */ 600 bakery_lock_get(&pm_sys_lock); 601 602 /* send CPU Suspend IPC Message to MSS */ 603 mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state); 604 605 /* trigger IPC message to MSS */ 606 mss_pm_ipc_msg_trigger(); 607 608 /* pm system synchronization */ 609 bakery_lock_release(&pm_sys_lock); 610 611 /* trace message */ 612 PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND); 613 } else { 614 uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; 615 616 INFO("Suspending to RAM\n"); 617 618 marvell_console_runtime_end(); 619 620 /* Prevent interrupts from spuriously waking up this cpu */ 621 gicv2_cpuif_disable(); 622 623 mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE; 624 mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_marvell_exit_bootrom; 625 626 #if PLAT_MARVELL_SHARED_RAM_CACHED 627 flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE + 628 MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t), 629 2 * sizeof(uintptr_t)); 630 #endif 631 /* Flush and disable LLC before going off-power */ 632 llc_disable(0); 633 634 isb(); 635 /* 636 * Do not halt here! 637 * The function must return for allowing the caller function 638 * psci_power_up_finish() to do the proper context saving and 639 * to release the CPU lock. 640 */ 641 } 642 } 643 644 /***************************************************************************** 645 * A8K handler called when a power domain has just been powered on after 646 * being turned off earlier. The target_state encodes the low power state that 647 * each level has woken up from. 648 ***************************************************************************** 649 */ 650 static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state) 651 { 652 /* arch specific configuration */ 653 marvell_psci_arch_init(0); 654 655 /* Interrupt initialization */ 656 gicv2_pcpu_distif_init(); 657 gicv2_cpuif_enable(); 658 659 if (is_pm_fw_running()) { 660 /* trace message */ 661 PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH); 662 } 663 } 664 665 /***************************************************************************** 666 * A8K handler called when a power domain has just been powered on after 667 * having been suspended earlier. The target_state encodes the low power state 668 * that each level has woken up from. 669 * TODO: At the moment we reuse the on finisher and reinitialize the secure 670 * context. Need to implement a separate suspend finisher. 671 ***************************************************************************** 672 */ 673 static void a8k_pwr_domain_suspend_finish( 674 const psci_power_state_t *target_state) 675 { 676 if (is_pm_fw_running()) { 677 /* arch specific configuration */ 678 marvell_psci_arch_init(0); 679 680 /* Interrupt initialization */ 681 gicv2_cpuif_enable(); 682 683 /* trace message */ 684 PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH); 685 } else { 686 uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE; 687 688 /* Only primary CPU requres platform init */ 689 if (!plat_my_core_pos()) { 690 /* Initialize the console to provide 691 * early debug support 692 */ 693 marvell_console_runtime_init(); 694 695 bl31_plat_arch_setup(); 696 marvell_bl31_platform_setup(); 697 /* 698 * Remove suspend to RAM marker from the mailbox 699 * for treating a regular reset as a cold boot 700 */ 701 mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0; 702 mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0; 703 #if PLAT_MARVELL_SHARED_RAM_CACHED 704 flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE + 705 MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t), 706 2 * sizeof(uintptr_t)); 707 #endif 708 } 709 } 710 } 711 712 /***************************************************************************** 713 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` 714 * call to get the `power_state` parameter. This allows the platform to encode 715 * the appropriate State-ID field within the `power_state` parameter which can 716 * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 717 ***************************************************************************** 718 */ 719 static void a8k_get_sys_suspend_power_state(psci_power_state_t *req_state) 720 { 721 /* lower affinities use PLAT_MAX_OFF_STATE */ 722 for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 723 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 724 } 725 726 static void 727 __dead2 a8k_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) 728 { 729 struct power_off_method *pm_cfg; 730 unsigned int srcmd; 731 unsigned int sdram_reg; 732 register_t gpio_data = 0, gpio_addr = 0; 733 734 if (is_pm_fw_running()) { 735 psci_power_down_wfi(); 736 panic(); 737 } 738 739 pm_cfg = (struct power_off_method *)plat_marvell_get_pm_cfg(); 740 741 /* Prepare for power off */ 742 plat_marvell_power_off_prepare(pm_cfg, &gpio_addr, &gpio_data); 743 744 /* First step to enable DDR self-refresh 745 * to keep the data during suspend 746 */ 747 mmio_write_32(MVEBU_MC_PWR_CTRL_REG, 0x8C1); 748 749 /* Save DDR self-refresh second step register 750 * and value to be issued later 751 */ 752 sdram_reg = MVEBU_USER_CMD_0_REG; 753 srcmd = mmio_read_32(sdram_reg); 754 srcmd &= ~(MVEBU_USER_CMD_CH0_MASK | MVEBU_USER_CMD_CS_MASK | 755 MVEBU_USER_CMD_SR_MASK); 756 srcmd |= (MVEBU_USER_CMD_CH0_EN | MVEBU_USER_CMD_CS_ALL | 757 MVEBU_USER_CMD_SR_ENTER); 758 759 /* 760 * Wait for DRAM is done using registers access only. 761 * At this stage any access to DRAM (procedure call) will 762 * release it from the self-refresh mode 763 */ 764 __asm__ volatile ( 765 /* Align to a cache line */ 766 " .balign 64\n\t" 767 768 /* Enter self refresh */ 769 " str %[srcmd], [%[sdram_reg]]\n\t" 770 771 /* 772 * Wait 100 cycles for DDR to enter self refresh, by 773 * doing 50 times two instructions. 774 */ 775 " mov x1, #50\n\t" 776 "1: subs x1, x1, #1\n\t" 777 " bne 1b\n\t" 778 779 /* Issue the command to trigger the SoC power off */ 780 " str %[gpio_data], [%[gpio_addr]]\n\t" 781 782 /* Trap the processor */ 783 " b .\n\t" 784 : : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg), 785 [gpio_addr] "r" (gpio_addr), [gpio_data] "r" (gpio_data) 786 : "x1"); 787 788 panic(); 789 } 790 791 /***************************************************************************** 792 * A8K handlers to shutdown/reboot the system 793 ***************************************************************************** 794 */ 795 796 /* Set a weak stub for platforms that don't configure system power off */ 797 #pragma weak system_power_off 798 int system_power_off(void) 799 { 800 return 0; 801 } 802 803 static void __dead2 a8k_system_off(void) 804 { 805 /* Call the platform specific system power off function */ 806 system_power_off(); 807 808 /* board doesn't have a system off implementation */ 809 ERROR("%s: needs to be implemented\n", __func__); 810 panic(); 811 } 812 813 void plat_marvell_system_reset(void) 814 { 815 mmio_write_32(MVEBU_RFU_BASE + MVEBU_RFU_GLOBL_SW_RST, 0x0); 816 } 817 818 static void __dead2 a8k_system_reset(void) 819 { 820 plat_marvell_system_reset(); 821 822 /* we shouldn't get to this point */ 823 panic(); 824 } 825 826 /***************************************************************************** 827 * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard 828 * platform layer will take care of registering the handlers with PSCI. 829 ***************************************************************************** 830 */ 831 const plat_psci_ops_t plat_arm_psci_pm_ops = { 832 .cpu_standby = a8k_cpu_standby, 833 .pwr_domain_on = a8k_pwr_domain_on, 834 .pwr_domain_off = a8k_pwr_domain_off, 835 .pwr_domain_suspend = a8k_pwr_domain_suspend, 836 .pwr_domain_on_finish = a8k_pwr_domain_on_finish, 837 .get_sys_suspend_power_state = a8k_get_sys_suspend_power_state, 838 .pwr_domain_suspend_finish = a8k_pwr_domain_suspend_finish, 839 .pwr_domain_pwr_down_wfi = a8k_pwr_domain_pwr_down_wfi, 840 .system_off = a8k_system_off, 841 .system_reset = a8k_system_reset, 842 .validate_power_state = a8k_validate_power_state, 843 .validate_ns_entrypoint = a8k_validate_ns_entrypoint 844 }; 845