Commit b611996e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-watchdog-6.2-rc1' of git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:

 - Add Advantech EC watchdog driver

 - Add support for MT6795 Helio X10 watchdog and toprgu

 - Add support for MT8188 watchdog device

 - Remove #ifdef guards for PM related functions

 - Other fixes and improvements

* tag 'linux-watchdog-6.2-rc1' of git://www.linux-watchdog.org/linux-watchdog:
  watchdog: aspeed: Enable pre-timeout interrupt
  watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running
  watchdog: rn5t618: add support for read out bootstatus
  watchdog: kempld: Remove #ifdef guards for PM related functions
  watchdog: omap: Remove #ifdef guards for PM related functions
  watchdog: twl4030: Remove #ifdef guards for PM related functions
  watchdog: at91rm9200: Remove #ifdef guards for PM related functions
  watchdog: Add Advantech EC watchdog driver
  dt-bindings: watchdog: mediatek,mtk-wdt: Add compatible for MT8173
  dt-bindings: watchdog: mediatek,mtk-wdt: Add compatible for MT6795
  dt-bindings: watchdog: mediatek: Convert mtk-wdt to json-schema
  watchdog: mediatek: mt8188: add wdt support
  dt-bindings: reset: mt8188: add toprgu reset-controller header file
  dt-bindings: watchdog: Add compatible for MediaTek MT8188
  watchdog: mtk_wdt: Add support for MT6795 Helio X10 watchdog and toprgu
