Commit 27acbec3 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:
 "Core:
   - min and max timeout improvements, WDOG_HW_RUNNING improvements,
     status funtionality
   - Add a device managed API for watchdog_register_device()

  New watchdog drivers:
   -  Aspeed SoCs
   -  Maxim PMIC MAX77620
   -  Amlogic Meson GXBB SoC

  Enhancements:
   - support for the r8a7796 watchdog device
   - support for F81866 watchdog device
   - support for 5th variation of Apollo Lake
   - support for MCP78S chipset
   - clean-up of softdog.c watchdog device driver
   - pic32-wdt and pic32-dmt fixes
   - Documentation/watchdog: watchdog-test improvements
   - several other fixes and improvements"

* git://www.linux-watchdog.org/linux-watchdog: (50 commits)
  watchdog: gpio_wdt: Fix missing platform_set_drvdata() in gpio_wdt_probe()
  watchdog: core: Clear WDOG_HW_RUNNING before calling the stop function
  watchdog: core: Fix error handling of watchdog_dev_init()
  watchdog: pic32-wdt: Fix return value check in pic32_wdt_drv_probe()
  watchdog: pic32-dmt: Remove .owner field for driver
  watchdog: pic32-wdt: Remove .owner field for driver
  watchdog: renesas-wdt: Add support for the r8a7796 wdt
  Documentation/watchdog: check return value for magic close
  watchdog: sbsa: Drop status function
  watchdog: Implement status function in watchdog core
  watchdog: tangox: Set max_hw_heartbeat_ms instead of max_timeout
  watchdog: change watchdog_need_worker logic
  watchdog: add support for MCP78S chipset in nv_tco
  watchdog: bcm2835_wdt: remove redundant ->set_timeout callback
  watchdog: bcm2835_wdt: constify _ops and _info structures
  dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
  watchdog: Add Meson GXBB Watchdog Driver
  watchdog: qcom: configure BARK time in addition to BITE time
  watchdog: qcom: add option for standalone watchdog not in timer block
  watchdog: qcom: update device tree bindings
  ...
