lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260121-a733-rtc-v1-2-d359437f23a7@pigmoral.tech>
Date: Wed, 21 Jan 2026 18:59:08 +0800
From: Junhui Liu <junhui.liu@...moral.tech>
To: Michael Turquette <mturquette@...libre.com>, 
 Stephen Boyd <sboyd@...nel.org>, Chen-Yu Tsai <wens@...nel.org>, 
 Jernej Skrabec <jernej.skrabec@...il.com>, 
 Samuel Holland <samuel@...lland.org>, 
 Alexandre Belloni <alexandre.belloni@...tlin.com>, 
 Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>, 
 Conor Dooley <conor+dt@...nel.org>, Maxime Ripard <mripard@...nel.org>
Cc: linux-clk@...r.kernel.org, linux-arm-kernel@...ts.infradead.org, 
 linux-sunxi@...ts.linux.dev, linux-kernel@...r.kernel.org, 
 linux-rtc@...r.kernel.org, devicetree@...r.kernel.org, 
 Junhui Liu <junhui.liu@...moral.tech>
Subject: [PATCH 2/7] rtc: sun6i: Bind internal CCU via auxiliary bus

The sun6i RTC block contains an internal clock control unit (CCU).
Currently, the RTC driver binds this CCU part by directly calling a
probe function exported by the clock framework. This creates a tight
coupling between the RTC and clock drivers and makes it difficult to
add internal CCU support for new SoCs.

Switch to use the auxiliary bus for binding the internal CCU to
decouple the drivers.

Signed-off-by: Junhui Liu <junhui.liu@...moral.tech>
---
 drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 29 +++++++++++++++++++++++------
 drivers/rtc/rtc-sun6i.c              | 31 +++++++++++++++++++++++--------
 include/linux/clk/sunxi-ng.h         |  2 --
 3 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index f6bfeba009e8..3088f247d927 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -3,6 +3,7 @@
 // Copyright (c) 2021 Samuel Holland <samuel@...lland.org>
 //
 
+#include <linux/auxiliary_bus.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -11,8 +12,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <linux/clk/sunxi-ng.h>
-
 #include "ccu_common.h"
 
 #include "ccu_div.h"
@@ -44,6 +43,8 @@
 #define DCXO_CTRL_REG			0x160
 #define DCXO_CTRL_CLK16M_RC_EN		BIT(0)
 
+#define SUN6I_RTC_AUX_ID(_name)		"rtc_sun6i." #_name
+
 struct sun6i_rtc_match_data {
 	bool				have_ext_osc32k		: 1;
 	bool				have_iosc_calibration	: 1;
@@ -349,14 +350,18 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
 
-int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
+static int sun6i_rtc_ccu_probe(struct auxiliary_device *adev,
+			       const struct auxiliary_device_id *id)
 {
 	const struct sun6i_rtc_match_data *data;
 	struct clk *ext_osc32k_clk = NULL;
 	const struct of_device_id *match;
+	struct device *dev = &adev->dev;
+	void __iomem *reg = dev->platform_data;
+	struct device *parent = dev->parent;
 
 	/* This driver is only used for newer variants of the hardware. */
-	match = of_match_device(sun6i_rtc_ccu_match, dev);
+	match = of_match_device(sun6i_rtc_ccu_match, parent);
 	if (!match)
 		return 0;
 
@@ -367,9 +372,9 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 		const char *fw_name;
 
 		/* ext-osc32k was the only input clock in the old binding. */
-		fw_name = of_property_present(dev->of_node, "clock-names")
+		fw_name = of_property_present(parent->of_node, "clock-names")
 			? "ext-osc32k" : NULL;
-		ext_osc32k_clk = devm_clk_get_optional(dev, fw_name);
+		ext_osc32k_clk = devm_clk_get_optional(parent, fw_name);
 		if (IS_ERR(ext_osc32k_clk))
 			return PTR_ERR(ext_osc32k_clk);
 	}
@@ -392,6 +397,18 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
 	return devm_sunxi_ccu_probe(dev, reg, &sun6i_rtc_ccu_desc);
 }
 
