mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-07 07:46:59 +02:00
Merge tag 'u-boot-watchdog-20250730' of https://source.denx.de/u-boot/custodians/u-boot-watchdog
CI: https://dev.azure.com/sr0718/u-boot/_build/results?buildId=395&view=results - watchdog for STM32MP family updates (Antonio, Clément and Patrice)
This commit is contained in:
commit
bb708e8249
@ -89,6 +89,7 @@ CONFIG_DM_RTC=y
|
|||||||
CONFIG_RTC_STM32=y
|
CONFIG_RTC_STM32=y
|
||||||
CONFIG_SERIAL_RX_BUFFER=y
|
CONFIG_SERIAL_RX_BUFFER=y
|
||||||
CONFIG_SYSRESET_SYSCON=y
|
CONFIG_SYSRESET_SYSCON=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_STM32MP=y
|
CONFIG_WDT_STM32MP=y
|
||||||
# CONFIG_BINMAN_FDT is not set
|
# CONFIG_BINMAN_FDT is not set
|
||||||
|
@ -89,6 +89,7 @@ CONFIG_DM_RTC=y
|
|||||||
CONFIG_RTC_STM32=y
|
CONFIG_RTC_STM32=y
|
||||||
CONFIG_SERIAL_RX_BUFFER=y
|
CONFIG_SERIAL_RX_BUFFER=y
|
||||||
CONFIG_SYSRESET_SYSCON=y
|
CONFIG_SYSRESET_SYSCON=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_STM32MP=y
|
CONFIG_WDT_STM32MP=y
|
||||||
# CONFIG_BINMAN_FDT is not set
|
# CONFIG_BINMAN_FDT is not set
|
||||||
|
@ -89,6 +89,7 @@ CONFIG_DM_RTC=y
|
|||||||
CONFIG_RTC_STM32=y
|
CONFIG_RTC_STM32=y
|
||||||
CONFIG_SERIAL_RX_BUFFER=y
|
CONFIG_SERIAL_RX_BUFFER=y
|
||||||
CONFIG_SYSRESET_SYSCON=y
|
CONFIG_SYSRESET_SYSCON=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_STM32MP=y
|
CONFIG_WDT_STM32MP=y
|
||||||
# CONFIG_BINMAN_FDT is not set
|
# CONFIG_BINMAN_FDT is not set
|
||||||
|
@ -89,6 +89,7 @@ CONFIG_DM_RTC=y
|
|||||||
CONFIG_RTC_STM32=y
|
CONFIG_RTC_STM32=y
|
||||||
CONFIG_SERIAL_RX_BUFFER=y
|
CONFIG_SERIAL_RX_BUFFER=y
|
||||||
CONFIG_SYSRESET_SYSCON=y
|
CONFIG_SYSRESET_SYSCON=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_STM32MP=y
|
CONFIG_WDT_STM32MP=y
|
||||||
# CONFIG_BINMAN_FDT is not set
|
# CONFIG_BINMAN_FDT is not set
|
||||||
|
@ -191,6 +191,7 @@ CONFIG_SPLASH_SCREEN_ALIGN=y
|
|||||||
CONFIG_BMP_16BPP=y
|
CONFIG_BMP_16BPP=y
|
||||||
CONFIG_BMP_24BPP=y
|
CONFIG_BMP_24BPP=y
|
||||||
CONFIG_BMP_32BPP=y
|
CONFIG_BMP_32BPP=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_STM32MP=y
|
CONFIG_WDT_STM32MP=y
|
||||||
# CONFIG_BINMAN_FDT is not set
|
# CONFIG_BINMAN_FDT is not set
|
||||||
|
@ -76,3 +76,4 @@ CONFIG_PREBOOT="run dh_preboot"
|
|||||||
CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
|
CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
|
||||||
CONFIG_TARGET_DH_STM32MP1_PDK2=y
|
CONFIG_TARGET_DH_STM32MP1_PDK2=y
|
||||||
CONFIG_USE_SERVERIP=y
|
CONFIG_USE_SERVERIP=y
|
||||||
|
CONFIG_WATCHDOG_AUTOSTART=y
|
||||||
|
@ -15,6 +15,7 @@ config WATCHDOG_AUTOSTART
|
|||||||
bool "Automatically start watchdog timer"
|
bool "Automatically start watchdog timer"
|
||||||
depends on WDT
|
depends on WDT
|
||||||
default n if ARCH_SUNXI
|
default n if ARCH_SUNXI
|
||||||
|
default n if ARCH_STM32MP
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Automatically start watchdog timer and start servicing it during
|
Automatically start watchdog timer and start servicing it during
|
||||||
|
@ -46,6 +46,8 @@ static int smcwd_call(struct udevice *dev, enum smcwd_call call,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if (res->a0 == PSCI_RET_INVALID_PARAMS)
|
if (res->a0 == PSCI_RET_INVALID_PARAMS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (res->a0 == PSCI_RET_DISABLED)
|
||||||
|
return -ENODATA;
|
||||||
if (res->a0 != PSCI_RET_SUCCESS)
|
if (res->a0 != PSCI_RET_SUCCESS)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@ -99,6 +101,21 @@ static int smcwd_probe(struct udevice *dev)
|
|||||||
priv->min_timeout = res.a1;
|
priv->min_timeout = res.a1;
|
||||||
priv->max_timeout = res.a2;
|
priv->max_timeout = res.a2;
|
||||||
|
|
||||||
|
/* If already started, then force u-boot to use it */
|
||||||
|
err = smcwd_call(dev, SMCWD_GET_TIMELEFT, 0, NULL);
|
||||||
|
switch (err) {
|
||||||
|
case 0:
|
||||||
|
dev_dbg(dev, "Already started\n");
|
||||||
|
wdt_set_force_autostart(dev);
|
||||||
|
break;
|
||||||
|
case -ENODATA:
|
||||||
|
dev_dbg(dev, "Not already started\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Optional SMCWD_GET_TIMELEFT not implemented */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +21,13 @@
|
|||||||
#define IWDG_PR 0x04 /* Prescaler Register */
|
#define IWDG_PR 0x04 /* Prescaler Register */
|
||||||
#define IWDG_RLR 0x08 /* ReLoad Register */
|
#define IWDG_RLR 0x08 /* ReLoad Register */
|
||||||
#define IWDG_SR 0x0C /* Status Register */
|
#define IWDG_SR 0x0C /* Status Register */
|
||||||
|
#define IWDG_VERR 0x3F4 /* Version Register */
|
||||||
|
|
||||||
/* IWDG_KR register bit mask */
|
/* IWDG_KR register bit mask */
|
||||||
#define KR_KEY_RELOAD 0xAAAA /* Reload counter enable */
|
#define KR_KEY_RELOAD 0xAAAA /* Reload counter enable */
|
||||||
#define KR_KEY_ENABLE 0xCCCC /* Peripheral enable */
|
#define KR_KEY_ENABLE 0xCCCC /* Peripheral enable */
|
||||||
#define KR_KEY_EWA 0x5555 /* Write access enable */
|
#define KR_KEY_EWA 0x5555 /* Write access enable */
|
||||||
|
#define KR_KEY_DWA 0x0000 /* Write access disable*/
|
||||||
|
|
||||||
/* IWDG_PR register bit values */
|
/* IWDG_PR register bit values */
|
||||||
#define PR_256 0x06 /* Prescaler set to 256 */
|
#define PR_256 0x06 /* Prescaler set to 256 */
|
||||||
@ -36,10 +38,17 @@
|
|||||||
/* IWDG_SR register bit values */
|
/* IWDG_SR register bit values */
|
||||||
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
|
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
|
||||||
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
|
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
|
||||||
|
#define SR_ONF BIT(8) /* Watchdog enable status bit */
|
||||||
|
|
||||||
|
/* IWDG Compatibility */
|
||||||
|
#define ONF_MIN_VER 0x31
|
||||||
|
|
||||||
|
#define TIMEOUT_US 10000
|
||||||
|
|
||||||
struct stm32mp_wdt_priv {
|
struct stm32mp_wdt_priv {
|
||||||
fdt_addr_t base; /* registers addr in physical memory */
|
fdt_addr_t base; /* registers addr in physical memory */
|
||||||
unsigned long wdt_clk_rate; /* Watchdog dedicated clock rate */
|
unsigned long wdt_clk_rate; /* Watchdog dedicated clock rate */
|
||||||
|
unsigned int hw_version; /* Peripheral version */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stm32mp_wdt_reset(struct udevice *dev)
|
static int stm32mp_wdt_reset(struct udevice *dev)
|
||||||
@ -90,6 +99,7 @@ static int stm32mp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
|||||||
static int stm32mp_wdt_probe(struct udevice *dev)
|
static int stm32mp_wdt_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
|
struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
|
||||||
|
u32 rlr, sr;
|
||||||
struct clk clk;
|
struct clk clk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -115,6 +125,29 @@ static int stm32mp_wdt_probe(struct udevice *dev)
|
|||||||
|
|
||||||
priv->wdt_clk_rate = clk_get_rate(&clk);
|
priv->wdt_clk_rate = clk_get_rate(&clk);
|
||||||
|
|
||||||
|
priv->hw_version = readl(priv->base + IWDG_VERR);
|
||||||
|
|
||||||
|
if (priv->hw_version >= ONF_MIN_VER) {
|
||||||
|
if (readl(priv->base + IWDG_SR) & SR_ONF)
|
||||||
|
wdt_set_force_autostart(dev);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Workaround for old versions without IWDG_SR_ONF bit:
|
||||||
|
* - write in IWDG_RLR_OFFSET
|
||||||
|
* - wait for sync
|
||||||
|
* - if sync succeeds, then iwdg is running
|
||||||
|
*/
|
||||||
|
writel(KR_KEY_EWA, priv->base + IWDG_KR);
|
||||||
|
rlr = readl(priv->base + IWDG_RLR);
|
||||||
|
writel(rlr, priv->base + IWDG_RLR);
|
||||||
|
ret = readl_poll_timeout(priv->base + IWDG_SR, sr, sr & SR_RVU,
|
||||||
|
TIMEOUT_US);
|
||||||
|
if (!ret)
|
||||||
|
wdt_set_force_autostart(dev);
|
||||||
|
|
||||||
|
writel(KR_KEY_DWA, priv->base + IWDG_KR);
|
||||||
|
}
|
||||||
|
|
||||||
dev_dbg(dev, "IWDG init done\n");
|
dev_dbg(dev, "IWDG init done\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -46,6 +46,15 @@ struct wdt_priv {
|
|||||||
struct cyclic_info cyclic;
|
struct cyclic_info cyclic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int wdt_set_force_autostart(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct wdt_priv *priv = dev_get_uclass_priv(dev);
|
||||||
|
|
||||||
|
priv->autostart = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void wdt_cyclic(struct cyclic_info *c)
|
static void wdt_cyclic(struct cyclic_info *c)
|
||||||
{
|
{
|
||||||
struct wdt_priv *priv = container_of(c, struct wdt_priv, cyclic);
|
struct wdt_priv *priv = container_of(c, struct wdt_priv, cyclic);
|
||||||
|
@ -18,6 +18,15 @@ struct udevice;
|
|||||||
* which typically include placing the system in a safe, known state.
|
* which typically include placing the system in a safe, known state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force watchdog start during init. Called by driver's probe when the watchdog
|
||||||
|
* is detected as already started.
|
||||||
|
*
|
||||||
|
* @dev: WDT Device
|
||||||
|
* @return: 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int wdt_set_force_autostart(struct udevice *dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the timer
|
* Start the timer
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user