108438e24SVarun Wadekar /* 2*500fc9e1SVarun Wadekar * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 308438e24SVarun Wadekar * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 508438e24SVarun Wadekar */ 608438e24SVarun Wadekar 708438e24SVarun Wadekar #include <assert.h> 809d40e0eSAntonio Nino Diaz 908438e24SVarun Wadekar #include <platform_def.h> 1009d40e0eSAntonio Nino Diaz 1109d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1209d40e0eSAntonio Nino Diaz #include <common/bl_common.h> 1309d40e0eSAntonio Nino Diaz #include <common/debug.h> 1409d40e0eSAntonio Nino Diaz #include <context.h> 1509d40e0eSAntonio Nino Diaz #include <drivers/console.h> 1609d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/context_mgmt.h> 1709d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1809d40e0eSAntonio Nino Diaz #include <lib/psci/psci.h> 1909d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 2009d40e0eSAntonio Nino Diaz 2109d40e0eSAntonio Nino Diaz #include <memctrl.h> 2208438e24SVarun Wadekar #include <pmc.h> 2308438e24SVarun Wadekar #include <tegra_def.h> 24322e7c3eSHarvey Hsieh #include <tegra_platform.h> 2508438e24SVarun Wadekar #include <tegra_private.h> 2608438e24SVarun Wadekar 2708438e24SVarun Wadekar extern uint64_t tegra_bl31_phys_base; 2871cb26eaSVarun Wadekar extern uint64_t tegra_sec_entry_point; 295b5928e8SVarun Wadekar extern uint64_t tegra_console_base; 3008438e24SVarun Wadekar 3108438e24SVarun Wadekar /* 32a9e0260cSVignesh Radhakrishnan * tegra_fake_system_suspend acts as a boolean var controlling whether 33a9e0260cSVignesh Radhakrishnan * we are going to take fake system suspend code or normal system suspend code 34a9e0260cSVignesh Radhakrishnan * path. This variable is set inside the sip call handlers,when the kernel 35a9e0260cSVignesh Radhakrishnan * requests a SIP call to set the suspend debug flags. 36a9e0260cSVignesh Radhakrishnan */ 37a9e0260cSVignesh Radhakrishnan uint8_t tegra_fake_system_suspend; 38a9e0260cSVignesh Radhakrishnan 39a9e0260cSVignesh Radhakrishnan /* 4008438e24SVarun Wadekar * The following platform setup functions are weakly defined. They 4108438e24SVarun Wadekar * provide typical implementations that will be overridden by a SoC. 4208438e24SVarun Wadekar */ 43cb95a19aSVarun Wadekar #pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early 440887026eSVarun Wadekar #pragma weak tegra_soc_cpu_standby 4571cb26eaSVarun Wadekar #pragma weak tegra_soc_pwr_domain_suspend 4671cb26eaSVarun Wadekar #pragma weak tegra_soc_pwr_domain_on 4771cb26eaSVarun Wadekar #pragma weak tegra_soc_pwr_domain_off 4871cb26eaSVarun Wadekar #pragma weak tegra_soc_pwr_domain_on_finish 4926c0d9b2SVarun Wadekar #pragma weak tegra_soc_pwr_domain_power_down_wfi 503b40f993SVarun Wadekar #pragma weak tegra_soc_prepare_system_reset 5131a4957cSVarun Wadekar #pragma weak tegra_soc_prepare_system_off 52a7cd0953SVarun Wadekar #pragma weak tegra_soc_get_target_pwr_state 5308438e24SVarun Wadekar 54b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 55cb95a19aSVarun Wadekar { 56cb95a19aSVarun Wadekar return PSCI_E_NOT_SUPPORTED; 57cb95a19aSVarun Wadekar } 58cb95a19aSVarun Wadekar 590887026eSVarun Wadekar int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) 600887026eSVarun Wadekar { 610887026eSVarun Wadekar (void)cpu_state; 620887026eSVarun Wadekar return PSCI_E_SUCCESS; 630887026eSVarun Wadekar } 640887026eSVarun Wadekar 65b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 6608438e24SVarun Wadekar { 67b36aea5aSAnthony Zhou (void)target_state; 6808438e24SVarun Wadekar return PSCI_E_NOT_SUPPORTED; 6908438e24SVarun Wadekar } 7008438e24SVarun Wadekar 71b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) 7208438e24SVarun Wadekar { 73b36aea5aSAnthony Zhou (void)mpidr; 7408438e24SVarun Wadekar return PSCI_E_SUCCESS; 7508438e24SVarun Wadekar } 7608438e24SVarun Wadekar 77b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 7808438e24SVarun Wadekar { 79b36aea5aSAnthony Zhou (void)target_state; 8008438e24SVarun Wadekar return PSCI_E_SUCCESS; 8108438e24SVarun Wadekar } 8208438e24SVarun Wadekar 83b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 8408438e24SVarun Wadekar { 85b36aea5aSAnthony Zhou (void)target_state; 8608438e24SVarun Wadekar return PSCI_E_SUCCESS; 8708438e24SVarun Wadekar } 8808438e24SVarun Wadekar 89b36aea5aSAnthony Zhou int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 9026c0d9b2SVarun Wadekar { 91b36aea5aSAnthony Zhou (void)target_state; 9226c0d9b2SVarun Wadekar return PSCI_E_SUCCESS; 9326c0d9b2SVarun Wadekar } 9426c0d9b2SVarun Wadekar 95b36aea5aSAnthony Zhou int32_t tegra_soc_prepare_system_reset(void) 963b40f993SVarun Wadekar { 973b40f993SVarun Wadekar return PSCI_E_SUCCESS; 983b40f993SVarun Wadekar } 993b40f993SVarun Wadekar 10031a4957cSVarun Wadekar __dead2 void tegra_soc_prepare_system_off(void) 10131a4957cSVarun Wadekar { 10231a4957cSVarun Wadekar ERROR("Tegra System Off: operation not handled.\n"); 10331a4957cSVarun Wadekar panic(); 10431a4957cSVarun Wadekar } 10531a4957cSVarun Wadekar 106b36aea5aSAnthony Zhou plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, 107a7cd0953SVarun Wadekar const plat_local_state_t *states, 108b36aea5aSAnthony Zhou uint32_t ncpu) 109a7cd0953SVarun Wadekar { 1108539f45dSVarun Wadekar plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; 111b36aea5aSAnthony Zhou uint32_t num_cpu = ncpu; 112b36aea5aSAnthony Zhou const plat_local_state_t *local_state = states; 113b36aea5aSAnthony Zhou 114b36aea5aSAnthony Zhou (void)lvl; 115a7cd0953SVarun Wadekar 1164c994002SAnthony Zhou assert(ncpu != 0U); 117a7cd0953SVarun Wadekar 118a7cd0953SVarun Wadekar do { 119b36aea5aSAnthony Zhou temp = *local_state; 120b36aea5aSAnthony Zhou if ((temp < target)) { 121a7cd0953SVarun Wadekar target = temp; 122b36aea5aSAnthony Zhou } 123b36aea5aSAnthony Zhou --num_cpu; 124b36aea5aSAnthony Zhou local_state++; 125b36aea5aSAnthony Zhou } while (num_cpu != 0U); 126a7cd0953SVarun Wadekar 127a7cd0953SVarun Wadekar return target; 128a7cd0953SVarun Wadekar } 129a7cd0953SVarun Wadekar 13008438e24SVarun Wadekar /******************************************************************************* 13171cb26eaSVarun Wadekar * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` 13271cb26eaSVarun Wadekar * call to get the `power_state` parameter. This allows the platform to encode 13371cb26eaSVarun Wadekar * the appropriate State-ID field within the `power_state` parameter which can 13471cb26eaSVarun Wadekar * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 13508438e24SVarun Wadekar ******************************************************************************/ 13671cb26eaSVarun Wadekar void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) 13708438e24SVarun Wadekar { 138a7cd0953SVarun Wadekar /* all affinities use system suspend state id */ 139b36aea5aSAnthony Zhou for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { 140a7cd0953SVarun Wadekar req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN; 14108438e24SVarun Wadekar } 142b36aea5aSAnthony Zhou } 14308438e24SVarun Wadekar 14408438e24SVarun Wadekar /******************************************************************************* 14508438e24SVarun Wadekar * Handler called when an affinity instance is about to enter standby. 14608438e24SVarun Wadekar ******************************************************************************/ 14771cb26eaSVarun Wadekar void tegra_cpu_standby(plat_local_state_t cpu_state) 14808438e24SVarun Wadekar { 14907faf4d8SVignesh Radhakrishnan u_register_t saved_scr_el3; 15007faf4d8SVignesh Radhakrishnan 151b36aea5aSAnthony Zhou (void)cpu_state; 152b36aea5aSAnthony Zhou 1530887026eSVarun Wadekar /* Tegra SoC specific handler */ 1540887026eSVarun Wadekar if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) 1550887026eSVarun Wadekar ERROR("%s failed\n", __func__); 1560887026eSVarun Wadekar 15707faf4d8SVignesh Radhakrishnan saved_scr_el3 = read_scr_el3(); 15807faf4d8SVignesh Radhakrishnan 15907faf4d8SVignesh Radhakrishnan /* 16007faf4d8SVignesh Radhakrishnan * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the 16107faf4d8SVignesh Radhakrishnan * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1', 16207faf4d8SVignesh Radhakrishnan * irrespective of the value of the PSTATE.I bit value. 16307faf4d8SVignesh Radhakrishnan */ 16407faf4d8SVignesh Radhakrishnan write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT); 16507faf4d8SVignesh Radhakrishnan 16608438e24SVarun Wadekar /* 16708438e24SVarun Wadekar * Enter standby state 16807faf4d8SVignesh Radhakrishnan * 16907faf4d8SVignesh Radhakrishnan * dsb & isb is good practice before using wfi to enter low power states 17008438e24SVarun Wadekar */ 17108438e24SVarun Wadekar dsb(); 17207faf4d8SVignesh Radhakrishnan isb(); 17308438e24SVarun Wadekar wfi(); 17407faf4d8SVignesh Radhakrishnan 17507faf4d8SVignesh Radhakrishnan /* 17607faf4d8SVignesh Radhakrishnan * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3 17707faf4d8SVignesh Radhakrishnan * handling any further interrupts 17807faf4d8SVignesh Radhakrishnan */ 17907faf4d8SVignesh Radhakrishnan write_scr_el3(saved_scr_el3); 18008438e24SVarun Wadekar } 18108438e24SVarun Wadekar 18208438e24SVarun Wadekar /******************************************************************************* 18308438e24SVarun Wadekar * Handler called when an affinity instance is about to be turned on. The 18408438e24SVarun Wadekar * level and mpidr determine the affinity instance. 18508438e24SVarun Wadekar ******************************************************************************/ 186b36aea5aSAnthony Zhou int32_t tegra_pwr_domain_on(u_register_t mpidr) 18708438e24SVarun Wadekar { 18871cb26eaSVarun Wadekar return tegra_soc_pwr_domain_on(mpidr); 18908438e24SVarun Wadekar } 19008438e24SVarun Wadekar 19108438e24SVarun Wadekar /******************************************************************************* 19271cb26eaSVarun Wadekar * Handler called when a power domain is about to be turned off. The 19371cb26eaSVarun Wadekar * target_state encodes the power state that each level should transition to. 19408438e24SVarun Wadekar ******************************************************************************/ 19571cb26eaSVarun Wadekar void tegra_pwr_domain_off(const psci_power_state_t *target_state) 19608438e24SVarun Wadekar { 197b36aea5aSAnthony Zhou (void)tegra_soc_pwr_domain_off(target_state); 19808438e24SVarun Wadekar } 19908438e24SVarun Wadekar 20008438e24SVarun Wadekar /******************************************************************************* 20126c0d9b2SVarun Wadekar * Handler called when a power domain is about to be suspended. The 20271cb26eaSVarun Wadekar * target_state encodes the power state that each level should transition to. 203cb95a19aSVarun Wadekar * This handler is called with SMP and data cache enabled, when 204cb95a19aSVarun Wadekar * HW_ASSISTED_COHERENCY = 0 205cb95a19aSVarun Wadekar ******************************************************************************/ 206cb95a19aSVarun Wadekar void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 207cb95a19aSVarun Wadekar { 208cb95a19aSVarun Wadekar tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 209cb95a19aSVarun Wadekar } 210cb95a19aSVarun Wadekar 211cb95a19aSVarun Wadekar /******************************************************************************* 212cb95a19aSVarun Wadekar * Handler called when a power domain is about to be suspended. The 213cb95a19aSVarun Wadekar * target_state encodes the power state that each level should transition to. 21408438e24SVarun Wadekar ******************************************************************************/ 21571cb26eaSVarun Wadekar void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 21608438e24SVarun Wadekar { 217b36aea5aSAnthony Zhou (void)tegra_soc_pwr_domain_suspend(target_state); 21808438e24SVarun Wadekar 2195b5928e8SVarun Wadekar /* Disable console if we are entering deep sleep. */ 2205b5928e8SVarun Wadekar if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 221b36aea5aSAnthony Zhou PSTATE_ID_SOC_POWERDN) { 222b36aea5aSAnthony Zhou (void)console_uninit(); 223b36aea5aSAnthony Zhou } 2245b5928e8SVarun Wadekar 22508438e24SVarun Wadekar /* disable GICC */ 22608438e24SVarun Wadekar tegra_gic_cpuif_deactivate(); 22708438e24SVarun Wadekar } 22808438e24SVarun Wadekar 22908438e24SVarun Wadekar /******************************************************************************* 23026c0d9b2SVarun Wadekar * Handler called at the end of the power domain suspend sequence. The 23126c0d9b2SVarun Wadekar * target_state encodes the power state that each level should transition to. 23226c0d9b2SVarun Wadekar ******************************************************************************/ 23326c0d9b2SVarun Wadekar __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 23426c0d9b2SVarun Wadekar *target_state) 23526c0d9b2SVarun Wadekar { 236a9e0260cSVignesh Radhakrishnan uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 237a9e0260cSVignesh Radhakrishnan uint64_t rmr_el3 = 0; 238a9e0260cSVignesh Radhakrishnan 23926c0d9b2SVarun Wadekar /* call the chip's power down handler */ 240b36aea5aSAnthony Zhou (void)tegra_soc_pwr_domain_power_down_wfi(target_state); 24126c0d9b2SVarun Wadekar 242a9e0260cSVignesh Radhakrishnan /* 243a9e0260cSVignesh Radhakrishnan * If we are in fake system suspend mode, ensure we start doing 244a9e0260cSVignesh Radhakrishnan * procedures that help in looping back towards system suspend exit 245a9e0260cSVignesh Radhakrishnan * instead of calling WFI by requesting a warm reset. 246a9e0260cSVignesh Radhakrishnan * Else, just call WFI to enter low power state. 247a9e0260cSVignesh Radhakrishnan */ 248a9e0260cSVignesh Radhakrishnan if ((tegra_fake_system_suspend != 0U) && 249a9e0260cSVignesh Radhakrishnan (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) { 250a9e0260cSVignesh Radhakrishnan 251a9e0260cSVignesh Radhakrishnan /* warm reboot */ 252a9e0260cSVignesh Radhakrishnan rmr_el3 = read_rmr_el3(); 253a9e0260cSVignesh Radhakrishnan write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); 254a9e0260cSVignesh Radhakrishnan 255a9e0260cSVignesh Radhakrishnan } else { 25626c0d9b2SVarun Wadekar /* enter power down state */ 25726c0d9b2SVarun Wadekar wfi(); 258a9e0260cSVignesh Radhakrishnan } 25926c0d9b2SVarun Wadekar 26026c0d9b2SVarun Wadekar /* we can never reach here */ 26126c0d9b2SVarun Wadekar panic(); 26226c0d9b2SVarun Wadekar } 26326c0d9b2SVarun Wadekar 26426c0d9b2SVarun Wadekar /******************************************************************************* 26571cb26eaSVarun Wadekar * Handler called when a power domain has just been powered on after 26671cb26eaSVarun Wadekar * being turned off earlier. The target_state encodes the low power state that 26771cb26eaSVarun Wadekar * each level has woken up from. 26808438e24SVarun Wadekar ******************************************************************************/ 26971cb26eaSVarun Wadekar void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 27008438e24SVarun Wadekar { 271b36aea5aSAnthony Zhou const plat_params_from_bl2_t *plat_params; 272322e7c3eSHarvey Hsieh uint32_t console_clock; 27308438e24SVarun Wadekar 27408438e24SVarun Wadekar /* 27508438e24SVarun Wadekar * Initialize the GIC cpu and distributor interfaces 27608438e24SVarun Wadekar */ 277*500fc9e1SVarun Wadekar tegra_gic_init(); 27808438e24SVarun Wadekar 27908438e24SVarun Wadekar /* 28008438e24SVarun Wadekar * Check if we are exiting from deep sleep. 28108438e24SVarun Wadekar */ 28271cb26eaSVarun Wadekar if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 28371cb26eaSVarun Wadekar PSTATE_ID_SOC_POWERDN) { 28408438e24SVarun Wadekar 285322e7c3eSHarvey Hsieh /* 286322e7c3eSHarvey Hsieh * Reference clock used by the FPGAs is a lot slower. 287322e7c3eSHarvey Hsieh */ 288b36aea5aSAnthony Zhou if (tegra_platform_is_fpga()) { 289322e7c3eSHarvey Hsieh console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; 290322e7c3eSHarvey Hsieh } else { 291322e7c3eSHarvey Hsieh console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; 292322e7c3eSHarvey Hsieh } 293322e7c3eSHarvey Hsieh 2945b5928e8SVarun Wadekar /* Initialize the runtime console */ 295b36aea5aSAnthony Zhou if (tegra_console_base != 0ULL) { 296b36aea5aSAnthony Zhou (void)console_init(tegra_console_base, console_clock, 2975b5928e8SVarun Wadekar TEGRA_CONSOLE_BAUDRATE); 2989b514f83SDamon Duan } 2995b5928e8SVarun Wadekar 30008438e24SVarun Wadekar /* 301102e4087SVarun Wadekar * Restore Memory Controller settings as it loses state 302102e4087SVarun Wadekar * during system suspend. 30308438e24SVarun Wadekar */ 304102e4087SVarun Wadekar tegra_memctrl_restore_settings(); 30508438e24SVarun Wadekar 30608438e24SVarun Wadekar /* 30708438e24SVarun Wadekar * Security configuration to allow DRAM/device access. 30808438e24SVarun Wadekar */ 30908438e24SVarun Wadekar plat_params = bl31_get_plat_params(); 310e0d4158cSVarun Wadekar tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 311b36aea5aSAnthony Zhou (uint32_t)plat_params->tzdram_size); 312207680c6SVarun Wadekar 313207680c6SVarun Wadekar /* 314207680c6SVarun Wadekar * Set up the TZRAM memory aperture to allow only secure world 315207680c6SVarun Wadekar * access 316207680c6SVarun Wadekar */ 317207680c6SVarun Wadekar tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); 31808438e24SVarun Wadekar } 31908438e24SVarun Wadekar 32008438e24SVarun Wadekar /* 32108438e24SVarun Wadekar * Reset hardware settings. 32208438e24SVarun Wadekar */ 323b36aea5aSAnthony Zhou (void)tegra_soc_pwr_domain_on_finish(target_state); 32408438e24SVarun Wadekar } 32508438e24SVarun Wadekar 32608438e24SVarun Wadekar /******************************************************************************* 32771cb26eaSVarun Wadekar * Handler called when a power domain has just been powered on after 32871cb26eaSVarun Wadekar * having been suspended earlier. The target_state encodes the low power state 32971cb26eaSVarun Wadekar * that each level has woken up from. 33008438e24SVarun Wadekar ******************************************************************************/ 33171cb26eaSVarun Wadekar void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 33208438e24SVarun Wadekar { 33371cb26eaSVarun Wadekar tegra_pwr_domain_on_finish(target_state); 33408438e24SVarun Wadekar } 33508438e24SVarun Wadekar 33608438e24SVarun Wadekar /******************************************************************************* 33708438e24SVarun Wadekar * Handler called when the system wants to be powered off 33808438e24SVarun Wadekar ******************************************************************************/ 33908438e24SVarun Wadekar __dead2 void tegra_system_off(void) 34008438e24SVarun Wadekar { 34131a4957cSVarun Wadekar INFO("Powering down system...\n"); 34231a4957cSVarun Wadekar 34331a4957cSVarun Wadekar tegra_soc_prepare_system_off(); 34408438e24SVarun Wadekar } 34508438e24SVarun Wadekar 34608438e24SVarun Wadekar /******************************************************************************* 34708438e24SVarun Wadekar * Handler called when the system wants to be restarted. 34808438e24SVarun Wadekar ******************************************************************************/ 34908438e24SVarun Wadekar __dead2 void tegra_system_reset(void) 35008438e24SVarun Wadekar { 35131a4957cSVarun Wadekar INFO("Restarting system...\n"); 35231a4957cSVarun Wadekar 3533b40f993SVarun Wadekar /* per-SoC system reset handler */ 354b36aea5aSAnthony Zhou (void)tegra_soc_prepare_system_reset(); 3553b40f993SVarun Wadekar 35608438e24SVarun Wadekar /* 35708438e24SVarun Wadekar * Program the PMC in order to restart the system. 35808438e24SVarun Wadekar */ 35908438e24SVarun Wadekar tegra_pmc_system_reset(); 36008438e24SVarun Wadekar } 36108438e24SVarun Wadekar 36208438e24SVarun Wadekar /******************************************************************************* 36371cb26eaSVarun Wadekar * Handler called to check the validity of the power state parameter. 36471cb26eaSVarun Wadekar ******************************************************************************/ 365b36aea5aSAnthony Zhou int32_t tegra_validate_power_state(uint32_t power_state, 36671cb26eaSVarun Wadekar psci_power_state_t *req_state) 36771cb26eaSVarun Wadekar { 3684c994002SAnthony Zhou assert(req_state != NULL); 36971cb26eaSVarun Wadekar 37071cb26eaSVarun Wadekar return tegra_soc_validate_power_state(power_state, req_state); 37171cb26eaSVarun Wadekar } 37271cb26eaSVarun Wadekar 37371cb26eaSVarun Wadekar /******************************************************************************* 37471cb26eaSVarun Wadekar * Platform handler called to check the validity of the non secure entrypoint. 37571cb26eaSVarun Wadekar ******************************************************************************/ 376b36aea5aSAnthony Zhou int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 37771cb26eaSVarun Wadekar { 378b36aea5aSAnthony Zhou int32_t ret = PSCI_E_INVALID_ADDRESS; 379b36aea5aSAnthony Zhou 38071cb26eaSVarun Wadekar /* 38171cb26eaSVarun Wadekar * Check if the non secure entrypoint lies within the non 38271cb26eaSVarun Wadekar * secure DRAM. 38371cb26eaSVarun Wadekar */ 384b36aea5aSAnthony Zhou if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 385b36aea5aSAnthony Zhou ret = PSCI_E_SUCCESS; 386b36aea5aSAnthony Zhou } 38771cb26eaSVarun Wadekar 388b36aea5aSAnthony Zhou return ret; 38971cb26eaSVarun Wadekar } 39071cb26eaSVarun Wadekar 39171cb26eaSVarun Wadekar /******************************************************************************* 39208438e24SVarun Wadekar * Export the platform handlers to enable psci to invoke them 39308438e24SVarun Wadekar ******************************************************************************/ 39471cb26eaSVarun Wadekar static const plat_psci_ops_t tegra_plat_psci_ops = { 39571cb26eaSVarun Wadekar .cpu_standby = tegra_cpu_standby, 39671cb26eaSVarun Wadekar .pwr_domain_on = tegra_pwr_domain_on, 39771cb26eaSVarun Wadekar .pwr_domain_off = tegra_pwr_domain_off, 398cb95a19aSVarun Wadekar .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 39971cb26eaSVarun Wadekar .pwr_domain_suspend = tegra_pwr_domain_suspend, 40071cb26eaSVarun Wadekar .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 40171cb26eaSVarun Wadekar .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 40226c0d9b2SVarun Wadekar .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 40308438e24SVarun Wadekar .system_off = tegra_system_off, 40408438e24SVarun Wadekar .system_reset = tegra_system_reset, 40594c672e7SVarun Wadekar .validate_power_state = tegra_validate_power_state, 40671cb26eaSVarun Wadekar .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 40771cb26eaSVarun Wadekar .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 40808438e24SVarun Wadekar }; 40908438e24SVarun Wadekar 41008438e24SVarun Wadekar /******************************************************************************* 41171cb26eaSVarun Wadekar * Export the platform specific power ops and initialize Power Controller 41208438e24SVarun Wadekar ******************************************************************************/ 41371cb26eaSVarun Wadekar int plat_setup_psci_ops(uintptr_t sec_entrypoint, 41471cb26eaSVarun Wadekar const plat_psci_ops_t **psci_ops) 41508438e24SVarun Wadekar { 41671cb26eaSVarun Wadekar psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 41771cb26eaSVarun Wadekar 41871cb26eaSVarun Wadekar /* 41971cb26eaSVarun Wadekar * Flush entrypoint variable to PoC since it will be 42071cb26eaSVarun Wadekar * accessed after a reset with the caches turned off. 42171cb26eaSVarun Wadekar */ 42271cb26eaSVarun Wadekar tegra_sec_entry_point = sec_entrypoint; 42371cb26eaSVarun Wadekar flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 42471cb26eaSVarun Wadekar 42508438e24SVarun Wadekar /* 42608438e24SVarun Wadekar * Reset hardware settings. 42708438e24SVarun Wadekar */ 428b36aea5aSAnthony Zhou (void)tegra_soc_pwr_domain_on_finish(&target_state); 42908438e24SVarun Wadekar 43008438e24SVarun Wadekar /* 43171cb26eaSVarun Wadekar * Initialize PSCI ops struct 43208438e24SVarun Wadekar */ 43371cb26eaSVarun Wadekar *psci_ops = &tegra_plat_psci_ops; 43408438e24SVarun Wadekar 43508438e24SVarun Wadekar return 0; 43608438e24SVarun Wadekar } 4372693f1dbSVarun Wadekar 4382693f1dbSVarun Wadekar /******************************************************************************* 4392693f1dbSVarun Wadekar * Platform handler to calculate the proper target power level at the 4402693f1dbSVarun Wadekar * specified affinity level 4412693f1dbSVarun Wadekar ******************************************************************************/ 4422693f1dbSVarun Wadekar plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 4432693f1dbSVarun Wadekar const plat_local_state_t *states, 4442693f1dbSVarun Wadekar unsigned int ncpu) 4452693f1dbSVarun Wadekar { 446a7cd0953SVarun Wadekar return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 4472693f1dbSVarun Wadekar } 448