From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 72189C43458 for ; Sun, 5 Jul 2026 14:02:02 +0000 (UTC) Received: from boromir.ozlabs.org (localhost [127.0.0.1]) by lists.ozlabs.org (Postfix) with ESMTP id 4gtTg338Qpz2ygh; Mon, 06 Jul 2026 00:01:19 +1000 (AEST) Authentication-Results: lists.ozlabs.org; arc=none smtp.remote-ip="2a00:1450:4864:20::331" ARC-Seal: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1783260079; cv=none; b=Bdma6rIravo+AM7Y8jC7IDLksKh4SBatP72fJPle9fU8dU0TjqU/9vwpQ5OqL/2+zXybEv0nP8O/KYbuovxNEnyOB8nAfaoB3Etmb2uw8gr+fBUN0aV2QdzyXeBBbY3yFhZy5Ovl2PvKvLxfrvgbJRahPQ9k/bib7zPfCAIGRWS/yaWOnepdsNJzv+SfWZ5qIIVYkcqzUDSCRRUjgPv4hlEAzYDXunQ0eAygMUrz+q1C7mrHBPVp+aevmFEqsYSdwTj2+xqVR49AEjlZxjrcd/8X864zQMmMjHwq9HUgySfARVKVEp5Y3fzsdDgxdvDw0Bhdcp2ssT7AfV+QqBKx4w== ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1783260079; c=relaxed/relaxed; bh=nuDU45OA6ggrf4VYV6YQ5pMRzsYDccU2hT9CMU+OAX0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=fkywwB33AWzTm8CsoUpZ05zlz2lPoiJQywvkSJsq8sOWg8BrPpT0KXY6Ch8X19Y+GO4MXOIYTld1MRgfKYihYKr/PuP6DIC4ck4+CS+CBM9Z+1it2MvUVSCIwoaDI4bl55e/sG8Vq7H43v1MNeGgaD0sI/u6MWk5e8Zfxy/uNpXQQGrJac/6bxLT44bT7cQoLCCJYWrPhoNk1g38OEULtOZ64l8qaHBaY50LtUN68SPxNnyGQQWFn3al1j/OYRwiokJJtjbOfpcxQBPQ/VWxvclRhZNib+4D9KyXNtY7svCUk+Blw861afooi+m9fiywXjCxJ6i6tu4irqkYUAzLXA== ARC-Authentication-Results: i=1; lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=WRK0yCEe; dkim-atps=neutral; spf=pass (client-ip=2a00:1450:4864:20::331; helo=mail-wm1-x331.google.com; envelope-from=tmaimon77@gmail.com; receiver=lists.ozlabs.org) smtp.mailfrom=gmail.com Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=WRK0yCEe; dkim-atps=neutral Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2a00:1450:4864:20::331; helo=mail-wm1-x331.google.com; envelope-from=tmaimon77@gmail.com; receiver=lists.ozlabs.org) Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4gtTg14wkbz2yf9 for ; Mon, 06 Jul 2026 00:01:17 +1000 (AEST) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-493c2c0b9a8so19024275e9.1 for ; Sun, 05 Jul 2026 07:01:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783260075; x=1783864875; darn=lists.ozlabs.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nuDU45OA6ggrf4VYV6YQ5pMRzsYDccU2hT9CMU+OAX0=; b=WRK0yCEe39ysTUZxXDjsLSAeB37/NfL/yceXXdTm2LByPIzTyDIWiunHGaYBz5fXy6 Na+SsfyqEy0JFJYWS+lOL8its+8qBntvS1yHNTLDBL/J45pON3u1ZQSqOUHmoFVFyvGJ 7sQE2VX4tU1lIk19FQDu3Pv2UM57OZFM0D7cUEYcgFZnjXhcIMBN4PBkPCJO+i7HJv94 EsXAcCDOrQY0g3DL+uVN/Y1tskpByspYvNOC1wEMKbysFmopyGEjSnNaqjKIRCcjlkMe yytIV/OeXUPp8WDzUUOlvpa6ChVArybSn3MrNyCFtRK7iSnnDwOsxvSihUuw5Bdjsb/U OLiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783260075; x=1783864875; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nuDU45OA6ggrf4VYV6YQ5pMRzsYDccU2hT9CMU+OAX0=; b=LPBYsREh1nsQTEFvf8iNmfZvDRfCuPK7Y/RoRwPUxL0aFBuAd0FC0ANbwUyZ/VCa3v twSPS5KXJ4xcADe/CajNwuea+nuxrUXfPZoQhHk2mktLGFeTaD1RVdrx0N421XI2aul2 9Tsvp1g5j5CzjTdF7Dcl0EdsVuBMKZW5uRaJgcsrjqjVyOp9GS91tQ2LNrttnReLa2ZF eFcp9+Y3D7ASh/y6FhNklof3DMQ5SG8Ey3+52urSs9HBu4dRUHeTgeipjYMGI3FHy4Dy CG4Ds6HvmHXIjqJ/ddqGKKxuvBoObrlWqq3ciob1UHLjR/3GYz3rZ2c27QP0w0K7L0EX DX4A== X-Gm-Message-State: AOJu0YxJcWfkWD7TzkrGM9ocii/heHSgVqknh7FTTAsBKWXdh4gDrGaF RzzQG/ehnNy4GVD9RsEcRxbxKAep8NmDIzKLYeY92xATfPgOPTp8113P X-Gm-Gg: AfdE7cn3XSQCsiAVcIqAfx9F5Ki31oSCy6zd05UwQ8xriGNjfUZ/sOXbZ4nUccZDy/A rhTKp/49W3qld1BHPNpmzIsbMfNlkvwAqW4gk1V388Wn+qtXyf2hKOIpp+vQOxkQKoMyZOwCAb9 gfnC4fyBSMPMDhUQVwov9RMZk5Qj/e8x1lqOaNdKpS2yF6ekMBV13/3DXpQXulRnuuhVvKA8a3d zp9FpdGsWyoosykF9izL/TZEVGgwtXJdimhnNou9SKrHZDWdjw9cp+36rhGpFyv3q051+5VJprz ldxqE8b0+5ciBqDqj+bvDPwC9XZSRk8Xng8fYAHR0TaboiEIl9j0k1HjjFMyL7RYHADwNjItn47 5V8pgyHwP0xkvrnJenwJZvTkDrhXaf1H5u3tj/424i7g3wacvmBE4x9SSGwqu0FbP8eBfLjFCC0 Q/1mSIsBHW6PZjtoKkA+MtE6TFbYCA0r5GRg== X-Received: by 2002:a05:600c:3515:b0:493:c42e:5be0 with SMTP id 5b1f17b1804b1-493d11894f7mr81253085e9.0.1783260074531; Sun, 05 Jul 2026 07:01:14 -0700 (PDT) Received: from taln60.nuvoton.co.il ([212.199.177.18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-493cce040b4sm275911115e9.10.2026.07.05.07.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Jul 2026 07:01:14 -0700 (PDT) From: Tomer Maimon To: andrew@codeconstruct.com.au, wim@linux-watchdog.org, linux@roeck-us.net, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org Cc: openbmc@lists.ozlabs.org, linux-watchdog@vger.kernel.org, linux-doc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, avifishman70@gmail.com, tmaimon77@gmail.com, tali.perry1@gmail.com, venture@google.com, yuenn@google.com, benjaminfair@google.com, corbet@lwn.net, skhan@linuxfoundation.org, joel@jms.id.au Subject: [PATCH v3 3/3] watchdog: npcm: add bootstatus support Date: Sun, 5 Jul 2026 17:01:00 +0300 Message-Id: <20260705140100.1543486-4-tmaimon77@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260705140100.1543486-1-tmaimon77@gmail.com> References: <20260705140100.1543486-1-tmaimon77@gmail.com> X-Mailing-List: openbmc@lists.ozlabs.org List-Id: List-Help: List-Owner: List-Post: List-Subscribe: , , List-Unsubscribe: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- drivers/watchdog/npcm_wdt.c | 217 +++++++++++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c index e62ea054bc61..cecfd6e574d8 100644 --- a/drivers/watchdog/npcm_wdt.c +++ b/drivers/watchdog/npcm_wdt.c @@ -7,14 +7,52 @@ #include #include #include +#include #include #include #include +#include #include #include #define NPCM_WTCR 0x1C +/* NPCM GCR module */ +#define NPCM_RESSR_OFFSET 0x6C +#define NPCM_INTCR2_OFFSET 0x60 +#define NPCM7XX_SCRPAD2_OFFSET 0x84 +#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 NPCM_RST GENMASK(31, 23) +#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 +85,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 +251,111 @@ 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 & NPCM_RST) { + ret = regmap_write(gcr_regmap, NPCM_INTCR2_OFFSET, + rstval & ~NPCM_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; + } + + if (rstval & NPCM_RST) { + ret = regmap_write(gcr_regmap, NPCM_RESSR_OFFSET, + rstval & ~NPCM_RST); + if (ret) { + dev_warn(dev, "Failed to clear RESSR reset status: %d\n", ret); + return; + } + + ret = regmap_write(gcr_regmap, NPCM7XX_SCRPAD2_OFFSET, + rstval); + if (ret) { + dev_warn(dev, + "Failed to cache reset status in SCRPAD2: %d\n", ret); + return; + } + } else { + ret = regmap_read(gcr_regmap, NPCM7XX_SCRPAD2_OFFSET, + &rstval); + if (ret) { + dev_warn(dev, + "Failed to read cached reset status from SCRPAD2: %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 +363,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 +389,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 +400,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 +418,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 +430,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 +455,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