* [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).