From bb2663653d542ea18333d2e9bb7473d10a40da2f Mon Sep 17 00:00:00 2001 From: Lech Betlej Date: Fri, 23 Nov 2018 14:51:05 +0100 Subject: [PATCH] Power up only subset of HP SRAM banks on FW init (CannonLake) In order to reduce power consumption in runtime only subset of HP SRAM banks have to be powered. The PR covers 2 aspects: 1. Changed memory map to move stack up by 21 memory banks. Buffer heap size was reduced from ~2.3MB to ~0.9MB. 2. Changed HP SRAM initialization to power up only needed banks and properly check HW response. Signed-off-by: Lech Betlej --- src/arch/xtensa/boot_loader.c | 62 ++++++++++++++++++- .../cannonlake/include/platform/memory.h | 26 ++++---- .../cannonlake/include/platform/platcfg.h | 5 ++ 3 files changed, 80 insertions(+), 13 deletions(-) diff --git a/src/arch/xtensa/boot_loader.c b/src/arch/xtensa/boot_loader.c index 925631fa262c..dba06c6c51b8 100644 --- a/src/arch/xtensa/boot_loader.c +++ b/src/arch/xtensa/boot_loader.c @@ -35,6 +35,7 @@ #include #include #include +#include #if defined CONFIG_SUECREEK #define MANIFEST_BASE BOOT_LDR_MANIFEST_BASE @@ -133,12 +134,71 @@ static int32_t hp_sram_init(void) { int delay_count = 256; uint32_t status; +#if defined(CONFIG_CANNONLAKE) + uint32_t ebb_in_use; + uint32_t ebb_mask0, ebb_mask1, ebb_avail_mask0, ebb_avail_mask1; +#endif shim_write(SHIM_LDOCTL, SHIM_LDOCTL_HPSRAM_LDO_ON); /* add some delay before touch power register */ idelay(delay_count); +#if defined(CONFIG_CANNONLAKE) + /* calculate total number of used SRAM banks (EBB) + * to power up only ncecesary banks + */ + ebb_in_use = ((SOF_MEMORY_SIZE % SRAM_BANK_SIZE) == 0) ? + (SOF_MEMORY_SIZE / SRAM_BANK_SIZE) : + (SOF_MEMORY_SIZE / SRAM_BANK_SIZE) + 1; + + /* bit masks reflect total number of available EBB (banks) in each + * segment; current implementation supports 2 segments 0,1 + */ + if (PLATFORM_HPSRAM_EBB_COUNT > EBB_SEGMENT_SIZE) { + ebb_avail_mask0 = (uint32_t)MASK(EBB_SEGMENT_SIZE - 1, 0); + ebb_avail_mask1 = (uint32_t)MASK(PLATFORM_HPSRAM_EBB_COUNT - + EBB_SEGMENT_SIZE - 1, 0); + } else{ + ebb_avail_mask0 = (uint32_t)MASK(PLATFORM_HPSRAM_EBB_COUNT - 1, + 0); + ebb_avail_mask1 = 0; + } + + /* bit masks of banks that have to be powered up in each segment */ + if (ebb_in_use > EBB_SEGMENT_SIZE) { + ebb_mask0 = (uint32_t)MASK(EBB_SEGMENT_SIZE - 1, 0); + ebb_mask1 = (uint32_t)MASK(ebb_in_use - EBB_SEGMENT_SIZE - 1, + 0); + } else{ + /* assumption that ebb_in_use is > 0 */ + ebb_mask0 = (uint32_t)MASK(ebb_in_use - 1, 0); + ebb_mask1 = 0; + } + + /* HSPGCTL, HSRMCTL use reverse logic - 0 means EBB is power gated */ + io_reg_write(HSPGCTL0, (~ebb_mask0) & ebb_avail_mask0); + io_reg_write(HSRMCTL0, (~ebb_mask0) & ebb_avail_mask0); + io_reg_write(HSPGCTL1, (~ebb_mask1) & ebb_avail_mask1); + io_reg_write(HSRMCTL1, (~ebb_mask1) & ebb_avail_mask1); + + /* query the power status of first part of HP memory */ + /* to check whether it has been powered up. A few */ + /* cycles are needed for it to be powered up */ + status = io_reg_read(HSPGISTS0); + while (status != ((~ebb_mask0) & ebb_avail_mask0)) { + idelay(delay_count); + status = io_reg_read(HSPGISTS0); + } + /* query the power status of second part of HP memory */ + /* and do as above code */ + + status = io_reg_read(HSPGISTS1); + while (status != ((~ebb_mask1) & ebb_avail_mask1)) { + idelay(delay_count); + status = io_reg_read(HSPGISTS1); + } +#else /* now all the memory bank has been powered up */ io_reg_write(HSPGCTL0, 0); io_reg_write(HSRMCTL0, 0); @@ -161,7 +221,7 @@ static int32_t hp_sram_init(void) idelay(delay_count); status = io_reg_read(HSPGISTS1); } - +#endif /* add some delay before touch power register */ idelay(delay_count); diff --git a/src/platform/cannonlake/include/platform/memory.h b/src/platform/cannonlake/include/platform/memory.h index 97f73766977c..480a75f46175 100644 --- a/src/platform/cannonlake/include/platform/memory.h +++ b/src/platform/cannonlake/include/platform/memory.h @@ -163,9 +163,9 @@ * +---------------------+----------------+-----------------------------------+ * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | + * | SOF_STACK_BASE | | | * +---------------------+----------------+-----------------------------------+ */ @@ -279,8 +279,11 @@ /* Stack configuration */ #define SOF_STACK_SIZE ARCH_STACK_SIZE #define SOF_STACK_TOTAL_SIZE ARCH_STACK_TOTAL_SIZE -#define SOF_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE) -#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) +/* SOF_STACK_OFFSET defines how much memory can be power gated */ +#define SOF_STACK_OFFSET 0x150000 +/* SOF_STACK_BASE is moved from end of physical memory by offset */ +#define SOF_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_STACK_OFFSET) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) #define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) #define HEAP_BUFFER_SIZE \ @@ -288,25 +291,26 @@ #define HEAP_BUFFER_BLOCK_SIZE 0x180 #define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) +#define SOF_MEMORY_SIZE (SOF_STACK_BASE - HP_SRAM_BASE) /* * The LP SRAM Heap and Stack on Cannonlake are organised like this :- * * +--------------------------------------------------------------------------+ * | Offset | Region | Size | * +---------------------+----------------+-----------------------------------+ - * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | + * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | * | | Data | | * | | BSS | | * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | + * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | + * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | + * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | * +---------------------+----------------+-----------------------------------+ - * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | + * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | + * | SOF_STACK_BASE | | | * +---------------------+----------------+-----------------------------------+ */ @@ -367,8 +371,6 @@ #define SOF_MEM_RESET_LIT_SIZE 0x8 #define SOF_MEM_VECBASE_LIT_SIZE 0x178 -#define SOF_MEM_RO_SIZE 0x8 - /* boot loader in IMR */ #define IMR_BOOT_LDR_MANIFEST_BASE 0xB0032000 #define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 diff --git a/src/platform/cannonlake/include/platform/platcfg.h b/src/platform/cannonlake/include/platform/platcfg.h index ca5506218c18..99127e734f4f 100644 --- a/src/platform/cannonlake/include/platform/platcfg.h +++ b/src/platform/cannonlake/include/platform/platcfg.h @@ -43,4 +43,9 @@ #define PLATFORM_MASTER_CORE_ID 0 +//TODO: move cAVS memory specific definitions to cavs/memory driver +#define SRAM_BANK_SIZE 0x10000 + +#define EBB_SEGMENT_SIZE 32 + #endif