0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/i2c.h>
0012 #include <linux/bcd.h>
0013 #include <linux/rtc.h>
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <linux/err.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019
0020
0021 #define ISL12022_REG_SC 0x00
0022 #define ISL12022_REG_MN 0x01
0023 #define ISL12022_REG_HR 0x02
0024 #define ISL12022_REG_DT 0x03
0025 #define ISL12022_REG_MO 0x04
0026 #define ISL12022_REG_YR 0x05
0027 #define ISL12022_REG_DW 0x06
0028
0029 #define ISL12022_REG_SR 0x07
0030 #define ISL12022_REG_INT 0x08
0031
0032
0033 #define ISL12022_HR_MIL (1 << 7)
0034
0035 #define ISL12022_SR_LBAT85 (1 << 2)
0036 #define ISL12022_SR_LBAT75 (1 << 1)
0037
0038 #define ISL12022_INT_WRTC (1 << 6)
0039
0040
0041 static struct i2c_driver isl12022_driver;
0042
0043 struct isl12022 {
0044 struct rtc_device *rtc;
0045
0046 bool write_enabled;
0047 };
0048
0049
0050 static int isl12022_read_regs(struct i2c_client *client, uint8_t reg,
0051 uint8_t *data, size_t n)
0052 {
0053 struct i2c_msg msgs[] = {
0054 {
0055 .addr = client->addr,
0056 .flags = 0,
0057 .len = 1,
0058 .buf = data
0059 },
0060 {
0061 .addr = client->addr,
0062 .flags = I2C_M_RD,
0063 .len = n,
0064 .buf = data
0065 }
0066 };
0067
0068 int ret;
0069
0070 data[0] = reg;
0071 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
0072 if (ret != ARRAY_SIZE(msgs)) {
0073 dev_err(&client->dev, "%s: read error, ret=%d\n",
0074 __func__, ret);
0075 return -EIO;
0076 }
0077
0078 return 0;
0079 }
0080
0081
0082 static int isl12022_write_reg(struct i2c_client *client,
0083 uint8_t reg, uint8_t val)
0084 {
0085 uint8_t data[2] = { reg, val };
0086 int err;
0087
0088 err = i2c_master_send(client, data, sizeof(data));
0089 if (err != sizeof(data)) {
0090 dev_err(&client->dev,
0091 "%s: err=%d addr=%02x, data=%02x\n",
0092 __func__, err, data[0], data[1]);
0093 return -EIO;
0094 }
0095
0096 return 0;
0097 }
0098
0099
0100
0101
0102
0103
0104 static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
0105 {
0106 struct i2c_client *client = to_i2c_client(dev);
0107 uint8_t buf[ISL12022_REG_INT + 1];
0108 int ret;
0109
0110 ret = isl12022_read_regs(client, ISL12022_REG_SC, buf, sizeof(buf));
0111 if (ret)
0112 return ret;
0113
0114 if (buf[ISL12022_REG_SR] & (ISL12022_SR_LBAT85 | ISL12022_SR_LBAT75)) {
0115 dev_warn(&client->dev,
0116 "voltage dropped below %u%%, "
0117 "date and time is not reliable.\n",
0118 buf[ISL12022_REG_SR] & ISL12022_SR_LBAT85 ? 85 : 75);
0119 }
0120
0121 dev_dbg(&client->dev,
0122 "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
0123 "mday=%02x, mon=%02x, year=%02x, wday=%02x, "
0124 "sr=%02x, int=%02x",
0125 __func__,
0126 buf[ISL12022_REG_SC],
0127 buf[ISL12022_REG_MN],
0128 buf[ISL12022_REG_HR],
0129 buf[ISL12022_REG_DT],
0130 buf[ISL12022_REG_MO],
0131 buf[ISL12022_REG_YR],
0132 buf[ISL12022_REG_DW],
0133 buf[ISL12022_REG_SR],
0134 buf[ISL12022_REG_INT]);
0135
0136 tm->tm_sec = bcd2bin(buf[ISL12022_REG_SC] & 0x7F);
0137 tm->tm_min = bcd2bin(buf[ISL12022_REG_MN] & 0x7F);
0138 tm->tm_hour = bcd2bin(buf[ISL12022_REG_HR] & 0x3F);
0139 tm->tm_mday = bcd2bin(buf[ISL12022_REG_DT] & 0x3F);
0140 tm->tm_wday = buf[ISL12022_REG_DW] & 0x07;
0141 tm->tm_mon = bcd2bin(buf[ISL12022_REG_MO] & 0x1F) - 1;
0142 tm->tm_year = bcd2bin(buf[ISL12022_REG_YR]) + 100;
0143
0144 dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
0145 "mday=%d, mon=%d, year=%d, wday=%d\n",
0146 __func__,
0147 tm->tm_sec, tm->tm_min, tm->tm_hour,
0148 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
0149
0150 return 0;
0151 }
0152
0153 static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
0154 {
0155 struct i2c_client *client = to_i2c_client(dev);
0156 struct isl12022 *isl12022 = i2c_get_clientdata(client);
0157 size_t i;
0158 int ret;
0159 uint8_t buf[ISL12022_REG_DW + 1];
0160
0161 dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
0162 "mday=%d, mon=%d, year=%d, wday=%d\n",
0163 __func__,
0164 tm->tm_sec, tm->tm_min, tm->tm_hour,
0165 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
0166
0167 if (!isl12022->write_enabled) {
0168
0169 ret = isl12022_read_regs(client, ISL12022_REG_INT, buf, 1);
0170 if (ret)
0171 return ret;
0172
0173
0174
0175 if (!(buf[0] & ISL12022_INT_WRTC)) {
0176 dev_info(&client->dev,
0177 "init write enable and 24 hour format\n");
0178
0179
0180 ret = isl12022_write_reg(client,
0181 ISL12022_REG_INT,
0182 buf[0] | ISL12022_INT_WRTC);
0183 if (ret)
0184 return ret;
0185
0186
0187
0188
0189 ret = isl12022_read_regs(client, ISL12022_REG_HR,
0190 buf, 1);
0191 if (ret)
0192 return ret;
0193
0194 ret = isl12022_write_reg(client,
0195 ISL12022_REG_HR,
0196 buf[0] | ISL12022_HR_MIL);
0197 if (ret)
0198 return ret;
0199 }
0200
0201 isl12022->write_enabled = true;
0202 }
0203
0204
0205 buf[ISL12022_REG_SC] = bin2bcd(tm->tm_sec);
0206 buf[ISL12022_REG_MN] = bin2bcd(tm->tm_min);
0207 buf[ISL12022_REG_HR] = bin2bcd(tm->tm_hour) | ISL12022_HR_MIL;
0208
0209 buf[ISL12022_REG_DT] = bin2bcd(tm->tm_mday);
0210
0211
0212 buf[ISL12022_REG_MO] = bin2bcd(tm->tm_mon + 1);
0213
0214
0215 buf[ISL12022_REG_YR] = bin2bcd(tm->tm_year % 100);
0216
0217 buf[ISL12022_REG_DW] = tm->tm_wday & 0x07;
0218
0219
0220 for (i = 0; i < ARRAY_SIZE(buf); i++) {
0221 ret = isl12022_write_reg(client, ISL12022_REG_SC + i,
0222 buf[ISL12022_REG_SC + i]);
0223 if (ret)
0224 return -EIO;
0225 }
0226
0227 return 0;
0228 }
0229
0230 static const struct rtc_class_ops isl12022_rtc_ops = {
0231 .read_time = isl12022_rtc_read_time,
0232 .set_time = isl12022_rtc_set_time,
0233 };
0234
0235 static int isl12022_probe(struct i2c_client *client)
0236 {
0237 struct isl12022 *isl12022;
0238
0239 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
0240 return -ENODEV;
0241
0242 isl12022 = devm_kzalloc(&client->dev, sizeof(struct isl12022),
0243 GFP_KERNEL);
0244 if (!isl12022)
0245 return -ENOMEM;
0246
0247 i2c_set_clientdata(client, isl12022);
0248
0249 isl12022->rtc = devm_rtc_device_register(&client->dev,
0250 isl12022_driver.driver.name,
0251 &isl12022_rtc_ops, THIS_MODULE);
0252 return PTR_ERR_OR_ZERO(isl12022->rtc);
0253 }
0254
0255 #ifdef CONFIG_OF
0256 static const struct of_device_id isl12022_dt_match[] = {
0257 { .compatible = "isl,isl12022" },
0258 { .compatible = "isil,isl12022" },
0259 { },
0260 };
0261 MODULE_DEVICE_TABLE(of, isl12022_dt_match);
0262 #endif
0263
0264 static const struct i2c_device_id isl12022_id[] = {
0265 { "isl12022", 0 },
0266 { }
0267 };
0268 MODULE_DEVICE_TABLE(i2c, isl12022_id);
0269
0270 static struct i2c_driver isl12022_driver = {
0271 .driver = {
0272 .name = "rtc-isl12022",
0273 #ifdef CONFIG_OF
0274 .of_match_table = of_match_ptr(isl12022_dt_match),
0275 #endif
0276 },
0277 .probe_new = isl12022_probe,
0278 .id_table = isl12022_id,
0279 };
0280
0281 module_i2c_driver(isl12022_driver);
0282
0283 MODULE_AUTHOR("roman.fietze@telemotive.de");
0284 MODULE_DESCRIPTION("ISL 12022 RTC driver");
0285 MODULE_LICENSE("GPL");