mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
linux-watchdog 6.2-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAmOcmvEACgkQ+iyteGJfRso1OwCfWAZIdbdWdeEVq33zAT4/TZKE foYAn0ebKrOX26HEAmGgZy4Ze2pdFxVo =toMy -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
b611996ef2
|
@ -0,0 +1,80 @@
|
|||
# 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>;
|
||||
};
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
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
|
||||
|
|
205
drivers/watchdog/advantech_ec_wdt.c
Normal file
205
drivers/watchdog/advantech_ec_wdt.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
// 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,
|
||||
|
|
36
include/dt-bindings/reset/mt8188-resets.h
Normal file
36
include/dt-bindings/reset/mt8188-resets.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* 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,
|
||||
|
|
Loading…
Reference in a new issue