aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-ds1307.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-ds1307.c')
-rw-r--r--drivers/rtc/rtc-ds1307.c74
1 files changed, 63 insertions, 11 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 970a236b147a..b53992ab3090 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -4,6 +4,7 @@
4 * Copyright (C) 2005 James Chapman (ds1337 core) 4 * Copyright (C) 2005 James Chapman (ds1337 core)
5 * Copyright (C) 2006 David Brownell 5 * Copyright (C) 2006 David Brownell
6 * Copyright (C) 2009 Matthias Fuchs (rx8025 support) 6 * Copyright (C) 2009 Matthias Fuchs (rx8025 support)
7 * Copyright (C) 2012 Bertrand Achard (nvram access fixes)
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
@@ -196,7 +197,7 @@ static s32 ds1307_read_block_data_once(const struct i2c_client *client,
196static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command, 197static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
197 u8 length, u8 *values) 198 u8 length, u8 *values)
198{ 199{
199 u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; 200 u8 oldvalues[255];
200 s32 ret; 201 s32 ret;
201 int tries = 0; 202 int tries = 0;
202 203
@@ -222,7 +223,7 @@ static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
222static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command, 223static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
223 u8 length, const u8 *values) 224 u8 length, const u8 *values)
224{ 225{
225 u8 currvalues[I2C_SMBUS_BLOCK_MAX]; 226 u8 currvalues[255];
226 int tries = 0; 227 int tries = 0;
227 228
228 dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length); 229 dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length);
@@ -250,6 +251,57 @@ static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
250 251
251/*----------------------------------------------------------------------*/ 252/*----------------------------------------------------------------------*/
252 253
254/* These RTC devices are not designed to be connected to a SMbus adapter.
255 SMbus limits block operations length to 32 bytes, whereas it's not
256 limited on I2C buses. As a result, accesses may exceed 32 bytes;
257 in that case, split them into smaller blocks */
258
259static s32 ds1307_native_smbus_write_block_data(const struct i2c_client *client,
260 u8 command, u8 length, const u8 *values)
261{
262 u8 suboffset = 0;
263
264 if (length <= I2C_SMBUS_BLOCK_MAX)
265 return i2c_smbus_write_i2c_block_data(client,
266 command, length, values);
267
268 while (suboffset < length) {
269 s32 retval = i2c_smbus_write_i2c_block_data(client,
270 command + suboffset,
271 min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
272 values + suboffset);
273 if (retval < 0)
274 return retval;
275
276 suboffset += I2C_SMBUS_BLOCK_MAX;
277 }
278 return length;
279}
280
281static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
282 u8 command, u8 length, u8 *values)
283{
284 u8 suboffset = 0;
285
286 if (length <= I2C_SMBUS_BLOCK_MAX)
287 return i2c_smbus_read_i2c_block_data(client,
288 command, length, values);
289
290 while (suboffset < length) {
291 s32 retval = i2c_smbus_read_i2c_block_data(client,
292 command + suboffset,
293 min(I2C_SMBUS_BLOCK_MAX, length - suboffset),
294 values + suboffset);
295 if (retval < 0)
296 return retval;
297
298 suboffset += I2C_SMBUS_BLOCK_MAX;
299 }
300 return length;
301}
302
303/*----------------------------------------------------------------------*/
304
253/* 305/*
254 * The IRQ logic includes a "real" handler running in IRQ context just 306 * The IRQ logic includes a "real" handler running in IRQ context just
255 * long enough to schedule this workqueue entry. We need a task context 307 * long enough to schedule this workqueue entry. We need a task context
@@ -646,8 +698,8 @@ static int ds1307_probe(struct i2c_client *client,
646 698
647 buf = ds1307->regs; 699 buf = ds1307->regs;
648 if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { 700 if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
649 ds1307->read_block_data = i2c_smbus_read_i2c_block_data; 701 ds1307->read_block_data = ds1307_native_smbus_read_block_data;
650 ds1307->write_block_data = i2c_smbus_write_i2c_block_data; 702 ds1307->write_block_data = ds1307_native_smbus_write_block_data;
651 } else { 703 } else {
652 ds1307->read_block_data = ds1307_read_block_data; 704 ds1307->read_block_data = ds1307_read_block_data;
653 ds1307->write_block_data = ds1307_write_block_data; 705 ds1307->write_block_data = ds1307_write_block_data;
@@ -661,7 +713,7 @@ static int ds1307_probe(struct i2c_client *client,
661 tmp = ds1307->read_block_data(ds1307->client, 713 tmp = ds1307->read_block_data(ds1307->client,
662 DS1337_REG_CONTROL, 2, buf); 714 DS1337_REG_CONTROL, 2, buf);
663 if (tmp != 2) { 715 if (tmp != 2) {
664 pr_debug("read error %d\n", tmp); 716 dev_dbg(&client->dev, "read error %d\n", tmp);
665 err = -EIO; 717 err = -EIO;
666 goto exit_free; 718 goto exit_free;
667 } 719 }
@@ -700,7 +752,7 @@ static int ds1307_probe(struct i2c_client *client,
700 tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 752 tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
701 RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); 753 RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
702 if (tmp != 2) { 754 if (tmp != 2) {
703 pr_debug("read error %d\n", tmp); 755 dev_dbg(&client->dev, "read error %d\n", tmp);
704 err = -EIO; 756 err = -EIO;
705 goto exit_free; 757 goto exit_free;
706 } 758 }
@@ -744,7 +796,7 @@ static int ds1307_probe(struct i2c_client *client,
744 tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 796 tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
745 RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); 797 RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
746 if (tmp != 2) { 798 if (tmp != 2) {
747 pr_debug("read error %d\n", tmp); 799 dev_dbg(&client->dev, "read error %d\n", tmp);
748 err = -EIO; 800 err = -EIO;
749 goto exit_free; 801 goto exit_free;
750 } 802 }
@@ -772,7 +824,7 @@ read_rtc:
772 /* read RTC registers */ 824 /* read RTC registers */
773 tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf); 825 tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
774 if (tmp != 8) { 826 if (tmp != 8) {
775 pr_debug("read error %d\n", tmp); 827 dev_dbg(&client->dev, "read error %d\n", tmp);
776 err = -EIO; 828 err = -EIO;
777 goto exit_free; 829 goto exit_free;
778 } 830 }
@@ -814,7 +866,7 @@ read_rtc:
814 866
815 tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG); 867 tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG);
816 if (tmp < 0) { 868 if (tmp < 0) {
817 pr_debug("read error %d\n", tmp); 869 dev_dbg(&client->dev, "read error %d\n", tmp);
818 err = -EIO; 870 err = -EIO;
819 goto exit_free; 871 goto exit_free;
820 } 872 }
@@ -908,8 +960,8 @@ read_rtc:
908 ds1307->nvram->attr.name = "nvram"; 960 ds1307->nvram->attr.name = "nvram";
909 ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR; 961 ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
910 sysfs_bin_attr_init(ds1307->nvram); 962 sysfs_bin_attr_init(ds1307->nvram);
911 ds1307->nvram->read = ds1307_nvram_read, 963 ds1307->nvram->read = ds1307_nvram_read;
912 ds1307->nvram->write = ds1307_nvram_write, 964 ds1307->nvram->write = ds1307_nvram_write;
913 ds1307->nvram->size = chip->nvram_size; 965 ds1307->nvram->size = chip->nvram_size;
914 ds1307->nvram_offset = chip->nvram_offset; 966 ds1307->nvram_offset = chip->nvram_offset;
915 err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram); 967 err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram);