Files
luban-lite-t3e-pro/bsp/artinchip/hal/wri/hal_wri.c

390 lines
12 KiB
C
Raw Normal View History

2023-08-30 16:21:18 +08:00
/*
* Copyright (c) 2023, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: matteo <duanmt@artinchip.com>
*/
#include "aic_core.h"
#include "aic_reboot_reason.h"
#include "hal_wri.h"
/* Register of WRI */
#define WRI_RST_FLAG (WRI_BASE + 0x0)
#define WRI_BOOT_INFO (WRI_BASE + 0x100)
#define WRI_SYS_BAK (WRI_BASE + 0x104)
#define WRI_VERSION (WRI_BASE + 0xFFC)
2023-11-09 20:19:51 +08:00
#if defined(AIC_WRI_DRV_V12) || defined(AIC_WRI_DRV_V11) || defined(AIC_WRI_DRV_V10)
2023-08-30 16:21:18 +08:00
#define WRI_FLAG_CMP_RST BIT(12)
#define WRI_FLAG_TSEN_RST BIT(11)
#define WRI_FLAG_WDT_RST BIT(10)
#define WRI_FLAG_DM_RST BIT(9)
#define WRI_FLAG_EXT_RST BIT(8)
#define WRI_FLAG_RTC_RST BIT(1)
#define WRI_FLAG_SYS_POR BIT(0)
2023-11-09 20:19:51 +08:00
#endif
#if defined(AIC_WRI_DRV_V13)
#define WRI_FLAG_SE_DM_NDM_RST BIT(29)
#define WRI_FLAG_SE_WDOG_RST BIT(28)
#define WRI_FLAG_SC_DM_CPU_RST BIT(26)
#define WRI_FLAG_SC_DM_NDM_RST BIT(25)
#define WRI_FLAG_SC_WDOG_RST BIT(24)
#define WRI_FLAG_CS_DM_CPU_RST BIT(22)
#define WRI_FLAG_CS_DM_NDM_RST BIT(21)
#define WRI_FLAG_CS_WDOG_RST BIT(20)
#define WRI_FLAG_SP_DM_CPU_RST BIT(18)
#define WRI_FLAG_SP_DM_NDM_RST BIT(17)
#define WRI_FLAG_SP_WDOG_RST BIT(16)
#define WRI_FLAG_THS_RST BIT(9)
#define WRI_FLAG_PIN_RST BIT(8)
#define WRI_FLAG_RTC_POR BIT(2)
#define WRI_FLAG_VDD11_SW_POR BIT(1)
#define WRI_FLAG_VDD11_SP_POR BIT(0)
#endif
2023-08-30 16:21:18 +08:00
#define WRI_REBOOT_REASON_MASK GENMASK(7, 4)
#define WRI_REBOOT_REASON_SHIFT 4
struct reboot_info {
u32 inited;
enum aic_reboot_reason reason;
enum aic_reboot_reason sw_reason;
enum aic_warm_reset_type hw_reason;
};
static struct reboot_info g_last_reboot = {0};
2023-11-09 20:19:51 +08:00
#if defined(AIC_WRI_DRV_V12) || defined(AIC_WRI_DRV_V11) || defined(AIC_WRI_DRV_V10)
2023-08-30 16:21:18 +08:00
enum aic_warm_reset_type aic_wr_type_get(void)
{
u32 val = 0;
u16 wr_bit[WRI_TYPE_MAX] = {
WRI_FLAG_SYS_POR, WRI_FLAG_RTC_RST, WRI_FLAG_EXT_RST, WRI_FLAG_DM_RST,
WRI_FLAG_WDT_RST, WRI_FLAG_TSEN_RST, WRI_FLAG_CMP_RST};
s32 i;
if (g_last_reboot.inited)
return g_last_reboot.hw_reason;
val = readl(WRI_RST_FLAG);
if (!val)
return WRI_TYPE_POR;
writel(val, WRI_RST_FLAG); /* clear the flag */
for (i = WRI_TYPE_MAX - 1; i >= 0; i--) {
if (val & wr_bit[i]) {
g_last_reboot.hw_reason = (enum aic_warm_reset_type)i;
return g_last_reboot.hw_reason;
}
}
pr_warn("Invalid warm reset flag: %#x\n", val);
return WRI_TYPE_POR;
}
enum aic_reboot_reason aic_judge_reboot_reason(enum aic_warm_reset_type hw,
u32 sw)
{
enum aic_reboot_reason r = (enum aic_reboot_reason)sw;
/* First, check the software-triggered reboot */
if (hw == WRI_TYPE_WDT) {
printf("Reboot action: Watchdog-Reset, reason: ");
switch (sw) {
case REBOOT_REASON_UPGRADE:
printf("Upgrade-Mode\n");
break;
case REBOOT_REASON_CMD_REBOOT:
printf("Command-Reboot\n");
break;
case REBOOT_REASON_SW_LOCKUP:
printf("Software-Lockup\n");
break;
case REBOOT_REASON_HW_LOCKUP:
printf("Hardware-Lockup\n");
break;
case REBOOT_REASON_PANIC:
printf("Kernel-Panic\n");
break;
case REBOOT_REASON_RAMDUMP:
printf("Ramdump\n");
break;
default:
printf("Unknown(%d)\n", r);
break;
}
return r;
}
if (r == REBOOT_REASON_CMD_SHUTDOWN) {
printf("Reboot reason: Command-Poweroff\n");
return r;
}
if (r == REBOOT_REASON_SUSPEND) {
pr_info("Reboot reason: Suspend\n");
return r;
}
/* Second, check the hardware-triggered reboot */
if (r == REBOOT_REASON_COLD) {
if (hw == WRI_TYPE_POR) {
printf("Startup reason: Power-On-Reset\n");
return (enum aic_reboot_reason)sw;
}
printf("Reboot action: Warm-Reset, reason: ");
switch (hw) {
case WRI_TYPE_RTC:
printf("RTC-Power-Down\n");
r = REBOOT_REASON_RTC;
break;
case WRI_TYPE_EXT:
printf("External-Reset\n");
r = REBOOT_REASON_EXTEND;
break;
case WRI_TYPE_DM:
printf("JTAG-Reset\n");
r = REBOOT_REASON_JTAG;
break;
case WRI_TYPE_TSEN:
printf("OTP-Reset\n");
r = REBOOT_REASON_OTP;
break;
case WRI_TYPE_CMP:
printf("Undervoltage-Reset\n");
r = REBOOT_REASON_UNDER_VOL;
break;
default:
printf("Unknown(%d)\n", hw);
break;
}
return r;
}
pr_warn("Unknow reboot reason: %d - %d\n", hw, sw);
return r;
}
2023-11-09 20:19:51 +08:00
#endif
#if defined(AIC_WRI_DRV_V13)
enum aic_warm_reset_type aic_wr_type_get(void)
{
u32 val = 0;
u32 wr_bit[WRI_TYPE_MAX] = {WRI_FLAG_VDD11_SP_POR,
WRI_FLAG_VDD11_SW_POR,
WRI_FLAG_RTC_POR,
WRI_FLAG_PIN_RST,
WRI_FLAG_THS_RST,
WRI_FLAG_SP_WDOG_RST,
WRI_FLAG_SP_DM_NDM_RST,
WRI_FLAG_SP_DM_CPU_RST,
WRI_FLAG_CS_WDOG_RST,
WRI_FLAG_CS_DM_NDM_RST,
WRI_FLAG_CS_DM_CPU_RST,
WRI_FLAG_SC_WDOG_RST,
WRI_FLAG_SC_DM_NDM_RST,
WRI_FLAG_SC_DM_CPU_RST,
WRI_FLAG_SE_WDOG_RST,
WRI_FLAG_SE_DM_NDM_RST
};
s32 i;
if (g_last_reboot.inited)
return g_last_reboot.hw_reason;
val = readl(WRI_RST_FLAG);
if (!val)
return WRI_TYPE_VDD11_SP_POR;
writel(val, WRI_RST_FLAG); /* clear the flag */
for (i = WRI_TYPE_MAX - 1; i >= 0; i--) {
if (val & wr_bit[i]) {
g_last_reboot.hw_reason = (enum aic_warm_reset_type)i;
return g_last_reboot.hw_reason;
}
}
pr_warn("Invalid warm reset flag: %#x\n", val);
return WRI_TYPE_VDD11_SP_POR;
}
enum aic_reboot_reason aic_judge_reboot_reason(enum aic_warm_reset_type hw,
u32 sw)
{
enum aic_reboot_reason r = (enum aic_reboot_reason)sw;
/* First, check the software-triggered reboot */
if (hw == WRI_TYPE_SP_WDOG_RST || hw == WRI_TYPE_CS_WDOG_RST || hw == WRI_TYPE_SC_WDOG_RST || hw == WRI_TYPE_SE_WDOG_RST) {
pr_info("Reboot action: Watchdog-Reset");
switch (sw) {
case REBOOT_REASON_UPGRADE:
pr_info("Reboot reason: Upgrade-Mode\n");
break;
case REBOOT_REASON_SW_LOCKUP:
pr_info("Reboot reason: Software-Lockup\n");
break;
case REBOOT_REASON_HW_LOCKUP:
pr_info("Reboot reason: Hardware-Lockup\n");
break;
case REBOOT_REASON_PANIC:
pr_info("Reboot reason: Kernel-Panic\n");
break;
case REBOOT_REASON_CS_CMD_REBOOT:
pr_info("Reboot reason: CS Command-Reboot\n");
break;
case REBOOT_REASON_SC_CMD_REBOOT:
pr_info("Reboot reason: SC Command-Reboot\n");
break;
case REBOOT_REASON_SP_CMD_REBOOT:
pr_info("Reboot reason: SP Command-Reboot\n");
break;
case REBOOT_REASON_RAMDUMP:
pr_info("Ramdump\n");
break;
default:
pr_info("Unknown(%d)\n", r);
break;
}
return r;
}
if (r == REBOOT_REASON_CMD_SHUTDOWN) {
printf("Reboot reason: Command-Poweroff\n");
return r;
}
if (r == REBOOT_REASON_SUSPEND) {
pr_info("Reboot reason: Suspend\n");
return r;
}
/* Second, check the hardware-triggered reboot */
if (r == REBOOT_REASON_COLD) {
if (hw == WRI_TYPE_VDD11_SP_POR) {
printf("Startup reason: Power-On-Reset\n");
return (enum aic_reboot_reason)sw;
}
if (hw == WRI_TYPE_VDD11_SW_POR) {
pr_info("Startup reason: SW Power-On-Reset\n");
return (enum aic_reboot_reason)sw;
}
printf("Reboot action: Warm-Reset, reason: ");
switch (hw) {
case WRI_TYPE_RTC_POR:
pr_info("Reboot reason: RTC-Power-Down\n");
r = REBOOT_REASON_RTC_POR;
break;
case WRI_TYPE_PIN_RST:
pr_info("Reboot reason: Extend-Reset\n");
r = REBOOT_REASON_PIN_RST;
break;
case WRI_TYPE_THS_RST:
pr_info("Reboot reason: OTP-Reset\n");
r = REBOOT_REASON_THS_RST;
break;
case WRI_TYPE_SP_DM_NDM_RST:
pr_info("Reboot reason: SP NDM Reset\n");
r = REBOOT_REASON_SP_DM_NDM_RST;
break;
case WRI_TYPE_SP_DM_CPU_RST:
pr_info("Reboot reason: SP JTAG-Reset\n");
r = REBOOT_REASON_SP_DM_CPU_RST;
break;
case WRI_TYPE_CS_DM_NDM_RST:
pr_info("Reboot reason: CS NDM Reset\n");
r = REBOOT_REASON_CS_DM_NDM_RST;
break;
case WRI_TYPE_CS_DM_CPU_RST:
pr_info("Reboot reason: CS JTAG-Reset\n");
r = REBOOT_REASON_CS_DM_CPU_RST;
break;
case WRI_TYPE_SC_DM_NDM_RST:
pr_info("Reboot reason: SC NDM Reset\n");
r = REBOOT_REASON_SC_DM_NDM_RST;
break;
case WRI_TYPE_SC_DM_CPU_RST:
pr_info("Reboot reason: SC JTAG-Reset\n");
r = REBOOT_REASON_SC_DM_CPU_RST;
break;
case WRI_TYPE_SE_DM_NDM_RST:
pr_info("Reboot reason: SE NDM Reset\n");
r = REBOOT_REASON_SE_DM_NDM_RST;
break;
default:
printf("Unknown(%d)\n", hw);
break;
}
return r;
}
pr_warn("Unknow reboot reason: %d - %d\n", hw, sw);
return r;
}
#endif
2023-08-30 16:21:18 +08:00
#if defined(AIC_WRI_DRV_V12)
void aic_set_reboot_reason(enum aic_reboot_reason r)
{
2023-11-09 20:19:51 +08:00
u8 reason_num = RTC_REBOOT_REASON_MASK >> RTC_REBOOT_REASON_SHIFT;
2023-08-30 16:21:18 +08:00
writel_bits(r, WRI_REBOOT_REASON_MASK, WRI_REBOOT_REASON_SHIFT,
WRI_SYS_BAK);
2023-11-09 20:19:51 +08:00
if (r <= reason_num)
2023-08-30 16:21:18 +08:00
pr_debug("Set reboot reason %d\n", r);
}
enum aic_reboot_reason aic_get_reboot_reason(void)
{
u32 val = 0;
enum aic_warm_reset_type hw = aic_wr_type_get();
if (g_last_reboot.inited)
return g_last_reboot.reason;
val = readl_bits(WRI_REBOOT_REASON_MASK, WRI_REBOOT_REASON_SHIFT,
WRI_SYS_BAK);
if (val)
aic_set_reboot_reason(REBOOT_REASON_COLD);
pr_debug("Last reboot info: hw %d, sw %d\n", hw, val);
g_last_reboot.reason = aic_judge_reboot_reason(hw, val);
g_last_reboot.inited = 1;
return g_last_reboot.reason;
}
/* Convert and print the time info from a GTC counter.
It's useful when print the time before console is ready. */
void aic_show_gtc_time(char *tag, u32 val)
{
u32 sec, msec;
u32 cnt = val;
if (!cnt)
cnt = readl(GTC_BASE + 0x8);
sec = cnt / 4000000;
msec = (cnt % 4000000) / 4 / 1000;
printf("[%s] time: %d.%03d sec\n", tag ? tag : "GTC", sec, msec);
}
2023-11-09 20:19:51 +08:00
void aic_show_startup_time(void)
2023-08-30 16:21:18 +08:00
{
u32 cnt = readl(GTC_BASE + 0x8);
aic_show_gtc_time("Startup", cnt);
}
#endif