* [PATCH 1/7] rtc: m41t93: add device tree support
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
@ 2025-09-03 14:25 ` Akhilesh Patil
2025-09-03 14:25 ` [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93 Akhilesh Patil
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:25 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Add device tree support for m41t93 rtc by adding of_match_table.
Define compatible string - "st,m41t93" which can be used to instantiate
this rtc device via DT node.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 9444cb5f5190..4e803ff0ce49 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -191,9 +191,16 @@ static int m41t93_probe(struct spi_device *spi)
return 0;
}
+static const struct of_device_id m41t93_dt_match[] = {
+ { .compatible = "st,m41t93" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, m41t93_dt_match);
+
static struct spi_driver m41t93_driver = {
.driver = {
.name = "rtc-m41t93",
+ .of_match_table = m41t93_dt_match,
},
.probe = m41t93_probe,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
2025-09-03 14:25 ` [PATCH 1/7] rtc: m41t93: add device tree support Akhilesh Patil
@ 2025-09-03 14:25 ` Akhilesh Patil
2025-09-03 14:30 ` Krzysztof Kozlowski
2025-09-03 20:33 ` Rob Herring (Arm)
2025-09-03 14:26 ` [PATCH 3/7] rtc: m41t93: migrate to regmap api for register access Akhilesh Patil
` (4 subsequent siblings)
6 siblings, 2 replies; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:25 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
add DT bindings for m41t93 rtc in YAML format.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
.../devicetree/bindings/rtc/st,m41t93.yaml | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/rtc/st,m41t93.yaml
diff --git a/Documentation/devicetree/bindings/rtc/st,m41t93.yaml b/Documentation/devicetree/bindings/rtc/st,m41t93.yaml
new file mode 100644
index 000000000000..03673adc79db
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/st,m41t93.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ST M41T93 RTC and compatible
+
+maintainers:
+ - Alexandre Belloni <alexandre.belloni@bootlin.com>
+
+properties:
+ compatible:
+ enum:
+ - st,m41t93
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 1
+
+allOf:
+ - $ref: rtc.yaml
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rtc@0 {
+ spi-max-frequency = <2000000>;
+ compatible = "st,m41t93";
+ reg = <0>;
+ };
+ };
+
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93
2025-09-03 14:25 ` [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93 Akhilesh Patil
@ 2025-09-03 14:30 ` Krzysztof Kozlowski
2025-09-03 20:33 ` Rob Herring (Arm)
1 sibling, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-03 14:30 UTC (permalink / raw)
To: Akhilesh Patil, alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
On 03/09/2025 16:25, Akhilesh Patil wrote:
> add DT bindings for m41t93 rtc in YAML format.
A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
Please organize the patch documenting compatible (DT bindings) before
their user.
See also:
https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46
>
> Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
> ---
> .../devicetree/bindings/rtc/st,m41t93.yaml | 43 +++++++++++++++++++
> 1 file changed, 43 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/rtc/st,m41t93.yaml
>
> diff --git a/Documentation/devicetree/bindings/rtc/st,m41t93.yaml b/Documentation/devicetree/bindings/rtc/st,m41t93.yaml
> new file mode 100644
> index 000000000000..03673adc79db
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/st,m41t93.yaml
> @@ -0,0 +1,43 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ST M41T93 RTC and compatible
> +
> +maintainers:
> + - Alexandre Belloni <alexandre.belloni@bootlin.com>
This should not be subsystem maintainer.
> +
> +properties:
> + compatible:
> + enum:
> + - st,m41t93
> +
> + reg:
> + maxItems: 1
> +
> + "#clock-cells":
Hm? Are you sure? Nothing in the driver nor commit msg suggests that.
> + const: 1
> +
> +allOf:
> + - $ref: rtc.yaml
> +
> +unevaluatedProperties: false
This goes after required. See example schema.
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + rtc@0 {
> + spi-max-frequency = <2000000>;
Does not look tested.
> + compatible = "st,m41t93";
> + reg = <0>;
Please follow DTS coding style. Which property is the first in the
coding style?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93
2025-09-03 14:25 ` [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93 Akhilesh Patil
2025-09-03 14:30 ` Krzysztof Kozlowski
@ 2025-09-03 20:33 ` Rob Herring (Arm)
1 sibling, 0 replies; 13+ messages in thread
From: Rob Herring (Arm) @ 2025-09-03 20:33 UTC (permalink / raw)
To: Akhilesh Patil
Cc: conor+dt, akhileshpatilvnit, alexandre.belloni, devicetree, skhan,
linux-kernel, linux-rtc, krzk+dt
On Wed, 03 Sep 2025 19:55:59 +0530, Akhilesh Patil wrote:
> add DT bindings for m41t93 rtc in YAML format.
>
> Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
> ---
> .../devicetree/bindings/rtc/st,m41t93.yaml | 43 +++++++++++++++++++
> 1 file changed, 43 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/rtc/st,m41t93.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/rtc/st,m41t93.example.dtb: rtc@0 (st,m41t93): Unevaluated properties are not allowed ('spi-max-frequency' was unexpected)
from schema $id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/40c91cbb07140ecdf4f91afc118c2518e85041c3.1756908788.git.akhilesh@ee.iitb.ac.in
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/7] rtc: m41t93: migrate to regmap api for register access
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
2025-09-03 14:25 ` [PATCH 1/7] rtc: m41t93: add device tree support Akhilesh Patil
2025-09-03 14:25 ` [PATCH 2/7] dt-bindings: rtc: add bindings for m41t93 Akhilesh Patil
@ 2025-09-03 14:26 ` Akhilesh Patil
2025-09-03 14:26 ` [PATCH 4/7] rtc: m41t93: Add alarm support Akhilesh Patil
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:26 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Adapt driver to use regmap api with spi bus instead of direct spi
subsystem calls to access device registers. Simplify and standardize the
register interactions using more abstract and bus agnostic regmap api
to reduce code duplication and improve maintainability. Define spi regmap
config suitable for m41t93 spi bus protocol to achieve same transactions on
spi bus.
Tested on TI am62x sk board with m41t93 rtc chip connected over spi0.
Validated set and get time using hwclock tool and verified spi bus
transfers using logic analyzer.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 121 ++++++++++++++++++++++-----------------
1 file changed, 70 insertions(+), 51 deletions(-)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 4e803ff0ce49..ad862bf706b6 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#define M41T93_REG_SSEC 0
#define M41T93_REG_ST_SEC 1
@@ -31,23 +32,17 @@
#define M41T93_FLAG_BL (1 << 4)
#define M41T93_FLAG_HT (1 << 6)
-static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
-{
- u8 buf[2];
-
- /* MSB must be '1' to write */
- buf[0] = addr | 0x80;
- buf[1] = data;
-
- return spi_write(spi, buf, sizeof(buf));
-}
+struct m41t93_data {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+};
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- int tmp;
- u8 buf[9] = {0x80}; /* write cmd + 8 data bytes */
- u8 * const data = &buf[1]; /* ptr to first data byte */
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int tmp, ret;
+ u8 buf[8] = {0}; /* 8 data bytes */
+ u8 * const data = &buf[0]; /* ptr to first data byte */
dev_dbg(dev, "%s secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -56,31 +51,31 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon, tm->tm_year, tm->tm_wday);
if (tm->tm_year < 100) {
- dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n");
+ dev_warn(dev, "unsupported date (before 2000-01-01).\n");
return -EINVAL;
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
- dev_warn(&spi->dev, "OF bit is set, resetting.\n");
- m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
+ dev_warn(dev, "OF bit is set, resetting.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0) {
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0) {
+ return ret;
} else if (tmp & M41T93_FLAG_OF) {
/* OF cannot be immediately reset: oscillator has to be
* restarted. */
u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
- dev_warn(&spi->dev,
+ dev_warn(dev,
"OF bit is still set, kickstarting clock.\n");
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
reset_osc &= ~M41T93_FLAG_ST;
- m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
+ regmap_write(m41t93->regmap, M41T93_REG_ST_SEC, reset_osc);
}
}
@@ -94,14 +89,13 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
data[M41T93_REG_MON] = bin2bcd(tm->tm_mon + 1);
data[M41T93_REG_YEAR] = bin2bcd(tm->tm_year % 100);
- return spi_write(spi, buf, sizeof(buf));
+ return regmap_bulk_write(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
}
static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- const u8 start_addr = 0;
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
u8 buf[8];
int century_after_1900;
int tmp;
@@ -113,32 +107,32 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
case after poweron. Time is valid after resetting HT bit.
2. oscillator fail bit (OF) is set: time is invalid.
*/
- tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_ALM_HOUR_HT, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_HT) {
- dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n");
- m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT,
- tmp & ~M41T93_FLAG_HT);
+ dev_dbg(dev, "HT bit is set, reenable clock update.\n");
+ regmap_write(m41t93->regmap, M41T93_REG_ALM_HOUR_HT,
+ tmp & ~M41T93_FLAG_HT);
}
- tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
- if (tmp < 0)
- return tmp;
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &tmp);
+ if (ret < 0)
+ return ret;
if (tmp & M41T93_FLAG_OF) {
ret = -EINVAL;
- dev_warn(&spi->dev, "OF bit is set, write time to restart.\n");
+ dev_warn(dev, "OF bit is set, write time to restart.\n");
}
if (tmp & M41T93_FLAG_BL)
- dev_warn(&spi->dev, "BL bit is set, replace battery.\n");
+ dev_warn(dev, "BL bit is set, replace battery.\n");
/* read actual time/date */
- tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf));
- if (tmp < 0)
- return tmp;
+ ret = regmap_bulk_read(m41t93->regmap, M41T93_REG_SSEC, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
tm->tm_sec = bcd2bin(buf[M41T93_REG_ST_SEC]);
tm->tm_min = bcd2bin(buf[M41T93_REG_MIN]);
@@ -167,26 +161,51 @@ static const struct rtc_class_ops m41t93_rtc_ops = {
static struct spi_driver m41t93_driver;
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .read_flag_mask = 0x00,
+ .write_flag_mask = 0x80,
+ .zero_flag_mask = true,
+};
+
static int m41t93_probe(struct spi_device *spi)
{
- struct rtc_device *rtc;
- int res;
+ int res, ret;
+ struct m41t93_data *m41t93;
spi->bits_per_word = 8;
spi_setup(spi);
- res = spi_w8r8(spi, M41T93_REG_WDAY);
+ m41t93 = devm_kzalloc(&spi->dev, sizeof(struct m41t93_data), GFP_KERNEL);
+
+ if (!m41t93)
+ return -ENOMEM;
+
+ /* Set up regmap to access device registers*/
+ m41t93->regmap = devm_regmap_init_spi(spi, ®map_config);
+ if (IS_ERR(m41t93->regmap)) {
+ dev_err(&spi->dev, "regmap init failure\n");
+ return PTR_ERR(m41t93->regmap);
+ }
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_WDAY, &res);
+ if (ret < 0) {
+ dev_err(&spi->dev, "IO error\n");
+ return -EIO;
+ }
+
if (res < 0 || (res & 0xf8) != 0) {
dev_err(&spi->dev, "not found 0x%x.\n", res);
return -ENODEV;
}
- rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
- &m41t93_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+ spi_set_drvdata(spi, m41t93);
- spi_set_drvdata(spi, rtc);
+ m41t93->rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
+ &m41t93_rtc_ops, THIS_MODULE);
+ if (IS_ERR(m41t93->rtc))
+ return PTR_ERR(m41t93->rtc);
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] rtc: m41t93: Add alarm support
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
` (2 preceding siblings ...)
2025-09-03 14:26 ` [PATCH 3/7] rtc: m41t93: migrate to regmap api for register access Akhilesh Patil
@ 2025-09-03 14:26 ` Akhilesh Patil
2025-09-04 5:07 ` kernel test robot
2025-09-03 14:27 ` [PATCH 5/7] rtc: m41t93: fix device connection/detection logic during probe Akhilesh Patil
` (2 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:26 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Implement alarm feature for rtc-m41t93 by adding necessary
callbacks - set_alarm, read_alarm and alarm_irq_enable.
Enable support to configure alarm 1 out of 2 alarms present in this rtc.
Tested by observing IRQ pin (pin 12 of SOX18 package) on logic analyzer
going low after alarm condition is met.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 101 +++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index ad862bf706b6..8cc179e08a4a 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -22,6 +22,14 @@
#define M41T93_REG_DAY 5
#define M41T93_REG_MON 6
#define M41T93_REG_YEAR 7
+#define M41T93_REG_AL1_MONTH 0xa
+#define M41T93_REG_AL1_DATE 0xb
+#define M41T93_REG_AL1_HOUR 0xc
+#define M41T93_REG_AL1_MIN 0xd
+#define M41T93_REG_AL1_SEC 0xe
+#define M41T93_BIT_A1IE BIT(7)
+#define M41T93_BIT_ABE BIT(5)
+#define M41T93_FLAG_AF1 BIT(6)
#define M41T93_REG_ALM_HOUR_HT 0xc
@@ -153,10 +161,103 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
return ret;
}
+static int m41t93_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int ret;
+ unsigned int val;
+ u8 alarm_vals[5] = {0};
+
+ ret = regmap_bulk_write(m41t93->regmap, M41T93_REG_AL1_DATE, alarm_vals, 4);
+ if (ret)
+ return ret;
+
+ /* Set alarm values */
+ alarm_vals[0] = bin2bcd(alrm->time.tm_mon + 1) & 0x1f;
+ alarm_vals[1] = bin2bcd(alrm->time.tm_mday) & 0x3f;
+ alarm_vals[2] = bin2bcd(alrm->time.tm_hour) & 0x3f;
+ alarm_vals[3] = bin2bcd(alrm->time.tm_min) & 0x7f;
+ alarm_vals[4] = bin2bcd(alrm->time.tm_sec) & 0x7f;
+
+ if (alrm->enabled) {
+ /* Enable alarm IRQ generation
+ * Note: SQWE is forced disabled while setting alarm
+ */
+ alarm_vals[0] |= M41T93_BIT_A1IE | M41T93_BIT_ABE;
+ }
+
+ ret = regmap_bulk_write(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ alarm_vals, sizeof(alarm_vals));
+ if (ret)
+ return ret;
+
+ /* Device address pointer is now at FLAG register, move it to other location
+ * to finish setting alarm, as recommended by the datasheet.
+ * We do read of AL1_MONTH register to achieve this.
+ */
+ ret = regmap_read(m41t93->regmap, M41T93_REG_AL1_MONTH, &val);
+ if (ret)
+ return ret;
+
+ if (bcd2bin(val & 0x1f) == (alrm->time.tm_mon & 0x1f))
+ dev_notice(dev, "Alarm set successfully\n");
+
+ return 0;
+}
+
+static int m41t93_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ int ret;
+ unsigned int val;
+ u8 alarm_vals[5] = {0};
+
+ ret = regmap_bulk_read(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ alarm_vals, sizeof(alarm_vals));
+ if (ret)
+ return ret;
+
+ alrm->time.tm_mon = bcd2bin(alarm_vals[0] & 0x1f) - 1;
+ alrm->time.tm_mday = bcd2bin(alarm_vals[1] & 0x3f);
+ alrm->time.tm_hour = bcd2bin(alarm_vals[2] & 0x3f);
+ alrm->time.tm_min = bcd2bin(alarm_vals[3] & 0x7f);
+ alrm->time.tm_sec = bcd2bin(alarm_vals[4] & 0x7f);
+
+ alrm->enabled = !!(alarm_vals[0] & M41T93_BIT_A1IE);
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_FLAGS, &val);
+ if (ret)
+ return ret;
+
+ alrm->pending = (val & M41T93_FLAG_AF1) && alrm->enabled;
+
+ return 0;
+}
+
+static int m41t93_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct m41t93_data *m41t93 = dev_get_drvdata(dev);
+ unsigned int val;
+ int ret;
+
+ val = enabled ? M41T93_BIT_A1IE | M41T93_BIT_ABE :
+ ~(M41T93_BIT_A1IE | M41T93_BIT_ABE);
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_A1IE | M41T93_BIT_ABE, val);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static const struct rtc_class_ops m41t93_rtc_ops = {
.read_time = m41t93_get_time,
.set_time = m41t93_set_time,
+ .set_alarm = m41t93_set_alarm,
+ .read_alarm = m41t93_get_alarm,
+ .alarm_irq_enable = m41t93_alarm_irq_enable,
};
static struct spi_driver m41t93_driver;
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 4/7] rtc: m41t93: Add alarm support
2025-09-03 14:26 ` [PATCH 4/7] rtc: m41t93: Add alarm support Akhilesh Patil
@ 2025-09-04 5:07 ` kernel test robot
0 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-09-04 5:07 UTC (permalink / raw)
To: Akhilesh Patil, alexandre.belloni, krzk+dt, robh, conor+dt
Cc: llvm, oe-kbuild-all, skhan, linux-rtc, devicetree, linux-kernel,
akhileshpatilvnit
Hi Akhilesh,
kernel test robot noticed the following build warnings:
[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on linus/master v6.17-rc4 next-20250903]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Akhilesh-Patil/rtc-m41t93-add-device-tree-support/20250903-223155
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link: https://lore.kernel.org/r/4f78f8fa113d4262e162972f5c15155410a64e8b.1756908788.git.akhilesh%40ee.iitb.ac.in
patch subject: [PATCH 4/7] rtc: m41t93: Add alarm support
config: loongarch-randconfig-002-20250904 (https://download.01.org/0day-ci/archive/20250904/202509041246.7GqISV63-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 2e122990391b2ba062e6308a12cfedf7206270ba)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250904/202509041246.7GqISV63-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/202509041246.7GqISV63-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/rtc/rtc-m41t93.c:244:3: warning: implicit conversion from 'unsigned long' to 'unsigned int' changes value from 18446744073709551455 to 4294967135 [-Wconstant-conversion]
243 | val = enabled ? M41T93_BIT_A1IE | M41T93_BIT_ABE :
| ~
244 | ~(M41T93_BIT_A1IE | M41T93_BIT_ABE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
vim +244 drivers/rtc/rtc-m41t93.c
236
237 static int m41t93_alarm_irq_enable(struct device *dev, unsigned int enabled)
238 {
239 struct m41t93_data *m41t93 = dev_get_drvdata(dev);
240 unsigned int val;
241 int ret;
242
243 val = enabled ? M41T93_BIT_A1IE | M41T93_BIT_ABE :
> 244 ~(M41T93_BIT_A1IE | M41T93_BIT_ABE);
245
246 ret = regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
247 M41T93_BIT_A1IE | M41T93_BIT_ABE, val);
248 if (ret)
249 return ret;
250
251 return 0;
252 }
253
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/7] rtc: m41t93: fix device connection/detection logic during probe
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
` (3 preceding siblings ...)
2025-09-03 14:26 ` [PATCH 4/7] rtc: m41t93: Add alarm support Akhilesh Patil
@ 2025-09-03 14:27 ` Akhilesh Patil
2025-09-03 14:47 ` Alexandre Belloni
2025-09-03 14:27 ` [PATCH 6/7] rtc: m41t93: Add square wave clock provider support Akhilesh Patil
2025-09-03 14:28 ` [PATCH 7/7] rtc: m41t93: Add watchdog support Akhilesh Patil
6 siblings, 1 reply; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:27 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Fix the incorrect assumption about WDAY register (0x4) bits 3 to 7
being 0 after initial power-on to test response from device during probe
Do not expect these bits to be 0 after power on as datasheet does not
explicitly mention these power on defaults but recommends software to
clear these bits during operation. Refer section 3.15 for initial
power-on default bits.
Fix the random probe failures after power on by removing this condition
check. Add alternate response check logic which performs write, read,
compare check on device SRAM register to check device connection.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 8cc179e08a4a..902797070246 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -30,6 +30,7 @@
#define M41T93_BIT_A1IE BIT(7)
#define M41T93_BIT_ABE BIT(5)
#define M41T93_FLAG_AF1 BIT(6)
+#define M41T93_SRAM_BASE 0x19
#define M41T93_REG_ALM_HOUR_HT 0xc
@@ -290,17 +291,25 @@ static int m41t93_probe(struct spi_device *spi)
return PTR_ERR(m41t93->regmap);
}
- ret = regmap_read(m41t93->regmap, M41T93_REG_WDAY, &res);
- if (ret < 0) {
+ ret = regmap_write(m41t93->regmap, M41T93_SRAM_BASE, 0xA5);
+ if (ret) {
dev_err(&spi->dev, "IO error\n");
return -EIO;
}
- if (res < 0 || (res & 0xf8) != 0) {
- dev_err(&spi->dev, "not found 0x%x.\n", res);
+ ret = regmap_read(m41t93->regmap, M41T93_SRAM_BASE, &res);
+ if (ret) {
+ dev_err(&spi->dev, "IO error\n");
+ return -EIO;
+ }
+
+ if (res != 0xA5) {
+ dev_err(&spi->dev, "No valid response from device 0x%x.\n", res);
return -ENODEV;
}
+ dev_notice(&spi->dev, "m41t93 device response success\n");
+
spi_set_drvdata(spi, m41t93);
m41t93->rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 5/7] rtc: m41t93: fix device connection/detection logic during probe
2025-09-03 14:27 ` [PATCH 5/7] rtc: m41t93: fix device connection/detection logic during probe Akhilesh Patil
@ 2025-09-03 14:47 ` Alexandre Belloni
0 siblings, 0 replies; 13+ messages in thread
From: Alexandre Belloni @ 2025-09-03 14:47 UTC (permalink / raw)
To: Akhilesh Patil
Cc: krzk+dt, robh, conor+dt, skhan, linux-rtc, devicetree,
linux-kernel, akhileshpatilvnit
On 03/09/2025 19:57:21+0530, Akhilesh Patil wrote:
> Fix the incorrect assumption about WDAY register (0x4) bits 3 to 7
> being 0 after initial power-on to test response from device during probe
>
> Do not expect these bits to be 0 after power on as datasheet does not
> explicitly mention these power on defaults but recommends software to
> clear these bits during operation. Refer section 3.15 for initial
> power-on default bits.
>
> Fix the random probe failures after power on by removing this condition
> check. Add alternate response check logic which performs write, read,
> compare check on device SRAM register to check device connection.
>
> Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
> ---
> drivers/rtc/rtc-m41t93.c | 17 +++++++++++++----
> 1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
> index 8cc179e08a4a..902797070246 100644
> --- a/drivers/rtc/rtc-m41t93.c
> +++ b/drivers/rtc/rtc-m41t93.c
> @@ -30,6 +30,7 @@
> #define M41T93_BIT_A1IE BIT(7)
> #define M41T93_BIT_ABE BIT(5)
> #define M41T93_FLAG_AF1 BIT(6)
> +#define M41T93_SRAM_BASE 0x19
>
>
> #define M41T93_REG_ALM_HOUR_HT 0xc
> @@ -290,17 +291,25 @@ static int m41t93_probe(struct spi_device *spi)
> return PTR_ERR(m41t93->regmap);
> }
>
> - ret = regmap_read(m41t93->regmap, M41T93_REG_WDAY, &res);
> - if (ret < 0) {
> + ret = regmap_write(m41t93->regmap, M41T93_SRAM_BASE, 0xA5);
Nope, probe is not called at RTC power on but when linux starts. The
whole point of the RTC is to survive Linux. Writing to this register is
breaking functionnality.
> + if (ret) {
> dev_err(&spi->dev, "IO error\n");
> return -EIO;
> }
>
> - if (res < 0 || (res & 0xf8) != 0) {
> - dev_err(&spi->dev, "not found 0x%x.\n", res);
> + ret = regmap_read(m41t93->regmap, M41T93_SRAM_BASE, &res);
> + if (ret) {
> + dev_err(&spi->dev, "IO error\n");
> + return -EIO;
> + }
> +
> + if (res != 0xA5) {
> + dev_err(&spi->dev, "No valid response from device 0x%x.\n", res);
> return -ENODEV;
> }
>
> + dev_notice(&spi->dev, "m41t93 device response success\n");
> +
This is too verbose.
> spi_set_drvdata(spi, m41t93);
>
> m41t93->rtc = devm_rtc_device_register(&spi->dev, m41t93_driver.driver.name,
> --
> 2.34.1
>
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 6/7] rtc: m41t93: Add square wave clock provider support
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
` (4 preceding siblings ...)
2025-09-03 14:27 ` [PATCH 5/7] rtc: m41t93: fix device connection/detection logic during probe Akhilesh Patil
@ 2025-09-03 14:27 ` Akhilesh Patil
2025-09-04 4:42 ` kernel test robot
2025-09-03 14:28 ` [PATCH 7/7] rtc: m41t93: Add watchdog support Akhilesh Patil
6 siblings, 1 reply; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:27 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Implement support to configure square wave output (SQW) of m41t93 rtc
via common clock framework clock provider api. Add clock provider
callbacks to control output frequency ranging from 1Hz to 32KHz as
supported by this rtc chip.
Tested by measuring various frequencies on pull-up connected SWQ(7) pin
of m41t93 rtc chip using logic analyzer.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 154 +++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 902797070246..83cc34c4baae 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -13,6 +13,7 @@
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
+#include <linux/clk-provider.h>
#define M41T93_REG_SSEC 0
#define M41T93_REG_ST_SEC 1
@@ -31,6 +32,10 @@
#define M41T93_BIT_ABE BIT(5)
#define M41T93_FLAG_AF1 BIT(6)
#define M41T93_SRAM_BASE 0x19
+#define M41T93_REG_SQW 0x13
+#define M41T93_SQW_RS_MASK 0xf0
+#define M41T93_SQW_RS_SHIFT 4
+#define M41T93_BIT_SQWE BIT(6)
#define M41T93_REG_ALM_HOUR_HT 0xc
@@ -44,6 +49,9 @@
struct m41t93_data {
struct rtc_device *rtc;
struct regmap *regmap;
+#ifdef CONFIG_COMMON_CLK
+ struct clk_hw clks;
+#endif
};
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
@@ -261,6 +269,146 @@ static const struct rtc_class_ops m41t93_rtc_ops = {
.alarm_irq_enable = m41t93_alarm_irq_enable,
};
+#ifdef CONFIG_COMMON_CLK
+#define clk_sqw_to_m41t93_data(clk) \
+ container_of(clk, struct m41t93_data, clks)
+
+/* m41t93 RTC clock output support */
+static unsigned long m41t93_clk_rates[] = {
+ 0,
+ 32768, /* RS3:RS0 = 0b0001 */
+ 8192,
+ 4096,
+ 2048,
+ 1024,
+ 512,
+ 256,
+ 128,
+ 64,
+ 32,
+ 16,
+ 8,
+ 4,
+ 2,
+ 1, /* RS3:RS0 = 0b1111 */
+};
+
+static unsigned long m41t93_clk_sqw_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ int ret;
+ unsigned int rate_id;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_SQW, &rate_id);
+ if (ret)
+ return ret;
+
+ rate_id &= M41T93_SQW_RS_MASK;
+ rate_id >>= M41T93_SQW_RS_SHIFT;
+
+ return m41t93_clk_rates[rate_id];
+}
+
+static int m41t93_clk_sqw_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(m41t93_clk_rates); i++) {
+ if (req->rate >= m41t93_clk_rates[i]) {
+ req->rate = m41t93_clk_rates[i];
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int m41t93_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int id, ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ for (id = 0; id < ARRAY_SIZE(m41t93_clk_rates); id++) {
+ if (m41t93_clk_rates[id] == rate)
+ break;
+ }
+
+ if (id >= ARRAY_SIZE(m41t93_clk_rates))
+ return -EINVAL;
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_SQW,
+ M41T93_SQW_RS_MASK, id << M41T93_SQW_RS_SHIFT);
+
+ return ret;
+}
+
+static int m41t93_clk_sqw_prepare(struct clk_hw *hw)
+{
+ int ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ ret = regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_SQWE, M41T93_BIT_SQWE);
+
+ return ret;
+}
+
+static void m41t93_clk_sqw_unprepare(struct clk_hw *hw)
+{
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+
+ regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
+ M41T93_BIT_SQWE, ~M41T93_BIT_SQWE);
+}
+
+static int m41t93_clk_sqw_is_prepared(struct clk_hw *hw)
+{
+ int ret;
+ struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
+ unsigned int status;
+
+ ret = regmap_read(m41t93->regmap, M41T93_REG_AL1_MONTH, &status);
+ if (ret)
+ return ret;
+
+ return !!(status & M41T93_BIT_SQWE);
+}
+
+static const struct clk_ops m41t93_clk_sqw_ops = {
+ .prepare = m41t93_clk_sqw_prepare,
+ .unprepare = m41t93_clk_sqw_unprepare,
+ .is_prepared = m41t93_clk_sqw_is_prepared,
+ .recalc_rate = m41t93_clk_sqw_recalc_rate,
+ .set_rate = m41t93_clk_sqw_set_rate,
+ .determine_rate = m41t93_clk_sqw_determine_rate,
+};
+
+static int rtc_m41t93_clks_register(struct device *dev, struct m41t93_data *m41t93)
+{
+ struct device_node *node = dev->of_node;
+ struct clk *clk;
+ struct clk_init_data init = {0};
+
+ init.name = "m41t93_clk_sqw";
+ init.ops = &m41t93_clk_sqw_ops;
+
+ m41t93->clks.init = &init;
+
+ /* Register the clock with CCF */
+ clk = devm_clk_register(dev, &m41t93->clks);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ if (node)
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ return 0;
+}
+#endif
+
static struct spi_driver m41t93_driver;
static const struct regmap_config regmap_config = {
@@ -317,6 +465,12 @@ static int m41t93_probe(struct spi_device *spi)
if (IS_ERR(m41t93->rtc))
return PTR_ERR(m41t93->rtc);
+#ifdef CONFIG_COMMON_CLK
+ ret = rtc_m41t93_clks_register(&spi->dev, m41t93);
+ if (ret)
+ dev_warn(&spi->dev, "Unable to register clock\n");
+#endif
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] rtc: m41t93: Add square wave clock provider support
2025-09-03 14:27 ` [PATCH 6/7] rtc: m41t93: Add square wave clock provider support Akhilesh Patil
@ 2025-09-04 4:42 ` kernel test robot
0 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-09-04 4:42 UTC (permalink / raw)
To: Akhilesh Patil, alexandre.belloni, krzk+dt, robh, conor+dt
Cc: oe-kbuild-all, skhan, linux-rtc, devicetree, linux-kernel,
akhileshpatilvnit
Hi Akhilesh,
kernel test robot noticed the following build warnings:
[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on linus/master v6.17-rc4 next-20250903]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Akhilesh-Patil/rtc-m41t93-add-device-tree-support/20250903-223155
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link: https://lore.kernel.org/r/c53cdf7c2af95160e05cb4db343bb172a88ae7c9.1756908788.git.akhilesh%40ee.iitb.ac.in
patch subject: [PATCH 6/7] rtc: m41t93: Add square wave clock provider support
config: x86_64-buildonly-randconfig-001-20250904 (https://download.01.org/0day-ci/archive/20250904/202509041224.AOsBArcW-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.4.0-5) 12.4.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250904/202509041224.AOsBArcW-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/202509041224.AOsBArcW-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/rtc/rtc-m41t93.c: In function 'm41t93_clk_sqw_unprepare':
>> drivers/rtc/rtc-m41t93.c:364:45: warning: conversion from 'long unsigned int' to 'unsigned int' changes value from '18446744073709551551' to '4294967231' [-Woverflow]
364 | M41T93_BIT_SQWE, ~M41T93_BIT_SQWE);
vim +364 drivers/rtc/rtc-m41t93.c
358
359 static void m41t93_clk_sqw_unprepare(struct clk_hw *hw)
360 {
361 struct m41t93_data *m41t93 = clk_sqw_to_m41t93_data(hw);
362
363 regmap_update_bits(m41t93->regmap, M41T93_REG_AL1_MONTH,
> 364 M41T93_BIT_SQWE, ~M41T93_BIT_SQWE);
365 }
366
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 7/7] rtc: m41t93: Add watchdog support
2025-09-03 14:23 [PATCH 0/7] rtc: m41t93: add new features alarm, clock out, watchdog Akhilesh Patil
` (5 preceding siblings ...)
2025-09-03 14:27 ` [PATCH 6/7] rtc: m41t93: Add square wave clock provider support Akhilesh Patil
@ 2025-09-03 14:28 ` Akhilesh Patil
6 siblings, 0 replies; 13+ messages in thread
From: Akhilesh Patil @ 2025-09-03 14:28 UTC (permalink / raw)
To: alexandre.belloni, krzk+dt, robh, conor+dt
Cc: skhan, linux-rtc, devicetree, linux-kernel, akhileshpatilvnit
Implement watchdog feature driver for m41t93 rtc with 1s resolution and
alarm only mode. Define start, stop, ping, and set_timeout callbacks
as needed by watchdog framework.
Tested by observing IRQ pin(12) going low after intentionally not pinging
watchdog.
Signed-off-by: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
---
drivers/rtc/rtc-m41t93.c | 93 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 83cc34c4baae..e549c5f1e11a 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -14,6 +14,7 @@
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/clk-provider.h>
+#include <linux/watchdog.h>
#define M41T93_REG_SSEC 0
#define M41T93_REG_ST_SEC 1
@@ -36,6 +37,10 @@
#define M41T93_SQW_RS_MASK 0xf0
#define M41T93_SQW_RS_SHIFT 4
#define M41T93_BIT_SQWE BIT(6)
+#define M41T93_REG_WATCHDOG 0x9
+#define M41T93_WDT_RB_MASK 0x3
+#define M41T93_WDT_BMB_MASK 0x7c
+#define M41T93_WDT_BMB_SHIFT 2
#define M41T93_REG_ALM_HOUR_HT 0xc
@@ -52,6 +57,7 @@ struct m41t93_data {
#ifdef CONFIG_COMMON_CLK
struct clk_hw clks;
#endif
+ struct watchdog_device wdd;
};
static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
@@ -409,6 +415,90 @@ static int rtc_m41t93_clks_register(struct device *dev, struct m41t93_data *m41t
}
#endif
+static int m41t93_wdt_ping(struct watchdog_device *wdd)
+{
+ u8 resolution, mult;
+ u8 val = 0;
+ int ret;
+ struct m41t93_data *m41t93 = watchdog_get_drvdata(wdd);
+
+ /* Resolution supported by hardware
+ * 0b00 : 1/16 seconds
+ * 0b01 : 1/4 second
+ * 0b10 : 1 second
+ * 0b11 : 4 seconds
+ */
+ resolution = 0x2; /* hardcode resolution to 1s */
+ mult = wdd->timeout;
+ val = resolution | (mult << M41T93_WDT_BMB_SHIFT & M41T93_WDT_BMB_MASK);
+
+ ret = regmap_write_bits(m41t93->regmap, M41T93_REG_WATCHDOG,
+ M41T93_WDT_RB_MASK | M41T93_WDT_BMB_MASK, val);
+
+ return ret;
+}
+
+static int m41t93_wdt_start(struct watchdog_device *wdd)
+{
+ return m41t93_wdt_ping(wdd);
+}
+
+static int m41t93_wdt_stop(struct watchdog_device *wdd)
+{
+ struct m41t93_data *m41t93 = watchdog_get_drvdata(wdd);
+
+ /* Write 0 to watchdog register */
+ return regmap_write_bits(m41t93->regmap, M41T93_REG_WATCHDOG,
+ M41T93_WDT_RB_MASK | M41T93_WDT_BMB_MASK, 0);
+}
+
+static int m41t93_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int new_timeout)
+{
+ wdd->timeout = new_timeout;
+
+ return 0;
+}
+
+static const struct watchdog_info m41t93_wdt_info = {
+ .identity = "m41t93 rtc Watchdog",
+ .options = WDIOF_ALARMONLY,
+};
+
+static const struct watchdog_ops m41t93_watchdog_ops = {
+ .owner = THIS_MODULE,
+ .start = m41t93_wdt_start,
+ .stop = m41t93_wdt_stop,
+ .ping = m41t93_wdt_ping,
+ .set_timeout = m41t93_wdt_set_timeout,
+};
+
+static int m41t93_watchdog_register(struct device *dev, struct m41t93_data *m41t93)
+{
+ int ret;
+
+ m41t93->wdd.parent = dev;
+ m41t93->wdd.info = &m41t93_wdt_info;
+ m41t93->wdd.ops = &m41t93_watchdog_ops;
+ m41t93->wdd.min_timeout = 0;
+ m41t93->wdd.max_timeout = 10;
+ m41t93->wdd.timeout = 3; /* Default timeout is 3 sec */
+ m41t93->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
+
+ watchdog_set_drvdata(&m41t93->wdd, m41t93);
+
+ ret = devm_watchdog_register_device(dev, &m41t93->wdd);
+ if (ret) {
+ dev_warn(dev, "Failed to register watchdog\n");
+ return ret;
+ }
+
+ /* Disable watchdog at start */
+ ret = m41t93_wdt_stop(&m41t93->wdd);
+
+ return ret;
+}
+
static struct spi_driver m41t93_driver;
static const struct regmap_config regmap_config = {
@@ -470,6 +560,9 @@ static int m41t93_probe(struct spi_device *spi)
if (ret)
dev_warn(&spi->dev, "Unable to register clock\n");
#endif
+ ret = m41t93_watchdog_register(&spi->dev, m41t93);
+ if (ret)
+ dev_warn(&spi->dev, "Unable to register watchdog\n");
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread