Commit 9eab0a788d2d6e513f43b7c0e5bb9d60446233cb
Committed by
Linus Torvalds
1 parent
40ce972d59
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 1 changed file with 47 additions and 31 deletions Side-by-side Diff
drivers/rtc/rtc-ds1307.c
... | ... | @@ -105,6 +105,8 @@ |
105 | 105 | struct ds1307 { |
106 | 106 | u8 offset; /* register's offset */ |
107 | 107 | u8 regs[11]; |
108 | + u16 nvram_offset; | |
109 | + struct bin_attribute *nvram; | |
108 | 110 | enum ds_type type; |
109 | 111 | unsigned long flags; |
110 | 112 | #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ |
111 | 113 | |
112 | 114 | |
113 | 115 | |
... | ... | @@ -119,19 +121,22 @@ |
119 | 121 | }; |
120 | 122 | |
121 | 123 | struct chip_desc { |
122 | - unsigned nvram56:1; | |
123 | 124 | unsigned alarm:1; |
125 | + u16 nvram_offset; | |
126 | + u16 nvram_size; | |
124 | 127 | }; |
125 | 128 | |
126 | 129 | static const struct chip_desc chips[last_ds_type] = { |
127 | 130 | [ds_1307] = { |
128 | - .nvram56 = 1, | |
131 | + .nvram_offset = 8, | |
132 | + .nvram_size = 56, | |
129 | 133 | }, |
130 | 134 | [ds_1337] = { |
131 | 135 | .alarm = 1, |
132 | 136 | }, |
133 | 137 | [ds_1338] = { |
134 | - .nvram56 = 1, | |
138 | + .nvram_offset = 8, | |
139 | + .nvram_size = 56, | |
135 | 140 | }, |
136 | 141 | [ds_1339] = { |
137 | 142 | .alarm = 1, |
... | ... | @@ -139,6 +144,11 @@ |
139 | 144 | [ds_3231] = { |
140 | 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 | |
144 | 154 | static const struct i2c_device_id ds1307_id[] = { |
... | ... | @@ -543,8 +553,6 @@ |
543 | 553 | |
544 | 554 | /*----------------------------------------------------------------------*/ |
545 | 555 | |
546 | -#define NVRAM_SIZE 56 | |
547 | - | |
548 | 556 | static ssize_t |
549 | 557 | ds1307_nvram_read(struct file *filp, struct kobject *kobj, |
550 | 558 | struct bin_attribute *attr, |
551 | 559 | |
552 | 560 | |
... | ... | @@ -557,14 +565,15 @@ |
557 | 565 | client = kobj_to_i2c_client(kobj); |
558 | 566 | ds1307 = i2c_get_clientdata(client); |
559 | 567 | |
560 | - if (unlikely(off >= NVRAM_SIZE)) | |
568 | + if (unlikely(off >= ds1307->nvram->size)) | |
561 | 569 | return 0; |
562 | - if ((off + count) > NVRAM_SIZE) | |
563 | - count = NVRAM_SIZE - off; | |
570 | + if ((off + count) > ds1307->nvram->size) | |
571 | + count = ds1307->nvram->size - off; | |
564 | 572 | if (unlikely(!count)) |
565 | 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 | 577 | if (result < 0) |
569 | 578 | dev_err(&client->dev, "%s error %d\n", "nvram read", result); |
570 | 579 | return result; |
571 | 580 | |
572 | 581 | |
... | ... | @@ -582,14 +591,15 @@ |
582 | 591 | client = kobj_to_i2c_client(kobj); |
583 | 592 | ds1307 = i2c_get_clientdata(client); |
584 | 593 | |
585 | - if (unlikely(off >= NVRAM_SIZE)) | |
594 | + if (unlikely(off >= ds1307->nvram->size)) | |
586 | 595 | return -EFBIG; |
587 | - if ((off + count) > NVRAM_SIZE) | |
588 | - count = NVRAM_SIZE - off; | |
596 | + if ((off + count) > ds1307->nvram->size) | |
597 | + count = ds1307->nvram->size - off; | |
589 | 598 | if (unlikely(!count)) |
590 | 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 | 603 | if (result < 0) { |
594 | 604 | dev_err(&client->dev, "%s error %d\n", "nvram write", result); |
595 | 605 | return result; |
... | ... | @@ -597,17 +607,6 @@ |
597 | 607 | return count; |
598 | 608 | } |
599 | 609 | |
600 | -static 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 | |
613 | 612 | static int __devinit ds1307_probe(struct i2c_client *client, |
614 | 613 | |
615 | 614 | |
... | ... | @@ -894,16 +893,31 @@ |
894 | 893 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
895 | 894 | } |
896 | 895 | |
897 | - if (chip->nvram56) { | |
898 | - err = sysfs_create_bin_file(&client->dev.kobj, &nvram); | |
899 | - if (err == 0) { | |
900 | - set_bit(HAS_NVRAM, &ds1307->flags); | |
901 | - dev_info(&client->dev, "56 bytes nvram\n"); | |
896 | + if (chip->nvram_size) { | |
897 | + ds1307->nvram = kzalloc(sizeof(struct bin_attribute), | |
898 | + GFP_KERNEL); | |
899 | + if (!ds1307->nvram) { | |
900 | + err = -ENOMEM; | |
901 | + goto exit_nvram; | |
902 | 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; | |
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 | 918 | return 0; |
906 | 919 | |
920 | +exit_nvram: | |
907 | 921 | exit_irq: |
908 | 922 | rtc_device_unregister(ds1307->rtc); |
909 | 923 | exit_free: |
... | ... | @@ -920,8 +934,10 @@ |
920 | 934 | cancel_work_sync(&ds1307->work); |
921 | 935 | } |
922 | 936 | |
923 | - if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) | |
924 | - sysfs_remove_bin_file(&client->dev.kobj, &nvram); | |
937 | + if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) { | |
938 | + sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram); | |
939 | + kfree(ds1307->nvram); | |
940 | + } | |
925 | 941 | |
926 | 942 | rtc_device_unregister(ds1307->rtc); |
927 | 943 | kfree(ds1307); |