platform: ace: Add pm notifiers to support Zephyr's D3 transition

During PowerOff (D3) transition Zephyr Power Manager must have
a pointer in IMR to save the LP/HPSRAM memory before
powering off.

As zephyr has no access to IMR heap, the memory must
be allocated by SOF

Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
This commit is contained in:
Marcin Szkudlinski 2022-11-16 15:21:32 +01:00 committed by Kai Vehmanen
parent ee6eb1b169
commit 4e8040c232
3 changed files with 53 additions and 1 deletions

View File

@ -76,7 +76,7 @@ int platform_boot_complete(uint32_t boot_message)
} }
static struct pm_notifier pm_state_notifier = { static struct pm_notifier pm_state_notifier = {
.state_entry = NULL, .state_entry = cpu_notify_state_entry,
.state_exit = cpu_notify_state_exit, .state_exit = cpu_notify_state_exit,
}; };

View File

@ -26,6 +26,8 @@
#include <zephyr/pm/pm.h> #include <zephyr/pm/pm.h>
void cpu_notify_state_entry(enum pm_state state);
void cpu_notify_state_exit(enum pm_state state); void cpu_notify_state_exit(enum pm_state state);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */

View File

@ -13,10 +13,14 @@
#include <sof/init.h> #include <sof/init.h>
#include <sof/lib/cpu.h> #include <sof/lib/cpu.h>
#include <sof/lib/pm_runtime.h> #include <sof/lib/pm_runtime.h>
#include <ipc/topology.h>
#include <rtos/alloc.h>
/* Zephyr includes */ /* Zephyr includes */
#include <version.h> #include <version.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/mm/mm_drv_intel_adsp_mtl_tlb.h>
#if CONFIG_MULTICORE && CONFIG_SMP #if CONFIG_MULTICORE && CONFIG_SMP
@ -64,6 +68,42 @@ LOG_MODULE_DECLARE(zephyr, CONFIG_SOF_LOG_LEVEL);
extern struct tr_ctx zephyr_tr; extern struct tr_ctx zephyr_tr;
/* address where zephyr PM will save memory during D3 transition */
#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
extern void *global_imr_ram_storage;
#endif
void cpu_notify_state_entry(enum pm_state state)
{
if (!cpu_is_primary(arch_proc_id()))
return;
if (state == PM_STATE_SOFT_OFF) {
#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
size_t storage_buffer_size;
/* allocate IMR global_imr_ram_storage */
const struct device *tlb_dev = DEVICE_DT_GET(DT_NODELABEL(tlb));
__ASSERT_NO_MSG(tlb_dev);
const struct intel_adsp_tlb_api *tlb_api =
(struct intel_adsp_tlb_api *)tlb_dev->api;
/* get HPSRAM storage buffer size */
storage_buffer_size = tlb_api->get_storage_size();
/* add space for LPSRAM */
storage_buffer_size += LP_SRAM_SIZE;
/* allocate IMR buffer and store it in the global pointer */
global_imr_ram_storage = rmalloc(SOF_MEM_ZONE_SYS_RUNTIME,
0,
SOF_MEM_CAPS_L3,
storage_buffer_size);
#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */
}
}
/* notifier called after every power state transition */ /* notifier called after every power state transition */
void cpu_notify_state_exit(enum pm_state state) void cpu_notify_state_exit(enum pm_state state)
{ {
@ -74,8 +114,18 @@ void cpu_notify_state_exit(enum pm_state state)
* state and is back in the Idle thread. * state and is back in the Idle thread.
*/ */
atomic_set(&ready_flag, 1); atomic_set(&ready_flag, 1);
return;
} }
#endif #endif
#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
/* free global_imr_ram_storage */
rfree(global_imr_ram_storage);
global_imr_ram_storage = NULL;
/* send FW Ready message */
platform_boot_complete(0);
#endif
} }
} }