uboot/drivers/watchdog/max6370_wdt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2// (C) 2022 Pali Rohár <pali@kernel.org>
   3
   4#include <asm/io.h>
   5#include <asm-generic/gpio.h>
   6#include <dm.h>
   7#include <linux/delay.h>
   8#include <wdt.h>
   9
  10#define MAX6370_SET_MASK        0x7
  11#define MAX6370_SET_1MS         0x0
  12#define MAX6370_SET_10MS        0x1
  13#define MAX6370_SET_30MS        0x2
  14#define MAX6370_SET_DISABLE     0x3
  15#define MAX6370_SET_100MS       0x4
  16#define MAX6370_SET_1S          0x5
  17#define MAX6370_SET_10S         0x6
  18#define MAX6370_SET_60S         0x7
  19
  20#define MAX6370_WDI             0x8
  21
  22struct max6370_wdt {
  23        void __iomem *reg;
  24        struct gpio_desc gpio_wdi;
  25};
  26
  27static int max6370_wdt_start(struct udevice *dev, u64 ms, ulong flags)
  28{
  29        struct max6370_wdt *wdt = dev_get_priv(dev);
  30        u8 val;
  31
  32        val = readb(wdt->reg);
  33        val &= ~MAX6370_SET_MASK;
  34
  35        if (ms <= 1)
  36                val |= MAX6370_SET_1MS;
  37        else if (ms <= 10)
  38                val |= MAX6370_SET_10MS;
  39        else if (ms <= 30)
  40                val |= MAX6370_SET_30MS;
  41        else if (ms <= 100)
  42                val |= MAX6370_SET_100MS;
  43        else if (ms <= 1000)
  44                val |= MAX6370_SET_1S;
  45        else if (ms <= 10000)
  46                val |= MAX6370_SET_10S;
  47        else
  48                val |= MAX6370_SET_60S;
  49
  50        writeb(val, wdt->reg);
  51
  52        return 0;
  53}
  54
  55static int max6370_wdt_stop(struct udevice *dev)
  56{
  57        struct max6370_wdt *wdt = dev_get_priv(dev);
  58        u8 val;
  59
  60        val = readb(wdt->reg);
  61        val &= ~MAX6370_SET_MASK;
  62        val |= MAX6370_SET_DISABLE;
  63        writeb(val, wdt->reg);
  64
  65        return 0;
  66}
  67
  68static int max6370_wdt_reset(struct udevice *dev)
  69{
  70        struct max6370_wdt *wdt = dev_get_priv(dev);
  71        u8 val;
  72
  73        if (dm_gpio_is_valid(&wdt->gpio_wdi)) {
  74                dm_gpio_set_value(&wdt->gpio_wdi, 1);
  75                __udelay(1);
  76                dm_gpio_set_value(&wdt->gpio_wdi, 0);
  77        } else {
  78                val = readb(wdt->reg);
  79                writeb(val | MAX6370_WDI, wdt->reg);
  80                writeb(val & ~MAX6370_WDI, wdt->reg);
  81        }
  82
  83        return 0;
  84}
  85
  86static int max6370_wdt_probe(struct udevice *dev)
  87{
  88        struct max6370_wdt *wdt = dev_get_priv(dev);
  89
  90        wdt->reg = dev_read_addr_ptr(dev);
  91        if (!wdt->reg)
  92                return -EINVAL;
  93
  94        /* WDI gpio is optional */
  95        gpio_request_by_name(dev, "gpios", 0, &wdt->gpio_wdi, GPIOD_IS_OUT);
  96
  97        return 0;
  98}
  99
 100static const struct wdt_ops max6370_wdt_ops = {
 101        .start = max6370_wdt_start,
 102        .stop = max6370_wdt_stop,
 103        .reset = max6370_wdt_reset,
 104};
 105
 106static const struct udevice_id max6370_wdt_ids[] = {
 107        { .compatible = "maxim,max6370" },
 108        {}
 109};
 110
 111U_BOOT_DRIVER(max6370_wdt) = {
 112        .name = "max6370_wdt",
 113        .id = UCLASS_WDT,
 114        .of_match = max6370_wdt_ids,
 115        .probe = max6370_wdt_probe,
 116        .priv_auto = sizeof(struct max6370_wdt),
 117        .ops = &max6370_wdt_ops,
 118};
 119