linux/drivers/watchdog/sbsa_gwdt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * SBSA(Server Base System Architecture) Generic Watchdog driver
   4 *
   5 * Copyright (c) 2015, Linaro Ltd.
   6 * Author: Fu Wei <fu.wei@linaro.org>
   7 *         Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
   8 *         Al Stone <al.stone@linaro.org>
   9 *         Timur Tabi <timur@codeaurora.org>
  10 *
  11 * ARM SBSA Generic Watchdog has two stage timeouts:
  12 * the first signal (WS0) is for alerting the system by interrupt,
  13 * the second one (WS1) is a real hardware reset.
  14 * More details about the hardware specification of this device:
  15 * ARM DEN0029B - Server Base System Architecture (SBSA)
  16 *
  17 * This driver can operate ARM SBSA Generic Watchdog as a single stage watchdog
  18 * or a two stages watchdog, it's set up by the module parameter "action".
  19 * In the single stage mode, when the timeout is reached, your system
  20 * will be reset by WS1. The first signal (WS0) is ignored.
  21 * In the two stages mode, when the timeout is reached, the first signal (WS0)
  22 * will trigger panic. If the system is getting into trouble and cannot be reset
  23 * by panic or restart properly by the kdump kernel(if supported), then the
  24 * second stage (as long as the first stage) will be reached, system will be
  25 * reset by WS1. This function can help administrator to backup the system
  26 * context info by panic console output or kdump.
  27 *
  28 * SBSA GWDT:
  29 * if action is 1 (the two stages mode):
  30 * |--------WOR-------WS0--------WOR-------WS1
  31 * |----timeout-----(panic)----timeout-----reset
  32 *
  33 * if action is 0 (the single stage mode):
  34 * |------WOR-----WS0(ignored)-----WOR------WS1
  35 * |--------------timeout-------------------reset
  36 *
  37 * Note: Since this watchdog timer has two stages, and each stage is determined
  38 * by WOR, in the single stage mode, the timeout is (WOR * 2); in the two
  39 * stages mode, the timeout is WOR. The maximum timeout in the two stages mode
  40 * is half of that in the single stage mode.
  41 */
  42
  43#include <linux/io.h>
  44#include <linux/io-64-nonatomic-lo-hi.h>
  45#include <linux/interrupt.h>
  46#include <linux/module.h>
  47#include <linux/moduleparam.h>
  48#include <linux/of.h>
  49#include <linux/of_device.h>
  50#include <linux/platform_device.h>
  51#include <linux/uaccess.h>
  52#include <linux/watchdog.h>
  53#include <asm/arch_timer.h>
  54
  55#define DRV_NAME                "sbsa-gwdt"
  56#define WATCHDOG_NAME           "SBSA Generic Watchdog"
  57
  58/* SBSA Generic Watchdog register definitions */
  59/* refresh frame */
  60#define SBSA_GWDT_WRR           0x000
  61
  62/* control frame */
  63#define SBSA_GWDT_WCS           0x000
  64#define SBSA_GWDT_WOR           0x008
  65#define SBSA_GWDT_WCV           0x010
  66
  67/* refresh/control frame */
  68#define SBSA_GWDT_W_IIDR        0xfcc
  69#define SBSA_GWDT_IDR           0xfd0
  70
  71/* Watchdog Control and Status Register */
  72#define SBSA_GWDT_WCS_EN        BIT(0)
  73#define SBSA_GWDT_WCS_WS0       BIT(1)
  74#define SBSA_GWDT_WCS_WS1       BIT(2)
  75
  76#define SBSA_GWDT_VERSION_MASK  0xF
  77#define SBSA_GWDT_VERSION_SHIFT 16
  78
  79/**
  80 * struct sbsa_gwdt - Internal representation of the SBSA GWDT
  81 * @wdd:                kernel watchdog_device structure
  82 * @clk:                store the System Counter clock frequency, in Hz.
  83 * @version:            store the architecture version
  84 * @refresh_base:       Virtual address of the watchdog refresh frame
  85 * @control_base:       Virtual address of the watchdog control frame
  86 */
  87struct sbsa_gwdt {
  88        struct watchdog_device  wdd;
  89        u32                     clk;
  90        int                     version;
  91        void __iomem            *refresh_base;
  92        void __iomem            *control_base;
  93};
  94
  95#define DEFAULT_TIMEOUT         10 /* seconds */
  96
  97static unsigned int timeout;
  98module_param(timeout, uint, 0);
  99MODULE_PARM_DESC(timeout,
 100                 "Watchdog timeout in seconds. (>=0, default="
 101                 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
 102
 103/*
 104 * action refers to action taken when watchdog gets WS0
 105 * 0 = skip
 106 * 1 = panic
 107 * defaults to skip (0)
 108 */
 109static int action;
 110module_param(action, int, 0);
 111MODULE_PARM_DESC(action, "after watchdog gets WS0 interrupt, do: "
 112                 "0 = skip(*)  1 = panic");
 113
 114static bool nowayout = WATCHDOG_NOWAYOUT;
 115module_param(nowayout, bool, S_IRUGO);
 116MODULE_PARM_DESC(nowayout,
 117                 "Watchdog cannot be stopped once started (default="
 118                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 119
 120/*
 121 * Arm Base System Architecture 1.0 introduces watchdog v1 which
 122 * increases the length watchdog offset register to 48 bits.
 123 * - For version 0: WOR is 32 bits;
 124 * - For version 1: WOR is 48 bits which comprises the register
 125 * offset 0x8 and 0xC, and the bits [63:48] are reserved which are
 126 * Read-As-Zero and Writes-Ignored.
 127 */
 128static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt)
 129{
 130        if (gwdt->version == 0)
 131                return readl(gwdt->control_base + SBSA_GWDT_WOR);
 132        else
 133                return lo_hi_readq(gwdt->control_base + SBSA_GWDT_WOR);
 134}
 135
 136static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt)
 137{
 138        if (gwdt->version == 0)
 139                writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR);
 140        else
 141                lo_hi_writeq(val, gwdt->control_base + SBSA_GWDT_WOR);
 142}
 143
 144/*
 145 * watchdog operation functions
 146 */
 147static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
 148                                 unsigned int timeout)
 149{
 150        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 151
 152        wdd->timeout = timeout;
 153
 154        if (action)
 155                sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt);
 156        else
 157                /*
 158                 * In the single stage mode, The first signal (WS0) is ignored,
 159                 * the timeout is (WOR * 2), so the WOR should be configured
 160                 * to half value of timeout.
 161                 */
 162                sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt);
 163
 164        return 0;
 165}
 166
 167static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
 168{
 169        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 170        u64 timeleft = 0;
 171
 172        /*
 173         * In the single stage mode, if WS0 is deasserted
 174         * (watchdog is in the first stage),
 175         * timeleft = WOR + (WCV - system counter)
 176         */
 177        if (!action &&
 178            !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0))
 179                timeleft += sbsa_gwdt_reg_read(gwdt);
 180
 181        timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) -
 182                    arch_timer_read_counter();
 183
 184        do_div(timeleft, gwdt->clk);
 185
 186        return timeleft;
 187}
 188
 189static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
 190{
 191        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 192
 193        /*
 194         * Writing WRR for an explicit watchdog refresh.
 195         * You can write anyting (like 0).
 196         */
 197        writel(0, gwdt->refresh_base + SBSA_GWDT_WRR);
 198
 199        return 0;
 200}
 201
 202static void sbsa_gwdt_get_version(struct watchdog_device *wdd)
 203{
 204        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 205        int ver;
 206
 207        ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR);
 208        ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK;
 209
 210        gwdt->version = ver;
 211}
 212
 213static int sbsa_gwdt_start(struct watchdog_device *wdd)
 214{
 215        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 216
 217        /* writing WCS will cause an explicit watchdog refresh */
 218        writel(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
 219
 220        return 0;
 221}
 222
 223static int sbsa_gwdt_stop(struct watchdog_device *wdd)
 224{
 225        struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 226
 227        /* Simply write 0 to WCS to clean WCS_EN bit */
 228        writel(0, gwdt->control_base + SBSA_GWDT_WCS);
 229
 230        return 0;
 231}
 232
 233static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
 234{
 235        panic(WATCHDOG_NAME " timeout");
 236
 237        return IRQ_HANDLED;
 238}
 239
 240static const struct watchdog_info sbsa_gwdt_info = {
 241        .identity       = WATCHDOG_NAME,
 242        .options        = WDIOF_SETTIMEOUT |
 243                          WDIOF_KEEPALIVEPING |
 244                          WDIOF_MAGICCLOSE |
 245                          WDIOF_CARDRESET,
 246};
 247
 248static const struct watchdog_ops sbsa_gwdt_ops = {
 249        .owner          = THIS_MODULE,
 250        .start          = sbsa_gwdt_start,
 251        .stop           = sbsa_gwdt_stop,
 252        .ping           = sbsa_gwdt_keepalive,
 253        .set_timeout    = sbsa_gwdt_set_timeout,
 254        .get_timeleft   = sbsa_gwdt_get_timeleft,
 255};
 256
 257static int sbsa_gwdt_probe(struct platform_device *pdev)
 258{
 259        void __iomem *rf_base, *cf_base;
 260        struct device *dev = &pdev->dev;
 261        struct watchdog_device *wdd;
 262        struct sbsa_gwdt *gwdt;
 263        int ret, irq;
 264        u32 status;
 265
 266        gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL);
 267        if (!gwdt)
 268                return -ENOMEM;
 269        platform_set_drvdata(pdev, gwdt);
 270
 271        cf_base = devm_platform_ioremap_resource(pdev, 0);
 272        if (IS_ERR(cf_base))
 273                return PTR_ERR(cf_base);
 274
 275        rf_base = devm_platform_ioremap_resource(pdev, 1);
 276        if (IS_ERR(rf_base))
 277                return PTR_ERR(rf_base);
 278
 279        /*
 280         * Get the frequency of system counter from the cp15 interface of ARM
 281         * Generic timer. We don't need to check it, because if it returns "0",
 282         * system would panic in very early stage.
 283         */
 284        gwdt->clk = arch_timer_get_cntfrq();
 285        gwdt->refresh_base = rf_base;
 286        gwdt->control_base = cf_base;
 287
 288        wdd = &gwdt->wdd;
 289        wdd->parent = dev;
 290        wdd->info = &sbsa_gwdt_info;
 291        wdd->ops = &sbsa_gwdt_ops;
 292        wdd->min_timeout = 1;
 293        wdd->timeout = DEFAULT_TIMEOUT;
 294        watchdog_set_drvdata(wdd, gwdt);
 295        watchdog_set_nowayout(wdd, nowayout);
 296        sbsa_gwdt_get_version(wdd);
 297        if (gwdt->version == 0)
 298                wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000;
 299        else
 300                wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000;
 301
 302        status = readl(cf_base + SBSA_GWDT_WCS);
 303        if (status & SBSA_GWDT_WCS_WS1) {
 304                dev_warn(dev, "System reset by WDT.\n");
 305                wdd->bootstatus |= WDIOF_CARDRESET;
 306        }
 307        if (status & SBSA_GWDT_WCS_EN)
 308                set_bit(WDOG_HW_RUNNING, &wdd->status);
 309
 310        if (action) {
 311                irq = platform_get_irq(pdev, 0);
 312                if (irq < 0) {
 313                        action = 0;
 314                        dev_warn(dev, "unable to get ws0 interrupt.\n");
 315                } else {
 316                        /*
 317                         * In case there is a pending ws0 interrupt, just ping
 318                         * the watchdog before registering the interrupt routine
 319                         */
 320                        writel(0, rf_base + SBSA_GWDT_WRR);
 321                        if (devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0,
 322                                             pdev->name, gwdt)) {
 323                                action = 0;
 324                                dev_warn(dev, "unable to request IRQ %d.\n",
 325                                         irq);
 326                        }
 327                }
 328                if (!action)
 329                        dev_warn(dev, "falling back to single stage mode.\n");
 330        }
 331        /*
 332         * In the single stage mode, The first signal (WS0) is ignored,
 333         * the timeout is (WOR * 2), so the maximum timeout should be doubled.
 334         */
 335        if (!action)
 336                wdd->max_hw_heartbeat_ms *= 2;
 337
 338        watchdog_init_timeout(wdd, timeout, dev);
 339        /*
 340         * Update timeout to WOR.
 341         * Because of the explicit watchdog refresh mechanism,
 342         * it's also a ping, if watchdog is enabled.
 343         */
 344        sbsa_gwdt_set_timeout(wdd, wdd->timeout);
 345
 346        watchdog_stop_on_reboot(wdd);
 347        ret = devm_watchdog_register_device(dev, wdd);
 348        if (ret)
 349                return ret;
 350
 351        dev_info(dev, "Initialized with %ds timeout @ %u Hz, action=%d.%s\n",
 352                 wdd->timeout, gwdt->clk, action,
 353                 status & SBSA_GWDT_WCS_EN ? " [enabled]" : "");
 354
 355        return 0;
 356}
 357
 358/* Disable watchdog if it is active during suspend */
 359static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
 360{
 361        struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
 362
 363        if (watchdog_active(&gwdt->wdd))
 364                sbsa_gwdt_stop(&gwdt->wdd);
 365
 366        return 0;
 367}
 368
 369/* Enable watchdog if necessary */
 370static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
 371{
 372        struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
 373
 374        if (watchdog_active(&gwdt->wdd))
 375                sbsa_gwdt_start(&gwdt->wdd);
 376
 377        return 0;
 378}
 379
 380static const struct dev_pm_ops sbsa_gwdt_pm_ops = {
 381        SET_SYSTEM_SLEEP_PM_OPS(sbsa_gwdt_suspend, sbsa_gwdt_resume)
 382};
 383
 384static const struct of_device_id sbsa_gwdt_of_match[] = {
 385        { .compatible = "arm,sbsa-gwdt", },
 386        {},
 387};
 388MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);
 389
 390static const struct platform_device_id sbsa_gwdt_pdev_match[] = {
 391        { .name = DRV_NAME, },
 392        {},
 393};
 394MODULE_DEVICE_TABLE(platform, sbsa_gwdt_pdev_match);
 395
 396static struct platform_driver sbsa_gwdt_driver = {
 397        .driver = {
 398                .name = DRV_NAME,
 399                .pm = &sbsa_gwdt_pm_ops,
 400                .of_match_table = sbsa_gwdt_of_match,
 401        },
 402        .probe = sbsa_gwdt_probe,
 403        .id_table = sbsa_gwdt_pdev_match,
 404};
 405
 406module_platform_driver(sbsa_gwdt_driver);
 407
 408MODULE_DESCRIPTION("SBSA Generic Watchdog Driver");
 409MODULE_AUTHOR("Fu Wei <fu.wei@linaro.org>");
 410MODULE_AUTHOR("Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>");
 411MODULE_AUTHOR("Al Stone <al.stone@linaro.org>");
 412MODULE_AUTHOR("Timur Tabi <timur@codeaurora.org>");
 413MODULE_LICENSE("GPL v2");
 414