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
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
© 2016 - 2025 Red Hat, Inc.