rtc: gamecube: Report low battery as invalid data
authorEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Wed, 15 Dec 2021 17:54:58 +0000 (18:54 +0100)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 16 Dec 2021 09:46:35 +0000 (10:46 +0100)
I haven’t been able to test this patch as all of my consoles have a
working RTC battery, but according to the documentation it should work
like that.

Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20211215175501.6761-3-linkmauve@linkmauve.fr
drivers/rtc/rtc-gamecube.c

index e8260c8..9812874 100644 (file)
 #define RTC_CONTROL0   0x21000c
 #define RTC_CONTROL1   0x21000d
 
+/* RTC flags */
+#define RTC_CONTROL0_UNSTABLE_POWER    0x00000800
+#define RTC_CONTROL0_LOW_BATTERY       0x00000200
+
 struct priv {
        struct regmap *regmap;
        void __iomem *iob;
@@ -182,9 +186,35 @@ static int gamecube_rtc_set_time(struct device *dev, struct rtc_time *t)
        return regmap_write(d->regmap, RTC_COUNTER, timestamp - d->rtc_bias);
 }
 
+static int gamecube_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct priv *d = dev_get_drvdata(dev);
+       int value;
+       int control0;
+       int ret;
+
+       switch (cmd) {
+       case RTC_VL_READ:
+               ret = regmap_read(d->regmap, RTC_CONTROL0, &control0);
+               if (ret)
+                       return ret;
+
+               value = 0;
+               if (control0 & RTC_CONTROL0_UNSTABLE_POWER)
+                       value |= RTC_VL_DATA_INVALID;
+               if (control0 & RTC_CONTROL0_LOW_BATTERY)
+                       value |= RTC_VL_BACKUP_LOW;
+               return put_user(value, (unsigned int __user *)arg);
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
 static const struct rtc_class_ops gamecube_rtc_ops = {
        .read_time      = gamecube_rtc_read_time,
        .set_time       = gamecube_rtc_set_time,
+       .ioctl          = gamecube_rtc_ioctl,
 };
 
 static int gamecube_rtc_read_offset_from_sram(struct priv *d)