uboot/drivers/watchdog/bcm6345_wdt.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
   3 *
   4 * Derived from linux/drivers/watchdog/bcm63xx_wdt.c:
   5 *      Copyright (C) 2007 Miguel Gaio <miguel.gaio@efixo.com>
   6 *      Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
   7 *
   8 * SPDX-License-Identifier: GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <dm.h>
  13#include <wdt.h>
  14#include <asm/io.h>
  15
  16/* WDT Value register */
  17#define WDT_VAL_REG             0x0
  18#define WDT_VAL_MIN             0x00000002
  19#define WDT_VAL_MAX             0xfffffffe
  20
  21/* WDT Control register */
  22#define WDT_CTL_REG             0x4
  23#define WDT_CTL_START1_MASK     0x0000ff00
  24#define WDT_CTL_START2_MASK     0x000000ff
  25#define WDT_CTL_STOP1_MASK      0x0000ee00
  26#define WDT_CTL_STOP2_MASK      0x000000ee
  27
  28struct bcm6345_wdt_priv {
  29        void __iomem *regs;
  30};
  31
  32static int bcm6345_wdt_reset(struct udevice *dev)
  33{
  34        struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
  35
  36        writel_be(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG);
  37        writel_be(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG);
  38
  39        return 0;
  40}
  41
  42static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
  43{
  44        struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
  45
  46        if (timeout < WDT_VAL_MIN) {
  47                debug("watchdog won't fire with less than 2 ticks\n");
  48                timeout = WDT_VAL_MIN;
  49        } else if (timeout > WDT_VAL_MAX) {
  50                debug("maximum watchdog timeout exceeded\n");
  51                timeout = WDT_VAL_MAX;
  52        }
  53
  54        writel_be(timeout, priv->regs + WDT_VAL_REG);
  55
  56        return bcm6345_wdt_reset(dev);
  57}
  58
  59static int bcm6345_wdt_expire_now(struct udevice *dev, ulong flags)
  60{
  61        return bcm6345_wdt_start(dev, WDT_VAL_MIN, flags);
  62}
  63
  64static int bcm6345_wdt_stop(struct udevice *dev)
  65{
  66        struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
  67
  68        writel_be(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG);
  69        writel_be(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG);
  70
  71        return 0;
  72}
  73
  74static const struct wdt_ops bcm6345_wdt_ops = {
  75        .expire_now = bcm6345_wdt_expire_now,
  76        .reset = bcm6345_wdt_reset,
  77        .start = bcm6345_wdt_start,
  78        .stop = bcm6345_wdt_stop,
  79};
  80
  81static const struct udevice_id bcm6345_wdt_ids[] = {
  82        { .compatible = "brcm,bcm6345-wdt" },
  83        { /* sentinel */ }
  84};
  85
  86static int bcm6345_wdt_probe(struct udevice *dev)
  87{
  88        struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
  89        fdt_addr_t addr;
  90        fdt_size_t size;
  91
  92        addr = devfdt_get_addr_size_index(dev, 0, &size);
  93        if (addr == FDT_ADDR_T_NONE)
  94                return -EINVAL;
  95
  96        priv->regs = ioremap(addr, size);
  97
  98        bcm6345_wdt_stop(dev);
  99
 100        return 0;
 101}
 102
 103U_BOOT_DRIVER(wdt_bcm6345) = {
 104        .name = "wdt_bcm6345",
 105        .id = UCLASS_WDT,
 106        .of_match = bcm6345_wdt_ids,
 107        .ops = &bcm6345_wdt_ops,
 108        .priv_auto_alloc_size = sizeof(struct bcm6345_wdt_priv),
 109        .probe = bcm6345_wdt_probe,
 110};
 111