Files
plant_car/drivers/source/reset/sdrv_rstgen.c
2025-11-08 13:26:19 +08:00

1195 lines
34 KiB
C

/**
* @file sdrv_rstgen_drv.c
* @brief semidrive reset driver
*
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*/
#include <armv7-r/barriers.h>
#include <types.h>
#include <bits.h>
#include <debug.h>
#include <reg.h>
#include <regs_base.h>
#include <part.h>
#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;
}