* [PATCH v2 6/6] clk: sunxi-ng: sun6i-rtc: add a733 support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
Add support for the sun60i a733 CCU RTC.
Compared to the a523, this SoC has a different input oscillator divider
which auto-detects the oscillator rate and select a divider to provide
a fixed 32768Hz clock. It also provides several phy reference clocks
with dedicated clock gates.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 74 ++++++++++++++++++++++++++++++++++--
drivers/clk/sunxi-ng/ccu-sun6i-rtc.h | 2 +-
2 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 25dd87e78eb7..2ec09e346472 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -42,11 +42,16 @@
#define LOSC_OUT_GATING_REG 0x60
#define DCXO_CTRL_REG 0x160
+#define DCXO_CTRL_DCXO_EN BIT(1)
#define DCXO_CTRL_CLK16M_RC_EN BIT(0)
+#define DCXO_GATING_REG 0x16c
+
struct sun6i_rtc_match_data {
bool have_ext_osc32k : 1;
bool have_iosc_calibration : 1;
+ bool have_dcxo_status : 1;
+ bool have_phy_ref_gates : 1;
bool rtc_32k_single_parent : 1;
const struct clk_parent_data *osc32k_fanout_parents;
u8 osc32k_fanout_nparents;
@@ -213,7 +218,12 @@ static struct ccu_mux osc32k_clk = {
},
};
-/* This falls back to the global name for fwnodes without a named reference. */
+/*
+ * This falls back to the global name for fwnodes without a named reference.
+ * NOTE: osc24M name might be misleading the oscillator could also be a 26MHz
+ * or a 19.2MHz one starting with the a733. The original name is kept anyway
+ * in case anything is relying on it.
+ */
static const struct clk_parent_data osc24M[] = {
{ .fw_name = "hosc", .name = "osc24M" }
};
@@ -227,8 +237,28 @@ static struct clk_fixed_factor osc24M_32k_div_clk = {
0),
};
-static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
- LOSC_OUT_GATING_REG, BIT(16), 0);
+static struct clk_div_table osc24M_32k_div_a733_table[] = {
+ { .val = 0, .div = 732 },
+ { .val = 1, .div = 586 },
+ { .val = 2, .div = 793 },
+ { .val = 3, .div = 732 },
+ { /* Sentinel */ },
+};
+
+static struct ccu_div osc24M_32k_div_a733_clk = {
+ .enable = BIT(1),
+ .div = _SUNXI_CCU_DIV_TABLE(14, 2, osc24M_32k_div_a733_table),
+ .common = {
+ .reg = DCXO_CTRL_REG,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+ osc24M,
+ &ccu_rodiv_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(osc24M_32k_clk, "osc24M-32k", "osc24M-32k-div",
+ LOSC_OUT_GATING_REG, BIT(16), 0);
static const struct clk_hw *rtc_32k_parents[] = {
&osc32k_clk.common.hw,
@@ -267,6 +297,15 @@ static struct ccu_mux osc32k_fanout_clk = {
},
};
+static SUNXI_CCU_GATE_FW(hosc_serdes1_clk, "hosc-serdes1", "hosc",
+ DCXO_GATING_REG, BIT(5), 0);
+static SUNXI_CCU_GATE_FW(hosc_serdes0_clk, "hosc-serdes0", "hosc",
+ DCXO_GATING_REG, BIT(4), 0);
+static SUNXI_CCU_GATE_FW(hosc_hdmi_clk, "hosc-hdmi", "hosc",
+ DCXO_GATING_REG, BIT(1), 0);
+static SUNXI_CCU_GATE_FW(hosc_ufs_clk, "hosc-ufs", "hosc",
+ DCXO_GATING_REG, BIT(0), 0);
+
static struct ccu_common *sun6i_rtc_ccu_clks[] = {
&iosc_clk,
&iosc_32k_clk,
@@ -275,6 +314,11 @@ static struct ccu_common *sun6i_rtc_ccu_clks[] = {
&osc24M_32k_clk.common,
&rtc_32k_clk.common,
&osc32k_fanout_clk.common,
+ &osc24M_32k_div_a733_clk.common,
+ &hosc_serdes1_clk.common,
+ &hosc_serdes0_clk.common,
+ &hosc_hdmi_clk.common,
+ &hosc_ufs_clk.common,
};
static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
@@ -288,6 +332,10 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
[CLK_OSC24M_32K] = &osc24M_32k_clk.common.hw,
[CLK_RTC_32K] = &rtc_32k_clk.common.hw,
[CLK_OSC24M_32K_DIV] = &osc24M_32k_div_clk.hw,
+ [CLK_HOSC_UFS] = &hosc_ufs_clk.common.hw,
+ [CLK_HOSC_HDMI] = &hosc_hdmi_clk.common.hw,
+ [CLK_HOSC_SERDES0] = &hosc_serdes0_clk.common.hw,
+ [CLK_HOSC_SERDES1] = &hosc_serdes1_clk.common.hw,
},
};
@@ -330,6 +378,15 @@ static const struct sun6i_rtc_match_data sun55i_a523_rtc_ccu_data = {
.osc32k_fanout_nparents = ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
};
+static const struct sun6i_rtc_match_data sun60i_a733_rtc_ccu_data = {
+ .have_ext_osc32k = true,
+ .have_iosc_calibration = true,
+ .have_dcxo_status = true,
+ .have_phy_ref_gates = true,
+ .osc32k_fanout_parents = sun50i_r329_osc32k_fanout_parents,
+ .osc32k_fanout_nparents = ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
+};
+
static const struct of_device_id sun6i_rtc_ccu_match[] = {
{
.compatible = "allwinner,sun50i-h616-rtc",
@@ -343,6 +400,10 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = {
.compatible = "allwinner,sun55i-a523-rtc",
.data = &sun55i_a523_rtc_ccu_data,
},
+ {
+ .compatible = "allwinner,sun60i-a733-rtc",
+ .data = &sun60i_a733_rtc_ccu_data,
+ },
{},
};
MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
@@ -375,6 +436,13 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
osc32k_fanout_init_data.parent_data = data->osc32k_fanout_parents;
osc32k_fanout_init_data.num_parents = data->osc32k_fanout_nparents;
+ if (data->have_dcxo_status)
+ sun6i_rtc_ccu_hw_clks.hws[CLK_OSC24M_32K_DIV] =
+ &osc24M_32k_div_a733_clk.common.hw;
+
+ if (!data->have_phy_ref_gates)
+ sun6i_rtc_ccu_hw_clks.num = CLK_OSC24M_32K_DIV + 1;
+
return devm_sunxi_ccu_probe(dev, reg, &sun6i_rtc_ccu_desc);
}
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index ab7b92b47f59..4f4f4cb00f1d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -11,6 +11,6 @@
#define CLK_RTC_32K 6
#define CLK_OSC24M_32K_DIV 7
-#define CLK_NUMBER (CLK_OSC24M_32K_DIV + 1)
+#define CLK_NUMBER (CLK_HOSC_SERDES1 + 1)
#endif /* _CCU_SUN6I_RTC_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 5/6] clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
On the a733 the "osc24M-32k" clock has the same gate bits as the previously
supported SoC but a different divider implementation.
Instead of a fixed 750 divider, the divider is selected based on the
rate of the oscillator. It can be seen as a simple read-only divider.
To easily replace the divider part depending the SoC, split the divider
and gate into two separate clock entities.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 20 +++++++++++---------
drivers/clk/sunxi-ng/ccu-sun6i-rtc.h | 3 ++-
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index b24c8b196e66..25dd87e78eb7 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -218,17 +218,18 @@ static const struct clk_parent_data osc24M[] = {
{ .fw_name = "hosc", .name = "osc24M" }
};
-static struct ccu_gate osc24M_32k_clk = {
- .enable = BIT(16),
- .common = {
- .reg = LOSC_OUT_GATING_REG,
- .prediv = 750,
- .features = CCU_FEATURE_ALL_PREDIV,
- .hw.init = CLK_HW_INIT_PARENTS_DATA("osc24M-32k", osc24M,
- &ccu_gate_ops, 0),
- },
+static struct clk_fixed_factor osc24M_32k_div_clk = {
+ .mult = 1,
+ .div = 750,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("osc24M-32k-div",
+ osc24M,
+ &clk_fixed_factor_ops,
+ 0),
};
+static SUNXI_CCU_GATE_HW(osc24M_32k_clk, "osc24M-32k", &osc24M_32k_div_clk.hw,
+ LOSC_OUT_GATING_REG, BIT(16), 0);
+
static const struct clk_hw *rtc_32k_parents[] = {
&osc32k_clk.common.hw,
&osc24M_32k_clk.common.hw
@@ -286,6 +287,7 @@ static struct clk_hw_onecell_data sun6i_rtc_ccu_hw_clks = {
[CLK_EXT_OSC32K_GATE] = &ext_osc32k_gate_clk.common.hw,
[CLK_OSC24M_32K] = &osc24M_32k_clk.common.hw,
[CLK_RTC_32K] = &rtc_32k_clk.common.hw,
+ [CLK_OSC24M_32K_DIV] = &osc24M_32k_div_clk.hw,
},
};
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
index 9ae821fc2599..ab7b92b47f59 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.h
@@ -9,7 +9,8 @@
#define CLK_EXT_OSC32K_GATE 4
#define CLK_OSC24M_32K 5
#define CLK_RTC_32K 6
+#define CLK_OSC24M_32K_DIV 7
-#define CLK_NUMBER (CLK_RTC_32K + 1)
+#define CLK_NUMBER (CLK_OSC24M_32K_DIV + 1)
#endif /* _CCU_SUN6I_RTC_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 4/6] clk: sunxi-ng: div: add read-only operation support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
Add support for sunxi-ng read-only dividers. This will be
useful to the a733 oscillator detection logic.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/sunxi-ng/ccu_div.c | 11 +++++++++++
drivers/clk/sunxi-ng/ccu_div.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index 62d680ccb524..0e3d9e6e30fb 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -143,3 +143,14 @@ const struct clk_ops ccu_div_ops = {
.set_rate = ccu_div_set_rate,
};
EXPORT_SYMBOL_NS_GPL(ccu_div_ops, "SUNXI_CCU");
+
+const struct clk_ops ccu_rodiv_ops = {
+ .disable = ccu_div_disable,
+ .enable = ccu_div_enable,
+ .is_enabled = ccu_div_is_enabled,
+
+ .get_parent = ccu_div_get_parent,
+
+ .recalc_rate = ccu_div_recalc_rate,
+};
+EXPORT_SYMBOL_NS_GPL(ccu_rodiv_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index be00b3277e97..a30a92780a05 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -300,5 +300,6 @@ static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
}
extern const struct clk_ops ccu_div_ops;
+extern const struct clk_ops ccu_rodiv_ops;
#endif /* _CCU_DIV_H_ */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 3/6] clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
From: Junhui Liu <junhui.liu@pigmoral.tech>
The sun6i-rtc CCU driver currently uses a global static variable to
denote whether calibration is supported, which makes IOSC operations
tightly coupled to this file.
Convert this into a feature bit to decouple the logic. This allows the
IOSC clock code to be moved into a shared module for reuse by other SoCs.
Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
Signed-off-by: Jerome Brunet<jbrunet@baylibre.com>
---
drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 17 +++++++++--------
drivers/clk/sunxi-ng/ccu_common.h | 1 +
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 0f528bfaed00..b24c8b196e66 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -52,8 +52,6 @@ struct sun6i_rtc_match_data {
u8 osc32k_fanout_nparents;
};
-static bool have_iosc_calibration;
-
static int ccu_iosc_enable(struct clk_hw *hw)
{
struct ccu_common *cm = hw_to_ccu_common(hw);
@@ -80,7 +78,7 @@ static unsigned long ccu_iosc_recalc_rate(struct clk_hw *hw,
{
struct ccu_common *cm = hw_to_ccu_common(hw);
- if (have_iosc_calibration) {
+ if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
u32 reg = readl(cm->base + IOSC_CLK_CALI_REG);
/*
@@ -119,7 +117,7 @@ static int ccu_iosc_32k_prepare(struct clk_hw *hw)
struct ccu_common *cm = hw_to_ccu_common(hw);
u32 val;
- if (!have_iosc_calibration)
+ if (!(cm->features & CCU_FEATURE_IOSC_CALIBRATION))
return 0;
val = readl(cm->base + IOSC_CLK_CALI_REG);
@@ -134,7 +132,7 @@ static void ccu_iosc_32k_unprepare(struct clk_hw *hw)
struct ccu_common *cm = hw_to_ccu_common(hw);
u32 val;
- if (!have_iosc_calibration)
+ if (!(cm->features & CCU_FEATURE_IOSC_CALIBRATION))
return;
val = readl(cm->base + IOSC_CLK_CALI_REG);
@@ -148,7 +146,7 @@ static unsigned long ccu_iosc_32k_recalc_rate(struct clk_hw *hw,
struct ccu_common *cm = hw_to_ccu_common(hw);
u32 val;
- if (have_iosc_calibration) {
+ if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
val = readl(cm->base + IOSC_CLK_CALI_REG);
/* Assume the calibrated 32k clock is accurate. */
@@ -167,7 +165,7 @@ static unsigned long ccu_iosc_32k_recalc_accuracy(struct clk_hw *hw,
struct ccu_common *cm = hw_to_ccu_common(hw);
u32 val;
- if (have_iosc_calibration) {
+ if (cm->features & CCU_FEATURE_IOSC_CALIBRATION) {
val = readl(cm->base + IOSC_CLK_CALI_REG);
/* Assume the calibrated 32k clock is accurate. */
@@ -358,7 +356,10 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
return 0;
data = match->data;
- have_iosc_calibration = data->have_iosc_calibration;
+ if (data->have_iosc_calibration) {
+ iosc_clk.features |= CCU_FEATURE_IOSC_CALIBRATION;
+ iosc_32k_clk.features |= CCU_FEATURE_IOSC_CALIBRATION;
+ }
if (!data->have_ext_osc32k) {
/* ext-osc32k-gate is an orphan, so do not register it. */
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index bbec283b9d99..d9dc24ad5503 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -21,6 +21,7 @@
#define CCU_FEATURE_CLOSEST_RATE BIT(9)
#define CCU_FEATURE_DUAL_DIV BIT(10)
#define CCU_FEATURE_UPDATE_BIT BIT(11)
+#define CCU_FEATURE_IOSC_CALIBRATION BIT(12)
/* MMC timing mode switch bit */
#define CCU_MMC_NEW_TIMING_MODE BIT(30)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 2/6] clk: sunxi-ng: sun6i-rtc: clean up DT usage
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
With sun6i-rtc compatible devices, the "ext-osc32k" clock input
is optional for the devices that support this input (r329 and onward).
Probably preparing for older SoC support, the driver does something funny
when parsing DT. It check if "ext-osc32k" is present in the clock-names and
if it is not, it uses the first clock as "ext-osc32k". This clock will
actually be the rtc bus clock so what the driver does is wrong.
At the moment, the driver does not support the older SoCs that would have
an external 32k clock provided on index #0 so just remove this quirk.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 23 +++--------------------
1 file changed, 3 insertions(+), 20 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index f6bfeba009e8..0f528bfaed00 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -191,10 +191,8 @@ static struct ccu_common iosc_32k_clk = {
CLK_GET_RATE_NOCACHE),
};
-static const struct clk_hw *ext_osc32k[] = { NULL }; /* updated during probe */
-
-static SUNXI_CCU_GATE_HWS(ext_osc32k_gate_clk, "ext-osc32k-gate",
- ext_osc32k, 0x0, BIT(4), 0);
+static SUNXI_CCU_GATE_FW(ext_osc32k_gate_clk, "ext-osc32k-gate",
+ "ext-osc32k", 0x0, BIT(4), 0);
static const struct clk_hw *osc32k_parents[] = {
&iosc_32k_clk.hw,
@@ -352,7 +350,6 @@ MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match);
int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
{
const struct sun6i_rtc_match_data *data;
- struct clk *ext_osc32k_clk = NULL;
const struct of_device_id *match;
/* This driver is only used for newer variants of the hardware. */
@@ -363,21 +360,7 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
data = match->data;
have_iosc_calibration = data->have_iosc_calibration;
- if (data->have_ext_osc32k) {
- 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")
- ? "ext-osc32k" : NULL;
- ext_osc32k_clk = devm_clk_get_optional(dev, fw_name);
- if (IS_ERR(ext_osc32k_clk))
- return PTR_ERR(ext_osc32k_clk);
- }
-
- if (ext_osc32k_clk) {
- /* Link ext-osc32k-gate to its parent. */
- *ext_osc32k = __clk_get_hw(ext_osc32k_clk);
- } else {
+ if (!data->have_ext_osc32k) {
/* ext-osc32k-gate is an orphan, so do not register it. */
sun6i_rtc_ccu_hw_clks.hws[CLK_EXT_OSC32K_GATE] = NULL;
osc32k_init_data.num_parents = 1;
--
2.47.3
^ permalink raw reply related
* [PATCH v2 1/6] dt-bindings: rtc: sun6i: add sun60i-a733 support
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
In-Reply-To: <20260629-a733-rtc-v2-0-7b72112784f8@baylibre.com>
Add a new rtc compatible for the sun60i-a733 SoC and new IDs for the
peripheral oscillator clock gates of this SoC.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 1 +
include/dt-bindings/clock/sun6i-rtc.h | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index 9df5cdb6f63f..197a6f67b180 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -33,6 +33,7 @@ properties:
- enum:
- allwinner,sun20i-d1-rtc
- allwinner,sun55i-a523-rtc
+ - allwinner,sun60i-a733-rtc
- const: allwinner,sun50i-r329-rtc
reg:
diff --git a/include/dt-bindings/clock/sun6i-rtc.h b/include/dt-bindings/clock/sun6i-rtc.h
index 3bd3aa3d57ce..5132a393ca4b 100644
--- a/include/dt-bindings/clock/sun6i-rtc.h
+++ b/include/dt-bindings/clock/sun6i-rtc.h
@@ -6,5 +6,9 @@
#define CLK_OSC32K 0
#define CLK_OSC32K_FANOUT 1
#define CLK_IOSC 2
+#define CLK_HOSC_UFS 8
+#define CLK_HOSC_HDMI 9
+#define CLK_HOSC_SERDES0 10
+#define CLK_HOSC_SERDES1 11
#endif /* _DT_BINDINGS_CLK_SUN6I_RTC_H_ */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 0/6] clk: sun6i-rtc: Add support for Allwinner A733 SoC
From: Jerome Brunet @ 2026-06-29 12:42 UTC (permalink / raw)
To: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Michael Turquette, Stephen Boyd, Maxime Ripard
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel, linux-clk, Jerome Brunet
Add support for the Allwinner A733 RTC and its internal Clock Control
Unit (CCU). Reuse the rtc-sun6i rtc driver while introducing a new
SoC-specific RTC CCU driver to handle the hardware's evolved clock
structure.
The A733 implementation supports hardware detection of three external
crystal frequencies (19.2MHz, 24MHz and 26MHz), which is represented in
the driver via read-only divider operations. Implement logic to derive a
normalized 32kHz reference from these DCXO sources using fixed
pre-dividers. Additionally, provide several new DCXO gate clocks for
peripherals, including SerDes, HDMI, and UFS.
This was tested on a Raxda Cubie A7A.
Changes in v2:
* Changed DT bindings as suggested. Those have changed significantly
since v1 so I did not pick up Rob's review trailer
* Support added in the existing RTC CCU driver rather than a separate driver
* Added DT parsing clean up of the existing driver
* Xtal detection exposed by RO divider rather than a MUX.
* Dropped conversion to aux device for now. This is not strictly related
the a733 support and will submitted again later on.
* Link to v1: https://lore.kernel.org/r/20260121-a733-rtc-v1-0-d359437f23a7@pigmoral.tech
---
Jerome Brunet (5):
dt-bindings: rtc: sun6i: add sun60i-a733 support
clk: sunxi-ng: sun6i-rtc: clean up DT usage
clk: sunxi-ng: div: add read-only operation support
clk: sunxi-ng: sun6i-rtc: split main oscillator div and gate.
clk: sunxi-ng: sun6i-rtc: add a733 support
Junhui Liu (1):
clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration
.../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 1 +
drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 124 +++++++++++++++------
drivers/clk/sunxi-ng/ccu-sun6i-rtc.h | 3 +-
drivers/clk/sunxi-ng/ccu_common.h | 1 +
drivers/clk/sunxi-ng/ccu_div.c | 11 ++
drivers/clk/sunxi-ng/ccu_div.h | 1 +
include/dt-bindings/clock/sun6i-rtc.h | 4 +
7 files changed, 109 insertions(+), 36 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20251226-a733-rtc-c5167df14e6e
Best regards,
--
Jerome
^ permalink raw reply
* RE: [EXTERNAL] Re: [PATCH] drivers: rtc: handle OTF clock changes
From: Elad Nachman @ 2026-06-28 17:34 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: linux-rtc@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260624153123af6b28e3@mail.local>
Hi Alexandre,
>
>
> From: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Sent: Wednesday, June 24, 2026 6:31 PM
> To: Elad Nachman <enachman@marvell.com>
> Cc: linux-rtc@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: [EXTERNAL] Re: [PATCH] drivers: rtc: handle OTF clock changes
>
> > From: Elad Nachman <mailto:enachman@marvell.com>
> >
> > When processing expired RTC events and rearming them, use now
> > instead of expiry to prevent endless loops.
> > Issue seen with Armada 385 SOC.
>
> The loop is not endless, it may be long however. How do you reproduce
48 seconds are long enough to trigger RCU related watchdog which eventually causes NOS reboot...
> this? Or maybe the question is what is enabling PIE on your system?
Not only PIE but also UIE enablement leads to this behavior.
UIE is enabled by Chrony, and that is activated by SONIC NOS.
SONIC NOS was introduced a time modification test (forward/backward)
which triggers this issue, causing the following kernel soft lockup:
[ 409.188746] rcu: blocking rcu_node structures (internal RCU debug):
[ 436.242391] watchdog: BUG: soft lockup - CPU#1 stuck for 48s! [kworker/1:3:432]
[ 436.250173] Kernel panic - not syncing: softlockup: hung tasks
[ 436.256032] CPU: 1 PID: 432 Comm: kworker/1:3 Tainted: G O L 6.1.0-29-2-armmp
[ 436.272194] Workqueue: events rtc_timer_do_work
[ 436.377383] __irq_svc from _raw_spin_unlock_irqrestore+0x24/0x28
[ 436.383510] _raw_spin_unlock_irqrestore from __wake_up_common_lock+0x8c/0xc0
[ 436.390685] __wake_up_common_lock from __wake_up+0x20/0x28
[ 436.396286] __wake_up from rtc_handle_legacy_irq+0x58/0x6c
[ 436.401890] rtc_handle_legacy_irq from rtc_timer_do_work+0xe0/0x37c
[ 436.408275] rtc_timer_do_work from process_one_work+0x1f8/0x4b4
[ 436.414317] process_one_work from worker_thread+0x54/0x50c
[ 436.419924] worker_thread from kthread+0xd8/0xf4
>
> Your patch breaks existing code because it will expect to get one event
> per elapsed period while your patch will cause events to be skipped.
I realize that, but the alternative of having soft lockup followed by reboot is worse in my opinion...
If you have any better idea, I am more than open to suggestions...
>
> >
> > Fixes commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events")
> > Signed-off-by: Elad Nachman <mailto:enachman@marvell.com>
> > ---
> > drivers/rtc/interface.c | 14 +++++++++++++-
> > 1 file changed, 13 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
> > index 96626f8068f9..c32ef95a07d4 100644
> > --- a/drivers/rtc/interface.c
> > +++ b/drivers/rtc/interface.c
> > @@ -126,6 +126,7 @@ EXPORT_SYMBOL_GPL(rtc_read_time);
> > int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
> > {
> > int err, uie;
> > + struct rtc_time new_tm;
> >
> > err = rtc_valid_tm(tm);
> > if (err != 0)
> > @@ -159,6 +160,17 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
> > else
> > err = -EINVAL;
> >
> > + if (rtc && rtc->ops && rtc->ops->read_time) {
> > + if (!rtc->ops->read_time(rtc->dev.parent, &new_tm)) {
> > + pr_debug("new rtc time secs %d mins %d hours %d mday %d mon %d year %d way %d yday %d dst %d\n",
> > + new_tm.tm_sec, new_tm.tm_min,
> > + new_tm.tm_hour, new_tm.tm_mday,
> > + new_tm.tm_mon, new_tm.tm_year,
> > + new_tm.tm_wday, new_tm.tm_yday,
> > + new_tm.tm_isdst);
> > + }
> > + }
> > +
>
>
> This is unrelated to the patch.
I can remove this easily once we find a solution to the main issue above...
>
> > pm_stay_awake(rtc->dev.parent);
> > mutex_unlock(&rtc->ops_lock);
> > /* A timer might have just expired */
> > @@ -999,7 +1011,7 @@ void rtc_timer_do_work(struct work_struct *work)
> > trace_rtc_timer_fired(timer);
> > /* Re-add/fwd periodic timers */
> > if (ktime_to_ns(timer->period)) {
> > - timer->node.expires = ktime_add(timer->node.expires,
> > + timer->node.expires = ktime_add(now,
> > timer->period);
> > timer->enabled = 1;
> > timerqueue_add(&rtc->timerqueue, &timer->node);
> > --
> > 2.25.1
> >
>
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://urldefense.proofpoint.com/v2/url?u=https-3A__bootlin.com&d=DwIBAg&c=nKjWec2b6R0mOyPaz7xtfQ&r=eTeNTLEK5-TxXczjOcKPhANIFtlB9pP4lq9qhdlFrwQ&m=6PDPbjuCmjWGjRiUxkS5sPKd4lHU_NypV7pVhoFdBcLnksTSMiVrFYs7blEViGJR&s=IQM9cBpCUzoV4ONJnQs4yjzbjygO7zRYDW1jpJL3zWM&e=
Thanks,
Elad.
^ permalink raw reply
* Re: [PATCH v1] rtc: m41t80: clean up watchdog on probe failure
From: 최유호 @ 2026-06-28 15:41 UTC (permalink / raw)
To: Alexandre Mergnat; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <178252038524.1704966.578320083174571195.b4-review@b4>
On Fri, 26 Jun 2026 at 20:33, Alexandre Mergnat <amergnat@baylibre.com> wrote:
> IMHO the right fix is to move the watchdog to the watchdog core.
>
> The leak comes from the watchdog being built on three non-devres
> save_client. A probe failure strands all three, after which the watchdog
> dereferences freed driver state (wdt_ping() reads
> i2c_get_clientdata(save_client), i.e. the devres-freed m41t80_data).
>
> Built on the watchdog core (CONFIG_WATCHDOG_CORE), none of that
> machinery is needed:
>
> - devm_watchdog_register_device() unregisters automatically on any probe
> failure and on unbind.
> - watchdog_stop_on_reboot() replaces the reboot notifier.
> - watchdog_set/get_drvdata() replaces the global save_client, closing
> the use-after-free surface itself.
> - m41t80_remove() does nothing but watchdog teardown today, so it goes
> away too.
>
> This is exactly what was done for the sibling driver rtc-ds1374, which
> carried the same legacy pattern: d3de4beb14a8 ("rtc: ds1374: wdt: Use
> watchdog core for watchdog part"), net -135 lines, adding "select
> WATCHDOG_CORE" in Kconfig. It is a usable template.
>
> primitives: a misc device, a reboot notifier, and the global
Thanks for the detailed suggestion, Alexandre.
Moving to the watchdog core sounds like a better approach. I will
rework this based on the rtc-ds1374 example and send v2.
Thanks,
Yuho
^ permalink raw reply
* Re: [PATCH v2 1/2] rtc: m5441x: add MCF5441x on-chip RTC driver
From: Alexandre Belloni @ 2026-06-28 12:40 UTC (permalink / raw)
To: Jean-Michel Hautbois
Cc: Greg Ungerer, Geert Uytterhoeven, linux-kernel, linux-rtc,
linux-m68k
In-Reply-To: <20260607-jmh-upstream-coldfire-rtc-v2-1-948d2b1ed146@yoseli.org>
Hello,
On 07/06/2026 11:00:40+0200, Jean-Michel Hautbois wrote:
> +static int m5441x_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct m5441x_rtc *p = dev_get_drvdata(dev);
> + u16 yearmon, days, hourmin, seconds;
> + unsigned int tries = 3;
> + unsigned long flags;
> + int ret;
> +
> + /*
> + * Without a running oscillator the counters are frozen; refuse the
> + * read rather than hand userspace a stale time that hwclock --hctosys
> + * would propagate into the system clock.
> + */
> + if (p->osc_dead)
> + return -ENODATA;
While not ideal, the current standard is to return -EINVAL in this case.
> +
> +static int m5441x_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> + struct m5441x_rtc *p = dev_get_drvdata(dev);
> + s8 yoff = (tm->tm_year + 1900) - M5441X_RTC_YEAR_BASE;
> + unsigned int tries = 3;
> + unsigned long flags;
> + int ret;
> +
> + /* A frozen oscillator would never latch the new time; reject it. */
> + if (p->osc_dead)
> + return -ENODATA;
set_time is a good location to actually restart the oscillator instead
of failing.
> +
> + /*
> + * Writes are nullified while INVAL is asserted. wait_valid() clears
> + * the path before the burst, but the knock plus four writes can cross
> + * a second boundary on a slow RTC bus, silently dropping fields.
> + * Re-check INVAL afterwards and rewrite on observed re-entry.
> + */
> + spin_lock_irqsave(&p->lock, flags);
> + do {
> + ret = m5441x_rtc_wait_valid(p);
> + if (ret)
> + break;
> + m5441x_rtc_unlock(p);
> + rtc_wr(p, M5441X_RTC_YEARMON,
> + ((u16)((u8)yoff) << 8) | ((tm->tm_mon + 1) & 0xff));
> + rtc_wr(p, M5441X_RTC_DAYS,
> + ((tm->tm_wday & 0x7) << 8) | (tm->tm_mday & 0x1f));
> + rtc_wr(p, M5441X_RTC_HOURMIN,
> + ((tm->tm_hour & 0x1f) << 8) | (tm->tm_min & 0x3f));
> + rtc_wr(p, M5441X_RTC_SECONDS, tm->tm_sec & 0x3f);
> + /* No boundary crossed mid-burst -> the writes all took. */
> + if (!(rtc_rd(p, M5441X_RTC_SR) & M5441X_RTC_SR_INVAL))
> + break;
> + ret = -EAGAIN;
> + } while (--tries);
> + spin_unlock_irqrestore(&p->lock, flags);
> +
> + return ret;
> +}
> +
> +
> +static int m5441x_rtc_probe(struct platform_device *pdev)
> +{
> + struct nvmem_config nvmem_cfg = {
> + .name = "m5441x_rtc_sram",
> + .type = NVMEM_TYPE_BATTERY_BACKED,
> + .word_size = 1,
> + .stride = 1,
> + .size = M5441X_RTC_SRAM_SIZE,
> + .reg_read = m5441x_rtc_nvram_read,
> + .reg_write = m5441x_rtc_nvram_write,
> + };
> + struct m5441x_rtc *p;
> + unsigned long flags;
> + bool osc_dead = false;
> + int irq, ret;
> + u16 cr, cfg;
> +
> + p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
> + if (!p)
> + return -ENOMEM;
> + spin_lock_init(&p->lock);
> +
> + p->base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(p->base))
> + return PTR_ERR(p->base);
> +
> + platform_set_drvdata(pdev, p);
> +
> + /* Enable the oscillator if needed and mask/clear stale interrupts. */
> + spin_lock_irqsave(&p->lock, flags);
> + m5441x_rtc_unlock(p);
> + /*
> + * Force binary, DST-free time/date encoding. The driver does not
> + * handle the BCD format, and Linux expects the RTC to keep monotonic
> + * time with local-time/DST conversion done in userspace, so clear
> + * BCDEN and DSTEN in case a bootloader or prior OS left them set. Also
> + * default the alarm match field to a full one-shot match: the reset
> + * value (AM=00) is a daily hh:mm:ss match, which would fire on the
> + * wrong day if userspace enables the alarm via RTC_AIE_ON without
> + * first programming it through set_alarm().
> + */
> + cr = rtc_rd(p, M5441X_RTC_CR);
> + cr &= ~(M5441X_RTC_CR_BCDEN | M5441X_RTC_CR_DSTEN | M5441X_RTC_CR_AM_MASK);
> + cr |= M5441X_RTC_CR_AM_FULL;
> + m5441x_rtc_write_cr(p, cr);
You must not enable the oscillator in probe as then you lose the
important information of whether the RTC has ever been set. Also,
forcefully setting DST here may destroy the existing date/time, don't do
this unless you know what is the current time (i.e. in set_time)
> +
> + /*
> + * The alarm registers are battery-backed and survive a power cycle,
> + * so a previously armed match could re-fire before set_alarm() runs.
> + * Clear them now (the write window is open).
> + */
> + rtc_wr(p, M5441X_RTC_ALM_YRMON, 0);
> + rtc_wr(p, M5441X_RTC_ALM_DAYS, 0);
> + rtc_wr(p, M5441X_RTC_ALM_HM, 0);
> + rtc_wr(p, M5441X_RTC_ALM_SEC, 0);
Why wouldn't you want an existing alarm to fire? The registers are
battery backed exactly for this purpose.
> +
> + /*
> + * Enable the 32kHz oscillator that drives the time counters. This only
> + * checks that the OSCEN enable bit latches: when it reads back clear
> + * the oscillator block rejected the enable, which in practice means no
> + * RTC crystal is fitted and the counters will never advance. It cannot
> + * tell a dead crystal from one still starting up, so it is a best-
> + * effort hint, not a liveness guarantee. Warn but keep probing, since
> + * the battery-backed standby RAM stays usable without the oscillator.
> + */
> + cfg = rtc_rd(p, M5441X_RTC_CFG_DATA);
> + if (!(cfg & M5441X_RTC_CFG_OSCEN)) {
> + rtc_wr(p, M5441X_RTC_CFG_DATA, cfg | M5441X_RTC_CFG_OSCEN);
> + if (!(rtc_rd(p, M5441X_RTC_CFG_DATA) & M5441X_RTC_CFG_OSCEN))
> + osc_dead = true;
> + }
> +
> + /* Mask every source but keep the reserved bit 0 set as required. */
> + rtc_wr(p, M5441X_RTC_IER, M5441X_RTC_IER_RSVD);
> + rtc_wr(p, M5441X_RTC_ISR, rtc_rd(p, M5441X_RTC_ISR));
An existing alarm needs to be kept enabled.
> + spin_unlock_irqrestore(&p->lock, flags);
I'm pretty sure locking here is useless until you register the interrupt.
> +
> + /*
> + * Keep the device (and its standby-RAM nvmem) usable, but record the
> + * dead oscillator so read_time/set_time refuse to expose a clock that
> + * cannot tick.
> + */
> + p->osc_dead = osc_dead;
> + if (osc_dead)
> + dev_warn(&pdev->dev,
> + "RTC oscillator enable did not latch; timekeeping unavailable (no 32kHz crystal?)\n");
> +
> + p->rtc = devm_rtc_allocate_device(&pdev->dev);
> + if (IS_ERR(p->rtc))
> + return PTR_ERR(p->rtc);
> +
> + p->rtc->ops = &m5441x_rtc_ops;
> + p->rtc->range_min = mktime64(1984, 1, 1, 0, 0, 0);
> + p->rtc->range_max = mktime64(2239, 12, 31, 23, 59, 59);
> +
> + irq = platform_get_irq_optional(pdev, 0);
> + if (irq > 0) {
> + ret = devm_request_irq(&pdev->dev, irq, m5441x_rtc_irq, 0,
> + dev_name(&pdev->dev), p);
If this interrupt can be threaded, the spinlock becomes useless as long
as you lock the RTC with rtc_lock/rtc_unlock in the interrupt handler.
> + if (ret) {
> + dev_err(&pdev->dev,
> + "failed to request IRQ %d: %d, alarm disabled\n",
> + irq, ret);
> + clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
> + } else {
> + /*
> + * The alarm comparator runs on standby power, so let it
> + * wake a suspended system. The PM core keeps the IRQ
> + * enabled across suspend once it is the device's wake
> + * IRQ; both are device-managed.
> + */
> + devm_device_init_wakeup(&pdev->dev);
> + devm_pm_set_wake_irq(&pdev->dev, irq);
> + }
> + } else {
> + clear_bit(RTC_FEATURE_ALARM, p->rtc->features);
> + }
> +
> + /*
> + * Register the RTC device before the nvmem provider:
> + * devm_rtc_nvmem_register() copies rtc->owner into the nvmem config,
> + * and that field is only assigned by devm_rtc_register_device().
> + * Registering nvmem first would leave its owner NULL and fail to pin
> + * this module while standby-RAM consumers hold references.
> + */
> + ret = devm_rtc_register_device(p->rtc);
> + if (ret)
> + return ret;
> +
> + nvmem_cfg.priv = p;
> + ret = devm_rtc_nvmem_register(p->rtc, &nvmem_cfg);
> + if (ret)
> + dev_warn(&pdev->dev, "standby RAM nvmem unavailable: %d\n", ret);
> +
> + return 0;
> +}
> +
> +static struct platform_driver m5441x_rtc_driver = {
> + .driver = {
> + .name = "rtc-m5441x",
> + },
> + .probe = m5441x_rtc_probe,
> +};
> +module_platform_driver(m5441x_rtc_driver);
> +
> +MODULE_DESCRIPTION("Freescale MCF5441x on-chip RTC driver");
> +MODULE_AUTHOR("Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:rtc-m5441x");
>
> --
> 2.39.5
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [GIT PULL] RTC for 7.2
From: pr-tracker-bot @ 2026-06-27 21:13 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: Linus Torvalds, linux-rtc, linux-kernel
In-Reply-To: <20260626220226c3609b27@mail.local>
The pull request you sent on Sat, 27 Jun 2026 00:02:26 +0200:
> git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.2
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/da7ca04e331e3e83f661e29c30d381a91e6ca245
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* Re: [PATCH v1] rtc: m41t80: clean up watchdog on probe failure
From: Alexandre Mergnat @ 2026-06-27 0:33 UTC (permalink / raw)
To: Yuho Choi; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <20260601194615.1979101-1-dbgh9129@gmail.com>
On Mon, 01 Jun 2026 15:46:15 -0400, Yuho Choi <dbgh9129@gmail.com> wrote:
> diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
> index b26afef37d9c..f4a30320c6ed 100644
> --- a/drivers/rtc/rtc-m41t80.c
> +++ b/drivers/rtc/rtc-m41t80.c
> @@ -1009,9 +1009,17 @@ static int m41t80_probe(struct i2c_client *client)
>
> rc = devm_rtc_register_device(m41t80_data->rtc);
> if (rc)
> - return rc;
> + goto err_wdt;
IMHO the right fix is to move the watchdog to the watchdog core.
The leak comes from the watchdog being built on three non-devres
save_client. A probe failure strands all three, after which the watchdog
dereferences freed driver state (wdt_ping() reads
i2c_get_clientdata(save_client), i.e. the devres-freed m41t80_data).
Built on the watchdog core (CONFIG_WATCHDOG_CORE), none of that
machinery is needed:
- devm_watchdog_register_device() unregisters automatically on any probe
failure and on unbind.
- watchdog_stop_on_reboot() replaces the reboot notifier.
- watchdog_set/get_drvdata() replaces the global save_client, closing
the use-after-free surface itself.
- m41t80_remove() does nothing but watchdog teardown today, so it goes
away too.
This is exactly what was done for the sibling driver rtc-ds1374, which
carried the same legacy pattern: d3de4beb14a8 ("rtc: ds1374: wdt: Use
watchdog core for watchdog part"), net -135 lines, adding "select
WATCHDOG_CORE" in Kconfig. It is a usable template.
primitives: a misc device, a reboot notifier, and the global
primitives: a misc device, a reboot notifier, and the global
--
Alexandre Mergnat <amergnat@baylibre.com>
^ permalink raw reply
* [GIT PULL] RTC for 7.2
From: Alexandre Belloni @ 2026-06-26 22:02 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-rtc, linux-kernel
Hello Linus,
Here is the RTC subsystem pull request for 7.2. Most of the work and
improvements are for features of the m41t93. The ds1307 also gets
support for OSF for new variants. The pcap driver is being removed as
the Motorola EZX support was removed a while ago.
The following changes since commit 254f49634ee16a731174d2ae34bc50bd5f45e731:
Linux 7.1-rc1 (2026-04-26 14:19:00 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git tags/rtc-7.2
for you to fetch changes up to 3c8f28578a0d68bc7fb91d881b832d55f734270c:
rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON (2026-06-25 14:44:39 +0200)
----------------------------------------------------------------
RTC for 7.2
Subsystem:
- add rtc_read_next_alarm() to read next expiring timer
Drivers:
- ds1307: handle OSF for ds1337/ds1339/ds3231, add clock provider for ds1307,
fix wday for rx8130
- m41t93: DT support, alarm, clock provider, watchdog support
- mv: add suspend/resume support for wakeup
- pcap: remove driver
- renesas-rtca3: many fixes
----------------------------------------------------------------
Adriana Stancu (1):
rtc: bq32000: add delay between RTC reads
Akhilesh Patil (7):
rtc: ds1307: add support for clock provider in ds1307
dt-bindings: rtc: Add ST m41t93
rtc: m41t93: add device tree support
rtc: m41t93: migrate to regmap api for register access
rtc: m41t93: Add alarm support
rtc: m41t93: Add square wave clock provider support
rtc: m41t93: Add watchdog support
Alexandre Belloni (1):
rtc: s35390a: fix typo in comment
Antoni Pokusinski (1):
rtc: abx80x: fix the RTC_VL_CLR clearing all status flags
Arnd Bergmann (1):
rtc: remove unused pcap driver
Conor Dooley (1):
rtc: mpfs: fix counter upload completion condition
Ethan Nelson-Moore (1):
rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON
Fredrik M Olsson (2):
dt-bindings: rtc: ds1307: Add epson,rx8901
rtc: ds1307: Fix off-by-one issue with wday for rx8130
Haoxiang Li (1):
rtc: cmos: unregister HPET IRQ handler on probe failure
John Madieu (1):
rtc: isl1208: Balance enable_irq_wake() with disable_irq_wake() on cleanup
Lad Prabhakar (5):
rtc: renesas-rtca3: Fix PIE clear polling condition in alarm setup error path
rtc: renesas-rtca3: Check RADJ poll result during initial setup
rtc: renesas-rtca3: Fix incorrect error message for reset assert
rtc: renesas-rtca3: Fix typo in rtca3_ppb_per_cycle documentation
rtc: renesas-rtca3: Factor out year decoding helper
Mario Limonciello (2):
rtc: interface: Add rtc_read_next_alarm() to read next expiring timer
platform/x86: amd-pmc: Fix S0i3 wakeup with alarmtimer
Maxwell Doose (1):
rtc: ab8500: replace sprintf() with sysfs_emit()
Ronan Dalton (1):
rtc: ds1307: handle oscillator stop flag for ds1337/ds1339/ds3231
Stepan Ionichev (1):
rtc: msc313: fix NULL deref in shared IRQ handler at probe
Tommy Huang (2):
dt-bindings: rtc: add ASPEED AST2700 compatible
rtc: aspeed: add AST2700 compatible
Udaya Kiran Challa (1):
dt-bindings: rtc: epson,rx6110: Convert to DT Schema
Uwe Kleine-König (The Capable Hub) (4):
rtc: Use named initializers for arrays of i2c_device_data
rtc: Drop unused assignment of platform_device_id driver data
rtc: ab8500: Simplify driver_data handling
rtc: Use named initializers for platform_device_id arrays
Xue Lei (1):
rtc: mv: add suspend/resume support for wakeup
Yahya Saqban (1):
rtc: interface: fix typos in rtc_handle_legacy_irq() documentation
.../devicetree/bindings/rtc/epson,rx6110.txt | 39 --
.../devicetree/bindings/rtc/epson,rx6110.yaml | 68 +++
.../devicetree/bindings/rtc/rtc-ds1307.yaml | 1 +
.../devicetree/bindings/rtc/st,m41t93.yaml | 50 +++
.../devicetree/bindings/rtc/trivial-rtc.yaml | 2 +
drivers/platform/x86/amd/pmc/pmc.c | 9 +-
drivers/rtc/Kconfig | 7 -
drivers/rtc/Makefile | 1 -
drivers/rtc/interface.c | 44 +-
drivers/rtc/rtc-88pm886.c | 2 +-
drivers/rtc/rtc-ab-b5ze-s3.c | 2 +-
drivers/rtc/rtc-ab-eoz9.c | 2 +-
drivers/rtc/rtc-ab8500.c | 8 +-
drivers/rtc/rtc-abx80x.c | 23 +-
drivers/rtc/rtc-aspeed.c | 1 +
drivers/rtc/rtc-bd70528.c | 8 +-
drivers/rtc/rtc-bq32k.c | 11 +-
drivers/rtc/rtc-cmos.c | 6 +
drivers/rtc/rtc-cros-ec.c | 4 +-
drivers/rtc/rtc-ds1307.c | 207 +++++++--
drivers/rtc/rtc-ds1374.c | 2 +-
drivers/rtc/rtc-ds1672.c | 2 +-
drivers/rtc/rtc-ds3232.c | 2 +-
drivers/rtc/rtc-em3027.c | 2 +-
drivers/rtc/rtc-fm3130.c | 2 +-
drivers/rtc/rtc-hym8563.c | 4 +-
drivers/rtc/rtc-isl12022.c | 2 +-
drivers/rtc/rtc-isl12026.c | 4 +-
drivers/rtc/rtc-isl1208.c | 25 +-
drivers/rtc/rtc-m41t80.c | 22 +-
drivers/rtc/rtc-m41t93.c | 488 ++++++++++++++++++---
drivers/rtc/rtc-max31335.c | 4 +-
drivers/rtc/rtc-max6900.c | 2 +-
drivers/rtc/rtc-max77686.c | 10 +-
drivers/rtc/rtc-max8997.c | 4 +-
drivers/rtc/rtc-max8998.c | 4 +-
drivers/rtc/rtc-mpfs.c | 2 +-
drivers/rtc/rtc-msc313.c | 4 +-
drivers/rtc/rtc-mv.c | 23 +
drivers/rtc/rtc-nct3018y.c | 2 +-
drivers/rtc/rtc-pcap.c | 179 --------
drivers/rtc/rtc-pcf2127.c | 8 +-
drivers/rtc/rtc-pcf85063.c | 12 +-
drivers/rtc/rtc-pcf8523.c | 2 +-
drivers/rtc/rtc-pcf8563.c | 6 +-
drivers/rtc/rtc-pcf8583.c | 2 +-
drivers/rtc/rtc-renesas-rtca3.c | 26 +-
drivers/rtc/rtc-rs5c372.c | 12 +-
drivers/rtc/rtc-rv3029c2.c | 4 +-
drivers/rtc/rtc-rv8803.c | 8 +-
drivers/rtc/rtc-rx6110.c | 2 +-
drivers/rtc/rtc-rx8010.c | 2 +-
drivers/rtc/rtc-rx8025.c | 4 +-
drivers/rtc/rtc-rx8581.c | 2 +-
drivers/rtc/rtc-s35390a.c | 4 +-
drivers/rtc/rtc-s5m.c | 12 +-
drivers/rtc/rtc-sd2405al.c | 2 +-
drivers/rtc/rtc-sd3078.c | 2 +-
drivers/rtc/rtc-tps6594.c | 4 +-
drivers/rtc/rtc-x1205.c | 2 +-
include/linux/rtc.h | 2 +
61 files changed, 961 insertions(+), 441 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/rtc/epson,rx6110.txt
create mode 100644 Documentation/devicetree/bindings/rtc/epson,rx6110.yaml
create mode 100644 Documentation/devicetree/bindings/rtc/st,m41t93.yaml
delete mode 100644 drivers/rtc/rtc-pcap.c
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH] rtc: zynqmp: Return optional clock lookup errors
From: Michal Simek @ 2026-06-26 12:42 UTC (permalink / raw)
To: Pengpeng Hou, Alexandre Belloni; +Cc: linux-rtc, linux-arm-kernel, linux-kernel
In-Reply-To: <20260624055524.38522-1-pengpeng@iscas.ac.cn>
On 6/24/26 07:55, Pengpeng Hou wrote:
> devm_clk_get_optional() returns NULL when the optional clock is absent,
> but returns an ERR_PTR when the clock provider lookup fails. Probe
> currently keeps the ERR_PTR and then passes it to clk_get_rate().
>
> Return the lookup error instead. A truly absent optional clock still
> reaches the existing calibration fallback through clk_get_rate(NULL).
>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
> drivers/rtc/rtc-zynqmp.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
> index 2ae54804b87a..5bcb7536e973 100644
> --- a/drivers/rtc/rtc-zynqmp.c
> +++ b/drivers/rtc/rtc-zynqmp.c
> @@ -334,10 +334,9 @@ static int xlnx_rtc_probe(struct platform_device *pdev)
>
> /* Getting the rtc info */
> xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc");
> - if (IS_ERR(xrtcdev->rtc_clk)) {
> - if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)
> - dev_warn(&pdev->dev, "Device clock not found.\n");
> - }
> + if (IS_ERR(xrtcdev->rtc_clk))
> + return dev_err_probe(&pdev->dev, PTR_ERR(xrtcdev->rtc_clk),
> + "Failed to get rtc clock\n");
> xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);
> if (!xrtcdev->freq) {
> ret = of_property_read_u32(pdev->dev.of_node, "calibration",
Fixes: 07dcc6f9c762 ("rtc: zynqmp: Add calibration set and get support")
cc: stable@kernel.org
Reviewed-by: Michal Simek <michal.simek@amd.com>
Thanks,
Michal
^ permalink raw reply
* [PATCH 2/2] rtc: mv: remove mv_rtc_remove
From: alexandre.belloni @ 2026-06-25 13:02 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: Grégory Clement, linux-rtc, linux-kernel
In-Reply-To: <20260625130202.1621692-1-alexandre.belloni@bootlin.com>
From: Alexandre Belloni <alexandre.belloni@bootlin.com>
Use devm_device_init_wakeup() so we can avoid having to explicitly teardown
of module removal.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-mv.c | 19 ++-----------------
1 file changed, 2 insertions(+), 17 deletions(-)
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index c0f1bcd838e3..db64c459ee19 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -260,7 +260,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
}
if (pdata->irq >= 0)
- device_init_wakeup(&pdev->dev, true);
+ devm_device_init_wakeup(&pdev->dev);
else
clear_bit(RTC_FEATURE_ALARM, pdata->rtc->features);
@@ -275,14 +275,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
return ret;
}
-static void __exit mv_rtc_remove(struct platform_device *pdev)
-{
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
- if (pdata->irq >= 0)
- device_init_wakeup(&pdev->dev, false);
-}
-
#ifdef CONFIG_OF
static const struct of_device_id rtc_mv_of_match_table[] = {
{ .compatible = "marvell,orion-rtc", },
@@ -313,14 +305,7 @@ static int mv_rtc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(mv_rtc_pm_ops, mv_rtc_suspend, mv_rtc_resume);
-/*
- * mv_rtc_remove() lives in .exit.text. For drivers registered via
- * module_platform_driver_probe() this is ok because they cannot get unbound at
- * runtime. So mark the driver struct with __refdata to prevent modpost
- * triggering a section mismatch warning.
- */
-static struct platform_driver mv_rtc_driver __refdata = {
- .remove = __exit_p(mv_rtc_remove),
+static struct platform_driver mv_rtc_driver = {
.driver = {
.name = "rtc-mv",
.of_match_table = of_match_ptr(rtc_mv_of_match_table),
--
2.54.0
^ permalink raw reply related
* [PATCH 1/2] rtc: mv: fix potential race condition
From: alexandre.belloni @ 2026-06-25 13:02 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: Grégory Clement, linux-rtc, linux-kernel
From: Alexandre Belloni <alexandre.belloni@bootlin.com>
Since the driver allocates the IRQ using devm_request_irq(), this means the
IRQ is going to be automatically unregistered by devres after
mv_rtc_remove() returns.
However, mv_rtc_remove() explicitly disables the hardware clock before
devres teardown happens so the interrupt handler may run while the clock is
disabled leading to a possible bus hang when accessing registers.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-mv.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index f88976fd6d5d..c0f1bcd838e3 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -219,17 +219,15 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
if (IS_ERR(pdata->ioaddr))
return PTR_ERR(pdata->ioaddr);
- pdata->clk = devm_clk_get(&pdev->dev, NULL);
- /* Not all SoCs require a clock.*/
- if (!IS_ERR(pdata->clk))
- clk_prepare_enable(pdata->clk);
+ pdata->clk = devm_clk_get_optional_prepared(&pdev->dev, NULL);
+ if (IS_ERR(pdata->clk))
+ return PTR_ERR(pdata->clk);
/* make sure the 24 hour mode is enabled */
rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
if (rtc_time & RTC_HOURS_12H_MODE) {
dev_err(&pdev->dev, "12 Hour mode is enabled but not supported.\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
/* make sure it is actually functional */
@@ -238,8 +236,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
if (rtc_time == 0x01000000) {
dev_err(&pdev->dev, "internal RTC not ticking\n");
- ret = -ENODEV;
- goto out;
+ return -ENODEV;
}
}
@@ -249,8 +246,7 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(pdata->rtc)) {
- ret = PTR_ERR(pdata->rtc);
- goto out;
+ return PTR_ERR(pdata->rtc);
}
if (pdata->irq >= 0) {
@@ -275,9 +271,6 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
ret = devm_rtc_register_device(pdata->rtc);
if (!ret)
return 0;
-out:
- if (!IS_ERR(pdata->clk))
- clk_disable_unprepare(pdata->clk);
return ret;
}
@@ -288,9 +281,6 @@ static void __exit mv_rtc_remove(struct platform_device *pdev)
if (pdata->irq >= 0)
device_init_wakeup(&pdev->dev, false);
-
- if (!IS_ERR(pdata->clk))
- clk_disable_unprepare(pdata->clk);
}
#ifdef CONFIG_OF
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON
From: Alexandre Belloni @ 2026-06-25 12:45 UTC (permalink / raw)
To: linux-rtc, Ethan Nelson-Moore; +Cc: Heiner Kallweit
In-Reply-To: <20260610054723.261008-1-enelsonmoore@gmail.com>
On Tue, 09 Jun 2026 22:47:22 -0700, Ethan Nelson-Moore wrote:
> The CONFIG_RTC_DRV_DS1307_HWMON macro was removed in favor of
> CONFIG_HWMON in commit 6b583a64fd1e ("rtc: ds1307: simplify hwmon
> config"), but a reference to it remained in a comment. Correct this
> reference.
>
> Discovered while searching for CONFIG_* symbols referenced in code but
> not defined in any Kconfig file.
>
> [...]
Applied, thanks!
[1/1] rtc: ds1307: update reference to removed CONFIG_RTC_DRV_DS1307_HWMON
https://git.kernel.org/abelloni/c/3c8f28578a0d
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: (subset) [PATCH v2 0/2] Fix S0i3 wakeup with alarmtimer
From: Alexandre Belloni @ 2026-06-25 12:43 UTC (permalink / raw)
To: Shyam Sundar S K, Mario Limonciello
Cc: Hans de Goede, Ilpo Järvinen, platform-driver-x86,
linux-kernel, linux-rtc, Thomas Gleixner
In-Reply-To: <20260521043714.1022930-1-mario.limonciello@amd.com>
On Wed, 20 May 2026 23:37:12 -0500, Mario Limonciello wrote:
> It was reported that suspend-then-hibernate stopped working with modern
> systemd versions on AMD Cezanne systems. The reason for this breakage
> was because systemd switched to using alarmtimer instead of the wakealarm
> sysfs file.
>
> But really it uncovered deeper problems with how these timers work. Adjust
> the code accordingly.
>
> [...]
Applied, thanks!
[2/2] platform/x86: amd-pmc: Fix S0i3 wakeup with alarmtimer
https://git.kernel.org/abelloni/c/f7ecfc3fe575
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: (subset) [PATCH v2 1/2] rtc: Add rtc_read_next_alarm() to read next expiring timer
From: Ilpo Järvinen @ 2026-06-25 10:08 UTC (permalink / raw)
To: Mario Limonciello
Cc: Shyam Sundar S K, Hans de Goede, platform-driver-x86, LKML,
linux-rtc, Thomas Gleixner, Alexandre Belloni
In-Reply-To: <9415b405-ec6c-425b-8abb-42964f5a2b3a@amd.com>
On Wed, 24 Jun 2026, Mario Limonciello wrote:
> On 6/24/26 14:15, Alexandre Belloni wrote:
> > On Wed, 20 May 2026 23:37:13 -0500, Mario Limonciello wrote:
> > > Add a new function rtc_read_next_alarm() that reads the next expiring
> > > alarm from the RTC timerqueue. This is different from rtc_read_alarm(),
> > > which only reads the aie_timer.
> > >
> > > The wakealarm sysfs file programs the rtc->aie_timer, whereas the
> > > alarmtimer suspend routine programs its own timer into the RTC timerqueue.
> > > Both timers end up in the RTC's timerqueue, and the first expiring timer
> > > is what gets armed in the hardware.
> > >
> > > [...]
> >
> > Applied, thanks!
> >
> > [1/2] rtc: Add rtc_read_next_alarm() to read next expiring timer
> > https://git.kernel.org/abelloni/c/947d7ea6f60b
> >
> > Best regards,
> >
>
> Thanks!
>
> Ilpo, Shyam,
>
> How do you want to handle patch 2/2? Immutable branch and come through pdx86?
> Or would you rather it go through Alexandre's tree?
It would be easier if it too goes through Alexandre's tree and I don't
expect conflicts on that area. I've replied with my Ack to 2/2.
--
i.
^ permalink raw reply
* Re: [PATCH v2 2/2] platform/x86: amd-pmc: Fix S0i3 wakeup with alarmtimer
From: Ilpo Järvinen @ 2026-06-25 10:06 UTC (permalink / raw)
To: Mario Limonciello
Cc: Shyam Sundar S K, Alexandre Belloni, Hans de Goede,
platform-driver-x86, LKML, linux-rtc, Thomas Gleixner
In-Reply-To: <20260521043714.1022930-3-mario.limonciello@amd.com>
[-- Attachment #1: Type: text/plain, Size: 2080 bytes --]
On Wed, 20 May 2026, Mario Limonciello wrote:
> It was reported that suspend-then-hibernate stopped working with modern
> systemd versions on AMD Cezanne systems. The reason for this breakage
> was because systemd switched to using alarmtimer instead of the wakealarm
> sysfs file.
>
> On AMD Cezanne systems, amd_pmc_verify_czn_rtc() programs a secondary
> timer with the alarm time. This was introduced by
> commit 59348401ebed ("platform/x86: amd-pmc: Add special handling for
> timer based S0i3 wakeup"). However, this function uses rtc_read_alarm(),
> which only reads the aie_timer, not the next expiring timer from the
> timerqueue.
>
> When both alarmtimer and wakealarm are active, the first expiring timer
> might be the alarmtimer, but amd_pmc_verify_czn_rtc() would only see
> the aie_timer, potentially missing the earlier alarm.
>
> Switch to rtc_read_next_alarm() to read whichever timer will fire next.
> Also handle -ENOENT (no alarm pending) explicitly as a non-error case.
>
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3591
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/platform/x86/amd/pmc/pmc.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
> index 50f5784f2aa2e..8cd2db0ccaacd 100644
> --- a/drivers/platform/x86/amd/pmc/pmc.c
> +++ b/drivers/platform/x86/amd/pmc/pmc.c
> @@ -595,9 +595,12 @@ static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
> rtc_device = rtc_class_open("rtc0");
> if (!rtc_device)
> return 0;
> - rc = rtc_read_alarm(rtc_device, &alarm);
> - if (rc)
> - return rc;
> + rc = rtc_read_next_alarm(rtc_device, &alarm);
> + if (rc) {
> + if (rc == -ENOENT)
> + dev_dbg(pdev->dev, "no alarm pending\n");
> + return rc == -ENOENT ? 0 : rc;
> + }
> if (!alarm.enabled) {
> dev_dbg(pdev->dev, "alarm not enabled\n");
> return 0;
Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
--
i.
^ permalink raw reply
* Re: (subset) [PATCH v2 1/2] rtc: Add rtc_read_next_alarm() to read next expiring timer
From: Mario Limonciello @ 2026-06-24 23:30 UTC (permalink / raw)
To: Shyam Sundar S K, Ilpo Järvinen
Cc: Hans de Goede, platform-driver-x86, linux-kernel, linux-rtc,
Thomas Gleixner, Alexandre Belloni
In-Reply-To: <178233558814.1517260.7453046865036017375.b4-ty@b4>
On 6/24/26 14:15, Alexandre Belloni wrote:
> On Wed, 20 May 2026 23:37:13 -0500, Mario Limonciello wrote:
>> Add a new function rtc_read_next_alarm() that reads the next expiring
>> alarm from the RTC timerqueue. This is different from rtc_read_alarm(),
>> which only reads the aie_timer.
>>
>> The wakealarm sysfs file programs the rtc->aie_timer, whereas the
>> alarmtimer suspend routine programs its own timer into the RTC timerqueue.
>> Both timers end up in the RTC's timerqueue, and the first expiring timer
>> is what gets armed in the hardware.
>>
>> [...]
>
> Applied, thanks!
>
> [1/2] rtc: Add rtc_read_next_alarm() to read next expiring timer
> https://git.kernel.org/abelloni/c/947d7ea6f60b
>
> Best regards,
>
Thanks!
Ilpo, Shyam,
How do you want to handle patch 2/2? Immutable branch and come through
pdx86? Or would you rather it go through Alexandre's tree?
Thanks,
^ permalink raw reply
* Re: [PATCH] rtc: cmos: unregister HPET IRQ handler on probe failure
From: Alexandre Belloni @ 2026-06-24 21:49 UTC (permalink / raw)
To: bwalle, akpm, Haoxiang Li; +Cc: linux-rtc, linux-kernel
In-Reply-To: <20260623100848.2127281-1-haoxiang_li2024@163.com>
On Tue, 23 Jun 2026 18:08:48 +0800, Haoxiang Li wrote:
> cmos_do_probe() registers cmos_interrupt() as the HPET RTC IRQ
> handler before requesting the RTC IRQ and registering the RTC
> device. If either request_irq() or devm_rtc_register_device()
> fails afterwards, the error path leaves the HPET RTC IRQ handler
> installed. This leaves a stale handler behind and make a later
> hpet_register_irq_handler() fail with -EBUSY.
>
> [...]
Applied, thanks!
[1/1] rtc: cmos: unregister HPET IRQ handler on probe failure
https://git.kernel.org/abelloni/c/a5bb580df018
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: (subset) [PATCH v2 0/3] rtc: ds1307: Add support for Epson RX8901CE
From: Alexandre Belloni @ 2026-06-24 21:42 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu,
Fredrik M Olsson
Cc: linux-rtc, devicetree, linux-kernel, kernel, Krzysztof Kozlowski,
Nobuhiro Iwamatsu
In-Reply-To: <20260520-ds1307-rx8901-add-v2-0-e069ea32e1db@axis.com>
On Wed, 20 May 2026 16:48:52 +0200, Fredrik M Olsson wrote:
> Add basic support for the Epson RX8901CE RTC.
> Datasheet: https://download.epsondevice.com/td/pdf/app/RX8901CE_en.pdf
>
> Also includes a bug fix for an issue with reading the weekday from the
> RTC which affects both the existing rx8130 and this rx8901 driver.
>
>
> [...]
Applied, thanks!
[1/3] dt-bindings: rtc: ds1307: Add epson,rx8901
https://git.kernel.org/abelloni/c/cc387941c0a1
[2/3] rtc: ds1307: Fix off-by-one issue with wday for rx8130
https://git.kernel.org/abelloni/c/6882aab3c661
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v3] rtc: bq32000: add configurable delay between RTC reads
From: Alexandre Belloni @ 2026-06-24 21:42 UTC (permalink / raw)
To: Adriana Stancu
Cc: linux-rtc, devicetree, linux-kernel, robh, krzk+dt, conor+dt
In-Reply-To: <20260416142151.3385827-1-adriana@arista.com>
On Thu, 16 Apr 2026 07:21:51 -0700, Adriana Stancu wrote:
> When the RTC is used on systems without a interrupt line, userspace
> tools like `hwclock` fall back to a frequent polling loop to synchronize
> with the edge of the next second.
>
> On the BQ32000, this aggressive polling can temporarly lock the register
> refresh cycle, because the continuous transfers prevent the hardware from
> updating the buffer. This results in stale data reads or select() timeouts
> in userspace.
>
> [...]
Applied, thanks!
[1/1] rtc: bq32000: add configurable delay between RTC reads
https://git.kernel.org/abelloni/c/d4992b7050a1
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* Re: [PATCH v2 3/3] rtc: ds1307: Add driver for Epson RX8901CE
From: Alexandre Belloni @ 2026-06-24 21:38 UTC (permalink / raw)
To: Fredrik M Olsson
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu,
linux-rtc, devicetree, linux-kernel, kernel
In-Reply-To: <20260520-ds1307-rx8901-add-v2-3-e069ea32e1db@axis.com>
On 20/05/2026 16:48:55+0200, Fredrik M Olsson wrote:
> +static int do_trickle_setup_rx8901(struct ds1307 *ds1307, u32 ohms __always_unused, bool diode)
> +{
> + int ret;
> + unsigned int setup;
> +
> + ret = regmap_read(ds1307->regmap, RX8901_REG_PWSW_CFG, &setup);
> + if (ret) {
> + dev_err(ds1307->dev, "Failed to read PWSW_CFG register\n");
> + return ret;
> + }
> +
> + /* Enable low battery voltage detection */
> + setup |= RX8901_REG_PWSW_CFG_VBATLDETEN;
> +
> + if (diode)
> + setup |= RX8901_REG_PWSW_CFG_CHGEN;
When diode is false, you need to explicitly clear
RX8901_REG_PWSW_CFG_CHGEN so it is possible to actually disable trickle
charging once it has been enabled has the register is battery backed.
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox