aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAustin Boyle <Austin.Boyle@aviatnet.com>2012-03-23 18:02:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-23 19:58:40 -0400
commit9eab0a788d2d6e513f43b7c0e5bb9d60446233cb (patch)
tree74b0e4386fbfd3b0ca58596bdb0616e57244a58d
parent40ce972d59fcfd4979e5de04456122447b40c1cf (diff)
rtc: ds1307: generalise ram size and offset
Generalise NVRAM to support RAM with other size and offset, such as the 64 bytes of SRAM on the mcp7941x. [rdunlap@xenotime.net: fix printk format warning] Signed-off-by: Austin Boyle <Austin.Boyle@aviatnet.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net> Cc: David Anders <danders.dev@gmail.com> Cc: Alessandro Zummo <alessandro.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rtc/rtc-ds1307.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 84ab971978cf..cd188ab72f79 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -105,6 +105,8 @@ enum ds_type {
105struct ds1307 { 105struct ds1307 {
106 u8 offset; /* register's offset */ 106 u8 offset; /* register's offset */
107 u8 regs[11]; 107 u8 regs[11];
108 u16 nvram_offset;
109 struct bin_attribute *nvram;
108 enum ds_type type; 110 enum ds_type type;
109 unsigned long flags; 111 unsigned long flags;
110#define HAS_NVRAM 0 /* bit 0 == sysfs file active */ 112#define HAS_NVRAM 0 /* bit 0 == sysfs file active */
@@ -119,19 +121,22 @@ struct ds1307 {
119}; 121};
120 122
121struct chip_desc { 123struct chip_desc {
122 unsigned nvram56:1;
123 unsigned alarm:1; 124 unsigned alarm:1;
125 u16 nvram_offset;
126 u16 nvram_size;
124}; 127};
125 128
126static const struct chip_desc chips[last_ds_type] = { 129static const struct chip_desc chips[last_ds_type] = {
127 [ds_1307] = { 130 [ds_1307] = {
128 .nvram56 = 1, 131 .nvram_offset = 8,
132 .nvram_size = 56,
129 }, 133 },
130 [ds_1337] = { 134 [ds_1337] = {
131 .alarm = 1, 135 .alarm = 1,
132 }, 136 },
133 [ds_1338] = { 137 [ds_1338] = {
134 .nvram56 = 1, 138 .nvram_offset = 8,
139 .nvram_size = 56,
135 }, 140 },
136 [ds_1339] = { 141 [ds_1339] = {
137 .alarm = 1, 142 .alarm = 1,
@@ -139,6 +144,11 @@ static const struct chip_desc chips[last_ds_type] = {
139 [ds_3231] = { 144 [ds_3231] = {
140 .alarm = 1, 145 .alarm = 1,
141 }, 146 },
147 [mcp7941x] = {
148 /* this is battery backed SRAM */
149 .nvram_offset = 0x20,
150 .nvram_size = 0x40,
151 },
142}; 152};
143 153
144static const struct i2c_device_id ds1307_id[] = { 154static const struct i2c_device_id ds1307_id[] = {
@@ -543,8 +553,6 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
543 553
544/*----------------------------------------------------------------------*/ 554/*----------------------------------------------------------------------*/
545 555
546#define NVRAM_SIZE 56
547
548static ssize_t 556static ssize_t
549ds1307_nvram_read(struct file *filp, struct kobject *kobj, 557ds1307_nvram_read(struct file *filp, struct kobject *kobj,
550 struct bin_attribute *attr, 558 struct bin_attribute *attr,
@@ -557,14 +565,15 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj,
557 client = kobj_to_i2c_client(kobj); 565 client = kobj_to_i2c_client(kobj);
558 ds1307 = i2c_get_clientdata(client); 566 ds1307 = i2c_get_clientdata(client);
559 567
560 if (unlikely(off >= NVRAM_SIZE)) 568 if (unlikely(off >= ds1307->nvram->size))
561 return 0; 569 return 0;
562 if ((off + count) > NVRAM_SIZE) 570 if ((off + count) > ds1307->nvram->size)
563 count = NVRAM_SIZE - off; 571 count = ds1307->nvram->size - off;
564 if (unlikely(!count)) 572 if (unlikely(!count))
565 return count; 573 return count;
566 574
567 result = ds1307->read_block_data(client, 8 + off, count, buf); 575 result = ds1307->read_block_data(client, ds1307->nvram_offset + off,
576 count, buf);
568 if (result < 0) 577 if (result < 0)
569 dev_err(&client->dev, "%s error %d\n", "nvram read", result); 578 dev_err(&client->dev, "%s error %d\n", "nvram read", result);
570 return result; 579 return result;
@@ -582,14 +591,15 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
582 client = kobj_to_i2c_client(kobj); 591 client = kobj_to_i2c_client(kobj);
583 ds1307 = i2c_get_clientdata(client); 592 ds1307 = i2c_get_clientdata(client);
584 593
585 if (unlikely(off >= NVRAM_SIZE)) 594 if (unlikely(off >= ds1307->nvram->size))
586 return -EFBIG; 595 return -EFBIG;
587 if ((off + count) > NVRAM_SIZE) 596 if ((off + count) > ds1307->nvram->size)
588 count = NVRAM_SIZE - off; 597 count = ds1307->nvram->size - off;
589 if (unlikely(!count)) 598 if (unlikely(!count))
590 return count; 599 return count;
591 600
592 result = ds1307->write_block_data(client, 8 + off, count, buf); 601 result = ds1307->write_block_data(client, ds1307->nvram_offset + off,
602 count, buf);
593 if (result < 0) { 603 if (result < 0) {
594 dev_err(&client->dev, "%s error %d\n", "nvram write", result); 604 dev_err(&client->dev, "%s error %d\n", "nvram write", result);
595 return result; 605 return result;
@@ -597,17 +607,6 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
597 return count; 607 return count;
598} 608}
599 609
600static struct bin_attribute nvram = {
601 .attr = {
602 .name = "nvram",
603 .mode = S_IRUGO | S_IWUSR,
604 },
605
606 .read = ds1307_nvram_read,
607 .write = ds1307_nvram_write,
608 .size = NVRAM_SIZE,
609};
610
611/*----------------------------------------------------------------------*/ 610/*----------------------------------------------------------------------*/
612 611
613static int __devinit ds1307_probe(struct i2c_client *client, 612static int __devinit ds1307_probe(struct i2c_client *client,
@@ -894,16 +893,31 @@ read_rtc:
894 dev_dbg(&client->dev, "got IRQ %d\n", client->irq); 893 dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
895 } 894 }
896 895
897 if (chip->nvram56) { 896 if (chip->nvram_size) {
898 err = sysfs_create_bin_file(&client->dev.kobj, &nvram); 897 ds1307->nvram = kzalloc(sizeof(struct bin_attribute),
899 if (err == 0) { 898 GFP_KERNEL);
900 set_bit(HAS_NVRAM, &ds1307->flags); 899 if (!ds1307->nvram) {
901 dev_info(&client->dev, "56 bytes nvram\n"); 900 err = -ENOMEM;
901 goto exit_nvram;
902 }
903 ds1307->nvram->attr.name = "nvram";
904 ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
905 ds1307->nvram->read = ds1307_nvram_read,
906 ds1307->nvram->write = ds1307_nvram_write,
907 ds1307->nvram->size = chip->nvram_size;
908 ds1307->nvram_offset = chip->nvram_offset;
909 err = sysfs_create_bin_file(&client->dev.kobj, ds1307->nvram);
910 if (err) {
911 kfree(ds1307->nvram);
912 goto exit_nvram;
902 } 913 }
914 set_bit(HAS_NVRAM, &ds1307->flags);
915 dev_info(&client->dev, "%zu bytes nvram\n", ds1307->nvram->size);
903 } 916 }
904 917
905 return 0; 918 return 0;
906 919
920exit_nvram:
907exit_irq: 921exit_irq:
908 rtc_device_unregister(ds1307->rtc); 922 rtc_device_unregister(ds1307->rtc);
909exit_free: 923exit_free:
@@ -920,8 +934,10 @@ static int __devexit ds1307_remove(struct i2c_client *client)
920 cancel_work_sync(&ds1307->work); 934 cancel_work_sync(&ds1307->work);
921 } 935 }
922 936
923 if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) 937 if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) {
924 sysfs_remove_bin_file(&client->dev.kobj, &nvram); 938 sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram);
939 kfree(ds1307->nvram);
940 }
925 941
926 rtc_device_unregister(ds1307->rtc); 942 rtc_device_unregister(ds1307->rtc);
927 kfree(ds1307); 943 kfree(ds1307);