From patchwork Mon Oct 28 02:48:11 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: 13852929 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB145184527; Mon, 28 Oct 2024 02:53:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730084009; cv=none; b=UZdKmU5V+QR467nUzQ9x39y1XPsvu3uubQATOduJgxscZ06a/tqoNpLhA8svqgSuqs0B4g1NiBC+W1s32vEjZqfEorx6GMzkh/JeFkNykDHHTyf54l5DFGVPuD/IO+AkIdlbwzx7Xb5za4GdQYBknWgIoSTtefXuDE7VkmGD/gU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730084009; c=relaxed/simple; bh=SfVok2QnDPH32Kmkcj3p1nt9RMkzDbWzinsZZpIrOOA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EHwgH8HuxGv9gpjqEHkWE402Vzn/y+gadGI84BG2N6iTzppPZEb2HfCkCQts6Egc9YFMCBDwItcT60dgfwuTjJe++0KavAvYZMw86Z4flPsrcFOH9YMQlMdX9tOB1PHhiJLi9We0kJ3Zn79anh02fF0RVSeBpy4ngctk6vKYlys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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, 28 Oct 2024 10:48:13 +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, 28 Oct 2024 10:48:13 +0800 From: Chin-Ting Kuo To: , , , , , , , , , , , , CC: , , , , , Subject: [PATCH v2 1/3] ARM: dts: aspeed: Add WDT controller into alias field Date: Mon, 28 Oct 2024 10:48:11 +0800 Message-ID: <20241028024813.2416962-2-chin-ting_kuo@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> References: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add WDT controller into alias field. After that, WDT index, used to distinguish different WDT controllers in the driver, can be gotten by using of_alias_get_id dts API. Signed-off-by: Chin-Ting Kuo --- arch/arm/boot/dts/aspeed/aspeed-g4.dtsi | 2 ++ arch/arm/boot/dts/aspeed/aspeed-g5.dtsi | 3 +++ arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi index 78c967812492..d8b4136d0ca0 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g4.dtsi @@ -29,6 +29,8 @@ aliases { serial3 = &uart4; serial4 = &uart5; serial5 = &vuart; + watchdog0 = &wdt1; + watchdog1 = &wdt2; }; cpus { diff --git a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi index 57a699a7c149..4dd220bca617 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g5.dtsi @@ -30,6 +30,9 @@ aliases { serial3 = &uart4; serial4 = &uart5; serial5 = &vuart; + watchdog0 = &wdt1; + watchdog1 = &wdt2; + watchdog2 = &wdt3; }; cpus { diff --git a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi index 8ed715bd53aa..c0a47c795fff 100644 --- a/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed/aspeed-g6.dtsi @@ -40,6 +40,10 @@ aliases { mdio1 = &mdio1; mdio2 = &mdio2; mdio3 = &mdio3; + watchdog0 = &wdt1; + watchdog1 = &wdt2; + watchdog2 = &wdt3; + watchdog3 = &wdt4; }; From patchwork Mon Oct 28 02:48:12 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: 13852930 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C554188917; Mon, 28 Oct 2024 02:53:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730084011; cv=none; b=UiUSA1KovMCJHEpKhxjRBUYm2r5HrKt7DQtlTW3wQQ4eYgSWYDFKwOKueMqdjL2l8snnmXxidJx4TWFWvCTBPj8RFOUPaA5taK6Cl8U+n18KvKMNkJaTOb00Do/xchqii+p+26uNA/ZT/I495YWj/eM1+bwhBAkyhCnaMLXWAcw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730084011; c=relaxed/simple; bh=rHo+1yQI8YBpNS72SJ9opcA1Hby9P3q4iD/0Z5n19mA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sNPr9lVXl4h3iXeCFWoUZ7YHk5Mfn2IvxqVJaFSg3F7WhvyAnIpaORtikUjtNQAVrtGWj0v8sATnq4runAFUDVSBB1t22mSt8LfyQYuNo+agCA5bRkG+aRNKgr/rNV1l9HnrawkKx2lGkQAHPo/V6xLCeg99/L1rSDIS0xsI0ww= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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, 28 Oct 2024 10:48:13 +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, 28 Oct 2024 10:48:13 +0800 From: Chin-Ting Kuo To: , , , , , , , , , , , , CC: , , , , , Subject: [PATCH v2 2/3] watchdog: aspeed: Update bootstatus handling Date: Mon, 28 Oct 2024 10:48:12 +0800 Message-ID: <20241028024813.2416962-3-chin-ting_kuo@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> References: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Update the bootstatus according to the latest design guide from the OpenBMC shown as below. https://github.com/openbmc/docs/blob/master/designs/bmc-reboot-cause-update.md#proposed-design In short, - WDIOF_EXTERN1 => system is reset by Software - WDIOF_CARDRESET => system is reset by WDT - Others => other reset events, e.g., power on reset. On AST2400 platform, only a bit, SCU3C[1], represents that the system is reset by WDT1 or WDT2. On AST2500 platform, SCU3C[4:2] are WDT reset flags. SCU3C[4]: system is reset by WDT3. SCU3C[3]: system is reset by WDT2. SCU3C[2]: system is reset by WDT1. On AST2600 platform, SCU074[31:16] are WDT reset flags. SCU074[31:28]: system is reset by WDT4 SCU074[31]: system is reset by WDT4 software reset. SCU074[27:24]: system is reset by WDT3 SCU074[27]: system is reset by WDT3 software reset. SCU074[23:20]: system is reset by WDT2 SCU074[23]: system is reset by WDT2 software reset. SCU074[19:16]: system is reset by WDT1 SCU074[19]: system is reset by WDT1 software reset. Signed-off-by: Chin-Ting Kuo --- drivers/watchdog/aspeed_wdt.c | 109 +++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 8 deletions(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index b4773a6aaf8c..a0c03a949173 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -11,10 +11,12 @@ #include #include #include +#include #include #include #include #include +#include #include static bool nowayout = WATCHDOG_NOWAYOUT; @@ -22,15 +24,41 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +/* AST SCU Register for System Reset Event Log Register Set + * ast2600 is scu074 ast2400/2500 is scu03c + */ +#define AST2400_SCU_SYS_RESET_STATUS 0x3c +#define AST2400_SCU_SYS_RESET_WDT_MASK 0x1 +#define AST2400_SCU_SYS_RESET_WDT_MASK_SHIFT 1 + +#define AST2500_SCU_SYS_RESET_WDT_MASK 0x1 +#define AST2500_SCU_SYS_RESET_WDT_MASK_SHIFT 2 + +#define AST2600_SCU_SYS_RESET_STATUS 0x74 +#define AST2600_SCU_SYS_RESET_WDT_MASK 0xf +#define AST2600_SCU_SYS_RESET_WDT_SW_MASK 0x8 +#define AST2600_SCU_SYS_RESET_WDT_MASK_SHIFT 16 + +struct aspeed_wdt_scu { + const char *compatible; + u32 reset_status_reg; + u32 wdt_reset_mask; + u32 wdt_sw_reset_mask; + u32 wdt_reset_mask_shift; +}; + struct aspeed_wdt_config { u32 ext_pulse_width_mask; u32 irq_shift; u32 irq_mask; + struct aspeed_wdt_scu scu; }; struct aspeed_wdt { struct watchdog_device wdd; void __iomem *base; + int idx; u32 ctrl; const struct aspeed_wdt_config *cfg; }; @@ -39,18 +67,39 @@ static const struct aspeed_wdt_config ast2400_config = { .ext_pulse_width_mask = 0xff, .irq_shift = 0, .irq_mask = 0, + .scu = { + .compatible = "aspeed,ast2400-scu", + .reset_status_reg = AST2400_SCU_SYS_RESET_STATUS, + .wdt_reset_mask = AST2400_SCU_SYS_RESET_WDT_MASK, + .wdt_sw_reset_mask = 0, + .wdt_reset_mask_shift = AST2400_SCU_SYS_RESET_WDT_MASK_SHIFT, + }, }; static const struct aspeed_wdt_config ast2500_config = { .ext_pulse_width_mask = 0xfffff, .irq_shift = 12, .irq_mask = GENMASK(31, 12), + .scu = { + .compatible = "aspeed,ast2500-scu", + .reset_status_reg = AST2400_SCU_SYS_RESET_STATUS, + .wdt_reset_mask = AST2500_SCU_SYS_RESET_WDT_MASK, + .wdt_sw_reset_mask = 0, + .wdt_reset_mask_shift = AST2500_SCU_SYS_RESET_WDT_MASK_SHIFT, + }, }; static const struct aspeed_wdt_config ast2600_config = { .ext_pulse_width_mask = 0xfffff, .irq_shift = 0, .irq_mask = GENMASK(31, 10), + .scu = { + .compatible = "aspeed,ast2600-scu", + .reset_status_reg = AST2600_SCU_SYS_RESET_STATUS, + .wdt_reset_mask = AST2600_SCU_SYS_RESET_WDT_MASK, + .wdt_sw_reset_mask = AST2600_SCU_SYS_RESET_WDT_SW_MASK, + .wdt_reset_mask_shift = AST2600_SCU_SYS_RESET_WDT_MASK_SHIFT, + }, }; static const struct of_device_id aspeed_wdt_of_table[] = { @@ -213,6 +262,52 @@ static int aspeed_wdt_restart(struct watchdog_device *wdd, return 0; } +static int aspeed_wdt_get_bootstatus(struct device *dev, + struct aspeed_wdt *wdt) +{ + struct device_node *np = dev->of_node; + struct aspeed_wdt_scu scu = wdt->cfg->scu; + struct regmap *scu_base; + u32 reset_mask_width; + u32 reset_mask_shift; + u32 status; + int ret; + + wdt->idx = of_alias_get_id(np, "watchdog"); + if (wdt->idx < 0) + wdt->idx = 0; + + scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); + if (IS_ERR(scu_base)) + return PTR_ERR(scu_base); + + ret = regmap_read(scu_base, scu.reset_status_reg, &status); + if (ret) + return ret; + + /* On AST2400, only a bit used to represent WDT reset */ + if (of_device_is_compatible(np, "aspeed,ast2400-wdt")) + wdt->idx = 0; + + reset_mask_width = hweight32(scu.wdt_reset_mask); + reset_mask_shift = scu.wdt_reset_mask_shift + + reset_mask_width * wdt->idx; + + if (status & (scu.wdt_sw_reset_mask << reset_mask_shift)) + wdt->wdd.bootstatus = WDIOF_EXTERN1; + else if (status & (scu.wdt_reset_mask << reset_mask_shift)) + wdt->wdd.bootstatus = WDIOF_CARDRESET; + else + wdt->wdd.bootstatus = 0; + + ret = regmap_write(scu_base, scu.reset_status_reg, + scu.wdt_reset_mask << reset_mask_shift); + if (ret) + return ret; + + return 0; +} + /* access_cs0 shows if cs0 is accessible, hence the reverted bit */ static ssize_t access_cs0_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -312,7 +407,6 @@ static int aspeed_wdt_probe(struct platform_device *pdev) struct device_node *np; const char *reset_type; u32 duration; - u32 status; int ret; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); @@ -458,14 +552,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev) writel(duration - 1, wdt->base + WDT_RESET_WIDTH); } - status = readl(wdt->base + WDT_TIMEOUT_STATUS); - if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { - wdt->wdd.bootstatus = WDIOF_CARDRESET; + ret = aspeed_wdt_get_bootstatus(dev, wdt); + if (ret) + return ret; - if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || - of_device_is_compatible(np, "aspeed,ast2500-wdt")) - wdt->wdd.groups = bswitch_groups; - } + if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || + of_device_is_compatible(np, "aspeed,ast2500-wdt")) + wdt->wdd.groups = bswitch_groups; dev_set_drvdata(dev, wdt); From patchwork Mon Oct 28 02:48:13 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: 13852915 Received: from TWMBX01.aspeed.com (mail.aspeedtech.com [211.20.114.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62D152C697; Mon, 28 Oct 2024 02:49:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.20.114.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730083768; cv=none; b=oM3kI/+OGgitW7H+g4wJmwUtOmK6CTHj6rUezC2jYs3vMl/gAyQvym5bMg9US5byQLWLJt8xlrRxFivaarYiJfs3YduvazFRzoPsoDvSutAbpiOPfWS7o+eVuG5Icgs5V/4KbdvZQtsk9ugsaEBkdltZk2z9pIZsTjSLKQGxnyw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730083768; c=relaxed/simple; bh=+W8rOujOB1poCvpXN2Vb6ocoev2Qu24//WYZBN1Lx6Q=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m+rXkycNNS+F+sX3HDH5HWnwqyoJgr6sPL0UmgBmpMZnXtAuzZWuAsMZ6OC1ADk37QeFns9ZCfCNIxmyht6xzlg7HIncnkTGWV8beINeNn7XZ2TAoKLbJ7e6a9gCrlmy3e86UWNDKWZdvUPuvU8Rw/KB7YrrhpbZ9auttYe8WA0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com; spf=pass smtp.mailfrom=aspeedtech.com; arc=none smtp.client-ip=211.20.114.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=aspeedtech.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aspeedtech.com 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, 28 Oct 2024 10:48:13 +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, 28 Oct 2024 10:48:13 +0800 From: Chin-Ting Kuo To: , , , , , , , , , , , , CC: , , , , , Subject: [PATCH v2 3/3] watchdog: aspeed: Add support for SW restart Date: Mon, 28 Oct 2024 10:48:13 +0800 Message-ID: <20241028024813.2416962-4-chin-ting_kuo@aspeedtech.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> References: <20241028024813.2416962-1-chin-ting_kuo@aspeedtech.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Since AST2600, except for HW WDT counter timeout, HW WDT reset can also be triggered by just cinfiguring some HW registers by SW directly. We named it "SW restart". Although it is "SW" restart, its mechanism is implemented by HW. Originally, system can only know it is reset by WDT through a reset flag. However, since AST2600, SW can trigger the reset event consciously and directly without wait for WDT timeout. WDT counter is not enabled when SW restart is adopted. After that, an independent reset event flag will be set after systemis reset by SW. Signed-off-by: Chin-Ting Kuo --- drivers/watchdog/aspeed_wdt.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index a0c03a949173..9ba9b7346d44 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -40,6 +40,9 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" #define AST2600_SCU_SYS_RESET_WDT_SW_MASK 0x8 #define AST2600_SCU_SYS_RESET_WDT_MASK_SHIFT 16 +/* WDT behavior control flag */ +#define WDT_RESTART_SYSTEM_SW_SUPPORT 0x00000001 + struct aspeed_wdt_scu { const char *compatible; u32 reset_status_reg; @@ -53,6 +56,7 @@ struct aspeed_wdt_config { u32 irq_shift; u32 irq_mask; struct aspeed_wdt_scu scu; + u32 flags; }; struct aspeed_wdt { @@ -67,6 +71,7 @@ static const struct aspeed_wdt_config ast2400_config = { .ext_pulse_width_mask = 0xff, .irq_shift = 0, .irq_mask = 0, + .flags = 0, .scu = { .compatible = "aspeed,ast2400-scu", .reset_status_reg = AST2400_SCU_SYS_RESET_STATUS, @@ -80,6 +85,7 @@ static const struct aspeed_wdt_config ast2500_config = { .ext_pulse_width_mask = 0xfffff, .irq_shift = 12, .irq_mask = GENMASK(31, 12), + .flags = 0, .scu = { .compatible = "aspeed,ast2500-scu", .reset_status_reg = AST2400_SCU_SYS_RESET_STATUS, @@ -93,6 +99,7 @@ static const struct aspeed_wdt_config ast2600_config = { .ext_pulse_width_mask = 0xfffff, .irq_shift = 0, .irq_mask = GENMASK(31, 10), + .flags = WDT_RESTART_SYSTEM_SW_SUPPORT, .scu = { .compatible = "aspeed,ast2600-scu", .reset_status_reg = AST2600_SCU_SYS_RESET_STATUS, @@ -130,6 +137,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 @@ -249,10 +261,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); + struct aspeed_wdt_config *cfg = wdt->cfg; + + if (cfg->flags & WDT_RESTART_SYSTEM_SW_SUPPORT) { + aspeed_wdt_sw_reset(wdd); + return 0; + } wdt->ctrl &= ~WDT_CTRL_BOOT_SECONDARY; aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000); @@ -524,6 +557,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (nrstmask > 1) writel(reset_mask[1], wdt->base + WDT_RESET_MASK2); } + + if (wdt->cfg->flags & WDT_RESTART_SYSTEM_SW_SUPPORT) { + reg = readl(wdt->base + WDT_RESET_MASK1); + writel(reg, wdt->base + WDT_SW_RESET_MASK1); + reg = readl(wdt->base + WDT_RESET_MASK2); + writel(reg, wdt->base + WDT_SW_RESET_MASK2); + } } if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {