* [PATCH v2 0/3] watchdog: npcm: Add reset status detection support
@ 2026-06-22 8:30 Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 1/3] dt-bindings: watchdog: npcm: add GCR syscon property Tomer Maimon
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Tomer Maimon @ 2026-06-22 8:30 UTC (permalink / raw)
To: andrew, wim, linux, robh, krzk+dt, conor+dt
Cc: openbmc, linux-watchdog, linux-doc, devicetree, linux-kernel,
avifishman70, tmaimon77, tali.perry1, venture, yuenn,
benjaminfair, corbet, skhan, joel
This series documents and implements reset indication reporting for the
NPCM watchdog driver on NPCM7xx and NPCM8xx systems, and documents the
optional GCR syscon property used by that support.
Patch 1 updates the watchdog binding to allow the optional
``nuvoton,sysgcr`` property used for reset-cause reporting.
Patch 2 adds watchdog documentation that describes the bootstatus
mapping.
Patch 3 reads the SoC reset indication bits and maps them into the
existing watchdog bootstatus flags for NPCM750 and NPCM845, while
leaving WPCM450 unchanged.
Addressed comments from:
- Krzysztof Kozlowski: https://patchwork.ozlabs.org/project/openbmc/patch/20260210133843.1078463-2-tmaimon77@gmail.com/
- Guenter Roeck: https://patchwork.ozlabs.org/project/openbmc/patch/20260210133843.1078463-3-tmaimon77@gmail.com/
Changes since version 1:
- Modify reset detection handle in the watchodg.
- reword patch 1 to use the GCR syscon-property wording from the
applied NPCM reset binding update and drop the optional property from
the binding example.
- reword the patch subjects and commit message bodies to match current
kernel dt-bindings, docs, and watchdog style.
Tomer Maimon (3):
dt-bindings: watchdog: npcm: add GCR syscon property
docs: watchdog: npcm: Add reset status description
watchdog: npcm: add bootstatus support
.../watchdog/nuvoton,npcm750-wdt.yaml | 6 +
Documentation/watchdog/index.rst | 1 +
Documentation/watchdog/npcm_wdt.rst | 70 +++++++
drivers/watchdog/npcm_wdt.c | 197 +++++++++++++++++-
4 files changed, 272 insertions(+), 2 deletions(-)
create mode 100644 Documentation/watchdog/npcm_wdt.rst
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] dt-bindings: watchdog: npcm: add GCR syscon property
2026-06-22 8:30 [PATCH v2 0/3] watchdog: npcm: Add reset status detection support Tomer Maimon
@ 2026-06-22 8:30 ` Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 2/3] docs: watchdog: npcm: Add reset status description Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 3/3] watchdog: npcm: add bootstatus support Tomer Maimon
2 siblings, 0 replies; 4+ messages in thread
From: Tomer Maimon @ 2026-06-22 8:30 UTC (permalink / raw)
To: andrew, wim, linux, robh, krzk+dt, conor+dt
Cc: openbmc, linux-watchdog, linux-doc, devicetree, linux-kernel,
avifishman70, tmaimon77, tali.perry1, venture, yuenn,
benjaminfair, corbet, skhan, joel
Describe syscon property that handles general control registers (GCR) in
Nuvoton BMC NPCM watchdog driver.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
.../devicetree/bindings/watchdog/nuvoton,npcm750-wdt.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/watchdog/nuvoton,npcm750-wdt.yaml b/Documentation/devicetree/bindings/watchdog/nuvoton,npcm750-wdt.yaml
index 7aa30f5b5c49..4f00f099b2d2 100644
--- a/Documentation/devicetree/bindings/watchdog/nuvoton,npcm750-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/nuvoton,npcm750-wdt.yaml
@@ -40,6 +40,12 @@ properties:
clock-frequency:
description: Frequency in Hz of the clock that drives the NPCM timer.
+ nuvoton,sysgcr:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ a phandle to access GCR registers on NPCM750 and NPCM845 watchdog
+ instances.
+
required:
- compatible
- reg
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] docs: watchdog: npcm: Add reset status description
2026-06-22 8:30 [PATCH v2 0/3] watchdog: npcm: Add reset status detection support Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 1/3] dt-bindings: watchdog: npcm: add GCR syscon property Tomer Maimon
@ 2026-06-22 8:30 ` Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 3/3] watchdog: npcm: add bootstatus support Tomer Maimon
2 siblings, 0 replies; 4+ messages in thread
From: Tomer Maimon @ 2026-06-22 8:30 UTC (permalink / raw)
To: andrew, wim, linux, robh, krzk+dt, conor+dt
Cc: openbmc, linux-watchdog, linux-doc, devicetree, linux-kernel,
avifishman70, tmaimon77, tali.perry1, venture, yuenn,
benjaminfair, corbet, skhan, joel
Add documentation describing how the NPCM watchdog driver reports reset
causes through bootstatus on NPCM750 and NPCM845 systems.
Document the reset flag mapping, the watchdog instance mapping for
WDIOF_CARDRESET, and the NPCM750/NPCM845 latch handling. Also mention
sysfs bootstatus reporting when watchdog sysfs support is enabled.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
Documentation/watchdog/index.rst | 1 +
Documentation/watchdog/npcm_wdt.rst | 70 +++++++++++++++++++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 Documentation/watchdog/npcm_wdt.rst
diff --git a/Documentation/watchdog/index.rst b/Documentation/watchdog/index.rst
index 1cea24681e6b..ef29e861e837 100644
--- a/Documentation/watchdog/index.rst
+++ b/Documentation/watchdog/index.rst
@@ -9,6 +9,7 @@ Watchdog Support
hpwdt
mlx-wdt
+ npcm_wdt
pcwd-watchdog
watchdog-api
watchdog-kernel-api
diff --git a/Documentation/watchdog/npcm_wdt.rst b/Documentation/watchdog/npcm_wdt.rst
new file mode 100644
index 000000000000..48f0c7920c11
--- /dev/null
+++ b/Documentation/watchdog/npcm_wdt.rst
@@ -0,0 +1,70 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+NPCM Watchdog
+=============
+
+The NPCM watchdog driver can report reset-cause information on
+``nuvoton,npcm750-wdt`` and ``nuvoton,npcm845-wdt`` systems.
+
+Userspace can read the latched reset cause through
+``WDIOC_GETBOOTSTATUS``. When ``CONFIG_WATCHDOG_SYSFS`` is enabled, the
+same value is also visible through ``/sys/class/watchdog/watchdogN/bootstatus``.
+
+The mapping is fixed in the driver. It exposes the SoC reset indications
+through the generic watchdog bootstatus flags and is not configurable from
+Device Tree.
+
+.. list-table:: Reset-cause mapping
+ :header-rows: 1
+
+ * - Platform
+ - Reset indication
+ - Bootstatus flag
+ - Reported meaning
+ * - NPCM750 and NPCM845
+ - ``PORST``
+ - ``WDIOF_OVERHEAT``
+ - power-on reset
+ * - NPCM750 and NPCM845
+ - ``CORST``
+ - ``WDIOF_FANFAULT``
+ - core reset
+ * - NPCM750 and NPCM845
+ - ``SWR1RST``
+ - ``WDIOF_EXTERN1``
+ - software reset source 1
+ * - NPCM750 and NPCM845
+ - ``SWR2RST``
+ - ``WDIOF_EXTERN2``
+ - software reset source 2
+ * - NPCM750 and NPCM845
+ - ``SWR3RST``
+ - ``WDIOF_POWERUNDER``
+ - software reset source 3
+ * - NPCM750
+ - ``SWR4RST``
+ - ``WDIOF_POWEROVER``
+ - software reset source 4
+ * - NPCM845
+ - ``TIP reset`` (``INTCR2[25]``)
+ - ``WDIOF_POWEROVER``
+ - TIP reset
+
+``WDIOF_CARDRESET`` is reported only for the watchdog instance whose own
+reset-status bit is latched. On systems with three watchdog instances, this
+maps ``WD0RST``, ``WD1RST``, and ``WD2RST`` to ``watchdog0``, ``watchdog1``,
+and ``watchdog2`` respectively.
+
+The driver may report ``WDIOF_CARDRESET`` together with one or more of the
+reset-cause flags listed above.
+
+On NPCM750, the driver samples ``RESSR`` and clears the latched reset bits
+after reading them.
+
+On NPCM845, the driver samples ``INTCR2``. When reset bits are still latched,
+it clears them and stores the sampled value in ``SCRPAD10`` so later watchdog
+probes can report the same boot-time state.
+
+The WPCM450 watchdog continues to operate without this reset-indication
+mapping.
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] watchdog: npcm: add bootstatus support
2026-06-22 8:30 [PATCH v2 0/3] watchdog: npcm: Add reset status detection support Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 1/3] dt-bindings: watchdog: npcm: add GCR syscon property Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 2/3] docs: watchdog: npcm: Add reset status description Tomer Maimon
@ 2026-06-22 8:30 ` Tomer Maimon
2 siblings, 0 replies; 4+ messages in thread
From: Tomer Maimon @ 2026-06-22 8:30 UTC (permalink / raw)
To: andrew, wim, linux, robh, krzk+dt, conor+dt
Cc: openbmc, linux-watchdog, linux-doc, devicetree, linux-kernel,
avifishman70, tmaimon77, tali.perry1, venture, yuenn,
benjaminfair, corbet, skhan, joel
The NPCM750 uses RESSR and the NPCM845 uses INTCR2 to latch reset
indications. Read those bits during probe and map them into watchdog
bootstatus flags.
For NPCM845, cache the sampled INTCR2 state in SCRPAD10 after the reset
status bits are cleared so later probes can report the same boot-time
state. Also report WDIOF_CARDRESET for the watchdog instance whose reset
bit is latched, while leaving WPCM450 behavior unchanged.
Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/watchdog/npcm_wdt.c | 197 +++++++++++++++++++++++++++++++++++-
1 file changed, 195 insertions(+), 2 deletions(-)
diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
index e62ea054bc61..98660419ec3f 100644
--- a/drivers/watchdog/npcm_wdt.c
+++ b/drivers/watchdog/npcm_wdt.c
@@ -7,14 +7,51 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/watchdog.h>
#define NPCM_WTCR 0x1C
+/* NPCM GCR module */
+#define NPCM_RESSR_OFFSET 0x6C
+#define NPCM_INTCR2_OFFSET 0x60
+#define NPCM8XX_SCRPAD10_OFFSET 0xE28
+
+#define NPCM_PORST BIT(31)
+#define NPCM_CORST BIT(30)
+#define NPCM_WD0RST BIT(29)
+#define NPCM_SWR1RST BIT(28)
+#define NPCM_SWR2RST BIT(27)
+#define NPCM_SWR3RST BIT(26)
+#define NPCM_SWR4RST BIT(25)
+#define NPCM_WD1RST BIT(24)
+#define NPCM_WD2RST BIT(23)
+#define NPCM8XX_RST (GENMASK(31, 23) | GENMASK(15, 12))
+#define NPCM8XX_TIP_RESET BIT(25) /* Replaces SWRST4 on NPCM8xx */
+
+/* Per-instance mapping of MMIO base address to its RESSR/INTCR2 reset bit. */
+struct npcm_wdt_rst_map {
+ phys_addr_t base;
+ u32 rst_bit;
+};
+
+struct npcm_wdt_status_map {
+ u32 rst_bit;
+ u32 wdiof_flag;
+};
+
+struct npcm_wdt_data {
+ const struct npcm_wdt_rst_map *rst_map;
+ unsigned int rst_map_size;
+ const struct npcm_wdt_status_map *status_map;
+ unsigned int status_map_size;
+};
+
#define NPCM_WTCLK (BIT(10) | BIT(11)) /* Clock divider */
#define NPCM_WTE BIT(7) /* Enable */
#define NPCM_WTIE BIT(6) /* Enable irq */
@@ -47,6 +84,50 @@ struct npcm_wdt {
struct clk *clk;
};
+static const struct npcm_wdt_rst_map npcm750_rst_map[] = {
+ { 0xf000801c, NPCM_WD0RST },
+ { 0xf000901c, NPCM_WD1RST },
+ { 0xf000a01c, NPCM_WD2RST },
+};
+
+static const struct npcm_wdt_status_map npcm750_status_map[] = {
+ { NPCM_PORST, WDIOF_OVERHEAT },
+ { NPCM_CORST, WDIOF_FANFAULT },
+ { NPCM_SWR1RST, WDIOF_EXTERN1 },
+ { NPCM_SWR2RST, WDIOF_EXTERN2 },
+ { NPCM_SWR3RST, WDIOF_POWERUNDER },
+ { NPCM_SWR4RST, WDIOF_POWEROVER },
+};
+
+static const struct npcm_wdt_data npcm750_data = {
+ .rst_map = npcm750_rst_map,
+ .rst_map_size = ARRAY_SIZE(npcm750_rst_map),
+ .status_map = npcm750_status_map,
+ .status_map_size = ARRAY_SIZE(npcm750_status_map),
+};
+
+static const struct npcm_wdt_rst_map npcm845_rst_map[] = {
+ { 0xf000801c, NPCM_WD0RST },
+ { 0xf000901c, NPCM_WD1RST },
+ { 0xf000a01c, NPCM_WD2RST },
+};
+
+static const struct npcm_wdt_status_map npcm845_status_map[] = {
+ { NPCM_PORST, WDIOF_OVERHEAT },
+ { NPCM_CORST, WDIOF_FANFAULT },
+ { NPCM_SWR1RST, WDIOF_EXTERN1 },
+ { NPCM_SWR2RST, WDIOF_EXTERN2 },
+ { NPCM_SWR3RST, WDIOF_POWERUNDER },
+ { NPCM8XX_TIP_RESET, WDIOF_POWEROVER },
+};
+
+static const struct npcm_wdt_data npcm845_data = {
+ .rst_map = npcm845_rst_map,
+ .rst_map_size = ARRAY_SIZE(npcm845_rst_map),
+ .status_map = npcm845_status_map,
+ .status_map_size = ARRAY_SIZE(npcm845_status_map),
+};
+
static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
{
return container_of(wdd, struct npcm_wdt, wdd);
@@ -169,6 +250,92 @@ static bool npcm_is_running(struct watchdog_device *wdd)
return readl(wdt->reg) & NPCM_WTE;
}
+static void npcm_get_reset_status(struct npcm_wdt *wdt, struct device *dev,
+ const struct npcm_wdt_data *data,
+ resource_size_t start)
+{
+ struct regmap *gcr_regmap;
+ u32 rstval = 0;
+ unsigned int i;
+ int ret;
+
+ if (!data)
+ return;
+
+ gcr_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "nuvoton,sysgcr");
+ if (IS_ERR(gcr_regmap)) {
+ dev_warn(dev,
+ "Failed to find nuvoton,sysgcr, WD reset status not supported\n");
+ return;
+ }
+
+ if (of_device_is_compatible(dev->of_node, "nuvoton,npcm845-wdt")) {
+ ret = regmap_read(gcr_regmap, NPCM_INTCR2_OFFSET, &rstval);
+ if (ret) {
+ dev_warn(dev, "Failed to read INTCR2 reset status: %d\n",
+ ret);
+ return;
+ }
+
+ if (rstval & NPCM8XX_RST) {
+ ret = regmap_write(gcr_regmap, NPCM_INTCR2_OFFSET,
+ rstval & ~NPCM8XX_RST);
+ if (ret) {
+ dev_warn(dev,
+ "Failed to clear INTCR2 reset status: %d\n",
+ ret);
+ return;
+ }
+
+ ret = regmap_write(gcr_regmap, NPCM8XX_SCRPAD10_OFFSET,
+ rstval);
+ if (ret) {
+ dev_warn(dev,
+ "Failed to cache reset status in SCRPAD10: %d\n",
+ ret);
+ return;
+ }
+ } else {
+ ret = regmap_read(gcr_regmap, NPCM8XX_SCRPAD10_OFFSET,
+ &rstval);
+ if (ret) {
+ dev_warn(dev,
+ "Failed to read cached reset status from SCRPAD10: %d\n",
+ ret);
+ return;
+ }
+ }
+ } else if (of_device_is_compatible(dev->of_node, "nuvoton,npcm750-wdt")) {
+ ret = regmap_read(gcr_regmap, NPCM_RESSR_OFFSET, &rstval);
+ if (ret) {
+ dev_warn(dev, "Failed to read RESSR reset status: %d\n",
+ ret);
+ return;
+ }
+
+ ret = regmap_write(gcr_regmap, NPCM_RESSR_OFFSET, rstval);
+ if (ret) {
+ dev_warn(dev, "Failed to clear RESSR reset status: %d\n",
+ ret);
+ return;
+ }
+ }
+
+ for (i = 0; i < data->status_map_size; i++) {
+ if (rstval & data->status_map[i].rst_bit)
+ wdt->wdd.bootstatus |= data->status_map[i].wdiof_flag;
+ }
+
+ for (i = 0; i < data->rst_map_size; i++) {
+ if (data->rst_map[i].base == start &&
+ rstval & data->rst_map[i].rst_bit) {
+ wdt->wdd.bootstatus |= WDIOF_CARDRESET;
+ break;
+ }
+ }
+}
+
static const struct watchdog_info npcm_wdt_info = {
.identity = KBUILD_MODNAME,
.options = WDIOF_SETTIMEOUT
@@ -176,6 +343,20 @@ static const struct watchdog_info npcm_wdt_info = {
| WDIOF_MAGICCLOSE,
};
+static const struct watchdog_info npcm_wdt_rst_info = {
+ .identity = KBUILD_MODNAME,
+ .options = WDIOF_SETTIMEOUT
+ | WDIOF_KEEPALIVEPING
+ | WDIOF_MAGICCLOSE
+ | WDIOF_CARDRESET
+ | WDIOF_OVERHEAT
+ | WDIOF_FANFAULT
+ | WDIOF_EXTERN1
+ | WDIOF_EXTERN2
+ | WDIOF_POWERUNDER
+ | WDIOF_POWEROVER,
+};
+
static const struct watchdog_ops npcm_wdt_ops = {
.owner = THIS_MODULE,
.start = npcm_wdt_start,
@@ -188,7 +369,10 @@ static const struct watchdog_ops npcm_wdt_ops = {
static int npcm_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const struct npcm_wdt_data *data = device_get_match_data(dev);
+ struct resource *res;
struct npcm_wdt *wdt;
+ resource_size_t start;
int irq;
int ret;
@@ -196,10 +380,16 @@ static int npcm_wdt_probe(struct platform_device *pdev)
if (!wdt)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
wdt->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(wdt->reg))
return PTR_ERR(wdt->reg);
+ start = res->start;
+
wdt->clk = devm_clk_get_optional(&pdev->dev, NULL);
if (IS_ERR(wdt->clk))
return PTR_ERR(wdt->clk);
@@ -208,7 +398,7 @@ static int npcm_wdt_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- wdt->wdd.info = &npcm_wdt_info;
+ wdt->wdd.info = data ? &npcm_wdt_rst_info : &npcm_wdt_info;
wdt->wdd.ops = &npcm_wdt_ops;
wdt->wdd.min_timeout = 1;
wdt->wdd.max_timeout = 2750;
@@ -220,6 +410,8 @@ static int npcm_wdt_probe(struct platform_device *pdev)
/* Ensure timeout is able to be represented by the hardware */
npcm_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
+ npcm_get_reset_status(wdt, dev, data, start);
+
if (npcm_is_running(&wdt->wdd)) {
/* Restart with the default or device-tree specified timeout */
npcm_wdt_start(&wdt->wdd);
@@ -243,7 +435,8 @@ static int npcm_wdt_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id npcm_wdt_match[] = {
{.compatible = "nuvoton,wpcm450-wdt"},
- {.compatible = "nuvoton,npcm750-wdt"},
+ {.compatible = "nuvoton,npcm750-wdt", .data = &npcm750_data},
+ {.compatible = "nuvoton,npcm845-wdt", .data = &npcm845_data},
{},
};
MODULE_DEVICE_TABLE(of, npcm_wdt_match);
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-22 8:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-22 8:30 [PATCH v2 0/3] watchdog: npcm: Add reset status detection support Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 1/3] dt-bindings: watchdog: npcm: add GCR syscon property Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 2/3] docs: watchdog: npcm: Add reset status description Tomer Maimon
2026-06-22 8:30 ` [PATCH v2 3/3] watchdog: npcm: add bootstatus support Tomer Maimon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox