linux-mediatek.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/2] rtc: Add support for MT6685 RTC
@ 2025-10-24  8:33 AngeloGioacchino Del Regno
  2025-10-24  8:33 ` [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock AngeloGioacchino Del Regno
  2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
  0 siblings, 2 replies; 7+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-10-24  8:33 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, kernel

This series adds a driver for the Real Time Clock found in the MT6685
Clock/PM IC.

This chip has been used on a number of different MediaTek platforms
from around 2023 to the latest ones released in 2025 - and on both
Smartphones (Helio and Dimensity), Chromebooks (Kompanio Ultra) and
Genio boards.

This was tested on a MT8196 (Kompanio Ultra) Chromebook.

NOTE: This series depends on series [1] "SPMI: Implement sub-devices
and migrate drivers"

[1]: https://lore.kernel.org/all/20251021083219.17382-1-angelogioacchino.delregno@collabora.com

AngeloGioacchino Del Regno (2):
  dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock
  rtc: Add support for MT6685 Clock IC's RTC over SPMI

 .../bindings/rtc/mediatek,mt6685-rtc.yaml     |  33 ++
 drivers/rtc/Kconfig                           |  12 +
 drivers/rtc/Makefile                          |   1 +
 drivers/rtc/rtc-mt6685.c                      | 472 ++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
 create mode 100644 drivers/rtc/rtc-mt6685.c

-- 
2.51.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock
  2025-10-24  8:33 [PATCH v1 0/2] rtc: Add support for MT6685 RTC AngeloGioacchino Del Regno
@ 2025-10-24  8:33 ` AngeloGioacchino Del Regno
  2025-10-24 16:22   ` Conor Dooley
  2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
  1 sibling, 1 reply; 7+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-10-24  8:33 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, kernel

The MediaTek MT6685 PM / Clock IC contains various SPMI sub
devices, of which two are Real Time Clock IPs, one usually
reserved for the secure world and one for the unsecured one,
reachable at different SPMI addresses.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---

NOTE: This does not contain any example because the MT6685 RTC
      will be added to the mfd binding for MediaTek SPMI PMICs
      and examples will be there.

** For reviewing purposes, this is how the example will look like: **

  - |
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/spmi/spmi.h>

    spmi {
      #address-cells = <2>;
      #size-cells = <0>;

      pmic@9 {
        compatible = "mediatek,mt6363";
        reg = <0x9 SPMI_USID>;
        interrupts = <9 1 IRQ_TYPE_LEVEL_HIGH>;
        interrupt-controller;
        #address-cells = <1>;
        #interrupt-cells = <3>;
        #size-cells = <0>;

        clock-controller@514 {
          compatible = "mediatek,mt6685-sck-top";
          reg = <0x514>;
          #clock-cells = <1>;
        };

        rtc@580 {
          compatible = "mediatek,mt6685-rtc";
          reg = <0x580>;
          interrupts = <9 0 IRQ_TYPE_LEVEL_HIGH>;
        };
      };
    };

 .../bindings/rtc/mediatek,mt6685-rtc.yaml     | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml

diff --git a/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml b/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
new file mode 100644
index 000000000000..1aec163b251a
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/mediatek,mt6685-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6685 PM/Clock IC Real Time Clock
+
+allOf:
+  - $ref: rtc.yaml#
+
+maintainers:
+  - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+properties:
+  compatible:
+    const: mediatek,mt6685-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
-- 
2.51.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
  2025-10-24  8:33 [PATCH v1 0/2] rtc: Add support for MT6685 RTC AngeloGioacchino Del Regno
  2025-10-24  8:33 ` [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock AngeloGioacchino Del Regno
@ 2025-10-24  8:33 ` AngeloGioacchino Del Regno
  2025-10-26  1:37   ` kernel test robot
                     ` (2 more replies)
  1 sibling, 3 replies; 7+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-10-24  8:33 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, kernel

The MT6685 Clock IC is connected over the SPMI bus and includes a
Real Time Clock (RTC) IP.

Like the IP found in the MT6323/57/58/97 PMICs, this RTC ranges
from year 1900 to 2027: for this reason, in this driver the start
date is set to 2/1/1968 instead, matching the intepretation that
is found in most MediaTek bootloaders (which, in too many cases,
cannot be replaced due to OEM signing) and in downstream drivers.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/rtc/Kconfig      |  12 +
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-mt6685.c | 472 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 485 insertions(+)
 create mode 100644 drivers/rtc/rtc-mt6685.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2933c41c77c8..5d14948b3abc 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1937,6 +1937,18 @@ config RTC_DRV_MT6397
 
 	  If you want to use MediaTek(R) RTC interface, select Y or M here.
 
+config RTC_DRV_MT6685
+	tristate "MediaTek MT6685 Clock IC based RTC"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on SPMI
+	select IRQ_DOMAIN
+	help
+	  Say yes here to enable support for the Real Time Clock found
+	  in the MediaTek MT6685 Clock IC communicating over SPMI.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-mt6685.
+
 config RTC_DRV_MT7622
 	tristate "MediaTek SoC based RTC"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8221bda6e6dc..5ccfb1e02e51 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_RTC_DRV_SSD202D)	+= rtc-ssd202d.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
 obj-$(CONFIG_RTC_DRV_MT2712)	+= rtc-mt2712.o
 obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
+obj-$(CONFIG_RTC_DRV_MT6685)	+= rtc-mt6685.o
 obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
 obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o
diff --git a/drivers/rtc/rtc-mt6685.c b/drivers/rtc/rtc-mt6685.c
new file mode 100644
index 000000000000..3e632a3edbb6
--- /dev/null
+++ b/drivers/rtc/rtc-mt6685.c
@@ -0,0 +1,472 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek MT6685 Clock IC - Real Time Clock IP driver
+ *
+ * Copyright (C) 2020 MediaTek Inc.
+ * Copyright (C) 2025 Collabora Ltd.
+ *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/spmi.h>
+
+#define RTC_REG_BBPU			0x8
+#define  RTC_BBPU_PWREN			BIT(0)
+#define  RTC_BBPU_CLR			BIT(1)
+#define  RTC_BBPU_RESET_AL		BIT(3)
+#define  RTC_BBPU_RELOAD		BIT(5)
+#define  RTC_BBPU_CBUSY			BIT(6)
+#define  RTC_BBPU_WR_UNLOCK_KEY		0x4300
+
+#define RTC_REG_IRQ_STA			0xa
+#define RTC_REG_IRQ_EN			0xc
+#define  RTC_IRQ_AL			BIT(0)
+#define  RTC_IRQ_ONESHOT		BIT(2)
+#define  RTC_IRQ_LP			BIT(3)
+
+#define RTC_REG_AL_MASK			0x10
+#define  RTC_AL_MASK_DOW		BIT(4)
+
+#define RTC_REG_TC_SEC			0x12
+#define RTC_REG_AL_SEC			0x20
+#define  RTC_AL_TC_YEAR			GENMASK(6, 0)
+#define  RTC_AL_TC_SEC_MIN		GENMASK(5, 0)
+#define  RTC_AL_TC_HOUR_DOM		GENMASK(4, 0)
+#define  RTC_AL_TC_MON			GENMASK(3, 0)
+#define  RTC_AL_TC_DOW			GENMASK(2, 0)
+
+#define RTC_REG_PDN2			0x36
+#define  RTC_PDN2_PWRON_ALARM		BIT(4)
+
+#define MT6685_RTC_REG_WRTGR		0x42
+
+#define MT6685_RTC_POLL_DELAY_US	10
+#define MT6685_RTC_POLL_TIMEOUT_US	2500
+
+/**
+ * struct mt6885_rtc - Main driver structure
+ * @rdev:     Pointer to RTC device
+ * @regmap:   Regmap (SPMI) Handle
+ * @mclk:     RTC MCLK clock for register write
+ * @irq:      Alarm interrupt number
+ */
+struct mt6685_rtc {
+	struct rtc_device *rdev;
+	struct regmap *regmap;
+	struct clk *mclk;
+	int irq;
+};
+
+/* HW time registers index - please do *not* add or remove indices! */
+enum mt6685_timereg_index {
+	RTC_AL_TC_REGIDX_SEC,
+	RTC_AL_TC_REGIDX_MIN,
+	RTC_AL_TC_REGIDX_HOUR,
+	RTC_AL_TC_REGIDX_DOM,
+	RTC_AL_TC_REGIDX_DOW,
+	RTC_AL_TC_REGIDX_MON,
+	RTC_AL_TC_REGIDX_YEAR,
+	RTC_AL_TC_REGIDX_MAX
+};
+
+/**
+ * rtc_mt6685_write_trigger() - Synchronize registers to the HW
+ * @rtc: Main driver structure
+ *
+ * Writes to the Write Trigger (WRTGR) RTC register to start synchronizing
+ * all of the previous register writes to the hardware.
+ * This is done in order to avoid race conditions in case an alarm fires
+ * during the writing of time registers.
+ *
+ * Context: Mutex lock must be held before calling this function.
+ *          Apart from interrupt handlers inside of this driver, that is
+ *          already taken care of by the RTC API's ops_lock.
+ * Return:  Zero for success or negative error number.
+ */
+static int rtc_mt6685_write_trigger(struct mt6685_rtc *rtc)
+{
+	const u16 val = 1;
+	u32 data;
+	int ret;
+
+	ret = regmap_bulk_write(rtc->regmap, MT6685_RTC_REG_WRTGR, &val, sizeof(val));
+	if (ret)
+		return ret;
+
+	/* The RTC usually takes 7-9uS to update: wait a bit before reading */
+	usleep_range(MT6685_RTC_POLL_DELAY_US, MT6685_RTC_POLL_DELAY_US + 10);
+
+	return regmap_read_poll_timeout(rtc->regmap, RTC_REG_BBPU, data,
+					!(data & RTC_BBPU_CBUSY),
+					MT6685_RTC_POLL_DELAY_US,
+					MT6685_RTC_POLL_TIMEOUT_US);
+}
+
+static irqreturn_t rtc_mt6685_irq_handler_thread(int irq, void *data)
+{
+	u16 irqsta, irqen = 0, bbpu = RTC_BBPU_WR_UNLOCK_KEY | RTC_BBPU_PWREN;
+	struct mt6685_rtc *rtc = data;
+	struct device *dev = &rtc->rdev->dev;
+	int ret;
+
+	ret = clk_prepare_enable(rtc->mclk);
+	if (ret)
+		return IRQ_NONE;
+
+	ret = regmap_bulk_read(rtc->regmap, RTC_REG_IRQ_STA, &irqsta, sizeof(irqsta));
+	if (ret)
+		goto end;
+
+	/* Only alarm interrupts are supported for now */
+	if (!(irqsta & RTC_IRQ_AL)) {
+		ret = -EINVAL;
+		goto end;
+	}
+
+	rtc_lock(rtc->rdev);
+
+	/* Enable BBPU power and clear the interrupt */
+	ret = regmap_bulk_write(rtc->regmap, RTC_REG_BBPU, &bbpu, sizeof(bbpu));
+	if (ret)
+		goto end;
+
+	ret = regmap_bulk_write(rtc->regmap, RTC_REG_IRQ_EN, &irqen, sizeof(irqen));
+	if (ret)
+		goto end;
+
+	/* Trigger reset of the RTC BBPU Alarm */
+	bbpu |= RTC_BBPU_RESET_AL;
+	ret = regmap_bulk_write(rtc->regmap, RTC_REG_BBPU, &bbpu, sizeof(bbpu));
+	if (ret) {
+		dev_err(dev, "Cannot reset alarm: %d\n", ret);
+		goto end;
+	}
+
+	/* Trigger write synchronization */
+	ret = rtc_mt6685_write_trigger(rtc);
+	if (ret) {
+		dev_err(dev, "Cannot synchronize write to RTC: %d\n", ret);
+		goto end;
+	}
+	rtc_update_irq(rtc->rdev, 1, RTC_IRQF | RTC_AF);
+end:
+	rtc_unlock(rtc->rdev);
+	clk_disable_unprepare(rtc->mclk);
+	return ret ? IRQ_NONE : IRQ_HANDLED;
+}
+
+static void rtc_mt6685_reload_bbpu(struct mt6685_rtc *rtc)
+{
+	u16 reload;
+
+	regmap_bulk_read(rtc->regmap, RTC_REG_BBPU, &reload, sizeof(reload));
+	reload |= RTC_BBPU_WR_UNLOCK_KEY | RTC_BBPU_RELOAD;
+	regmap_bulk_write(rtc->regmap, RTC_REG_BBPU, &reload, sizeof(reload));
+
+	rtc_mt6685_write_trigger(rtc);
+}
+
+static int rtc_mt6685_read_time_regs(struct mt6685_rtc *rtc, struct rtc_time *tm, u16 reg)
+{
+	u16 data[RTC_AL_TC_REGIDX_MAX];
+	int ret;
+
+	ret = regmap_bulk_read(rtc->regmap, reg, &data,
+			       RTC_AL_TC_REGIDX_MAX * sizeof(data[0]));
+	if (ret) {
+		dev_err(&rtc->rdev->dev, "Cannot read time regs\n");
+		return ret;
+	}
+
+	tm->tm_sec  = FIELD_GET(RTC_AL_TC_SEC_MIN, data[RTC_AL_TC_REGIDX_SEC]);
+	tm->tm_min  = FIELD_GET(RTC_AL_TC_SEC_MIN, data[RTC_AL_TC_REGIDX_MIN]);
+	tm->tm_hour = FIELD_GET(RTC_AL_TC_HOUR_DOM, data[RTC_AL_TC_REGIDX_HOUR]);
+	tm->tm_mday = FIELD_GET(RTC_AL_TC_HOUR_DOM, data[RTC_AL_TC_REGIDX_DOM]);
+	tm->tm_wday = FIELD_GET(RTC_AL_TC_DOW, data[RTC_AL_TC_REGIDX_DOW]);
+	tm->tm_mon  = FIELD_GET(RTC_AL_TC_MON, data[RTC_AL_TC_REGIDX_MON]);
+	tm->tm_year = FIELD_GET(RTC_AL_TC_YEAR, data[RTC_AL_TC_REGIDX_YEAR]);
+
+	/* HW register start mon/wday from one, but tm_mon/tm_wday start from zero. */
+	tm->tm_mon--;
+	tm->tm_wday--;
+
+	return 0;
+}
+
+static int rtc_mt6685_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+	u16 sec;
+	int ret;
+
+	ret = clk_prepare_enable(rtc->mclk);
+	if (ret)
+		return ret;
+
+	do {
+		rtc_mt6685_reload_bbpu(rtc);
+
+		ret = rtc_mt6685_read_time_regs(rtc, tm, RTC_REG_TC_SEC);
+		if (ret)
+			goto end;
+
+		ret = regmap_bulk_read(rtc->regmap, RTC_REG_TC_SEC, &sec, sizeof(sec));
+		if (ret)
+			goto end;
+	} while ((sec & RTC_AL_TC_SEC_MIN) < tm->tm_sec);
+
+end:
+	clk_disable_unprepare(rtc->mclk);
+	return ret;
+}
+
+static int rtc_mt6685_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+	u16 data[RTC_AL_TC_REGIDX_MAX];
+	int ret;
+
+	ret = clk_prepare_enable(rtc->mclk);
+	if (ret)
+		return ret;
+
+	tm->tm_mon++;
+	tm->tm_wday++;
+
+	data[RTC_AL_TC_REGIDX_SEC] = FIELD_PREP(RTC_AL_TC_SEC_MIN, tm->tm_sec);
+	data[RTC_AL_TC_REGIDX_MIN] = FIELD_PREP(RTC_AL_TC_SEC_MIN, tm->tm_min);
+	data[RTC_AL_TC_REGIDX_HOUR] = FIELD_PREP(RTC_AL_TC_HOUR_DOM, tm->tm_hour);
+	data[RTC_AL_TC_REGIDX_DOM] = FIELD_PREP(RTC_AL_TC_HOUR_DOM, tm->tm_mday);
+	data[RTC_AL_TC_REGIDX_DOW] = FIELD_PREP(RTC_AL_TC_DOW, tm->tm_wday);
+	data[RTC_AL_TC_REGIDX_MON] = FIELD_PREP(RTC_AL_TC_MON, tm->tm_mon);
+	data[RTC_AL_TC_REGIDX_YEAR] = FIELD_PREP(RTC_AL_TC_YEAR, tm->tm_year);
+
+	ret = regmap_bulk_write(rtc->regmap, RTC_REG_TC_SEC, data,
+				RTC_AL_TC_REGIDX_MAX * sizeof(data[0]));
+	if (ret)
+		goto end;
+
+	/* Wait until write is synchronized (means time was set in HW) */
+	ret = rtc_mt6685_write_trigger(rtc);
+end:
+	clk_disable_unprepare(rtc->mclk);
+	return ret;
+}
+
+static int rtc_mt6685_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alm->time;
+	u16 irqen, pdn2;
+	int ret;
+
+	ret = regmap_bulk_read(rtc->regmap, RTC_REG_IRQ_EN, &irqen, sizeof(irqen));
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(rtc->regmap, RTC_REG_PDN2, &pdn2, sizeof(pdn2));
+	if (ret)
+		return ret;
+
+	ret = rtc_mt6685_read_time_regs(rtc, tm, RTC_REG_AL_SEC);
+	if (ret)
+		return ret;
+
+	alm->enabled = FIELD_GET(RTC_IRQ_AL, irqen);
+	alm->pending = FIELD_GET(RTC_PDN2_PWRON_ALARM, pdn2);
+	return 0;
+}
+
+static int rtc_mt6685_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alm->time;
+	u16 data[RTC_AL_TC_REGIDX_MAX];
+	u16 irqen;
+	int ret;
+
+	/*
+	 * Clocks must be enabled when writing and, if that cannot be done,
+	 * reading fields is pointless as the alarm cannot finally be set.
+	 */
+	ret = clk_prepare_enable(rtc->mclk);
+	if (ret)
+		return ret;
+
+	tm->tm_mon++;
+	tm->tm_wday++;
+
+	ret = regmap_bulk_read(rtc->regmap, RTC_REG_IRQ_EN, &irqen, sizeof(irqen));
+	if (ret)
+		goto end;
+
+	ret = regmap_bulk_read(rtc->regmap, RTC_REG_AL_SEC, data,
+			       RTC_AL_TC_REGIDX_MAX * sizeof(data[0]));
+	if (ret)
+		goto end;
+
+	FIELD_MODIFY(RTC_IRQ_AL, &irqen, alm->enabled);
+	FIELD_MODIFY(RTC_AL_TC_SEC_MIN, &data[RTC_AL_TC_REGIDX_SEC], tm->tm_sec);
+	FIELD_MODIFY(RTC_AL_TC_SEC_MIN, &data[RTC_AL_TC_REGIDX_MIN], tm->tm_min);
+	FIELD_MODIFY(RTC_AL_TC_HOUR_DOM, &data[RTC_AL_TC_REGIDX_HOUR], tm->tm_hour);
+	FIELD_MODIFY(RTC_AL_TC_HOUR_DOM, &data[RTC_AL_TC_REGIDX_DOM], tm->tm_mday);
+	FIELD_MODIFY(RTC_AL_TC_DOW, &data[RTC_AL_TC_REGIDX_DOW], tm->tm_wday);
+	FIELD_MODIFY(RTC_AL_TC_MON, &data[RTC_AL_TC_REGIDX_MON], tm->tm_mon);
+	FIELD_MODIFY(RTC_AL_TC_YEAR, &data[RTC_AL_TC_REGIDX_YEAR], tm->tm_year);
+
+	if (alm->enabled) {
+		u16 val = RTC_AL_MASK_DOW;
+
+		ret = regmap_bulk_write(rtc->regmap, RTC_REG_AL_SEC, data,
+					RTC_AL_TC_REGIDX_MAX * sizeof(data[0]));
+		if (ret)
+			goto end;
+
+		ret = regmap_bulk_write(rtc->regmap,
+					RTC_REG_AL_MASK, &val, sizeof(val));
+		if (ret)
+			goto end;
+	}
+
+	ret = regmap_bulk_write(rtc->regmap, RTC_REG_IRQ_EN, &irqen, sizeof(irqen));
+	if (ret)
+		goto end;
+
+	ret = rtc_mt6685_write_trigger(rtc);
+end:
+	clk_disable_unprepare(rtc->mclk);
+	return ret;
+}
+
+static const struct rtc_class_ops rtc_mt6685_ops = {
+	.read_time  = rtc_mt6685_read_time,
+	.set_time   = rtc_mt6685_set_time,
+	.read_alarm = rtc_mt6685_read_alarm,
+	.set_alarm  = rtc_mt6685_set_alarm,
+};
+
+static int rtc_mt6685_probe(struct platform_device *pdev)
+{
+	struct regmap_config mt6685_rtc_regmap_config = {
+		.reg_bits = 16,
+		.val_bits = 8,
+		.max_register = 0x60,
+		.fast_io = true,
+		.use_single_read = true,
+		.use_single_write = true,
+	};
+	struct device *dev = &pdev->dev;
+	struct spmi_subdevice *sub_sdev;
+	struct spmi_device *sparent;
+	struct mt6685_rtc *rtc;
+	int ret;
+
+	rtc = devm_kzalloc(dev, sizeof(struct mt6685_rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	sparent = to_spmi_device(dev->parent);
+	sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
+	if (IS_ERR(sub_sdev))
+		return PTR_ERR(sub_sdev);
+
+	ret = of_property_read_u32(pdev->dev.of_node, "reg",
+				   &mt6685_rtc_regmap_config.reg_base);
+	if (ret)
+		return ret;
+
+	rtc->irq = platform_get_irq(pdev, 0);
+	if (rtc->irq < 0)
+		return rtc->irq;
+
+	rtc->mclk = devm_clk_get(dev, 0);
+	if (IS_ERR(rtc->mclk))
+		return PTR_ERR(rtc->mclk);
+
+	rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
+	if (IS_ERR(rtc->regmap))
+		return PTR_ERR(rtc->regmap);
+
+	rtc->rdev = devm_rtc_allocate_device(dev);
+	if (IS_ERR(rtc->rdev))
+		return PTR_ERR(rtc->rdev);
+
+	platform_set_drvdata(pdev, rtc);
+
+	/* Clock is required to auto-synchronize IRQ enable to RTC */
+	ret = clk_prepare_enable(rtc->mclk);
+	if (ret)
+		return ret;
+
+	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
+					rtc_mt6685_irq_handler_thread,
+					IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+					"mt6685-rtc", rtc);
+	clk_disable_unprepare(rtc->mclk);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Cannot request alarm IRQ");
+
+	device_init_wakeup(&pdev->dev, true);
+
+	rtc->rdev->ops = &rtc_mt6685_ops;
+	rtc->rdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
+	rtc->rdev->range_max = mktime64(2027, 12, 31, 23, 59, 59);
+	rtc->rdev->start_secs = mktime64(1968, 1, 1, 0, 0, 0);
+	rtc->rdev->set_start_time = true;
+
+	return devm_rtc_register_device(rtc->rdev);
+}
+
+static int __maybe_unused rtc_mt6685_suspend(struct device *dev)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(rtc->irq);
+
+	return 0;
+}
+
+static int __maybe_unused rtc_mt6685_resume(struct device *dev)
+{
+	struct mt6685_rtc *rtc = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(rtc->irq);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(rtc_mt6685_pm_ops, rtc_mt6685_suspend, rtc_mt6685_resume);
+
+static const struct of_device_id rtc_mt6685_of_match[] = {
+	{ .compatible = "mediatek,mt6685-rtc" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtc_mt6685_of_match);
+
+static struct platform_driver rtc_mt6685_driver = {
+	.driver = {
+		.name = "rtc-mt6685",
+		.of_match_table = rtc_mt6685_of_match,
+		.pm = &rtc_mt6685_pm_ops,
+	},
+	.probe	= rtc_mt6685_probe,
+};
+module_platform_driver(rtc_mt6685_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("MediaTek MT6685 Clock IC RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("SPMI");
-- 
2.51.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock
  2025-10-24  8:33 ` [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock AngeloGioacchino Del Regno
@ 2025-10-24 16:22   ` Conor Dooley
  0 siblings, 0 replies; 7+ messages in thread
From: Conor Dooley @ 2025-10-24 16:22 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: alexandre.belloni, robh, krzk+dt, conor+dt, matthias.bgg,
	linux-rtc, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, kernel

[-- Attachment #1: Type: text/plain, Size: 2877 bytes --]

On Fri, Oct 24, 2025 at 10:33:17AM +0200, AngeloGioacchino Del Regno wrote:
> The MediaTek MT6685 PM / Clock IC contains various SPMI sub
> devices, of which two are Real Time Clock IPs, one usually
> reserved for the secure world and one for the unsecured one,
> reachable at different SPMI addresses.
> 
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> 
> NOTE: This does not contain any example because the MT6685 RTC
>       will be added to the mfd binding for MediaTek SPMI PMICs
>       and examples will be there.

Were it not for this mfd stuff, could easily go in trivial-rtc.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

> 
> ** For reviewing purposes, this is how the example will look like: **
> 
>   - |
>     #include <dt-bindings/interrupt-controller/irq.h>
>     #include <dt-bindings/spmi/spmi.h>
> 
>     spmi {
>       #address-cells = <2>;
>       #size-cells = <0>;
> 
>       pmic@9 {
>         compatible = "mediatek,mt6363";
>         reg = <0x9 SPMI_USID>;
>         interrupts = <9 1 IRQ_TYPE_LEVEL_HIGH>;
>         interrupt-controller;
>         #address-cells = <1>;
>         #interrupt-cells = <3>;
>         #size-cells = <0>;
> 
>         clock-controller@514 {
>           compatible = "mediatek,mt6685-sck-top";
>           reg = <0x514>;
>           #clock-cells = <1>;
>         };
> 
>         rtc@580 {
>           compatible = "mediatek,mt6685-rtc";
>           reg = <0x580>;
>           interrupts = <9 0 IRQ_TYPE_LEVEL_HIGH>;
>         };
>       };
>     };
> 
>  .../bindings/rtc/mediatek,mt6685-rtc.yaml     | 33 +++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml b/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
> new file mode 100644
> index 000000000000..1aec163b251a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/mediatek,mt6685-rtc.yaml
> @@ -0,0 +1,33 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/rtc/mediatek,mt6685-rtc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT6685 PM/Clock IC Real Time Clock
> +
> +allOf:
> +  - $ref: rtc.yaml#
> +
> +maintainers:
> +  - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt6685-rtc
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +
> +unevaluatedProperties: false
> -- 
> 2.51.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
  2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
@ 2025-10-26  1:37   ` kernel test robot
  2025-10-26  5:13   ` kernel test robot
  2025-10-30 17:27   ` Alexandre Belloni
  2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2025-10-26  1:37 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, alexandre.belloni
  Cc: oe-kbuild-all, robh, krzk+dt, conor+dt, matthias.bgg,
	angelogioacchino.delregno, linux-rtc, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, kernel

Hi AngeloGioacchino,

kernel test robot noticed the following build errors:

[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on robh/for-next linus/master v6.18-rc2 next-20251024]
[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/AngeloGioacchino-Del-Regno/dt-bindings-rtc-Add-MediaTek-MT6685-PM-Clock-IC-Real-Time-Clock/20251024-164423
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20251024083318.25890-3-angelogioacchino.delregno%40collabora.com
patch subject: [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20251026/202510260921.IcI6vsTN-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251026/202510260921.IcI6vsTN-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/202510260921.IcI6vsTN-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/rtc/rtc-mt6685.c: In function 'rtc_mt6685_probe':
>> drivers/rtc/rtc-mt6685.c:380:20: error: implicit declaration of function 'devm_spmi_subdevice_alloc_and_add' [-Wimplicit-function-declaration]
     380 |         sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
         |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/rtc/rtc-mt6685.c:380:18: error: assignment to 'struct spmi_subdevice *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     380 |         sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
         |                  ^
   In file included from drivers/rtc/rtc-mt6685.c:20:
>> drivers/rtc/rtc-mt6685.c:397:58: error: invalid use of undefined type 'struct spmi_subdevice'
     397 |         rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
         |                                                          ^~
   include/linux/regmap.h:782:52: note: in definition of macro '__regmap_lockdep_wrapper'
     782 | #define __regmap_lockdep_wrapper(fn, name, ...) fn(__VA_ARGS__, NULL, NULL)
         |                                                    ^~~~~~~~~~~
   drivers/rtc/rtc-mt6685.c:397:23: note: in expansion of macro 'devm_regmap_init_spmi_ext'
     397 |         rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
         |                       ^~~~~~~~~~~~~~~~~~~~~~~~~


vim +/devm_spmi_subdevice_alloc_and_add +380 drivers/rtc/rtc-mt6685.c

   358	
   359	static int rtc_mt6685_probe(struct platform_device *pdev)
   360	{
   361		struct regmap_config mt6685_rtc_regmap_config = {
   362			.reg_bits = 16,
   363			.val_bits = 8,
   364			.max_register = 0x60,
   365			.fast_io = true,
   366			.use_single_read = true,
   367			.use_single_write = true,
   368		};
   369		struct device *dev = &pdev->dev;
   370		struct spmi_subdevice *sub_sdev;
   371		struct spmi_device *sparent;
   372		struct mt6685_rtc *rtc;
   373		int ret;
   374	
   375		rtc = devm_kzalloc(dev, sizeof(struct mt6685_rtc), GFP_KERNEL);
   376		if (!rtc)
   377			return -ENOMEM;
   378	
   379		sparent = to_spmi_device(dev->parent);
 > 380		sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
   381		if (IS_ERR(sub_sdev))
   382			return PTR_ERR(sub_sdev);
   383	
   384		ret = of_property_read_u32(pdev->dev.of_node, "reg",
   385					   &mt6685_rtc_regmap_config.reg_base);
   386		if (ret)
   387			return ret;
   388	
   389		rtc->irq = platform_get_irq(pdev, 0);
   390		if (rtc->irq < 0)
   391			return rtc->irq;
   392	
   393		rtc->mclk = devm_clk_get(dev, 0);
   394		if (IS_ERR(rtc->mclk))
   395			return PTR_ERR(rtc->mclk);
   396	
 > 397		rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
   398		if (IS_ERR(rtc->regmap))
   399			return PTR_ERR(rtc->regmap);
   400	
   401		rtc->rdev = devm_rtc_allocate_device(dev);
   402		if (IS_ERR(rtc->rdev))
   403			return PTR_ERR(rtc->rdev);
   404	
   405		platform_set_drvdata(pdev, rtc);
   406	
   407		/* Clock is required to auto-synchronize IRQ enable to RTC */
   408		ret = clk_prepare_enable(rtc->mclk);
   409		if (ret)
   410			return ret;
   411	
   412		ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
   413						rtc_mt6685_irq_handler_thread,
   414						IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
   415						"mt6685-rtc", rtc);
   416		clk_disable_unprepare(rtc->mclk);
   417		if (ret)
   418			return dev_err_probe(&pdev->dev, ret, "Cannot request alarm IRQ");
   419	
   420		device_init_wakeup(&pdev->dev, true);
   421	
   422		rtc->rdev->ops = &rtc_mt6685_ops;
   423		rtc->rdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
   424		rtc->rdev->range_max = mktime64(2027, 12, 31, 23, 59, 59);
   425		rtc->rdev->start_secs = mktime64(1968, 1, 1, 0, 0, 0);
   426		rtc->rdev->set_start_time = true;
   427	
   428		return devm_rtc_register_device(rtc->rdev);
   429	}
   430	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
  2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
  2025-10-26  1:37   ` kernel test robot
@ 2025-10-26  5:13   ` kernel test robot
  2025-10-30 17:27   ` Alexandre Belloni
  2 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2025-10-26  5:13 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, alexandre.belloni
  Cc: oe-kbuild-all, robh, krzk+dt, conor+dt, matthias.bgg,
	angelogioacchino.delregno, linux-rtc, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek, kernel

Hi AngeloGioacchino,

kernel test robot noticed the following build errors:

[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on robh/for-next linus/master v6.18-rc2 next-20251024]
[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/AngeloGioacchino-Del-Regno/dt-bindings-rtc-Add-MediaTek-MT6685-PM-Clock-IC-Real-Time-Clock/20251024-164423
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20251024083318.25890-3-angelogioacchino.delregno%40collabora.com
patch subject: [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
config: sparc64-randconfig-r062-20251026 (https://download.01.org/0day-ci/archive/20251026/202510261223.NRLximA4-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251026/202510261223.NRLximA4-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/202510261223.NRLximA4-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   drivers/rtc/rtc-mt6685.c: In function 'rtc_mt6685_probe':
   drivers/rtc/rtc-mt6685.c:380:13: error: implicit declaration of function 'devm_spmi_subdevice_alloc_and_add' [-Werror=implicit-function-declaration]
     380 |  sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/rtc/rtc-mt6685.c:380:11: warning: assignment to 'struct spmi_subdevice *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     380 |  sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
         |           ^
   In file included from drivers/rtc/rtc-mt6685.c:20:
>> drivers/rtc/rtc-mt6685.c:397:51: error: dereferencing pointer to incomplete type 'struct spmi_subdevice'
     397 |  rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
         |                                                   ^~
   include/linux/regmap.h:775:6: note: in definition of macro '__regmap_lockdep_wrapper'
     775 |   fn(__VA_ARGS__, &_key,     \
         |      ^~~~~~~~~~~
   drivers/rtc/rtc-mt6685.c:397:16: note: in expansion of macro 'devm_regmap_init_spmi_ext'
     397 |  rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +397 drivers/rtc/rtc-mt6685.c

   358	
   359	static int rtc_mt6685_probe(struct platform_device *pdev)
   360	{
   361		struct regmap_config mt6685_rtc_regmap_config = {
   362			.reg_bits = 16,
   363			.val_bits = 8,
   364			.max_register = 0x60,
   365			.fast_io = true,
   366			.use_single_read = true,
   367			.use_single_write = true,
   368		};
   369		struct device *dev = &pdev->dev;
   370		struct spmi_subdevice *sub_sdev;
   371		struct spmi_device *sparent;
   372		struct mt6685_rtc *rtc;
   373		int ret;
   374	
   375		rtc = devm_kzalloc(dev, sizeof(struct mt6685_rtc), GFP_KERNEL);
   376		if (!rtc)
   377			return -ENOMEM;
   378	
   379		sparent = to_spmi_device(dev->parent);
 > 380		sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
   381		if (IS_ERR(sub_sdev))
   382			return PTR_ERR(sub_sdev);
   383	
   384		ret = of_property_read_u32(pdev->dev.of_node, "reg",
   385					   &mt6685_rtc_regmap_config.reg_base);
   386		if (ret)
   387			return ret;
   388	
   389		rtc->irq = platform_get_irq(pdev, 0);
   390		if (rtc->irq < 0)
   391			return rtc->irq;
   392	
   393		rtc->mclk = devm_clk_get(dev, 0);
   394		if (IS_ERR(rtc->mclk))
   395			return PTR_ERR(rtc->mclk);
   396	
 > 397		rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
   398		if (IS_ERR(rtc->regmap))
   399			return PTR_ERR(rtc->regmap);
   400	
   401		rtc->rdev = devm_rtc_allocate_device(dev);
   402		if (IS_ERR(rtc->rdev))
   403			return PTR_ERR(rtc->rdev);
   404	
   405		platform_set_drvdata(pdev, rtc);
   406	
   407		/* Clock is required to auto-synchronize IRQ enable to RTC */
   408		ret = clk_prepare_enable(rtc->mclk);
   409		if (ret)
   410			return ret;
   411	
   412		ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
   413						rtc_mt6685_irq_handler_thread,
   414						IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
   415						"mt6685-rtc", rtc);
   416		clk_disable_unprepare(rtc->mclk);
   417		if (ret)
   418			return dev_err_probe(&pdev->dev, ret, "Cannot request alarm IRQ");
   419	
   420		device_init_wakeup(&pdev->dev, true);
   421	
   422		rtc->rdev->ops = &rtc_mt6685_ops;
   423		rtc->rdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
   424		rtc->rdev->range_max = mktime64(2027, 12, 31, 23, 59, 59);
   425		rtc->rdev->start_secs = mktime64(1968, 1, 1, 0, 0, 0);
   426		rtc->rdev->set_start_time = true;
   427	
   428		return devm_rtc_register_device(rtc->rdev);
   429	}
   430	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI
  2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
  2025-10-26  1:37   ` kernel test robot
  2025-10-26  5:13   ` kernel test robot
@ 2025-10-30 17:27   ` Alexandre Belloni
  2 siblings, 0 replies; 7+ messages in thread
From: Alexandre Belloni @ 2025-10-30 17:27 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: robh, krzk+dt, conor+dt, matthias.bgg, linux-rtc, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, kernel

On 24/10/2025 10:33:18+0200, AngeloGioacchino Del Regno wrote:
> +static irqreturn_t rtc_mt6685_irq_handler_thread(int irq, void *data)
> +{
> +	u16 irqsta, irqen = 0, bbpu = RTC_BBPU_WR_UNLOCK_KEY | RTC_BBPU_PWREN;
> +	struct mt6685_rtc *rtc = data;
> +	struct device *dev = &rtc->rdev->dev;
> +	int ret;
> +
> +	ret = clk_prepare_enable(rtc->mclk);
> +	if (ret)
> +		return IRQ_NONE;
> +
> +	ret = regmap_bulk_read(rtc->regmap, RTC_REG_IRQ_STA, &irqsta, sizeof(irqsta));
> +	if (ret)
> +		goto end;
> +
> +	/* Only alarm interrupts are supported for now */
> +	if (!(irqsta & RTC_IRQ_AL)) {
> +		ret = -EINVAL;
> +		goto end;
> +	}
> +
> +	rtc_lock(rtc->rdev);
> +
> +	/* Enable BBPU power and clear the interrupt */
> +	ret = regmap_bulk_write(rtc->regmap, RTC_REG_BBPU, &bbpu, sizeof(bbpu));
> +	if (ret)
> +		goto end;
> +
> +	ret = regmap_bulk_write(rtc->regmap, RTC_REG_IRQ_EN, &irqen, sizeof(irqen));
> +	if (ret)
> +		goto end;
> +
> +	/* Trigger reset of the RTC BBPU Alarm */
> +	bbpu |= RTC_BBPU_RESET_AL;
> +	ret = regmap_bulk_write(rtc->regmap, RTC_REG_BBPU, &bbpu, sizeof(bbpu));
> +	if (ret) {
> +		dev_err(dev, "Cannot reset alarm: %d\n", ret);
> +		goto end;
> +	}
> +
> +	/* Trigger write synchronization */
> +	ret = rtc_mt6685_write_trigger(rtc);
> +	if (ret) {
> +		dev_err(dev, "Cannot synchronize write to RTC: %d\n", ret);

I'm not sure those two dev_err are necessary.

> +		goto end;
> +	}
> +	rtc_update_irq(rtc->rdev, 1, RTC_IRQF | RTC_AF);
> +end:
> +	rtc_unlock(rtc->rdev);
> +	clk_disable_unprepare(rtc->mclk);
> +	return ret ? IRQ_NONE : IRQ_HANDLED;
> +}
> +


> +static int rtc_mt6685_read_time_regs(struct mt6685_rtc *rtc, struct rtc_time *tm, u16 reg)
> +{
> +	u16 data[RTC_AL_TC_REGIDX_MAX];
> +	int ret;
> +
> +	ret = regmap_bulk_read(rtc->regmap, reg, &data,
> +			       RTC_AL_TC_REGIDX_MAX * sizeof(data[0]));
> +	if (ret) {
> +		dev_err(&rtc->rdev->dev, "Cannot read time regs\n");

Same here, there is not much the user can do and your are already
returning an error.

> +		return ret;
> +	}
> +
> +	tm->tm_sec  = FIELD_GET(RTC_AL_TC_SEC_MIN, data[RTC_AL_TC_REGIDX_SEC]);
> +	tm->tm_min  = FIELD_GET(RTC_AL_TC_SEC_MIN, data[RTC_AL_TC_REGIDX_MIN]);
> +	tm->tm_hour = FIELD_GET(RTC_AL_TC_HOUR_DOM, data[RTC_AL_TC_REGIDX_HOUR]);
> +	tm->tm_mday = FIELD_GET(RTC_AL_TC_HOUR_DOM, data[RTC_AL_TC_REGIDX_DOM]);
> +	tm->tm_wday = FIELD_GET(RTC_AL_TC_DOW, data[RTC_AL_TC_REGIDX_DOW]);
> +	tm->tm_mon  = FIELD_GET(RTC_AL_TC_MON, data[RTC_AL_TC_REGIDX_MON]);
> +	tm->tm_year = FIELD_GET(RTC_AL_TC_YEAR, data[RTC_AL_TC_REGIDX_YEAR]);
> +
> +	/* HW register start mon/wday from one, but tm_mon/tm_wday start from zero. */
> +	tm->tm_mon--;
> +	tm->tm_wday--;
> +
> +	return 0;
> +}
> +

> +static int rtc_mt6685_probe(struct platform_device *pdev)
> +{
> +	struct regmap_config mt6685_rtc_regmap_config = {
> +		.reg_bits = 16,
> +		.val_bits = 8,
> +		.max_register = 0x60,
> +		.fast_io = true,
> +		.use_single_read = true,
> +		.use_single_write = true,
> +	};
> +	struct device *dev = &pdev->dev;
> +	struct spmi_subdevice *sub_sdev;
> +	struct spmi_device *sparent;
> +	struct mt6685_rtc *rtc;
> +	int ret;
> +
> +	rtc = devm_kzalloc(dev, sizeof(struct mt6685_rtc), GFP_KERNEL);
> +	if (!rtc)
> +		return -ENOMEM;
> +
> +	sparent = to_spmi_device(dev->parent);
> +	sub_sdev = devm_spmi_subdevice_alloc_and_add(dev, sparent);
> +	if (IS_ERR(sub_sdev))
> +		return PTR_ERR(sub_sdev);
> +
> +	ret = of_property_read_u32(pdev->dev.of_node, "reg",
> +				   &mt6685_rtc_regmap_config.reg_base);
> +	if (ret)
> +		return ret;
> +
> +	rtc->irq = platform_get_irq(pdev, 0);
> +	if (rtc->irq < 0)
> +		return rtc->irq;
> +
> +	rtc->mclk = devm_clk_get(dev, 0);
> +	if (IS_ERR(rtc->mclk))
> +		return PTR_ERR(rtc->mclk);
> +
> +	rtc->regmap = devm_regmap_init_spmi_ext(&sub_sdev->sdev, &mt6685_rtc_regmap_config);
> +	if (IS_ERR(rtc->regmap))
> +		return PTR_ERR(rtc->regmap);
> +
> +	rtc->rdev = devm_rtc_allocate_device(dev);
> +	if (IS_ERR(rtc->rdev))
> +		return PTR_ERR(rtc->rdev);
> +
> +	platform_set_drvdata(pdev, rtc);
> +
> +	/* Clock is required to auto-synchronize IRQ enable to RTC */
> +	ret = clk_prepare_enable(rtc->mclk);
> +	if (ret)
> +		return ret;
> +
> +	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
> +					rtc_mt6685_irq_handler_thread,
> +					IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
> +					"mt6685-rtc", rtc);
> +	clk_disable_unprepare(rtc->mclk);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "Cannot request alarm IRQ");
> +
> +	device_init_wakeup(&pdev->dev, true);

devm_device_init_wakeup ?


-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-10-30 17:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-24  8:33 [PATCH v1 0/2] rtc: Add support for MT6685 RTC AngeloGioacchino Del Regno
2025-10-24  8:33 ` [PATCH v1 1/2] dt-bindings: rtc: Add MediaTek MT6685 PM/Clock IC Real Time Clock AngeloGioacchino Del Regno
2025-10-24 16:22   ` Conor Dooley
2025-10-24  8:33 ` [PATCH v1 2/2] rtc: Add support for MT6685 Clock IC's RTC over SPMI AngeloGioacchino Del Regno
2025-10-26  1:37   ` kernel test robot
2025-10-26  5:13   ` kernel test robot
2025-10-30 17:27   ` Alexandre Belloni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).