Commit 032e22fe authored by Linus Torvalds's avatar Linus Torvalds

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

Pull watchdog updates from Wim Van Sebroeck:

 - Remove usage of the deprecated ida_simple_xx() API

 - Add kernel-doc for wdt_set_timeout()

 - Add support for R-Car V4M, StarFive's JH8100 and sam9x7-wdt

 - Fixes and small improvements

* tag 'linux-watchdog-6.9-rc1' of git://www.linux-watchdog.org/linux-watchdog:
  watchdog: intel-mid_wdt: Get platform data via dev_get_platdata()
  watchdog: intel-mid_wdt: Don't use "proxy" headers
  watchdog: intel-mid_wdt: Remove unused intel-mid.h
  dt-bindings: watchdog: sama5d4-wdt: add compatible for sam9x7-wdt
  dt-bindings: watchdog: sprd,sp9860-wdt: convert to YAML
  dt-bindings: watchdog: starfive,jh7100-wdt: Add compatible for JH8100
  watchdog: stm32_iwdg: initialize default timeout
  dt-bindings: watchdog: arm,sp805: document the reset signal
  watchdog: sp805_wdt: deassert the reset if available
  watchdog/hpwdt: Support Suspend and Resume
  dt-bindings: watchdog: renesas-wdt: Add support for R-Car V4M
  watchdog: starfive: check watchdog status before enabling in system resume
  watchdog: starfive: Check pm_runtime_enabled() before decrementing usage counter
  watchdog: qcom: fine tune the max timeout value calculation
  watchdog: Add kernel-doc for wdt_set_timeout()
  watchdog: core: Remove usage of the deprecated ida_simple_xx() API