parents 75caf594 9ec0b7e0
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/watchdog/mediatek,mtk-wdt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek SoCs Watchdog timer
maintainers:
- Matthias Brugger <matthias.bgg@gmail.com>
description:
The watchdog supports a pre-timeout interrupt that fires
timeout-sec/2 before the expiry.
allOf:
- $ref: watchdog.yaml#
properties:
compatible:
oneOf:
- enum:
- mediatek,mt2712-wdt
- mediatek,mt6589-wdt
- mediatek,mt6795-wdt
- mediatek,mt7986-wdt
- mediatek,mt8183-wdt
- mediatek,mt8186-wdt
- mediatek,mt8188-wdt
- mediatek,mt8192-wdt
- mediatek,mt8195-wdt
- items:
- enum:
- mediatek,mt2701-wdt
- mediatek,mt6582-wdt
- mediatek,mt6797-wdt
- mediatek,mt7622-wdt
- mediatek,mt7623-wdt
- mediatek,mt7629-wdt
- mediatek,mt8173-wdt
- mediatek,mt8516-wdt
- const: mediatek,mt6589-wdt
reg:
maxItems: 1
interrupts:
items:
- description: Watchdog pre-timeout (bark) interrupt
mediatek,disable-extrst:
description: Disable sending output reset signal
type: boolean
'#reset-cells':
const: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
watchdog: watchdog@10007000 {
compatible = "mediatek,mt8183-wdt";
reg = <0 0x10007000 0 0x100>;
interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
mediatek,disable-extrst;
timeout-sec = <10>;
#reset-cells = <1>;
};
};
Mediatek SoCs Watchdog timer
The watchdog supports a pre-timeout interrupt that fires timeout-sec/2
before the expiry.
Required properties:
- compatible should contain:
"mediatek,mt2701-wdt", "mediatek,mt6589-wdt": for MT2701
"mediatek,mt2712-wdt": for MT2712
"mediatek,mt6582-wdt", "mediatek,mt6589-wdt": for MT6582
"mediatek,mt6589-wdt": for MT6589
"mediatek,mt6797-wdt", "mediatek,mt6589-wdt": for MT6797
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
"mediatek,mt7986-wdt", "mediatek,mt6589-wdt": for MT7986
"mediatek,mt8183-wdt": for MT8183
"mediatek,mt8186-wdt", "mediatek,mt6589-wdt": for MT8186
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
"mediatek,mt8192-wdt": for MT8192
"mediatek,mt8195-wdt", "mediatek,mt6589-wdt": for MT8195
- reg : Specifies base physical address and size of the registers.
Optional properties:
- mediatek,disable-extrst: disable send output reset signal
- interrupts: Watchdog pre-timeout (bark) interrupt.
- timeout-sec: contains the watchdog timeout in seconds.
- #reset-cells: Should be 1.
Example:
watchdog: watchdog@10007000 {
compatible = "mediatek,mt8183-wdt",
"mediatek,mt6589-wdt";
mediatek,disable-extrst;
reg = <0 0x10007000 0 0x100>;
interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>;
timeout-sec = <10>;
#reset-cells = <1>;
};
......@@ -1055,6 +1055,13 @@ config ADVANTECH_WDT
feature. More information can be found at
<https://www.advantech.com.tw/products/>
config ADVANTECH_EC_WDT
tristate "Advantech Embedded Controller Watchdog Timer"
depends on X86
help
This driver supports Advantech products with ITE based Embedded Controller.
It does not support Advantech products with other ECs or without EC.
config ALIM1535_WDT
tristate "ALi M1535 PMU Watchdog Timer"
depends on X86 && PCI
......
......@@ -102,6 +102,7 @@ obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
# X86 (i386 + ia64 + x86_64) Architecture
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
obj-$(CONFIG_ADVANTECH_EC_WDT) += advantech_ec_wdt.o
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
obj-$(CONFIG_EBC_C384_WDT) += ebc-c384_wdt.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Advantech Embedded Controller Watchdog Driver
*
* This driver supports Advantech products with ITE based Embedded Controller.
* It does not support Advantech products with other ECs or without EC.
*
* Copyright (C) 2022 Advantech Europe B.V.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/watchdog.h>
#define DRIVER_NAME "advantech_ec_wdt"
/* EC IO region */
#define EC_BASE_ADDR 0x299
#define EC_ADDR_EXTENT 2
/* EC minimum IO access delay in ms */
#define EC_MIN_DELAY 10
/* EC interface definitions */
#define EC_ADDR_CMD (EC_BASE_ADDR + 1)
#define EC_ADDR_DATA EC_BASE_ADDR
#define EC_CMD_EC_PROBE 0x30
#define EC_CMD_COMM 0x89
#define EC_CMD_WDT_START 0x28
#define EC_CMD_WDT_STOP 0x29
#define EC_CMD_WDT_RESET 0x2A
#define EC_DAT_EN_DLY_H 0x58
#define EC_DAT_EN_DLY_L 0x59
#define EC_DAT_RST_DLY_H 0x5E
#define EC_DAT_RST_DLY_L 0x5F
#define EC_MAGIC 0x95
/* module parameters */
#define MIN_TIME 1
#define MAX_TIME 6000 /* 100 minutes */
#define DEFAULT_TIME 60
static unsigned int timeout;
static ktime_t ec_timestamp;
module_param(timeout, uint, 0);
MODULE_PARM_DESC(timeout,
"Default Watchdog timer setting (" __MODULE_STRING(DEFAULT_TIME) "s). The range is from " __MODULE_STRING(MIN_TIME) " to " __MODULE_STRING(MAX_TIME) ".");
static void adv_ec_wdt_timing_gate(void)
{
ktime_t time_cur, time_delta;
/* ensure minimum delay between IO accesses*/
time_cur = ktime_get();
time_delta = ktime_to_ms(ktime_sub(time_cur, ec_timestamp));
if (time_delta < EC_MIN_DELAY) {
time_delta = EC_MIN_DELAY - time_delta;
usleep_range(time_delta * 1000, (time_delta + 1) * 1000);
}
ec_timestamp = ktime_get();
}
static void adv_ec_wdt_outb(unsigned char value, unsigned short port)
{
adv_ec_wdt_timing_gate();
outb(value, port);
}
static unsigned char adv_ec_wdt_inb(unsigned short port)
{
adv_ec_wdt_timing_gate();
return inb(port);
}
static int adv_ec_wdt_ping(struct watchdog_device *wdd)
{
adv_ec_wdt_outb(EC_CMD_WDT_RESET, EC_ADDR_CMD);
return 0;
}
static int adv_ec_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
{
unsigned int val;
/* scale time to EC 100 ms base */
val = t * 10;
/* reset enable delay, just in case it was set by BIOS etc. */
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
adv_ec_wdt_outb(EC_DAT_EN_DLY_H, EC_ADDR_DATA);
adv_ec_wdt_outb(0, EC_ADDR_DATA);
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
adv_ec_wdt_outb(EC_DAT_EN_DLY_L, EC_ADDR_DATA);
adv_ec_wdt_outb(0, EC_ADDR_DATA);
/* set reset delay */
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
adv_ec_wdt_outb(EC_DAT_RST_DLY_H, EC_ADDR_DATA);
adv_ec_wdt_outb(val >> 8, EC_ADDR_DATA);
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
adv_ec_wdt_outb(EC_DAT_RST_DLY_L, EC_ADDR_DATA);
adv_ec_wdt_outb(val & 0xFF, EC_ADDR_DATA);
wdd->timeout = t;
return 0;
}
static int adv_ec_wdt_start(struct watchdog_device *wdd)
{
adv_ec_wdt_set_timeout(wdd, wdd->timeout);
adv_ec_wdt_outb(EC_CMD_WDT_START, EC_ADDR_CMD);
return 0;
}
static int adv_ec_wdt_stop(struct watchdog_device *wdd)
{
adv_ec_wdt_outb(EC_CMD_WDT_STOP, EC_ADDR_CMD);
return 0;
}
static const struct watchdog_info adv_ec_wdt_info = {
.identity = DRIVER_NAME,
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
};
static const struct watchdog_ops adv_ec_wdt_ops = {
.owner = THIS_MODULE,
.start = adv_ec_wdt_start,
.stop = adv_ec_wdt_stop,
.ping = adv_ec_wdt_ping,
.set_timeout = adv_ec_wdt_set_timeout,
};
static struct watchdog_device adv_ec_wdt_dev = {
.info = &adv_ec_wdt_info,
.ops = &adv_ec_wdt_ops,
.min_timeout = MIN_TIME,
.max_timeout = MAX_TIME,
.timeout = DEFAULT_TIME,
};
static int adv_ec_wdt_probe(struct device *dev, unsigned int id)
{
if (!devm_request_region(dev, EC_BASE_ADDR, EC_ADDR_EXTENT, dev_name(dev))) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
EC_BASE_ADDR, EC_BASE_ADDR + EC_ADDR_EXTENT);
return -EBUSY;
}
watchdog_init_timeout(&adv_ec_wdt_dev, timeout, dev);
watchdog_stop_on_reboot(&adv_ec_wdt_dev);
watchdog_stop_on_unregister(&adv_ec_wdt_dev);
return devm_watchdog_register_device(dev, &adv_ec_wdt_dev);
}
static struct isa_driver adv_ec_wdt_driver = {
.probe = adv_ec_wdt_probe,
.driver = {
.name = DRIVER_NAME,
},
};
static int __init adv_ec_wdt_init(void)
{
unsigned int val;
/* quick probe for EC */
if (!request_region(EC_BASE_ADDR, EC_ADDR_EXTENT, DRIVER_NAME))
return -EBUSY;
adv_ec_wdt_outb(EC_CMD_EC_PROBE, EC_ADDR_CMD);
val = adv_ec_wdt_inb(EC_ADDR_DATA);
release_region(EC_BASE_ADDR, EC_ADDR_EXTENT);
if (val != EC_MAGIC)
return -ENODEV;
return isa_register_driver(&adv_ec_wdt_driver, 1);
}
static void __exit adv_ec_wdt_exit(void)
{
isa_unregister_driver(&adv_ec_wdt_driver);
}
module_init(adv_ec_wdt_init);
module_exit(adv_ec_wdt_exit);
MODULE_AUTHOR("Thomas Kastner <thomas.kastner@advantech.com>");
MODULE_DESCRIPTION("Advantech Embedded Controller Watchdog Device Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("20221019");
MODULE_ALIAS("isa:" DRIVER_NAME);
......@@ -5,11 +5,14 @@
* Joel Stanley <joel@jms.id.au>
*/
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
......@@ -18,28 +21,41 @@ module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
struct aspeed_wdt_config {
u32 ext_pulse_width_mask;
u32 irq_shift;
u32 irq_mask;
};
struct aspeed_wdt {
struct watchdog_device wdd;
void __iomem *base;
u32 ctrl;
};
struct aspeed_wdt_config {
u32 ext_pulse_width_mask;
const struct aspeed_wdt_config *cfg;
};
static const struct aspeed_wdt_config ast2400_config = {
.ext_pulse_width_mask = 0xff,
.irq_shift = 0,
.irq_mask = 0,
};
static const struct aspeed_wdt_config ast2500_config = {
.ext_pulse_width_mask = 0xfffff,
.irq_shift = 12,
.irq_mask = GENMASK(31, 12),
};
static const struct aspeed_wdt_config ast2600_config = {
.ext_pulse_width_mask = 0xfffff,
.irq_shift = 0,
.irq_mask = GENMASK(31, 10),
};
static const struct of_device_id aspeed_wdt_of_table[] = {
{ .compatible = "aspeed,ast2400-wdt", .data = &ast2400_config },
{ .compatible = "aspeed,ast2500-wdt", .data = &ast2500_config },
{ .compatible = "aspeed,ast2600-wdt", .data = &ast2500_config },
{ .compatible = "aspeed,ast2600-wdt", .data = &ast2600_config },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
......@@ -58,6 +74,7 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
#define WDT_CTRL_RESET_SYSTEM BIT(1)
#define WDT_CTRL_ENABLE BIT(0)
#define WDT_TIMEOUT_STATUS 0x10
#define WDT_TIMEOUT_STATUS_IRQ BIT(2)
#define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1)
#define WDT_CLEAR_TIMEOUT_STATUS 0x14
#define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0)
......@@ -160,6 +177,26 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
return 0;
}
static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd,
unsigned int pretimeout)
{
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
u32 actual = pretimeout * WDT_RATE_1MHZ;
u32 s = wdt->cfg->irq_shift;
u32 m = wdt->cfg->irq_mask;
wdd->pretimeout = pretimeout;
wdt->ctrl &= ~m;
if (pretimeout)
wdt->ctrl |= ((actual << s) & m) | WDT_CTRL_WDT_INTR;
else
wdt->ctrl &= ~WDT_CTRL_WDT_INTR;
writel(wdt->ctrl, wdt->base + WDT_CTRL);
return 0;
}
static int aspeed_wdt_restart(struct watchdog_device *wdd,
unsigned long action, void *data)
{
......@@ -232,6 +269,7 @@ static const struct watchdog_ops aspeed_wdt_ops = {
.stop = aspeed_wdt_stop,
.ping = aspeed_wdt_ping,
.set_timeout = aspeed_wdt_set_timeout,
.set_pretimeout = aspeed_wdt_set_pretimeout,
.restart = aspeed_wdt_restart,
.owner = THIS_MODULE,
};
......@@ -243,10 +281,29 @@ static const struct watchdog_info aspeed_wdt_info = {
.identity = KBUILD_MODNAME,
};
static const struct watchdog_info aspeed_wdt_pretimeout_info = {
.options = WDIOF_KEEPALIVEPING
| WDIOF_PRETIMEOUT
| WDIOF_MAGICCLOSE
| WDIOF_SETTIMEOUT,
.identity = KBUILD_MODNAME,
};
static irqreturn_t aspeed_wdt_irq(int irq, void *arg)
{
struct watchdog_device *wdd = arg;
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS);
if (status & WDT_TIMEOUT_STATUS_IRQ)
watchdog_notify_pretimeout(wdd);
return IRQ_HANDLED;
}
static int aspeed_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct aspeed_wdt_config *config;
const struct of_device_id *ofdid;
struct aspeed_wdt *wdt;
struct device_node *np;
......@@ -259,11 +316,33 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
if (!wdt)
return -ENOMEM;
np = dev->of_node;
ofdid = of_match_node(aspeed_wdt_of_table, np);
if (!ofdid)
return -EINVAL;
wdt->cfg = ofdid->data;
wdt->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(wdt->base))
return PTR_ERR(wdt->base);
wdt->wdd.info = &aspeed_wdt_info;
if (wdt->cfg->irq_mask) {
int irq = platform_get_irq_optional(pdev, 0);
if (irq > 0) {
ret = devm_request_irq(dev, irq, aspeed_wdt_irq,
IRQF_SHARED, dev_name(dev),
wdt);
if (ret)
return ret;
wdt->wdd.info = &aspeed_wdt_pretimeout_info;
}
}
wdt->wdd.ops = &aspeed_wdt_ops;
wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
wdt->wdd.parent = dev;
......@@ -273,13 +352,6 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(&wdt->wdd, nowayout);
np = dev->of_node;
ofdid = of_match_node(aspeed_wdt_of_table, np);
if (!ofdid)
return -EINVAL;
config = ofdid->data;
/*
* On clock rates:
* - ast2400 wdt can run at PCLK, or 1MHz
......@@ -331,7 +403,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
(of_device_is_compatible(np, "aspeed,ast2600-wdt"))) {
u32 reg = readl(wdt->base + WDT_RESET_WIDTH);
reg &= config->ext_pulse_width_mask;
reg &= wdt->cfg->ext_pulse_width_mask;
if (of_property_read_bool(np, "aspeed,ext-active-high"))
reg |= WDT_ACTIVE_HIGH_MAGIC;
else
......@@ -339,7 +411,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
writel(reg, wdt->base + WDT_RESET_WIDTH);
reg &= config->ext_pulse_width_mask;
reg &= wdt->cfg->ext_pulse_width_mask;
if (of_property_read_bool(np, "aspeed,ext-push-pull"))
reg |= WDT_PUSH_PULL_MAGIC;
else
......@@ -349,7 +421,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
}
if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {
u32 max_duration = config->ext_pulse_width_mask + 1;
u32 max_duration = wdt->cfg->ext_pulse_width_mask + 1;
if (duration == 0 || duration > max_duration) {
dev_err(dev, "Invalid pulse duration: %uus\n",
......
......@@ -278,8 +278,6 @@ static void at91wdt_shutdown(struct platform_device *pdev)
at91_wdt_stop();
}
#ifdef CONFIG_PM
static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
{
at91_wdt_stop();
......@@ -293,11 +291,6 @@ static int at91wdt_resume(struct platform_device *pdev)
return 0;
}
#else
#define at91wdt_suspend NULL
#define at91wdt_resume NULL
#endif
static const struct of_device_id at91_wdt_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-wdt" },
{ /* sentinel */ }
......@@ -308,8 +301,8 @@ static struct platform_driver at91wdt_driver = {
.probe = at91wdt_probe,
.remove = at91wdt_remove,
.shutdown = at91wdt_shutdown,
.suspend = at91wdt_suspend,
.resume = at91wdt_resume,
.suspend = pm_ptr(at91wdt_suspend),
.resume = pm_ptr(at91wdt_resume),
.driver = {
.name = "atmel_st_watchdog",
.of_match_table = at91_wdt_dt_ids,
......
......@@ -105,7 +105,6 @@ static int db8500_wdt_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int db8500_wdt_suspend(struct platform_device *pdev,
pm_message_t state)
{
......@@ -130,15 +129,11 @@ static int db8500_wdt_resume(struct platform_device *pdev)
}
return 0;
}
#else
#define db8500_wdt_suspend NULL
#define db8500_wdt_resume NULL
#endif
static struct platform_driver db8500_wdt_driver = {
.probe = db8500_wdt_probe,
.suspend = db8500_wdt_suspend,
.resume = db8500_wdt_resume,
.suspend = pm_ptr(db8500_wdt_suspend),
.resume = pm_ptr(db8500_wdt_resume),
.driver = {
.name = "db8500_wdt",
},
......
......@@ -423,14 +423,18 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
return time_left;
}
static void iTCO_wdt_set_running(struct iTCO_wdt_private *p)
/* Returns true if the watchdog was running */
static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p)
{
u16 val;
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is * enabled */
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled */
val = inw(TCO1_CNT(p));
if (!(val & BIT(11)))
if (!(val & BIT(11))) {
set_bit(WDOG_HW_RUNNING, &p->wddev.status);
return true;
}
return false;
}
/*
......@@ -518,9 +522,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
return -ENODEV; /* Cannot reset NO_REBOOT bit */
}
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
p->update_no_reboot_bit(p->no_reboot_priv, true);
if (turn_SMI_watchdog_clear_off >= p->iTCO_version) {
/*
* Bit 13: TCO_EN -> 0
......@@ -572,7 +573,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
watchdog_set_drvdata(&p->wddev, p);
platform_set_drvdata(pdev, p);
iTCO_wdt_set_running(p);
if (!iTCO_wdt_set_running(p)) {
/*
* If the watchdog was not running set NO_REBOOT now to
* prevent later reboots.
*/
p->update_no_reboot_bit(p->no_reboot_priv, true);
}
/* Check that the heartbeat value is within it's range;
if not reset to the default */
......
......@@ -75,9 +75,7 @@ struct kempld_wdt_data {
struct watchdog_device wdd;
unsigned int pretimeout;
struct kempld_wdt_stage stage[KEMPLD_WDT_MAX_STAGES];
#ifdef CONFIG_PM
u8 pm_status_store;
#endif
};
#define DEFAULT_TIMEOUT 30 /* seconds */
......@@ -495,7 +493,6 @@ static int kempld_wdt_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
/* Disable watchdog if it is active during suspend */
static int kempld_wdt_suspend(struct platform_device *pdev,
pm_message_t message)
......@@ -531,18 +528,14 @@ static int kempld_wdt_resume(struct platform_device *pdev)
else
return kempld_wdt_stop(wdd);
}
#else
#define kempld_wdt_suspend NULL
#define kempld_wdt_resume NULL
#endif
static struct platform_driver kempld_wdt_driver = {
.driver = {
.name = "kempld-wdt",
},
.probe = kempld_wdt_probe,
.suspend = kempld_wdt_suspend,
.resume = kempld_wdt_resume,
.suspend = pm_ptr(kempld_wdt_suspend),
.resume = pm_ptr(kempld_wdt_resume),
};
module_platform_driver(kempld_wdt_driver);
......
......@@ -10,9 +10,11 @@
*/
#include <dt-bindings/reset/mt2712-resets.h>
#include <dt-bindings/reset/mediatek,mt6795-resets.h>
#include <dt-bindings/reset/mt7986-resets.h>
#include <dt-bindings/reset/mt8183-resets.h>
#include <dt-bindings/reset/mt8186-resets.h>
#include <dt-bindings/reset/mt8188-resets.h>
#include <dt-bindings/reset/mt8192-resets.h>
#include <dt-bindings/reset/mt8195-resets.h>
#include <linux/delay.h>
......@@ -78,6 +80,10 @@ static const struct mtk_wdt_data mt2712_data = {
.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
};
static const struct mtk_wdt_data mt6795_data = {
.toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM,
};
static const struct mtk_wdt_data mt7986_data = {
.toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM,
};
......@@ -90,6 +96,10 @@ static const struct mtk_wdt_data mt8186_data = {
.toprgu_sw_rst_num = MT8186_TOPRGU_SW_RST_NUM,
};
static const struct mtk_wdt_data mt8188_data = {
.toprgu_sw_rst_num = MT8188_TOPRGU_SW_RST_NUM,
};
static const struct mtk_wdt_data mt8192_data = {
.toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM,
};
......@@ -426,9 +436,11 @@ static int mtk_wdt_resume(struct device *dev)
static const struct of_device_id mtk_wdt_dt_ids[] = {
{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
{ .compatible = "mediatek,mt6589-wdt" },
{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
{ .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data },
{ .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data },
{ .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data },
{ .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data },
{ /* sentinel */ }
......
......@@ -316,8 +316,6 @@ static int omap_wdt_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
/* REVISIT ... not clear this is the best way to handle system suspend; and
* it's very inappropriate for selective device suspend (e.g. suspending this
* through sysfs rather than by stopping the watchdog daemon). Also, this
......@@ -353,11 +351,6 @@ static int omap_wdt_resume(struct platform_device *pdev)
return 0;
}
#else
#define omap_wdt_suspend NULL
#define omap_wdt_resume NULL
#endif
static const struct of_device_id omap_wdt_of_match[] = {
{ .compatible = "ti,omap3-wdt", },
{},
......@@ -368,8 +361,8 @@ static struct platform_driver omap_wdt_driver = {
.probe = omap_wdt_probe,
.remove = omap_wdt_remove,
.shutdown = omap_wdt_shutdown,
.suspend = omap_wdt_suspend,
.resume = omap_wdt_resume,
.suspend = pm_ptr(omap_wdt_suspend),
.resume = pm_ptr(omap_wdt_resume),
.driver = {
.name = "omap_wdt",
.of_match_table = omap_wdt_of_match,
......
......@@ -144,6 +144,8 @@ static int rn5t618_wdt_probe(struct platform_device *pdev)
struct rn5t618 *rn5t618 = dev_get_drvdata(dev->parent);
struct rn5t618_wdt *wdt;
int min_timeout, max_timeout;
int ret;
unsigned int val;
wdt = devm_kzalloc(dev, sizeof(struct rn5t618_wdt), GFP_KERNEL);
if (!wdt)
......@@ -160,6 +162,16 @@ static int rn5t618_wdt_probe(struct platform_device *pdev)
wdt->wdt_dev.timeout = max_timeout;
wdt->wdt_dev.parent = dev;
/* Read out previous power-off factor */
ret = regmap_read(wdt->rn5t618->regmap, RN5T618_POFFHIS, &val);
if (ret)
return ret;
if (val & RN5T618_POFFHIS_VINDET)
wdt->wdt_dev.bootstatus = WDIOF_POWERUNDER;
else if (val & RN5T618_POFFHIS_WDG)
wdt->wdt_dev.bootstatus = WDIOF_CARDRESET;
watchdog_set_drvdata(&wdt->wdt_dev, wdt);
watchdog_init_timeout(&wdt->wdt_dev, timeout, dev);
watchdog_set_nowayout(&wdt->wdt_dev, nowayout);
......
......@@ -81,7 +81,6 @@ static int twl4030_wdt_probe(struct platform_device *pdev)
return devm_watchdog_register_device(dev, wdt);
}
#ifdef CONFIG_PM
static int twl4030_wdt_suspend(struct platform_device *pdev, pm_message_t state)
{
struct watchdog_device *wdt = platform_get_drvdata(pdev);
......@@ -99,10 +98,6 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
return 0;
}
#else
#define twl4030_wdt_suspend NULL
#define twl4030_wdt_resume NULL
#endif
static const struct of_device_id twl_wdt_of_match[] = {
{ .compatible = "ti,twl4030-wdt", },
......@@ -112,8 +107,8 @@ MODULE_DEVICE_TABLE(of, twl_wdt_of_match);
static struct platform_driver twl4030_wdt_driver = {
.probe = twl4030_wdt_probe,
.suspend = twl4030_wdt_suspend,
.resume = twl4030_wdt_resume,
.suspend = pm_ptr(twl4030_wdt_suspend),
.resume = pm_ptr(twl4030_wdt_resume),
.driver = {
.name = "twl4030_wdt",
.of_match_table = twl_wdt_of_match,
......
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)*/
/*
* Copyright (c) 2022 MediaTek Inc.
* Author: Runyang Chen <runyang.chen@mediatek.com>
*/
#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8188
#define _DT_BINDINGS_RESET_CONTROLLER_MT8188
#define MT8188_TOPRGU_CONN_MCU_SW_RST 0
#define MT8188_TOPRGU_INFRA_GRST_SW_RST 1
#define MT8188_TOPRGU_IPU0_SW_RST 2
#define MT8188_TOPRGU_IPU1_SW_RST 3
#define MT8188_TOPRGU_IPU2_SW_RST 4
#define MT8188_TOPRGU_AUD_ASRC_SW_RST 5
#define MT8188_TOPRGU_INFRA_SW_RST 6
#define MT8188_TOPRGU_MMSYS_SW_RST 7
#define MT8188_TOPRGU_MFG_SW_RST 8
#define MT8188_TOPRGU_VENC_SW_RST 9
#define MT8188_TOPRGU_VDEC_SW_RST 10
#define MT8188_TOPRGU_CAM_VCORE_SW_RST 11
#define MT8188_TOPRGU_SCP_SW_RST 12
#define MT8188_TOPRGU_APMIXEDSYS_SW_RST 13
#define MT8188_TOPRGU_AUDIO_SW_RST 14
#define MT8188_TOPRGU_CAMSYS_SW_RST 15
#define MT8188_TOPRGU_MJC_SW_RST 16
#define MT8188_TOPRGU_PERI_SW_RST 17
#define MT8188_TOPRGU_PERI_AO_SW_RST 18
#define MT8188_TOPRGU_PCIE_SW_RST 19
#define MT8188_TOPRGU_ADSPSYS_SW_RST 21
#define MT8188_TOPRGU_DPTX_SW_RST 22
#define MT8188_TOPRGU_SPMI_MST_SW_RST 23
#define MT8188_TOPRGU_SW_RST_NUM 24
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8188 */
......@@ -227,6 +227,15 @@
#define RN5T618_WATCHDOG_WDOGTIM_S 0
#define RN5T618_PWRIRQ_IR_WDOG BIT(6)
#define RN5T618_POFFHIS_PWRON BIT(0)
#define RN5T618_POFFHIS_TSHUT BIT(1)
#define RN5T618_POFFHIS_VINDET BIT(2)
#define RN5T618_POFFHIS_IODET BIT(3)
#define RN5T618_POFFHIS_CPU BIT(4)
#define RN5T618_POFFHIS_WDG BIT(5)
#define RN5T618_POFFHIS_DCLIM BIT(6)
#define RN5T618_POFFHIS_N_OE BIT(7)
enum {
RN5T618_DCDC1,
RN5T618_DCDC2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment