From 1e47b4af4ad895ccc73bc786762612ffd709d49e Mon Sep 17 00:00:00 2001 From: Lech Betlej Date: Fri, 9 Nov 2018 15:59:26 +0100 Subject: [PATCH] Added SRAM power gating on D3 entry for cAVS 1.8 (i.e. Cannonlake). On D3 entry FW needs to power gate both LP & HP SRAM banks. The power gating is done from code executed from L1 cache. Signed-off-by: Lech Betlej --- src/ipc/cnl-ipc.c | 16 +- src/platform/cannonlake/Makefile.am | 8 +- .../cannonlake/include/platform/Makefile.am | 4 +- .../include/platform/asm_memory_management.h | 112 ++++++++++++++ .../cannonlake/include/platform/platcfg.h | 6 + .../cannonlake/include/platform/pm_runtime.h | 5 + .../cannonlake/include/platform/power_down.h | 43 ++++++ .../cannonlake/include/platform/shim.h | 3 + src/platform/cannonlake/power_down.S | 140 ++++++++++++++++++ src/platform/intel/cavs/pm_runtime.c | 15 +- 10 files changed, 341 insertions(+), 11 deletions(-) create mode 100644 src/platform/cannonlake/include/platform/asm_memory_management.h create mode 100644 src/platform/cannonlake/include/platform/power_down.h create mode 100644 src/platform/cannonlake/power_down.S diff --git a/src/ipc/cnl-ipc.c b/src/ipc/cnl-ipc.c index f14dcaed0..881340a7d 100644 --- a/src/ipc/cnl-ipc.c +++ b/src/ipc/cnl-ipc.c @@ -50,8 +50,14 @@ #include #include #include +//<<<<<<< HEAD #include +//======= +//#include +//#include +#include +//>>>>>>> Added SRAM power gating on D3 entry for cAVS 1.8 (i.e. Cannonlake). extern struct ipc *_ipc; /* test code to check working IRQ */ @@ -139,8 +145,14 @@ done: // TODO: signal audio work to enter D3 in normal context /* are we about to enter D3 ? */ if (iipc->pm_prepare_D3) { - while (1) - wait_for_interrupt(0); +#if defined(CONFIG_CANNONLAKE) + /* no return - memory will be powered off */ + platform_pm_runtime_power_off(); +#else + //TODO: add support for Icelake, consider a spearate file icl-ipc.c + while (1) + wait_for_interrupt(0); +#endif } tracev_ipc("CmD"); diff --git a/src/platform/cannonlake/Makefile.am b/src/platform/cannonlake/Makefile.am index d352a5448..ae75c4895 100644 --- a/src/platform/cannonlake/Makefile.am +++ b/src/platform/cannonlake/Makefile.am @@ -8,7 +8,7 @@ noinst_LTLIBRARIES = libplatform.la libplatform_la_LIBADD = ../intel/cavs/libcavsplatform.la -libplatform_la_SOURCES = +libplatform_la_SOURCES = power_down.S libplatform_la_CFLAGS = \ $(AM_CFLAGS) \ @@ -17,6 +17,12 @@ libplatform_la_CFLAGS = \ $(PLATFORM_INCDIR) \ $(SOF_INCDIR) +libplatform_la_CCASFLAGS = \ + $(ARCH_INCDIR) \ + $(ASFLAGS) \ + $(ARCH_ASFLAGS) \ + $(PLATFORM_INCDIR) + noinst_PROGRAMS = module boot_module module_SOURCES = \ diff --git a/src/platform/cannonlake/include/platform/Makefile.am b/src/platform/cannonlake/include/platform/Makefile.am index 501ed4071..561b30212 100644 --- a/src/platform/cannonlake/include/platform/Makefile.am +++ b/src/platform/cannonlake/include/platform/Makefile.am @@ -10,4 +10,6 @@ noinst_HEADERS = \ platform.h \ pm_runtime.h \ shim.h \ - timer.h + timer.h \ + asm_memory_management.h \ + power_down.h diff --git a/src/platform/cannonlake/include/platform/asm_memory_management.h b/src/platform/cannonlake/include/platform/asm_memory_management.h new file mode 100644 index 000000000..b38f7662d --- /dev/null +++ b/src/platform/cannonlake/include/platform/asm_memory_management.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lech Betlej + */ + +/** + * \file platform/cannonlake/include/platform/asm_memory_management.h + * \brief Macros for power gating memory banks specific for cAVS 1.8 + * \(CannonLake) + * \author Lech Betlej + */ +#ifndef ASM_MEMORY_MANAGEMENT_H +#define ASM_MEMORY_MANAGEMENT_H + +#ifndef ASSEMBLY +#warning "ASSEMBLY macro not defined. Header can't be inluded in C files" +#warning "The file is intended to be includded in assembly files only." +#endif + +#include +#include + +#define MAX_EBB_BANKS_IN_SEGMENT 32 +#define HPSRAM_MASK(seg_idx)\ + ((1 << (PLATFORM_HPSRAM_EBB_COUNT\ + - MAX_EBB_BANKS_IN_SEGMENT * seg_idx)) - 1) +#define LPSRAM_MASK ((1 << PLATFORM_LPSRAM_EBB_COUNT) - 1) +#define MAX_MEMORY_SEGMENTS ((PLATFORM_HPSRAM_EBB_COUNT + \ + MAX_EBB_BANKS_IN_SEGMENT - 1) / MAX_EBB_BANKS_IN_SEGMENT) + +/** + * powers down entire hpsram. on entry lirerals and code for section from + * where this code is executed needs to be placed in memory which is not + * HPSRAM (in case when this code is located in HPSRAM, lock memory in L1$ or + * L1 SRAM) + */ +.macro m_cavs_hpsram_power_down_entire ax, ay, az + //TODO: add LDO control + // SEGMENT #0 + movi \az, SHIM_HSPGCTL(0) + movi \ax, SHIM_HSPGISTS(0) + movi \ay, HPSRAM_MASK(0) + s32i \ay, \ax, 0 + memw +1 : + l32i \ax, \az, 0 + bne \ax, \ay, 1b + + // SEGMENT #1 + movi \az, SHIM_HSPGCTL(1) + movi \ax, SHIM_HSPGISTS(1) + movi \ay, HPSRAM_MASK(1) + s32i \ay, \ax, 0 + memw +1 : + l32i \ax, \az, 0 + bne \ax, \ay, 1b + // TODO: Add LDO control +.endm + +.macro m_cavs_hpsram_power_change segment_index, mask, ax, ay, az + // TODO: Add LDO Control + movi \ax, SHIM_HSPGCTL(\segment_index) + movi \ay, SHIM_HSPGISTS(\segment_index) + s32i \mask, \ax, 0 + memw + // assumed that HDA shared dma buffer will be in LPSRAM +1 : + l32i \ax, \ay, 0 + bne \ax, \mask, 1b + // TODO: Add LDO Control +.endm + +.macro m_cavs_lpsram_power_down_entire ax, ay, az + movi \az, LSPGISTS + movi \ax, LSPGCTL + movi \ay, LPSRAM_MASK + s32i \ay, \ax, 0 + memw + // assumed that HDA shared dma buffer will be in LPSRAM + movi \ax, 4096 +1 : + addi \ax, \ax, -1 + bnez \ax, 1b +.endm + +#endif /* ASM_MEMORY_MANAGEMENT_H */ diff --git a/src/platform/cannonlake/include/platform/platcfg.h b/src/platform/cannonlake/include/platform/platcfg.h index f455ff203..ca5506218 100644 --- a/src/platform/cannonlake/include/platform/platcfg.h +++ b/src/platform/cannonlake/include/platform/platcfg.h @@ -35,6 +35,12 @@ #define PLATFORM_CORE_COUNT 4 +#define PLATFORM_LPSRAM_EBB_COUNT 1 + +#define PLATFORM_HPSRAM_EBB_COUNT 47 + +#define PLATFORM_HPSRAM_SEGMENTS 2 + #define PLATFORM_MASTER_CORE_ID 0 #endif diff --git a/src/platform/cannonlake/include/platform/pm_runtime.h b/src/platform/cannonlake/include/platform/pm_runtime.h index 2158f99a5..236456170 100644 --- a/src/platform/cannonlake/include/platform/pm_runtime.h +++ b/src/platform/cannonlake/include/platform/pm_runtime.h @@ -70,4 +70,9 @@ void platform_pm_runtime_get(enum pm_runtime_context context, uint32_t index, void platform_pm_runtime_put(enum pm_runtime_context context, uint32_t index, uint32_t flags); +/** + * \brief Power gates platform specific hardware resources. + */ +void platform_pm_runtime_power_off(void); + #endif /* __INCLUDE_PLATFORM_PM_RUNTIME__ */ diff --git a/src/platform/cannonlake/include/platform/power_down.h b/src/platform/cannonlake/include/platform/power_down.h new file mode 100644 index 000000000..fcca079f5 --- /dev/null +++ b/src/platform/cannonlake/include/platform/power_down.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lech Betlej + */ +#ifndef CANNONLAKE_INCLUDE_PLATFORM_POWER_DOWN_H +#define CANNONLAKE_INCLUDE_PLATFORM_POWER_DOWN_H + +#include +/** + * Power down procedure. + * Locks its code in L1 cache and shuts down memories. + * @param disable_lpsram flag if LPSRAM is to be disabled (whole) + * @param hpsram_pwrgating_mask pointer to memory segments power gating mask + * (each bit corresponds to one ebb) + * @return nothing returned - this function never quits + */ +void power_down(bool disable_lpsram, uint32_t *hpsram_pwrgating_mask); +#endif /* CANNONLAKE_INCLUDE_PLATFORM_POWER_DOWN_H */ diff --git a/src/platform/cannonlake/include/platform/shim.h b/src/platform/cannonlake/include/platform/shim.h index 6cb819567..4ab246fd1 100644 --- a/src/platform/cannonlake/include/platform/shim.h +++ b/src/platform/cannonlake/include/platform/shim.h @@ -196,6 +196,9 @@ #define HSRMCTL1 0x71D24 #define HSPGISTS1 0x71D28 +#define SHIM_HSPGCTL(x) (HSPGCTL0 + 0x10 * (x)) +#define SHIM_HSPGISTS(x) (HSPGISTS0 + 0x18 * (x)) + #define LSPGCTL 0x71D50 #define LSRMCTL 0x71D54 #define LSPGISTS 0x71D58 diff --git a/src/platform/cannonlake/power_down.S b/src/platform/cannonlake/power_down.S new file mode 100644 index 000000000..cb5a82143 --- /dev/null +++ b/src/platform/cannonlake/power_down.S @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lech Betlej + */ + +/** + * \file platform/apollolake/power_down.S + * \brief Power gating memory banks - implementation specific for Apollolake + * \author Lech Betlej + */ +#include + + .section .text, "ax" + .align 64 +literals: + .literal_position + .global power_down + .type power_down, @function +/** + * Perform power down. + * + * Depending on arguments, memories are switched off. + * A2 - argument for LPSRAM + * A3 - pointer to array containing power gating mask. + *Size of array is determined by MEMORY_SEGMENTS define. + * A4 - platform type + * A5 - response_to_ipc + */ +//TODO: add IPC reply sending before core enters waiti + +#define b_enable_lpsram a2 +#define pu32_hpsram_mask a3 +#define temp_reg0 a6 +#define temp_reg1 a7 +#define temp_reg2 a8 +#define temp_reg3 a9 +#define pfl_reg a15 + + +power_down: + entry sp, 32 + // effectively executes: + // xthal_dcache_region_lock(&literals, 128); + // xthal_dcache_region_lock(&powerdown, 256); + // xthal_dcache_region_lock(&pu32_hpsram_mask, 64); + movi pfl_reg, literals + dpfl pfl_reg, 0 + dpfl pfl_reg, 64 + + movi pfl_reg, power_down + ipfl pfl_reg, 0 + ipfl pfl_reg, 64 + ipfl pfl_reg, 128 + ipfl pfl_reg, 192 + + mov pfl_reg, pu32_hpsram_mask + dpfl pfl_reg, 0 + +_PD_DISABLE_LPSRAM: +/* effectively executes: + * if (b_enable_lpsram){ + * cavs_lpsram_power_down_entire(); + * } + */ + beqz b_enable_lpsram, _PD_DISABLE_HPSRAM + m_cavs_lpsram_power_down_entire temp_reg0, temp_reg1, temp_reg2 + j _PD_DISABLE_HPSRAM + +_PD_DISABLE_HPSRAM: + /* if value in memory pointed by pu32_hpsram_mask = 0 + (hpsram_pwrgating_mask) - do not disable hpsram. */ +beqz pu32_hpsram_mask, _PD_SLEEP + +/* effectively executes: + * for (size_t seg_index = (MAX_MEMORY_SEGMENTS - 1); seg_index >= 0; + * --seg_index) { + * cavs_hpsram_power_change(seg_index, mask[seg_index]); + * } + * where mask is given in pu32_hpsram_mask register + */ + + .set seg_index, MAX_MEMORY_SEGMENTS - 1 + .rept MAX_MEMORY_SEGMENTS + l32i temp_reg0, pu32_hpsram_mask, 4 * seg_index + m_cavs_hpsram_power_change\ + /*segment_index=*/ seg_index,\ + /*mask=*/ temp_reg0,\ + temp_reg1,\ + temp_reg2,\ + temp_reg3 + .set seg_index, seg_index - 1 + .endr + + +//TODO: add LDO Control +//TODO: add sending IPC reply from L1$ locked code + +_PD_SLEEP: +/* effecfively executes: + * xmp_spin() + * waiti 5 + */ + movi temp_reg0, 128 +loop: + addi temp_reg0, temp_reg0, -1 + bnez temp_reg0, loop + + extw + extw + waiti 5 + j _PD_SLEEP + +.size power_down , . - power_down + + diff --git a/src/platform/intel/cavs/pm_runtime.c b/src/platform/intel/cavs/pm_runtime.c index cf64ce688..a8573cb51 100644 --- a/src/platform/intel/cavs/pm_runtime.c +++ b/src/platform/intel/cavs/pm_runtime.c @@ -40,8 +40,8 @@ #include #include -#if defined(CONFIG_APOLLOLAKE) -//TODO: add support or at least stub api for Cannonlake & Icelake +#if defined(CONFIG_APOLLOLAKE) || defined(CONFIG_CANNONLAKE) +//TODO: add support or at least stub api for Icelake based on Cannonlake #include #endif @@ -229,15 +229,16 @@ void platform_pm_runtime_put(enum pm_runtime_context context, uint32_t index, } } -#if defined(CONFIG_APOLLOLAKE) +#if defined(CONFIG_APOLLOLAKE) || defined(CONFIG_CANNONLAKE) void platform_pm_runtime_power_off(void) { - uint32_t hpsram_mask[PLATFORM_HPSRAM_SEGMENTS]; + uint32_t hpsram_mask[PLATFORM_HPSRAM_SEGMENTS], i; //TODO: add LDO control for LP SRAM - set LDO BYPASS & LDO ON - //TODO: mask to be used in the future for run-time power management of - //SRAM banks + //TODO: hpsram_mask to be used in the future for run-time + //power management of SRAM banks i.e use. HPSRAM_MASK() macro /* power down entire HPSRAM */ - hpsram_mask[0] = 0x1; + for (i = 0; i < PLATFORM_HPSRAM_SEGMENTS; i++) + hpsram_mask[i] = UINT32_MAX; power_down(true, hpsram_mask); }