diff --git a/plat/ti/k3/board/lite/include/board_def.h b/plat/ti/k3/board/lite/include/board_def.h index 18b7f4206..fd4e5b1c4 100644 --- a/plat/ti/k3/board/lite/include/board_def.h +++ b/plat/ti/k3/board/lite/include/board_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -33,7 +33,7 @@ * defined as default for our platform. */ #define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */ -#define SEC_SRAM_SIZE UL(0x0001c000) /* 112k */ +#define SEC_SRAM_SIZE UL(0x00020000) /* 128k */ #define PLAT_MAX_OFF_STATE U(2) #define PLAT_MAX_RET_STATE U(1) diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c index 2c3313c43..2cbfa3d6e 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -2,7 +2,7 @@ * Texas Instruments System Control Interface Driver * Based on Linux and U-Boot implementation * - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ * * SPDX-License-Identifier: BSD-3-Clause */ @@ -1663,6 +1663,57 @@ int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, return 0; } +/** + * ti_sci_enter_sleep - Command to initiate system transition into suspend. + * + * @proc_id: Processor ID. + * @mode: Low power mode to enter. + * @core_resume_addr: Address that core should be + * resumed from after low power transition. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_enter_sleep(uint8_t proc_id, + uint8_t mode, + uint64_t core_resume_addr) +{ + struct ti_sci_msg_req_enter_sleep req; + struct ti_sci_msg_hdr *hdr; + struct k3_sec_proxy_msg tx_message; + int ret; + + /* Ensure we have sane transfer size */ + if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE) { + return -ERANGE; + } + + hdr = (struct ti_sci_msg_hdr *)&req; + hdr->seq = ++message_sequence; + hdr->type = TI_SCI_MSG_ENTER_SLEEP; + hdr->host = TI_SCI_HOST_ID; + /* Setup with NORESPONSE flag to keep response queue clean */ + hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE; + + req.processor_id = proc_id; + req.mode = mode; + req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK; + req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + + tx_message.buf = (uint8_t *)&req; + tx_message.len = sizeof(req); + + /* Send message */ + ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message); + if (ret != 0) { + ERROR("Message sending failed (%d)\n", ret); + return ret; + } + + /* Return without waiting for response */ + return 0; +} + /** * ti_sci_init() - Basic initialization * diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h index c7b09b30d..06944a74b 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h @@ -2,7 +2,7 @@ * Texas Instruments System Control Interface API * Based on Linux and U-Boot implementation * - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ * * SPDX-License-Identifier: BSD-3-Clause */ @@ -206,6 +206,22 @@ int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, uint32_t status_flags_1_clr_all_wait, uint32_t status_flags_1_clr_any_wait); +/** + * System Low Power Operations + * + * - ti_sci_enter_sleep - Command to initiate system transition into suspend. + * @proc_id: Processor ID. + * @mode: Low power mode to enter. + * @core_resume_addr: Address that core should be resumed from + * after low power transition. + * + * NOTE: for all these functions, the following are generic in nature: + * Returns 0 for successful request, else returns corresponding error message. + */ +int ti_sci_enter_sleep(uint8_t proc_id, + uint8_t mode, + uint64_t core_resume_addr); + /** * ti_sci_init() - Basic initialization * diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h index 310bf459d..d220612ee 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -5,7 +5,7 @@ * The system works in a message response protocol * See: http://processors.wiki.ti.com/index.php/TISCI for details * - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ * * SPDX-License-Identifier: BSD-3-Clause */ @@ -28,6 +28,9 @@ #define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 #define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 +/* Low Power Mode Requests */ +#define TI_SCI_MSG_ENTER_SLEEP 0x0301 + /* Clock requests */ #define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 #define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 @@ -706,4 +709,26 @@ struct ti_sci_msg_req_wait_proc_boot_status { uint32_t status_flags_1_clr_any_wait; } __packed; +/** + * struct ti_sci_msg_req_enter_sleep - Request for TI_SCI_MSG_ENTER_SLEEP. + * + * @hdr Generic Header + * @mode Low power mode to enter. + * @proc_id Processor id to be restored. + * @core_resume_lo Low 32-bits of physical pointer to address for core + * to begin execution upon resume. + * @core_resume_hi High 32-bits of physical pointer to address for core + * to begin execution upon resume. + * + * This message is to be sent after TI_SCI_MSG_PREPARE_SLEEP is sent from OS + * and is what actually triggers entry into the specified low power mode. + */ +struct ti_sci_msg_req_enter_sleep { + struct ti_sci_msg_hdr hdr; + uint8_t mode; + uint8_t processor_id; + uint32_t core_resume_lo; + uint32_t core_resume_hi; +} __packed; + #endif /* TI_SCI_PROTOCOL_H */ diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c index 1932eaae5..019982261 100644 --- a/plat/ti/k3/common/k3_gicv3.c +++ b/plat/ti/k3/common/k3_gicv3.c @@ -19,6 +19,11 @@ /* The GICv3 driver only needs to be initialized in EL3 */ uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; +#if K3_PM_SYSTEM_SUSPEND +static gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT]; +static gicv3_dist_ctx_t dist_ctx; +#endif + static const interrupt_prop_t k3_interrupt_props[] = { PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) @@ -88,3 +93,21 @@ void k3_gic_pcpu_init(void) { gicv3_rdistif_init(plat_my_core_pos()); } + +#if K3_PM_SYSTEM_SUSPEND +void k3_gic_save_context(void) +{ + for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) { + gicv3_rdistif_save(i, &rdist_ctx[i]); + } + gicv3_distif_save(&dist_ctx); +} + +void k3_gic_restore_context(void) +{ + gicv3_distif_init_restore(&dist_ctx); + for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) { + gicv3_rdistif_init_restore(i, &rdist_ctx[i]); + } +} +#endif diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c index 050074007..6febbc6d3 100644 --- a/plat/ti/k3/common/k3_psci.c +++ b/plat/ti/k3/common/k3_psci.c @@ -234,11 +234,50 @@ static int k3_validate_ns_entrypoint(uintptr_t entrypoint) return PSCI_E_SUCCESS; } +#if K3_PM_SYSTEM_SUSPEND +static void k3_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + unsigned int core, proc_id; + + core = plat_my_core_pos(); + proc_id = PLAT_PROC_START_ID + core; + + /* Prevent interrupts from spuriously waking up this cpu */ + k3_gic_cpuif_disable(); + k3_gic_save_context(); + + k3_pwr_domain_off(target_state); + + ti_sci_enter_sleep(proc_id, 0, k3_sec_entrypoint); +} + +static void k3_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + k3_gic_restore_context(); + k3_gic_cpuif_enable(); +} + +static void k3_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int i; + + /* CPU & cluster off, system in retention */ + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } +} +#endif + static const plat_psci_ops_t k3_plat_psci_ops = { .cpu_standby = k3_cpu_standby, .pwr_domain_on = k3_pwr_domain_on, .pwr_domain_off = k3_pwr_domain_off, .pwr_domain_on_finish = k3_pwr_domain_on_finish, +#if K3_PM_SYSTEM_SUSPEND + .pwr_domain_suspend = k3_pwr_domain_suspend, + .pwr_domain_suspend_finish = k3_pwr_domain_suspend_finish, + .get_sys_suspend_power_state = k3_get_sys_suspend_power_state, +#endif .system_off = k3_system_off, .system_reset = k3_system_reset, .validate_power_state = k3_validate_power_state, diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk index ab7366b7e..e299c30cc 100644 --- a/plat/ti/k3/common/plat_common.mk +++ b/plat/ti/k3/common/plat_common.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -45,6 +45,10 @@ $(eval $(call add_define,K3_USART)) K3_USART_BAUD := 115200 $(eval $(call add_define,K3_USART_BAUD)) +# Enable system suspend modes +K3_PM_SYSTEM_SUSPEND := 0 +$(eval $(call add_define,K3_PM_SYSTEM_SUSPEND)) + # Libraries include lib/xlat_tables_v2/xlat_tables.mk diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h index 2329a16e5..2c68a7518 100644 --- a/plat/ti/k3/include/k3_gicv3.h +++ b/plat/ti/k3/include/k3_gicv3.h @@ -14,5 +14,7 @@ void k3_gic_init(void); void k3_gic_cpuif_enable(void); void k3_gic_cpuif_disable(void); void k3_gic_pcpu_init(void); +void k3_gic_save_context(void); +void k3_gic_restore_context(void); #endif /* K3_GICV3_H */