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

146 lines
3.6 KiB
C
Raw Normal View History

2023-08-30 16:21:18 +08:00
/*
2024-09-03 11:16:08 +08:00
* Copyright (c) 2023-2024, ArtInChip Technology Co., Ltd
2023-08-30 16:21:18 +08:00
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: matteo <duanmt@artinchip.com>
*/
#include "aic_core.h"
#include "hal_wri.h"
2024-09-03 11:16:08 +08:00
#define GTC_CNTVL 0x8
#define GTC_CLK_FREQ 4000000
2023-08-30 16:21:18 +08:00
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};
2024-09-03 11:16:08 +08:00
static const struct aic_wri_ops *ops = &wri_ops;
2023-08-30 16:21:18 +08:00
enum aic_warm_reset_type aic_wr_type_get(void)
{
s32 i;
2024-09-03 11:16:08 +08:00
u32 val = 0;
2023-08-30 16:21:18 +08:00
if (g_last_reboot.inited)
return g_last_reboot.hw_reason;
val = readl(WRI_RST_FLAG);
if (!val)
2024-09-03 11:16:08 +08:00
return WRI_TYPE_ERR;
2023-08-30 16:21:18 +08:00
for (i = WRI_TYPE_MAX - 1; i >= 0; i--) {
2024-09-03 11:16:08 +08:00
if (val & ops->wri_bit[i]) {
2023-08-30 16:21:18 +08:00
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);
2024-09-03 11:16:08 +08:00
return WRI_TYPE_ERR;
2023-08-30 16:21:18 +08:00
}
enum aic_reboot_reason aic_judge_reboot_reason(enum aic_warm_reset_type hw,
u32 sw)
{
2024-09-03 11:16:08 +08:00
int ret;
2023-08-30 16:21:18 +08:00
enum aic_reboot_reason r = (enum aic_reboot_reason)sw;
/* First, check the software-triggered reboot */
2024-09-03 11:16:08 +08:00
if (wri_ops.reset_type(hw)) {
#if defined(AIC_WRI_DRV_V12) || defined(AIC_WRI_DRV_V11) || defined(AIC_WRI_DRV_V10)
wri_ops.sw_reboot_reason(sw, r);
2023-11-09 20:19:51 +08:00
#endif
#if defined(AIC_WRI_DRV_V13)
2024-09-03 11:16:08 +08:00
wri_ops.hw_reboot_action(hw);
wri_ops.sw_reboot_reason(sw, r);
#endif
2023-11-09 20:19:51 +08:00
return r;
}
/* Second, check the hardware-triggered reboot */
2024-09-03 11:16:08 +08:00
ret = wri_ops.hw_reboot_reason(hw, &r, sw);
if (ret >= 0) {
return (enum aic_reboot_reason)ret;
2023-11-09 20:19:51 +08:00
}
2024-01-27 08:47:24 +08:00
pr_warn("Unknown reboot reason: %d - %d\n", hw, sw);
2023-11-09 20:19:51 +08:00
return r;
}
2023-08-30 16:21:18 +08:00
void aic_set_reboot_reason(enum aic_reboot_reason r)
{
2024-01-27 08:47:24 +08:00
u32 cur = 0;
2023-11-30 19:48:02 +08:00
u8 reason_num = WRI_REBOOT_REASON_MASK >> WRI_REBOOT_REASON_SHIFT;
2023-11-09 20:19:51 +08:00
2024-09-03 11:16:08 +08:00
cur = GET_REG_STATUS(REG_BOOT_INFO);
2024-01-27 08:47:24 +08:00
/* If it's valid already, so ignore the current request */
if (cur & WRI_REBOOT_REASON_MASK)
return;
2024-09-03 11:16:08 +08:00
BOOT_INFO_SET(r, WRI_REBOOT_REASON_MASK, WRI_REBOOT_REASON_SHIFT, cur);
2023-08-30 16:21:18 +08:00
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;
2024-09-03 11:16:08 +08:00
BOOT_INFO_GET(WRI_REBOOT_REASON_MASK, WRI_REBOOT_REASON_SHIFT, val);
2023-08-30 16:21:18 +08:00
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;
2024-04-03 16:40:57 +08:00
2023-08-30 16:21:18 +08:00
return g_last_reboot.reason;
}
2024-09-03 11:16:08 +08:00
void aic_clr_reboot_reason(void)
{
u32 val = 0;
val = readl(WRI_RST_FLAG);
writel(val, WRI_RST_FLAG); /* clear the flag */
BOOT_INFO_GET(WRI_REBOOT_REASON_MASK, WRI_REBOOT_REASON_SHIFT, val);
if (val) {
/* Clear the previous state */
clrbits(WRI_REBOOT_REASON_MASK, val);
BOOT_INFO_WRITEB(val);
}
return;
}
2023-08-30 16:21:18 +08:00
/* 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)
2024-09-03 11:16:08 +08:00
cnt = readl(GTC_BASE + GTC_CNTVL);
2023-08-30 16:21:18 +08:00
2024-09-03 11:16:08 +08:00
sec = cnt / GTC_CLK_FREQ;
msec = (cnt % GTC_CLK_FREQ) / 4 / 1000;
printf("\n%s time: %d.%03d sec\n", tag ? tag : "GTC", sec, msec);
2023-08-30 16:21:18 +08:00
}
2023-11-09 20:19:51 +08:00
void aic_show_startup_time(void)
2023-08-30 16:21:18 +08:00
{
2024-09-03 11:16:08 +08:00
u32 cnt = readl(GTC_BASE + GTC_CNTVL);
2023-08-30 16:21:18 +08:00
aic_show_gtc_time("Startup", cnt);
}