From nobody Sun Feb 8 17:22:03 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2EA62F3C2C; Tue, 11 Nov 2025 09:30:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762853430; cv=none; b=NXfFGrcoVPMQN72GWt9EbI84IwdDf6qHes3MTxeZsnP8BVROWClQMiYQ5Wtyf2Xf6bIaw5hXUj9Si4BHwaxGQvGVk4TNK6eBHs3BNL12hMbVqurlvKAWuB8/MXG+SGp90cpmS2b61bq8+6dBTasGXN59aOOhpQTVIQ96n8NHRCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762853430; c=relaxed/simple; bh=q/+UGrfEYnd7OS1mNZHwDDrVEYkRSR1wjd4fofnbsxU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=p821/fbMOLW9h8/Lmnm8drQkb/KqAtUXogWwwWOtvWbxKeyHw3BCMTOgkRlU43BUIR3gFCLz7tdxngWraEoTqz+6gk7YDVSjcN/nTPCmz+IEQCjoXQGGgeaZPDzd8/F/gbv8K9nydMFGU3n7XvCg888kdw3BkuPlxXbdBdFwlI0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=K6pAVydt; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="K6pAVydt" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 5AB9U03H03459977, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1762853400; bh=T26tsWFQAHQcHBEFzzxd44dLBhgLcJCE21QiVXnNjNQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=K6pAVydtCDPifWvldfN44U6R18krME3PQsHIAE4c70kfe9eh1nVyIFTdRG5VLClNa 3Te+iTSq01WyMCb3QZf6iW0h7iAGMGNYREQnQ4jkQ6xIdH+3k9TOyo3rnvVvpRxU4J Zh/Z4NGtcVQPt9POULd+yxIYI/u4LN4y2WGy455ZQ/tOyYAgVu4ERtRIjFSq2lDvxh 0WTFxIzM4mmTp5jpC8FwMMlHQuFTxaO4hQ3+vzXg1CVbTvs6b8/6P5AmMcMGsMeTg1 5O87lCVW/COWs3SRfWgyyXXeyw1kH679KxEUx2vlA7zvpodKGeupwFGBES6u6KCgGX u4NYYpBImT7YA== Received: from mail.realtek.com (rtkexhmbs02.realtek.com.tw[172.21.6.41]) by rtits2.realtek.com.tw (8.15.2/3.21/5.94) with ESMTPS id 5AB9U03H03459977 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 11 Nov 2025 17:30:00 +0800 Received: from RTKEXHMBS05.realtek.com.tw (10.21.1.55) by RTKEXHMBS02.realtek.com.tw (172.21.6.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.27; Tue, 11 Nov 2025 17:30:00 +0800 Received: from RTKEXHMBS04.realtek.com.tw (10.21.1.54) by RTKEXHMBS05.realtek.com.tw (10.21.1.55) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.27; Tue, 11 Nov 2025 17:30:00 +0800 Received: from ww-haowen.ting (172.21.177.97) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server id 15.2.1544.27 via Frontend Transport; Tue, 11 Nov 2025 17:30:00 +0800 From: Hao-Wen Ting To: , CC: , , , , , , , , , , , , , Subject: [PATCH 1/2] dt-bindings: timer: Add Realtek SYSTIMER binding Date: Tue, 11 Nov 2025 17:29:58 +0800 Message-ID: <20251111092959.616089-2-haowen.ting@realtek.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251111092959.616089-1-haowen.ting@realtek.com> References: <20251111092959.616089-1-haowen.ting@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add device tree binding documentation for the Realtek SYSTIMER, a 64-bit timer that can be used as a tick broadcast timer on multi-core Realtek SoCs. The SYSTIMER remains active during deep CPU idle states where local timers are powered off, allowing all CPUs to enter power-cut idle states simultaneously for improved power efficiency. The timer operates at a fixed 1MHz frequency and supports oneshot mode for tick broadcast functionality. This binding defines the required properties for memory-mapped register access and interrupt configuration needed by the timer driver. Signed-off-by: Hao-Wen Ting --- .../bindings/timer/realtek,systimer.yaml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/realtek,systime= r.yaml diff --git a/Documentation/devicetree/bindings/timer/realtek,systimer.yaml = b/Documentation/devicetree/bindings/timer/realtek,systimer.yaml new file mode 100644 index 000000000000..28ab9b91f45d --- /dev/null +++ b/Documentation/devicetree/bindings/timer/realtek,systimer.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/realtek,systimer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Realtek SYSTIMER + +maintainers: + - Hao-Wen Ting + +description: | + The Realtek SYSTIMER is a 64-bit timer that can be used as a tick + broadcast timer on multi-core Realtek SoCs. It remains active during + deep CPU idle states where local timers are powered off, allowing all + CPUs to enter power-cut idle states simultaneously for better power + efficiency. + + The timer operates at a fixed 1MHz frequency and supports oneshot mode + for tick broadcast functionality. + +properties: + compatible: + const: realtek,systimer + + reg: + description: | + Physical base address and length of the timer's memory mapped + registers. The register range contains the 64-bit timestamp counter, + compare value registers, control and status registers. + maxItems: 1 + + interrupts: + description: | + Timer interrupt specifier. This interrupt is triggered when the + timer compare value matches the current timestamp counter. + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + systimer: systimer@89420 { + compatible =3D "realtek,systimer"; + reg =3D <0x89420 0x18>; + interrupts =3D ; + }; --=20 2.34.1 From nobody Sun Feb 8 17:22:03 2026 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3BDD62EDD64; Tue, 11 Nov 2025 09:30:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762853429; cv=none; b=BDOCIqXcvGidV+4bG5Sy8kYgv9xDcsLWp6oIkB46MmIfQd1z/9i875smzAfuiOAFovDqtcccznwBWejV2R6qKA02BGQMEBtfHoL+QLTDpRR30RBHTs2zreBMQRdA7+mXJM3OabnyhFdmO+iepSD/nga2gHOSm082782TQ+S+24c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762853429; c=relaxed/simple; bh=YNIR2HlnxpUswWCTo+IodSzPW2/A6glWE3H9lfSiYcw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m42sRcFnemYo9PLpAt+MX8PpIF96Dr9CxpvyU7sMLytUFDEvE66pSnGGwXVCfiEJ/m34W4tlrHXQ3IQlx0qvA2ZD3znJxP8SScSgELjD+QvQfk+SKKwWwzRwxDgbij2AJd1BCqGLpCOuy2cUwnkLj7N2M61MKkRiE/La41Y8Sdw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b=oceqHVNZ; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com header.b="oceqHVNZ" X-SpamFilter-By: ArmorX SpamTrap 5.80 with qID 5AB9U0dZ43459979, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim; t=1762853400; bh=UcSEBri+FPhJDXIS60ZlyutMie3hRBhbsDhcL2GBMgM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=oceqHVNZAnef8YW9gcWR2DnlgaFOlynXj/JnNyj75FJZ3Vs3E33xTsAjrq4SrixK+ eJVF/ocEoGFKYQUbIpSIm8YWcDBdqfYMkkgn3P1+Ls+rrT5WjFdgvt+m28mmZn11V9 yyT43M+MefAZRcE0KS45tqnQrBFG7xESigNYCKBROcUqHLfbLz9ji4xaSPYaaVgnmN wgeNvckNYNOUsgjWpy5rmUYX1L2/txHX1BEweLBNmKExPRi7Yn3F8RK8A3bKrKmqdQ MXWmGWshKE70k5DR054YbX24DAaXmc873NATvzPNhgkrlGtZW3LxMOAO91qt4hruID i10WbmWz6GF0w== Received: from mail.realtek.com (rtkexhmbs03.realtek.com.tw[10.21.1.53]) by rtits2.realtek.com.tw (8.15.2/3.21/5.94) with ESMTPS id 5AB9U0dZ43459979 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 11 Nov 2025 17:30:00 +0800 Received: from RTKEXHMBS04.realtek.com.tw (10.21.1.54) by RTKEXHMBS03.realtek.com.tw (10.21.1.53) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.27; Tue, 11 Nov 2025 17:30:00 +0800 Received: from ww-haowen.ting (172.21.177.97) by RTKEXHMBS04.realtek.com.tw (10.21.1.54) with Microsoft SMTP Server id 15.2.1544.27 via Frontend Transport; Tue, 11 Nov 2025 17:30:00 +0800 From: Hao-Wen Ting To: , CC: , , , , , , , , , , , , , Subject: [PATCH 2/2] clocksource: Add Realtek systimer as tick broadcast driver Date: Tue, 11 Nov 2025 17:29:59 +0800 Message-ID: <20251111092959.616089-3-haowen.ting@realtek.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251111092959.616089-1-haowen.ting@realtek.com> References: <20251111092959.616089-1-haowen.ting@realtek.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a tick broadcast timer driver for Realtek SoCs. On Realtek platforms, CPUs can enter deep idle states (C-states) where the local timer is stopped and powered off. Without a global tick broadcast timer, one CPU must remain awake to wake up the others, preventing all CPUs from entering deep idle simultaneously. This driver provides a tick broadcast timer which remains active during deep idle states. This allows all CPUs to enter power-cut idle states simultaneously, significantly reducing overall power consumption. The timer operates at 1MHz and supports oneshot mode. Signed-off-by: Hao-Wen Ting --- MAINTAINERS | 5 + drivers/clocksource/Kconfig | 10 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-realtek.c | 173 ++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 drivers/clocksource/timer-realtek.c diff --git a/MAINTAINERS b/MAINTAINERS index c7a116b795d5..59dfd7543c39 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28395,3 +28395,8 @@ S: Buried alive in reporters T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git F: * F: */ + +REALTEK SYSTIMER DRIVER +M: Hao-Wen Ting +S: Maintained +F: drivers/clocksource/timer-realtek.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index ffcd23668763..e86905378f82 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -782,4 +782,14 @@ config NXP_STM_TIMER Enables the support for NXP System Timer Module found in the s32g NXP platform series. =20 +config RTK_SYSTIMER + bool "Realtek SYSTIMER support" + depends on OF + select TIMER_OF + help + This enables the global tick-broadcast timer on Realtek platforms. + If your Realtek platform supports power-cut level CPU idle states, + enabling this timer allows all CPUs to enter power-cut simultaneously + to achieve lower power consumption. + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index ec4452ee958f..b46376af6b49 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -95,3 +95,4 @@ obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) +=3D timer-loongson1-p= wm.o obj-$(CONFIG_EP93XX_TIMER) +=3D timer-ep93xx.o obj-$(CONFIG_RALINK_TIMER) +=3D timer-ralink.o obj-$(CONFIG_NXP_STM_TIMER) +=3D timer-nxp-stm.o +obj-$(CONFIG_RTK_SYSTIMER) +=3D timer-realtek.o diff --git a/drivers/clocksource/timer-realtek.c b/drivers/clocksource/time= r-realtek.c new file mode 100644 index 000000000000..3f3ab276aa86 --- /dev/null +++ b/drivers/clocksource/timer-realtek.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Realtek Semiconductor Corp. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include "timer-of.h" + +#define ENBL 1 +#define DSBL 0 + +#define SYSTIMER_RATE 1000000 +#define SYSTIMER_MIN_DELTA 0x64 +#define SYSTIMER_MAX_DELTA ULONG_MAX + +/* SYSTIMER Register Offset (RTK Internal Use) */ +#define TS_LW_OFST 0x0 +#define TS_HW_OFST 0x4 +#define TS_CMP_VAL_LW_OFST 0x8 +#define TS_CMP_VAL_HW_OFST 0xC +#define TS_CMP_CTRL_OFST 0x10 +#define TS_CMP_STAT_OFST 0x14 + +/* SYSTIMER CMP CTRL REG Mask */ +#define TS_CMP_EN_MASK 0x1 +#define TS_WR_EN0_MASK 0x2 + +static void __iomem *systimer_base; + +static u64 rtk_ts64_read(void) +{ + u64 ts; + u32 low, high; + + /* Caution: Read LSB word (TS_LW_OFST) first then MSB (TS_HW_OFST) */ + low =3D readl(systimer_base + TS_LW_OFST); + high =3D readl(systimer_base + TS_HW_OFST); + + pr_debug("64bit-TS:HW=3D0x%08x,LW=3D0x%08x\n", high, low); + ts =3D ((u64)high << 32) | low; + + return ts; +} + +static void rtk_cmp_value_write(u64 value) +{ + u32 high, low; + + low =3D value & 0xFFFFFFFF; + high =3D value >> 32; + pr_debug("Write 64bit-CMP:HW=3D0x%08x,LW=3D0x%08x\n", high, low); + + writel(high, systimer_base + TS_CMP_VAL_HW_OFST); + writel(low, systimer_base + TS_CMP_VAL_LW_OFST); +} + +static inline void rtk_cmp_en_write(bool cmp_en) +{ + u32 val; + + val =3D TS_WR_EN0_MASK; + if (cmp_en =3D=3D ENBL) + val |=3D TS_CMP_EN_MASK; + + writel(val, systimer_base + TS_CMP_CTRL_OFST); + pr_debug("Write TS CMP CTRL =3D 0x%08x\n", val); +} + +static int rtk_syst_clkevt_next_ktime(ktime_t expires, + struct clock_event_device *clkevt) +{ + u64 cmp_val; + unsigned long flags; + ktime_t now =3D ktime_get(); + s64 delta_ns =3D ktime_to_ns(ktime_sub(expires, now)); + u64 delta_us =3D delta_ns / 1000; + + pr_debug("delta_ns =3D %lld, clkevt.min_delta_ns =3D %llu\n", + delta_ns, clkevt->min_delta_ns); + + if (delta_ns <=3D (s64)clkevt->min_delta_ns) { + delta_ns =3D clkevt->min_delta_ns; + delta_us =3D delta_ns / 1000; + pr_debug("Clamping delta_ns to min_delta_ns\n"); + } + + rtk_cmp_en_write(DSBL); + local_irq_save(flags); + cmp_val =3D rtk_ts64_read(); + + /* Set CMP value to current timestamp plus delta_us */ + rtk_cmp_value_write(cmp_val + delta_us); + rtk_cmp_en_write(ENBL); + local_irq_restore(flags); + return 0; +} + +static irqreturn_t rtk_ts_match_intr_handler(int irq, void *dev_id) +{ + u32 val; + void __iomem *reg_base; + struct clock_event_device *clkevt =3D dev_id; + + /* Disable TS CMP Match */ + rtk_cmp_en_write(DSBL); + + /* Clear TS CMP INTR */ + reg_base =3D systimer_base + TS_CMP_STAT_OFST; + val =3D readl(reg_base) & TS_CMP_EN_MASK; + writel(val | TS_CMP_EN_MASK, reg_base); + + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static int rtk_syst_shutdown(struct clock_event_device *clkevt) +{ + void __iomem *reg_base; + u64 cmp_val =3D 0; + + /* Disable TS CMP Match */ + rtk_cmp_en_write(DSBL); + /* Set compare value to 0 */ + rtk_cmp_value_write(cmp_val); + + /* Clear TS CMP INTR */ + reg_base =3D systimer_base + TS_CMP_STAT_OFST; + writel(TS_CMP_EN_MASK, reg_base); + return 0; +} + +static struct timer_of _to =3D { + .flags =3D TIMER_OF_IRQ | TIMER_OF_BASE, + + .clkevt =3D { + .name =3D "rtk-clkevt", + .rating =3D 300, + .cpumask =3D cpu_possible_mask, + .features =3D CLOCK_EVT_FEAT_DYNIRQ | + CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_KTIME, + .set_next_ktime =3D rtk_syst_clkevt_next_ktime, + .set_state_oneshot =3D rtk_syst_shutdown, + .set_state_shutdown =3D rtk_syst_shutdown + }, + + .of_irq =3D { + .flags =3D IRQF_TIMER | IRQF_IRQPOLL, + .handler =3D rtk_ts_match_intr_handler + }, +}; + +static int __init rtk_systimer_init(struct device_node *node) +{ + int ret; + + ret =3D timer_of_init(node, &_to); + if (ret) + return ret; + + systimer_base =3D timer_of_base(&_to); + clockevents_config_and_register(&_to.clkevt, SYSTIMER_RATE, + SYSTIMER_MIN_DELTA, SYSTIMER_MAX_DELTA); + + pr_info("Realtek SYSTIMER registered\n"); + return 0; +} + +TIMER_OF_DECLARE(rtk_systimer, "realtek,systimer", rtk_systimer_init); --=20 2.34.1