- nuvoton: add expire function for generic reset (Jim) - handle watchdogs during keyed autoboot (Rasmus) - cyclic: Don't disable cylic function upon exceeding CPU time (Stefan) - ulp wdog: Updates to support iMX93 and DM (Alice)
This commit is contained in:
@@ -130,6 +130,23 @@ void os_exit(int exit_code)
|
|||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int os_alarm(unsigned int seconds)
|
||||||
|
{
|
||||||
|
return alarm(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void os_set_alarm_handler(void (*handler)(int))
|
||||||
|
{
|
||||||
|
if (!handler)
|
||||||
|
handler = SIG_DFL;
|
||||||
|
signal(SIGALRM, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void os_raise_sigalrm(void)
|
||||||
|
{
|
||||||
|
raise(SIGALRM);
|
||||||
|
}
|
||||||
|
|
||||||
int os_write_file(const char *fname, const void *buf, int size)
|
int os_write_file(const char *fname, const void *buf, int size)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@@ -27,6 +27,12 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
alarm_wdt: alarm-wdt {
|
||||||
|
compatible = "sandbox,alarm-wdt";
|
||||||
|
timeout-sec = <5>;
|
||||||
|
u-boot,autostart;
|
||||||
|
};
|
||||||
|
|
||||||
audio: audio-codec {
|
audio: audio-codec {
|
||||||
compatible = "sandbox,audio-codec";
|
compatible = "sandbox,audio-codec";
|
||||||
#sound-dai-cells = <1>;
|
#sound-dai-cells = <1>;
|
||||||
|
@@ -85,13 +85,17 @@ void cyclic_run(void)
|
|||||||
cyclic->cpu_time_us += cpu_time;
|
cyclic->cpu_time_us += cpu_time;
|
||||||
|
|
||||||
/* Check if cpu-time exceeds max allowed time */
|
/* Check if cpu-time exceeds max allowed time */
|
||||||
if (cpu_time > CONFIG_CYCLIC_MAX_CPU_TIME_US) {
|
if ((cpu_time > CONFIG_CYCLIC_MAX_CPU_TIME_US) &&
|
||||||
pr_err("cyclic function %s took too long: %lldus vs %dus max, disabling\n",
|
(!cyclic->already_warned)) {
|
||||||
|
pr_err("cyclic function %s took too long: %lldus vs %dus max\n",
|
||||||
cyclic->name, cpu_time,
|
cyclic->name, cpu_time,
|
||||||
CONFIG_CYCLIC_MAX_CPU_TIME_US);
|
CONFIG_CYCLIC_MAX_CPU_TIME_US);
|
||||||
|
|
||||||
/* Unregister this cyclic function */
|
/*
|
||||||
cyclic_unregister(cyclic);
|
* Don't disable this function, just warn once
|
||||||
|
* about this exceeding CPU time usage
|
||||||
|
*/
|
||||||
|
cyclic->already_warned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,7 @@ CONFIG_CMD_REMOTEPROC=y
|
|||||||
CONFIG_CMD_SPI=y
|
CONFIG_CMD_SPI=y
|
||||||
CONFIG_CMD_USB=y
|
CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_CAT=y
|
CONFIG_CMD_CAT=y
|
||||||
|
CONFIG_CMD_WDT=y
|
||||||
CONFIG_BOOTP_DNS2=y
|
CONFIG_BOOTP_DNS2=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_TFTPSRV=y
|
CONFIG_CMD_TFTPSRV=y
|
||||||
@@ -238,6 +239,7 @@ CONFIG_SPLASH_SCREEN_ALIGN=y
|
|||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_GPIO=y
|
CONFIG_WDT_GPIO=y
|
||||||
CONFIG_WDT_SANDBOX=y
|
CONFIG_WDT_SANDBOX=y
|
||||||
|
CONFIG_WDT_ALARM_SANDBOX=y
|
||||||
CONFIG_FS_CBFS=y
|
CONFIG_FS_CBFS=y
|
||||||
CONFIG_FS_CRAMFS=y
|
CONFIG_FS_CRAMFS=y
|
||||||
CONFIG_CMD_DHRYSTONE=y
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
|
@@ -80,6 +80,7 @@ CONFIG_CMD_REMOTEPROC=y
|
|||||||
CONFIG_CMD_SPI=y
|
CONFIG_CMD_SPI=y
|
||||||
CONFIG_CMD_TEMPERATURE=y
|
CONFIG_CMD_TEMPERATURE=y
|
||||||
CONFIG_CMD_USB=y
|
CONFIG_CMD_USB=y
|
||||||
|
CONFIG_CMD_WDT=y
|
||||||
CONFIG_CMD_AXI=y
|
CONFIG_CMD_AXI=y
|
||||||
CONFIG_CMD_CAT=y
|
CONFIG_CMD_CAT=y
|
||||||
CONFIG_CMD_SETEXPR_FMT=y
|
CONFIG_CMD_SETEXPR_FMT=y
|
||||||
@@ -314,6 +315,7 @@ CONFIG_W1_EEPROM_SANDBOX=y
|
|||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_GPIO=y
|
CONFIG_WDT_GPIO=y
|
||||||
CONFIG_WDT_SANDBOX=y
|
CONFIG_WDT_SANDBOX=y
|
||||||
|
CONFIG_WDT_ALARM_SANDBOX=y
|
||||||
CONFIG_FS_CBFS=y
|
CONFIG_FS_CBFS=y
|
||||||
CONFIG_FS_CRAMFS=y
|
CONFIG_FS_CRAMFS=y
|
||||||
CONFIG_ADDR_MAP=y
|
CONFIG_ADDR_MAP=y
|
||||||
|
@@ -6,7 +6,8 @@ Optional properties:
|
|||||||
be used instead.
|
be used instead.
|
||||||
- hw_margin_ms : Period used to reset the watchdog in ms
|
- hw_margin_ms : Period used to reset the watchdog in ms
|
||||||
If this period is not defined, the default value is 1000.
|
If this period is not defined, the default value is 1000.
|
||||||
- u-boot,noautostart : Specify that this watchdog should not autostart
|
- u-boot,noautostart :
|
||||||
When the config option WATCHDOG_AUTOSTART is set, all enabled
|
- u-boot,autostart : These (mutually exclusive) boolean properties can be used to control
|
||||||
watchdogs are started. This property allows specifying that this
|
whether the watchdog is automatically started when probed. If neither
|
||||||
watchdog should NOT be started.
|
are present, the behaviour is determined by the config option
|
||||||
|
WATCHDOG_AUTOSTART.
|
||||||
|
@@ -281,6 +281,14 @@ config WDT_SANDBOX
|
|||||||
can be probed and supports all of the methods of WDT, but does not
|
can be probed and supports all of the methods of WDT, but does not
|
||||||
really do anything.
|
really do anything.
|
||||||
|
|
||||||
|
config WDT_ALARM_SANDBOX
|
||||||
|
bool "Enable SIGALRM-based Watchdog Timer support for Sandbox"
|
||||||
|
depends on SANDBOX && WDT
|
||||||
|
help
|
||||||
|
Enable support for a SIGALRM-based watchdog timer in Sandbox. This is
|
||||||
|
a watchdog device based on the host OS' alarm() function, which will
|
||||||
|
kill the sandbox with SIGALRM unless properly maintained.
|
||||||
|
|
||||||
config WDT_SBSA
|
config WDT_SBSA
|
||||||
bool "SBSA watchdog timer support"
|
bool "SBSA watchdog timer support"
|
||||||
depends on WDT
|
depends on WDT
|
||||||
|
@@ -16,6 +16,7 @@ obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
|
|||||||
obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
|
obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
|
obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
|
||||||
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
|
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
|
||||||
|
obj-$(CONFIG_WDT_ALARM_SANDBOX) += sandbox_alarm-wdt.o
|
||||||
obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
|
obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
|
||||||
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
|
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
|
||||||
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
|
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
|
||||||
|
@@ -75,6 +75,11 @@ static int npcm_wdt_reset(struct udevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int npcm_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||||
|
{
|
||||||
|
return npcm_wdt_reset(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int npcm_wdt_of_to_plat(struct udevice *dev)
|
static int npcm_wdt_of_to_plat(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct npcm_wdt_priv *priv = dev_get_priv(dev);
|
struct npcm_wdt_priv *priv = dev_get_priv(dev);
|
||||||
@@ -87,6 +92,7 @@ static int npcm_wdt_of_to_plat(struct udevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct wdt_ops npcm_wdt_ops = {
|
static const struct wdt_ops npcm_wdt_ops = {
|
||||||
|
.expire_now = npcm_wdt_expire_now,
|
||||||
.start = npcm_wdt_start,
|
.start = npcm_wdt_start,
|
||||||
.reset = npcm_wdt_reset,
|
.reset = npcm_wdt_reset,
|
||||||
.stop = npcm_wdt_stop,
|
.stop = npcm_wdt_stop,
|
||||||
|
79
drivers/watchdog/sandbox_alarm-wdt.c
Normal file
79
drivers/watchdog/sandbox_alarm-wdt.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <os.h>
|
||||||
|
#include <wdt.h>
|
||||||
|
|
||||||
|
struct alarm_wdt_priv {
|
||||||
|
unsigned int timeout_sec;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void alarm_handler(int sig)
|
||||||
|
{
|
||||||
|
const char *msg = "!!! ALARM !!!\n";
|
||||||
|
|
||||||
|
os_write(2, msg, strlen(msg));
|
||||||
|
os_fd_restore();
|
||||||
|
os_set_alarm_handler(NULL);
|
||||||
|
os_raise_sigalrm();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alarm_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
|
||||||
|
{
|
||||||
|
struct alarm_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
unsigned int sec;
|
||||||
|
|
||||||
|
timeout = DIV_ROUND_UP(timeout, 1000);
|
||||||
|
sec = min_t(u64, UINT_MAX, timeout);
|
||||||
|
priv->timeout_sec = sec;
|
||||||
|
|
||||||
|
os_alarm(0);
|
||||||
|
os_set_alarm_handler(alarm_handler);
|
||||||
|
os_alarm(sec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alarm_wdt_stop(struct udevice *dev)
|
||||||
|
{
|
||||||
|
os_alarm(0);
|
||||||
|
os_set_alarm_handler(NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alarm_wdt_reset(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct alarm_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
os_alarm(priv->timeout_sec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int alarm_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||||
|
{
|
||||||
|
alarm_handler(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct wdt_ops alarm_wdt_ops = {
|
||||||
|
.start = alarm_wdt_start,
|
||||||
|
.reset = alarm_wdt_reset,
|
||||||
|
.stop = alarm_wdt_stop,
|
||||||
|
.expire_now = alarm_wdt_expire_now,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id alarm_wdt_ids[] = {
|
||||||
|
{ .compatible = "sandbox,alarm-wdt" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(alarm_wdt_sandbox) = {
|
||||||
|
.name = "alarm_wdt_sandbox",
|
||||||
|
.id = UCLASS_WDT,
|
||||||
|
.of_match = alarm_wdt_ids,
|
||||||
|
.ops = &alarm_wdt_ops,
|
||||||
|
.priv_auto = sizeof(struct alarm_wdt_priv),
|
||||||
|
};
|
@@ -7,6 +7,8 @@
|
|||||||
#include <cpu_func.h>
|
#include <cpu_func.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/arch/imx-regs.h>
|
#include <asm/arch/imx-regs.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <wdt.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MX7ULP WDOG Register Map
|
* MX7ULP WDOG Register Map
|
||||||
@@ -18,6 +20,11 @@ struct wdog_regs {
|
|||||||
u32 win;
|
u32 win;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ulp_wdt_priv {
|
||||||
|
struct wdog_regs *wdog;
|
||||||
|
u32 clk_rate;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
|
#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
|
||||||
#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
|
#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
|
||||||
#endif
|
#endif
|
||||||
@@ -28,18 +35,27 @@ struct wdog_regs {
|
|||||||
#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
|
#define UNLOCK_WORD0 0xC520 /* 1st unlock word */
|
||||||
#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
|
#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */
|
||||||
|
|
||||||
|
#define UNLOCK_WORD 0xD928C520 /* unlock word */
|
||||||
|
#define REFRESH_WORD 0xB480A602 /* refresh word */
|
||||||
|
|
||||||
#define WDGCS_WDGE BIT(7)
|
#define WDGCS_WDGE BIT(7)
|
||||||
#define WDGCS_WDGUPDATE BIT(5)
|
#define WDGCS_WDGUPDATE BIT(5)
|
||||||
|
|
||||||
#define WDGCS_RCS BIT(10)
|
#define WDGCS_RCS BIT(10)
|
||||||
#define WDGCS_ULK BIT(11)
|
#define WDGCS_ULK BIT(11)
|
||||||
|
#define WDOG_CS_PRES BIT(12)
|
||||||
|
#define WDGCS_CMD32EN BIT(13)
|
||||||
#define WDGCS_FLG BIT(14)
|
#define WDGCS_FLG BIT(14)
|
||||||
|
#define WDGCS_INT BIT(6)
|
||||||
|
|
||||||
#define WDG_BUS_CLK (0x0)
|
#define WDG_BUS_CLK (0x0)
|
||||||
#define WDG_LPO_CLK (0x1)
|
#define WDG_LPO_CLK (0x1)
|
||||||
#define WDG_32KHZ_CLK (0x2)
|
#define WDG_32KHZ_CLK (0x2)
|
||||||
#define WDG_EXT_CLK (0x3)
|
#define WDG_EXT_CLK (0x3)
|
||||||
|
|
||||||
|
#define CLK_RATE_1KHZ 1000
|
||||||
|
#define CLK_RATE_32KHZ 125
|
||||||
|
|
||||||
void hw_watchdog_set_timeout(u16 val)
|
void hw_watchdog_set_timeout(u16 val)
|
||||||
{
|
{
|
||||||
/* setting timeout value */
|
/* setting timeout value */
|
||||||
@@ -48,60 +64,96 @@ void hw_watchdog_set_timeout(u16 val)
|
|||||||
writel(val, &wdog->toval);
|
writel(val, &wdog->toval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hw_watchdog_reset(void)
|
void ulp_watchdog_reset(struct wdog_regs *wdog)
|
||||||
{
|
{
|
||||||
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
if (readl(&wdog->cs) & WDGCS_CMD32EN) {
|
||||||
|
writel(REFRESH_WORD, &wdog->cnt);
|
||||||
|
} else {
|
||||||
dmb();
|
dmb();
|
||||||
__raw_writel(REFRESH_WORD0, &wdog->cnt);
|
__raw_writel(REFRESH_WORD0, &wdog->cnt);
|
||||||
__raw_writel(REFRESH_WORD1, &wdog->cnt);
|
__raw_writel(REFRESH_WORD1, &wdog->cnt);
|
||||||
dmb();
|
dmb();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ulp_watchdog_init(struct wdog_regs *wdog, u16 timeout)
|
||||||
|
{
|
||||||
|
u32 cmd32 = 0;
|
||||||
|
|
||||||
|
if (readl(&wdog->cs) & WDGCS_CMD32EN) {
|
||||||
|
writel(UNLOCK_WORD, &wdog->cnt);
|
||||||
|
cmd32 = WDGCS_CMD32EN;
|
||||||
|
} else {
|
||||||
|
dmb();
|
||||||
|
__raw_writel(UNLOCK_WORD0, &wdog->cnt);
|
||||||
|
__raw_writel(UNLOCK_WORD1, &wdog->cnt);
|
||||||
|
dmb();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait WDOG Unlock */
|
||||||
|
while (!(readl(&wdog->cs) & WDGCS_ULK))
|
||||||
|
;
|
||||||
|
|
||||||
|
hw_watchdog_set_timeout(timeout);
|
||||||
|
writel(0, &wdog->win);
|
||||||
|
|
||||||
|
/* setting 1-kHz clock source, enable counter running, and clear interrupt */
|
||||||
|
if (IS_ENABLED(CONFIG_ARCH_IMX9))
|
||||||
|
writel((cmd32 | WDGCS_WDGE | WDGCS_WDGUPDATE | (WDG_LPO_CLK << 8) |
|
||||||
|
WDGCS_FLG | WDOG_CS_PRES | WDGCS_INT), &wdog->cs);
|
||||||
|
else
|
||||||
|
writel((cmd32 | WDGCS_WDGE | WDGCS_WDGUPDATE | (WDG_LPO_CLK << 8) |
|
||||||
|
WDGCS_FLG), &wdog->cs);
|
||||||
|
|
||||||
|
/* Wait WDOG reconfiguration */
|
||||||
|
while (!(readl(&wdog->cs) & WDGCS_RCS))
|
||||||
|
;
|
||||||
|
|
||||||
|
ulp_watchdog_reset(wdog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw_watchdog_reset(void)
|
||||||
|
{
|
||||||
|
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
||||||
|
|
||||||
|
ulp_watchdog_reset(wdog);
|
||||||
|
}
|
||||||
|
|
||||||
void hw_watchdog_init(void)
|
void hw_watchdog_init(void)
|
||||||
{
|
{
|
||||||
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
||||||
|
|
||||||
dmb();
|
ulp_watchdog_init(wdog, CONFIG_WATCHDOG_TIMEOUT_MSECS);
|
||||||
__raw_writel(UNLOCK_WORD0, &wdog->cnt);
|
|
||||||
__raw_writel(UNLOCK_WORD1, &wdog->cnt);
|
|
||||||
dmb();
|
|
||||||
|
|
||||||
/* Wait WDOG Unlock */
|
|
||||||
while (!(readl(&wdog->cs) & WDGCS_ULK))
|
|
||||||
;
|
|
||||||
|
|
||||||
hw_watchdog_set_timeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
|
|
||||||
writel(0, &wdog->win);
|
|
||||||
|
|
||||||
/* setting 1-kHz clock source, enable counter running, and clear interrupt */
|
|
||||||
writel((WDGCS_WDGE | WDGCS_WDGUPDATE |(WDG_LPO_CLK << 8) | WDGCS_FLG), &wdog->cs);
|
|
||||||
|
|
||||||
/* Wait WDOG reconfiguration */
|
|
||||||
while (!(readl(&wdog->cs) & WDGCS_RCS))
|
|
||||||
;
|
|
||||||
|
|
||||||
hw_watchdog_reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_cpu(void)
|
void reset_cpu(void)
|
||||||
{
|
{
|
||||||
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
|
||||||
|
u32 cmd32 = 0;
|
||||||
|
|
||||||
|
if (readl(&wdog->cs) & WDGCS_CMD32EN) {
|
||||||
|
writel(UNLOCK_WORD, &wdog->cnt);
|
||||||
|
cmd32 = WDGCS_CMD32EN;
|
||||||
|
} else {
|
||||||
dmb();
|
dmb();
|
||||||
__raw_writel(UNLOCK_WORD0, &wdog->cnt);
|
__raw_writel(UNLOCK_WORD0, &wdog->cnt);
|
||||||
__raw_writel(UNLOCK_WORD1, &wdog->cnt);
|
__raw_writel(UNLOCK_WORD1, &wdog->cnt);
|
||||||
dmb();
|
dmb();
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait WDOG Unlock */
|
/* Wait WDOG Unlock */
|
||||||
while (!(readl(&wdog->cs) & WDGCS_ULK))
|
while (!(readl(&wdog->cs) & WDGCS_ULK))
|
||||||
;
|
;
|
||||||
|
|
||||||
hw_watchdog_set_timeout(5); /* 5ms timeout */
|
hw_watchdog_set_timeout(5); /* 5ms timeout for general; 40ms timeout for imx93 */
|
||||||
writel(0, &wdog->win);
|
writel(0, &wdog->win);
|
||||||
|
|
||||||
/* enable counter running */
|
/* enable counter running */
|
||||||
writel((WDGCS_WDGE | (WDG_LPO_CLK << 8)), &wdog->cs);
|
if (IS_ENABLED(CONFIG_ARCH_IMX9))
|
||||||
|
writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8) | WDOG_CS_PRES |
|
||||||
|
WDGCS_INT), &wdog->cs);
|
||||||
|
else
|
||||||
|
writel((cmd32 | WDGCS_WDGE | (WDG_LPO_CLK << 8)), &wdog->cs);
|
||||||
|
|
||||||
/* Wait WDOG reconfiguration */
|
/* Wait WDOG reconfiguration */
|
||||||
while (!(readl(&wdog->cs) & WDGCS_RCS))
|
while (!(readl(&wdog->cs) & WDGCS_RCS))
|
||||||
@@ -111,3 +163,62 @@ void reset_cpu(void)
|
|||||||
|
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ulp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||||
|
{
|
||||||
|
struct ulp_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
u64 timeout = 0;
|
||||||
|
|
||||||
|
timeout = (timeout_ms * priv->clk_rate) / 1000;
|
||||||
|
if (timeout > U16_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ulp_watchdog_init(priv->wdog, (u16)timeout);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ulp_wdt_reset(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct ulp_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
ulp_watchdog_reset(priv->wdog);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ulp_wdt_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct ulp_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
priv->wdog = dev_read_addr_ptr(dev);
|
||||||
|
if (!priv->wdog)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
priv->clk_rate = (u32)dev_get_driver_data(dev);
|
||||||
|
if (!priv->clk_rate)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wdt_ops ulp_wdt_ops = {
|
||||||
|
.start = ulp_wdt_start,
|
||||||
|
.reset = ulp_wdt_reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id ulp_wdt_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx7ulp-wdt", .data = CLK_RATE_1KHZ },
|
||||||
|
{ .compatible = "fsl,imx8ulp-wdt", .data = CLK_RATE_1KHZ },
|
||||||
|
{ .compatible = "fsl,imx93-wdt", .data = CLK_RATE_32KHZ },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(ulp_wdt) = {
|
||||||
|
.name = "ulp_wdt",
|
||||||
|
.id = UCLASS_WDT,
|
||||||
|
.of_match = ulp_wdt_ids,
|
||||||
|
.priv_auto = sizeof(struct ulp_wdt_priv),
|
||||||
|
.probe = ulp_wdt_probe,
|
||||||
|
.ops = &ulp_wdt_ops,
|
||||||
|
};
|
||||||
|
@@ -37,8 +37,8 @@ struct wdt_priv {
|
|||||||
ulong next_reset;
|
ulong next_reset;
|
||||||
/* Whether watchdog_start() has been called on the device. */
|
/* Whether watchdog_start() has been called on the device. */
|
||||||
bool running;
|
bool running;
|
||||||
/* No autostart */
|
/* autostart */
|
||||||
bool noautostart;
|
bool autostart;
|
||||||
|
|
||||||
struct cyclic_info *cyclic;
|
struct cyclic_info *cyclic;
|
||||||
};
|
};
|
||||||
@@ -72,7 +72,7 @@ static void init_watchdog_dev(struct udevice *dev)
|
|||||||
dev->name);
|
dev->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART) || priv->noautostart) {
|
if (!priv->autostart) {
|
||||||
printf("WDT: Not starting %s\n", dev->name);
|
printf("WDT: Not starting %s\n", dev->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -267,19 +267,22 @@ static int wdt_pre_probe(struct udevice *dev)
|
|||||||
* indicated by a hw_margin_ms property.
|
* indicated by a hw_margin_ms property.
|
||||||
*/
|
*/
|
||||||
ulong reset_period = 1000;
|
ulong reset_period = 1000;
|
||||||
bool noautostart = false;
|
bool autostart = IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART);
|
||||||
struct wdt_priv *priv;
|
struct wdt_priv *priv;
|
||||||
|
|
||||||
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
timeout = dev_read_u32_default(dev, "timeout-sec", timeout);
|
timeout = dev_read_u32_default(dev, "timeout-sec", timeout);
|
||||||
reset_period = dev_read_u32_default(dev, "hw_margin_ms",
|
reset_period = dev_read_u32_default(dev, "hw_margin_ms",
|
||||||
4 * reset_period) / 4;
|
4 * reset_period) / 4;
|
||||||
noautostart = dev_read_bool(dev, "u-boot,noautostart");
|
if (dev_read_bool(dev, "u-boot,noautostart"))
|
||||||
|
autostart = false;
|
||||||
|
else if (dev_read_bool(dev, "u-boot,autostart"))
|
||||||
|
autostart = true;
|
||||||
}
|
}
|
||||||
priv = dev_get_uclass_priv(dev);
|
priv = dev_get_uclass_priv(dev);
|
||||||
priv->timeout = timeout;
|
priv->timeout = timeout;
|
||||||
priv->reset_period = reset_period;
|
priv->reset_period = reset_period;
|
||||||
priv->noautostart = noautostart;
|
priv->autostart = autostart;
|
||||||
/*
|
/*
|
||||||
* Pretend this device was last reset "long" ago so the first
|
* Pretend this device was last reset "long" ago so the first
|
||||||
* watchdog_reset will actually call its ->reset method.
|
* watchdog_reset will actually call its ->reset method.
|
||||||
|
@@ -39,6 +39,7 @@ struct cyclic_drv {
|
|||||||
* @run_cnt: Counter of executions occurances
|
* @run_cnt: Counter of executions occurances
|
||||||
* @next_call: Next time in us, when the function shall be executed again
|
* @next_call: Next time in us, when the function shall be executed again
|
||||||
* @list: List node
|
* @list: List node
|
||||||
|
* @already_warned: Flag that we've warned about exceeding CPU time usage
|
||||||
*/
|
*/
|
||||||
struct cyclic_info {
|
struct cyclic_info {
|
||||||
void (*func)(void *ctx);
|
void (*func)(void *ctx);
|
||||||
@@ -50,6 +51,7 @@ struct cyclic_info {
|
|||||||
uint64_t run_cnt;
|
uint64_t run_cnt;
|
||||||
uint64_t next_call;
|
uint64_t next_call;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
bool already_warned;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Function type for cyclic functions */
|
/** Function type for cyclic functions */
|
||||||
|
17
include/os.h
17
include/os.h
@@ -108,6 +108,23 @@ int os_unlink(const char *pathname);
|
|||||||
*/
|
*/
|
||||||
void os_exit(int exit_code) __attribute__((noreturn));
|
void os_exit(int exit_code) __attribute__((noreturn));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* os_alarm() - access to the OS alarm() system call
|
||||||
|
*/
|
||||||
|
unsigned int os_alarm(unsigned int seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* os_set_alarm_handler() - set handler for SIGALRM
|
||||||
|
*
|
||||||
|
* @handler: The handler function. Pass NULL for SIG_DFL.
|
||||||
|
*/
|
||||||
|
void os_set_alarm_handler(void (*handler)(int));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* os_raise_sigalrm() - do raise(SIGALRM)
|
||||||
|
*/
|
||||||
|
void os_raise_sigalrm(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* os_tty_raw() - put tty into raw mode to mimic serial console better
|
* os_tty_raw() - put tty into raw mode to mimic serial console better
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user