summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrent Piepho <tpiepho@impinj.com>2019-02-11 21:34:04 -0500
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2019-02-17 15:29:10 -0500
commit5909b87db8ef0df4e11363afc53ed788b7ea17cb (patch)
tree159a9e1cd839cd1c7039dcd9f7dbdd6e2c370258
parented3c52a075e9488cc672c5658414b2f157fc5688 (diff)
rtc: isl1208: Support more chip variations
Add more support in the driver for dealing with differences in is1208 compatible chips. Put the 1208, 1209, 1218, and 1219 in the list and encode information about nvram size, tamper, and timestamp features. This adds support for the isl1209, which has a tamper detect but no timestamp feature. Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Trent Piepho <tpiepho@impinj.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/rtc/rtc-isl1208.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index d8e0670e12fc..036e5fc148d4 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -13,6 +13,7 @@
13#include <linux/bcd.h> 13#include <linux/bcd.h>
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/of_device.h>
16#include <linux/of_irq.h> 17#include <linux/of_irq.h>
17#include <linux/rtc.h> 18#include <linux/rtc.h>
18 19
@@ -73,15 +74,49 @@
73static struct i2c_driver isl1208_driver; 74static struct i2c_driver isl1208_driver;
74 75
75/* ISL1208 various variants */ 76/* ISL1208 various variants */
76enum { 77enum isl1208_id {
77 TYPE_ISL1208 = 0, 78 TYPE_ISL1208 = 0,
79 TYPE_ISL1209,
78 TYPE_ISL1218, 80 TYPE_ISL1218,
79 TYPE_ISL1219, 81 TYPE_ISL1219,
82 ISL_LAST_ID
80}; 83};
81 84
85/* Chip capabilities table */
86static const struct isl1208_config {
87 const char name[8];
88 unsigned int nvmem_length;
89 unsigned has_tamper:1;
90 unsigned has_timestamp:1;
91} isl1208_configs[] = {
92 [TYPE_ISL1208] = { "isl1208", 2, false, false },
93 [TYPE_ISL1209] = { "isl1209", 2, true, false },
94 [TYPE_ISL1218] = { "isl1218", 8, false, false },
95 [TYPE_ISL1219] = { "isl1219", 2, true, true },
96};
97
98static const struct i2c_device_id isl1208_id[] = {
99 { "isl1208", TYPE_ISL1208 },
100 { "isl1209", TYPE_ISL1209 },
101 { "isl1218", TYPE_ISL1218 },
102 { "isl1219", TYPE_ISL1219 },
103 { }
104};
105MODULE_DEVICE_TABLE(i2c, isl1208_id);
106
107static const struct of_device_id isl1208_of_match[] = {
108 { .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] },
109 { .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] },
110 { .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] },
111 { .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] },
112 { }
113};
114MODULE_DEVICE_TABLE(of, isl1208_of_match);
115
82/* Device state */ 116/* Device state */
83struct isl1208_state { 117struct isl1208_state {
84 struct rtc_device *rtc; 118 struct rtc_device *rtc;
119 const struct isl1208_config *config;
85}; 120};
86 121
87/* block read */ 122/* block read */
@@ -602,11 +637,12 @@ isl1208_rtc_interrupt(int irq, void *data)
602 return err; 637 return err;
603 } 638 }
604 639
605 if (sr & ISL1208_REG_SR_EVT) { 640 if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) {
606 sysfs_notify(&isl1208->rtc->dev.kobj, NULL,
607 dev_attr_timestamp0.attr.name);
608 dev_warn(&client->dev, "event detected"); 641 dev_warn(&client->dev, "event detected");
609 handled = 1; 642 handled = 1;
643 if (isl1208->config->has_timestamp)
644 sysfs_notify(&isl1208->rtc->dev.kobj, NULL,
645 dev_attr_timestamp0.attr.name);
610 } 646 }
611 647
612 return handled ? IRQ_HANDLED : IRQ_NONE; 648 return handled ? IRQ_HANDLED : IRQ_NONE;
@@ -743,6 +779,17 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
743 return -ENOMEM; 779 return -ENOMEM;
744 i2c_set_clientdata(client, isl1208); 780 i2c_set_clientdata(client, isl1208);
745 781
782 /* Determine which chip we have */
783 if (client->dev.of_node) {
784 isl1208->config = of_device_get_match_data(&client->dev);
785 if (!isl1208->config)
786 return -ENODEV;
787 } else {
788 if (id->driver_data >= ISL_LAST_ID)
789 return -ENODEV;
790 isl1208->config = &isl1208_configs[id->driver_data];
791 }
792
746 isl1208->rtc = devm_rtc_allocate_device(&client->dev); 793 isl1208->rtc = devm_rtc_allocate_device(&client->dev);
747 if (IS_ERR(isl1208->rtc)) 794 if (IS_ERR(isl1208->rtc))
748 return PTR_ERR(isl1208->rtc); 795 return PTR_ERR(isl1208->rtc);
@@ -759,7 +806,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
759 dev_warn(&client->dev, "rtc power failure detected, " 806 dev_warn(&client->dev, "rtc power failure detected, "
760 "please set clock.\n"); 807 "please set clock.\n");
761 808
762 if (id->driver_data == TYPE_ISL1219) { 809 if (isl1208->config->has_tamper) {
763 struct device_node *np = client->dev.of_node; 810 struct device_node *np = client->dev.of_node;
764 u32 evienb; 811 u32 evienb;
765 812
@@ -780,10 +827,12 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
780 dev_err(&client->dev, "could not enable tamper detection\n"); 827 dev_err(&client->dev, "could not enable tamper detection\n");
781 return rc; 828 return rc;
782 } 829 }
830 evdet_irq = of_irq_get_byname(np, "evdet");
831 }
832 if (isl1208->config->has_timestamp) {
783 rc = rtc_add_group(isl1208->rtc, &isl1219_rtc_sysfs_files); 833 rc = rtc_add_group(isl1208->rtc, &isl1219_rtc_sysfs_files);
784 if (rc) 834 if (rc)
785 return rc; 835 return rc;
786 evdet_irq = of_irq_get_byname(np, "evdet");
787 } 836 }
788 837
789 rc = rtc_add_group(isl1208->rtc, &isl1208_rtc_sysfs_files); 838 rc = rtc_add_group(isl1208->rtc, &isl1208_rtc_sysfs_files);
@@ -803,22 +852,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
803 return rtc_register_device(isl1208->rtc); 852 return rtc_register_device(isl1208->rtc);
804} 853}
805 854
806static const struct i2c_device_id isl1208_id[] = {
807 { "isl1208", TYPE_ISL1208 },
808 { "isl1218", TYPE_ISL1218 },
809 { "isl1219", TYPE_ISL1219 },
810 { }
811};
812MODULE_DEVICE_TABLE(i2c, isl1208_id);
813
814static const struct of_device_id isl1208_of_match[] = {
815 { .compatible = "isil,isl1208" },
816 { .compatible = "isil,isl1218" },
817 { .compatible = "isil,isl1219" },
818 { }
819};
820MODULE_DEVICE_TABLE(of, isl1208_of_match);
821
822static struct i2c_driver isl1208_driver = { 855static struct i2c_driver isl1208_driver = {
823 .driver = { 856 .driver = {
824 .name = "rtc-isl1208", 857 .name = "rtc-isl1208",