From 655632be7ee4c9d757e3cf2a953705a56155784c Mon Sep 17 00:00:00 2001 From: snek Date: Fri, 12 Jun 2026 12:26:27 +0200 Subject: [PATCH] enable psram on emery/gabbro Signed-off-by: snek --- src/fw/soc/sf32lb/sf32lb52x/init.c | 73 ++++++++++++++++++++++-------- src/fw/wscript | 37 ++++++++++----- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/fw/soc/sf32lb/sf32lb52x/init.c b/src/fw/soc/sf32lb/sf32lb52x/init.c index e3a361b1fb..598858f192 100644 --- a/src/fw/soc/sf32lb/sf32lb52x/init.c +++ b/src/fw/soc/sf32lb/sf32lb52x/init.c @@ -9,6 +9,59 @@ #define HCPU_FREQ_MHZ 240 #define PWRKEY_RESET_CNT (32000 * 15) +#define PBL_PSRAM_SIZE_MB 16 +#define PSRAM_MPI1_DIV_OPI 1 +#define PSRAM_MPI1_DIV_QSPI 2 + +static void prv_psram_init(void) { + HAL_RCC_HCPU_EnableDLL2(288000000); + HAL_RCC_HCPU_ClockSelect(RCC_CLK_MOD_FLASH1, RCC_CLK_FLASH_DLL2); + + // PSRAM is powered by VDD_SiP; also enable the 1V8 peripheral LDO + HAL_PMU_ConfigPeriLdo(PMU_PERI_LDO_1V8, true, true); + + qspi_configure_t cfg = { + .Instance = hwp_qspi1, + .base = PSRAM_BASE, + .msize = PBL_PSRAM_SIZE_MB, + }; + + uint16_t div = PSRAM_MPI1_DIV_QSPI; + uint32_t pid = (hwp_hpsys_cfg->IDR & HPSYS_CFG_IDR_PID_Msk) >> HPSYS_CFG_IDR_PID_Pos; + switch (pid & 7) { + case 5: // BOOT_PSRAM_APS_16P: 16Mb APM QSPI PSRAM + cfg.SpiMode = SPI_MODE_PSRAM; + break; + case 4: // BOOT_PSRAM_APS_32P: 32Mb APM legacy PSRAM + cfg.SpiMode = SPI_MODE_LEGPSRAM; + break; + case 6: // BOOT_PSRAM_WINBOND: Winbond HyperBus PSRAM + cfg.SpiMode = SPI_MODE_HBPSRAM; + break; + case 2: // BOOT_PSRAM_APS_128P: 128Mb (16MB) APM XCELLA OPI PSRAM + case 3: // BOOT_PSRAM_APS_64P: 64Mb APM XCELLA OPI PSRAM + cfg.SpiMode = SPI_MODE_OPSRAM; + div = PSRAM_MPI1_DIV_OPI; + break; + default: + PBL_CROAK("Unexpected PSRAM PID %lu", pid); + } + + static FLASH_HandleTypeDef f_handle; + f_handle.wakeup = (SystemPowerOnModeGet() == PM_STANDBY_BOOT) ? 1 : 0; + HAL_StatusTypeDef ret = HAL_MPI_PSRAM_Init(&f_handle, &cfg, div); + PBL_ASSERTN(ret == HAL_OK); + + // Self-test + volatile uint32_t *first = (volatile uint32_t *)PSRAM_BASE; + volatile uint32_t *last = + (volatile uint32_t *)(PSRAM_BASE + PBL_PSRAM_SIZE_MB * 1024 * 1024 - sizeof(uint32_t)); + *first = 0xA5A5A5A5U; + *last = 0x5A5A5A5AU; + __DSB(); + PBL_ASSERTN(*first == 0xA5A5A5A5U && *last == 0x5A5A5A5AU); +} + void soc_early_init(void) { HAL_StatusTypeDef ret; uint32_t bootopt; @@ -82,24 +135,8 @@ void soc_early_init(void) { //set Sifli chipset pwrkey reset time to 15s, so it always use PMIC cold reboot for long press hwp_pmuc->PWRKEY_CNT = PWRKEY_RESET_CNT; - // Disable 1V8 LDO (feeds PSRAM, we use VDD_SiP to power it) - hwp_pmuc->PERI_LDO &= ~(PMUC_PERI_LDO_EN_LDO18_Msk | PMUC_PERI_LDO_LDO18_PD_Msk); - hwp_pmuc->PERI_LDO |= PMUC_PERI_LDO_LDO18_PD_Msk; - - // Set all PSRAM pins as analog (low-power) - HAL_PIN_Set_Analog(PAD_SA00, 1); - HAL_PIN_Set_Analog(PAD_SA01, 1); - HAL_PIN_Set_Analog(PAD_SA02, 1); - HAL_PIN_Set_Analog(PAD_SA03, 1); - HAL_PIN_Set_Analog(PAD_SA04, 1); - HAL_PIN_Set_Analog(PAD_SA05, 1); - HAL_PIN_Set_Analog(PAD_SA06, 1); - HAL_PIN_Set_Analog(PAD_SA07, 1); - HAL_PIN_Set_Analog(PAD_SA08, 1); - HAL_PIN_Set_Analog(PAD_SA09, 1); - HAL_PIN_Set_Analog(PAD_SA10, 1); - HAL_PIN_Set_Analog(PAD_SA11, 1); - HAL_PIN_Set_Analog(PAD_SA12, 1); + // Bring up the MPI-PSRAM (pins SA00..SA12). APP_RAM/WORKER_RAM live there. + prv_psram_init(); HAL_HPAON_EnableWakeupSrc(HPAON_WAKEUP_SRC_LP2HP_REQ, AON_PIN_MODE_HIGH); HAL_HPAON_EnableWakeupSrc(HPAON_WAKEUP_SRC_LP2HP_IRQ, AON_PIN_MODE_HIGH); diff --git a/src/fw/wscript b/src/fw/wscript index 1b69e628d2..769d260b3f 100644 --- a/src/fw/wscript +++ b/src/fw/wscript @@ -174,9 +174,9 @@ def _generate_memory_layout(bld): 'chalk': AppRamSize(66 * 1024, 30 * 1024), # FIXME: The runtime_reserved size could be reduced for diorite 'diorite': AppRamSize(66 * 1024, 30 * 1024), - 'emery': AppRamSize(130 * 1024, 62 * 1024), + 'emery': AppRamSize(2048 * 1024, 62 * 1024), 'flint': AppRamSize(66 * 1024, 30 * 1024), - 'gabbro': AppRamSize(130 * 1024, 94 * 1024), + 'gabbro': AppRamSize(2048 * 1024, 94 * 1024), } APP_UNSUPPORTED = AppRamSize(0, 0) @@ -200,40 +200,55 @@ def _generate_memory_layout(bld): app_ram_size_2x = APP_RAM_SIZES['aplite'] app_ram_size_3x = APP_RAM_SIZES['basalt'] app_ram_size_4x = APP_RAM_SIZES['emery'] + # We have 512K of SRAM, last 1K reserved for LCPU IPC - total_ram = (0x20000000, (512 - 1) * 1024) + sram = (0x20000000, (512 - 1) * 1024) + psram = (0x60000000, 16 * 1024 * 1024) elif bld.env.CONFIG_PLATFORM_FLINT: app_ram_size_2x = APP_RAM_SIZES['aplite'] app_ram_size_3x = APP_RAM_SIZES['aplite'] app_ram_size_4x = APP_RAM_SIZES['flint'] + retained_size = 256 - total_ram = (0x20000000 + retained_size, 256 * 1024 - retained_size) + sram = (0x20000000 + retained_size, 256 * 1024 - retained_size) + psram = None elif bld.env.CONFIG_PLATFORM_GABBRO: app_ram_size_2x = APP_UNSUPPORTED app_ram_size_3x = APP_RAM_SIZES['chalk'] app_ram_size_4x = APP_RAM_SIZES['gabbro'] + # We have 512K of SRAM, last 1K reserved for LCPU IPC - total_ram = (0x20000000, (512 - 1) * 1024) + sram = (0x20000000, (512 - 1) * 1024) + psram = (0x60000000, 16 * 1024 * 1024) else: bld.fatal("No set of supported SDK platforms defined for this board") # Allocate RAM from the end to the start. Do the app first, then the worker, then give whatever # is left to the kernel. - ram_end = sum(total_ram) # The end of RAM is the start address plus the size. all_app_ram_sizes = [app_ram_size_2x, app_ram_size_3x, app_ram_size_4x] app_ram_size = max(sum(x) for x in all_app_ram_sizes) system_app_segment_size = max(x.app_segment for x in all_app_ram_sizes) app_runtime_size = max(x.runtime_reserved for x in all_app_ram_sizes) if app_ram_size <= 0 or app_runtime_size <= 0: bld.fatal("App RAM is too small!") - app_ram = (ram_end - app_ram_size, app_ram_size) worker_ram_size = 12 * 1024 # The worker always gets 12k of RAM. - worker_ram = (ram_end - app_ram_size - worker_ram_size, worker_ram_size) - kernel_ram_size = total_ram[1] - app_ram_size - worker_ram_size - kernel_ram = (total_ram[0], kernel_ram_size) + + if psram: + kernel_ram = sram + + ram_end = sum(psram) + app_ram = (ram_end - app_ram_size, app_ram_size) + worker_ram = (ram_end - app_ram_size - worker_ram_size, worker_ram_size) + else: + ram_end = sum(sram) + app_ram = (ram_end - app_ram_size, app_ram_size) + worker_ram = (ram_end - app_ram_size - worker_ram_size, worker_ram_size) + kernel_ram_size = sram[1] - app_ram_size - worker_ram_size + kernel_ram = (sram[0], kernel_ram_size) + # As a basic sanity check, make sure we're giving the kernel at least 64k. - if kernel_ram_size < 64 * 1024: + if kernel_ram[1] < 64 * 1024: bld.fatal("Kernel RAM is too small!") ldscript_result = ldscript_template.get_bld().change_ext('.ld', ext_in='.ld.template')