On 11/10/21 2:54 PM, Alexandre Belloni wrote:
Hello,
On 10/11/2021 12:54:54+0100, Camel Guo wrote:
From: Camel Guo <camelg@xxxxxxxx>
In order to make it possible to get battery voltage status, this commit
adds RTC_VL_READ, RTC_VL_CLR ioctl commands to rtc-rs5c372.
Signed-off-by: Camel Guo <camelg@xxxxxxxx>
---
drivers/rtc/rtc-rs5c372.c | 66 +++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 80980414890c..5a96e5d3663a 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -485,6 +485,71 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
#define rs5c372_rtc_proc NULL
#endif
+#ifdef CONFIG_RTC_INTF_DEV
+static int rs5c372_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct rs5c372 *rs5c = i2c_get_clientdata(to_i2c_client(dev));
+ unsigned char ctrl2;
+ int addr;
+ unsigned int flags;
+
+ dev_dbg(dev, "%s: cmd=%x\n", __func__, cmd);
+
+ addr = RS5C_ADDR(RS5C_REG_CTRL2);
+ ctrl2 = i2c_smbus_read_byte_data(rs5c->client, addr);
+
+ switch (cmd) {
+ case RTC_VL_READ:
+ flags = 0;
+
+ switch (rs5c->type) {
+ case rtc_r2025sd:
+ case rtc_r2221tl:
+ if ((rs5c->type == rtc_r2025sd && !(ctrl2 & R2x2x_CTRL2_XSTP)) ||
+ (rs5c->type == rtc_r2221tl && (ctrl2 & R2x2x_CTRL2_XSTP))) {
+ flags |= RTC_VL_DATA_INVALID;
+ }
+ if (ctrl2 & R2x2x_CTRL2_VDET)
+ flags |= RTC_VL_ACCURACY_LOW;
Shouldn't that be RTC_VL_BACKUP_LOW?
Some drivers (e.g: rv3029_ioctl and rv8803_ioctl) use
RTC_VL_ACCURACY_LOW, but some other drivers (e.g: abx80x_ioctl,
pcf2127_rtc_ioctl and pcf8523_rtc_ioctl) use RTC_VL_BACKUP_LOW instead.
Is there any guideline or document telling the differences between them?
I can change it to RTC_VL_BACKUP_LOW of course.
+ break;
+ default:
+ if (ctrl2 & RS5C_CTRL2_XSTP)
+ flags |= RTC_VL_DATA_INVALID;
+ break;
+ }
+
+ return put_user(flags, (unsigned int __user *)arg);
+ case RTC_VL_CLR:
+ /* clear rtc VDET, PON and XSTP bits */
+ switch (rs5c->type) {
+ case rtc_r2025sd:
+ case rtc_r2221tl:
+ ctrl2 &= ~(R2x2x_CTRL2_VDET | R2x2x_CTRL2_PON);
+ if (rs5c->type == rtc_r2025sd)
+ ctrl2 |= R2x2x_CTRL2_XSTP;
+ else
+ ctrl2 &= ~R2x2x_CTRL2_XSTP;
+ break;
+ default:
+ ctrl2 &= ~RS5C_CTRL2_XSTP;
You can clear VDET but you must nt clear PON or XSTP as they are used to
know whether the time on the RTC has been set correctly. Clearing those
can only be done in .set_time.
Will update shortly.
+ break;
+ }
+
+ if (i2c_smbus_write_byte_data(rs5c->client, addr, ctrl2) < 0) {
+ dev_dbg(&rs5c->client->dev, "%s: write error in line %i\n",
+ __func__, __LINE__);
+ return -EIO;
+ }
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+#else
+#define rs5c372_ioctl NULL
+#endif
+
static const struct rtc_class_ops rs5c372_rtc_ops = {
.proc = rs5c372_rtc_proc,
.read_time = rs5c372_rtc_read_time,
@@ -492,6 +557,7 @@ static const struct rtc_class_ops rs5c372_rtc_ops = {
.read_alarm = rs5c_read_alarm,
.set_alarm = rs5c_set_alarm,
.alarm_irq_enable = rs5c_rtc_alarm_irq_enable,
+ .ioctl = rs5c372_ioctl,
};
#if IS_ENABLED(CONFIG_RTC_INTF_SYSFS)
--
2.20.1
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com