From patchwork Sat Nov 6 14:52:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sander Vanheule X-Patchwork-Id: 1551761 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=cW2P99I3; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=svanheule.net header.i=@svanheule.net header.a=rsa-sha256 header.s=mail1707 header.b=xFBZisgU; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HmlKw2j54z9sR4 for ; Sun, 7 Nov 2021 04:51:16 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id: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=ySC0vnr9eq24UnGOfIWYmK9snSJnpIHqPrNEX4hCkCY=; b=cW2P99I33fe/C0 tBxqYVqL1LocbTjFuZJX3OE0/PamYPV3e3P78BEfo30IfLBe2XLU6XDIAsIQWHpO73/BMOEVz92GG R0S9Yw4phS1tcIxnNBDciYmAHbSIdgg5J9attYU6aTRdu9qXT7W4lR3Ga5uIWo1C+OvtQNDvpxEQ1 cXEglng285F0HLrtSt1m/3g2bQTyUHHqX9FGvw9GejIeXm699fiGBmFPxOfsS1O3MBTu/t/tc5vq/ 4VL11Byb34W9Q6A/gzN6ZizlaDfwhwqis27ZIUSE1d9xMLAVDr4NX5shx+EVVvcHbqSnOW1uyUgUE DtkxF6FmnRoFUkGcrx9g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mjPoE-00DP1A-LU; Sat, 06 Nov 2021 17:48:55 +0000 Received: from polaris.svanheule.net ([2a00:c98:2060:a004:1::200]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mjP0k-00DBy4-RE for openwrt-devel@lists.openwrt.org; Sat, 06 Nov 2021 16:57:53 +0000 Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:9857:75d5:20f7:4cbb]) (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) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id CCA0A26D55D; Sat, 6 Nov 2021 15:52:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1636210377; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3+vXkzPRwSihbEGeT9vJbV4D3QFKbnshfY/xRfyw4Wk=; b=xFBZisgUdDrWs5gTEelpiUoZypr9SVq+h3haHTiRPg+xukfOzrgrNAtI/Sow5IhmqIFq3F Lu+MZFGMHREbuLx9nTQVreD+Qiq6J86H51pP3K6Ar1wvMLAPYNWnmtso1nmH76/9/0lUMJ 7vDFekjrw9z7ZsidLcQdJ36nvbPd2NEVwSOAvR1llXQU6rMK/8WyaMrKVgxfOwhJ96fmo7 v5oR7AjVJig8Tc710uhcrT3tvvzvs/D1SYbG4RHiqe4yPNLVy8gICtUnkjPJsGMX4jAyV3 d9G4Vc05zRvuzI/9UPR3bKxUxcCyvsQDRkBe5QOvmchaX5JEY3a4FbLvbweOhQ== From: Sander Vanheule To: openwrt-devel@lists.openwrt.org Cc: Birger Koblitz , John Crispin , Christian Lamparter , Sander Vanheule Subject: [PATCH v3 3/5] realtek: Backport Realtek Otto WDT driver Date: Sat, 6 Nov 2021 15:52:48 +0100 Message-Id: X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211106_095747_834869_A0484EB9 X-CRM114-Status: GOOD ( 27.42 ) X-Spam-Score: -2.5 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add patch submitted upstream to linux-watchdog and replace the MIPS architecture symbols. Requires one extra patch for the DIV_ROUND_* macros, which have moved to a different header since 5.10. Signed-off-by: Sander Vanheule Content analysis details: (-2.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [2a00:c98:2060:a004:1:0:0:200 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Add patch submitted upstream to linux-watchdog and replace the MIPS architecture symbols. Requires one extra patch for the DIV_ROUND_* macros, which have moved to a different header since 5.10. Signed-off-by: Sander Vanheule --- v3: - Fix watchdog Kconfig modifation patch v2: - Remove kernel config update from patch --- ...hdog-add-realtek-otto-watchdog-timer.patch | 456 ++++++++++++++++++ ...date-dependency-for-realtek-otto-wdt.patch | 17 + ...308-otto-wdt-fix-missing-math-header.patch | 13 + 3 files changed, 486 insertions(+) create mode 100644 target/linux/realtek/patches-5.10/100-watchdog-add-realtek-otto-watchdog-timer.patch create mode 100644 target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch create mode 100644 target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch diff --git a/target/linux/realtek/patches-5.10/100-watchdog-add-realtek-otto-watchdog-timer.patch b/target/linux/realtek/patches-5.10/100-watchdog-add-realtek-otto-watchdog-timer.patch new file mode 100644 index 000000000000..5aa988dc5585 --- /dev/null +++ b/target/linux/realtek/patches-5.10/100-watchdog-add-realtek-otto-watchdog-timer.patch @@ -0,0 +1,456 @@ +From 2dbf0c6e0eebf523008c15794434d2d1a9b1260e Mon Sep 17 00:00:00 2001 +Message-Id: <2dbf0c6e0eebf523008c15794434d2d1a9b1260e.1636018117.git.sander@svanheule.net> +In-Reply-To: +References: +From: Sander Vanheule +Date: Sun, 3 Oct 2021 09:25:27 +0200 +Subject: [PATCH v3 2/2] watchdog: Add Realtek Otto watchdog timer + +Realtek MIPS SoCs (platform name Otto) have a watchdog timer with +pretimeout notifitication support. The WDT can (partially) hard reset, +or soft reset the SoC. + +This driver implements all features as described in the devicetree +binding, except the phase2 interrupt, and also functions as a restart +handler. The cpu reset mode is considered to be a "warm" restart, since +this mode does not reset all peripherals. Being an embedded system +though, the "cpu" and "software" modes will still cause the bootloader +to run on restart. + +It is not known how a forced system reset can be disabled on the +supported platforms. This means that the phase2 interrupt will only fire +at the same time as reset, so implementing phase2 is of little use. + +Signed-off-by: Sander Vanheule +--- + MAINTAINERS | 7 + + drivers/watchdog/Kconfig | 13 + + drivers/watchdog/Makefile | 1 + + drivers/watchdog/realtek_otto_wdt.c | 361 ++++++++++++++++++++++++++++ + 4 files changed, 382 insertions(+) + create mode 100644 drivers/watchdog/realtek_otto_wdt.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 2c9070aeba2a..54c8f788d3e5 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -15991,6 +15991,13 @@ S: Maintained + F: include/sound/rt*.h + F: sound/soc/codecs/rt* + ++REALTEK OTTO WATCHDOG ++M: Sander Vanheule ++L: linux-watchdog@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml ++F: driver/watchdog/realtek_otto_wdt.c ++ + REALTEK RTL83xx SMI DSA ROUTER CHIPS + M: Linus Walleij + S: Maintained +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index bf59faeb3de1..d308e13a9aa1 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -954,6 +954,19 @@ config RTD119X_WATCHDOG + Say Y here to include support for the watchdog timer in + Realtek RTD1295 SoCs. + ++config REALTEK_OTTO_WDT ++ tristate "Realtek Otto MIPS watchdog support" ++ depends on MACH_REALTEK_RTL || COMPILE_TEST ++ depends on COMMON_CLK ++ select WATCHDOG_CORE ++ default MACH_REALTEK_RTL ++ help ++ Say Y here to include support for the watchdog timer on Realtek ++ RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout ++ notifications and system reset on timeout. ++ ++ When built as a module this will be called realtek_otto_wdt. ++ + config SPRD_WATCHDOG + tristate "Spreadtrum watchdog support" + depends on ARCH_SPRD || COMPILE_TEST +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index 1bd2d6f37c53..a8dccf819163 100644 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -171,6 +171,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o + obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o + obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o + obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o ++obj-$(CONFIG_REALTEK_OTTO_WDT) += realtek_otto_wdt.o + + # PARISC Architecture + +diff --git a/drivers/watchdog/realtek_otto_wdt.c b/drivers/watchdog/realtek_otto_wdt.c +new file mode 100644 +index 000000000000..48bc8dfefc25 +--- /dev/null ++++ b/drivers/watchdog/realtek_otto_wdt.c +@@ -0,0 +1,361 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++/* ++ * Realtek Otto MIPS platform watchdog ++ * ++ * Watchdog timer that will reset the system after timeout, using the selected ++ * reset mode. ++ * ++ * Counter scaling and timeouts: ++ * - Base prescale of (2 << 25), providing tick duration T_0: 168ms @ 200MHz ++ * - PRESCALE: logarithmic prescaler adding a factor of {1, 2, 4, 8} ++ * - Phase 1: Times out after (PHASE1 + 1) × PRESCALE × T_0 ++ * Generates an interrupt, WDT cannot be stopped after phase 1 ++ * - Phase 2: starts after phase 1, times out after (PHASE2 + 1) × PRESCALE × T_0 ++ * Resets the system according to RST_MODE ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define OTTO_WDT_REG_CNTR 0x0 ++#define OTTO_WDT_CNTR_PING BIT(31) ++ ++#define OTTO_WDT_REG_INTR 0x4 ++#define OTTO_WDT_INTR_PHASE_1 BIT(31) ++#define OTTO_WDT_INTR_PHASE_2 BIT(30) ++ ++#define OTTO_WDT_REG_CTRL 0x8 ++#define OTTO_WDT_CTRL_ENABLE BIT(31) ++#define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29) ++#define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22) ++#define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15) ++#define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0) ++#define OTTO_WDT_MODE_SOC 0 ++#define OTTO_WDT_MODE_CPU 1 ++#define OTTO_WDT_MODE_SOFTWARE 2 ++#define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU ++ ++#define OTTO_WDT_PRESCALE_MAX 3 ++ ++/* ++ * One higher than the max values contained in PHASE{1,2}, since a value of 0 ++ * corresponds to one tick. ++ */ ++#define OTTO_WDT_PHASE_TICKS_MAX 32 ++ ++/* ++ * The maximum reset delay is actually 2×32 ticks, but that would require large ++ * pretimeout values for timeouts longer than 32 ticks. Limit the maximum timeout ++ * to 32 + 1 to ensure small pretimeout values can be configured as expected. ++ */ ++#define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1) ++ ++struct otto_wdt_ctrl { ++ struct watchdog_device wdev; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++ int irq_phase1; ++}; ++ ++static int otto_wdt_start(struct watchdog_device *wdev) ++{ ++ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); ++ u32 v; ++ ++ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); ++ v |= OTTO_WDT_CTRL_ENABLE; ++ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ return 0; ++} ++ ++static int otto_wdt_stop(struct watchdog_device *wdev) ++{ ++ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); ++ u32 v; ++ ++ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); ++ v &= ~OTTO_WDT_CTRL_ENABLE; ++ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ return 0; ++} ++ ++static int otto_wdt_ping(struct watchdog_device *wdev) ++{ ++ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); ++ ++ iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR); ++ ++ return 0; ++} ++ ++static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale) ++{ ++ unsigned int rate_khz = clk_get_rate(ctrl->clk) / 1000; ++ ++ if (!rate_khz) ++ return 0; ++ ++ return DIV_ROUND_CLOSEST(1 << (25 + prescale), rate_khz); ++} ++ ++/* ++ * The timer asserts the PHASE1/PHASE2 IRQs when the number of ticks exceeds ++ * the value stored in those fields. This means each phase will run for at least ++ * one tick, so small values need to be clamped to correctly reflect the timeout. ++ */ ++static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration, ++ unsigned int min_ticks) ++{ ++ return max(min_ticks, DIV_ROUND_UP(val, tick_duration)); ++} ++ ++static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout, ++ unsigned int pretimeout) ++{ ++ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); ++ unsigned int pretimeout_ms = pretimeout * 1000; ++ unsigned int timeout_ms = timeout * 1000; ++ unsigned int prescale_next = 0; ++ unsigned int phase1_ticks; ++ unsigned int phase2_ticks; ++ unsigned int total_ticks; ++ unsigned int prescale; ++ unsigned int tick_ms; ++ u32 v; ++ ++ do { ++ prescale = prescale_next; ++ if (prescale > OTTO_WDT_PRESCALE_MAX) ++ return -EINVAL; ++ ++ tick_ms = otto_wdt_tick_ms(ctrl, prescale); ++ total_ticks = div_round_ticks(timeout_ms, tick_ms, 2); ++ phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1); ++ phase2_ticks = total_ticks - phase1_ticks; ++ ++ prescale_next++; ++ } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX ++ || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX); ++ ++ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2); ++ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1); ++ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1); ++ v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale); ++ ++ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ timeout_ms = total_ticks * tick_ms; ++ ctrl->wdev.timeout = timeout_ms / 1000; ++ ++ pretimeout_ms = phase2_ticks * tick_ms; ++ ctrl->wdev.pretimeout = pretimeout_ms / 1000; ++ ++ return 0; ++} ++ ++static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val) ++{ ++ return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1)); ++} ++ ++static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val) ++{ ++ return otto_wdt_determine_timeouts(wdev, wdev->timeout, val); ++} ++ ++static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode, ++ void *data) ++{ ++ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev); ++ u32 reset_mode; ++ u32 v; ++ ++ disable_irq(ctrl->irq_phase1); ++ ++ switch (reboot_mode) { ++ case REBOOT_SOFT: ++ reset_mode = OTTO_WDT_MODE_SOFTWARE; ++ break; ++ case REBOOT_WARM: ++ reset_mode = OTTO_WDT_MODE_CPU; ++ break; ++ default: ++ reset_mode = OTTO_WDT_MODE_SOC; ++ break; ++ } ++ ++ /* Configure for shortest timeout and wait for reset to occur */ ++ v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE; ++ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ mdelay(3 * otto_wdt_tick_ms(ctrl, 0)); ++ ++ return 0; ++} ++ ++static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id) ++{ ++ struct otto_wdt_ctrl *ctrl = dev_id; ++ ++ iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR); ++ dev_crit(ctrl->dev, "phase 1 timeout\n"); ++ watchdog_notify_pretimeout(&ctrl->wdev); ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct watchdog_ops otto_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = otto_wdt_start, ++ .stop = otto_wdt_stop, ++ .ping = otto_wdt_ping, ++ .set_timeout = otto_wdt_set_timeout, ++ .set_pretimeout = otto_wdt_set_pretimeout, ++ .restart = otto_wdt_restart, ++}; ++ ++static const struct watchdog_info otto_wdt_info = { ++ .identity = "Realtek Otto watchdog timer", ++ .options = WDIOF_KEEPALIVEPING | ++ WDIOF_MAGICCLOSE | ++ WDIOF_SETTIMEOUT | ++ WDIOF_PRETIMEOUT, ++}; ++ ++static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl) ++{ ++ static const char *mode_property = "realtek,reset-mode"; ++ const struct fwnode_handle *node = ctrl->dev->fwnode; ++ int mode_count; ++ u32 mode; ++ u32 v; ++ ++ if (!node) ++ return -ENXIO; ++ ++ mode_count = fwnode_property_string_array_count(node, mode_property); ++ if (mode_count < 0) ++ return mode_count; ++ else if (mode_count == 0) ++ return 0; ++ else if (mode_count != 1) ++ return -EINVAL; ++ ++ if (fwnode_property_match_string(node, mode_property, "soc") == 0) ++ mode = OTTO_WDT_MODE_SOC; ++ else if (fwnode_property_match_string(node, mode_property, "cpu") == 0) ++ mode = OTTO_WDT_MODE_CPU; ++ else if (fwnode_property_match_string(node, mode_property, "software") == 0) ++ mode = OTTO_WDT_MODE_SOFTWARE; ++ else ++ return -EINVAL; ++ ++ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL); ++ v &= ~OTTO_WDT_CTRL_RST_MODE; ++ v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode); ++ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ return 0; ++} ++ ++static int otto_wdt_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct otto_wdt_ctrl *ctrl; ++ unsigned int max_tick_ms; ++ int ret; ++ ++ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); ++ if (!ctrl) ++ return -ENOMEM; ++ ++ ctrl->dev = dev; ++ ctrl->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(ctrl->base)) ++ return PTR_ERR(ctrl->base); ++ ++ /* Clear any old interrupts and reset initial state */ ++ iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2, ++ ctrl->base + OTTO_WDT_REG_INTR); ++ iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL); ++ ++ ctrl->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(ctrl->clk)) ++ return dev_err_probe(dev, PTR_ERR(ctrl->clk), "Failed to get clock\n"); ++ ++ ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1"); ++ if (ctrl->irq_phase1 < 0) ++ return dev_err_probe(dev, ctrl->irq_phase1, "phase1 IRQ not found\n"); ++ ++ ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0, ++ "realtek-otto-wdt", ctrl); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n"); ++ ++ ret = otto_wdt_probe_reset_mode(ctrl); ++ if (ret) ++ return dev_err_probe(dev, ret, "Invalid reset mode specified\n"); ++ ++ ctrl->wdev.parent = dev; ++ ctrl->wdev.info = &otto_wdt_info; ++ ctrl->wdev.ops = &otto_wdt_ops; ++ ++ /* ++ * Since pretimeout cannot be disabled, min. timeout is twice the ++ * subsystem resolution. max. timeout is ca. 43s at a bus clock of 200MHz. ++ */ ++ ctrl->wdev.min_timeout = 2; ++ max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX); ++ ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX; ++ ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000); ++ ++ watchdog_set_drvdata(&ctrl->wdev, ctrl); ++ watchdog_init_timeout(&ctrl->wdev, 0, dev); ++ watchdog_stop_on_reboot(&ctrl->wdev); ++ watchdog_set_restart_priority(&ctrl->wdev, 128); ++ ++ ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to set timeout\n"); ++ ++ return devm_watchdog_register_device(dev, &ctrl->wdev); ++} ++ ++static const struct of_device_id otto_wdt_ids[] = { ++ { .compatible = "realtek,rtl8380-wdt" }, ++ { .compatible = "realtek,rtl8390-wdt" }, ++ { .compatible = "realtek,rtl9300-wdt" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, otto_wdt_ids); ++ ++static struct platform_driver otto_wdt_driver = { ++ .probe = otto_wdt_probe, ++ .driver = { ++ .name = "realtek-otto-watchdog", ++ .of_match_table = otto_wdt_ids, ++ }, ++}; ++module_platform_driver(otto_wdt_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Sander Vanheule "); ++MODULE_DESCRIPTION("Realtek Otto watchdog timer driver"); +-- +2.31.1 + diff --git a/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch b/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch new file mode 100644 index 000000000000..32c3e2bb6942 --- /dev/null +++ b/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch @@ -0,0 +1,17 @@ +Index: linux-5.10.76/drivers/watchdog/Kconfig +=================================================================== +--- linux-5.10.76.orig/drivers/watchdog/Kconfig ++++ linux-5.10.76/drivers/watchdog/Kconfig +@@ -997,10 +997,10 @@ config RTD119X_WATCHDOG + + config REALTEK_OTTO_WDT + tristate "Realtek Otto MIPS watchdog support" +- depends on MACH_REALTEK_RTL || COMPILE_TEST ++ depends on RTL838X + depends on COMMON_CLK + select WATCHDOG_CORE +- default MACH_REALTEK_RTL ++ default RTL838X + help + Say Y here to include support for the watchdog timer on Realtek + RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout diff --git a/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch b/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch new file mode 100644 index 000000000000..20f86ed7e2ba --- /dev/null +++ b/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch @@ -0,0 +1,13 @@ +Index: linux-5.10.72/drivers/watchdog/realtek_otto_wdt.c +=================================================================== +--- linux-5.10.72.orig/drivers/watchdog/realtek_otto_wdt.c ++++ linux-5.10.72/drivers/watchdog/realtek_otto_wdt.c +@@ -21,7 +21,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include