hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/rtc/rtc-isl1208.c
....@@ -1,21 +1,16 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Intersil ISL1208 rtc class driver
34 *
45 * Copyright 2005,2006 Hebert Valerio Riedel <hvr@gnu.org>
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License as published by the
8
- * Free Software Foundation; either version 2 of the License, or (at your
9
- * option) any later version.
10
- *
116 */
127
13
-#include <linux/module.h>
14
-#include <linux/i2c.h>
158 #include <linux/bcd.h>
16
-#include <linux/rtc.h>
17
-#include "rtc-core.h"
9
+#include <linux/i2c.h>
10
+#include <linux/module.h>
11
+#include <linux/of_device.h>
1812 #include <linux/of_irq.h>
13
+#include <linux/rtc.h>
1914
2015 /* Register map */
2116 /* rtc section */
....@@ -74,10 +69,50 @@
7469 static struct i2c_driver isl1208_driver;
7570
7671 /* ISL1208 various variants */
77
-enum {
72
+enum isl1208_id {
7873 TYPE_ISL1208 = 0,
74
+ TYPE_ISL1209,
7975 TYPE_ISL1218,
8076 TYPE_ISL1219,
77
+ ISL_LAST_ID
78
+};
79
+
80
+/* Chip capabilities table */
81
+static const struct isl1208_config {
82
+ const char name[8];
83
+ unsigned int nvmem_length;
84
+ unsigned has_tamper:1;
85
+ unsigned has_timestamp:1;
86
+} isl1208_configs[] = {
87
+ [TYPE_ISL1208] = { "isl1208", 2, false, false },
88
+ [TYPE_ISL1209] = { "isl1209", 2, true, false },
89
+ [TYPE_ISL1218] = { "isl1218", 8, false, false },
90
+ [TYPE_ISL1219] = { "isl1219", 2, true, true },
91
+};
92
+
93
+static const struct i2c_device_id isl1208_id[] = {
94
+ { "isl1208", TYPE_ISL1208 },
95
+ { "isl1209", TYPE_ISL1209 },
96
+ { "isl1218", TYPE_ISL1218 },
97
+ { "isl1219", TYPE_ISL1219 },
98
+ { }
99
+};
100
+MODULE_DEVICE_TABLE(i2c, isl1208_id);
101
+
102
+static const struct of_device_id isl1208_of_match[] = {
103
+ { .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] },
104
+ { .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] },
105
+ { .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] },
106
+ { .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] },
107
+ { }
108
+};
109
+MODULE_DEVICE_TABLE(of, isl1208_of_match);
110
+
111
+/* Device state */
112
+struct isl1208_state {
113
+ struct nvmem_config nvmem_config;
114
+ struct rtc_device *rtc;
115
+ const struct isl1208_config *config;
81116 };
82117
83118 /* block read */
....@@ -85,29 +120,13 @@
85120 isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
86121 unsigned len)
87122 {
88
- u8 reg_addr[1] = { reg };
89
- struct i2c_msg msgs[2] = {
90
- {
91
- .addr = client->addr,
92
- .len = sizeof(reg_addr),
93
- .buf = reg_addr
94
- },
95
- {
96
- .addr = client->addr,
97
- .flags = I2C_M_RD,
98
- .len = len,
99
- .buf = buf
100
- }
101
- };
102123 int ret;
103124
104125 WARN_ON(reg > ISL1219_REG_YRT);
105126 WARN_ON(reg + len > ISL1219_REG_YRT + 1);
106127
107
- ret = i2c_transfer(client->adapter, msgs, 2);
108
- if (ret > 0)
109
- ret = 0;
110
- return ret;
128
+ ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
129
+ return (ret < 0) ? ret : 0;
111130 }
112131
113132 /* block write */
....@@ -115,26 +134,13 @@
115134 isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
116135 unsigned len)
117136 {
118
- u8 i2c_buf[ISL1208_REG_USR2 + 2];
119
- struct i2c_msg msgs[1] = {
120
- {
121
- .addr = client->addr,
122
- .len = len + 1,
123
- .buf = i2c_buf
124
- }
125
- };
126137 int ret;
127138
128139 WARN_ON(reg > ISL1219_REG_YRT);
129140 WARN_ON(reg + len > ISL1219_REG_YRT + 1);
130141
131
- i2c_buf[0] = reg;
132
- memcpy(&i2c_buf[1], &buf[0], len);
133
-
134
- ret = i2c_transfer(client->adapter, msgs, 1);
135
- if (ret > 0)
136
- ret = 0;
137
- return ret;
142
+ ret = i2c_smbus_write_i2c_block_data(client, reg, len, buf);
143
+ return (ret < 0) ? ret : 0;
138144 }
139145
140146 /* simple check to see whether we have a isl1208 */
....@@ -191,6 +197,7 @@
191197 return atr;
192198 }
193199
200
+/* returns adjustment value + 100 */
194201 static int
195202 isl1208_i2c_get_dtr(struct i2c_client *client)
196203 {
....@@ -201,7 +208,7 @@
201208 /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */
202209 dtr = ((dtr & 0x3) * 20) * (dtr & (1 << 2) ? -1 : 1);
203210
204
- return dtr;
211
+ return dtr + 100;
205212 }
206213
207214 static int
....@@ -278,8 +285,8 @@
278285 (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay");
279286
280287 dtr = isl1208_i2c_get_dtr(client);
281
- if (dtr >= 0 - 1)
282
- seq_printf(seq, "digital_trim\t: %d ppm\n", dtr);
288
+ if (dtr >= 0)
289
+ seq_printf(seq, "digital_trim\t: %d ppm\n", dtr - 100);
283290
284291 atr = isl1208_i2c_get_atr(client);
285292 if (atr >= 0)
....@@ -586,7 +593,7 @@
586593 {
587594 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
588595 struct i2c_client *client = data;
589
- struct rtc_device *rtc = i2c_get_clientdata(client);
596
+ struct isl1208_state *isl1208 = i2c_get_clientdata(client);
590597 int handled = 0, sr, err;
591598
592599 /*
....@@ -609,7 +616,7 @@
609616 if (sr & ISL1208_REG_SR_ALM) {
610617 dev_dbg(&client->dev, "alarm!\n");
611618
612
- rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
619
+ rtc_update_irq(isl1208->rtc, 1, RTC_IRQF | RTC_AF);
613620
614621 /* Clear the alarm */
615622 sr &= ~ISL1208_REG_SR_ALM;
....@@ -626,11 +633,12 @@
626633 return err;
627634 }
628635
629
- if (sr & ISL1208_REG_SR_EVT) {
630
- sysfs_notify(&rtc->dev.kobj, NULL,
631
- dev_attr_timestamp0.attr.name);
636
+ if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) {
632637 dev_warn(&client->dev, "event detected");
633638 handled = 1;
639
+ if (isl1208->config->has_timestamp)
640
+ sysfs_notify(&isl1208->rtc->dev.kobj, NULL,
641
+ dev_attr_timestamp0.attr.name);
634642 }
635643
636644 return handled ? IRQ_HANDLED : IRQ_NONE;
....@@ -667,7 +675,7 @@
667675 if (dtr < 0)
668676 return dtr;
669677
670
- return sprintf(buf, "%d ppm\n", dtr);
678
+ return sprintf(buf, "%d ppm\n", dtr - 100);
671679 }
672680
673681 static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL);
....@@ -730,6 +738,46 @@
730738 .attrs = isl1219_rtc_attrs,
731739 };
732740
741
+static int isl1208_nvmem_read(void *priv, unsigned int off, void *buf,
742
+ size_t count)
743
+{
744
+ struct isl1208_state *isl1208 = priv;
745
+ struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent);
746
+ int ret;
747
+
748
+ /* nvmem sanitizes offset/count for us, but count==0 is possible */
749
+ if (!count)
750
+ return count;
751
+ ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf,
752
+ count);
753
+ return ret == 0 ? count : ret;
754
+}
755
+
756
+static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf,
757
+ size_t count)
758
+{
759
+ struct isl1208_state *isl1208 = priv;
760
+ struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent);
761
+ int ret;
762
+
763
+ /* nvmem sanitizes off/count for us, but count==0 is possible */
764
+ if (!count)
765
+ return count;
766
+ ret = isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf,
767
+ count);
768
+
769
+ return ret == 0 ? count : ret;
770
+}
771
+
772
+static const struct nvmem_config isl1208_nvmem_config = {
773
+ .name = "isl1208_nvram",
774
+ .word_size = 1,
775
+ .stride = 1,
776
+ /* .size from chip specific config */
777
+ .reg_read = isl1208_nvmem_read,
778
+ .reg_write = isl1208_nvmem_write,
779
+};
780
+
733781 static int isl1208_setup_irq(struct i2c_client *client, int irq)
734782 {
735783 int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
....@@ -752,7 +800,7 @@
752800 isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
753801 {
754802 int rc = 0;
755
- struct rtc_device *rtc;
803
+ struct isl1208_state *isl1208;
756804 int evdet_irq = -1;
757805
758806 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
....@@ -761,13 +809,33 @@
761809 if (isl1208_i2c_validate_client(client) < 0)
762810 return -ENODEV;
763811
764
- rtc = devm_rtc_allocate_device(&client->dev);
765
- if (IS_ERR(rtc))
766
- return PTR_ERR(rtc);
812
+ /* Allocate driver state, point i2c client data to it */
813
+ isl1208 = devm_kzalloc(&client->dev, sizeof(*isl1208), GFP_KERNEL);
814
+ if (!isl1208)
815
+ return -ENOMEM;
816
+ i2c_set_clientdata(client, isl1208);
767817
768
- rtc->ops = &isl1208_rtc_ops;
818
+ /* Determine which chip we have */
819
+ if (client->dev.of_node) {
820
+ isl1208->config = of_device_get_match_data(&client->dev);
821
+ if (!isl1208->config)
822
+ return -ENODEV;
823
+ } else {
824
+ if (id->driver_data >= ISL_LAST_ID)
825
+ return -ENODEV;
826
+ isl1208->config = &isl1208_configs[id->driver_data];
827
+ }
769828
770
- i2c_set_clientdata(client, rtc);
829
+ isl1208->rtc = devm_rtc_allocate_device(&client->dev);
830
+ if (IS_ERR(isl1208->rtc))
831
+ return PTR_ERR(isl1208->rtc);
832
+
833
+ isl1208->rtc->ops = &isl1208_rtc_ops;
834
+
835
+ /* Setup nvmem configuration in driver state struct */
836
+ isl1208->nvmem_config = isl1208_nvmem_config;
837
+ isl1208->nvmem_config.size = isl1208->config->nvmem_length;
838
+ isl1208->nvmem_config.priv = isl1208;
771839
772840 rc = isl1208_i2c_get_sr(client);
773841 if (rc < 0) {
....@@ -779,7 +847,7 @@
779847 dev_warn(&client->dev, "rtc power failure detected, "
780848 "please set clock.\n");
781849
782
- if (id->driver_data == TYPE_ISL1219) {
850
+ if (isl1208->config->has_tamper) {
783851 struct device_node *np = client->dev.of_node;
784852 u32 evienb;
785853
....@@ -800,13 +868,15 @@
800868 dev_err(&client->dev, "could not enable tamper detection\n");
801869 return rc;
802870 }
803
- rc = rtc_add_group(rtc, &isl1219_rtc_sysfs_files);
804
- if (rc)
805
- return rc;
806871 evdet_irq = of_irq_get_byname(np, "evdet");
807872 }
873
+ if (isl1208->config->has_timestamp) {
874
+ rc = rtc_add_group(isl1208->rtc, &isl1219_rtc_sysfs_files);
875
+ if (rc)
876
+ return rc;
877
+ }
808878
809
- rc = rtc_add_group(rtc, &isl1208_rtc_sysfs_files);
879
+ rc = rtc_add_group(isl1208->rtc, &isl1208_rtc_sysfs_files);
810880 if (rc)
811881 return rc;
812882
....@@ -820,24 +890,12 @@
820890 if (rc)
821891 return rc;
822892
823
- return rtc_register_device(rtc);
893
+ rc = rtc_nvmem_register(isl1208->rtc, &isl1208->nvmem_config);
894
+ if (rc)
895
+ return rc;
896
+
897
+ return rtc_register_device(isl1208->rtc);
824898 }
825
-
826
-static const struct i2c_device_id isl1208_id[] = {
827
- { "isl1208", TYPE_ISL1208 },
828
- { "isl1218", TYPE_ISL1218 },
829
- { "isl1219", TYPE_ISL1219 },
830
- { }
831
-};
832
-MODULE_DEVICE_TABLE(i2c, isl1208_id);
833
-
834
-static const struct of_device_id isl1208_of_match[] = {
835
- { .compatible = "isil,isl1208" },
836
- { .compatible = "isil,isl1218" },
837
- { .compatible = "isil,isl1219" },
838
- { }
839
-};
840
-MODULE_DEVICE_TABLE(of, isl1208_of_match);
841899
842900 static struct i2c_driver isl1208_driver = {
843901 .driver = {