Re: [PATCH] rtc: Add support for century bits to m41t62 (rv4162) RTC devices
From: Lukasz Majewski
Date: Mon Sep 30 2019 - 03:57:07 EST
Hi Alessandro, Alexandre,
> This change adds support for 'century bits' on 4162 family of RTC
> devices (from ST or microcrystal), which allow storing time beyond
> year 2099.
>
> For rv4162 century bits - CB1[7]:CB0[6] are stored in reg6 - 0x6
> (MONTH): CB1 CB0
> 0 0 (year 2000 - 2099)
> 0 1 (year 2100 - 2199)
> 1 0 (year 2200 - 2299)
> 1 1 (year 2300 - 2399)
>
> The driver has been also adjusted to allow setting time up to year
> 2399 if the M41T80_FEATURE_CB is set in its DTS/I2C data.
>
> There shall be no functional changes for devices not supporting this
> feature. However, other devices - like m41t80 - have different
> approaches to handle century information.
Gentle ping on this patch - it has been almost 3 weeks without any
reply ...
Thanks in advance.
>
> Signed-off-by: Lukasz Majewski <lukma@xxxxxxx>
> ---
> drivers/rtc/rtc-m41t80.c | 56
> +++++++++++++++++++++++++++++++--------- 1 file changed, 44
> insertions(+), 12 deletions(-)
>
> diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
> index 9fdc284c943b..5452ab693568 100644
> --- a/drivers/rtc/rtc-m41t80.c
> +++ b/drivers/rtc/rtc-m41t80.c
> @@ -68,9 +68,22 @@
> #define M41T80_FEATURE_SQ BIT(2) /* Squarewave feature
> */ #define M41T80_FEATURE_WD BIT(3) /* Extra watchdog
> resolution */ #define M41T80_FEATURE_SQ_ALT BIT(4) /*
> RSx bits are in reg 4 */ +#define M41T80_FEATURE_CB
> BIT(5) /* Century Bits[CB1:CB0] are in reg 6 */ +
> +/*
> + * Century bits - CB1[7]:CB0[6] in reg6 (MONTH):
> + * CB1 CB0
> + * 0 0 (year 2000 - 2099)
> + * 0 1 (year 2100 - 2199)
> + * 1 0 (year 2200 - 2299)
> + * 1 1 (year 2300 - 2399)
> + */
> +#define M41T80_CB_SHIFT 6 /* CB[0] bit position */
> +#define M41T80_CB_MASK 0xc0 /* Century bits mask */
>
> static const struct i2c_device_id m41t80_id[] = {
> - { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
> + { "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT |
> + M41T80_FEATURE_CB},
> { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
> { "m41t80", M41T80_FEATURE_SQ },
> { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ},
> @@ -80,7 +93,8 @@ static const struct i2c_device_id m41t80_id[] = {
> { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL |
> M41T80_FEATURE_SQ }, { "m41st85", M41T80_FEATURE_HT |
> M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, { "m41st87",
> M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
> - { "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD |
> M41T80_FEATURE_SQ_ALT },
> + { "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD |
> + M41T80_FEATURE_SQ_ALT | M41T80_FEATURE_CB},
> { }
> };
> MODULE_DEVICE_TABLE(i2c, m41t80_id);
> @@ -88,7 +102,8 @@ MODULE_DEVICE_TABLE(i2c, m41t80_id);
> static const struct of_device_id m41t80_of_match[] = {
> {
> .compatible = "st,m41t62",
> - .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_SQ_ALT)
> + .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_SQ_ALT |
> + M41T80_FEATURE_CB)
> },
> {
> .compatible = "st,m41t65",
> @@ -128,16 +143,19 @@ static const struct of_device_id
> m41t80_of_match[] = { },
> {
> .compatible = "microcrystal,rv4162",
> - .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
> + .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD |
> + M41T80_FEATURE_SQ_ALT |
> M41T80_FEATURE_CB) },
> /* DT compatibility only, do not use compatibles below: */
> {
> .compatible = "st,rv4162",
> - .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
> + .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD |
> + M41T80_FEATURE_SQ_ALT |
> M41T80_FEATURE_CB) },
> {
> .compatible = "rv4162",
> - .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
> + .data = (void *)(M41T80_FEATURE_SQ |
> M41T80_FEATURE_WD |
> + M41T80_FEATURE_SQ_ALT |
> M41T80_FEATURE_CB) },
> { }
> };
> @@ -197,6 +215,7 @@ static irqreturn_t m41t80_handle_irq(int irq,
> void *dev_id) static int m41t80_rtc_read_time(struct device *dev,
> struct rtc_time *tm) {
> struct i2c_client *client = to_i2c_client(dev);
> + struct m41t80_data *clientdata = i2c_get_clientdata(client);
> unsigned char buf[8];
> int err, flags;
>
> @@ -222,9 +241,13 @@ static int m41t80_rtc_read_time(struct device
> *dev, struct rtc_time *tm) tm->tm_mday = bcd2bin(buf[M41T80_REG_DAY]
> & 0x3f); tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
> tm->tm_mon = bcd2bin(buf[M41T80_REG_MON] & 0x1f) - 1;
> -
> - /* assume 20YY not 19YY, and ignore the Century Bit */
> + /* assume 20YY not 19YY */
> tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
> +
> + if (clientdata->features & M41T80_FEATURE_CB)
> + tm->tm_year += ((buf[M41T80_REG_MON] &
> M41T80_CB_MASK)
> + >> M41T80_CB_SHIFT) * 100;
> +
> return 0;
> }
>
> @@ -232,10 +255,13 @@ static int m41t80_rtc_set_time(struct device
> *dev, struct rtc_time *tm) {
> struct i2c_client *client = to_i2c_client(dev);
> struct m41t80_data *clientdata = i2c_get_clientdata(client);
> + int err, flags, max_year = 199;
> unsigned char buf[8];
> - int err, flags;
>
> - if (tm->tm_year < 100 || tm->tm_year > 199)
> + if (clientdata->features & M41T80_FEATURE_CB)
> + max_year = 499;
> +
> + if (tm->tm_year < 100 || tm->tm_year > max_year)
> return -EINVAL;
>
> buf[M41T80_REG_SSEC] = 0;
> @@ -243,8 +269,14 @@ static int m41t80_rtc_set_time(struct device
> *dev, struct rtc_time *tm) buf[M41T80_REG_MIN] = bin2bcd(tm->tm_min);
> buf[M41T80_REG_HOUR] = bin2bcd(tm->tm_hour);
> buf[M41T80_REG_DAY] = bin2bcd(tm->tm_mday);
> - buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1);
> - buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100);
> + if (clientdata->features & M41T80_FEATURE_CB) {
> + buf[M41T80_REG_YEAR] = bin2bcd((tm->tm_year - 100) %
> 100);
> + buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1) |
> + (((tm->tm_year - 100) / 100) <<
> M41T80_CB_SHIFT);
> + } else {
> + buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1);
> + buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100);
> + }
> buf[M41T80_REG_WDAY] = tm->tm_wday;
>
> /* If the square wave output is controlled in the weekday
> register */
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@xxxxxxx
Attachment:
pgphIy4jJ4mH8.pgp
Description: OpenPGP digital signature