watchdog: imx: Add DM support

Add DM and DT probing support to iMX watchdog driver. This should
allow boards to move over to this driver, enable SYSRESET_WATCHDOG
to handle cpu_reset() if required.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Peng Fan <Peng.Fan@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Tested-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
Marek Vasut 2019-06-09 03:46:22 +02:00 committed by Stefano Babic
parent 6874cb7220
commit 4b969deac0
2 changed files with 105 additions and 18 deletions

View File

@ -28,7 +28,7 @@ config BCM2835_WDT
config IMX_WATCHDOG config IMX_WATCHDOG
bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP" bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
select HW_WATCHDOG select HW_WATCHDOG if !WDT
help help
Select this to enable the IMX and LSCH2 of Layerscape watchdog Select this to enable the IMX and LSCH2 of Layerscape watchdog
driver. driver.

View File

@ -5,7 +5,9 @@
*/ */
#include <common.h> #include <common.h>
#include <dm.h>
#include <asm/io.h> #include <asm/io.h>
#include <wdt.h>
#include <watchdog.h> #include <watchdog.h>
#include <asm/arch/imx-regs.h> #include <asm/arch/imx-regs.h>
#ifdef CONFIG_FSL_LSCH2 #ifdef CONFIG_FSL_LSCH2
@ -13,20 +15,40 @@
#endif #endif
#include <fsl_wdog.h> #include <fsl_wdog.h>
#ifdef CONFIG_IMX_WATCHDOG static void imx_watchdog_expire_now(struct watchdog_regs *wdog)
void hw_watchdog_reset(void) {
clrsetbits_le16(&wdog->wcr, WCR_WT_MSK, WCR_WDE);
writew(0x5555, &wdog->wsr);
writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */
while (1) {
/*
* spin for .5 seconds before reset
*/
}
}
#if !defined(CONFIG_IMX_WATCHDOG) || \
(defined(CONFIG_IMX_WATCHDOG) && !CONFIG_IS_ENABLED(WDT))
void __attribute__((weak)) reset_cpu(ulong addr)
{ {
#ifndef CONFIG_WATCHDOG_RESET_DISABLE
struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
imx_watchdog_expire_now(wdog);
}
#endif
#if defined(CONFIG_IMX_WATCHDOG)
static void imx_watchdog_reset(struct watchdog_regs *wdog)
{
#ifndef CONFIG_WATCHDOG_RESET_DISABLE
writew(0x5555, &wdog->wsr); writew(0x5555, &wdog->wsr);
writew(0xaaaa, &wdog->wsr); writew(0xaaaa, &wdog->wsr);
#endif /* CONFIG_WATCHDOG_RESET_DISABLE*/ #endif /* CONFIG_WATCHDOG_RESET_DISABLE*/
} }
void hw_watchdog_init(void) static void imx_watchdog_init(struct watchdog_regs *wdog)
{ {
struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
u16 timeout; u16 timeout;
/* /*
@ -44,21 +66,86 @@ void hw_watchdog_init(void)
writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS | writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS |
WCR_WDA | SET_WCR_WT(timeout), &wdog->wcr); WCR_WDA | SET_WCR_WT(timeout), &wdog->wcr);
#endif /* CONFIG_FSL_LSCH2*/ #endif /* CONFIG_FSL_LSCH2*/
hw_watchdog_reset(); imx_watchdog_reset(wdog);
} }
#endif
void __attribute__((weak)) reset_cpu(ulong addr) #if !CONFIG_IS_ENABLED(WDT)
void hw_watchdog_reset(void)
{ {
struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
clrsetbits_le16(&wdog->wcr, WCR_WT_MSK, WCR_WDE); imx_watchdog_reset(wdog);
}
writew(0x5555, &wdog->wsr); void hw_watchdog_init(void)
writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */ {
while (1) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
/*
* spin for .5 seconds before reset imx_watchdog_init(wdog);
*/
} }
#else
struct imx_wdt_priv {
void __iomem *base;
};
static int imx_wdt_reset(struct udevice *dev)
{
struct imx_wdt_priv *priv = dev_get_priv(dev);
imx_watchdog_reset(priv->base);
return 0;
} }
static int imx_wdt_expire_now(struct udevice *dev, ulong flags)
{
struct imx_wdt_priv *priv = dev_get_priv(dev);
imx_watchdog_expire_now(priv->base);
hang();
return 0;
}
static int imx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
{
struct imx_wdt_priv *priv = dev_get_priv(dev);
imx_watchdog_init(priv->base);
return 0;
}
static int imx_wdt_probe(struct udevice *dev)
{
struct imx_wdt_priv *priv = dev_get_priv(dev);
priv->base = dev_read_addr_ptr(dev);
if (!priv->base)
return -ENOENT;
return 0;
}
static const struct wdt_ops imx_wdt_ops = {
.start = imx_wdt_start,
.reset = imx_wdt_reset,
.expire_now = imx_wdt_expire_now,
};
static const struct udevice_id imx_wdt_ids[] = {
{ .compatible = "fsl,imx21-wdt" },
{}
};
U_BOOT_DRIVER(imx_wdt) = {
.name = "imx_wdt",
.id = UCLASS_WDT,
.of_match = imx_wdt_ids,
.probe = imx_wdt_probe,
.ops = &imx_wdt_ops,
.priv_auto_alloc_size = sizeof(struct imx_wdt_priv),
.flags = DM_FLAG_PRE_RELOC,
};
#endif
#endif