diff options
author | Keerthy <j-keerthy@ti.com> | 2016-06-01 06:49:07 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-07-09 04:24:44 -0400 |
commit | e29385fab0bf94017fac130ee32f5bb2daf74417 (patch) | |
tree | 8541a455ce5697bfc01ec92580995d06dda808c8 /drivers/rtc | |
parent | cd9b518b98d3e989f523e63b2ffda78467a3679e (diff) |
rtc: ds1307: Fix relying on reset value for weekday
The reset value of weekday is 0x1. This is wrong since
the reset values of the day/month/year make up to Jan 1 2001.
When computed weekday comes out to be Monday. On a scale
of 1-7(Sunday - Saturday) it should be 0x2. So we should not
be relying on the reset value.
Hence compute the wday using the current date/month/year values.
Check if reset wday is any different from the computed wday,
If different then set the wday which we computed using
date/month/year values.
Document Referred:
http://ww1.microchip.com/downloads/en/DeviceDoc/20002266F.pdf
Fixes: 1d1945d261a2af "drivers/rtc/rtc-ds1307.c: add alarm support for mcp7941x chips"
Signed-off-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 821d9c089cdb..f25f7dce6e1f 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -602,6 +602,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { | |||
602 | * Alarm support for mcp794xx devices. | 602 | * Alarm support for mcp794xx devices. |
603 | */ | 603 | */ |
604 | 604 | ||
605 | #define MCP794XX_REG_WEEKDAY 0x3 | ||
606 | #define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7 | ||
605 | #define MCP794XX_REG_CONTROL 0x07 | 607 | #define MCP794XX_REG_CONTROL 0x07 |
606 | # define MCP794XX_BIT_ALM0_EN 0x10 | 608 | # define MCP794XX_BIT_ALM0_EN 0x10 |
607 | # define MCP794XX_BIT_ALM1_EN 0x20 | 609 | # define MCP794XX_BIT_ALM1_EN 0x20 |
@@ -1231,13 +1233,16 @@ static int ds1307_probe(struct i2c_client *client, | |||
1231 | { | 1233 | { |
1232 | struct ds1307 *ds1307; | 1234 | struct ds1307 *ds1307; |
1233 | int err = -ENODEV; | 1235 | int err = -ENODEV; |
1234 | int tmp; | 1236 | int tmp, wday; |
1235 | struct chip_desc *chip = &chips[id->driver_data]; | 1237 | struct chip_desc *chip = &chips[id->driver_data]; |
1236 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1238 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1237 | bool want_irq = false; | 1239 | bool want_irq = false; |
1238 | bool ds1307_can_wakeup_device = false; | 1240 | bool ds1307_can_wakeup_device = false; |
1239 | unsigned char *buf; | 1241 | unsigned char *buf; |
1240 | struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); | 1242 | struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); |
1243 | struct rtc_time tm; | ||
1244 | unsigned long timestamp; | ||
1245 | |||
1241 | irq_handler_t irq_handler = ds1307_irq; | 1246 | irq_handler_t irq_handler = ds1307_irq; |
1242 | 1247 | ||
1243 | static const int bbsqi_bitpos[] = { | 1248 | static const int bbsqi_bitpos[] = { |
@@ -1526,6 +1531,27 @@ read_rtc: | |||
1526 | bin2bcd(tmp)); | 1531 | bin2bcd(tmp)); |
1527 | } | 1532 | } |
1528 | 1533 | ||
1534 | /* | ||
1535 | * Some IPs have weekday reset value = 0x1 which might not correct | ||
1536 | * hence compute the wday using the current date/month/year values | ||
1537 | */ | ||
1538 | ds1307_get_time(&client->dev, &tm); | ||
1539 | wday = tm.tm_wday; | ||
1540 | timestamp = rtc_tm_to_time64(&tm); | ||
1541 | rtc_time64_to_tm(timestamp, &tm); | ||
1542 | |||
1543 | /* | ||
1544 | * Check if reset wday is different from the computed wday | ||
1545 | * If different then set the wday which we computed using | ||
1546 | * timestamp | ||
1547 | */ | ||
1548 | if (wday != tm.tm_wday) { | ||
1549 | wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY); | ||
1550 | wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK; | ||
1551 | wday = wday | (tm.tm_wday + 1); | ||
1552 | i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday); | ||
1553 | } | ||
1554 | |||
1529 | if (want_irq) { | 1555 | if (want_irq) { |
1530 | device_set_wakeup_capable(&client->dev, true); | 1556 | device_set_wakeup_capable(&client->dev, true); |
1531 | set_bit(HAS_ALARM, &ds1307->flags); | 1557 | set_bit(HAS_ALARM, &ds1307->flags); |