Commit 7733193482f990488d8f5c414f8fd3aa95b50c9f

Authored by Álvaro Fernández Rojas
Committed by Daniel Schwierzeck
1 parent ccbbada0a5

dm: watchdog: add BCM6345 watchdog driver

This driver is a simplified version of linux/drivers/watchdog/bcm63xx_wdt.c

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 119 additions and 0 deletions Side-by-side Diff

drivers/watchdog/Kconfig
... ... @@ -54,5 +54,13 @@
54 54 It currently does not support Boot Flash Addressing Mode Detection or
55 55 Second Boot.
56 56  
  57 +config WDT_BCM6345
  58 + bool "BCM6345 watchdog timer support"
  59 + depends on WDT && ARCH_BMIPS
  60 + help
  61 + Select this to enable watchdog timer for BCM6345 SoCs.
  62 + The watchdog timer is stopped when initialized.
  63 + It performs full SoC reset.
  64 +
57 65 endmenu
drivers/watchdog/Makefile
... ... @@ -18,5 +18,6 @@
18 18 obj-$(CONFIG_WDT) += wdt-uclass.o
19 19 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
20 20 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
  21 +obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
21 22 obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
drivers/watchdog/bcm6345_wdt.c
  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 +
  28 +struct bcm6345_wdt_priv {
  29 + void __iomem *regs;
  30 +};
  31 +
  32 +static 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 +
  42 +static 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 +
  59 +static int bcm6345_wdt_expire_now(struct udevice *dev, ulong flags)
  60 +{
  61 + return bcm6345_wdt_start(dev, WDT_VAL_MIN, flags);
  62 +}
  63 +
  64 +static 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 +
  74 +static 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 +
  81 +static const struct udevice_id bcm6345_wdt_ids[] = {
  82 + { .compatible = "brcm,bcm6345-wdt" },
  83 + { /* sentinel */ }
  84 +};
  85 +
  86 +static 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 = dev_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 +
  103 +U_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 +};