* [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
* [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 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 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 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 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 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
* Re: [PATCH v2 3/3] rtc: ds1307: Add driver for Epson RX8901CE
From: Fredrik M Olsson @ 2026-06-29 15:07 UTC (permalink / raw)
To: Alexandre Belloni, Fredrik M Olsson
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu,
linux-rtc, devicetree, linux-kernel, kernel
In-Reply-To: <20260624213847b0e6c315@mail.local>
On 6/24/26 23:38, Alexandre Belloni wrote:
> [Some people who received this message don't often get email from alexandre.belloni@bootlin.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> 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.
Okay thanks I will update that in v3.
--
/Fredrik
^ permalink raw reply
* [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: Fredrik M Olsson @ 2026-06-29 15:13 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Nobuhiro Iwamatsu
Cc: linux-rtc, devicetree, linux-kernel, kernel, Fredrik M Olsson
Adds support for:
- Reading and writing time to/from the RTC.
- Changing Backup Switch Mode (BSM) to DISABLED/DIRECT/LEVEL using the
RTC_PARAM_SET ioctl.
- Optionally enabling battery charging.
- Reading the battery voltage low status using the RTC_VL_READ ioctl
(only supported in LEVEL BSM), which also reports invalid time
information if the VLF flag is set.
Signed-off-by: Fredrik M Olsson <fredrik.m.olsson@axis.com>
---
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.
---
Changes in v3:
- Clear CHGEN when trickle battery charging is disabled.
- Link to v2: https://lore.kernel.org/r/20260520-ds1307-rx8901-add-v2-0-e069ea32e1db@axis.com
Changes in v2:
- Squashed the Voltage Low status patch into the driver patch
- Switch from dev_err to dev_dbg
- Implement Backup Switch Mode (BSM) ioctl instead of hard coding
switching mode.
- Change the prototype for the do_trickle_setup function pointer in
order to make it possible to propagate error codes from the added
PWSW_CFG register read operation. This read operation is added so not
to override previously set register fields.
- Link to v1: https://lore.kernel.org/r/20251219-ds1307-rx8901-add-v1-0-b13f346ebe93@axis.com
---
drivers/rtc/rtc-ds1307.c | 218 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 209 insertions(+), 9 deletions(-)
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 0707ded5368b..488fd1d8d8e3 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -9,6 +9,7 @@
*/
#include <linux/bcd.h>
+#include <linux/bitfield.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kstrtox.h>
@@ -48,6 +49,7 @@ enum ds_type {
mcp794xx,
rx_8025,
rx_8130,
+ rx_8901,
last_ds_type /* always last */
/* rs5c372 too? different address... */
};
@@ -129,6 +131,18 @@ enum ds_type {
#define RX8130_REG_CONTROL1_INIEN BIT(4)
#define RX8130_REG_CONTROL1_CHGEN BIT(5)
+#define RX8901_REG_INTF 0x0e
+#define RX8901_REG_INTF_VLF BIT(1)
+#define RX8901_REG_PWSW_CFG 0x37
+#define RX8901_REG_PWSW_CFG_SWSEL GENMASK(3, 2)
+#define RX8901_REG_PWSW_CFG_VBATLDETEN BIT(4)
+#define RX8901_REG_PWSW_CFG_INIEN BIT(6)
+#define RX8901_REG_PWSW_CFG_CHGEN BIT(7)
+#define RX8901_REG_BUF_INTF 0x46
+#define RX8901_REG_BUF_INTF_VBATLF BIT(3)
+#define RX8901_SWSEL_PRIMARY_BACKUP 0x1
+#define RX8901_SWSEL_PRIMARY 0x2
+
#define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10
# define MCP794XX_BIT_ALM1_EN 0x20
@@ -192,8 +206,8 @@ struct chip_desc {
irq_handler_t irq_handler;
const struct rtc_class_ops *rtc_ops;
u16 trickle_charger_reg;
- u8 (*do_trickle_setup)(struct ds1307 *, u32,
- bool);
+ int (*do_trickle_setup)(struct ds1307 *ds1307, u32 ohms,
+ bool diode);
/* Does the RTC require trickle-resistor-ohms to select the value of
* the resistor between Vcc and Vbackup?
*/
@@ -216,6 +230,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
if (ds1307->type == rx_8130) {
unsigned int regflag;
+
ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, ®flag);
if (ret) {
dev_err(dev, "%s error %d\n", "read", ret);
@@ -226,6 +241,19 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
dev_warn_once(dev, "oscillator failed, set time!\n");
return -EINVAL;
}
+ } else if (ds1307->type == rx_8901) {
+ unsigned int regflag;
+
+ ret = regmap_read(ds1307->regmap, RX8901_REG_INTF, ®flag);
+ if (ret) {
+ dev_dbg(dev, "%s error %d\n", "read", ret);
+ return ret;
+ }
+
+ if (regflag & RX8901_REG_INTF_VLF) {
+ dev_warn_once(dev, "oscillator failed, set time!\n");
+ return -EINVAL;
+ }
}
/* read the RTC date and time registers all at once */
@@ -310,7 +338,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
tmp = regs[DS1307_REG_HOUR] & 0x3f;
t->tm_hour = bcd2bin(tmp);
/* rx8130 is bit position, not BCD */
- if (ds1307->type == rx_8130)
+ if (ds1307->type == rx_8130 || ds1307->type == rx_8901)
t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f) - 1;
else
t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
@@ -361,7 +389,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);
regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
/* rx8130 is bit position, not BCD */
- if (ds1307->type == rx_8130)
+ if (ds1307->type == rx_8130 || ds1307->type == rx_8901)
regs[DS1307_REG_WDAY] = 1 << t->tm_wday;
else
regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
@@ -428,11 +456,132 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
dev_err(dev, "%s error %d\n", "write", result);
return result;
}
+ } else if (ds1307->type == rx_8901) {
+ /*
+ * clear Voltage Loss Flag as data is available now (writing 1
+ * to the other bits in the INTF register has no effect)
+ */
+ result = regmap_write(ds1307->regmap, RX8901_REG_INTF,
+ 0xff ^ RX8901_REG_INTF_VLF);
+ if (result) {
+ dev_dbg(dev, "%s error %d\n", "write", result);
+ return result;
+ }
}
return 0;
}
+#ifdef CONFIG_RTC_INTF_DEV
+static int rx8901_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ unsigned int regflag, tmp = 0;
+ int ret = 0;
+
+ switch (cmd) {
+ case RTC_VL_READ:
+ ret = regmap_read(ds1307->regmap, RX8901_REG_INTF, ®flag);
+ if (ret)
+ return ret;
+
+ if (regflag & RX8901_REG_INTF_VLF)
+ tmp |= RTC_VL_DATA_INVALID;
+
+ ret = regmap_read(ds1307->regmap, RX8901_REG_BUF_INTF, ®flag);
+ if (ret)
+ return ret;
+
+ if (regflag & RX8901_REG_BUF_INTF_VBATLF)
+ tmp |= RTC_VL_BACKUP_LOW;
+
+ return put_user(tmp, (unsigned int __user *)arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return ret;
+}
+
+static int rx8901_param_get(struct device *dev, struct rtc_param *param)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ unsigned int regflag;
+ int ret;
+
+ switch (param->param) {
+ case RTC_PARAM_BACKUP_SWITCH_MODE:
+ ret = regmap_read(ds1307->regmap, RX8901_REG_PWSW_CFG, ®flag);
+ if (ret)
+ return ret;
+
+ if (regflag & RX8901_REG_PWSW_CFG_INIEN) {
+ param->uvalue = RTC_BSM_LEVEL;
+ } else {
+ unsigned int swsel = FIELD_GET(RX8901_REG_PWSW_CFG_SWSEL, regflag);
+
+ if (swsel == RX8901_SWSEL_PRIMARY_BACKUP)
+ param->uvalue = RTC_BSM_DIRECT;
+ else
+ param->uvalue = RTC_BSM_DISABLED;
+ }
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static int rx8901_param_set(struct device *dev, struct rtc_param *param)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ unsigned int regmask;
+ unsigned int regval;
+ int ret;
+
+ switch (param->param) {
+ case RTC_PARAM_BACKUP_SWITCH_MODE:
+
+ switch (param->uvalue) {
+ case RTC_BSM_DISABLED:
+ /* Only main power supply is used */
+ regmask = RX8901_REG_PWSW_CFG_INIEN |
+ RX8901_REG_PWSW_CFG_SWSEL;
+ regval = FIELD_PREP(RX8901_REG_PWSW_CFG_SWSEL,
+ RX8901_SWSEL_PRIMARY) |
+ FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 0);
+ break;
+ case RTC_BSM_DIRECT:
+ /* Main and battery power supply is put in parallel (default) */
+ regmask = RX8901_REG_PWSW_CFG_INIEN |
+ RX8901_REG_PWSW_CFG_SWSEL;
+ regval = FIELD_PREP(RX8901_REG_PWSW_CFG_SWSEL,
+ RX8901_SWSEL_PRIMARY_BACKUP) |
+ FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 0);
+ break;
+ case RTC_BSM_LEVEL:
+ /* Enable auto power switching between main and backup power supply */
+ regmask = RX8901_REG_PWSW_CFG_INIEN;
+ regval = FIELD_PREP(RX8901_REG_PWSW_CFG_INIEN, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = regmap_update_bits(ds1307->regmap, RX8901_REG_PWSW_CFG, regmask, regval);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+#else
+#define rx8901_ioctl NULL
+#define rx8901_param_get NULL
+#define rx8901_param_set NULL
+#endif
+
static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
@@ -539,7 +688,7 @@ static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
enabled ? DS1337_BIT_A1IE : 0);
}
-static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
+static int do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
{
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
DS1307_TRICKLE_CHARGER_NO_DIODE;
@@ -564,7 +713,7 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
return setup;
}
-static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
+static int do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
{
/* make sure that the backup battery is enabled */
u8 setup = RX8130_REG_CONTROL1_INIEN;
@@ -574,6 +723,28 @@ static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
return setup;
}
+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;
+ else
+ setup &= ~RX8901_REG_PWSW_CFG_CHGEN;
+
+ return setup;
+}
+
static irqreturn_t rx8130_irq(int irq, void *dev_id)
{
struct ds1307 *ds1307 = dev_id;
@@ -966,6 +1137,14 @@ static const struct rtc_class_ops rx8130_rtc_ops = {
.alarm_irq_enable = rx8130_alarm_irq_enable,
};
+static const struct rtc_class_ops rx8901_rtc_ops = {
+ .read_time = ds1307_get_time,
+ .set_time = ds1307_set_time,
+ .ioctl = rx8901_ioctl,
+ .param_get = rx8901_param_get,
+ .param_set = rx8901_param_set,
+};
+
static const struct rtc_class_ops mcp794xx_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
@@ -1046,6 +1225,12 @@ static const struct chip_desc chips[last_ds_type] = {
.trickle_charger_reg = RX8130_REG_CONTROL1,
.do_trickle_setup = &do_trickle_setup_rx8130,
},
+ [rx_8901] = {
+ .offset = 0x0,
+ .rtc_ops = &rx8901_rtc_ops,
+ .trickle_charger_reg = RX8901_REG_PWSW_CFG,
+ .do_trickle_setup = &do_trickle_setup_rx8901,
+ },
[m41t0] = {
.rtc_ops = &m41txx_rtc_ops,
},
@@ -1087,6 +1272,7 @@ static const struct i2c_device_id ds1307_id[] = {
{ .name = "rx8025", .driver_data = rx_8025 },
{ .name = "isl12057", .driver_data = ds_1337 },
{ .name = "rx8130", .driver_data = rx_8130 },
+ { .name = "rx8901", .driver_data = rx_8901 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1307_id);
@@ -1164,6 +1350,10 @@ static const struct of_device_id ds1307_of_match[] = {
.compatible = "epson,rx8130",
.data = (void *)rx_8130
},
+ {
+ .compatible = "epson,rx8901",
+ .data = (void *)rx_8901
+ },
{ }
};
MODULE_DEVICE_TABLE(of, ds1307_of_match);
@@ -1298,7 +1488,7 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
/*----------------------------------------------------------------------*/
-static u8 ds1307_trickle_init(struct ds1307 *ds1307,
+static int ds1307_trickle_init(struct ds1307 *ds1307,
const struct chip_desc *chip)
{
u32 ohms, chargeable;
@@ -1886,7 +2076,7 @@ static int ds1307_probe(struct i2c_client *client)
bool ds1307_can_wakeup_device = false;
unsigned char regs[8];
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
- u8 trickle_charger_setup = 0;
+ int trickle_charger_setup = 0;
ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
if (!ds1307)
@@ -1922,12 +2112,15 @@ static int ds1307_probe(struct i2c_client *client)
else if (pdata->trickle_charger_setup)
trickle_charger_setup = pdata->trickle_charger_setup;
+ if (trickle_charger_setup < 0)
+ return trickle_charger_setup;
+
if (trickle_charger_setup && chip->trickle_charger_reg) {
dev_dbg(ds1307->dev,
"writing trickle charger info 0x%x to 0x%x\n",
trickle_charger_setup, chip->trickle_charger_reg);
regmap_write(ds1307->regmap, chip->trickle_charger_reg,
- trickle_charger_setup);
+ (u8)trickle_charger_setup);
}
/*
@@ -2131,6 +2324,13 @@ static int ds1307_probe(struct i2c_client *client)
}
}
+ switch (ds1307->type) {
+ case rx_8901:
+ set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
+ break;
+ default:
+ }
+
ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
err = ds1307_add_frequency_test(ds1307);
if (err)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20251126-ds1307-rx8901-add-a0fe173093e3
Best regards,
--
Fredrik M Olsson <fredrik.m.olsson@axis.com>
^ permalink raw reply related
* Re: [PATCH v2 3/6] clk: sunxi-ng: sun6i-rtc: Add feature bit for IOSC calibration
From: Chen-Yu Tsai @ 2026-06-29 15:25 UTC (permalink / raw)
To: Jerome Brunet
Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk
In-Reply-To: <20260629-a733-rtc-v2-3-7b72112784f8@baylibre.com>
On Mon, Jun 29, 2026 at 8:42 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> 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>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 2/6] clk: sunxi-ng: sun6i-rtc: clean up DT usage
From: Chen-Yu Tsai @ 2026-06-29 15:37 UTC (permalink / raw)
To: Jerome Brunet
Cc: Junhui Liu, Alexandre Belloni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jernej Skrabec, Samuel Holland, Michael Turquette,
Stephen Boyd, Maxime Ripard, linux-rtc, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk
In-Reply-To: <20260629-a733-rtc-v2-2-7b72112784f8@baylibre.com>
On Mon, Jun 29, 2026 at 8:42 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> 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>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
^ permalink raw reply
* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 20:15 UTC (permalink / raw)
To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
Cc: llvm, oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>
Hi Fredrik,
kernel test robot noticed the following build warnings:
[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]
url: https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base: dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link: https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: um-randconfig-002-20260630 (https://download.01.org/0day-ci/archive/20260630/202606300447.wDrgfpSn-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300447.wDrgfpSn-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/202606300447.wDrgfpSn-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/rtc/rtc-ds1307.c:2332:2: warning: label at end of compound statement is a C2x extension [-Wc2x-extensions]
2332 | }
| ^
1 warning generated.
vim +2332 drivers/rtc/rtc-ds1307.c
2066
2067 static int ds1307_probe(struct i2c_client *client)
2068 {
2069 const struct i2c_device_id *id = i2c_client_get_device_id(client);
2070 struct ds1307 *ds1307;
2071 const void *match;
2072 int err = -ENODEV;
2073 int tmp;
2074 const struct chip_desc *chip;
2075 bool want_irq;
2076 bool ds1307_can_wakeup_device = false;
2077 unsigned char regs[8];
2078 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
2079 int trickle_charger_setup = 0;
2080
2081 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
2082 if (!ds1307)
2083 return -ENOMEM;
2084
2085 dev_set_drvdata(&client->dev, ds1307);
2086 ds1307->dev = &client->dev;
2087 ds1307->name = client->name;
2088
2089 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
2090 if (IS_ERR(ds1307->regmap)) {
2091 dev_err(ds1307->dev, "regmap allocation failed\n");
2092 return PTR_ERR(ds1307->regmap);
2093 }
2094
2095 i2c_set_clientdata(client, ds1307);
2096
2097 match = device_get_match_data(&client->dev);
2098 if (match) {
2099 ds1307->type = (uintptr_t)match;
2100 chip = &chips[ds1307->type];
2101 } else if (id) {
2102 chip = &chips[id->driver_data];
2103 ds1307->type = id->driver_data;
2104 } else {
2105 return -ENODEV;
2106 }
2107
2108 want_irq = client->irq > 0 && chip->alarm;
2109
2110 if (!pdata)
2111 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2112 else if (pdata->trickle_charger_setup)
2113 trickle_charger_setup = pdata->trickle_charger_setup;
2114
2115 if (trickle_charger_setup < 0)
2116 return trickle_charger_setup;
2117
2118 if (trickle_charger_setup && chip->trickle_charger_reg) {
2119 dev_dbg(ds1307->dev,
2120 "writing trickle charger info 0x%x to 0x%x\n",
2121 trickle_charger_setup, chip->trickle_charger_reg);
2122 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2123 (u8)trickle_charger_setup);
2124 }
2125
2126 /*
2127 * For devices with no IRQ directly connected to the SoC, the RTC chip
2128 * can be forced as a wakeup source by stating that explicitly in
2129 * the device's .dts file using the "wakeup-source" boolean property.
2130 * If the "wakeup-source" property is set, don't request an IRQ.
2131 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2132 * if supported by the RTC.
2133 */
2134 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2135 ds1307_can_wakeup_device = true;
2136
2137 switch (ds1307->type) {
2138 case ds_1337:
2139 case ds_1339:
2140 case ds_1341:
2141 case ds_3231:
2142 /* get registers that the "rtc" read below won't read... */
2143 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2144 regs, 2);
2145 if (err) {
2146 dev_dbg(ds1307->dev, "read error %d\n", err);
2147 goto exit;
2148 }
2149
2150 /* oscillator off? turn it on, so clock can tick. */
2151 if (regs[0] & DS1337_BIT_nEOSC)
2152 regs[0] &= ~DS1337_BIT_nEOSC;
2153
2154 /*
2155 * Using IRQ or defined as wakeup-source?
2156 * Disable the square wave and both alarms.
2157 * For some variants, be sure alarms can trigger when we're
2158 * running on Vbackup (BBSQI/BBSQW)
2159 */
2160 if (want_irq || ds1307_can_wakeup_device)
2161 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2162
2163 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2164 regs[0]);
2165
2166 /* oscillator fault? warn */
2167 if (regs[1] & DS1337_BIT_OSF) {
2168 dev_warn(ds1307->dev, "SET TIME!\n");
2169 }
2170 break;
2171
2172 case rx_8025:
2173 err = regmap_bulk_read(ds1307->regmap,
2174 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2175 if (err) {
2176 dev_dbg(ds1307->dev, "read error %d\n", err);
2177 goto exit;
2178 }
2179
2180 /* oscillator off? turn it on, so clock can tick. */
2181 if (!(regs[1] & RX8025_BIT_XST)) {
2182 regs[1] |= RX8025_BIT_XST;
2183 regmap_write(ds1307->regmap,
2184 RX8025_REG_CTRL2 << 4 | 0x08,
2185 regs[1]);
2186 dev_warn(ds1307->dev,
2187 "oscillator stop detected - SET TIME!\n");
2188 }
2189
2190 if (regs[1] & RX8025_BIT_PON) {
2191 regs[1] &= ~RX8025_BIT_PON;
2192 regmap_write(ds1307->regmap,
2193 RX8025_REG_CTRL2 << 4 | 0x08,
2194 regs[1]);
2195 dev_warn(ds1307->dev, "power-on detected\n");
2196 }
2197
2198 if (regs[1] & RX8025_BIT_VDET) {
2199 regs[1] &= ~RX8025_BIT_VDET;
2200 regmap_write(ds1307->regmap,
2201 RX8025_REG_CTRL2 << 4 | 0x08,
2202 regs[1]);
2203 dev_warn(ds1307->dev, "voltage drop detected\n");
2204 }
2205
2206 /* make sure we are running in 24hour mode */
2207 if (!(regs[0] & RX8025_BIT_2412)) {
2208 u8 hour;
2209
2210 /* switch to 24 hour mode */
2211 regmap_write(ds1307->regmap,
2212 RX8025_REG_CTRL1 << 4 | 0x08,
2213 regs[0] | RX8025_BIT_2412);
2214
2215 err = regmap_bulk_read(ds1307->regmap,
2216 RX8025_REG_CTRL1 << 4 | 0x08,
2217 regs, 2);
2218 if (err) {
2219 dev_dbg(ds1307->dev, "read error %d\n", err);
2220 goto exit;
2221 }
2222
2223 /* correct hour */
2224 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2225 if (hour == 12)
2226 hour = 0;
2227 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2228 hour += 12;
2229
2230 regmap_write(ds1307->regmap,
2231 DS1307_REG_HOUR << 4 | 0x08, hour);
2232 }
2233 break;
2234 case ds_1388:
2235 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2236 if (err) {
2237 dev_dbg(ds1307->dev, "read error %d\n", err);
2238 goto exit;
2239 }
2240
2241 /* oscillator off? turn it on, so clock can tick. */
2242 if (tmp & DS1388_BIT_nEOSC) {
2243 tmp &= ~DS1388_BIT_nEOSC;
2244 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2245 }
2246 break;
2247 default:
2248 break;
2249 }
2250
2251 /* read RTC registers */
2252 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2253 sizeof(regs));
2254 if (err) {
2255 dev_dbg(ds1307->dev, "read error %d\n", err);
2256 goto exit;
2257 }
2258
2259 if (ds1307->type == mcp794xx &&
2260 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2261 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2262 regs[DS1307_REG_WDAY] |
2263 MCP794XX_BIT_VBATEN);
2264 }
2265
2266 tmp = regs[DS1307_REG_HOUR];
2267 switch (ds1307->type) {
2268 case ds_1340:
2269 case m41t0:
2270 case m41t00:
2271 case m41t11:
2272 /*
2273 * NOTE: ignores century bits; fix before deploying
2274 * systems that will run through year 2100.
2275 */
2276 break;
2277 case rx_8025:
2278 break;
2279 default:
2280 if (!(tmp & DS1307_BIT_12HR))
2281 break;
2282
2283 /*
2284 * Be sure we're in 24 hour mode. Multi-master systems
2285 * take note...
2286 */
2287 tmp = bcd2bin(tmp & 0x1f);
2288 if (tmp == 12)
2289 tmp = 0;
2290 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2291 tmp += 12;
2292 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2293 bin2bcd(tmp));
2294 }
2295
2296 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2297 if (IS_ERR(ds1307->rtc))
2298 return PTR_ERR(ds1307->rtc);
2299
2300 if (want_irq || ds1307_can_wakeup_device)
2301 device_set_wakeup_capable(ds1307->dev, true);
2302 else
2303 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2304
2305 if (ds1307_can_wakeup_device && !want_irq) {
2306 dev_info(ds1307->dev,
2307 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2308 /* We cannot support UIE mode if we do not have an IRQ line */
2309 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
2310 }
2311
2312 if (want_irq) {
2313 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2314 chip->irq_handler ?: ds1307_irq,
2315 IRQF_SHARED | IRQF_ONESHOT,
2316 ds1307->name, ds1307);
2317 if (err) {
2318 client->irq = 0;
2319 device_set_wakeup_capable(ds1307->dev, false);
2320 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2321 dev_err(ds1307->dev, "unable to request IRQ!\n");
2322 } else {
2323 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2324 }
2325 }
2326
2327 switch (ds1307->type) {
2328 case rx_8901:
2329 set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
2330 break;
2331 default:
> 2332 }
2333
2334 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2335 err = ds1307_add_frequency_test(ds1307);
2336 if (err)
2337 return err;
2338
2339 err = devm_rtc_register_device(ds1307->rtc);
2340 if (err)
2341 return err;
2342
2343 if (chip->nvram_size) {
2344 struct nvmem_config nvmem_cfg = {
2345 .name = "ds1307_nvram",
2346 .word_size = 1,
2347 .stride = 1,
2348 .size = chip->nvram_size,
2349 .reg_read = ds1307_nvram_read,
2350 .reg_write = ds1307_nvram_write,
2351 .priv = ds1307,
2352 };
2353
2354 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2355 }
2356
2357 ds1307_hwmon_register(ds1307);
2358 ds1307_clks_register(ds1307);
2359 ds1307_wdt_register(ds1307);
2360
2361 return 0;
2362
2363 exit:
2364 return err;
2365 }
2366
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 21:10 UTC (permalink / raw)
To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
Cc: oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>
Hi Fredrik,
kernel test robot noticed the following build errors:
[auto build test ERROR on dc59e4fea9d83f03bad6bddf3fa2e52491777482]
url: https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base: dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link: https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: sparc64-randconfig-002-20260630 (https://download.01.org/0day-ci/archive/20260630/202606300522.9EnurYvY-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300522.9EnurYvY-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/202606300522.9EnurYvY-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/rtc/rtc-ds1307.c: In function 'ds1307_probe':
>> drivers/rtc/rtc-ds1307.c:2331:2: error: label at end of compound statement
default:
^~~~~~~
vim +2331 drivers/rtc/rtc-ds1307.c
2066
2067 static int ds1307_probe(struct i2c_client *client)
2068 {
2069 const struct i2c_device_id *id = i2c_client_get_device_id(client);
2070 struct ds1307 *ds1307;
2071 const void *match;
2072 int err = -ENODEV;
2073 int tmp;
2074 const struct chip_desc *chip;
2075 bool want_irq;
2076 bool ds1307_can_wakeup_device = false;
2077 unsigned char regs[8];
2078 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
2079 int trickle_charger_setup = 0;
2080
2081 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
2082 if (!ds1307)
2083 return -ENOMEM;
2084
2085 dev_set_drvdata(&client->dev, ds1307);
2086 ds1307->dev = &client->dev;
2087 ds1307->name = client->name;
2088
2089 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
2090 if (IS_ERR(ds1307->regmap)) {
2091 dev_err(ds1307->dev, "regmap allocation failed\n");
2092 return PTR_ERR(ds1307->regmap);
2093 }
2094
2095 i2c_set_clientdata(client, ds1307);
2096
2097 match = device_get_match_data(&client->dev);
2098 if (match) {
2099 ds1307->type = (uintptr_t)match;
2100 chip = &chips[ds1307->type];
2101 } else if (id) {
2102 chip = &chips[id->driver_data];
2103 ds1307->type = id->driver_data;
2104 } else {
2105 return -ENODEV;
2106 }
2107
2108 want_irq = client->irq > 0 && chip->alarm;
2109
2110 if (!pdata)
2111 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2112 else if (pdata->trickle_charger_setup)
2113 trickle_charger_setup = pdata->trickle_charger_setup;
2114
2115 if (trickle_charger_setup < 0)
2116 return trickle_charger_setup;
2117
2118 if (trickle_charger_setup && chip->trickle_charger_reg) {
2119 dev_dbg(ds1307->dev,
2120 "writing trickle charger info 0x%x to 0x%x\n",
2121 trickle_charger_setup, chip->trickle_charger_reg);
2122 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2123 (u8)trickle_charger_setup);
2124 }
2125
2126 /*
2127 * For devices with no IRQ directly connected to the SoC, the RTC chip
2128 * can be forced as a wakeup source by stating that explicitly in
2129 * the device's .dts file using the "wakeup-source" boolean property.
2130 * If the "wakeup-source" property is set, don't request an IRQ.
2131 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2132 * if supported by the RTC.
2133 */
2134 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2135 ds1307_can_wakeup_device = true;
2136
2137 switch (ds1307->type) {
2138 case ds_1337:
2139 case ds_1339:
2140 case ds_1341:
2141 case ds_3231:
2142 /* get registers that the "rtc" read below won't read... */
2143 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2144 regs, 2);
2145 if (err) {
2146 dev_dbg(ds1307->dev, "read error %d\n", err);
2147 goto exit;
2148 }
2149
2150 /* oscillator off? turn it on, so clock can tick. */
2151 if (regs[0] & DS1337_BIT_nEOSC)
2152 regs[0] &= ~DS1337_BIT_nEOSC;
2153
2154 /*
2155 * Using IRQ or defined as wakeup-source?
2156 * Disable the square wave and both alarms.
2157 * For some variants, be sure alarms can trigger when we're
2158 * running on Vbackup (BBSQI/BBSQW)
2159 */
2160 if (want_irq || ds1307_can_wakeup_device)
2161 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2162
2163 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2164 regs[0]);
2165
2166 /* oscillator fault? warn */
2167 if (regs[1] & DS1337_BIT_OSF) {
2168 dev_warn(ds1307->dev, "SET TIME!\n");
2169 }
2170 break;
2171
2172 case rx_8025:
2173 err = regmap_bulk_read(ds1307->regmap,
2174 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2175 if (err) {
2176 dev_dbg(ds1307->dev, "read error %d\n", err);
2177 goto exit;
2178 }
2179
2180 /* oscillator off? turn it on, so clock can tick. */
2181 if (!(regs[1] & RX8025_BIT_XST)) {
2182 regs[1] |= RX8025_BIT_XST;
2183 regmap_write(ds1307->regmap,
2184 RX8025_REG_CTRL2 << 4 | 0x08,
2185 regs[1]);
2186 dev_warn(ds1307->dev,
2187 "oscillator stop detected - SET TIME!\n");
2188 }
2189
2190 if (regs[1] & RX8025_BIT_PON) {
2191 regs[1] &= ~RX8025_BIT_PON;
2192 regmap_write(ds1307->regmap,
2193 RX8025_REG_CTRL2 << 4 | 0x08,
2194 regs[1]);
2195 dev_warn(ds1307->dev, "power-on detected\n");
2196 }
2197
2198 if (regs[1] & RX8025_BIT_VDET) {
2199 regs[1] &= ~RX8025_BIT_VDET;
2200 regmap_write(ds1307->regmap,
2201 RX8025_REG_CTRL2 << 4 | 0x08,
2202 regs[1]);
2203 dev_warn(ds1307->dev, "voltage drop detected\n");
2204 }
2205
2206 /* make sure we are running in 24hour mode */
2207 if (!(regs[0] & RX8025_BIT_2412)) {
2208 u8 hour;
2209
2210 /* switch to 24 hour mode */
2211 regmap_write(ds1307->regmap,
2212 RX8025_REG_CTRL1 << 4 | 0x08,
2213 regs[0] | RX8025_BIT_2412);
2214
2215 err = regmap_bulk_read(ds1307->regmap,
2216 RX8025_REG_CTRL1 << 4 | 0x08,
2217 regs, 2);
2218 if (err) {
2219 dev_dbg(ds1307->dev, "read error %d\n", err);
2220 goto exit;
2221 }
2222
2223 /* correct hour */
2224 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2225 if (hour == 12)
2226 hour = 0;
2227 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2228 hour += 12;
2229
2230 regmap_write(ds1307->regmap,
2231 DS1307_REG_HOUR << 4 | 0x08, hour);
2232 }
2233 break;
2234 case ds_1388:
2235 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2236 if (err) {
2237 dev_dbg(ds1307->dev, "read error %d\n", err);
2238 goto exit;
2239 }
2240
2241 /* oscillator off? turn it on, so clock can tick. */
2242 if (tmp & DS1388_BIT_nEOSC) {
2243 tmp &= ~DS1388_BIT_nEOSC;
2244 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2245 }
2246 break;
2247 default:
2248 break;
2249 }
2250
2251 /* read RTC registers */
2252 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2253 sizeof(regs));
2254 if (err) {
2255 dev_dbg(ds1307->dev, "read error %d\n", err);
2256 goto exit;
2257 }
2258
2259 if (ds1307->type == mcp794xx &&
2260 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2261 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2262 regs[DS1307_REG_WDAY] |
2263 MCP794XX_BIT_VBATEN);
2264 }
2265
2266 tmp = regs[DS1307_REG_HOUR];
2267 switch (ds1307->type) {
2268 case ds_1340:
2269 case m41t0:
2270 case m41t00:
2271 case m41t11:
2272 /*
2273 * NOTE: ignores century bits; fix before deploying
2274 * systems that will run through year 2100.
2275 */
2276 break;
2277 case rx_8025:
2278 break;
2279 default:
2280 if (!(tmp & DS1307_BIT_12HR))
2281 break;
2282
2283 /*
2284 * Be sure we're in 24 hour mode. Multi-master systems
2285 * take note...
2286 */
2287 tmp = bcd2bin(tmp & 0x1f);
2288 if (tmp == 12)
2289 tmp = 0;
2290 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2291 tmp += 12;
2292 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2293 bin2bcd(tmp));
2294 }
2295
2296 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2297 if (IS_ERR(ds1307->rtc))
2298 return PTR_ERR(ds1307->rtc);
2299
2300 if (want_irq || ds1307_can_wakeup_device)
2301 device_set_wakeup_capable(ds1307->dev, true);
2302 else
2303 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2304
2305 if (ds1307_can_wakeup_device && !want_irq) {
2306 dev_info(ds1307->dev,
2307 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2308 /* We cannot support UIE mode if we do not have an IRQ line */
2309 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
2310 }
2311
2312 if (want_irq) {
2313 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2314 chip->irq_handler ?: ds1307_irq,
2315 IRQF_SHARED | IRQF_ONESHOT,
2316 ds1307->name, ds1307);
2317 if (err) {
2318 client->irq = 0;
2319 device_set_wakeup_capable(ds1307->dev, false);
2320 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2321 dev_err(ds1307->dev, "unable to request IRQ!\n");
2322 } else {
2323 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2324 }
2325 }
2326
2327 switch (ds1307->type) {
2328 case rx_8901:
2329 set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
2330 break;
> 2331 default:
2332 }
2333
2334 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2335 err = ds1307_add_frequency_test(ds1307);
2336 if (err)
2337 return err;
2338
2339 err = devm_rtc_register_device(ds1307->rtc);
2340 if (err)
2341 return err;
2342
2343 if (chip->nvram_size) {
2344 struct nvmem_config nvmem_cfg = {
2345 .name = "ds1307_nvram",
2346 .word_size = 1,
2347 .stride = 1,
2348 .size = chip->nvram_size,
2349 .reg_read = ds1307_nvram_read,
2350 .reg_write = ds1307_nvram_write,
2351 .priv = ds1307,
2352 };
2353
2354 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2355 }
2356
2357 ds1307_hwmon_register(ds1307);
2358 ds1307_clks_register(ds1307);
2359 ds1307_wdt_register(ds1307);
2360
2361 return 0;
2362
2363 exit:
2364 return err;
2365 }
2366
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-29 21:10 UTC (permalink / raw)
To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
Cc: llvm, oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>
Hi Fredrik,
kernel test robot noticed the following build warnings:
[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]
url: https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base: dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link: https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20260630/202606300521.DkMaPRKi-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 6cc609bb250b21b47fc7d394b4019101e9983597)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606300521.DkMaPRKi-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/202606300521.DkMaPRKi-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/rtc/rtc-ds1307.c:2332:2: warning: label at end of compound statement is a C23 extension [-Wc23-extensions]
2332 | }
| ^
1 warning generated.
vim +2332 drivers/rtc/rtc-ds1307.c
2066
2067 static int ds1307_probe(struct i2c_client *client)
2068 {
2069 const struct i2c_device_id *id = i2c_client_get_device_id(client);
2070 struct ds1307 *ds1307;
2071 const void *match;
2072 int err = -ENODEV;
2073 int tmp;
2074 const struct chip_desc *chip;
2075 bool want_irq;
2076 bool ds1307_can_wakeup_device = false;
2077 unsigned char regs[8];
2078 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
2079 int trickle_charger_setup = 0;
2080
2081 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
2082 if (!ds1307)
2083 return -ENOMEM;
2084
2085 dev_set_drvdata(&client->dev, ds1307);
2086 ds1307->dev = &client->dev;
2087 ds1307->name = client->name;
2088
2089 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
2090 if (IS_ERR(ds1307->regmap)) {
2091 dev_err(ds1307->dev, "regmap allocation failed\n");
2092 return PTR_ERR(ds1307->regmap);
2093 }
2094
2095 i2c_set_clientdata(client, ds1307);
2096
2097 match = device_get_match_data(&client->dev);
2098 if (match) {
2099 ds1307->type = (uintptr_t)match;
2100 chip = &chips[ds1307->type];
2101 } else if (id) {
2102 chip = &chips[id->driver_data];
2103 ds1307->type = id->driver_data;
2104 } else {
2105 return -ENODEV;
2106 }
2107
2108 want_irq = client->irq > 0 && chip->alarm;
2109
2110 if (!pdata)
2111 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2112 else if (pdata->trickle_charger_setup)
2113 trickle_charger_setup = pdata->trickle_charger_setup;
2114
2115 if (trickle_charger_setup < 0)
2116 return trickle_charger_setup;
2117
2118 if (trickle_charger_setup && chip->trickle_charger_reg) {
2119 dev_dbg(ds1307->dev,
2120 "writing trickle charger info 0x%x to 0x%x\n",
2121 trickle_charger_setup, chip->trickle_charger_reg);
2122 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2123 (u8)trickle_charger_setup);
2124 }
2125
2126 /*
2127 * For devices with no IRQ directly connected to the SoC, the RTC chip
2128 * can be forced as a wakeup source by stating that explicitly in
2129 * the device's .dts file using the "wakeup-source" boolean property.
2130 * If the "wakeup-source" property is set, don't request an IRQ.
2131 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2132 * if supported by the RTC.
2133 */
2134 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2135 ds1307_can_wakeup_device = true;
2136
2137 switch (ds1307->type) {
2138 case ds_1337:
2139 case ds_1339:
2140 case ds_1341:
2141 case ds_3231:
2142 /* get registers that the "rtc" read below won't read... */
2143 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2144 regs, 2);
2145 if (err) {
2146 dev_dbg(ds1307->dev, "read error %d\n", err);
2147 goto exit;
2148 }
2149
2150 /* oscillator off? turn it on, so clock can tick. */
2151 if (regs[0] & DS1337_BIT_nEOSC)
2152 regs[0] &= ~DS1337_BIT_nEOSC;
2153
2154 /*
2155 * Using IRQ or defined as wakeup-source?
2156 * Disable the square wave and both alarms.
2157 * For some variants, be sure alarms can trigger when we're
2158 * running on Vbackup (BBSQI/BBSQW)
2159 */
2160 if (want_irq || ds1307_can_wakeup_device)
2161 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2162
2163 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2164 regs[0]);
2165
2166 /* oscillator fault? warn */
2167 if (regs[1] & DS1337_BIT_OSF) {
2168 dev_warn(ds1307->dev, "SET TIME!\n");
2169 }
2170 break;
2171
2172 case rx_8025:
2173 err = regmap_bulk_read(ds1307->regmap,
2174 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2175 if (err) {
2176 dev_dbg(ds1307->dev, "read error %d\n", err);
2177 goto exit;
2178 }
2179
2180 /* oscillator off? turn it on, so clock can tick. */
2181 if (!(regs[1] & RX8025_BIT_XST)) {
2182 regs[1] |= RX8025_BIT_XST;
2183 regmap_write(ds1307->regmap,
2184 RX8025_REG_CTRL2 << 4 | 0x08,
2185 regs[1]);
2186 dev_warn(ds1307->dev,
2187 "oscillator stop detected - SET TIME!\n");
2188 }
2189
2190 if (regs[1] & RX8025_BIT_PON) {
2191 regs[1] &= ~RX8025_BIT_PON;
2192 regmap_write(ds1307->regmap,
2193 RX8025_REG_CTRL2 << 4 | 0x08,
2194 regs[1]);
2195 dev_warn(ds1307->dev, "power-on detected\n");
2196 }
2197
2198 if (regs[1] & RX8025_BIT_VDET) {
2199 regs[1] &= ~RX8025_BIT_VDET;
2200 regmap_write(ds1307->regmap,
2201 RX8025_REG_CTRL2 << 4 | 0x08,
2202 regs[1]);
2203 dev_warn(ds1307->dev, "voltage drop detected\n");
2204 }
2205
2206 /* make sure we are running in 24hour mode */
2207 if (!(regs[0] & RX8025_BIT_2412)) {
2208 u8 hour;
2209
2210 /* switch to 24 hour mode */
2211 regmap_write(ds1307->regmap,
2212 RX8025_REG_CTRL1 << 4 | 0x08,
2213 regs[0] | RX8025_BIT_2412);
2214
2215 err = regmap_bulk_read(ds1307->regmap,
2216 RX8025_REG_CTRL1 << 4 | 0x08,
2217 regs, 2);
2218 if (err) {
2219 dev_dbg(ds1307->dev, "read error %d\n", err);
2220 goto exit;
2221 }
2222
2223 /* correct hour */
2224 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2225 if (hour == 12)
2226 hour = 0;
2227 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2228 hour += 12;
2229
2230 regmap_write(ds1307->regmap,
2231 DS1307_REG_HOUR << 4 | 0x08, hour);
2232 }
2233 break;
2234 case ds_1388:
2235 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2236 if (err) {
2237 dev_dbg(ds1307->dev, "read error %d\n", err);
2238 goto exit;
2239 }
2240
2241 /* oscillator off? turn it on, so clock can tick. */
2242 if (tmp & DS1388_BIT_nEOSC) {
2243 tmp &= ~DS1388_BIT_nEOSC;
2244 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2245 }
2246 break;
2247 default:
2248 break;
2249 }
2250
2251 /* read RTC registers */
2252 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2253 sizeof(regs));
2254 if (err) {
2255 dev_dbg(ds1307->dev, "read error %d\n", err);
2256 goto exit;
2257 }
2258
2259 if (ds1307->type == mcp794xx &&
2260 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2261 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2262 regs[DS1307_REG_WDAY] |
2263 MCP794XX_BIT_VBATEN);
2264 }
2265
2266 tmp = regs[DS1307_REG_HOUR];
2267 switch (ds1307->type) {
2268 case ds_1340:
2269 case m41t0:
2270 case m41t00:
2271 case m41t11:
2272 /*
2273 * NOTE: ignores century bits; fix before deploying
2274 * systems that will run through year 2100.
2275 */
2276 break;
2277 case rx_8025:
2278 break;
2279 default:
2280 if (!(tmp & DS1307_BIT_12HR))
2281 break;
2282
2283 /*
2284 * Be sure we're in 24 hour mode. Multi-master systems
2285 * take note...
2286 */
2287 tmp = bcd2bin(tmp & 0x1f);
2288 if (tmp == 12)
2289 tmp = 0;
2290 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2291 tmp += 12;
2292 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2293 bin2bcd(tmp));
2294 }
2295
2296 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2297 if (IS_ERR(ds1307->rtc))
2298 return PTR_ERR(ds1307->rtc);
2299
2300 if (want_irq || ds1307_can_wakeup_device)
2301 device_set_wakeup_capable(ds1307->dev, true);
2302 else
2303 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2304
2305 if (ds1307_can_wakeup_device && !want_irq) {
2306 dev_info(ds1307->dev,
2307 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2308 /* We cannot support UIE mode if we do not have an IRQ line */
2309 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
2310 }
2311
2312 if (want_irq) {
2313 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2314 chip->irq_handler ?: ds1307_irq,
2315 IRQF_SHARED | IRQF_ONESHOT,
2316 ds1307->name, ds1307);
2317 if (err) {
2318 client->irq = 0;
2319 device_set_wakeup_capable(ds1307->dev, false);
2320 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2321 dev_err(ds1307->dev, "unable to request IRQ!\n");
2322 } else {
2323 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2324 }
2325 }
2326
2327 switch (ds1307->type) {
2328 case rx_8901:
2329 set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
2330 break;
2331 default:
> 2332 }
2333
2334 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2335 err = ds1307_add_frequency_test(ds1307);
2336 if (err)
2337 return err;
2338
2339 err = devm_rtc_register_device(ds1307->rtc);
2340 if (err)
2341 return err;
2342
2343 if (chip->nvram_size) {
2344 struct nvmem_config nvmem_cfg = {
2345 .name = "ds1307_nvram",
2346 .word_size = 1,
2347 .stride = 1,
2348 .size = chip->nvram_size,
2349 .reg_read = ds1307_nvram_read,
2350 .reg_write = ds1307_nvram_write,
2351 .priv = ds1307,
2352 };
2353
2354 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2355 }
2356
2357 ds1307_hwmon_register(ds1307);
2358 ds1307_clks_register(ds1307);
2359 ds1307_wdt_register(ds1307);
2360
2361 return 0;
2362
2363 exit:
2364 return err;
2365 }
2366
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
From: kernel test robot @ 2026-06-30 2:07 UTC (permalink / raw)
To: Fredrik M Olsson, Alexandre Belloni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Nobuhiro Iwamatsu
Cc: oe-kbuild-all, linux-rtc, devicetree, linux-kernel, kernel,
Fredrik M Olsson
In-Reply-To: <20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e@axis.com>
Hi Fredrik,
kernel test robot noticed the following build warnings:
[auto build test WARNING on dc59e4fea9d83f03bad6bddf3fa2e52491777482]
url: https://github.com/intel-lab-lkp/linux/commits/Fredrik-M-Olsson/rtc-ds1307-Add-driver-for-Epson-RX8901CE/20260629-232253
base: dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link: https://lore.kernel.org/r/20260629-ds1307-rx8901-add-v3-1-302dc3cbb71e%40axis.com
patch subject: [PATCH v3] rtc: ds1307: Add driver for Epson RX8901CE
config: loongarch-randconfig-r132-20260630 (https://download.01.org/0day-ci/archive/20260630/202606301024.GdcSNC79-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 16.1.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260630/202606301024.GdcSNC79-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/202606301024.GdcSNC79-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> drivers/rtc/rtc-ds1307.c:2332:9: sparse: sparse: statement expected after case label
vim +2332 drivers/rtc/rtc-ds1307.c
2066
2067 static int ds1307_probe(struct i2c_client *client)
2068 {
2069 const struct i2c_device_id *id = i2c_client_get_device_id(client);
2070 struct ds1307 *ds1307;
2071 const void *match;
2072 int err = -ENODEV;
2073 int tmp;
2074 const struct chip_desc *chip;
2075 bool want_irq;
2076 bool ds1307_can_wakeup_device = false;
2077 unsigned char regs[8];
2078 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
2079 int trickle_charger_setup = 0;
2080
2081 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
2082 if (!ds1307)
2083 return -ENOMEM;
2084
2085 dev_set_drvdata(&client->dev, ds1307);
2086 ds1307->dev = &client->dev;
2087 ds1307->name = client->name;
2088
2089 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
2090 if (IS_ERR(ds1307->regmap)) {
2091 dev_err(ds1307->dev, "regmap allocation failed\n");
2092 return PTR_ERR(ds1307->regmap);
2093 }
2094
2095 i2c_set_clientdata(client, ds1307);
2096
2097 match = device_get_match_data(&client->dev);
2098 if (match) {
2099 ds1307->type = (uintptr_t)match;
2100 chip = &chips[ds1307->type];
2101 } else if (id) {
2102 chip = &chips[id->driver_data];
2103 ds1307->type = id->driver_data;
2104 } else {
2105 return -ENODEV;
2106 }
2107
2108 want_irq = client->irq > 0 && chip->alarm;
2109
2110 if (!pdata)
2111 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2112 else if (pdata->trickle_charger_setup)
2113 trickle_charger_setup = pdata->trickle_charger_setup;
2114
2115 if (trickle_charger_setup < 0)
2116 return trickle_charger_setup;
2117
2118 if (trickle_charger_setup && chip->trickle_charger_reg) {
2119 dev_dbg(ds1307->dev,
2120 "writing trickle charger info 0x%x to 0x%x\n",
2121 trickle_charger_setup, chip->trickle_charger_reg);
2122 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2123 (u8)trickle_charger_setup);
2124 }
2125
2126 /*
2127 * For devices with no IRQ directly connected to the SoC, the RTC chip
2128 * can be forced as a wakeup source by stating that explicitly in
2129 * the device's .dts file using the "wakeup-source" boolean property.
2130 * If the "wakeup-source" property is set, don't request an IRQ.
2131 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2132 * if supported by the RTC.
2133 */
2134 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2135 ds1307_can_wakeup_device = true;
2136
2137 switch (ds1307->type) {
2138 case ds_1337:
2139 case ds_1339:
2140 case ds_1341:
2141 case ds_3231:
2142 /* get registers that the "rtc" read below won't read... */
2143 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2144 regs, 2);
2145 if (err) {
2146 dev_dbg(ds1307->dev, "read error %d\n", err);
2147 goto exit;
2148 }
2149
2150 /* oscillator off? turn it on, so clock can tick. */
2151 if (regs[0] & DS1337_BIT_nEOSC)
2152 regs[0] &= ~DS1337_BIT_nEOSC;
2153
2154 /*
2155 * Using IRQ or defined as wakeup-source?
2156 * Disable the square wave and both alarms.
2157 * For some variants, be sure alarms can trigger when we're
2158 * running on Vbackup (BBSQI/BBSQW)
2159 */
2160 if (want_irq || ds1307_can_wakeup_device)
2161 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2162
2163 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2164 regs[0]);
2165
2166 /* oscillator fault? warn */
2167 if (regs[1] & DS1337_BIT_OSF) {
2168 dev_warn(ds1307->dev, "SET TIME!\n");
2169 }
2170 break;
2171
2172 case rx_8025:
2173 err = regmap_bulk_read(ds1307->regmap,
2174 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2175 if (err) {
2176 dev_dbg(ds1307->dev, "read error %d\n", err);
2177 goto exit;
2178 }
2179
2180 /* oscillator off? turn it on, so clock can tick. */
2181 if (!(regs[1] & RX8025_BIT_XST)) {
2182 regs[1] |= RX8025_BIT_XST;
2183 regmap_write(ds1307->regmap,
2184 RX8025_REG_CTRL2 << 4 | 0x08,
2185 regs[1]);
2186 dev_warn(ds1307->dev,
2187 "oscillator stop detected - SET TIME!\n");
2188 }
2189
2190 if (regs[1] & RX8025_BIT_PON) {
2191 regs[1] &= ~RX8025_BIT_PON;
2192 regmap_write(ds1307->regmap,
2193 RX8025_REG_CTRL2 << 4 | 0x08,
2194 regs[1]);
2195 dev_warn(ds1307->dev, "power-on detected\n");
2196 }
2197
2198 if (regs[1] & RX8025_BIT_VDET) {
2199 regs[1] &= ~RX8025_BIT_VDET;
2200 regmap_write(ds1307->regmap,
2201 RX8025_REG_CTRL2 << 4 | 0x08,
2202 regs[1]);
2203 dev_warn(ds1307->dev, "voltage drop detected\n");
2204 }
2205
2206 /* make sure we are running in 24hour mode */
2207 if (!(regs[0] & RX8025_BIT_2412)) {
2208 u8 hour;
2209
2210 /* switch to 24 hour mode */
2211 regmap_write(ds1307->regmap,
2212 RX8025_REG_CTRL1 << 4 | 0x08,
2213 regs[0] | RX8025_BIT_2412);
2214
2215 err = regmap_bulk_read(ds1307->regmap,
2216 RX8025_REG_CTRL1 << 4 | 0x08,
2217 regs, 2);
2218 if (err) {
2219 dev_dbg(ds1307->dev, "read error %d\n", err);
2220 goto exit;
2221 }
2222
2223 /* correct hour */
2224 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2225 if (hour == 12)
2226 hour = 0;
2227 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2228 hour += 12;
2229
2230 regmap_write(ds1307->regmap,
2231 DS1307_REG_HOUR << 4 | 0x08, hour);
2232 }
2233 break;
2234 case ds_1388:
2235 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2236 if (err) {
2237 dev_dbg(ds1307->dev, "read error %d\n", err);
2238 goto exit;
2239 }
2240
2241 /* oscillator off? turn it on, so clock can tick. */
2242 if (tmp & DS1388_BIT_nEOSC) {
2243 tmp &= ~DS1388_BIT_nEOSC;
2244 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2245 }
2246 break;
2247 default:
2248 break;
2249 }
2250
2251 /* read RTC registers */
2252 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2253 sizeof(regs));
2254 if (err) {
2255 dev_dbg(ds1307->dev, "read error %d\n", err);
2256 goto exit;
2257 }
2258
2259 if (ds1307->type == mcp794xx &&
2260 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2261 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2262 regs[DS1307_REG_WDAY] |
2263 MCP794XX_BIT_VBATEN);
2264 }
2265
2266 tmp = regs[DS1307_REG_HOUR];
2267 switch (ds1307->type) {
2268 case ds_1340:
2269 case m41t0:
2270 case m41t00:
2271 case m41t11:
2272 /*
2273 * NOTE: ignores century bits; fix before deploying
2274 * systems that will run through year 2100.
2275 */
2276 break;
2277 case rx_8025:
2278 break;
2279 default:
2280 if (!(tmp & DS1307_BIT_12HR))
2281 break;
2282
2283 /*
2284 * Be sure we're in 24 hour mode. Multi-master systems
2285 * take note...
2286 */
2287 tmp = bcd2bin(tmp & 0x1f);
2288 if (tmp == 12)
2289 tmp = 0;
2290 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2291 tmp += 12;
2292 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2293 bin2bcd(tmp));
2294 }
2295
2296 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2297 if (IS_ERR(ds1307->rtc))
2298 return PTR_ERR(ds1307->rtc);
2299
2300 if (want_irq || ds1307_can_wakeup_device)
2301 device_set_wakeup_capable(ds1307->dev, true);
2302 else
2303 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2304
2305 if (ds1307_can_wakeup_device && !want_irq) {
2306 dev_info(ds1307->dev,
2307 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2308 /* We cannot support UIE mode if we do not have an IRQ line */
2309 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
2310 }
2311
2312 if (want_irq) {
2313 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2314 chip->irq_handler ?: ds1307_irq,
2315 IRQF_SHARED | IRQF_ONESHOT,
2316 ds1307->name, ds1307);
2317 if (err) {
2318 client->irq = 0;
2319 device_set_wakeup_capable(ds1307->dev, false);
2320 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2321 dev_err(ds1307->dev, "unable to request IRQ!\n");
2322 } else {
2323 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2324 }
2325 }
2326
2327 switch (ds1307->type) {
2328 case rx_8901:
2329 set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, ds1307->rtc->features);
2330 break;
2331 default:
> 2332 }
2333
2334 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2335 err = ds1307_add_frequency_test(ds1307);
2336 if (err)
2337 return err;
2338
2339 err = devm_rtc_register_device(ds1307->rtc);
2340 if (err)
2341 return err;
2342
2343 if (chip->nvram_size) {
2344 struct nvmem_config nvmem_cfg = {
2345 .name = "ds1307_nvram",
2346 .word_size = 1,
2347 .stride = 1,
2348 .size = chip->nvram_size,
2349 .reg_read = ds1307_nvram_read,
2350 .reg_write = ds1307_nvram_write,
2351 .priv = ds1307,
2352 };
2353
2354 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2355 }
2356
2357 ds1307_hwmon_register(ds1307);
2358 ds1307_clks_register(ds1307);
2359 ds1307_wdt_register(ds1307);
2360
2361 return 0;
2362
2363 exit:
2364 return err;
2365 }
2366
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v1] rtc: mpfs: fix counter upload completion condition
From: Geert Uytterhoeven @ 2026-06-30 15:18 UTC (permalink / raw)
To: Conor Dooley
Cc: linux-riscv, Conor Dooley, stable, Valentina.FernandezAlanis,
Daire McNamara, Alexandre Belloni, linux-rtc, linux-kernel
In-Reply-To: <20260513-panhandle-ashy-70c6abf84d59@spud>
Hi Conor,
On Wed, 13 May 2026 at 20:04, Conor Dooley <conor@kernel.org> wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
>
> The condition that needs to be checked for upload completion is the
> UPLOAD bit in the completion register going low. The original iterations
> of this driver used a do-while and this was converted to a
> read_poll_timeout() during upstreaming without the condition being
> inverted as it should have been.
>
> I suspect that this went unnoticed until now because a) the first read
> was done when the bit was still set, immediately completing the
> read_poll_timeout() and b) because the RTC doesn't hold time when power
> is removed from the SoC reducing its utility (I for one keep it
> disabled). If my first suspicion was true when the driver was
> upstreamed, it's not true any longer though, hence the detection of the
> problem.
>
> Fixes: 0b31d703598dc ("rtc: Add driver for Microchip PolarFire SoC")
> CC: stable@vger.kernel.org
> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Thanks, this landed as commit 9792ff8afa9017fe ("rtc: mpfs: fix counter
upload completion condition") in v7.2-rc1, and finally the endless
stream of:
mpfs_rtc 20124000.rtc: timed out uploading time to rtc
is gone!
And no, it didn't go unnoticed, at least not for me, but you couldn't
reproduce it reliably before:
https://lore.kernel.org/bce2ca405ef96b1363fd1370887409d9e8468422.1660659437.git.geert+renesas@glider.be/
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 1/4] rtc: palmas: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
To: Balakrishnan Sambath
Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-1-29dc9cb6c3f0@microchip.com>
On Thu, 28 May 2026 09:16:44 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
> index aecada6bcf8b..25fe7a8b73a0 100644
> --- a/drivers/rtc/rtc-palmas.c
> +++ b/drivers/rtc/rtc-palmas.c
> @@ -280,10 +278,8 @@ static int palmas_rtc_probe(struct platform_device *pdev)
> ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
> PALMAS_RTC_CTRL_REG_STOP_RTC,
> PALMAS_RTC_CTRL_REG_STOP_RTC);
> - if (ret < 0) {
> - dev_err(&pdev->dev, "RTC_CTRL write failed, err = %d\n", ret);
> - return ret;
> - }
> + if (ret < 0)
> + return dev_err_probe(&pdev->dev, ret, "RTC_CTRL write failed\n");
The enable_bb_charging block earlier in this function (the two
palmas_update_bits() / "BACKUP_BATTERY_CTRL update failed" error paths)
follows the same dev_err()+return ret pattern but is left unconverted.
Converting those too keeps the whole probe consistent.
It's purely about readability, not correctness, so I give my RB.
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
--
Alexandre Mergnat <amergnat@baylibre.com>
^ permalink raw reply
* Re: [PATCH 2/4] rtc: moxart: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
To: Balakrishnan Sambath
Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-2-29dc9cb6c3f0@microchip.com>
On Thu, 28 May 2026 09:16:45 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> Use dev_err_probe() in place of dev_err() and return, which
> communicates the error type and helps debugging hardware issues.
>
> No functional change.
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
--
Alexandre Mergnat <amergnat@baylibre.com>
^ permalink raw reply
* Re: [PATCH 3/4] rtc: sc27xx: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
To: Balakrishnan Sambath
Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-3-29dc9cb6c3f0@microchip.com>
On Thu, 28 May 2026 09:16:46 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> Use dev_err_probe() in place of dev_err() and return, which
> communicates the error type and helps debugging hardware issues.
>
> No functional change.
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
--
Alexandre Mergnat <amergnat@baylibre.com>
^ permalink raw reply
* Re: [PATCH 4/4] rtc: s35390a: convert to dev_err_probe()
From: Alexandre Mergnat @ 2026-06-30 17:10 UTC (permalink / raw)
To: Balakrishnan Sambath
Cc: Alexandre Belloni, Baolin Wang, Chunyan Zhang, Orson Zhai,
linux-kernel, linux-rtc
In-Reply-To: <20260528-cleanup-dev-err-probe-rtc-v1-4-29dc9cb6c3f0@microchip.com>
On Thu, 28 May 2026 09:16:47 +0530, Balakrishnan Sambath <balakrishnan.s@microchip.com> wrote:
> diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
> index a4678d7c6cf6..342fd2b568a3 100644
> --- a/drivers/rtc/rtc-s35390a.c
> +++ b/drivers/rtc/rtc-s35390a.c
> @@ -479,10 +479,8 @@ static int s35390a_probe(struct i2c_client *client)
> return PTR_ERR(rtc);
>
> err_read = s35390a_read_status(s35390a, &status1);
> - if (err_read < 0) {
> - dev_err(dev, "error resetting chip\n");
> - return err_read;
> - }
> + if (err_read < 0)
> + return dev_err_probe(dev, err_read, "error resetting chip\n");
The devm_i2c_new_dummy_device() loop above this hunk still uses
dev_err()+return PTR_ERR("Address %02x unavailable"). dev_err_probe() takes
format args, so it converts cleanly:
return dev_err_probe(dev, PTR_ERR(s35390a->client[i]),
"Address %02x unavailable\n", client->addr + i);
Worth converting for consistency with the rest of the probe.
> @@ -493,16 +491,12 @@ static int s35390a_probe(struct i2c_client *client)
> /* disable alarm (and maybe test mode) */
> buf = 0;
> err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
> - if (err < 0) {
> - dev_err(dev, "error disabling alarm");
> - return err;
> - }
> + if (err < 0)
> + return dev_err_probe(dev, err, "error disabling alarm");
This message is missing its trailing newline (pre-existing). dev_err_probe()
formats as "error %pe: %pV" and does not append "\n" itself, so the line
runs into the next log message. Since you are touching this line, adding
"\n" is a cheap fix even if the issue was here before your patch.
I recommand to fix it ;)
--
Alexandre Mergnat <amergnat@baylibre.com>
^ permalink raw reply
* [PATCH 0/3] rtc: s35390a: Allow use of output pin for interrupt signal 1 for wakealarm
From: Markus Probst @ 2026-06-30 19:22 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth
Cc: linux-arm-kernel, linux-rtc, devicetree, linux-kernel,
Markus Probst
Add a dt property to allow the use of output pin for interrupt signal 1
for wakealarm. This is needed for wakealarms to work on Synology NAS
devices.
It appears there is currently no entry in the MAINTAINERS file for the
S35390A driver. I assume the driver is currently maintained by
Alexandre Belloni.
I hope its fine I added him as maintainer for the newly added devicetree
binding, in order to keep it maintained by the same person.
Also If I am not mistaken, wake alarms on these systems are currently broken:
(not tested, judged by looking at the devicetrees).
- arch/arm/boot/dts/marvell/armada-370-synology-ds213j.dts
- arch/arm/boot/dts/marvell/armada-xp-synology-ds414.dts
- arch/arm/boot/dts/marvell/kirkwood-synology.dtsi
- arch/arm/boot/dts/marvell/kirkwood-ds110jv10.dts
- arch/arm/boot/dts/marvell/kirkwood-ds111.dts
- arch/arm/boot/dts/marvell/kirkwood-ds112.dts
- arch/arm/boot/dts/marvell/kirkwood-ds210.dts
- arch/arm/boot/dts/marvell/kirkwood-ds212.dts
- arch/arm/boot/dts/marvell/kirkwood-ds212j.dts
- arch/arm/boot/dts/marvell/kirkwood-ds411.dts
- arch/arm/boot/dts/marvell/kirkwood-ds411j.dts
- arch/arm/boot/dts/marvell/kirkwood-ds411slim.dts
- arch/arm/boot/dts/marvell/kirkwood-rs212.dts
- arch/arm/boot/dts/marvell/kirkwood-rs411.dts
If thats the case it can be fixed by using this patch series and adding
`sii,wakealarm-output-pin = <S35390A_OUTPUT_PIN_INT1>;` to the
s35390a devicetree.
If somebody still runs one of these systems, please test.
Thanks
- Markus Probst
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Markus Probst (3):
dt-bindings: rtc: Add sii,wakealarm-output-pin property for S35390A
rtc: s35390a: Add missing newline to dev_err
rtc: s35390a: make use of interrupt signal 1
.../devicetree/bindings/rtc/sii,s35390a.yaml | 54 +++++++++++++++++++
.../devicetree/bindings/rtc/trivial-rtc.yaml | 3 --
MAINTAINERS | 1 +
drivers/rtc/rtc-s35390a.c | 63 +++++++++++++++++-----
include/dt-bindings/rtc/s35390a.h | 9 ++++
5 files changed, 114 insertions(+), 16 deletions(-)
---
base-commit: 728e68a889bcf257b1e67298b12c360e5c3a13e0
change-id: 20260630-rtc_s35390a_int1-556ccb308d3f
^ permalink raw reply
* [PATCH 1/3] dt-bindings: rtc: Add sii,wakealarm-output-pin property for S35390A
From: Markus Probst @ 2026-06-30 19:22 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth
Cc: linux-arm-kernel, linux-rtc, devicetree, linux-kernel,
Markus Probst
In-Reply-To: <20260630-rtc_s35390a_int1-v1-0-1b2239e16be2@posteo.de>
Synology NAS devices use the output pin for interrupt signal 1 to wake up
the system.
Move devicetree bindings for sii,s35390a into its own file.
Add sii,wakealarm-output-pin property to enable the use of the output
pin for interrupt signal 1 for the wake alarm, which makes it possible to
set an wake alarm on Synology NAS devices.
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
.../devicetree/bindings/rtc/sii,s35390a.yaml | 54 ++++++++++++++++++++++
.../devicetree/bindings/rtc/trivial-rtc.yaml | 3 --
MAINTAINERS | 1 +
include/dt-bindings/rtc/s35390a.h | 9 ++++
4 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml
new file mode 100644
index 000000000000..31a578673870
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/sii,s35390a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: S-35390A 2-WIRE REAL-TIME CLOCK
+
+maintainers:
+ - Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+description:
+ The S-35390A is a CMOS 2-wire real-time clock IC which operates with the
+ very low current consumption in the wide range of operation voltage.
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ const: sii,s35390a
+
+ reg:
+ maxItems: 1
+
+ sii,wakealarm-output-pin:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2]
+ description: |
+ The output pin to wake up the system.
+ Default will use the output pin for interrupt signal 2.
+ <S35390A_OUTPUT_PIN_INT1> : Output pin for interrupt signal 1
+ <S35390A_OUTPUT_PIN_INT2> : Output pin for interrupt signal 2
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/rtc/s35390a.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc: rtc@30 {
+ compatible = "sii,s35390a";
+ reg = <0x30>;
+ sii,wakealarm-output-pin = <S35390A_OUTPUT_PIN_INT2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
index f4d0eed98a08..7b3f682ef4d5 100644
--- a/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/trivial-rtc.yaml
@@ -81,8 +81,6 @@ properties:
- ricoh,rv5c386
# I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
- ricoh,rv5c387a
- # 2-wire CMOS real-time clock
- - sii,s35390a
# ST SPEAr Real-time Clock
- st,spear600-rtc
# VIA/Wondermedia VT8500 Real-time Clock
@@ -105,5 +103,4 @@ required:
- reg
additionalProperties: false
-
...
diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a9..46a19a0873e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22690,6 +22690,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
F: Documentation/admin-guide/rtc.rst
F: Documentation/devicetree/bindings/rtc/
F: drivers/rtc/
+F: include/dt-bindings/rtc/
F: include/linux/rtc.h
F: include/linux/rtc/
F: include/uapi/linux/rtc.h
diff --git a/include/dt-bindings/rtc/s35390a.h b/include/dt-bindings/rtc/s35390a.h
new file mode 100644
index 000000000000..bd99db118d31
--- /dev/null
+++ b/include/dt-bindings/rtc/s35390a.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+
+#ifndef __DT_BINDINGS_RTC_S35390A_H
+#define __DT_BINDINGS_RTC_S35390A_H
+
+#define S35390A_OUTPUT_PIN_INT1 1
+#define S35390A_OUTPUT_PIN_INT2 2
+
+#endif /* __DT_BINDINGS_RTC_S35390A_H */
--
2.54.0
^ permalink raw reply related
* [PATCH 3/3] rtc: s35390a: make use of interrupt signal 1
From: Markus Probst @ 2026-06-30 19:22 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth
Cc: linux-arm-kernel, linux-rtc, devicetree, linux-kernel,
Markus Probst
In-Reply-To: <20260630-rtc_s35390a_int1-v1-0-1b2239e16be2@posteo.de>
If configured, use output pin for interrupt signal 1 for the wake alarm.
Successfully Tested on a Synology DS923+.
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
drivers/rtc/rtc-s35390a.c | 61 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 49 insertions(+), 12 deletions(-)
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index 4cfe7034c516..6875bf039cbf 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -12,11 +12,13 @@
#include <linux/bcd.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <dt-bindings/rtc/s35390a.h>
#define S35390A_CMD_STATUS1 0
#define S35390A_CMD_STATUS2 1
#define S35390A_CMD_TIME1 2
#define S35390A_CMD_TIME2 3
+#define S35390A_CMD_INT1_REG1 4
#define S35390A_CMD_INT2_REG1 5
#define S35390A_CMD_FREE_REG 7
@@ -36,6 +38,7 @@
#define S35390A_FLAG_POC BIT(0)
#define S35390A_FLAG_BLD BIT(1)
#define S35390A_FLAG_INT2 BIT(2)
+#define S35390A_FLAG_INT1 BIT(3)
#define S35390A_FLAG_24H BIT(6)
#define S35390A_FLAG_RESET BIT(7)
@@ -50,6 +53,14 @@
#define S35390A_INT2_MODE_FREQ BIT(3) /* INT2FE */
#define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */
+/* INT1 pin output mode */
+#define S35390A_INT1_MODE_MASK 0xE0
+#define S35390A_INT1_MODE_NOINTR 0x00
+#define S35390A_INT1_MODE_ALARM BIT(5) /* INT1AE */
+#define S35390A_INT1_MODE_PMIN_EDG BIT(6) /* INT1ME */
+#define S35390A_INT1_MODE_FREQ BIT(7) /* INT1FE */
+#define S35390A_INT1_MODE_PMIN (BIT(7) | BIT(6)) /* INT1FE | INT1ME */
+
static const struct i2c_device_id s35390a_id[] = {
{ .name = "s35390a" },
{ }
@@ -65,6 +76,7 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match);
struct s35390a {
struct i2c_client *client[8];
int twentyfourhour;
+ bool wakealarm_use_int1;
};
static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len)
@@ -275,7 +287,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
u8 buf[3], sts = 0;
- int err, i;
+ int err, i, reg;
dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
"mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec,
@@ -293,9 +305,13 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
return err;
if (alm->enabled)
- sts = S35390A_INT2_MODE_ALARM;
+ sts = s35390a->wakealarm_use_int1
+ ? S35390A_INT1_MODE_ALARM
+ : S35390A_INT2_MODE_ALARM;
else
- sts = S35390A_INT2_MODE_NOINTR;
+ sts = s35390a->wakealarm_use_int1
+ ? S35390A_INT1_MODE_NOINTR
+ : S35390A_INT2_MODE_NOINTR;
/* set interrupt mode*/
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
@@ -317,8 +333,11 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
for (i = 0; i < 3; ++i)
buf[i] = bitrev8(buf[i]);
- err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf,
- sizeof(buf));
+ reg = s35390a->wakealarm_use_int1
+ ? S35390A_CMD_INT1_REG1
+ : S35390A_CMD_INT2_REG1;
+
+ err = s35390a_set_reg(s35390a, reg, buf, sizeof(buf));
return err;
}
@@ -328,13 +347,21 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
struct i2c_client *client = to_i2c_client(dev);
struct s35390a *s35390a = i2c_get_clientdata(client);
u8 buf[3], sts;
- int i, err;
+ int i, err, reg, mask, mode;
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0)
return err;
- if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
+ mask = s35390a->wakealarm_use_int1
+ ? S35390A_INT1_MODE_MASK
+ : S35390A_INT2_MODE_MASK;
+
+ mode = s35390a->wakealarm_use_int1
+ ? S35390A_INT1_MODE_ALARM
+ : S35390A_INT2_MODE_ALARM;
+
+ if ((sts & mask) != mode) {
/*
* When the alarm isn't enabled, the register to configure
* the alarm time isn't accessible.
@@ -345,7 +372,11 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->enabled = 1;
}
- err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
+ reg = s35390a->wakealarm_use_int1
+ ? S35390A_CMD_INT1_REG1
+ : S35390A_CMD_INT2_REG1;
+
+ err = s35390a_get_reg(s35390a, reg, buf, sizeof(buf));
if (err < 0)
return err;
@@ -437,10 +468,10 @@ static int s35390a_nvmem_write(void *priv, unsigned int offset, void *val,
static int s35390a_probe(struct i2c_client *client)
{
int err, err_read;
- unsigned int i;
+ unsigned int i, wakealarm_output_pin = 0;
struct s35390a *s35390a;
struct rtc_device *rtc;
- u8 buf, status1;
+ u8 buf, status1, flag;
struct device *dev = &client->dev;
struct nvmem_config nvmem_cfg = {
.name = "s35390a_nvram",
@@ -452,6 +483,9 @@ static int s35390a_probe(struct i2c_client *client)
.reg_write = s35390a_nvmem_write,
};
+ fwnode_property_read_u32(dev->fwnode, "sii,wakealarm-output-pin",
+ &wakealarm_output_pin);
+
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -460,6 +494,7 @@ static int s35390a_probe(struct i2c_client *client)
return -ENOMEM;
s35390a->client[0] = client;
+ s35390a->wakealarm_use_int1 = wakealarm_output_pin == S35390A_OUTPUT_PIN_INT1;
i2c_set_clientdata(client, s35390a);
/* This chip uses multiple addresses, use dummy devices for them */
@@ -489,7 +524,9 @@ static int s35390a_probe(struct i2c_client *client)
else
s35390a->twentyfourhour = 0;
- if (status1 & S35390A_FLAG_INT2) {
+ flag = s35390a->wakealarm_use_int1 ? S35390A_FLAG_INT1 : S35390A_FLAG_INT2;
+
+ if (status1 & flag) {
/* disable alarm (and maybe test mode) */
buf = 0;
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
@@ -514,7 +551,7 @@ static int s35390a_probe(struct i2c_client *client)
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
- if (status1 & S35390A_FLAG_INT2)
+ if (status1 & flag)
rtc_update_irq(rtc, 1, RTC_AF);
nvmem_cfg.priv = s35390a;
--
2.54.0
^ permalink raw reply related
* [PATCH 2/3] rtc: s35390a: Add missing newline to dev_err
From: Markus Probst @ 2026-06-30 19:22 UTC (permalink / raw)
To: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Andrew Lunn, Gregory Clement,
Sebastian Hesselbarth
Cc: linux-arm-kernel, linux-rtc, devicetree, linux-kernel,
Markus Probst
In-Reply-To: <20260630-rtc_s35390a_int1-v1-0-1b2239e16be2@posteo.de>
Fixes: 3bd32722c827d ("rtc: s35390a: improve irq handling")
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
drivers/rtc/rtc-s35390a.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index b72eef4fb099..4cfe7034c516 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -494,7 +494,7 @@ static int s35390a_probe(struct i2c_client *client)
buf = 0;
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
if (err < 0) {
- dev_err(dev, "error disabling alarm");
+ dev_err(dev, "error disabling alarm\n");
return err;
}
} else {
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 2/3] rtc: s35390a: Add missing newline to dev_err
From: sashiko-bot @ 2026-06-30 19:24 UTC (permalink / raw)
To: Markus Probst; +Cc: Alexandre Belloni, robh, conor+dt, linux-rtc, devicetree
In-Reply-To: <20260630-rtc_s35390a_int1-v1-2-1b2239e16be2@posteo.de>
> Fixes: 3bd32722c827d ("rtc: s35390a: improve irq handling")
> Signed-off-by: Markus Probst <markus.probst@posteo.de>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260630-rtc_s35390a_int1-v1-0-1b2239e16be2@posteo.de?part=2
^ 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