aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/rtc/Kconfig4
-rw-r--r--drivers/rtc/rtc-ds1307.c93
2 files changed, 95 insertions, 2 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 7958635f12cc..e5cdc0294aaa 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -135,8 +135,8 @@ config RTC_DRV_DS1307
135 135
136 The first seven registers on these chips hold an RTC, and other 136 The first seven registers on these chips hold an RTC, and other
137 registers may add features such as NVRAM, a trickle charger for 137 registers may add features such as NVRAM, a trickle charger for
138 the RTC/NVRAM backup power, and alarms. This driver may not 138 the RTC/NVRAM backup power, and alarms. NVRAM is visible in
139 expose all those available chip features. 139 sysfs, but other chip features may not be available.
140 140
141 This driver can also be built as a module. If so, the module 141 This driver can also be built as a module. If so, the module
142 will be called rtc-ds1307. 142 will be called rtc-ds1307.
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index db6f3f0d8982..bc1c7fe94ad3 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -89,6 +89,7 @@ enum ds_type {
89 89
90struct ds1307 { 90struct ds1307 {
91 u8 reg_addr; 91 u8 reg_addr;
92 bool has_nvram;
92 u8 regs[8]; 93 u8 regs[8];
93 enum ds_type type; 94 enum ds_type type;
94 struct i2c_msg msg[2]; 95 struct i2c_msg msg[2];
@@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
242 .set_time = ds1307_set_time, 243 .set_time = ds1307_set_time,
243}; 244};
244 245
246/*----------------------------------------------------------------------*/
247
248#define NVRAM_SIZE 56
249
250static ssize_t
251ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
252 char *buf, loff_t off, size_t count)
253{
254 struct i2c_client *client;
255 struct ds1307 *ds1307;
256 struct i2c_msg msg[2];
257 int result;
258
259 client = to_i2c_client(container_of(kobj, struct device, kobj));
260 ds1307 = i2c_get_clientdata(client);
261
262 if (unlikely(off >= NVRAM_SIZE))
263 return 0;
264 if ((off + count) > NVRAM_SIZE)
265 count = NVRAM_SIZE - off;
266 if (unlikely(!count))
267 return count;
268
269 msg[0].addr = client->addr;
270 msg[0].flags = 0;
271 msg[0].len = 1;
272 msg[0].buf = buf;
273
274 buf[0] = 8 + off;
275
276 msg[1].addr = client->addr;
277 msg[1].flags = I2C_M_RD;
278 msg[1].len = count;
279 msg[1].buf = buf;
280
281 result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
282 if (result != 2) {
283 dev_err(&client->dev, "%s error %d\n", "nvram read", result);
284 return -EIO;
285 }
286 return count;
287}
288
289static ssize_t
290ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
291 char *buf, loff_t off, size_t count)
292{
293 struct i2c_client *client;
294 u8 buffer[NVRAM_SIZE + 1];
295 int ret;
296
297 client = to_i2c_client(container_of(kobj, struct device, kobj));
298
299 if (unlikely(off >= NVRAM_SIZE))
300 return -EFBIG;
301 if ((off + count) > NVRAM_SIZE)
302 count = NVRAM_SIZE - off;
303 if (unlikely(!count))
304 return count;
305
306 buffer[0] = 8 + off;
307 memcpy(buffer + 1, buf, count);
308
309 ret = i2c_master_send(client, buffer, count + 1);
310 return (ret < 0) ? ret : (ret - 1);
311}
312
313static struct bin_attribute nvram = {
314 .attr = {
315 .name = "nvram",
316 .mode = S_IRUGO | S_IWUSR,
317 .owner = THIS_MODULE,
318 },
319
320 .read = ds1307_nvram_read,
321 .write = ds1307_nvram_write,
322 .size = NVRAM_SIZE,
323};
324
325/*----------------------------------------------------------------------*/
326
245static struct i2c_driver ds1307_driver; 327static struct i2c_driver ds1307_driver;
246 328
247static int __devinit ds1307_probe(struct i2c_client *client) 329static int __devinit ds1307_probe(struct i2c_client *client)
@@ -413,6 +495,14 @@ read_rtc:
413 goto exit_free; 495 goto exit_free;
414 } 496 }
415 497
498 if (chip->nvram56) {
499 err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
500 if (err == 0) {
501 ds1307->has_nvram = true;
502 dev_info(&client->dev, "56 bytes nvram\n");
503 }
504 }
505
416 return 0; 506 return 0;
417 507
418exit_bad: 508exit_bad:
@@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
432{ 522{
433 struct ds1307 *ds1307 = i2c_get_clientdata(client); 523 struct ds1307 *ds1307 = i2c_get_clientdata(client);
434 524
525 if (ds1307->has_nvram)
526 sysfs_remove_bin_file(&client->dev.kobj, &nvram);
527
435 rtc_device_unregister(ds1307->rtc); 528 rtc_device_unregister(ds1307->rtc);
436 kfree(ds1307); 529 kfree(ds1307);
437 return 0; 530 return 0;