parents ba929b66 1ac06563
Aspeed Watchdog Timer
Required properties:
- compatible: must be one of:
- "aspeed,ast2400-wdt"
- "aspeed,ast2500-wdt"
- reg: physical base address of the controller and length of memory mapped
region
Example:
wdt1: watchdog@1e785000 {
compatible = "aspeed,ast2400-wdt";
reg = <0x1e785000 0x1c>;
};
Meson GXBB SoCs Watchdog timer
Required properties:
- compatible : should be "amlogic,meson-gxbb-wdt"
- reg : Specifies base physical address and size of the registers.
- clocks : Should be a phandle to the Watchdog clock source, for GXBB the xtal
is the default clock source.
Example:
wdt: watchdog@98d0 {
compatible = "amlogic,meson-gxbb-wdt";
reg = <0 0x98d0 0x0 0x10>;
clocks = <&xtal>;
};
......@@ -7,6 +7,10 @@ Required properties :
"qcom,kpss-wdt-msm8960"
"qcom,kpss-wdt-apq8064"
"qcom,kpss-wdt-ipq8064"
"qcom,kpss-wdt-ipq4019"
"qcom,kpss-timer"
"qcom,scss-timer"
"qcom,kpss-wdt"
- reg : shall contain base register location and length
- clocks : shall contain the input clock
......
Renesas Watchdog Timer (WDT) Controller
Required properties:
- compatible : Should be "renesas,r8a7795-wdt", or "renesas,rcar-gen3-wdt"
- compatible : Should be "renesas,<soctype>-wdt", and
"renesas,rcar-gen3-wdt" as fallback.
Examples with soctypes are:
- "renesas,r8a7795-wdt" (R-Car H3)
- "renesas,r8a7796-wdt" (R-Car M3-W)
When compatible with the generic version, nodes must list the SoC-specific
version corresponding to the platform first, followed by the generic
......
......@@ -357,3 +357,6 @@ SLAVE DMA ENGINE
SPI
devm_spi_register_master()
WATCHDOG
devm_watchdog_register_device()
Last reviewed: 04/04/2016
Last reviewed: 05/20/2016
HPE iLO NMI Watchdog Driver
NMI sourcing for iLO based ProLiant Servers
Documentation and Driver by
Thomas Mingarelli <thomas.mingarelli@hpe.com>
Thomas Mingarelli
The HPE iLO NMI Watchdog driver is a kernel module that provides basic
watchdog functionality and the added benefit of NMI sourcing. Both the
......@@ -95,4 +95,3 @@ Last reviewed: 04/04/2016
-- Tom Mingarelli
(thomas.mingarelli@hpe.com)
......@@ -2,6 +2,7 @@
* Watchdog Driver Test Program
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -13,6 +14,7 @@
#include <linux/watchdog.h>
int fd;
const char v = 'V';
/*
* This function simply sends an IOCTL to the driver, which in turn ticks
......@@ -23,6 +25,7 @@ static void keep_alive(void)
{
int dummy;
printf(".");
ioctl(fd, WDIOC_KEEPALIVE, &dummy);
}
......@@ -33,8 +36,13 @@ static void keep_alive(void)
static void term(int sig)
{
int ret = write(fd, &v, 1);
close(fd);
fprintf(stderr, "Stopping watchdog ticks...\n");
if (ret < 0)
printf("\nStopping watchdog ticks failed (%d)...\n", errno);
else
printf("\nStopping watchdog ticks...\n");
exit(0);
}
......@@ -42,12 +50,14 @@ int main(int argc, char *argv[])
{
int flags;
unsigned int ping_rate = 1;
int ret;
setbuf(stdout, NULL);
fd = open("/dev/watchdog", O_WRONLY);
if (fd == -1) {
fprintf(stderr, "Watchdog device not enabled.\n");
fflush(stderr);
printf("Watchdog device not enabled.\n");
exit(-1);
}
......@@ -55,36 +65,30 @@ int main(int argc, char *argv[])
if (!strncasecmp(argv[1], "-d", 2)) {
flags = WDIOS_DISABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &flags);
fprintf(stderr, "Watchdog card disabled.\n");
fflush(stderr);
printf("Watchdog card disabled.\n");
goto end;
} else if (!strncasecmp(argv[1], "-e", 2)) {
flags = WDIOS_ENABLECARD;
ioctl(fd, WDIOC_SETOPTIONS, &flags);
fprintf(stderr, "Watchdog card enabled.\n");
fflush(stderr);
printf("Watchdog card enabled.\n");
goto end;
} else if (!strncasecmp(argv[1], "-t", 2) && argv[2]) {
flags = atoi(argv[2]);
ioctl(fd, WDIOC_SETTIMEOUT, &flags);
fprintf(stderr, "Watchdog timeout set to %u seconds.\n", flags);
fflush(stderr);
printf("Watchdog timeout set to %u seconds.\n", flags);
goto end;
} else if (!strncasecmp(argv[1], "-p", 2) && argv[2]) {
ping_rate = strtoul(argv[2], NULL, 0);
fprintf(stderr, "Watchdog ping rate set to %u seconds.\n", ping_rate);
fflush(stderr);
printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
} else {
fprintf(stderr, "-d to disable, -e to enable, -t <n> to set " \
printf("-d to disable, -e to enable, -t <n> to set " \
"the timeout,\n-p <n> to set the ping rate, and \n");
fprintf(stderr, "run by itself to tick the card.\n");
fflush(stderr);
printf("run by itself to tick the card.\n");
goto end;
}
}
fprintf(stderr, "Watchdog Ticking Away!\n");
fflush(stderr);
printf("Watchdog Ticking Away!\n");
signal(SIGINT, term);
......@@ -93,6 +97,9 @@ int main(int argc, char *argv[])
sleep(ping_rate);
}
end:
ret = write(fd, &v, 1);
if (ret < 0)
printf("Stopping watchdog ticks failed (%d)...\n", errno);
close(fd);
return 0;
}
......@@ -82,8 +82,9 @@ It contains following fields:
* max_timeout: the watchdog timer's maximum timeout value (in seconds),
as seen from userspace. If set, the maximum configurable value for
'timeout'. Not used if max_hw_heartbeat_ms is non-zero.
* min_hw_heartbeat_ms: Minimum time between heartbeats sent to the chip,
in milli-seconds.
* min_hw_heartbeat_ms: Hardware limit for minimum time between heartbeats,
in milli-seconds. This value is normally 0; it should only be provided
if the hardware can not tolerate lower intervals between heartbeats.
* max_hw_heartbeat_ms: Maximum hardware heartbeat, in milli-seconds.
If set, the infrastructure will send heartbeats to the watchdog driver
if 'timeout' is larger than max_hw_heartbeat_ms, unless WDOG_ACTIVE
......@@ -166,6 +167,10 @@ they are supported. These optional routines/operations are:
info structure).
* status: this routine checks the status of the watchdog timer device. The
status of the device is reported with watchdog WDIOF_* status flags/bits.
WDIOF_MAGICCLOSE and WDIOF_KEEPALIVEPING are reported by the watchdog core;
it is not necessary to report those bits from the driver. Also, if no status
function is provided by the driver, the watchdog core reports the status bits
provided in the bootstatus variable of struct watchdog_device.
* set_timeout: this routine checks and changes the timeout of the watchdog
timer device. It returns 0 on success, -EINVAL for "parameter out of range"
and -EIO for "could not write value to the watchdog". On success this
......
......@@ -5353,6 +5353,12 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/dvb-frontends/hd29l2*
HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
M: Brian Boylston <brian.boylston@hpe.com>
S: Supported
F: Documentation/watchdog/hpwdt.txt
F: drivers/watchdog/hpwdt.c
HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
M: Don Brace <don.brace@microsemi.com>
L: iss_storagedev@hp.com
......
......@@ -247,7 +247,8 @@
};
timer@200a000 {
compatible = "qcom,kpss-timer", "qcom,msm-timer";
compatible = "qcom,kpss-timer",
"qcom,kpss-wdt-apq8064", "qcom,msm-timer";
interrupts = <1 1 0x301>,
<1 2 0x301>,
<1 3 0x301>;
......
......@@ -252,7 +252,7 @@
};
watchdog@b017000 {
compatible = "qcom,kpss-standalone";
compatible = "qcom,kpss-wdt", "qcom,kpss-wdt-ipq4019";
reg = <0xb017000 0x40>;
clocks = <&sleep_clk>;
timeout-sec = <10>;
......
......@@ -122,7 +122,8 @@
};
timer@200a000 {
compatible = "qcom,kpss-timer", "qcom,msm-timer";
compatible = "qcom,kpss-timer",
"qcom,kpss-wdt-ipq8064", "qcom,msm-timer";
interrupts = <1 1 0x301>,
<1 2 0x301>,
<1 3 0x301>,
......
......@@ -87,7 +87,8 @@
};
timer@200a000 {
compatible = "qcom,kpss-timer", "qcom,msm-timer";
compatible = "qcom,kpss-timer",
"qcom,kpss-wdt-msm8960", "qcom,msm-timer";
interrupts = <1 1 0x301>,
<1 2 0x301>,
<1 3 0x301>;
......
......@@ -85,7 +85,7 @@
* platform device and to export resources for those functions.
*/
#define TCO_DEVICE_NAME "iTCO_wdt"
#define SMI_EN_OFFSET 0x30
#define SMI_EN_OFFSET 0x40
#define SMI_EN_SIZE 4
#define TCO_BASE_OFFSET 0x60
#define TCO_REGS_SIZE 16
......@@ -94,6 +94,8 @@
#define TELEM_SSRAM_SIZE 240
#define TELEM_PMC_SSRAM_OFFSET 0x1B00
#define TELEM_PUNIT_SSRAM_OFFSET 0x1A00
#define TCO_PMC_OFFSET 0x8
#define TCO_PMC_SIZE 0x4
static const int iTCO_version = 3;
......@@ -502,7 +504,7 @@ static struct resource tco_res[] = {
static struct itco_wdt_platform_data tco_info = {
.name = "Apollo Lake SoC",
.version = 3,
.version = 5,
};
#define TELEMETRY_RESOURCE_PUNIT_SSRAM 0
......@@ -572,8 +574,8 @@ static int ipc_create_tco_device(void)
res->end = res->start + SMI_EN_SIZE - 1;
res = tco_res + TCO_RESOURCE_GCR_MEM;
res->start = ipcdev.gcr_base;
res->end = res->start + ipcdev.gcr_size - 1;
res->start = ipcdev.gcr_base + TCO_PMC_OFFSET;
res->end = res->start + TCO_PMC_SIZE - 1;
ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res));
if (ret) {
......
......@@ -48,7 +48,6 @@ config WATCHDOG_NOWAYOUT
config WATCHDOG_SYSFS
bool "Read different watchdog information through sysfs"
default n
help
Say Y here if you want to enable watchdog device status read through
sysfs attributes.
......@@ -516,6 +515,15 @@ config MAX63XX_WATCHDOG
help
Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
config MAX77620_WATCHDOG
tristate "Maxim Max77620 Watchdog Timer"
depends on MFD_MAX77620
help
This is the driver for the Max77620 watchdog timer.
Say 'Y' here to enable the watchdog timer support for
MAX77620 chips. To compile this driver as a module,
choose M here: the module will be called max77620_wdt.
config IMX2_WDT
tristate "IMX2+ Watchdog"
depends on ARCH_MXC || ARCH_LAYERSCAPE
......@@ -609,6 +617,16 @@ config QCOM_WDT
To compile this driver as a module, choose M here: the
module will be called qcom_wdt.
config MESON_GXBB_WATCHDOG
tristate "Amlogic Meson GXBB SoCs watchdog support"
depends on ARCH_MESON
select WATCHDOG_CORE
help
Say Y here to include support for the watchdog timer
in Amlogic Meson GXBB SoCs.
To compile this driver as a module, choose M here: the
module will be called meson_gxbb_wdt.
config MESON_WATCHDOG
tristate "Amlogic Meson SoCs watchdog support"
depends on ARCH_MESON
......@@ -669,6 +687,19 @@ config RENESAS_WDT
This driver adds watchdog support for the integrated watchdogs in the
Renesas R-Car and other SH-Mobile SoCs (usually named RWDT or SWDT).
config ASPEED_WATCHDOG
tristate "Aspeed 2400 watchdog support"
depends on ARCH_ASPEED || COMPILE_TEST
select WATCHDOG_CORE
help
Say Y here to include support for the watchdog timer
in Apseed BMC SoCs.
This driver is required to reboot the SoC.
To compile this driver as a module, choose M here: the
module will be called aspeed_wdt.
# AVR32 Architecture
config AT32AP700X_WDT
......
......@@ -67,6 +67,7 @@ obj-$(CONFIG_ST_LPC_WATCHDOG) += st_lpc_wdt.o
obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
obj-$(CONFIG_MESON_GXBB_WATCHDOG) += meson_gxbb_wdt.o
obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
......@@ -74,6 +75,7 @@ obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
......@@ -203,6 +205,7 @@ obj-$(CONFIG_TANGOX_WATCHDOG) += tangox_wdt.o
obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o
obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
/*
* Copyright 2016 IBM Corporation
*
* Joel Stanley <joel@jms.id.au>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
struct aspeed_wdt {
struct watchdog_device wdd;
void __iomem *base;
u32 ctrl;
};
static const struct of_device_id aspeed_wdt_of_table[] = {
{ .compatible = "aspeed,ast2400-wdt" },
{ .compatible = "aspeed,ast2500-wdt" },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
#define WDT_STATUS 0x00
#define WDT_RELOAD_VALUE 0x04
#define WDT_RESTART 0x08
#define WDT_CTRL 0x0C
#define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
#define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
#define WDT_CTRL_1MHZ_CLK BIT(4)
#define WDT_CTRL_WDT_EXT BIT(3)
#define WDT_CTRL_WDT_INTR BIT(2)
#define WDT_CTRL_RESET_SYSTEM BIT(1)
#define WDT_CTRL_ENABLE BIT(0)
#define WDT_RESTART_MAGIC 0x4755
/* 32 bits at 1MHz, in milliseconds */
#define WDT_MAX_TIMEOUT_MS 4294967
#define WDT_DEFAULT_TIMEOUT 30
#define WDT_RATE_1MHZ 1000000
static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
{
return container_of(wdd, struct aspeed_wdt, wdd);
}
static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
{
wdt->ctrl |= WDT_CTRL_ENABLE;
writel(0, wdt->base + WDT_CTRL);
writel(count, wdt->base + WDT_RELOAD_VALUE);
writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
writel(wdt->ctrl, wdt->base + WDT_CTRL);
}
static int aspeed_wdt_start(struct watchdog_device *wdd)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ);
return 0;
}
static int aspeed_wdt_stop(struct watchdog_device *wdd)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
wdt->ctrl &= ~WDT_CTRL_ENABLE;
writel(wdt->ctrl, wdt->base + WDT_CTRL);
return 0;
}
static int aspeed_wdt_ping(struct watchdog_device *wdd)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
return 0;
}
static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
u32 actual;
wdd->timeout = timeout;
actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000);
writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE);
writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
return 0;
}
static int aspeed_wdt_restart(struct watchdog_device *wdd,
unsigned long action, void *data)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000);
mdelay(1000);
return 0;
}
static const struct watchdog_ops aspeed_wdt_ops = {
.start = aspeed_wdt_start,
.stop = aspeed_wdt_stop,
.ping = aspeed_wdt_ping,
.set_timeout = aspeed_wdt_set_timeout,
.restart = aspeed_wdt_restart,
.owner = THIS_MODULE,
};
static const struct watchdog_info aspeed_wdt_info = {
.options = WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
| WDIOF_SETTIMEOUT,
.identity = KBUILD_MODNAME,
};
static int aspeed_wdt_remove(struct platform_device *pdev)
{
struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
watchdog_unregister_device(&wdt->wdd);
return 0;
}
static int aspeed_wdt_probe(struct platform_device *pdev)
{
struct aspeed_wdt *wdt;
struct resource *res;
int ret;
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
wdt->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(wdt->base))
return PTR_ERR(wdt->base);
/*
* The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
* runs at 1MHz. We chose to always run at 1MHz, as there's no
* good reason to have a faster watchdog counter.
*/
wdt->wdd.info = &aspeed_wdt_info;
wdt->wdd.ops = &aspeed_wdt_ops;
wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
wdt->wdd.parent = &pdev->dev;
wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
/*
* Control reset on a per-device basis to ensure the
* host is not affected by a BMC reboot, so only reset
* the SOC and not the full chip
*/
wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
WDT_CTRL_1MHZ_CLK |
WDT_CTRL_RESET_SYSTEM;
if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE) {
aspeed_wdt_start(&wdt->wdd);
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
}
ret = watchdog_register_device(&wdt->wdd);
if (ret) {
dev_err(&pdev->dev, "failed to register\n");
return ret;
}
platform_set_drvdata(pdev, wdt);
return 0;
}
static struct platform_driver aspeed_watchdog_driver = {
.probe = aspeed_wdt_probe,
.remove = aspeed_wdt_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(aspeed_wdt_of_table),
},
};
module_platform_driver(aspeed_watchdog_driver);
MODULE_DESCRIPTION("Aspeed Watchdog Driver");
MODULE_LICENSE("GPL");
......@@ -82,12 +82,6 @@ static int bcm2835_wdt_stop(struct watchdog_device *wdog)
return 0;
}
static int bcm2835_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t)
{
wdog->timeout = t;
return 0;
}
static unsigned int bcm2835_wdt_get_timeleft(struct watchdog_device *wdog)
{
struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog);
......@@ -96,15 +90,14 @@ static unsigned int bcm2835_wdt_get_timeleft(struct watchdog_device *wdog)
return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
}
static struct watchdog_ops bcm2835_wdt_ops = {
static const struct watchdog_ops bcm2835_wdt_ops = {
.owner = THIS_MODULE,
.start = bcm2835_wdt_start,
.stop = bcm2835_wdt_stop,
.set_timeout = bcm2835_wdt_set_timeout,
.get_timeleft = bcm2835_wdt_get_timeleft,
};
static struct watchdog_info bcm2835_wdt_info = {
static const struct watchdog_info bcm2835_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.identity = "Broadcom BCM2835 Watchdog timer",
......
......@@ -34,6 +34,7 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
#define DA9063_WDT_MIN_TIMEOUT wdt_timeout[DA9063_TWDSCALE_MIN]
#define DA9063_WDT_MAX_TIMEOUT wdt_timeout[DA9063_TWDSCALE_MAX]
#define DA9063_WDG_TIMEOUT wdt_timeout[3]
#define DA9063_RESET_PROTECTION_MS 256
struct da9063_watchdog {
struct da9063 *da9063;
......@@ -171,6 +172,7 @@ static int da9063_wdt_probe(struct platform_device *pdev)
wdt->wdtdev.ops = &da9063_watchdog_ops;
wdt->wdtdev.min_timeout = DA9063_WDT_MIN_TIMEOUT;
wdt->wdtdev.max_timeout = DA9063_WDT_MAX_TIMEOUT;
wdt->wdtdev.min_hw_heartbeat_ms = DA9063_RESET_PROTECTION_MS;
wdt->wdtdev.timeout = DA9063_WDG_TIMEOUT;
wdt->wdtdev.parent = &pdev->dev;
......
......@@ -45,9 +45,11 @@
#define SIO_REG_DEVREV 0x22 /* Device revision */
#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
#define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */
#define SIO_F81866_REG_PORT_SEL 0x27 /* F81866 Multi-Function Register */
#define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */
#define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */
#define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */
#define SIO_F81866_REG_GPIO1 0x2c /* F81866 GPIO1 Enable Register */
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
......@@ -60,6 +62,7 @@
#define SIO_F71882_ID 0x0541 /* Chipset ID */
#define SIO_F71889_ID 0x0723 /* Chipset ID */
#define SIO_F81865_ID 0x0704 /* Chipset ID */
#define SIO_F81866_ID 0x1010 /* Chipset ID */
#define F71808FG_REG_WDO_CONF 0xf0
#define F71808FG_REG_WDT_CONF 0xf5
......@@ -116,7 +119,8 @@ module_param(start_withtimeout, uint, 0);
MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with"
" given initial timeout. Zero (default) disables this feature.");
enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg, f81865 };
enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg, f81865,
f81866};
static const char *f71808e_names[] = {
"f71808fg",
......@@ -126,6 +130,7 @@ static const char *f71808e_names[] = {
"f71882fg",
"f71889fg",
"f81865",
"f81866",
};
/* Super-I/O Function prototypes */
......@@ -370,6 +375,22 @@ static int watchdog_start(void)
superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 5);
break;
case f81866:
/* Set pin 70 to WDTRST# */
superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL,
BIT(3) | BIT(0));
superio_set_bit(watchdog.sioaddr, SIO_F81866_REG_PORT_SEL,
BIT(2));
/*
* GPIO1 Control Register when 27h BIT3:2 = 01 & BIT0 = 0.
* The PIN 70(GPIO15/WDTRST) is controlled by 2Ch:
* BIT5: 0 -> WDTRST#
* 1 -> GPIO15
*/
superio_clear_bit(watchdog.sioaddr, SIO_F81866_REG_GPIO1,
BIT(5));
break;
default:
/*
* 'default' label to shut up the compiler and catch
......@@ -382,7 +403,7 @@ static int watchdog_start(void)
superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT);
superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0);
if (watchdog.type == f81865)
if (watchdog.type == f81865 || watchdog.type == f81866)
superio_set_bit(watchdog.sioaddr, F81865_REG_WDO_CONF,
F81865_FLAG_WDOUT_EN);
else
......@@ -788,6 +809,9 @@ static int __init f71808e_find(int sioaddr)
case SIO_F81865_ID:
watchdog.type = f81865;
break;
case SIO_F81866_ID:
watchdog.type = f81866;
break;
default:
pr_info("Unrecognized Fintek device: %04x\n",
(unsigned int)devid);
......
......@@ -151,6 +151,8 @@ static int gpio_wdt_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);