* [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 1:10 ` [PATCH v7 1/6] clocksource/drivers/exynos_mct: Don't register as a sched_clock on arm64 Will McVicker
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
This series adds support to build the Arm64 Exynos MCT driver as a module.
This is only possible on Arm64 SoCs since they can use the Arm architected
timer as the clocksource. Once the Exynos MCT module is loaded and the device
probes, the MCT is used as the wakeup source for the arch_timer to ensure the
device can wakeup from the "c2" idle state.
These patches are originally from the downstream Pixel 6 (gs101) kernel found
at [1] and have been adapted for upstream. Not only has the Exynos MCT driver
been shipping as a module in the field with Android, but I've also tested this
series with the upstream kernel on my Pixel 6 Pro.
To the driver changes (both as built-in and as module) on Pixel 6 Pro, I ran
these tests:
# cat /proc/interrupts | grep -E "mct|arch_timer"
23: 6823 10938 7795 5607 8935 12828 21947 2200 GICv3 30 Level arch_timer
104: 1 0 0 0 0 0 0 0 GICv3 785 Level mct_comp_irq
105: 547 0 0 0 0 0 0 0 GICv3 789 Level mct_tick0
106: 0 1333 0 0 0 0 0 0 GICv3 790 Level mct_tick1
107: 0 0 1467 0 0 0 0 0 GICv3 791 Level mct_tick2
108: 0 0 0 583 0 0 0 0 GICv3 792 Level mct_tick3
109: 0 0 0 0 206 0 0 0 GICv3 793 Level mct_tick4
110: 0 0 0 0 0 153 0 0 GICv3 794 Level mct_tick5
111: 0 0 0 0 0 0 13 0 GICv3 795 Level mct_tick6
112: 0 0 0 0 0 0 0 87 GICv3 796 Level mct_tick7
# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
arch_sys_counter
When built and loaded as a module, you can verify via:
# lsmod | grep exynos_mct
exynos_mct 20480 9
I also compile tested for ARCH=ARM DEFCONFIG=multi_v7_defconfig with the
following debug configs to ensure the section mismatches are fixed:
CONFIG_DEBUG_SECTION_MISMATCH=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
Any additional testing is much appreciated!
Thanks,
Will
Note1, instructions to build and flash a Pixel 6 device with the upstream
kernel can be found at [2].
Note2, this series is based off of krzk/for-next commit bca42080637c (Merge
branch 'next/drivers-late' into for-next).
[1] https://android.googlesource.com/kernel/gs/+log/refs/heads/android-gs-raviole-5.10-android12-d1
[2] https://gitlab.com/LinaroLtd/googlelt/pixelscripts/-/blob/clo/main/README.md?ref_type=heads
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Donghoon Yu <hoony.yu@samsung.com>
Cc: Rob Herring <robh@kernel.org>
Cc: John Stultz <jstultz@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Youngmin Nam <youngmin.nam@samsung.com>
Cc: Peter Griffin <peter.griffin@linaro.org>
Cc: Tudor Ambarus <tudor.ambarus@linaro.org>
Cc: André Draszik <andre.draszik@linaro.org>
Cc: Will Deacon <will@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: "Russell King (Oracle)" <linux@armlinux.org.uk>
Cc: linux-samsung-soc@vger.kernel.org
Cc: kernel-team@android.com
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
Changes in v7:
- Dropped v6 patch 1/6 that removed __init from register_current_timer_delay()
- Refactored the init function in patch 4/7 to handle the case of registering
the timer delay function for ARM 32-bit systems from an __init tagged function.
This addresses the original section mismatch issues reported in v4.
- Rebased series onto base commit bca42080637c (Merge branch
'next/drivers-late' into for-next).
Changes in v6:
- Updated module support to only register the MCT driver as a platform driver
for ARM64 to ensure ARM 32-bit SoCs continue to probe the MCT driver very
early.
- Squashed the percpu fix suggested by Marek Szyprowski in
https://lore.kernel.org/all/20250827102645.1964659-1-m.szyprowski@samsung.com/
together with patch 3/6.
Changes in v5:
- Fixed section mismatch issues.
- Addressed Arnd's concerns regarding potential issues with unloading and/or
unbinding the driver.
- Fixed SoB concerns to clarify the development chain from AOSP to Linux.
- Pulled in https://lore.kernel.org/all/20250827102645.1964659-1-m.szyprowski@samsung.com/
to limit percpu interrupts only for ARM64.
Changes in v4:
- Missed the "v3" string in the previous series for the actual patches
- Re-generated patches with --base a15edf91668beefdb5171c53fa698c9b43dd1e0d
for kernel test robot.
Changes in v3:
- Rebased on top of Daniel's timer modularization prep series [3] and
krzk/for-next commit a15edf91668b ("Merge branch 'next/dt64' into
for-next")
- Added owner references to Exynos MCT clocksource and clockevent objects.
- Dropped #ifdef MODULE conditional section in favor of just using
module_platform_driver() which will properly handle setting up the
of_device_id table based on if the driver is built-in or a module.
- Update commit message for patch 2 based on John's feedback.
- Dropped DT change from v2 as it was picked up by Krzysztof for CPU Idle.
Changes in v2:
- Re-worked patch v1 5 based on Rob Herring's review to use the compatible
data for retrieving the mct_init function pointer.
- Updated the Kconfig logic to disallow building the Exynos MCT driver as
a module for ARM32 configurations based on Krzysztof Kozlowski's findings.
- Added comments and clarified commit messages in patches 1 and 2 based on
reviews from John Stultz and Youngmin Nam.
- Fixed an issue found during testing that resulted in the device getting
stuck on boot. This is included in v2 as patch 5.
- Collected *-by tags
- Rebased to the latest linux-next/master.
---
Donghoon Yu (1):
clocksource/drivers/exynos_mct: Don't register as a sched_clock on
arm64
Hosung Kim (1):
clocksource/drivers/exynos_mct: Set percpu local timer interrupts for
ARM64
Will McVicker (4):
clocksource/drivers/exynos_mct: Fix uninitialized irq name warning
clocksource/drivers/exynos_mct: Refactor driver init
clocksource/drivers/exynos_mct: Add module support for ARM64
arm64: exynos: Drop select CLKSRC_EXYNOS_MCT
arch/arm64/Kconfig.platforms | 1 -
drivers/clocksource/Kconfig | 3 +-
drivers/clocksource/exynos_mct.c | 255 ++++++++++++++++++++++---------
3 files changed, 182 insertions(+), 77 deletions(-)
base-commit: bca42080637ce3a21092fc0f7d5411e853b0c3b3
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v7 1/6] clocksource/drivers/exynos_mct: Don't register as a sched_clock on arm64
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 1:10 ` [PATCH v7 2/6] clocksource/drivers/exynos_mct: Set percpu local timer interrupts for ARM64 Will McVicker
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
From: Donghoon Yu <hoony.yu@samsung.com>
The MCT register is unfortunately very slow to access, but importantly
does not halt in the c2 idle state. So for ARM64, we can improve
performance by not registering the MCT for sched_clock, allowing the
system to use the faster ARM architected timer for sched_clock instead.
The MCT is still registered as a clocksource, and a clockevent in order
to be a wakeup source for the arch_timer to exit the "c2" idle state.
Since ARM32 SoCs don't have an architected timer, the MCT must continue
to be used for sched_clock. Detailed discussion on this topic can be
found at [1].
[1] https://lore.kernel.org/linux-samsung-soc/1400188079-21832-1-git-send-email-chirantan@chromium.org/
[Original commit from https://android.googlesource.com/kernel/gs/+/630817f7080e92c5e0216095ff52f6eb8dd00727
Signed-off-by: Donghoon Yu <hoony.yu@samsung.com>
Signed-off-by: Youngmin Nam <youngmin.nam@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: John Stultz <jstultz@google.com>
Tested-by: Youngmin Nam <youngmin.nam@samsung.com> # AOSP -> Linux port
Reviewed-by: Youngmin Nam <youngmin.nam@samsung.com> # AOSP -> Linux port
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
drivers/clocksource/exynos_mct.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index da09f467a6bb..96361d5dc57d 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -219,12 +219,18 @@ static struct clocksource mct_frc = {
.resume = exynos4_frc_resume,
};
+/*
+ * Since ARM devices do not have an architected timer, they need to continue
+ * using the MCT as the main clocksource for timekeeping, sched_clock, and the
+ * delay timer. For AARCH64 SoCs, the architected timer is the preferred
+ * clocksource due to it's superior performance.
+ */
+#if defined(CONFIG_ARM)
static u64 notrace exynos4_read_sched_clock(void)
{
return exynos4_read_count_32();
}
-#if defined(CONFIG_ARM)
static struct delay_timer exynos4_delay_timer;
static cycles_t exynos4_read_current_timer(void)
@@ -250,12 +256,13 @@ static int __init exynos4_clocksource_init(bool frc_shared)
exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer;
exynos4_delay_timer.freq = clk_rate;
register_current_timer_delay(&exynos4_delay_timer);
+
+ sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
#endif
if (clocksource_register_hz(&mct_frc, clk_rate))
panic("%s: can't register clocksource\n", mct_frc.name);
- sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
return 0;
}
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 2/6] clocksource/drivers/exynos_mct: Set percpu local timer interrupts for ARM64
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
2025-12-05 1:10 ` [PATCH v7 1/6] clocksource/drivers/exynos_mct: Don't register as a sched_clock on arm64 Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 1:10 ` [PATCH v7 3/6] clocksource/drivers/exynos_mct: Fix uninitialized irq name warning Will McVicker
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel,
Hosung Kim
From: Hosung Kim <hosung0.kim@samsung.com>
To allow the CPU to handle it's own clock events, we need to set the
IRQF_PERCPU flag. This prevents the local timer interrupts from
migrating to other CPUs. This is only supported on ARM64.
Signed-off-by: Hosung Kim <hosung0.kim@samsung.com>
[Original commit from https://android.googlesource.com/kernel/gs/+/03267fad19f093bac979ca78309483e9eb3a8d16]
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Reviewed-by: Youngmin Nam <youngmin.nam@samsung.com>
Tested-by: Youngmin Nam <youngmin.nam@samsung.com>
Suggested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/all/20250827102645.1964659-1-m.szyprowski@samsung.com/
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
drivers/clocksource/exynos_mct.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 96361d5dc57d..1429b9d03a58 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -596,7 +596,9 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
irq_set_status_flags(mct_irq, IRQ_NOAUTOEN);
if (request_irq(mct_irq,
exynos4_mct_tick_isr,
- IRQF_TIMER | IRQF_NOBALANCING,
+ IRQF_TIMER | IRQF_NOBALANCING |
+ (IS_ENABLED(CONFIG_ARM64) ?
+ IRQF_PERCPU : 0),
pcpu_mevt->name, pcpu_mevt)) {
pr_err("exynos-mct: cannot register IRQ (cpu%d)\n",
cpu);
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 3/6] clocksource/drivers/exynos_mct: Fix uninitialized irq name warning
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
2025-12-05 1:10 ` [PATCH v7 1/6] clocksource/drivers/exynos_mct: Don't register as a sched_clock on arm64 Will McVicker
2025-12-05 1:10 ` [PATCH v7 2/6] clocksource/drivers/exynos_mct: Set percpu local timer interrupts for ARM64 Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 1:10 ` [PATCH v7 4/6] clocksource/drivers/exynos_mct: Refactor driver init Will McVicker
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
The Exynos MCT driver doesn't set the clocksource name until the CPU
hotplug state is setup which happens after the IRQs are requested. This
results in an empty IRQ name which leads to the below warning at
proc_create() time. When this happens, the userdata partition fails to
mount and the device gets stuck in an endless loop printing the error:
root '/dev/disk/by-partlabel/userdata' doesn't exist or does not contain a /dev.
To fix this, we just need to initialize the name before requesting the
IRQs.
Warning from Pixel 6 kernel log:
[ T430] name len 0
[ T430] WARNING: CPU: 6 PID: 430 at fs/proc/generic.c:407 __proc_create+0x258/0x2b4
[ T430] Modules linked in: dwc3_exynos(E+)
[ T430] ufs_exynos(E+) phy_exynos_ufs(E)
[ T430] phy_exynos5_usbdrd(E) exynos_usi(E+) exynos_mct(E+) s3c2410_wdt(E)
[ T430] arm_dsu_pmu(E) simplefb(E)
[ T430] CPU: 6 UID: 0 PID: 430 Comm: (udev-worker) Tainted:
... 6.14.0-next-20250331-4k-00008-g59adf909e40e #1 ...
[ T430] Tainted: [W]=WARN, [E]=UNSIGNED_MODULE
[ T430] Hardware name: Raven (DT)
[...]
[ T430] Call trace:
[ T430] __proc_create+0x258/0x2b4 (P)
[ T430] proc_mkdir+0x40/0xa0
[ T430] register_handler_proc+0x118/0x140
[ T430] __setup_irq+0x460/0x6d0
[ T430] request_threaded_irq+0xcc/0x1b0
[ T430] mct_init_dt+0x244/0x604 [exynos_mct ...]
[ T430] mct_init_spi+0x18/0x34 [exynos_mct ...]
[ T430] exynos4_mct_probe+0x30/0x4c [exynos_mct ...]
[ T430] platform_probe+0x6c/0xe4
[ T430] really_probe+0xf4/0x38c
[...]
[ T430] driver_register+0x6c/0x140
[ T430] __platform_driver_register+0x28/0x38
[ T430] exynos4_mct_driver_init+0x24/0xfe8 [exynos_mct ...]
[ T430] do_one_initcall+0x84/0x3c0
[ T430] do_init_module+0x58/0x208
[ T430] load_module+0x1de0/0x2500
[ T430] init_module_from_file+0x8c/0xdc
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Reviewed-by: Youngmin Nam <youngmin.nam@samsung.com>
Tested-by: Youngmin Nam <youngmin.nam@samsung.com>
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
drivers/clocksource/exynos_mct.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 1429b9d03a58..fece6bbc190e 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -465,8 +465,6 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
per_cpu_ptr(&percpu_mct_tick, cpu);
struct clock_event_device *evt = &mevt->evt;
- snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu);
-
evt->name = mevt->name;
evt->cpumask = cpumask_of(cpu);
evt->set_next_event = exynos4_tick_set_next_event;
@@ -567,6 +565,14 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
for (i = MCT_L0_IRQ; i < nr_irqs; i++)
mct_irqs[i] = irq_of_parse_and_map(np, i);
+ for_each_possible_cpu(cpu) {
+ struct mct_clock_event_device *mevt =
+ per_cpu_ptr(&percpu_mct_tick, cpu);
+
+ snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d",
+ cpu);
+ }
+
if (mct_int_type == MCT_INT_PPI) {
err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 4/6] clocksource/drivers/exynos_mct: Refactor driver init
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
` (2 preceding siblings ...)
2025-12-05 1:10 ` [PATCH v7 3/6] clocksource/drivers/exynos_mct: Fix uninitialized irq name warning Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 1:10 ` [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64 Will McVicker
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
This patch cleans up the driver a bit by
- refactoring mct_init_dt() to allow better separation of ARM 32-bit
specific code and ARM64 code. Ultimately this allows the driver to
access context data outside of mct_init_dt().
- adds driver data to distinguish the interrupt type which allows
a single driver init function.
This clean up is in preparation for modularizing the MCT driver for only
ARM64 SoCs.
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
drivers/clocksource/exynos_mct.c | 199 +++++++++++++++++++------------
1 file changed, 125 insertions(+), 74 deletions(-)
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index fece6bbc190e..922c2b519a39 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -74,13 +74,22 @@ enum {
MCT_INT_PPI
};
+/* Needs to be global for sched_clock_register() since we can't pass in data. */
static void __iomem *reg_base;
-static unsigned long clk_rate;
-static unsigned int mct_int_type;
-static int mct_irqs[MCT_NR_IRQS];
+
+struct mct_data {
+ unsigned int int_type;
+};
+
+struct mct_context {
+ const struct mct_data *drvdata;
+ unsigned long clk_rate;
+ int mct_irqs[MCT_NR_IRQS];
+};
struct mct_clock_event_device {
struct clock_event_device evt;
+ struct mct_context *ctx;
unsigned long base;
/**
* The length of the name must be adjusted if number of
@@ -89,6 +98,12 @@ struct mct_clock_event_device {
char name[11];
};
+static struct mct_clock_event_device *
+to_mct_clock_event_device(struct clock_event_device *evt)
+{
+ return container_of(evt, struct mct_clock_event_device, evt);
+}
+
static void exynos4_mct_write(unsigned int value, unsigned long offset)
{
unsigned long stat_addr;
@@ -241,7 +256,7 @@ static cycles_t exynos4_read_current_timer(void)
}
#endif
-static int __init exynos4_clocksource_init(bool frc_shared)
+static int __init exynos4_clocksource_init(struct mct_context *ctx, bool frc_shared)
{
/*
* When the frc is shared, the main processor should have already
@@ -252,18 +267,9 @@ static int __init exynos4_clocksource_init(bool frc_shared)
else
exynos4_mct_frc_start();
-#if defined(CONFIG_ARM)
- exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer;
- exynos4_delay_timer.freq = clk_rate;
- register_current_timer_delay(&exynos4_delay_timer);
-
- sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
-#endif
-
- if (clocksource_register_hz(&mct_frc, clk_rate))
+ if (clocksource_register_hz(&mct_frc, ctx->clk_rate))
panic("%s: can't register clocksource\n", mct_frc.name);
-
return 0;
}
@@ -297,7 +303,7 @@ static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles)
exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
tcon |= MCT_G_TCON_COMP0_ENABLE;
- exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
+ exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
}
static int exynos4_comp_set_next_event(unsigned long cycles,
@@ -325,17 +331,19 @@ static int mct_set_state_periodic(struct clock_event_device *evt)
return 0;
}
-static struct clock_event_device mct_comp_device = {
- .name = "mct-comp",
- .features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT,
- .rating = 250,
- .set_next_event = exynos4_comp_set_next_event,
- .set_state_periodic = mct_set_state_periodic,
- .set_state_shutdown = mct_set_state_shutdown,
- .set_state_oneshot = mct_set_state_shutdown,
- .set_state_oneshot_stopped = mct_set_state_shutdown,
- .tick_resume = mct_set_state_shutdown,
+static struct mct_clock_event_device mct_comp_device = {
+ .evt = {
+ .name = "mct-comp",
+ .features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 250,
+ .set_next_event = exynos4_comp_set_next_event,
+ .set_state_periodic = mct_set_state_periodic,
+ .set_state_shutdown = mct_set_state_shutdown,
+ .set_state_oneshot = mct_set_state_shutdown,
+ .set_state_oneshot_stopped = mct_set_state_shutdown,
+ .tick_resume = mct_set_state_shutdown,
+ },
};
static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
@@ -349,14 +357,16 @@ static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int exynos4_clockevent_init(void)
+static int exynos4_clockevent_init(struct mct_context *ctx)
{
- mct_comp_device.cpumask = cpumask_of(0);
- clockevents_config_and_register(&mct_comp_device, clk_rate,
+ struct clock_event_device *evt = &mct_comp_device.evt;
+
+ mct_comp_device.ctx = ctx;
+ evt->cpumask = cpumask_of(0);
+ clockevents_config_and_register(evt, ctx->clk_rate,
0xf, 0xffffffff);
- if (request_irq(mct_irqs[MCT_G0_IRQ], exynos4_mct_comp_isr,
- IRQF_TIMER | IRQF_IRQPOLL, "mct_comp_irq",
- &mct_comp_device))
+ if (request_irq(ctx->mct_irqs[MCT_G0_IRQ], exynos4_mct_comp_isr,
+ IRQF_TIMER | IRQF_IRQPOLL, "mct_comp_irq", evt))
pr_err("%s: request_irq() failed\n", "mct_comp_irq");
return 0;
@@ -409,18 +419,16 @@ static void exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
static int exynos4_tick_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- struct mct_clock_event_device *mevt;
+ struct mct_clock_event_device *mevt = to_mct_clock_event_device(evt);
- mevt = container_of(evt, struct mct_clock_event_device, evt);
exynos4_mct_tick_start(cycles, mevt);
return 0;
}
static int set_state_shutdown(struct clock_event_device *evt)
{
- struct mct_clock_event_device *mevt;
+ struct mct_clock_event_device *mevt = to_mct_clock_event_device(evt);
- mevt = container_of(evt, struct mct_clock_event_device, evt);
exynos4_mct_tick_stop(mevt);
exynos4_mct_tick_clear(mevt);
return 0;
@@ -428,10 +436,9 @@ static int set_state_shutdown(struct clock_event_device *evt)
static int set_state_periodic(struct clock_event_device *evt)
{
- struct mct_clock_event_device *mevt;
+ struct mct_clock_event_device *mevt = to_mct_clock_event_device(evt);
unsigned long cycles_per_jiffy;
- mevt = container_of(evt, struct mct_clock_event_device, evt);
cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult)
>> evt->shift);
exynos4_mct_tick_stop(mevt);
@@ -464,6 +471,7 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
struct mct_clock_event_device *mevt =
per_cpu_ptr(&percpu_mct_tick, cpu);
struct clock_event_device *evt = &mevt->evt;
+ struct mct_context *ctx = mevt->ctx;
evt->name = mevt->name;
evt->cpumask = cpumask_of(cpu);
@@ -479,7 +487,7 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
- if (mct_int_type == MCT_INT_SPI) {
+ if (ctx->drvdata->int_type == MCT_INT_SPI) {
if (evt->irq == -1)
return -EIO;
@@ -487,9 +495,9 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
irq_force_affinity(evt->irq, cpumask_of(cpu));
enable_irq(evt->irq);
} else {
- enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
+ enable_percpu_irq(ctx->mct_irqs[MCT_L0_IRQ], 0);
}
- clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
+ clockevents_config_and_register(evt, ctx->clk_rate / (TICK_BASE_CNT + 1),
0xf, 0x7fffffff);
return 0;
@@ -500,18 +508,20 @@ static int exynos4_mct_dying_cpu(unsigned int cpu)
struct mct_clock_event_device *mevt =
per_cpu_ptr(&percpu_mct_tick, cpu);
struct clock_event_device *evt = &mevt->evt;
+ struct mct_context *ctx = mevt->ctx;
- if (mct_int_type == MCT_INT_SPI) {
+ if (ctx->drvdata->int_type == MCT_INT_SPI) {
if (evt->irq != -1)
disable_irq_nosync(evt->irq);
exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
} else {
- disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
+ disable_percpu_irq(ctx->mct_irqs[MCT_L0_IRQ]);
}
return 0;
}
-static int __init exynos4_timer_resources(struct device_node *np)
+static int __init exynos4_timer_resources(struct mct_context *ctx,
+ struct device_node *np)
{
struct clk *mct_clk, *tick_clk;
@@ -522,7 +532,7 @@ static int __init exynos4_timer_resources(struct device_node *np)
tick_clk = of_clk_get_by_name(np, "fin_pll");
if (IS_ERR(tick_clk))
panic("%s: unable to determine tick clock rate\n", __func__);
- clk_rate = clk_get_rate(tick_clk);
+ ctx->clk_rate = clk_get_rate(tick_clk);
mct_clk = of_clk_get_by_name(np, "mct");
if (IS_ERR(mct_clk))
@@ -534,22 +544,20 @@ static int __init exynos4_timer_resources(struct device_node *np)
/**
* exynos4_timer_interrupts - initialize MCT interrupts
+ * @ctx: device context
* @np: device node for MCT
- * @int_type: interrupt type, MCT_INT_PPI or MCT_INT_SPI
* @local_idx: array mapping CPU numbers to local timer indices
* @nr_local: size of @local_idx array
*/
-static int __init exynos4_timer_interrupts(struct device_node *np,
- unsigned int int_type,
+static int __init exynos4_timer_interrupts(struct mct_context *ctx,
+ struct device_node *np,
const u32 *local_idx,
size_t nr_local)
{
int nr_irqs, i, err, cpu;
- mct_int_type = int_type;
-
/* This driver uses only one global timer interrupt */
- mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+ ctx->mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
/*
* Find out the number of local irqs specified. The local
@@ -557,29 +565,30 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
* irqs are specified.
*/
nr_irqs = of_irq_count(np);
- if (nr_irqs > ARRAY_SIZE(mct_irqs)) {
+ if (nr_irqs > ARRAY_SIZE(ctx->mct_irqs)) {
pr_err("exynos-mct: too many (%d) interrupts configured in DT\n",
nr_irqs);
- nr_irqs = ARRAY_SIZE(mct_irqs);
+ nr_irqs = ARRAY_SIZE(ctx->mct_irqs);
}
for (i = MCT_L0_IRQ; i < nr_irqs; i++)
- mct_irqs[i] = irq_of_parse_and_map(np, i);
+ ctx->mct_irqs[i] = irq_of_parse_and_map(np, i);
for_each_possible_cpu(cpu) {
struct mct_clock_event_device *mevt =
per_cpu_ptr(&percpu_mct_tick, cpu);
+ mevt->ctx = ctx;
snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d",
cpu);
}
- if (mct_int_type == MCT_INT_PPI) {
+ if (ctx->drvdata->int_type == MCT_INT_PPI) {
- err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
+ err = request_percpu_irq(ctx->mct_irqs[MCT_L0_IRQ],
exynos4_mct_tick_isr, "MCT",
&percpu_mct_tick);
WARN(err, "MCT: can't request IRQ %d (%d)\n",
- mct_irqs[MCT_L0_IRQ], err);
+ ctx->mct_irqs[MCT_L0_IRQ], err);
} else {
for_each_possible_cpu(cpu) {
int mct_irq;
@@ -595,9 +604,9 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
irq_idx = MCT_L0_IRQ + local_idx[cpu];
pcpu_mevt->evt.irq = -1;
- if (irq_idx >= ARRAY_SIZE(mct_irqs))
+ if (irq_idx >= ARRAY_SIZE(ctx->mct_irqs))
break;
- mct_irq = mct_irqs[irq_idx];
+ mct_irq = ctx->mct_irqs[irq_idx];
irq_set_status_flags(mct_irq, IRQ_NOAUTOEN);
if (request_irq(mct_irq,
@@ -637,8 +646,8 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
return 0;
out_irq:
- if (mct_int_type == MCT_INT_PPI) {
- free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
+ if (ctx->drvdata->int_type == MCT_INT_PPI) {
+ free_percpu_irq(ctx->mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
} else {
for_each_possible_cpu(cpu) {
struct mct_clock_event_device *pcpu_mevt =
@@ -653,7 +662,7 @@ static int __init exynos4_timer_interrupts(struct device_node *np,
return err;
}
-static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
+static int __init mct_init_dt(struct mct_context *ctx, struct device_node *np)
{
bool frc_shared = of_property_read_bool(np, "samsung,frc-shared");
u32 local_idx[MCT_NR_LOCAL] = {0};
@@ -679,15 +688,15 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
local_idx[i] = i;
}
- ret = exynos4_timer_resources(np);
+ ret = exynos4_timer_resources(ctx, np);
if (ret)
return ret;
- ret = exynos4_timer_interrupts(np, int_type, local_idx, nr_local);
+ ret = exynos4_timer_interrupts(ctx, np, local_idx, nr_local);
if (ret)
return ret;
- ret = exynos4_clocksource_init(frc_shared);
+ ret = exynos4_clocksource_init(ctx, frc_shared);
if (ret)
return ret;
@@ -698,18 +707,60 @@ static int __init mct_init_dt(struct device_node *np, unsigned int int_type)
if (frc_shared)
return 0;
- return exynos4_clockevent_init();
+ ret = exynos4_clockevent_init(ctx);
+ if (ret)
+ return ret;
+
+ return 0;
}
+static const struct mct_data exynos4210_mct_data = { .int_type = MCT_INT_SPI, };
+static const struct mct_data exynos4412_mct_data = { .int_type = MCT_INT_PPI, };
-static int __init mct_init_spi(struct device_node *np)
-{
- return mct_init_dt(np, MCT_INT_SPI);
-}
+static const struct of_device_id exynos4_mct_match_table[] = {
+ { .compatible = "samsung,exynos4210-mct", .data = &exynos4210_mct_data, },
+ { .compatible = "samsung,exynos4412-mct", .data = &exynos4412_mct_data, },
+ {}
+};
-static int __init mct_init_ppi(struct device_node *np)
+/* Note, legacy ARM 32-bit systems depend on the MCT as the only clocksource
+ * which requires this driver to be initialized very early. We need to keep this
+ * special condition until we can transparently support modular and early init
+ * timers.
+ */
+static int __init mct_of_declare_init(struct device_node *np)
{
- return mct_init_dt(np, MCT_INT_PPI);
+ struct mct_context *ctx;
+ const struct of_device_id *match;
+ int ret;
+
+ match = of_match_node(exynos4_mct_match_table, np);
+ if (!match || !match->data)
+ return -ENODEV;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->drvdata = match->data;
+
+ ret = mct_init_dt(ctx, np);
+ if (ret)
+ goto out_ctx;
+
+#if defined(CONFIG_ARM)
+ sched_clock_register(exynos4_read_sched_clock, 32, ctx->clk_rate);
+
+ exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer;
+ exynos4_delay_timer.freq = ctx->clk_rate;
+ register_current_timer_delay(&exynos4_delay_timer);
+#endif
+
+ return 0;
+
+out_ctx:
+ kfree(ctx);
+ return ret;
}
-TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
-TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
+TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_of_declare_init);
+TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_of_declare_init);
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
` (3 preceding siblings ...)
2025-12-05 1:10 ` [PATCH v7 4/6] clocksource/drivers/exynos_mct: Refactor driver init Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 23:27 ` kernel test robot
2025-12-07 8:42 ` kernel test robot
2025-12-05 1:10 ` [PATCH v7 6/6] arm64: exynos: Drop select CLKSRC_EXYNOS_MCT Will McVicker
2025-12-05 9:55 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Marek Szyprowski
6 siblings, 2 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
On Arm64 platforms the Exynos MCT driver can be built as a module. On
boot (and even after boot) the arch_timer is used as the clocksource and
tick timer. Once the MCT driver is loaded, it can be used as the wakeup
source for the arch_timer.
Note, this commit was derived from
https://android.googlesource.com/kernel/gs/+/8a52a8288ec7d88ff78f0b37480dbb0e9c65bbfd.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Youngmin Nam <youngmin.nam@samsung.com> # AOSP -> Linux port
Tested-by: Youngmin Nam <youngmin.nam@samsung.com> # AOSP -> Linux port
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
drivers/clocksource/Kconfig | 3 +-
drivers/clocksource/exynos_mct.c | 51 ++++++++++++++++++++++++++++----
2 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index ffcd23668763..9450cfaf982f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -451,7 +451,8 @@ config ATMEL_TCB_CLKSRC
Support for Timer Counter Blocks on Atmel SoCs.
config CLKSRC_EXYNOS_MCT
- bool "Exynos multi core timer driver" if COMPILE_TEST
+ tristate "Exynos multi core timer driver" if ARM64
+ default y if ARCH_EXYNOS || COMPILE_TEST
depends on ARM || ARM64
depends on ARCH_ARTPEC || ARCH_EXYNOS || COMPILE_TEST
help
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 922c2b519a39..d9a888607726 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -15,9 +15,11 @@
#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/percpu.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
+#include <linux/platform_device.h>
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
@@ -232,6 +234,7 @@ static struct clocksource mct_frc = {
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.resume = exynos4_frc_resume,
+ .owner = THIS_MODULE,
};
/*
@@ -256,7 +259,7 @@ static cycles_t exynos4_read_current_timer(void)
}
#endif
-static int __init exynos4_clocksource_init(struct mct_context *ctx, bool frc_shared)
+static int __init_or_module exynos4_clocksource_init(struct mct_context *ctx, bool frc_shared)
{
/*
* When the frc is shared, the main processor should have already
@@ -343,6 +346,7 @@ static struct mct_clock_event_device mct_comp_device = {
.set_state_oneshot = mct_set_state_shutdown,
.set_state_oneshot_stopped = mct_set_state_shutdown,
.tick_resume = mct_set_state_shutdown,
+ .owner = THIS_MODULE,
},
};
@@ -484,6 +488,7 @@ static int exynos4_mct_starting_cpu(unsigned int cpu)
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_PERCPU;
evt->rating = MCT_CLKEVENTS_RATING;
+ evt->owner = THIS_MODULE;
exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
@@ -520,7 +525,7 @@ static int exynos4_mct_dying_cpu(unsigned int cpu)
return 0;
}
-static int __init exynos4_timer_resources(struct mct_context *ctx,
+static int __init_or_module exynos4_timer_resources(struct mct_context *ctx,
struct device_node *np)
{
struct clk *mct_clk, *tick_clk;
@@ -549,7 +554,7 @@ static int __init exynos4_timer_resources(struct mct_context *ctx,
* @local_idx: array mapping CPU numbers to local timer indices
* @nr_local: size of @local_idx array
*/
-static int __init exynos4_timer_interrupts(struct mct_context *ctx,
+static int __init_or_module exynos4_timer_interrupts(struct mct_context *ctx,
struct device_node *np,
const u32 *local_idx,
size_t nr_local)
@@ -662,7 +667,7 @@ static int __init exynos4_timer_interrupts(struct mct_context *ctx,
return err;
}
-static int __init mct_init_dt(struct mct_context *ctx, struct device_node *np)
+static int __init_or_module mct_init_dt(struct mct_context *ctx, struct device_node *np)
{
bool frc_shared = of_property_read_bool(np, "samsung,frc-shared");
u32 local_idx[MCT_NR_LOCAL] = {0};
@@ -722,7 +727,9 @@ static const struct of_device_id exynos4_mct_match_table[] = {
{ .compatible = "samsung,exynos4412-mct", .data = &exynos4412_mct_data, },
{}
};
+MODULE_DEVICE_TABLE(of, exynos4_mct_match_table);
+#if defined(CONFIG_ARM)
/* Note, legacy ARM 32-bit systems depend on the MCT as the only clocksource
* which requires this driver to be initialized very early. We need to keep this
* special condition until we can transparently support modular and early init
@@ -748,13 +755,11 @@ static int __init mct_of_declare_init(struct device_node *np)
if (ret)
goto out_ctx;
-#if defined(CONFIG_ARM)
sched_clock_register(exynos4_read_sched_clock, 32, ctx->clk_rate);
exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer;
exynos4_delay_timer.freq = ctx->clk_rate;
register_current_timer_delay(&exynos4_delay_timer);
-#endif
return 0;
@@ -764,3 +769,37 @@ static int __init mct_of_declare_init(struct device_node *np)
}
TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_of_declare_init);
TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_of_declare_init);
+#else
+static int exynos4_mct_probe(struct platform_device *pdev)
+{
+ struct mct_context *ctx;
+ struct device *dev = &pdev->dev;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->drvdata = of_device_get_match_data(dev);
+ if (!ctx->drvdata)
+ return -EINVAL;
+
+ return mct_init_dt(ctx, dev->of_node);
+}
+
+static struct platform_driver exynos4_mct_driver = {
+ .probe = exynos4_mct_probe,
+ .driver = {
+ .name = "exynos-mct",
+ .of_match_table = exynos4_mct_match_table,
+ },
+};
+
+static int __init exynos_mct_init(void)
+{
+ return platform_driver_register(&exynos4_mct_driver);
+}
+module_init(exynos_mct_init);
+
+MODULE_DESCRIPTION("Exynos Multi Core Timer Driver");
+MODULE_LICENSE("GPL");
+#endif /* CONFIG_ARM */
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v7 6/6] arm64: exynos: Drop select CLKSRC_EXYNOS_MCT
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
` (4 preceding siblings ...)
2025-12-05 1:10 ` [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64 Will McVicker
@ 2025-12-05 1:10 ` Will McVicker
2025-12-05 9:55 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Marek Szyprowski
6 siblings, 0 replies; 10+ messages in thread
From: Will McVicker @ 2025-12-05 1:10 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Daniel Lezcano, Thomas Gleixner,
Krzysztof Kozlowski, Alim Akhtar
Cc: Will McVicker, Donghoon Yu, Rob Herring, John Stultz,
Youngmin Nam, Peter Griffin, Tudor Ambarus, André Draszik,
Conor Dooley, Marek Szyprowski, Russell King (Oracle),
linux-samsung-soc, kernel-team, linux-arm-kernel, linux-kernel
Since the Exynos MCT driver can be built as a module for some Arm64 SoCs
like gs101, drop force-selecting it as a built-in driver by ARCH_EXYNOS
and instead depend on `default y if ARCH_EXYNOS` to select it
automatically. This allows platforms like Android to build the driver as
a module if desired.
Reviewed-by: Youngmin Nam <youngmin.nam@samsung.com>
Tested-by: Youngmin Nam <youngmin.nam@samsung.com>
Signed-off-by: Will McVicker <willmcvicker@google.com>
---
arch/arm64/Kconfig.platforms | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 13173795c43d..fc6026c368ca 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -128,7 +128,6 @@ config ARCH_CIX
config ARCH_EXYNOS
bool "Samsung Exynos SoC family"
select COMMON_CLK_SAMSUNG
- select CLKSRC_EXYNOS_MCT
select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
select EXYNOS_PMU
select PINCTRL
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
` (5 preceding siblings ...)
2025-12-05 1:10 ` [PATCH v7 6/6] arm64: exynos: Drop select CLKSRC_EXYNOS_MCT Will McVicker
@ 2025-12-05 9:55 ` Marek Szyprowski
6 siblings, 0 replies; 10+ messages in thread
From: Marek Szyprowski @ 2025-12-05 9:55 UTC (permalink / raw)
To: Will McVicker, Catalin Marinas, Will Deacon, Daniel Lezcano,
Thomas Gleixner, Krzysztof Kozlowski, Alim Akhtar
Cc: Donghoon Yu, Rob Herring, John Stultz, Youngmin Nam,
Peter Griffin, Tudor Ambarus, André Draszik, Conor Dooley,
Russell King (Oracle), linux-samsung-soc, kernel-team,
linux-arm-kernel, linux-kernel
On 05.12.2025 02:10, Will McVicker wrote:
> This series adds support to build the Arm64 Exynos MCT driver as a module.
> This is only possible on Arm64 SoCs since they can use the Arm architected
> timer as the clocksource. Once the Exynos MCT module is loaded and the device
> probes, the MCT is used as the wakeup source for the arch_timer to ensure the
> device can wakeup from the "c2" idle state.
>
> These patches are originally from the downstream Pixel 6 (gs101) kernel found
> at [1] and have been adapted for upstream. Not only has the Exynos MCT driver
> been shipping as a module in the field with Android, but I've also tested this
> series with the upstream kernel on my Pixel 6 Pro.
>
> To the driver changes (both as built-in and as module) on Pixel 6 Pro, I ran
> these tests:
>
> # cat /proc/interrupts | grep -E "mct|arch_timer"
> 23: 6823 10938 7795 5607 8935 12828 21947 2200 GICv3 30 Level arch_timer
> 104: 1 0 0 0 0 0 0 0 GICv3 785 Level mct_comp_irq
> 105: 547 0 0 0 0 0 0 0 GICv3 789 Level mct_tick0
> 106: 0 1333 0 0 0 0 0 0 GICv3 790 Level mct_tick1
> 107: 0 0 1467 0 0 0 0 0 GICv3 791 Level mct_tick2
> 108: 0 0 0 583 0 0 0 0 GICv3 792 Level mct_tick3
> 109: 0 0 0 0 206 0 0 0 GICv3 793 Level mct_tick4
> 110: 0 0 0 0 0 153 0 0 GICv3 794 Level mct_tick5
> 111: 0 0 0 0 0 0 13 0 GICv3 795 Level mct_tick6
> 112: 0 0 0 0 0 0 0 87 GICv3 796 Level mct_tick7
>
> # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
> arch_sys_counter
>
> When built and loaded as a module, you can verify via:
>
> # lsmod | grep exynos_mct
> exynos_mct 20480 9
>
> I also compile tested for ARCH=ARM DEFCONFIG=multi_v7_defconfig with the
> following debug configs to ensure the section mismatches are fixed:
> CONFIG_DEBUG_SECTION_MISMATCH=y
> # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
>
> Any additional testing is much appreciated!
>
> Thanks,
> Will
>
> Note1, instructions to build and flash a Pixel 6 device with the upstream
> kernel can be found at [2].
>
> Note2, this series is based off of krzk/for-next commit bca42080637c (Merge
> branch 'next/drivers-late' into for-next).
>
> [1] https://android.googlesource.com/kernel/gs/+log/refs/heads/android-gs-raviole-5.10-android12-d1
> [2] https://gitlab.com/LinaroLtd/googlelt/pixelscripts/-/blob/clo/main/README.md?ref_type=heads
>
> Cc: Alim Akhtar <alim.akhtar@samsung.com>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Donghoon Yu <hoony.yu@samsung.com>
> Cc: Rob Herring <robh@kernel.org>
> Cc: John Stultz <jstultz@google.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Youngmin Nam <youngmin.nam@samsung.com>
> Cc: Peter Griffin <peter.griffin@linaro.org>
> Cc: Tudor Ambarus <tudor.ambarus@linaro.org>
> Cc: André Draszik <andre.draszik@linaro.org>
> Cc: Will Deacon <will@kernel.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: "Russell King (Oracle)" <linux@armlinux.org.uk>
> Cc: linux-samsung-soc@vger.kernel.org
> Cc: kernel-team@android.com
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
Works fine on ARM Exynos 32bit based boards.
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>
> Changes in v7:
> - Dropped v6 patch 1/6 that removed __init from register_current_timer_delay()
> - Refactored the init function in patch 4/7 to handle the case of registering
> the timer delay function for ARM 32-bit systems from an __init tagged function.
> This addresses the original section mismatch issues reported in v4.
> - Rebased series onto base commit bca42080637c (Merge branch
> 'next/drivers-late' into for-next).
>
> Changes in v6:
> - Updated module support to only register the MCT driver as a platform driver
> for ARM64 to ensure ARM 32-bit SoCs continue to probe the MCT driver very
> early.
> - Squashed the percpu fix suggested by Marek Szyprowski in
> https://lore.kernel.org/all/20250827102645.1964659-1-m.szyprowski@samsung.com/
> together with patch 3/6.
>
> Changes in v5:
> - Fixed section mismatch issues.
> - Addressed Arnd's concerns regarding potential issues with unloading and/or
> unbinding the driver.
> - Fixed SoB concerns to clarify the development chain from AOSP to Linux.
> - Pulled in https://lore.kernel.org/all/20250827102645.1964659-1-m.szyprowski@samsung.com/
> to limit percpu interrupts only for ARM64.
>
> Changes in v4:
> - Missed the "v3" string in the previous series for the actual patches
> - Re-generated patches with --base a15edf91668beefdb5171c53fa698c9b43dd1e0d
> for kernel test robot.
>
> Changes in v3:
> - Rebased on top of Daniel's timer modularization prep series [3] and
> krzk/for-next commit a15edf91668b ("Merge branch 'next/dt64' into
> for-next")
> - Added owner references to Exynos MCT clocksource and clockevent objects.
> - Dropped #ifdef MODULE conditional section in favor of just using
> module_platform_driver() which will properly handle setting up the
> of_device_id table based on if the driver is built-in or a module.
> - Update commit message for patch 2 based on John's feedback.
> - Dropped DT change from v2 as it was picked up by Krzysztof for CPU Idle.
>
> Changes in v2:
> - Re-worked patch v1 5 based on Rob Herring's review to use the compatible
> data for retrieving the mct_init function pointer.
> - Updated the Kconfig logic to disallow building the Exynos MCT driver as
> a module for ARM32 configurations based on Krzysztof Kozlowski's findings.
> - Added comments and clarified commit messages in patches 1 and 2 based on
> reviews from John Stultz and Youngmin Nam.
> - Fixed an issue found during testing that resulted in the device getting
> stuck on boot. This is included in v2 as patch 5.
> - Collected *-by tags
> - Rebased to the latest linux-next/master.
> ---
>
> Donghoon Yu (1):
> clocksource/drivers/exynos_mct: Don't register as a sched_clock on
> arm64
>
> Hosung Kim (1):
> clocksource/drivers/exynos_mct: Set percpu local timer interrupts for
> ARM64
>
> Will McVicker (4):
> clocksource/drivers/exynos_mct: Fix uninitialized irq name warning
> clocksource/drivers/exynos_mct: Refactor driver init
> clocksource/drivers/exynos_mct: Add module support for ARM64
> arm64: exynos: Drop select CLKSRC_EXYNOS_MCT
>
> arch/arm64/Kconfig.platforms | 1 -
> drivers/clocksource/Kconfig | 3 +-
> drivers/clocksource/exynos_mct.c | 255 ++++++++++++++++++++++---------
> 3 files changed, 182 insertions(+), 77 deletions(-)
>
>
> base-commit: bca42080637ce3a21092fc0f7d5411e853b0c3b3
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64
2025-12-05 1:10 ` [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64 Will McVicker
@ 2025-12-05 23:27 ` kernel test robot
2025-12-07 8:42 ` kernel test robot
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-12-05 23:27 UTC (permalink / raw)
To: Will McVicker, Catalin Marinas, Will Deacon, Daniel Lezcano,
Thomas Gleixner, Krzysztof Kozlowski, Alim Akhtar
Cc: llvm, oe-kbuild-all, Will McVicker, Donghoon Yu, Rob Herring,
John Stultz, Youngmin Nam, Peter Griffin, Tudor Ambarus,
André Draszik, Conor Dooley, Marek Szyprowski,
Russell King (Oracle), linux-samsung-soc, kernel-team,
linux-arm-kernel, linux-kernel
Hi Will,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bca42080637ce3a21092fc0f7d5411e853b0c3b3]
url: https://github.com/intel-lab-lkp/linux/commits/Will-McVicker/clocksource-drivers-exynos_mct-Don-t-register-as-a-sched_clock-on-arm64/20251205-091403
base: bca42080637ce3a21092fc0f7d5411e853b0c3b3
patch link: https://lore.kernel.org/r/20251205011027.720512-6-willmcvicker%40google.com
patch subject: [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64
config: arm64-randconfig-004-20251205 (https://download.01.org/0day-ci/archive/20251206/202512060730.wBnpCnQv-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 14bf95b06a18b9b59c89601cbc0e5a6f2176b118)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251206/202512060730.wBnpCnQv-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512060730.wBnpCnQv-lkp@intel.com/
All warnings (new ones prefixed by >>, old ones prefixed by <<):
>> WARNING: modpost: vmlinux: section mismatch in reference: exynos4_mct_probe+0x70 (section: .text.exynos4_mct_probe) -> mct_init_dt (section: .init.text)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64
2025-12-05 1:10 ` [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64 Will McVicker
2025-12-05 23:27 ` kernel test robot
@ 2025-12-07 8:42 ` kernel test robot
1 sibling, 0 replies; 10+ messages in thread
From: kernel test robot @ 2025-12-07 8:42 UTC (permalink / raw)
To: Will McVicker, Catalin Marinas, Will Deacon, Daniel Lezcano,
Thomas Gleixner, Krzysztof Kozlowski, Alim Akhtar
Cc: llvm, oe-kbuild-all, Will McVicker, Donghoon Yu, Rob Herring,
John Stultz, Youngmin Nam, Peter Griffin, Tudor Ambarus,
André Draszik, Conor Dooley, Marek Szyprowski,
Russell King (Oracle), linux-samsung-soc, kernel-team,
linux-arm-kernel, linux-kernel
Hi Will,
kernel test robot noticed the following build warnings:
[auto build test WARNING on bca42080637ce3a21092fc0f7d5411e853b0c3b3]
url: https://github.com/intel-lab-lkp/linux/commits/Will-McVicker/clocksource-drivers-exynos_mct-Don-t-register-as-a-sched_clock-on-arm64/20251205-091403
base: bca42080637ce3a21092fc0f7d5411e853b0c3b3
patch link: https://lore.kernel.org/r/20251205011027.720512-6-willmcvicker%40google.com
patch subject: [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64
config: arm64-randconfig-001-20251207 (https://download.01.org/0day-ci/archive/20251207/202512071659.We0N43XW-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project a805147ac1ba123916de182babb0831fbb148756)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251207/202512071659.We0N43XW-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512071659.We0N43XW-lkp@intel.com/
All warnings (new ones prefixed by >>, old ones prefixed by <<):
>> WARNING: modpost: vmlinux: section mismatch in reference: exynos4_mct_probe+0x84 (section: .text) -> mct_init_dt (section: .init.text)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-12-07 8:42 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20251205011037eucas1p2bfaec27d78550b53099ebb0ca8713b2f@eucas1p2.samsung.com>
2025-12-05 1:10 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Will McVicker
2025-12-05 1:10 ` [PATCH v7 1/6] clocksource/drivers/exynos_mct: Don't register as a sched_clock on arm64 Will McVicker
2025-12-05 1:10 ` [PATCH v7 2/6] clocksource/drivers/exynos_mct: Set percpu local timer interrupts for ARM64 Will McVicker
2025-12-05 1:10 ` [PATCH v7 3/6] clocksource/drivers/exynos_mct: Fix uninitialized irq name warning Will McVicker
2025-12-05 1:10 ` [PATCH v7 4/6] clocksource/drivers/exynos_mct: Refactor driver init Will McVicker
2025-12-05 1:10 ` [PATCH v7 5/6] clocksource/drivers/exynos_mct: Add module support for ARM64 Will McVicker
2025-12-05 23:27 ` kernel test robot
2025-12-07 8:42 ` kernel test robot
2025-12-05 1:10 ` [PATCH v7 6/6] arm64: exynos: Drop select CLKSRC_EXYNOS_MCT Will McVicker
2025-12-05 9:55 ` [PATCH v7 0/6] Add module support for Arm64 Exynos MCT driver Marek Szyprowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).