zephyr/soc/intel/intel_adsp/cavs/sram.c

145 lines
3.7 KiB
C

/* Copyright(c) 2021 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <stdint.h>
#include <zephyr/devicetree.h>
#include <soc_util.h>
#include <zephyr/cache.h>
#include <adsp_shim.h>
#include <adsp_memory.h>
#include <cpu_init.h>
#include "manifest.h"
#define DELAY_COUNT 256
#define LPSRAM_MASK(x) 0x00000003
#define PLATFORM_INIT_HPSRAM
#define PLATFORM_INIT_LPSRAM
BUILD_ASSERT((DT_REG_SIZE(DT_NODELABEL(sram0)) % SRAM_BANK_SIZE) == 0,
"sram0 must be divisible by 64*1024 bank size.");
/*
* Function powers up a number of memory banks provided as an argument
* and gates remaining memory banks
*/
static __imr void hp_sram_pm_banks(uint32_t banks)
{
#ifdef CONFIG_ADSP_INIT_HPSRAM
uint32_t status, ebb_mask0, ebb_mask1, ebb_avail_mask0, ebb_avail_mask1,
total_banks_count = HPSRAM_EBB_COUNT;
CAVS_SHIM.ldoctl = SHIM_LDOCTL_HPSRAM_LDO_ON;
/* Add some delay before touch power register */
z_idelay(DELAY_COUNT);
/*
* bit masks reflect total number of available EBB (banks) in each
* segment; current implementation supports 2 segments 0,1
*/
if (total_banks_count > EBB_SEG_SIZE) {
ebb_avail_mask0 = (uint32_t)GENMASK(EBB_SEG_SIZE - 1, 0);
ebb_avail_mask1 = (uint32_t)GENMASK(total_banks_count -
EBB_SEG_SIZE - 1, 0);
} else {
ebb_avail_mask0 = (uint32_t)GENMASK(total_banks_count - 1, 0);
ebb_avail_mask1 = 0;
}
/* bit masks of banks that have to be powered up in each segment */
if (banks > EBB_SEG_SIZE) {
ebb_mask0 = (uint32_t)GENMASK(EBB_SEG_SIZE - 1, 0);
ebb_mask1 = (uint32_t)GENMASK(banks - EBB_SEG_SIZE - 1,
0);
} else {
/* assumption that ebb_in_use is > 0 */
ebb_mask0 = (uint32_t)GENMASK(banks - 1, 0);
ebb_mask1 = 0;
}
/* HSPGCTL, HSRMCTL use reverse logic - 0 means EBB is power gated */
CAVS_L2LM.hspgctl0 = (~ebb_mask0) & ebb_avail_mask0;
CAVS_L2LM.hsrmctl0 = (~ebb_mask0) & ebb_avail_mask0;
CAVS_L2LM.hspgctl1 = (~ebb_mask1) & ebb_avail_mask1;
CAVS_L2LM.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 = CAVS_L2LM.hspgists0;
while (status != ((~ebb_mask0) & ebb_avail_mask0)) {
z_idelay(DELAY_COUNT);
status = CAVS_L2LM.hspgists0;
}
/*
* Query the power status of second part of HP memory
* and do as above code
*/
status = CAVS_L2LM.hspgists1;
while (status != ((~ebb_mask1) & ebb_avail_mask1)) {
z_idelay(DELAY_COUNT);
status = CAVS_L2LM.hspgists1;
}
/* Add some delay before touch power register */
z_idelay(DELAY_COUNT);
CAVS_SHIM.ldoctl = SHIM_LDOCTL_HPSRAM_LDO_BYPASS;
#endif
}
__imr void hp_sram_init(uint32_t memory_size)
{
uint32_t ebb_in_use;
/*
* Calculate total number of used SRAM banks (EBB)
* to power up only necessary banks
*/
ebb_in_use = DIV_ROUND_UP(memory_size, SRAM_BANK_SIZE);
hp_sram_pm_banks(ebb_in_use);
bbzero((void *)L2_SRAM_BASE, L2_SRAM_SIZE);
}
__imr void lp_sram_init(void)
{
#ifdef PLATFORM_INIT_LPSRAM
uint32_t timeout_counter;
timeout_counter = DELAY_COUNT;
CAVS_SHIM.ldoctl = SHIM_LDOCTL_LPSRAM_LDO_ON;
/* Add some delay before writing power registers */
z_idelay(DELAY_COUNT);
/* FIXME */
CAVS_L2LM.lspgctl = CAVS_L2LM.lspgists & ~LPSRAM_MASK(0);
/* Add some delay before checking the status */
z_idelay(DELAY_COUNT);
/*
* Query the power status of first part of LP memory
* to check whether it has been powered up. A few
* cycles are needed for it to be powered up
*/
/* FIXME */
while (CAVS_L2LM.lspgists && timeout_counter--) {
z_idelay(DELAY_COUNT);
}
CAVS_SHIM.ldoctl = SHIM_LDOCTL_LPSRAM_LDO_BYPASS;
bbzero((void *)LP_SRAM_BASE, LP_SRAM_SIZE);
#endif
}