From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B968E6070F51 for ; Thu, 12 Nov 2026 18:55:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=bS2EYyDR; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b=zj4z9OoW 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:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Unsubscribe-Post: List-Owner; bh=dY6ypCx6Aqc4mXezTdyvYsWbav3aY7CBv+TwjbEBghk=; b=bS2EYyDRvORT33 GDr9/dOm0rNMsIzCRy5aDF35PTS7WKRhGv76n9yD+lX+zLUMqg6TvXo9/3KyiAfGiXNMHuBvMqyYF RMtC2RmoA5xvc6aXhMPfkyerS9ukatjpi+KXVX74rDBcsqxckGxQjHmNDvyFhPDLpMizi7rlCSSIX UQHSEgILF36hOF0aSJT2K9ZqIudAEuWyqWYB5GyQUb5LURvqNVc7bjtcolnzTP57RxFlYpOEUsk+K iJwIq3Xfxp7o9Byi5cHMEWP+3rg37oTlhqVc33wc3BCxfc0Yzsyy8QqtgZ7MevFbZu5LvPzn2TzcJ 5w9pW+ncposLar5nFmOQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.100.1 #2 (Red Hat Linux)) id 1xRZxW-0000000AtoC-05Yu; Thu, 12 Nov 2026 18:55:43 +0000 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by bombadil.infradead.org with esmtps (Exim 4.100.1 #2 (Red Hat Linux)) id 1xRZxH-0000000Atji-01oA for linux-arm-kernel@lists.infradead.org; Thu, 12 Nov 2026 18:55:34 +0000 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4a2d6d01ecbso977475e9.0 for ; Thu, 12 Nov 2026 10:55:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794509725; x=1795114525; darn=lists.infradead.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=dY6ypCx6Aqc4mXezTdyvYsWbav3aY7CBv+TwjbEBghk=; b=zj4z9OoWt+MY0jjUDExTsMg5azDZ8ul8SzjE5E/ZYmOwEWNnOm8DlWNuU7f8oFBlhE QTB9f0d0ZF132CgoeNXXEY7BNoABthgV5fXlAEvfWQcDXENVrlw446411okp2vWZ3Xkj n8/cYATRkaafTArg8LjI5ecIQDCT/gvFM9xOMMGbMz4Vhk20tM2MV0xZFM45rwCWcFv0 aPtSSn2J35FnKRGt6k91Vg7CNBCQAUkfRwmI5rmRE4L/kVjaT6j3UTcx4NVQuoD1tN63 nJdcapeN8JuAoYIxOYSZXZG0NUTx6OKKBDSgWipA764ymYGrA0ez3eM2kQoXq3fI+1fN /PjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794509725; x=1795114525; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=dY6ypCx6Aqc4mXezTdyvYsWbav3aY7CBv+TwjbEBghk=; b=yxIvJ3H2ljvNvQ5nSYqCdSiEB+e+qk1gHz7YfaZzsQr0Jefsy/kyIgVQbVNKflH/T1 OIGlM9oFKZmu8qnWrS7roKwvUKiZgl5TS9Ep6n3eOv6DM7qPh5hQxsUzUpcvYaXaPVC0 i7yV8hPUH7gcTFZOwJT/bOUw8NOn5AzWCpR621/ReqdU8vAU9sySBVefAbfLH/eO6//d L4BTR7kj2/tYKmGCgRP85ZocR2X8T4eHJmbe69t3P4t0BUcI0Q0+y1JnsS+JttcSw9nR Q7BT4NXVUOMz3HdpdhuCt/ROfHNu6v36jveN30A7IaRCM1ENdSamFyBZjTdMeNbSmXr9 XRzQ== X-Gm-Message-State: APuU4Z/I/yAy7gkf8PFNVxkCucap6x72zgm5mQrupPDB94PZsV/rpk87 EwScXJMtseOQFOIiH8WOwY8XfZzrFz6Xg/xEtcaG+85D77HtjDtfSMmf X-Gm-Gg: AYBFou2vTx/0t1V4MCkXiRa307mDTio7nSKWZZHF6JZvsINBkv2wRdpDxjiGo2iZqnq gh5YGPjLvg0fPl73Xn2x3GDDzFNbdxcpJWy44ySOj/OEy9dHHkH9Rd8IVf5PdpjO1JwPS7oDkIO O0Q3py+PWPK+dXkKXCGBRYUMpLmQity5OsjtJd6FmQRJOiBnJThdJ0x0L34c/E2bcO8LO/MfTAc F1KihfwPdPHr5m7nWRxALwf0MxgJSZETKEDm9Sq3awm5/HuxzzHSmqETnR39MgQhUxWE2/19a0l If8Ivo8GF09NpOeGB5XQpnTgBdh6IodnxnkiP+AbsgUxrHry3uO1xhWOBg0kvdi+GdmCa+TYock Er3mEFdG8b1Kt2IpuFH2NwdVd0mkE3YEg1jPjLaUNyxHURnq7dVYRDGMMUdaJkzedzOBBolSfRh nC1K5M9GJMBhSb9h9cd3WpbV3e+tVTTcUl/IlZsMmMm2fVaxTojEyOsA8mPjkz56q4HZ7EGuaOZ Q/EWOJ3GfhgoEcDYXLlCkues/48WQTxk8t1KeQsx4ZIx9GY2tKc+7aqxiJYX+Og7wxgGKsFcEq2 93eFQ5dpm5FJXgjI+xwpHqTPC52zmmBOJJO5o75Izee59H0LYnJbViuXx8W2p0mDJmE6UgW//qi p5sZBADQ= X-Received: by 2002:a05:600c:83ca:b0:4aa:2339:a375 with SMTP id 5b1f17b1804b1-4bb55a4d9b3mr3039565e9.13.1794509725074; Thu, 12 Nov 2026 10:55:25 -0800 (PST) Received: from alchark-surface.localdomain (bba-86-98-194-229.alshamil.net.ae. [86.98.194.229]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4bb4e28d0b2sm71734755e9.7.2026.11.12.10.55.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Nov 2026 10:55:24 -0800 (PST) From: Alexey Charkov Date: Thu, 12 Nov 2026 22:55:09 +0400 Subject: [PATCH v6 2/4] clocksource/drivers/timer-vt8500: Prepare for watchdog functionality X-Archived-By: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20261112-vt8500-timer-updates-v6-2-fd1cea645d1f@gmail.com> References: <20261112-vt8500-timer-updates-v6-0-fd1cea645d1f@gmail.com> In-Reply-To: <20261112-vt8500-timer-updates-v6-0-fd1cea645d1f@gmail.com> To: Alexey Charkov , Krzysztof Kozlowski , Daniel Lezcano , Thomas Gleixner , Wim Van Sebroeck , Guenter Roeck Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=8797; i=alchark@gmail.com; h=from:subject:message-id; bh=eTM/WsmEdC1BDL2OwSEVypWxkzCYcnQpKYeJZ89EVmc=; b=owGbwMvMwCW2adGNfoHIK0sZT6slMWR94566XlXfyt5YU4D3e8shpcjrkyf/4prw28f9l9Ryl UePU391dkxkYRDjYrAUU2SZ+22J7VQjvlm7PDy+wsxhZQIZIi3SwAAELAx8uYl5pUY6Rnqm2oZ6 hkY6xjpGDFycAjDV66wY/hf0zfVcPO24hmGOV2tfzS//X7HcHel3ryqpuQtcjXNz2c7IcGNPz4N DuicPNZ5o/bKCd4esjsUxg20XOc6b962YrfbbkhcA X-Developer-Key: i=alchark@gmail.com; a=openpgp; fpr=9DF6A43D95320E9ABA4848F5B2A2D88F1059D4A5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20261112_105528_256104_D0408853 X-CRM114-Status: GOOD ( 33.60 ) X-Spam-Score: -2.1 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=4.0.1 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 VIA/WonderMedia system timer can generate a watchdog reset when its clocksource counter matches the value in the match register 0 and watchdog function is enabled. For this to work, obviously the clock event device must use a different match register (1~3) and respective interrupt. Check if at least two interrupts are provided by the device tree, then use match register 1 for system clock events and reserve match register 0 for the watchdog. Keep match register 0 for clock events on device trees that list a single interrupt, and offer no watchdog there. Instantiate the watchdog as an auxiliary device of the timer from a platform driver bound to the timer node, as the timer itself comes up too early to have a struct device. Share what the watchdog needs through a new header, include/clocksource/vt8500-timer.h. Unmap the registers if the timer interrupt is missing, so that no watchdog gets created on a timer whose counter never started. Signed-off-by: Alexey Charkov --- MAINTAINERS | 1 + drivers/clocksource/Kconfig | 1 + drivers/clocksource/timer-vt8500.c | 127 ++++++++++++++++++++++++++++++++++--- include/clocksource/vt8500-timer.h | 22 +++++++ 4 files changed, 142 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 27461b2161a7..acc4d2915460 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4010,6 +4010,7 @@ F: drivers/tty/serial/vt8500_serial.c F: drivers/video/fbdev/vt8500lcdfb.* F: drivers/video/fbdev/wm8505fb* F: drivers/video/fbdev/wmt_ge_rops.* +F: include/clocksource/vt8500-timer.h ARM/ZTE ZX29 SOC SUPPORT M: Stefan Dösinger diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index da83483296d5..d060863fcc07 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -197,6 +197,7 @@ config TEGRA186_TIMER config VT8500_TIMER bool "VT8500 timer driver" if COMPILE_TEST depends on HAS_IOMEM + select AUXILIARY_BUS help Enables support for the VT8500 driver. diff --git a/drivers/clocksource/timer-vt8500.c b/drivers/clocksource/timer-vt8500.c index c4694cf8bea6..b54ed5d692d7 100644 --- a/drivers/clocksource/timer-vt8500.c +++ b/drivers/clocksource/timer-vt8500.c @@ -11,6 +11,7 @@ * Alexey Charkov. Minor changes have been made for Device Tree Support. */ +#include #include #include #include @@ -21,9 +22,9 @@ #include #include #include +#include -#define VT8500_TIMER_OFFSET 0x0100 -#define VT8500_TIMER_HZ 3000000 +#include #define TIMER_MATCH_REG(x) (4 * (x)) #define TIMER_COUNT_REG 0x0010 /* clocksource counter */ @@ -53,6 +54,9 @@ static void __iomem *regbase; +/* Which match register to use for the system timer */ +static unsigned int sys_timer_ch; + static u64 vt8500_timer_read(struct clocksource *cs) { int loops = msecs_to_loops(10); @@ -72,21 +76,26 @@ static struct clocksource clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 vt8500_timer_next(u64 cycles) +{ + return clocksource.read(&clocksource) + cycles; +} + static int vt8500_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { int loops = msecs_to_loops(10); - u64 alarm = clocksource.read(&clocksource) + cycles; + u64 alarm = vt8500_timer_next(cycles); - while (readl(regbase + TIMER_ACC_STS_REG) & TIMER_ACC_WR_MATCH(0) && - --loops) + while (readl(regbase + TIMER_ACC_STS_REG) & + TIMER_ACC_WR_MATCH(sys_timer_ch) && --loops) cpu_relax(); - writel((unsigned long)alarm, regbase + TIMER_MATCH_REG(0)); + writel((unsigned long)alarm, regbase + TIMER_MATCH_REG(sys_timer_ch)); if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA) return -ETIME; - writel(TIMER_INT_EN_MATCH(0), regbase + TIMER_INT_EN_REG); + writel(TIMER_INT_EN_MATCH(sys_timer_ch), regbase + TIMER_INT_EN_REG); return 0; } @@ -128,16 +137,29 @@ static int __init vt8500_timer_init(struct device_node *np) return -ENXIO; } - timer_irq = irq_of_parse_and_map(np, 0); + /* + * The watchdog function is available on channel 0, but not on other + * channels. So to use it, the clock event device must use a different + * match register (1~3) and respective interrupt. + * + * Check if at least two interrupts are provided by the device tree, + * then use match register 1 for system clock events and reserve match + * register 0 for the watchdog. + */ + sys_timer_ch = of_irq_count(np) > 1 ? 1 : 0; + + timer_irq = irq_of_parse_and_map(np, sys_timer_ch); if (!timer_irq) { pr_err("%s: Missing irq description in Device Tree\n", __func__); + iounmap(regbase); + regbase = NULL; return -EINVAL; } writel(TIMER_CTRL_ENABLE, regbase + TIMER_CTRL_REG); writel(TIMER_STATUS_CLEARALL, regbase + TIMER_STATUS_REG); - writel(~0, regbase + TIMER_MATCH_REG(0)); + writel(~0, regbase + TIMER_MATCH_REG(sys_timer_ch)); ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); if (ret) { @@ -163,4 +185,91 @@ static int __init vt8500_timer_init(struct device_node *np) return 0; } +static void vt8500_timer_aux_uninit(void *data) +{ + auxiliary_device_uninit(data); +} + +static void vt8500_timer_aux_delete(void *data) +{ + auxiliary_device_delete(data); +} + +static void vt8500_timer_aux_release(struct device *dev) +{ + struct vt8500_wdt_info *wdt_info; + struct auxiliary_device *auxdev; + + auxdev = container_of(dev, struct auxiliary_device, dev); + wdt_info = container_of(auxdev, struct vt8500_wdt_info, auxdev); + kfree(wdt_info); +} + +/* + * This probe gets called after vt8500_timer_init(), which leaves regbase set + * only once the clocksource counter is running: that counter and match + * register 0 are all the watchdog needs, even if registering the clocksource + * or the clock event device failed afterwards. Create the watchdog device as + * a child, since the registers are shared. + */ +static int vt8500_timer_probe(struct platform_device *pdev) +{ + struct vt8500_wdt_info *wdt_info; + struct device *dev = &pdev->dev; + int ret; + + if (!regbase) + return dev_err_probe(dev, -ENODEV, + "Timer not initialized, cannot create watchdog\n"); + + if (!sys_timer_ch) { + dev_info(dev, "Not enabling watchdog: only one irq was given\n"); + return 0; + } + + wdt_info = kzalloc_obj(*wdt_info); + if (!wdt_info) + return -ENOMEM; + + wdt_info->timer_next = &vt8500_timer_next; + wdt_info->regbase = regbase; + wdt_info->auxdev.name = "vt8500-wdt"; + wdt_info->auxdev.dev.parent = dev; + wdt_info->auxdev.dev.release = &vt8500_timer_aux_release; + + ret = auxiliary_device_init(&wdt_info->auxdev); + if (ret) { + kfree(wdt_info); + return ret; + } + + ret = devm_add_action_or_reset(dev, vt8500_timer_aux_uninit, + &wdt_info->auxdev); + if (ret) + return ret; + + ret = auxiliary_device_add(&wdt_info->auxdev); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, vt8500_timer_aux_delete, + &wdt_info->auxdev); +} + +static const struct of_device_id vt8500_timer_of_match[] = { + { .compatible = "via,vt8500-timer", }, + {}, +}; + +static struct platform_driver vt8500_timer_driver = { + .probe = vt8500_timer_probe, + .driver = { + .name = "vt8500-timer", + .of_match_table = vt8500_timer_of_match, + .suppress_bind_attrs = true, + }, +}; + +builtin_platform_driver(vt8500_timer_driver); + TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/include/clocksource/vt8500-timer.h b/include/clocksource/vt8500-timer.h new file mode 100644 index 000000000000..956863d50d02 --- /dev/null +++ b/include/clocksource/vt8500-timer.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef CLOCKSOURCE_VT8500_TIMER_H_ +#define CLOCKSOURCE_VT8500_TIMER_H_ + +#include +#include + +#define VT8500_TIMER_HZ 3000000 + +/** + * struct vt8500_wdt_info - timer resources shared with the watchdog + * @auxdev: auxiliary device the watchdog driver binds to + * @timer_next: returns the clocksource counter value @cycles from now + * @regbase: timer register block; the watchdog uses match register 0 + */ +struct vt8500_wdt_info { + struct auxiliary_device auxdev; + u64 (*timer_next)(u64 cycles); + void __iomem *regbase; +}; + +#endif /* CLOCKSOURCE_VT8500_TIMER_H_ */ -- 2.56.0