+static const struct auxiliary_device_id sun6i_ccu_rtc_ids[] = {
+	{ .name = SUN6I_RTC_AUX_ID(sun6i) },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(auxiliary, sun6i_ccu_rtc_ids);
+
+static struct auxiliary_driver sun6i_ccu_rtc_driver = {
+	.probe = sun6i_rtc_ccu_probe,
+	.id_table = sun6i_ccu_rtc_ids,
+};
+module_auxiliary_driver(sun6i_ccu_rtc_driver);
+
 MODULE_IMPORT_NS("SUNXI_CCU");
 MODULE_DESCRIPTION("Support for the Allwinner H616/R329 RTC CCU");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index e5e6013d080e..b4489e0a09ce 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -11,9 +11,9 @@
  * Copyright (c) 2013, Carlo Caione <carlo.caione@...il.com>
  */
 
+#include <linux/auxiliary_bus.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clk/sunxi-ng.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/fs.h>
@@ -141,6 +141,11 @@ struct sun6i_rtc_clk_data {
 
 #define RTC_LINEAR_DAY	BIT(0)
 
+struct sun6i_rtc_match_data {
+	const char *adev_name;
+	unsigned long flags;
+};
+
 struct sun6i_rtc_dev {
 	struct rtc_device *rtc;
 	const struct sun6i_rtc_clk_data *data;
@@ -745,8 +750,10 @@ static void sun6i_rtc_bus_clk_cleanup(void *data)
 
 static int sun6i_rtc_probe(struct platform_device *pdev)
 {
+	const struct sun6i_rtc_match_data *data;
 	struct sun6i_rtc_dev *chip = sun6i_rtc;
 	struct device *dev = &pdev->dev;
+	struct auxiliary_device *adev;
 	struct clk *bus_clk;
 	int ret;
 
@@ -765,6 +772,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 			return ret;
 	}
 
+	data = of_device_get_match_data(&pdev->dev);
+
 	if (!chip) {
 		chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
 		if (!chip)
@@ -776,16 +785,17 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 		if (IS_ERR(chip->base))
 			return PTR_ERR(chip->base);
 
-		if (IS_REACHABLE(CONFIG_SUN6I_RTC_CCU)) {
-			ret = sun6i_rtc_ccu_probe(dev, chip->base);
-			if (ret)
-				return ret;
+		if (data && data->adev_name) {
+			adev = devm_auxiliary_device_create(dev, data->adev_name, chip->base);
+			if (!adev)
+				return -ENODEV;
 		}
 	}
 
 	platform_set_drvdata(pdev, chip);
 
-	chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev);
+	if (data)
+		chip->flags = data->flags;
 
 	chip->irq = platform_get_irq(pdev, 0);
 	if (chip->irq < 0)
@@ -850,6 +860,11 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct sun6i_rtc_match_data sun6i_rtc_match_data = {
+	.adev_name = "sun6i",
+	.flags = RTC_LINEAR_DAY,
+};
+
 /*
  * As far as RTC functionality goes, all models are the same. The
  * datasheets claim that different models have different number of
@@ -865,9 +880,9 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = {
 	{ .compatible = "allwinner,sun50i-h5-rtc" },
 	{ .compatible = "allwinner,sun50i-h6-rtc" },
 	{ .compatible = "allwinner,sun50i-h616-rtc",
-		.data = (void *)RTC_LINEAR_DAY },
+		.data = &sun6i_rtc_match_data },
 	{ .compatible = "allwinner,sun50i-r329-rtc",
-		.data = (void *)RTC_LINEAR_DAY },
+		.data = &sun6i_rtc_match_data },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
diff --git a/include/linux/clk/sunxi-ng.h b/include/linux/clk/sunxi-ng.h
index 57c8ec44ab4e..cf32123b39f5 100644
--- a/include/linux/clk/sunxi-ng.h
+++ b/include/linux/clk/sunxi-ng.h
@@ -9,6 +9,4 @@
 int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode);
 int sunxi_ccu_get_mmc_timing_mode(struct clk *clk);
 
-int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg);
-
 #endif

-- 
2.52.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