linux/drivers/watchdog/i6300esb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      i6300esb:       Watchdog timer driver for Intel 6300ESB chipset
   4 *
   5 *      (c) Copyright 2004 Google Inc.
   6 *      (c) Copyright 2005 David Härdeman <david@2gen.com>
   7 *
   8 *      based on i810-tco.c which is in turn based on softdog.c
   9 *
  10 *      The timer is implemented in the following I/O controller hubs:
  11 *      (See the intel documentation on http://developer.intel.com.)
  12 *      6300ESB chip : document number 300641-004
  13 *
  14 *  2004YYZZ Ross Biro
  15 *      Initial version 0.01
  16 *  2004YYZZ Ross Biro
  17 *      Version 0.02
  18 *  20050210 David Härdeman <david@2gen.com>
  19 *      Ported driver to kernel 2.6
  20 *  20171016 Radu Rendec <rrendec@arista.com>
  21 *      Change driver to use the watchdog subsystem
  22 *      Add support for multiple 6300ESB devices
  23 */
  24
  25/*
  26 *      Includes, defines, variables, module parameters, ...
  27 */
  28
  29#include <linux/module.h>
  30#include <linux/types.h>
  31#include <linux/kernel.h>
  32#include <linux/fs.h>
  33#include <linux/mm.h>
  34#include <linux/miscdevice.h>
  35#include <linux/watchdog.h>
  36#include <linux/pci.h>
  37#include <linux/ioport.h>
  38#include <linux/uaccess.h>
  39#include <linux/io.h>
  40
  41/* Module and version information */
  42#define ESB_MODULE_NAME "i6300ESB timer"
  43
  44/* PCI configuration registers */
  45#define ESB_CONFIG_REG  0x60            /* Config register                   */
  46#define ESB_LOCK_REG    0x68            /* WDT lock register                 */
  47
  48/* Memory mapped registers */
  49#define ESB_TIMER1_REG(w) ((w)->base + 0x00)/* Timer1 value after each reset */
  50#define ESB_TIMER2_REG(w) ((w)->base + 0x04)/* Timer2 value after each reset */
  51#define ESB_GINTSR_REG(w) ((w)->base + 0x08)/* General Interrupt Status Reg  */
  52#define ESB_RELOAD_REG(w) ((w)->base + 0x0c)/* Reload register               */
  53
  54/* Lock register bits */
  55#define ESB_WDT_FUNC    (0x01 << 2)   /* Watchdog functionality            */
  56#define ESB_WDT_ENABLE  (0x01 << 1)   /* Enable WDT                        */
  57#define ESB_WDT_LOCK    (0x01 << 0)   /* Lock (nowayout)                   */
  58
  59/* Config register bits */
  60#define ESB_WDT_REBOOT  (0x01 << 5)   /* Enable reboot on timeout          */
  61#define ESB_WDT_FREQ    (0x01 << 2)   /* Decrement frequency               */
  62#define ESB_WDT_INTTYPE (0x03 << 0)   /* Interrupt type on timer1 timeout  */
  63
  64/* Reload register bits */
  65#define ESB_WDT_TIMEOUT (0x01 << 9)    /* Watchdog timed out                */
  66#define ESB_WDT_RELOAD  (0x01 << 8)    /* prevent timeout                   */
  67
  68/* Magic constants */
  69#define ESB_UNLOCK1     0x80            /* Step 1 to unlock reset registers  */
  70#define ESB_UNLOCK2     0x86            /* Step 2 to unlock reset registers  */
  71
  72/* module parameters */
  73/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
  74#define ESB_HEARTBEAT_MIN       1
  75#define ESB_HEARTBEAT_MAX       2046
  76#define ESB_HEARTBEAT_DEFAULT   30
  77#define ESB_HEARTBEAT_RANGE __MODULE_STRING(ESB_HEARTBEAT_MIN) \
  78        "<heartbeat<" __MODULE_STRING(ESB_HEARTBEAT_MAX)
  79static int heartbeat; /* in seconds */
  80module_param(heartbeat, int, 0);
  81MODULE_PARM_DESC(heartbeat,
  82        "Watchdog heartbeat in seconds. (" ESB_HEARTBEAT_RANGE
  83        ", default=" __MODULE_STRING(ESB_HEARTBEAT_DEFAULT) ")");
  84
  85static bool nowayout = WATCHDOG_NOWAYOUT;
  86module_param(nowayout, bool, 0);
  87MODULE_PARM_DESC(nowayout,
  88                "Watchdog cannot be stopped once started (default="
  89                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  90
  91/* internal variables */
  92struct esb_dev {
  93        struct watchdog_device wdd;
  94        void __iomem *base;
  95        struct pci_dev *pdev;
  96};
  97
  98#define to_esb_dev(wptr) container_of(wptr, struct esb_dev, wdd)
  99
 100/*
 101 * Some i6300ESB specific functions
 102 */
 103
 104/*
 105 * Prepare for reloading the timer by unlocking the proper registers.
 106 * This is performed by first writing 0x80 followed by 0x86 to the
 107 * reload register. After this the appropriate registers can be written
 108 * to once before they need to be unlocked again.
 109 */
 110static inline void esb_unlock_registers(struct esb_dev *edev)
 111{
 112        writew(ESB_UNLOCK1, ESB_RELOAD_REG(edev));
 113        writew(ESB_UNLOCK2, ESB_RELOAD_REG(edev));
 114}
 115
 116static int esb_timer_start(struct watchdog_device *wdd)
 117{
 118        struct esb_dev *edev = to_esb_dev(wdd);
 119        int _wdd_nowayout = test_bit(WDOG_NO_WAY_OUT, &wdd->status);
 120        u8 val;
 121
 122        esb_unlock_registers(edev);
 123        writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
 124        /* Enable or Enable + Lock? */
 125        val = ESB_WDT_ENABLE | (_wdd_nowayout ? ESB_WDT_LOCK : 0x00);
 126        pci_write_config_byte(edev->pdev, ESB_LOCK_REG, val);
 127        return 0;
 128}
 129
 130static int esb_timer_stop(struct watchdog_device *wdd)
 131{
 132        struct esb_dev *edev = to_esb_dev(wdd);
 133        u8 val;
 134
 135        /* First, reset timers as suggested by the docs */
 136        esb_unlock_registers(edev);
 137        writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
 138        /* Then disable the WDT */
 139        pci_write_config_byte(edev->pdev, ESB_LOCK_REG, 0x0);
 140        pci_read_config_byte(edev->pdev, ESB_LOCK_REG, &val);
 141
 142        /* Returns 0 if the timer was disabled, non-zero otherwise */
 143        return val & ESB_WDT_ENABLE;
 144}
 145
 146static int esb_timer_keepalive(struct watchdog_device *wdd)
 147{
 148        struct esb_dev *edev = to_esb_dev(wdd);
 149
 150        esb_unlock_registers(edev);
 151        writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
 152        /* FIXME: Do we need to flush anything here? */
 153        return 0;
 154}
 155
 156static int esb_timer_set_heartbeat(struct watchdog_device *wdd,
 157                unsigned int time)
 158{
 159        struct esb_dev *edev = to_esb_dev(wdd);
 160        u32 val;
 161
 162        /* We shift by 9, so if we are passed a value of 1 sec,
 163         * val will be 1 << 9 = 512, then write that to two
 164         * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
 165         */
 166        val = time << 9;
 167
 168        /* Write timer 1 */
 169        esb_unlock_registers(edev);
 170        writel(val, ESB_TIMER1_REG(edev));
 171
 172        /* Write timer 2 */
 173        esb_unlock_registers(edev);
 174        writel(val, ESB_TIMER2_REG(edev));
 175
 176        /* Reload */
 177        esb_unlock_registers(edev);
 178        writew(ESB_WDT_RELOAD, ESB_RELOAD_REG(edev));
 179
 180        /* FIXME: Do we need to flush everything out? */
 181
 182        /* Done */
 183        wdd->timeout = time;
 184        return 0;
 185}
 186
 187/*
 188 * Watchdog Subsystem Interfaces
 189 */
 190
 191static struct watchdog_info esb_info = {
 192        .identity = ESB_MODULE_NAME,
 193        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 194};
 195
 196static const struct watchdog_ops esb_ops = {
 197        .owner = THIS_MODULE,
 198        .start = esb_timer_start,
 199        .stop = esb_timer_stop,
 200        .set_timeout = esb_timer_set_heartbeat,
 201        .ping = esb_timer_keepalive,
 202};
 203
 204/*
 205 * Data for PCI driver interface
 206 */
 207static const struct pci_device_id esb_pci_tbl[] = {
 208        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
 209        { 0, },                 /* End of list */
 210};
 211MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
 212
 213/*
 214 *      Init & exit routines
 215 */
 216
 217static unsigned char esb_getdevice(struct esb_dev *edev)
 218{
 219        if (pci_enable_device(edev->pdev)) {
 220                dev_err(&edev->pdev->dev, "failed to enable device\n");
 221                goto err_devput;
 222        }
 223
 224        if (pci_request_region(edev->pdev, 0, ESB_MODULE_NAME)) {
 225                dev_err(&edev->pdev->dev, "failed to request region\n");
 226                goto err_disable;
 227        }
 228
 229        edev->base = pci_ioremap_bar(edev->pdev, 0);
 230        if (edev->base == NULL) {
 231                /* Something's wrong here, BASEADDR has to be set */
 232                dev_err(&edev->pdev->dev, "failed to get BASEADDR\n");
 233                goto err_release;
 234        }
 235
 236        /* Done */
 237        dev_set_drvdata(&edev->pdev->dev, edev);
 238        return 1;
 239
 240err_release:
 241        pci_release_region(edev->pdev, 0);
 242err_disable:
 243        pci_disable_device(edev->pdev);
 244err_devput:
 245        return 0;
 246}
 247
 248static void esb_initdevice(struct esb_dev *edev)
 249{
 250        u8 val1;
 251        u16 val2;
 252
 253        /*
 254         * Config register:
 255         * Bit    5 : 0 = Enable WDT_OUTPUT
 256         * Bit    2 : 0 = set the timer frequency to the PCI clock
 257         * divided by 2^15 (approx 1KHz).
 258         * Bits 1:0 : 11 = WDT_INT_TYPE Disabled.
 259         * The watchdog has two timers, it can be setup so that the
 260         * expiry of timer1 results in an interrupt and the expiry of
 261         * timer2 results in a reboot. We set it to not generate
 262         * any interrupts as there is not much we can do with it
 263         * right now.
 264         */
 265        pci_write_config_word(edev->pdev, ESB_CONFIG_REG, 0x0003);
 266
 267        /* Check that the WDT isn't already locked */
 268        pci_read_config_byte(edev->pdev, ESB_LOCK_REG, &val1);
 269        if (val1 & ESB_WDT_LOCK)
 270                dev_warn(&edev->pdev->dev, "nowayout already set\n");
 271
 272        /* Set the timer to watchdog mode and disable it for now */
 273        pci_write_config_byte(edev->pdev, ESB_LOCK_REG, 0x00);
 274
 275        /* Check if the watchdog was previously triggered */
 276        esb_unlock_registers(edev);
 277        val2 = readw(ESB_RELOAD_REG(edev));
 278        if (val2 & ESB_WDT_TIMEOUT)
 279                edev->wdd.bootstatus = WDIOF_CARDRESET;
 280
 281        /* Reset WDT_TIMEOUT flag and timers */
 282        esb_unlock_registers(edev);
 283        writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG(edev));
 284
 285        /* And set the correct timeout value */
 286        esb_timer_set_heartbeat(&edev->wdd, edev->wdd.timeout);
 287}
 288
 289static int esb_probe(struct pci_dev *pdev,
 290                const struct pci_device_id *ent)
 291{
 292        struct esb_dev *edev;
 293        int ret;
 294
 295        edev = devm_kzalloc(&pdev->dev, sizeof(*edev), GFP_KERNEL);
 296        if (!edev)
 297                return -ENOMEM;
 298
 299        /* Check whether or not the hardware watchdog is there */
 300        edev->pdev = pdev;
 301        if (!esb_getdevice(edev))
 302                return -ENODEV;
 303
 304        /* Initialize the watchdog and make sure it does not run */
 305        edev->wdd.info = &esb_info;
 306        edev->wdd.ops = &esb_ops;
 307        edev->wdd.min_timeout = ESB_HEARTBEAT_MIN;
 308        edev->wdd.max_timeout = ESB_HEARTBEAT_MAX;
 309        edev->wdd.timeout = ESB_HEARTBEAT_DEFAULT;
 310        watchdog_init_timeout(&edev->wdd, heartbeat, NULL);
 311        watchdog_set_nowayout(&edev->wdd, nowayout);
 312        watchdog_stop_on_reboot(&edev->wdd);
 313        watchdog_stop_on_unregister(&edev->wdd);
 314        esb_initdevice(edev);
 315
 316        /* Register the watchdog so that userspace has access to it */
 317        ret = watchdog_register_device(&edev->wdd);
 318        if (ret != 0)
 319                goto err_unmap;
 320        dev_info(&pdev->dev,
 321                "initialized. heartbeat=%d sec (nowayout=%d)\n",
 322                edev->wdd.timeout, nowayout);
 323        return 0;
 324
 325err_unmap:
 326        iounmap(edev->base);
 327        pci_release_region(edev->pdev, 0);
 328        pci_disable_device(edev->pdev);
 329        return ret;
 330}
 331
 332static void esb_remove(struct pci_dev *pdev)
 333{
 334        struct esb_dev *edev = dev_get_drvdata(&pdev->dev);
 335
 336        watchdog_unregister_device(&edev->wdd);
 337        iounmap(edev->base);
 338        pci_release_region(edev->pdev, 0);
 339        pci_disable_device(edev->pdev);
 340}
 341
 342static struct pci_driver esb_driver = {
 343        .name           = ESB_MODULE_NAME,
 344        .id_table       = esb_pci_tbl,
 345        .probe          = esb_probe,
 346        .remove         = esb_remove,
 347};
 348
 349module_pci_driver(esb_driver);
 350
 351MODULE_AUTHOR("Ross Biro and David Härdeman");
 352MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
 353MODULE_LICENSE("GPL");
 354