[RFC] RFC: clocksource: timer-mediatek: Add means to register as platform_driver

Message ID 20230309132119.175650-1-angelogioacchino.delregno@collabora.com
State New
Headers
Series [RFC] RFC: clocksource: timer-mediatek: Add means to register as platform_driver |

Commit Message

AngeloGioacchino Del Regno March 9, 2023, 1:21 p.m. UTC
  This commit is not meant to be picked!

As some parties have some interest [1] in converting timers to
modules (for the sake of GKI), which IMO is quite tricky and hard
to do, I started some (quite fast) research on how could this be
achieved: not like that, for sure!

This kind of timers are obviously started early in the kernel init
process and as far as I saw (rightfully) even before pure_initcall,
or actually, better said, even before *any* initcall.

I fully acknowledge that this, as it is right now, is a quite big
hack... though, this actually compiles and actually... works if
timer-mediatek is compiled as built-in (so, in a way, I achieved
nothing), but the addition of the pure_initcall() there may be an
idea for others to experiment with initializing system timers at
a later stage.

This commit is practically one of the last steps involved in the
conversion, but it's meant as a conversation piece for the
interested parties.

Last thing last, after performing this research, I'm not sure
that pursuing modularization for timers is really worth it,
but I may be ignoring something :-)

[1]: https://patchwork.kernel.org/project/linux-mediatek/patch/20230214105412.5856-5-walter.chang@mediatek.com/
---
 drivers/clocksource/timer-mediatek.c | 40 ++++++++++++++++++++++++++--
 include/linux/clocksource.h          |  8 ++++++
 2 files changed, 46 insertions(+), 2 deletions(-)
  

Patch

diff --git a/drivers/clocksource/timer-mediatek.c b/drivers/clocksource/timer-mediatek.c
index 7bcb4a3f26fb..eda7f60475b6 100644
--- a/drivers/clocksource/timer-mediatek.c
+++ b/drivers/clocksource/timer-mediatek.c
@@ -13,6 +13,7 @@ 
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
 #include <linux/irqreturn.h>
+#include <linux/platform_device.h>
 #include <linux/sched_clock.h>
 #include <linux/slab.h>
 #include "timer-of.h"
@@ -337,5 +338,40 @@  static int __init mtk_gpt_init(struct device_node *node)
 
 	return 0;
 }
-TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init);
-TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init);
+
+static int mtk_timer_probe(struct platform_device *pdev)
+{
+	int (*mtk_timer_init)(struct device_node *node);
+
+	mtk_timer_init = device_get_match_data(&pdev->dev);
+	if (!mtk_timer_init)
+		return -EINVAL;
+
+	return mtk_timer_init(pdev->dev.of_node);
+}
+
+static const struct of_device_id timer_mediatek_of_match[] __timer_of_section = {
+	{ .compatible = "mediatek,mt6577-timer", .data = mtk_gpt_init },
+	{ .compatible = "mediatek,mt6765-timer", .data = mtk_syst_init },
+#ifdef MODULE
+	{ /* sentinel */ }
+#endif
+};
+MODULE_DEVICE_TABLE(of, timer_mediatek_of_match);
+
+static struct platform_driver timer_mediatek_driver __maybe_unused = {
+	.driver = {
+		.name = "mediatek-timer",
+		.of_match_table = timer_mediatek_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = mtk_timer_probe,
+};
+
+#ifdef MODULE
+static int __init timer_mediatek_init(void)
+{
+	return platform_driver_register(&timer_mediatek_driver);
+}
+pure_initcall(timer_mediatek_init)
+#endif
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 1d42d4b17327..a5d61a1099e4 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -279,6 +279,14 @@  extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
+#if defined(CONFIG_OF) && !defined(MODULE)
+ #define __timer_of_section				\
+	 __used __section("__timer_of_table")		\
+	 __aligned(__alignof__(struct of_device_id))
+#else
+ #define __timer_of_section
+#endif
+
 #define TIMER_OF_DECLARE(name, compat, fn) \
 	OF_DECLARE_1_RET(timer, name, compat, fn)