aboutsummaryrefslogtreecommitdiff
path: root/nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch')
-rw-r--r--nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch104
1 files changed, 104 insertions, 0 deletions
diff --git a/nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch b/nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch
new file mode 100644
index 0000000..7ad61a4
--- /dev/null
+++ b/nixos/modules/kernel-patches/0034-rtc-rs5c372-support-alarms-up-to-1-week.patch
@@ -0,0 +1,104 @@
+From debf651897e47681bb72bfcefd6b308264ae4985 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= <dgcbueu@gmail.com>
+Date: Tue, 27 Sep 2022 16:21:26 +0200
+Subject: [PATCH 34/96] rtc: rs5c372: support alarms up to 1 week
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Ricoh R2221x, R2223x, RS5C372, RV5C387A chips can handle 1 week
+alarms.
+
+Read the "wday" alarm register and convert it to a date to support up 1
+week in our driver.
+
+Signed-off-by: Daniel González Cabanelas <dgcbueu@gmail.com>
+---
+ drivers/rtc/rtc-rs5c372.c | 48 ++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 42 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
+index cb15983383f5..ab4b5209870d 100644
+--- a/drivers/rtc/rtc-rs5c372.c
++++ b/drivers/rtc/rtc-rs5c372.c
+@@ -399,7 +399,9 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+- int status;
++ int status, wday_offs;
++ struct rtc_time rtc;
++ unsigned long alarm_secs;
+
+ status = rs5c_get_regs(rs5c);
+ if (status < 0)
+@@ -409,6 +411,30 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+ t->time.tm_sec = 0;
+ t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
+ t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
++ t->time.tm_wday = ffs(rs5c->regs[RS5C_REG_ALARM_A_WDAY] & 0x7f) - 1;
++
++ /* determine the day, month and year based on alarm wday, taking as a
++ * reference the current time from the rtc
++ */
++ status = rs5c372_rtc_read_time(dev, &rtc);
++ if (status < 0)
++ return status;
++
++ wday_offs = t->time.tm_wday - rtc.tm_wday;
++ alarm_secs = mktime64(rtc.tm_year + 1900,
++ rtc.tm_mon + 1,
++ rtc.tm_mday + wday_offs,
++ t->time.tm_hour,
++ t->time.tm_min,
++ t->time.tm_sec);
++
++ if (wday_offs < 0 || (wday_offs == 0 &&
++ (t->time.tm_hour < rtc.tm_hour ||
++ (t->time.tm_hour == rtc.tm_hour &&
++ t->time.tm_min <= rtc.tm_min))))
++ alarm_secs += 7 * 86400;
++
++ rtc_time64_to_tm(alarm_secs, &t->time);
+
+ /* ... and status */
+ t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
+@@ -423,12 +449,20 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+ struct rs5c372 *rs5c = i2c_get_clientdata(client);
+ int status, addr, i;
+ unsigned char buf[3];
++ struct rtc_time rtc_tm;
++ unsigned long rtc_secs, alarm_secs;
+
+- /* only handle up to 24 hours in the future, like RTC_ALM_SET */
+- if (t->time.tm_mday != -1
+- || t->time.tm_mon != -1
+- || t->time.tm_year != -1)
++ /* chip only can handle alarms up to one week in the future*/
++ status = rs5c372_rtc_read_time(dev, &rtc_tm);
++ if (status)
++ return status;
++ rtc_secs = rtc_tm_to_time64(&rtc_tm);
++ alarm_secs = rtc_tm_to_time64(&t->time);
++ if (alarm_secs >= rtc_secs + 7 * 86400) {
++ dev_err(dev, "%s: alarm maximum is one week in the future (%d)\n",
++ __func__, status);
+ return -EINVAL;
++ }
+
+ /* REVISIT: round up tm_sec */
+
+@@ -449,7 +483,9 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+ /* set alarm */
+ buf[0] = bin2bcd(t->time.tm_min);
+ buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
+- buf[2] = 0x7f; /* any/all days */
++ /* each bit is the day of the week, 0x7f means all days */
++ buf[2] = (t->time.tm_wday >= 0 && t->time.tm_wday < 7) ?
++ BIT(t->time.tm_wday) : 0x7f;
+
+ for (i = 0; i < sizeof(buf); i++) {
+ addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);
+--
+2.37.2
+