/** * @file sdrv_rstgen_drv.c * @brief semidrive reset driver * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #include #include "sdrv_rstgen.h" #include "sdrv_rstgen_hw.h" #include "sdrv_recovery_hw.h" #include "sdrv_common.h" #include "udelay/udelay.h" #define RSTGEN_POLLs 0x10000 /** * @brief sdrv rstgen core control * * Control core processor, set core running on/off. * * @param[in] base sdrv rstgen address * @param[in] core_idx core index * @param[in] run_mode run mode bit */ static status_t sdrv_rstgen_core_control(paddr_t base, uint32_t core_idx, bool run_mode) { uint32_t core_rst_en = base + CORE_RESET_RS_OFF(core_idx); uint32_t core_sw_rst = base + CORE_RESET_CONTROL_OFF(core_idx); /* Check the reset lock bit */ if (readl(core_rst_en) & (0x1u << CORE_RESET_RS_LOCK)) return SDRV_RESET_STATUS_LOCK; /* Check core SW reset status */ if (run_mode && (readl(core_sw_rst) & (0x1u << CORE_RESET_CONTROL_RSTA))) return SDRV_STATUS_OK; if (!run_mode && !(readl(core_sw_rst) & (0x1u << CORE_RESET_CONTROL_RSTA))) return SDRV_STATUS_OK; /* Set core run mode. */ RMWREG32(core_sw_rst, CORE_RESET_CONTROL_RUN_MODE, 1, run_mode); /* Wait reset done. */ while (run_mode != ((readl(core_sw_rst) >> CORE_RESET_CONTROL_RSTA) & 0x1u)); return SDRV_STATUS_OK; } /** * @brief sdrv rstgen core reset * * Reset core processor. * * @param[in] base sdrv rstgen address * @param[in] core_idx core index */ static status_t sdrv_rstgen_core_reset(paddr_t base, uint32_t core_idx) { uint32_t tms = 0; uint32_t core_rst = base + CORE_RESET_CONTROL_OFF(core_idx); uint32_t val = readl(core_rst); if (val & (1 << CORE_RESET_CONTROL_RSTA)) { DSB; ISB; /* Auto clear reset when the core is already running */ writel(val | (1 << CORE_RESET_CONTROL_AUTO_CLR_RST_B), core_rst); /* Trigger auto clear reset */ while (readl(core_rst) & (1 << CORE_RESET_CONTROL_AUTO_CLR_RST_B)) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } else { /* Set running mode when the core is off */ writel(val | (1 << CORE_RESET_CONTROL_RUN_MODE), core_rst); /* Trigger real time reset status */ while (0 == (readl(core_rst) & (1 << CORE_RESET_CONTROL_RSTA))) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } return SDRV_STATUS_OK; } /** * @brief sdrv rstgen auto clr rst * * some module .e SEIP , diff with other modules, must auto clr before set * * @param[in] base sdrv rstgen address * @param[in] module_idx module index */ static status_t sdrv_rstgen_module_clr_rst(paddr_t base, uint32_t module_idx) { uint32_t module_rst = base + MODULE_RESET_CONTROL_OFF(module_idx); uint32_t val = readl(module_rst); val |= 1 << MODULE_RESET_CONTROL_AUTO_CLR_RST_B; writel(val, module_rst); udelay(2); return SDRV_STATUS_OK; } /** * @brief sdrv rstgen module control * * Reset IP module, each module must be reset before used. * * @param[in] base sdrv rstgen address * @param[in] module_idx module index * @param[in] run_mode 0:module off, 1:module on */ static status_t sdrv_rstgen_module_control(paddr_t base, uint32_t module_idx, bool run_mode) { uint32_t tms = 0; uint32_t module_rst = base + MODULE_RESET_CONTROL_OFF(module_idx); uint32_t val = readl(module_rst); if (((val >> MODULE_RESET_CONTROL_RUN_MODE) & 0x1) == run_mode) { return SDRV_STATUS_OK; } if (run_mode) { val |= 1 << MODULE_RESET_CONTROL_RUN_MODE; } else { val &= ~(1 << MODULE_RESET_CONTROL_RUN_MODE); } writel(val, module_rst); if (run_mode) while (!(readl(module_rst) & (0x1u << MODULE_RESET_CONTROL_RSTA))) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } else while (readl(module_rst) & (0x1u << MODULE_RESET_CONTROL_RSTA)) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } return SDRV_STATUS_OK; } /** * @brief sdrv rstgen mission control * * ALl the missions are reset automatically when SOC is power on. * * @param[in] base sdrv rstgen address * @param[in] mission_idx mission index * @param[in] run_mode 0:misson off, 1:misson on */ static status_t sdrv_rstgen_mission_control(paddr_t base, uint32_t mission_idx, bool run_mode) { uint32_t tms = 0; uint32_t mission_rst = base + MISSION_RESET_CONTROL_OFF(mission_idx); uint32_t val = readl(mission_rst); if (((val >> MISSION_RESET_CONTROL_RUN_MODE) & 0x1) == run_mode) { return SDRV_STATUS_OK; } if (run_mode) { val |= (0x1u << MISSION_RESET_CONTROL_RUN_MODE); } else { val &= ~(0x1u << MISSION_RESET_CONTROL_RUN_MODE); } writel(val, mission_rst); if (run_mode) { while (!(readl(mission_rst) & (1 << MISSION_RESET_CONTROL_RSTA))) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } else { while ((readl(mission_rst) & (1 << MISSION_RESET_CONTROL_RSTA))) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } return SDRV_STATUS_OK; } /** * @brief sdrv rstgen latent control * * ALl the latents are reset automatically when SOC is power on. * * @param[in] base sdrv rstgen address * @param[in] latent_idx latent index * @param[in] run_mode 0:latent on, 1:latent off */ static status_t sdrv_rstgen_latent_control(paddr_t base, uint32_t latent_idx, bool run_mode) { uint32_t tms = 0; uint32_t latent_rst = base + LATENT_RESET_CONTROL_OFF(latent_idx); uint32_t val = readl(latent_rst); if (((val >> LATENT_RESET_CONTROL_RUN_MODE) & 0x1) == run_mode) { return SDRV_STATUS_OK; } if (val & (0x1u << LATENT_RESET_CONTROL_LOCK)) { return SDRV_RESET_STATUS_LOCK; } if (run_mode) { val |= (0x1u << LATENT_RESET_CONTROL_RUN_MODE); } else { val &= ~(0x1u << LATENT_RESET_CONTROL_RUN_MODE); } writel(val, latent_rst); if (run_mode) { while (!(readl(latent_rst) & (1 << LATENT_RESET_CONTROL_RSTA))) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } else { while (readl(latent_rst) & (1 << LATENT_RESET_CONTROL_RSTA)) { if (tms++ > RSTGEN_POLLs) { return SDRV_RESET_STATUS_TIMEOUT; } } } return SDRV_STATUS_OK; } /** * @brief sdrv rstgen get core reset status * * @param[in] base sdrv rstgen address * @param[in] core_idx core index * @return 1, the core reset has be released. * 0, the core reset hasn't be released. */ static int32_t sdrv_rstgen_get_core_reset_status(paddr_t base, uint32_t core_idx) { uint32_t core_rst = base + CORE_RESET_CONTROL_OFF(core_idx); return !!(readl(core_rst) & (0x1u << MODULE_RESET_CONTROL_RSTA)); } /** * @brief sdrv rstgen get module reset status * * @param[in] base sdrv rstgen address * @param[in] module_idx module index * @return 1, the module reset has be released. * 0, the module reset hasn't be released. */ static int32_t sdrv_rstgen_get_module_reset_status(paddr_t base, uint32_t module_idx) { uint32_t module_rst = base + MODULE_RESET_CONTROL_OFF(module_idx); /* RSTGEN_MODULE_RST_STA, 0 = reset, 1 = release. */ return !!(readl(module_rst) & (0x1u << MODULE_RESET_CONTROL_RSTA)); } /** * @brief sdrv rstgen get mission reset status * * @param[in] base sdrv rstgen address * @param[in] mission_idx mission index * @return 1, the mission reset has be released. * 0, the mission reset hasn't be released. */ static int32_t sdrv_rstgen_get_mission_reset_status(paddr_t base, uint32_t mission_idx) { uint32_t mission_rst = base + MISSION_RESET_CONTROL_OFF(mission_idx); /* RSTGEN_MODULE_RST_STA, 0 = reset, 1 = release. */ return !!(readl(mission_rst) & (0x1u << MISSION_RESET_CONTROL_RSTA)); } /** * @brief sdrv rstgen get latent reset status * * @param[in] base sdrv rstgen address * @param[in] latent_idx latent index * @return 1, the latent reset has be released. * 0, the latent reset hasn't be released. */ static int32_t sdrv_rstgen_get_latent_reset_status(paddr_t base, uint32_t latent_idx) { uint32_t latent_rst = base + LATENT_RESET_CONTROL_OFF(latent_idx); /* RSTGEN_MODULE_RST_STA, 0 = reset, 1 = release. */ return !!(readl(latent_rst) & (0x1u << LATENT_RESET_CONTROL_RSTA)); } static void sdrv_rstgen_set_ist_reset_by_mode(paddr_t base, uint32_t index, uint32_t mode, uint32_t val) { if (mode <= IST_RESET_CONTROL_SLP_MODE) { RMWREG32(base + IST_RESET_CONTROL_OFF, mode, 1, val & 0x1u); } } static void sdrv_rstgen_set_mission_reset_by_mode(paddr_t base, uint32_t index, uint32_t mode, uint32_t val) { if (mode <= MISSION_RESET_CONTROL_SLP_MODE) { RMWREG32(base + MISSION_RESET_CONTROL_OFF(index), mode, 1, val & 0x1u); } } static void sdrv_rstgen_set_latent_reset_by_mode(paddr_t base, uint32_t index, int32_t mode, uint32_t val) { if (mode <= LATENT_RESET_CONTROL_SLP_MODE) { RMWREG32(base + LATENT_RESET_CONTROL_OFF(index), mode, 1, val & 0x1u); } } static void sdrv_rstgen_set_module_reset_by_mode(paddr_t base, uint32_t index, uint32_t mode, uint32_t val) { if (mode <= MODULE_RESET_CONTROL_SLP_MODE) { RMWREG32(base + MODULE_RESET_CONTROL_OFF(index), mode, 1, val & 0x1u); } } static void sdrv_rstgen_set_core_reset_by_mode(paddr_t base, uint32_t index, uint32_t mode, uint32_t val) { if (mode <= CORE_RESET_CONTROL_SLP_MODE) { RMWREG32(base + CORE_RESET_CONTROL_OFF(index), mode, 1, val & 0x1u); } } static void sdrv_rstgen_set_debug_reset_by_mode(paddr_t base, uint32_t index, uint32_t mode, uint32_t val) { if (mode <= DBG_RESET_CONTROL_SLP_MODE) { RMWREG32(base + DBG_RESET_CONTROL_OFF, mode, 1, val & 0x1u); } } static status_t sdrv_rstgen_release_ctl(sdrv_rstgen_t *rst_ctl, uint32_t id, bool release) { int32_t ret = SDRV_STATUS_FAIL; switch (SDRV_RSTGEN_TYPE(id)) { case SDRV_RSTGEN_CORE: ret = sdrv_rstgen_core_control( rst_ctl->base, SDRV_RSTGEN_INDEX(id), release); break; case SDRV_RSTGEN_MODULE: ret = sdrv_rstgen_module_control( rst_ctl->base, SDRV_RSTGEN_INDEX(id), release); break; case SDRV_RSTGEN_MISSION: ret = sdrv_rstgen_mission_control( rst_ctl->base, SDRV_RSTGEN_INDEX(id), release); break; case SDRV_RSTGEN_LATENT: ret = sdrv_rstgen_latent_control( rst_ctl->base, SDRV_RSTGEN_INDEX(id), release); break; default: break; } return ret; } /** * @brief Assert a reset signal. * * The reset singal will stay asserted until reset_deassert() is called. * * @param[in] rst_sig Reset signal. * @return 0 if OK, or a negative error code. */ status_t sdrv_rstgen_assert(sdrv_rstgen_sig_t *rst_sig) { if (rst_sig == NULL) { return SDRV_RESET_STATUS_WRONG_SIGNAL; } sdrv_rstgen_t *rst_ctl = rst_sig->rst_ctl; uint32_t id = rst_sig->id; if(rst_sig->pre_handler) { rst_sig->pre_handler(rst_sig->id); } return sdrv_rstgen_release_ctl(rst_ctl, id, false); } /** * @brief Deassert a reset signal. * * Release a reset signal. * * @param[in] rst_sig Reset signal. * @return 0 if OK, or a negative error code. */ status_t sdrv_rstgen_deassert(sdrv_rstgen_sig_t *rst_sig) { status_t ret = SDRV_STATUS_OK; if (rst_sig == NULL) { return SDRV_RESET_STATUS_WRONG_SIGNAL; } sdrv_rstgen_t *rst_ctl = rst_sig->rst_ctl; uint32_t id = rst_sig->id; ret = sdrv_rstgen_release_ctl(rst_ctl, id, true); if(rst_sig->post_handler) { rst_sig->post_handler(rst_sig->id); } return ret; } /** * @brief Reset a reset signal. * * Assert a reset signal, and then deassert it automatically. * * @param[in] rst_sig Reset signal. * @return 0 if OK, or a negative error code. */ status_t sdrv_rstgen_reset(sdrv_rstgen_sig_t *rst_sig) { if (rst_sig == NULL) { return SDRV_RESET_STATUS_WRONG_SIGNAL; } int32_t ret = SDRV_STATUS_FAIL; sdrv_rstgen_t *sdrv_rst = rst_sig->rst_ctl; uint32_t id = rst_sig->id; if(rst_sig->pre_handler) { rst_sig->pre_handler(rst_sig->id); } switch (SDRV_RSTGEN_TYPE(id)) { case SDRV_RSTGEN_CORE: ret = sdrv_rstgen_core_reset(sdrv_rst->base, SDRV_RSTGEN_INDEX(id)); break; case SDRV_RSTGEN_MODULE: if (rst_sig->need_clr_rst) { ret = sdrv_rstgen_module_clr_rst(sdrv_rst->base, SDRV_RSTGEN_INDEX(id)); if (ret == 0) { ret = sdrv_rstgen_module_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), true); } } else { ret = sdrv_rstgen_module_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), false); if (ret == 0) { ret = sdrv_rstgen_module_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), true); } } break; case SDRV_RSTGEN_MISSION: ret = sdrv_rstgen_mission_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), false); if (ret == 0) { ret = sdrv_rstgen_mission_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), true); } break; case SDRV_RSTGEN_LATENT: ret = sdrv_rstgen_latent_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), false); if (ret == 0) { ret = sdrv_rstgen_latent_control( sdrv_rst->base, SDRV_RSTGEN_INDEX(id), true); } break; default: ret = SDRV_RESET_STATUS_WRONG_SIGNAL; break; } if(rst_sig->post_handler) { rst_sig->post_handler(rst_sig->id); } return ret; } /** * @brief Global reset. * * Global reset SF/AP domain * * @param[in] rst_glb_ctl Global reset controller. * @return 0 if OK, or a negative error code. */ status_t sdrv_rstgen_global_reset(sdrv_rstgen_glb_t *rst_glb_ctl) { sdrv_rstgen_t *rst_sf_ctl = rst_glb_ctl->rst_sf_ctl; if (rst_sf_ctl == NULL) { return SDRV_STATUS_INVALID_PARAM; } RMWREG32(rst_sf_ctl->base + GLOBAL_RESET_CONTROL_OFF, GLOBAL_RESET_CONTROL_SW_GLB_RST_EN, 1, 1); RMWREG32(rst_sf_ctl->base + GLOBAL_RESET_CONTROL_OFF, GLOBAL_RESET_CONTROL_SW_GLB_RST, 1, 1); return SDRV_STATUS_OK; } /** * @brief Check reset signal status. * * @param[in] rst_sig Reset signal. * @return 0 if deasserted, or a negative error code. */ status_t sdrv_rstgen_status(sdrv_rstgen_sig_t *rst_sig) { if (rst_sig == NULL) { return SDRV_RESET_STATUS_WRONG_SIGNAL; } sdrv_rstgen_t *rst_ctl = rst_sig->rst_ctl; uint32_t id = rst_sig->id; int32_t ret = SDRV_STATUS_FAIL; switch (SDRV_RSTGEN_TYPE(id)) { case SDRV_RSTGEN_CORE: ret = !sdrv_rstgen_get_core_reset_status( rst_ctl->base, SDRV_RSTGEN_INDEX(id)); break; case SDRV_RSTGEN_MISSION: ret = !sdrv_rstgen_get_mission_reset_status( rst_ctl->base, SDRV_RSTGEN_INDEX(id)); break; case SDRV_RSTGEN_LATENT: ret = !sdrv_rstgen_get_latent_reset_status( rst_ctl->base, SDRV_RSTGEN_INDEX(id)); break; case SDRV_RSTGEN_MODULE: ret = !sdrv_rstgen_get_module_reset_status( rst_ctl->base, SDRV_RSTGEN_INDEX(id)); break; default: ret = SDRV_RESET_STATUS_WRONG_SIGNAL; break; } if (ret == 1) { ret = SDRV_RESET_STATUS_SIGNAL_ASSERT; } return ret; } /** * @brief Check global reset status. * * Global reset status for all the time, * including each global reset status before clear or power off. * If multiple reset source comes neatly the same time, * only the first one will be recorded. * * @param[in] rst_glb_ctl Global reset controller. * @return SF and AP domain global reset status. * bit[31:25] for rstgen AP: * bit[31] rstgen ap software global reset * bit[30] reserved * bit[29] efusec security violation * bit[28] system panic(vdc function irq) * bit[27] sem1/sem2 error * bit[26] reserved * bit[25] PT sensor interrupt * bit[24:0] for rstgen SF: * bit[24] wdt6 int reset request * bit[23] wdt6 int reset request * bit[22] wdt4 int reset request * bit[21] wdt4 int reset request * bit[20] wdt2 int reset request * bit[19] reserved * bit[18] wdt5 int reset request * bit[17] wdt5 int reset request * bit[16] wdt3 int reset request * bit[15] wdt3 int reset request * bit[14] wdt1 int reset request * bit[13] reserved * bit[12] ist done fail * bit[11] rstgen sf software global reset * bit[10] reserved * bit[9] wdt2 int reset request (Only for E3104/E3106/E3205/E3206) * bit[8] wdt1 int reset request (Only for E3104/E3106/E3205/E3206) * bit[7] ist done fail (Only for E3104/E3106/E3205/E3206) * bit[6] rstgen sf software global reset (Only for E3104/E3106/E3205/E3206) * bit[5] rstgen ap cold reset request * bit[4] efusec security violation * bit[3] system panic(vdc function irq) * bit[2] sem1/sem2 error * bit[1] reserved * bit[0] PT sensor interrupt * Especially, bit[31:10] are invalid for E3104/E3106/E3205/E3206. */ uint32_t sdrv_rstgen_global_status(sdrv_rstgen_glb_t *rst_glb_ctl) { uint32_t status = 0; sdrv_rstgen_t *rst_sf_ctl = rst_glb_ctl->rst_sf_ctl; sdrv_rstgen_t *rst_ap_ctl = rst_glb_ctl->rst_ap_ctl; if (rst_ap_ctl) { status = (readl(rst_ap_ctl->base + GLOBAL_RESET_STA_ALL_OFF) & 0x7F) << 25; } if (rst_sf_ctl) { status |= (readl(rst_sf_ctl->base + GLOBAL_RESET_STA_ALL_OFF) & 0x1FFFFFF); } return status; } /** * @brief clear global reset status. * * Clear global reset status, otherwise the status will keep until power off. * * @param[in] rst_glb_ctl Global reset controller. */ status_t sdrv_rstgen_global_status_clear(sdrv_rstgen_glb_t *rst_glb_ctl) { sdrv_rstgen_t *rst_sf_ctl = rst_glb_ctl->rst_sf_ctl; sdrv_rstgen_t *rst_ap_ctl = rst_glb_ctl->rst_ap_ctl; if ((rst_sf_ctl == NULL) && (rst_ap_ctl == NULL)) { return SDRV_STATUS_INVALID_PARAM; } if (rst_ap_ctl) { writel(0, rst_ap_ctl->base + GLOBAL_RESET_STA_ALL_OFF); } if (rst_sf_ctl) { writel(0, rst_sf_ctl->base + GLOBAL_RESET_STA_ALL_OFF); } return SDRV_STATUS_OK; } /** * @brief Check current global reset status. * * Global reset status only for the last time. * If multiple reset source comes neatly the same time, * only the first one will be recorded. * * @param[in] rst_glb_ctl Global reset controller. * @return SF and AP domain current global reset status. * bit[31:25] for rstgen AP: * bit[31] rstgen ap software global reset * bit[30] reserved * bit[29] efusec security violation * bit[28] system panic(vdc function irq) * bit[27] sem1/sem2 error * bit[26] reserved * bit[25] PT sensor interrupt * bit[24:0] for rstgen SF: * bit[24] wdt6 int reset request * bit[23] wdt6 int reset request * bit[22] wdt4 int reset request * bit[21] wdt4 int reset request * bit[20] wdt2 int reset request * bit[19] reserved * bit[18] wdt5 int reset request * bit[17] wdt5 int reset request * bit[16] wdt3 int reset request * bit[15] wdt3 int reset request * bit[14] wdt1 int reset request * bit[13] reserved * bit[12] ist done fail * bit[11] rstgen sf software global reset * bit[10] reserved * bit[9] wdt2 int reset request (Only for E3104/E3106/E3205/E3206) * bit[8] wdt1 int reset request (Only for E3104/E3106/E3205/E3206) * bit[7] ist done fail (Only for E3104/E3106/E3205/E3206) * bit[6] rstgen sf software global reset (Only for E3104/E3106/E3205/E3206) * bit[5] rstgen ap cold reset request * bit[4] efusec security violation * bit[3] system panic(vdc function irq) * bit[2] sem1/sem2 error * bit[1] reserved * bit[0] PT sensor interrupt * Especially, bit[31:10] are invalid for E3104/E3106/E3205/E3206. */ uint32_t sdrv_rstgen_current_global_status(sdrv_rstgen_glb_t *rst_glb_ctl) { uint32_t status = 0; sdrv_rstgen_t *rst_sf_ctl = rst_glb_ctl->rst_sf_ctl; sdrv_rstgen_t *rst_ap_ctl = rst_glb_ctl->rst_ap_ctl; if (rst_ap_ctl) { status = (readl(rst_ap_ctl->base + GLOBAL_RESET_STA_OFF) & 0x7F) << 25; } if (rst_sf_ctl) { status |= (readl(rst_sf_ctl->base + GLOBAL_RESET_STA_OFF) & 0x1FFFFFF); } return status; } /** * @brief Read reset general reg. * * The data saved in general regs will be not lost until SOC power down. * * @param[in] rst_gen_reg reset general reg. * @return general reg value. */ uint32_t sdrv_rstgen_read_general(sdrv_rstgen_general_reg_t *rst_gen_reg) { uint32_t ret = 0; sdrv_rstgen_t *rst_ctl = rst_gen_reg->rst_ctl; uint32_t id = rst_gen_reg->id; if ((rst_ctl) && (id < SDRV_RSTGEN_GENERAL_REG_NUM)) { ret = readl(rst_ctl->base + GENERAL_REG_OFF(id)); } return ret; } /** * @brief Write reset general reg. * * @param[in] rst_gen_reg reset general reg. * @param[in] val write value. * @return 0 if success, * or a negative error code. */ status_t sdrv_rstgen_write_general(sdrv_rstgen_general_reg_t *rst_gen_reg, uint32_t val) { sdrv_rstgen_t *rst_ctl = rst_gen_reg->rst_ctl; uint32_t id = rst_gen_reg->id; if ((rst_ctl == NULL) || (id >= SDRV_RSTGEN_GENERAL_REG_NUM)) { return SDRV_STATUS_INVALID_PARAM; } writel(val, rst_ctl->base + GENERAL_REG_OFF(id)); return SDRV_STATUS_OK; } /** * @brief Write reset general reg bit. * * @param[in] rst_gen_reg reset general reg. * @param[in] start write start bit. * @param[in] width write bit width. * @param[in] val write value. * @return 0 if success, * or a negative error code. */ status_t sdrv_rstgen_write_general_bit(sdrv_rstgen_general_reg_t *rst_gen_reg, uint8_t start, uint8_t width, uint32_t val) { sdrv_rstgen_t *rst_ctl = rst_gen_reg->rst_ctl; uint32_t id = rst_gen_reg->id; if ((rst_ctl == NULL) || (id >= SDRV_RSTGEN_GENERAL_REG_NUM) || (start + width > 32)) { return SDRV_STATUS_INVALID_PARAM; } RMWREG32(rst_ctl->base + GENERAL_REG_OFF(id), start, width, val); return SDRV_STATUS_OK; } /** * @brief Config reset signal assert/deassert in lowpower mode. * * @param[in] rst_sig Reset signal. * @param[in] mode lowpower mode * @param[in] val 0:assert, 1:deassert * * @return 0 if OK, or a negative error code. */ status_t sdrv_rstgen_lowpower_set(sdrv_rstgen_sig_t *rst_sig, enum reset_lowpower_mode mode, uint32_t val) { sdrv_rstgen_t *rst_ctl = rst_sig->rst_ctl; uint32_t id = rst_sig->id; uint32_t lp_mode; if (rst_ctl == NULL) { return SDRV_STATUS_INVALID_PARAM; } if (mode == RESET_LP_HIB) { lp_mode = 1; } else { lp_mode = 2; } switch (SDRV_RSTGEN_TYPE(id)) { case SDRV_RSTGEN_CORE: sdrv_rstgen_set_core_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; case SDRV_RSTGEN_MODULE: sdrv_rstgen_set_module_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; case SDRV_RSTGEN_MISSION: sdrv_rstgen_set_mission_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; case SDRV_RSTGEN_LATENT: sdrv_rstgen_set_latent_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; case SDRV_RSTGEN_IST: sdrv_rstgen_set_ist_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; case SDRV_RSTGEN_DEBUG: sdrv_rstgen_set_debug_reset_by_mode(rst_ctl->base, SDRV_RSTGEN_INDEX(id), lp_mode, val); break; default: return SDRV_STATUS_INVALID_PARAM; } return SDRV_STATUS_OK; } /** * @brief Config wdt cause global reset enable * * @param [in] wdt wdt id * @param [in] enable true/false * @return 0 if success, or a negative error code. */ #if CONFIG_E3 || CONFIG_D3 status_t sdrv_rstgen_wdt_reset_enable(reset_wdt_id_e wdt, bool enable) { switch (wdt) { case RESET_WDT1: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 4, 1, 1); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 4, 1, 0); } break; case RESET_WDT2: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 12, 1, 1); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 12, 1, 0); } break; case RESET_WDT3: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 5, 2, 0x3); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 5, 2, 0x0); } break; case RESET_WDT4: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 13, 2, 0x3); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 13, 2, 0x0); } break; case RESET_WDT5: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 7, 2, 0x3); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 7, 2, 0x0); } break; case RESET_WDT6: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 15, 2, 0x3); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 15, 2, 0x0); } break; default: return SDRV_STATUS_INVALID_PARAM; } return SDRV_STATUS_OK; } status_t sdrv_rstgen_wdt_core_reset_enable(reset_wdt_id_e wdt, reset_core_id_e core, bool enable) { status_t ret = SDRV_STATUS_INVALID_PARAM; uint32_t en_bit; if (wdt == RESET_WDT1 || wdt == RESET_WDT3 || wdt == RESET_WDT5) { en_bit = CORE_RESET_CONTROL_WDT1_RST_EN; } else { en_bit = CORE_RESET_CONTROL_WDT2_RST_EN; } switch (wdt) { case RESET_WDT1: case RESET_WDT2: if (core == RESET_CORE_SF) { ret = SDRV_STATUS_OK; } break; case RESET_WDT3: case RESET_WDT4: if (core == RESET_CORE_SP0 || core == RESET_CORE_SP1) { ret = SDRV_STATUS_OK; } break; case RESET_WDT5: case RESET_WDT6: if (core == RESET_CORE_SX0 || core == RESET_CORE_SX1) { ret = SDRV_STATUS_OK; } break; default: break; } if (ret == SDRV_STATUS_OK) { RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(core), en_bit, 1, enable); } return ret; } #endif /* CONFIG_E3 || CONFIG_D3 */ #if CONFIG_E3L status_t sdrv_rstgen_wdt_reset_enable(reset_wdt_id_e wdt, bool enable) { switch (wdt) { case RESET_WDT1: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 3, 1, 1); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 3, 1, 0); } break; case RESET_WDT2: if (enable) { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 11, 1, 1); } else { RMWREG32(APB_RSTGEN_SF_BASE + GLOBAL_RESET_CONTROL_OFF, 11, 1, 0); } break; default: return SDRV_STATUS_INVALID_PARAM; } return SDRV_STATUS_OK; } status_t sdrv_rstgen_wdt_core_reset_enable(reset_wdt_id_e wdt, reset_core_id_e core, bool enable) { status_t ret = SDRV_STATUS_INVALID_PARAM; uint32_t en_bit; if (wdt == RESET_WDT1) { en_bit = CORE_RESET_CONTROL_WDT1_RST_EN; } else { en_bit = CORE_RESET_CONTROL_WDT2_RST_EN; } switch (wdt) { case RESET_WDT1: case RESET_WDT2: if (core == RESET_CORE_SF) { ret = SDRV_STATUS_OK; } break; default: break; } if (ret == SDRV_STATUS_OK) { RMWREG32(APB_RSTGEN_SF_BASE + CORE_RESET_CONTROL_OFF(core), en_bit, 1, enable); } return ret; } #endif /* CONFIG_E3L */ /** * @brief recovery btm module. * * @param[in] base recovery btm module base addr */ static void sdrv_recovery_btm_module(uint32_t base) { /* disable G0 */ writel(0, base + BTM_G0_EN_OFFSET); /* disable G1 */ writel(0, base + BTM_G1_EN_OFFSET); /* disable int */ writel(0, base + BTM_INT_STA_EN_OFFSET); writel(0, base + BTM_INT_SIG_EN_OFFSET); /* clear int sta */ writel(0xF, base + BTM_INT_STA_OFFSET); } /** * @brief recovery epwm module. * * @param[in] base recovery epwm module base addr */ static void sdrv_recovery_epwm_module(uint32_t base) { /* disable cmp module */ writel(0, base + EPWM_CMP_CTRL_OFFSET); /* disable G0 */ writel(0, base + EPWM_G0_EN_OFFSET); /* disable G1 */ writel(0, base + EPWM_G1_EN_OFFSET); /* reset all counter and fifo to 0 */ writel(0x3FF, base + EPWM_SW_RST_OFFSET); /* reset dma config */ writel(0, base + EPWM_DMA_CTRL_OFFSET); /* disable int */ writel(0, base + EPWM_INT_STA_EN_OFFSET); writel(0, base + EPWM_INT_SIG_EN_OFFSET); /* clear int sta */ writel(0xFFFFFFFF, base + EPWM_INT_STA_OFFSET); } /** * @brief recovery etimer module. * * @param[in] base recovery etimer module base addr */ static void sdrv_recovery_etimer_module(uint32_t base) { /* disable cpt module */ writel(0, base + ETIMER_CPT_CTRL_OFFSET); /* disable cmp module */ writel(0, base + ETIMER_CMP_CTRL_OFFSET); /* disable G0 */ writel(0, base + ETIMER_G0_EN_OFFSET); /* disable G1 */ writel(0, base + ETIMER_G1_EN_OFFSET); /* disable lcnt_a */ writel(0, base + ETIMER_LCNT_A_EN_OFFSET); /* disable lcnt_b */ writel(0, base + ETIMER_LCNT_B_EN_OFFSET); /* disable lcnt_c */ writel(0, base + ETIMER_LCNT_C_EN_OFFSET); /* disable lcnt_d */ writel(0, base + ETIMER_LCNT_D_EN_OFFSET); /* reset dma ctrl to 0 */ writel(0, base + ETIMER_DMA_CTRL_OFFSET); /* reset all counter to 0 */ writel(0x3F, base + ETIMER_SW_RST_OFFSET); /* disable int */ writel(0, base + ETIMER_INT_STA_EN_OFFSET); writel(0, base + ETIMER_INT_SIG_EN_OFFSET); /* clear int sta */ writel(0xFFFFFFFF, base + ETIMER_INT_STA_OFFSET); } /** * @brief sdrv recovery latent module. * * Some latent modules (btm/etimer/epwm etc.) will be not reset when core is reset, * so these modules should be recovery when core restart. * * @param[in] recovery_module recovery latent module list * @return 0 if success, or a negative error code. */ status_t sdrv_recovery_module(sdrv_recovery_module_t *recovery_module) { int i = 0; for (i = 0; i < recovery_module->btm_list->btm_num; i++) { sdrv_recovery_btm_module(recovery_module->btm_list->btm_base[i]); } for (i = 0; i < recovery_module->etimer_list->etimer_num; i++) { sdrv_recovery_etimer_module(recovery_module->etimer_list->etimer_base[i]); } for (i = 0; i < recovery_module->epwm_list->epwm_num; i++) { sdrv_recovery_epwm_module(recovery_module->epwm_list->epwm_base[i]); } return SDRV_STATUS_OK; }