parents 75e41d42 6fe5aabf
...@@ -50,6 +50,10 @@ properties: ...@@ -50,6 +50,10 @@ properties:
- const: wdog_clk - const: wdog_clk
- const: apb_pclk - const: apb_pclk
resets:
maxItems: 1
description: WDOGRESn input reset signal for sp805 module.
required: required:
- compatible - compatible
- reg - reg
...@@ -67,4 +71,5 @@ examples: ...@@ -67,4 +71,5 @@ examples:
interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&wdt_clk>, <&apb_pclk>; clocks = <&wdt_clk>, <&apb_pclk>;
clock-names = "wdog_clk", "apb_pclk"; clock-names = "wdog_clk", "apb_pclk";
resets = <&wdt_rst>;
}; };
...@@ -14,10 +14,14 @@ allOf: ...@@ -14,10 +14,14 @@ allOf:
properties: properties:
compatible: compatible:
enum: oneOf:
- atmel,sama5d4-wdt - enum:
- microchip,sam9x60-wdt - atmel,sama5d4-wdt
- microchip,sama7g5-wdt - microchip,sam9x60-wdt
- microchip,sama7g5-wdt
- items:
- const: microchip,sam9x7-wdt
- const: microchip,sam9x60-wdt
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -71,6 +71,7 @@ properties: ...@@ -71,6 +71,7 @@ properties:
- renesas,r8a779a0-wdt # R-Car V3U - renesas,r8a779a0-wdt # R-Car V3U
- renesas,r8a779f0-wdt # R-Car S4-8 - renesas,r8a779f0-wdt # R-Car S4-8
- renesas,r8a779g0-wdt # R-Car V4H - renesas,r8a779g0-wdt # R-Car V4H
- renesas,r8a779h0-wdt # R-Car V4M
- const: renesas,rcar-gen4-wdt # R-Car Gen4 - const: renesas,rcar-gen4-wdt # R-Car Gen4
reg: reg:
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/watchdog/sprd,sp9860-wdt.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Spreadtrum SP9860 watchdog timer
maintainers:
- Orson Zhai <orsonzhai@gmail.com>
- Baolin Wang <baolin.wang7@gmail.com>
- Chunyan Zhang <zhang.lyra@gmail.com>
allOf:
- $ref: watchdog.yaml#
properties:
compatible:
const: sprd,sp9860-wdt
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: enable
- const: rtc_enable
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- timeout-sec
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/sprd,sc9860-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
watchdog@40310000 {
compatible = "sprd,sp9860-wdt";
reg = <0 0x40310000 0 0x1000>;
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&aon_gate CLK_APCPU_WDG_EB>, <&aon_gate CLK_AP_WDG_RTC_EB>;
clock-names = "enable", "rtc_enable";
timeout-sec = <12>;
};
};
...
Spreadtrum SoCs Watchdog timer
Required properties:
- compatible : Should be "sprd,sp9860-wdt".
- reg : Specifies base physical address and size of the registers.
- interrupts : Exactly one interrupt specifier.
- timeout-sec : Contain the default watchdog timeout in seconds.
- clock-names : Contain the input clock names.
- clocks : Phandles to input clocks.
Example:
watchdog: watchdog@40310000 {
compatible = "sprd,sp9860-wdt";
reg = <0 0x40310000 0 0x1000>;
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
timeout-sec = <12>;
clock-names = "enable", "rtc_enable";
clocks = <&clk_aon_apb_gates1 8>, <&clk_aon_apb_rtc_gates 9>;
};
...@@ -19,14 +19,16 @@ description: ...@@ -19,14 +19,16 @@ description:
isn't cleared, the watchdog will reset the system unless the watchdog isn't cleared, the watchdog will reset the system unless the watchdog
reset is disabled. reset is disabled.
allOf:
- $ref: watchdog.yaml#
properties: properties:
compatible: compatible:
enum: oneOf:
- starfive,jh7100-wdt - enum:
- starfive,jh7110-wdt - starfive,jh7100-wdt
- starfive,jh7110-wdt
- items:
- enum:
- starfive,jh8100-wdt
- const: starfive,jh7110-wdt
reg: reg:
maxItems: 1 maxItems: 1
...@@ -45,9 +47,8 @@ properties: ...@@ -45,9 +47,8 @@ properties:
- const: core - const: core
resets: resets:
items: minItems: 1
- description: APB reset maxItems: 2
- description: Core reset
required: required:
- compatible - compatible
...@@ -56,6 +57,27 @@ required: ...@@ -56,6 +57,27 @@ required:
- clock-names - clock-names
- resets - resets
allOf:
- $ref: watchdog.yaml#
- if:
properties:
compatible:
contains:
enum:
- starfive,jh8100-wdt
then:
properties:
resets:
items:
- description: Core reset
else:
properties:
resets:
items:
- description: APB reset
- description: Core reset
unevaluatedProperties: false unevaluatedProperties: false
examples: examples:
......
...@@ -378,11 +378,36 @@ static void hpwdt_exit(struct pci_dev *dev) ...@@ -378,11 +378,36 @@ static void hpwdt_exit(struct pci_dev *dev)
pci_disable_device(dev); pci_disable_device(dev);
} }
static int hpwdt_suspend(struct device *dev)
{
if (watchdog_active(&hpwdt_dev))
hpwdt_stop();
return 0;
}
static int hpwdt_resume(struct device *dev)
{
if (watchdog_active(&hpwdt_dev))
hpwdt_start(&hpwdt_dev);
return 0;
}
static const struct dev_pm_ops hpwdt_pm_ops = {
LATE_SYSTEM_SLEEP_PM_OPS(hpwdt_suspend, hpwdt_resume)
};
static struct pci_driver hpwdt_driver = { static struct pci_driver hpwdt_driver = {
.name = "hpwdt", .name = "hpwdt",
.id_table = hpwdt_devices, .id_table = hpwdt_devices,
.probe = hpwdt_init_one, .probe = hpwdt_init_one,
.remove = hpwdt_exit, .remove = hpwdt_exit,
.driver = {
.name = "hpwdt",
.pm = &hpwdt_pm_ops,
}
}; };
MODULE_AUTHOR("Tom Mingarelli"); MODULE_AUTHOR("Tom Mingarelli");
......
...@@ -9,15 +9,20 @@ ...@@ -9,15 +9,20 @@
* Contact: David Cohen <david.a.cohen@linux.intel.com> * Contact: David Cohen <david.a.cohen@linux.intel.com>
*/ */
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/math.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/nmi.h> #include <linux/panic.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/platform_data/intel-mid_wdt.h> #include <linux/platform_data/intel-mid_wdt.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
#include <asm/intel-mid.h>
#define IPC_WATCHDOG 0xf8 #define IPC_WATCHDOG 0xf8
...@@ -122,7 +127,7 @@ static int mid_wdt_probe(struct platform_device *pdev) ...@@ -122,7 +127,7 @@ static int mid_wdt_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct watchdog_device *wdt_dev; struct watchdog_device *wdt_dev;
struct intel_mid_wdt_pdata *pdata = dev->platform_data; struct intel_mid_wdt_pdata *pdata = dev_get_platdata(dev);
struct mid_wdt *mid; struct mid_wdt *mid;
int ret; int ret;
......
...@@ -213,12 +213,16 @@ static int wdt_stop(struct watchdog_device *wdd) ...@@ -213,12 +213,16 @@ static int wdt_stop(struct watchdog_device *wdd)
/** /**
* wdt_set_timeout - set a new timeout value with watchdog ioctl * wdt_set_timeout - set a new timeout value with watchdog ioctl
* @wdd: pointer to the watchdog_device structure
* @t: timeout value in seconds * @t: timeout value in seconds
* *
* The hardware device has a 8 or 16 bit watchdog timer (depends on * The hardware device has a 8 or 16 bit watchdog timer (depends on
* chip version) that can be configured to count seconds or minutes. * chip version) that can be configured to count seconds or minutes.
* *
* Used within WDIOC_SETTIMEOUT watchdog device ioctl. * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
*
* Return: 0 if the timeout was set successfully, or a negative error code on
* failure.
*/ */
static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
......
...@@ -41,6 +41,7 @@ static const u32 reg_offset_data_kpss[] = { ...@@ -41,6 +41,7 @@ static const u32 reg_offset_data_kpss[] = {
struct qcom_wdt_match_data { struct qcom_wdt_match_data {
const u32 *offset; const u32 *offset;
bool pretimeout; bool pretimeout;
u32 max_tick_count;
}; };
struct qcom_wdt { struct qcom_wdt {
...@@ -177,11 +178,13 @@ static const struct watchdog_info qcom_wdt_pt_info = { ...@@ -177,11 +178,13 @@ static const struct watchdog_info qcom_wdt_pt_info = {
static const struct qcom_wdt_match_data match_data_apcs_tmr = { static const struct qcom_wdt_match_data match_data_apcs_tmr = {
.offset = reg_offset_data_apcs_tmr, .offset = reg_offset_data_apcs_tmr,
.pretimeout = false, .pretimeout = false,
.max_tick_count = 0x10000000U,
}; };
static const struct qcom_wdt_match_data match_data_kpss = { static const struct qcom_wdt_match_data match_data_kpss = {
.offset = reg_offset_data_kpss, .offset = reg_offset_data_kpss,
.pretimeout = true, .pretimeout = true,
.max_tick_count = 0xFFFFFU,
}; };
static int qcom_wdt_probe(struct platform_device *pdev) static int qcom_wdt_probe(struct platform_device *pdev)
...@@ -236,7 +239,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) ...@@ -236,7 +239,7 @@ static int qcom_wdt_probe(struct platform_device *pdev)
*/ */
wdt->rate = clk_get_rate(clk); wdt->rate = clk_get_rate(clk);
if (wdt->rate == 0 || if (wdt->rate == 0 ||
wdt->rate > 0x10000000U) { wdt->rate > data->max_tick_count) {
dev_err(dev, "invalid clock rate\n"); dev_err(dev, "invalid clock rate\n");
return -EINVAL; return -EINVAL;
} }
...@@ -260,7 +263,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) ...@@ -260,7 +263,7 @@ static int qcom_wdt_probe(struct platform_device *pdev)
wdt->wdd.ops = &qcom_wdt_ops; wdt->wdd.ops = &qcom_wdt_ops;
wdt->wdd.min_timeout = 1; wdt->wdd.min_timeout = 1;
wdt->wdd.max_timeout = 0x10000000U / wdt->rate; wdt->wdd.max_timeout = data->max_tick_count / wdt->rate;
wdt->wdd.parent = dev; wdt->wdd.parent = dev;
wdt->layout = data->offset; wdt->layout = data->offset;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/reset.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -232,6 +233,7 @@ static int ...@@ -232,6 +233,7 @@ static int
sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
{ {
struct sp805_wdt *wdt; struct sp805_wdt *wdt;
struct reset_control *rst;
u64 rate = 0; u64 rate = 0;
int ret = 0; int ret = 0;
...@@ -264,6 +266,12 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -264,6 +266,12 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
return -ENODEV; return -ENODEV;
} }
rst = devm_reset_control_get_optional_exclusive(&adev->dev, NULL);
if (IS_ERR(rst))
return dev_err_probe(&adev->dev, PTR_ERR(rst), "Can not get reset\n");
reset_control_deassert(rst);
wdt->adev = adev; wdt->adev = adev;
wdt->wdd.info = &wdt_info; wdt->wdd.info = &wdt_info;
wdt->wdd.ops = &wdt_ops; wdt->wdd.ops = &wdt_ops;
......
...@@ -494,8 +494,13 @@ static int starfive_wdt_probe(struct platform_device *pdev) ...@@ -494,8 +494,13 @@ static int starfive_wdt_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_exit; goto err_exit;
if (!early_enable) if (!early_enable) {
pm_runtime_put_sync(&pdev->dev); if (pm_runtime_enabled(&pdev->dev)) {
ret = pm_runtime_put_sync(&pdev->dev);
if (ret)
goto err_exit;
}
}
return 0; return 0;
...@@ -554,7 +559,10 @@ static int starfive_wdt_resume(struct device *dev) ...@@ -554,7 +559,10 @@ static int starfive_wdt_resume(struct device *dev)
starfive_wdt_set_reload_count(wdt, wdt->reload); starfive_wdt_set_reload_count(wdt, wdt->reload);
starfive_wdt_lock(wdt); starfive_wdt_lock(wdt);
return starfive_wdt_start(wdt); if (watchdog_active(&wdt->wdd))
return starfive_wdt_start(wdt);
return 0;
} }
static int starfive_wdt_runtime_suspend(struct device *dev) static int starfive_wdt_runtime_suspend(struct device *dev)
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#define DEFAULT_TIMEOUT 10
/* IWDG registers */ /* IWDG registers */
#define IWDG_KR 0x00 /* Key register */ #define IWDG_KR 0x00 /* Key register */
#define IWDG_PR 0x04 /* Prescaler Register */ #define IWDG_PR 0x04 /* Prescaler Register */
...@@ -248,6 +250,7 @@ static int stm32_iwdg_probe(struct platform_device *pdev) ...@@ -248,6 +250,7 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
wdd->parent = dev; wdd->parent = dev;
wdd->info = &stm32_iwdg_info; wdd->info = &stm32_iwdg_info;
wdd->ops = &stm32_iwdg_ops; wdd->ops = &stm32_iwdg_ops;
wdd->timeout = DEFAULT_TIMEOUT;
wdd->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, wdt->rate); wdd->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, wdt->rate);
wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler * wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler *
1000) / wdt->rate; 1000) / wdt->rate;
......
...@@ -260,12 +260,12 @@ static int __watchdog_register_device(struct watchdog_device *wdd) ...@@ -260,12 +260,12 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
if (wdd->parent) { if (wdd->parent) {
ret = of_alias_get_id(wdd->parent->of_node, "watchdog"); ret = of_alias_get_id(wdd->parent->of_node, "watchdog");
if (ret >= 0) if (ret >= 0)
id = ida_simple_get(&watchdog_ida, ret, id = ida_alloc_range(&watchdog_ida, ret, ret,
ret + 1, GFP_KERNEL); GFP_KERNEL);
} }
if (id < 0) if (id < 0)
id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL); id = ida_alloc_max(&watchdog_ida, MAX_DOGS - 1, GFP_KERNEL);
if (id < 0) if (id < 0)
return id; return id;
...@@ -273,19 +273,20 @@ static int __watchdog_register_device(struct watchdog_device *wdd) ...@@ -273,19 +273,20 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
ret = watchdog_dev_register(wdd); ret = watchdog_dev_register(wdd);
if (ret) { if (ret) {
ida_simple_remove(&watchdog_ida, id); ida_free(&watchdog_ida, id);
if (!(id == 0 && ret == -EBUSY)) if (!(id == 0 && ret == -EBUSY))
return ret; return ret;
/* Retry in case a legacy watchdog module exists */ /* Retry in case a legacy watchdog module exists */
id = ida_simple_get(&watchdog_ida, 1, MAX_DOGS, GFP_KERNEL); id = ida_alloc_range(&watchdog_ida, 1, MAX_DOGS - 1,
GFP_KERNEL);
if (id < 0) if (id < 0)
return id; return id;
wdd->id = id; wdd->id = id;
ret = watchdog_dev_register(wdd); ret = watchdog_dev_register(wdd);
if (ret) { if (ret) {
ida_simple_remove(&watchdog_ida, id); ida_free(&watchdog_ida, id);
return ret; return ret;
} }
} }
...@@ -309,7 +310,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd) ...@@ -309,7 +310,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
wdd->id, ret); wdd->id, ret);
watchdog_dev_unregister(wdd); watchdog_dev_unregister(wdd);
ida_simple_remove(&watchdog_ida, id); ida_free(&watchdog_ida, id);
return ret; return ret;
} }
} }
...@@ -382,7 +383,7 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd) ...@@ -382,7 +383,7 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)
unregister_reboot_notifier(&wdd->reboot_nb); unregister_reboot_notifier(&wdd->reboot_nb);
watchdog_dev_unregister(wdd); watchdog_dev_unregister(wdd);
ida_simple_remove(&watchdog_ida, wdd->id); ida_free(&watchdog_ida, wdd->id);
} }
/** /**
......
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