watchdog: Add MAX6370 watchdog timer driver

MAX6370 watchdog is available e.g. on Freescale P1/P2 RDB-PC boards.

Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
This commit is contained in:
Pali Rohár 2022-05-02 18:41:07 +02:00 committed by Stefan Roese
parent 03b873b4f4
commit 0a095fc53b
3 changed files with 126 additions and 0 deletions

View File

@ -168,6 +168,13 @@ config WDT_GPIO
doc/device-tree-bindings/watchdog/gpio-wdt.txt for
information on how to describe the watchdog in device tree.
config WDT_MAX6370
bool "MAX6370 watchdog timer support"
depends on WDT
select DM_GPIO
help
Select this to enable max6370 watchdog timer.
config WDT_MPC8xx
bool "MPC8xx watchdog timer support"
depends on WDT && MPC8xx

View File

@ -26,6 +26,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o

View File

@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0+
// (C) 2022 Pali Rohár <pali@kernel.org>
#include <asm/io.h>
#include <asm-generic/gpio.h>
#include <dm.h>
#include <linux/delay.h>
#include <wdt.h>
#define MAX6370_SET_MASK 0x7
#define MAX6370_SET_1MS 0x0
#define MAX6370_SET_10MS 0x1
#define MAX6370_SET_30MS 0x2
#define MAX6370_SET_DISABLE 0x3
#define MAX6370_SET_100MS 0x4
#define MAX6370_SET_1S 0x5
#define MAX6370_SET_10S 0x6
#define MAX6370_SET_60S 0x7
#define MAX6370_WDI 0x8
struct max6370_wdt {
void __iomem *reg;
struct gpio_desc gpio_wdi;
};
static int max6370_wdt_start(struct udevice *dev, u64 ms, ulong flags)
{
struct max6370_wdt *wdt = dev_get_priv(dev);
u8 val;
val = readb(wdt->reg);
val &= ~MAX6370_SET_MASK;
if (ms <= 1)
val |= MAX6370_SET_1MS;
else if (ms <= 10)
val |= MAX6370_SET_10MS;
else if (ms <= 30)
val |= MAX6370_SET_30MS;
else if (ms <= 100)
val |= MAX6370_SET_100MS;
else if (ms <= 1000)
val |= MAX6370_SET_1S;
else if (ms <= 10000)
val |= MAX6370_SET_10S;
else
val |= MAX6370_SET_60S;
writeb(val, wdt->reg);
return 0;
}
static int max6370_wdt_stop(struct udevice *dev)
{
struct max6370_wdt *wdt = dev_get_priv(dev);
u8 val;
val = readb(wdt->reg);
val &= ~MAX6370_SET_MASK;
val |= MAX6370_SET_DISABLE;
writeb(val, wdt->reg);
return 0;
}
static int max6370_wdt_reset(struct udevice *dev)
{
struct max6370_wdt *wdt = dev_get_priv(dev);
u8 val;
if (dm_gpio_is_valid(&wdt->gpio_wdi)) {
dm_gpio_set_value(&wdt->gpio_wdi, 1);
udelay(1);
dm_gpio_set_value(&wdt->gpio_wdi, 0);
} else {
val = readb(wdt->reg);
writeb(val | MAX6370_WDI, wdt->reg);
writeb(val & ~MAX6370_WDI, wdt->reg);
}
return 0;
}
static int max6370_wdt_probe(struct udevice *dev)
{
struct max6370_wdt *wdt = dev_get_priv(dev);
wdt->reg = dev_read_addr_ptr(dev);
if (!wdt->reg)
return -EINVAL;
/* WDI gpio is optional */
gpio_request_by_name(dev, "gpios", 0, &wdt->gpio_wdi, GPIOD_IS_OUT);
return 0;
}
static const struct wdt_ops max6370_wdt_ops = {
.start = max6370_wdt_start,
.stop = max6370_wdt_stop,
.reset = max6370_wdt_reset,
};
static const struct udevice_id max6370_wdt_ids[] = {
{ .compatible = "maxim,max6370" },
{}
};
U_BOOT_DRIVER(max6370_wdt) = {
.name = "max6370_wdt",
.id = UCLASS_WDT,
.of_match = max6370_wdt_ids,
.probe = max6370_wdt_probe,
.priv_auto = sizeof(struct max6370_wdt),
.ops = &max6370_wdt_ops,
};