From patchwork Mon Oct 7 06:34:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chin-Ting Kuo X-Patchwork-Id: 13824182 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 44F5CCFB440 for ; Mon, 7 Oct 2024 06:41:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date :Subject:CC:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=NkrE9/31Fc1p/Lh2D9loLc3hpnTR+ltsn1I4oP5hYGc=; b=NSqq+zauA61ZAXIZ/jvozelGrw Sge9ONx3cK6fqfzhDIOkAgFG/ONQMJ8AbIVy5HqWmnAKf8cFBLSv/94cMXFHcZ1236aloA4ME/308 dR71LfyO3ONWgIWZhon6GXyw4Z4I4JmeyBRmE58rH6RiYlKHOczhO9DNFZM2QDYSrnccrwKT5NEQ6 2b8A6YK2zU6w2WikthXd7qwK46Z0+BjgFz7NK96AGUhLp5/sK4vVxACDpUlRdw4d1JEYoQg90alXG VoMrmpm0rlGa3yfcZDewN02yXDN8HsMa/NfUyZv671p2CZn9NyUwEpNslXaNrBHpS4MnAkSlj7or5 /isIqeMQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1sxhQm-00000001THL-05vx; Mon, 07 Oct 2024 06:41:20 +0000 Received: from mail.aspeedtech.com ([211.20.114.72] helo=TWMBX01.aspeed.com) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1sxhKG-00000001Ryw-2wk6 for linux-arm-kernel@lists.infradead.org; Mon, 07 Oct 2024 06:34:38 +0000 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Mon, 7 Oct 2024 14:34:09 +0800 Received: from aspeedtech.com (192.168.10.152) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Mon, 7 Oct 2024 14:34:09 +0800 From: Chin-Ting Kuo To: , , , , , , , , , , , , CC: , , , , Subject: [PATCH 4/4] watchdog: aspeed: Add support for SW restart Date: Mon, 7 Oct 2024 14:34:08 +0800 Message-ID: <20241007063408.2360874-5-chin-ting_kuo@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241007063408.2360874-1-chin-ting_kuo@aspeedtech.com> References: <20241007063408.2360874-1-chin-ting_kuo@aspeedtech.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241006_233437_028799_0CD9CF8A X-CRM114-Status: GOOD ( 17.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org WDT reset can be triggered when system hangs or a deliberate SW restart scenario. Originally, system can only know it is reset by WDT through a reset flag. However, since AST2600, a SW reset mechanism is created, SW can trigger the reset event consciously and directly without wait for WDT timeout. This function can be achieved by adding "aspeed,restart-sw" property in dts. After that, an independent reset event flag will be set after system reset by SW. Signed-off-by: Chin-Ting Kuo --- drivers/watchdog/aspeed_wdt.c | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 68eaada8a564..eefca972dfa4 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -61,6 +61,7 @@ struct aspeed_wdt { int idx; u32 ctrl; const struct aspeed_wdt_config *cfg; + u32 flags; }; static const struct aspeed_wdt_config ast2400_config = { @@ -130,6 +131,11 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table); #define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0) #define WDT_RESET_MASK1 0x1c #define WDT_RESET_MASK2 0x20 +#define WDT_SW_RESET_CTRL 0x24 +#define WDT_SW_RESET_COUNT_CLEAR 0xDEADDEAD +#define WDT_SW_RESET_ENABLE 0xAEEDF123 +#define WDT_SW_RESET_MASK1 0x28 +#define WDT_SW_RESET_MASK2 0x2c /* * WDT_RESET_WIDTH controls the characteristics of the external pulse (if @@ -170,6 +176,9 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table); #define WDT_DEFAULT_TIMEOUT 30 #define WDT_RATE_1MHZ 1000000 +/* WDT behavior control flag */ +#define WDT_RESTART_SYSTEM_SW 0x00000001 + static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd) { return container_of(wdd, struct aspeed_wdt, wdd); @@ -249,11 +258,31 @@ static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd, return 0; } +static void aspeed_wdt_sw_reset(struct watchdog_device *wdd) +{ + struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); + u32 ctrl = WDT_CTRL_RESET_MODE_SOC | + WDT_CTRL_RESET_SYSTEM; + + writel(ctrl, wdt->base + WDT_CTRL); + writel(WDT_SW_RESET_COUNT_CLEAR, + wdt->base + WDT_SW_RESET_CTRL); + writel(WDT_SW_RESET_ENABLE, wdt->base + WDT_SW_RESET_CTRL); + + /* system must be reset immediately */ + mdelay(1000); +} + static int aspeed_wdt_restart(struct watchdog_device *wdd, unsigned long action, void *data) { struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); + if (wdt->flags & WDT_RESTART_SYSTEM_SW) { + aspeed_wdt_sw_reset(wdd); + return 0; + } + wdt->ctrl &= ~WDT_CTRL_BOOT_SECONDARY; aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000); @@ -521,8 +550,11 @@ static int aspeed_wdt_probe(struct platform_device *pdev) ret = of_property_read_u32_array(np, "aspeed,reset-mask", reset_mask, nrstmask); if (!ret) { writel(reset_mask[0], wdt->base + WDT_RESET_MASK1); - if (nrstmask > 1) + writel(reset_mask[0], wdt->base + WDT_SW_RESET_MASK1); + if (nrstmask > 1) { writel(reset_mask[1], wdt->base + WDT_RESET_MASK2); + writel(reset_mask[1], wdt->base + WDT_SW_RESET_MASK2); + } } } @@ -552,6 +584,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev) writel(duration - 1, wdt->base + WDT_RESET_WIDTH); } + wdt->flags = 0; + if (!of_device_is_compatible(np, "aspeed,ast2400-wdt") && + !of_device_is_compatible(np, "aspeed,ast2500-wdt") && + of_property_read_bool(np, "aspeed,restart-sw")) + wdt->flags |= WDT_RESTART_SYSTEM_SW; + ret = aspeed_wdt_get_bootstatus(dev, wdt); if (ret) return ret;