/** * @file device_init.c * @brief Semidrive device ealryinit. * * @copyright Copyright (c) 2022 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #ifndef APB_IRAMC1_BASE /* IRAM1 RAM Controller */ #define APB_IRAMC1_BASE (0xF0D20000ul) #endif #ifndef APB_IRAMC2_BASE /* IRAM2 RAM Controller */ #define APB_IRAMC2_BASE (0xF0D30000ul) #endif #ifndef APB_IRAMC3_BASE /* IRAM3 RAM Controller */ #define APB_IRAMC3_BASE (0xF0D40000ul) #endif #ifndef APB_IRAMC4_BASE /* IRAM4 RAM Controller */ #define APB_IRAMC4_BASE (0xF2030000ul) #endif #define SAF_LP_CTL_OFF(n) (0x1008U + 8U * (n)) #define SAF_RAM_LP_CTL_OFF(n) (0x1060U + 4U * (n)) #define CORE_RESET_CONTROL_OFF(n) (0x1a04U + 8U*(n)) extern const sdrv_ckgen_node_t **g_ckgen_unused[]; static const mcu_power_e g_unused_power[] = { MCU_POWER_SP, MCU_POWER_SX, MCU_POWER_GAMA, MCU_POWER_END }; static void mcu_unused_power_register_set(uint32_t index) { uint32_t addr, ram_addr; addr = APB_SMC_BASE + SAF_LP_CTL_OFF(index); ram_addr = APB_SMC_BASE + SAF_RAM_LP_CTL_OFF(index); RMWREG32(ram_addr, 0, 3, 0x7u); RMWREG32(ram_addr, 3, 9, 0x1FFu); RMWREG32(addr, 0, 4, 0xFu); RMWREG32(addr, 4, 1, 0x1u); } static void mcu_unused_power_config(const mcu_power_e *powers) { uint32_t i = 0; while (powers[i] != MCU_POWER_END) { switch (powers[i]) { case MCU_POWER_SF: mcu_unused_power_register_set(0); break; case MCU_POWER_SP: mcu_unused_power_register_set(1); break; case MCU_POWER_SX: mcu_unused_power_register_set(2); break; case MCU_POWER_GAMA: mcu_unused_power_register_set(3); break; default: break; } i++; } } static void mcu_unused_iramc_config(const mcu_power_e *powers) { uint32_t i = 0; while (powers[i] != MCU_POWER_END) { switch (powers[i]) { case MCU_POWER_IRAM1: RMWREG32(APB_IRAMC1_BASE + 0x4, 0, 3, 0x4u); break; case MCU_POWER_IRAM2: RMWREG32(APB_IRAMC2_BASE + 0x4, 0, 3, 0x4u); break; case MCU_POWER_IRAM3: RMWREG32(APB_IRAMC3_BASE + 0x4, 0, 3, 0x4u); break; case MCU_POWER_IRAM4: RMWREG32(APB_IRAMC4_BASE + 0x4, 0, 3, 0x4u); break; default: break; } i++; } } static int mcu_unused_ip_cglist_mask(const sdrv_ckgen_node_t *ckgen_ip[], bool mask) { sdrv_ckgen_node_t *node; uint32_t i = 0; int ret = 0; while (ckgen_ip[i] && !ret) { node = (sdrv_ckgen_node_t *)ckgen_ip[i]; ret = sdrv_ckgen_cg_mask(node, mask); i++; } return ret; } static int mcu_unused_ip_config(void) { uint32_t i = 0; int ret = 0; mcu_unused_iramc_config(g_unused_power); while (g_ckgen_unused[i]) { ret = sdrv_ckgen_ip_clock_enable(g_ckgen_unused[i], CKGEN_HIB_MODE, false); ret = sdrv_ckgen_ip_clock_enable(g_ckgen_unused[i], CKGEN_SLP_MODE, false); ret = sdrv_ckgen_ip_clock_enable(g_ckgen_unused[i], CKGEN_RUN_MODE, false); ret = mcu_unused_ip_cglist_mask(g_ckgen_unused[i], true); i++; } RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(4), 0, 3, 0); RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(5), 0, 3, 0); RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(2), 0, 3, 0); RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(3), 0, 3, 0); mcu_unused_power_config(g_unused_power); return ret; } static void sdrv_port_pre_init(void) { volatile uint32_t val; for (uint32_t i = 0; i < 5; i++) { val = readl(APB_DISP_MUX_BASE + 0x1010 + 0x4 * i); val &= ~(0x1U << 1); val &= ~(0x3U << 6); writel(val, APB_DISP_MUX_BASE + 0x1010 + 0x4 * i); } val = readl(APB_DISP_MUX_BASE + 0x1100); val &= ~(0xFU << 1); writel(val, APB_DISP_MUX_BASE + 0x1100); } /** * @brief initializes the device. * * This function initializes the device before call main function. */ void device_init(void) { if (IS_P0) /* initializes LDO module. */ writel(0x0, APB_LDO_DIG_BASE + 0x10); /* Set rtc_lbist bypass when do offline-bist */ RMWREG32(APB_PMU_CORE_BASE + 0x70U, 2, 1, 1); RMWREG32(APB_PMU_CORE_BASE + 0x70U, 3, 1, 1); sdrv_port_pre_init(); mcu_unused_ip_config(); }