1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Intersil ISL1208 rtc class driver |
4 | * |
5 | * Copyright 2005,2006 Hebert Valerio Riedel <hvr@gnu.org> |
6 | */ |
7 | |
8 | #include <linux/bcd.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> |
12 | #include <linux/of.h> |
13 | #include <linux/of_irq.h> |
14 | #include <linux/rtc.h> |
15 | |
16 | /* Register map */ |
17 | /* rtc section */ |
18 | #define ISL1208_REG_SC 0x00 |
19 | #define ISL1208_REG_MN 0x01 |
20 | #define ISL1208_REG_HR 0x02 |
21 | #define ISL1208_REG_HR_MIL (1<<7) /* 24h/12h mode */ |
22 | #define ISL1208_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ |
23 | #define ISL1208_REG_DT 0x03 |
24 | #define ISL1208_REG_MO 0x04 |
25 | #define ISL1208_REG_YR 0x05 |
26 | #define ISL1208_REG_DW 0x06 |
27 | #define ISL1208_RTC_SECTION_LEN 7 |
28 | |
29 | /* control/status section */ |
30 | #define ISL1208_REG_SR 0x07 |
31 | #define ISL1208_REG_SR_ARST (1<<7) /* auto reset */ |
32 | #define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */ |
33 | #define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */ |
34 | #define ISL1208_REG_SR_EVT (1<<3) /* event */ |
35 | #define ISL1208_REG_SR_ALM (1<<2) /* alarm */ |
36 | #define ISL1208_REG_SR_BAT (1<<1) /* battery */ |
37 | #define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */ |
38 | #define ISL1208_REG_INT 0x08 |
39 | #define ISL1208_REG_INT_ALME (1<<6) /* alarm enable */ |
40 | #define ISL1208_REG_INT_IM (1<<7) /* interrupt/alarm mode */ |
41 | #define ISL1219_REG_EV 0x09 |
42 | #define ISL1219_REG_EV_EVEN (1<<4) /* event detection enable */ |
43 | #define ISL1219_REG_EV_EVIENB (1<<7) /* event in pull-up disable */ |
44 | #define ISL1208_REG_ATR 0x0a |
45 | #define ISL1208_REG_DTR 0x0b |
46 | |
47 | /* alarm section */ |
48 | #define ISL1208_REG_SCA 0x0c |
49 | #define ISL1208_REG_MNA 0x0d |
50 | #define ISL1208_REG_HRA 0x0e |
51 | #define ISL1208_REG_DTA 0x0f |
52 | #define ISL1208_REG_MOA 0x10 |
53 | #define ISL1208_REG_DWA 0x11 |
54 | #define ISL1208_ALARM_SECTION_LEN 6 |
55 | |
56 | /* user section */ |
57 | #define ISL1208_REG_USR1 0x12 |
58 | #define ISL1208_REG_USR2 0x13 |
59 | #define ISL1208_USR_SECTION_LEN 2 |
60 | |
61 | /* event section */ |
62 | #define ISL1219_REG_SCT 0x14 |
63 | #define ISL1219_REG_MNT 0x15 |
64 | #define ISL1219_REG_HRT 0x16 |
65 | #define ISL1219_REG_DTT 0x17 |
66 | #define ISL1219_REG_MOT 0x18 |
67 | #define ISL1219_REG_YRT 0x19 |
68 | #define ISL1219_EVT_SECTION_LEN 6 |
69 | |
70 | static struct i2c_driver isl1208_driver; |
71 | |
72 | /* Chip capabilities table */ |
73 | struct isl1208_config { |
74 | unsigned int nvmem_length; |
75 | unsigned has_tamper:1; |
76 | unsigned has_timestamp:1; |
77 | unsigned has_inverted_osc_bit:1; |
78 | }; |
79 | |
80 | static const struct isl1208_config config_isl1208 = { |
81 | .nvmem_length = 2, |
82 | .has_tamper = false, |
83 | .has_timestamp = false |
84 | }; |
85 | |
86 | static const struct isl1208_config config_isl1209 = { |
87 | .nvmem_length = 2, |
88 | .has_tamper = true, |
89 | .has_timestamp = false |
90 | }; |
91 | |
92 | static const struct isl1208_config config_isl1218 = { |
93 | .nvmem_length = 8, |
94 | .has_tamper = false, |
95 | .has_timestamp = false |
96 | }; |
97 | |
98 | static const struct isl1208_config config_isl1219 = { |
99 | .nvmem_length = 2, |
100 | .has_tamper = true, |
101 | .has_timestamp = true |
102 | }; |
103 | |
104 | static const struct isl1208_config config_raa215300_a0 = { |
105 | .nvmem_length = 2, |
106 | .has_tamper = false, |
107 | .has_timestamp = false, |
108 | .has_inverted_osc_bit = true |
109 | }; |
110 | |
111 | static const struct i2c_device_id isl1208_id[] = { |
112 | { "isl1208" , .driver_data = (kernel_ulong_t)&config_isl1208 }, |
113 | { "isl1209" , .driver_data = (kernel_ulong_t)&config_isl1209 }, |
114 | { "isl1218" , .driver_data = (kernel_ulong_t)&config_isl1218 }, |
115 | { "isl1219" , .driver_data = (kernel_ulong_t)&config_isl1219 }, |
116 | { "raa215300_a0" , .driver_data = (kernel_ulong_t)&config_raa215300_a0 }, |
117 | { } |
118 | }; |
119 | MODULE_DEVICE_TABLE(i2c, isl1208_id); |
120 | |
121 | static const __maybe_unused struct of_device_id isl1208_of_match[] = { |
122 | { .compatible = "isil,isl1208" , .data = &config_isl1208 }, |
123 | { .compatible = "isil,isl1209" , .data = &config_isl1209 }, |
124 | { .compatible = "isil,isl1218" , .data = &config_isl1218 }, |
125 | { .compatible = "isil,isl1219" , .data = &config_isl1219 }, |
126 | { } |
127 | }; |
128 | MODULE_DEVICE_TABLE(of, isl1208_of_match); |
129 | |
130 | /* Device state */ |
131 | struct isl1208_state { |
132 | struct nvmem_config nvmem_config; |
133 | struct rtc_device *rtc; |
134 | const struct isl1208_config *config; |
135 | }; |
136 | |
137 | /* block read */ |
138 | static int |
139 | isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], |
140 | unsigned len) |
141 | { |
142 | int ret; |
143 | |
144 | WARN_ON(reg > ISL1219_REG_YRT); |
145 | WARN_ON(reg + len > ISL1219_REG_YRT + 1); |
146 | |
147 | ret = i2c_smbus_read_i2c_block_data(client, command: reg, length: len, values: buf); |
148 | return (ret < 0) ? ret : 0; |
149 | } |
150 | |
151 | /* block write */ |
152 | static int |
153 | isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], |
154 | unsigned len) |
155 | { |
156 | int ret; |
157 | |
158 | WARN_ON(reg > ISL1219_REG_YRT); |
159 | WARN_ON(reg + len > ISL1219_REG_YRT + 1); |
160 | |
161 | ret = i2c_smbus_write_i2c_block_data(client, command: reg, length: len, values: buf); |
162 | return (ret < 0) ? ret : 0; |
163 | } |
164 | |
165 | /* simple check to see whether we have a isl1208 */ |
166 | static int |
167 | isl1208_i2c_validate_client(struct i2c_client *client) |
168 | { |
169 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; |
170 | u8 zero_mask[ISL1208_RTC_SECTION_LEN] = { |
171 | 0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8 |
172 | }; |
173 | int i; |
174 | int ret; |
175 | |
176 | ret = isl1208_i2c_read_regs(client, reg: 0, buf: regs, ISL1208_RTC_SECTION_LEN); |
177 | if (ret < 0) |
178 | return ret; |
179 | |
180 | for (i = 0; i < ISL1208_RTC_SECTION_LEN; ++i) { |
181 | if (regs[i] & zero_mask[i]) /* check if bits are cleared */ |
182 | return -ENODEV; |
183 | } |
184 | |
185 | return 0; |
186 | } |
187 | |
188 | static int isl1208_set_xtoscb(struct i2c_client *client, int sr, int xtosb_val) |
189 | { |
190 | /* Do nothing if bit is already set to desired value */ |
191 | if (!!(sr & ISL1208_REG_SR_XTOSCB) == xtosb_val) |
192 | return 0; |
193 | |
194 | if (xtosb_val) |
195 | sr |= ISL1208_REG_SR_XTOSCB; |
196 | else |
197 | sr &= ~ISL1208_REG_SR_XTOSCB; |
198 | |
199 | return i2c_smbus_write_byte_data(client, ISL1208_REG_SR, value: sr); |
200 | } |
201 | |
202 | static int |
203 | isl1208_i2c_get_sr(struct i2c_client *client) |
204 | { |
205 | return i2c_smbus_read_byte_data(client, ISL1208_REG_SR); |
206 | } |
207 | |
208 | static int |
209 | isl1208_i2c_get_atr(struct i2c_client *client) |
210 | { |
211 | int atr = i2c_smbus_read_byte_data(client, ISL1208_REG_ATR); |
212 | if (atr < 0) |
213 | return atr; |
214 | |
215 | /* The 6bit value in the ATR register controls the load |
216 | * capacitance C_load * in steps of 0.25pF |
217 | * |
218 | * bit (1<<5) of the ATR register is inverted |
219 | * |
220 | * C_load(ATR=0x20) = 4.50pF |
221 | * C_load(ATR=0x00) = 12.50pF |
222 | * C_load(ATR=0x1f) = 20.25pF |
223 | * |
224 | */ |
225 | |
226 | atr &= 0x3f; /* mask out lsb */ |
227 | atr ^= 1 << 5; /* invert 6th bit */ |
228 | atr += 2 * 9; /* add offset of 4.5pF; unit[atr] = 0.25pF */ |
229 | |
230 | return atr; |
231 | } |
232 | |
233 | /* returns adjustment value + 100 */ |
234 | static int |
235 | isl1208_i2c_get_dtr(struct i2c_client *client) |
236 | { |
237 | int dtr = i2c_smbus_read_byte_data(client, ISL1208_REG_DTR); |
238 | if (dtr < 0) |
239 | return -EIO; |
240 | |
241 | /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */ |
242 | dtr = ((dtr & 0x3) * 20) * (dtr & (1 << 2) ? -1 : 1); |
243 | |
244 | return dtr + 100; |
245 | } |
246 | |
247 | static int |
248 | isl1208_i2c_get_usr(struct i2c_client *client) |
249 | { |
250 | u8 buf[ISL1208_USR_SECTION_LEN] = { 0, }; |
251 | int ret; |
252 | |
253 | ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1, buf, |
254 | ISL1208_USR_SECTION_LEN); |
255 | if (ret < 0) |
256 | return ret; |
257 | |
258 | return (buf[1] << 8) | buf[0]; |
259 | } |
260 | |
261 | static int |
262 | isl1208_i2c_set_usr(struct i2c_client *client, u16 usr) |
263 | { |
264 | u8 buf[ISL1208_USR_SECTION_LEN]; |
265 | |
266 | buf[0] = usr & 0xff; |
267 | buf[1] = (usr >> 8) & 0xff; |
268 | |
269 | return isl1208_i2c_set_regs(client, ISL1208_REG_USR1, buf, |
270 | ISL1208_USR_SECTION_LEN); |
271 | } |
272 | |
273 | static int |
274 | isl1208_rtc_toggle_alarm(struct i2c_client *client, int enable) |
275 | { |
276 | int icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT); |
277 | |
278 | if (icr < 0) { |
279 | dev_err(&client->dev, "%s: reading INT failed\n" , __func__); |
280 | return icr; |
281 | } |
282 | |
283 | if (enable) |
284 | icr |= ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM; |
285 | else |
286 | icr &= ~(ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM); |
287 | |
288 | icr = i2c_smbus_write_byte_data(client, ISL1208_REG_INT, value: icr); |
289 | if (icr < 0) { |
290 | dev_err(&client->dev, "%s: writing INT failed\n" , __func__); |
291 | return icr; |
292 | } |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | static int |
298 | isl1208_rtc_proc(struct device *dev, struct seq_file *seq) |
299 | { |
300 | struct i2c_client *const client = to_i2c_client(dev); |
301 | int sr, dtr, atr, usr; |
302 | |
303 | sr = isl1208_i2c_get_sr(client); |
304 | if (sr < 0) { |
305 | dev_err(&client->dev, "%s: reading SR failed\n" , __func__); |
306 | return sr; |
307 | } |
308 | |
309 | seq_printf(m: seq, fmt: "status_reg\t:%s%s%s%s%s%s (0x%.2x)\n" , |
310 | (sr & ISL1208_REG_SR_RTCF) ? " RTCF" : "" , |
311 | (sr & ISL1208_REG_SR_BAT) ? " BAT" : "" , |
312 | (sr & ISL1208_REG_SR_ALM) ? " ALM" : "" , |
313 | (sr & ISL1208_REG_SR_WRTC) ? " WRTC" : "" , |
314 | (sr & ISL1208_REG_SR_XTOSCB) ? " XTOSCB" : "" , |
315 | (sr & ISL1208_REG_SR_ARST) ? " ARST" : "" , sr); |
316 | |
317 | seq_printf(m: seq, fmt: "batt_status\t: %s\n" , |
318 | (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay" ); |
319 | |
320 | dtr = isl1208_i2c_get_dtr(client); |
321 | if (dtr >= 0) |
322 | seq_printf(m: seq, fmt: "digital_trim\t: %d ppm\n" , dtr - 100); |
323 | |
324 | atr = isl1208_i2c_get_atr(client); |
325 | if (atr >= 0) |
326 | seq_printf(m: seq, fmt: "analog_trim\t: %d.%.2d pF\n" , |
327 | atr >> 2, (atr & 0x3) * 25); |
328 | |
329 | usr = isl1208_i2c_get_usr(client); |
330 | if (usr >= 0) |
331 | seq_printf(m: seq, fmt: "user_data\t: 0x%.4x\n" , usr); |
332 | |
333 | return 0; |
334 | } |
335 | |
336 | static int |
337 | isl1208_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) |
338 | { |
339 | int sr; |
340 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; |
341 | |
342 | sr = isl1208_i2c_get_sr(client); |
343 | if (sr < 0) { |
344 | dev_err(&client->dev, "%s: reading SR failed\n" , __func__); |
345 | return -EIO; |
346 | } |
347 | |
348 | sr = isl1208_i2c_read_regs(client, reg: 0, buf: regs, ISL1208_RTC_SECTION_LEN); |
349 | if (sr < 0) { |
350 | dev_err(&client->dev, "%s: reading RTC section failed\n" , |
351 | __func__); |
352 | return sr; |
353 | } |
354 | |
355 | tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]); |
356 | tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]); |
357 | |
358 | /* HR field has a more complex interpretation */ |
359 | { |
360 | const u8 _hr = regs[ISL1208_REG_HR]; |
361 | if (_hr & ISL1208_REG_HR_MIL) /* 24h format */ |
362 | tm->tm_hour = bcd2bin(_hr & 0x3f); |
363 | else { |
364 | /* 12h format */ |
365 | tm->tm_hour = bcd2bin(_hr & 0x1f); |
366 | if (_hr & ISL1208_REG_HR_PM) /* PM flag set */ |
367 | tm->tm_hour += 12; |
368 | } |
369 | } |
370 | |
371 | tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]); |
372 | tm->tm_mon = bcd2bin(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */ |
373 | tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 100; |
374 | tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]); |
375 | |
376 | return 0; |
377 | } |
378 | |
379 | static int |
380 | isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) |
381 | { |
382 | struct rtc_time *const tm = &alarm->time; |
383 | u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, }; |
384 | int icr, yr, sr = isl1208_i2c_get_sr(client); |
385 | |
386 | if (sr < 0) { |
387 | dev_err(&client->dev, "%s: reading SR failed\n" , __func__); |
388 | return sr; |
389 | } |
390 | |
391 | sr = isl1208_i2c_read_regs(client, ISL1208_REG_SCA, buf: regs, |
392 | ISL1208_ALARM_SECTION_LEN); |
393 | if (sr < 0) { |
394 | dev_err(&client->dev, "%s: reading alarm section failed\n" , |
395 | __func__); |
396 | return sr; |
397 | } |
398 | |
399 | /* MSB of each alarm register is an enable bit */ |
400 | tm->tm_sec = bcd2bin(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f); |
401 | tm->tm_min = bcd2bin(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f); |
402 | tm->tm_hour = bcd2bin(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f); |
403 | tm->tm_mday = bcd2bin(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f); |
404 | tm->tm_mon = |
405 | bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1; |
406 | tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03); |
407 | |
408 | /* The alarm doesn't store the year so get it from the rtc section */ |
409 | yr = i2c_smbus_read_byte_data(client, ISL1208_REG_YR); |
410 | if (yr < 0) { |
411 | dev_err(&client->dev, "%s: reading RTC YR failed\n" , __func__); |
412 | return yr; |
413 | } |
414 | tm->tm_year = bcd2bin(yr) + 100; |
415 | |
416 | icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT); |
417 | if (icr < 0) { |
418 | dev_err(&client->dev, "%s: reading INT failed\n" , __func__); |
419 | return icr; |
420 | } |
421 | alarm->enabled = !!(icr & ISL1208_REG_INT_ALME); |
422 | |
423 | return 0; |
424 | } |
425 | |
426 | static int |
427 | isl1208_i2c_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm) |
428 | { |
429 | struct rtc_time *alarm_tm = &alarm->time; |
430 | u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, }; |
431 | const int offs = ISL1208_REG_SCA; |
432 | struct rtc_time rtc_tm; |
433 | int err, enable; |
434 | |
435 | err = isl1208_i2c_read_time(client, tm: &rtc_tm); |
436 | if (err) |
437 | return err; |
438 | |
439 | /* If the alarm time is before the current time disable the alarm */ |
440 | if (!alarm->enabled || rtc_tm_sub(lhs: alarm_tm, rhs: &rtc_tm) <= 0) |
441 | enable = 0x00; |
442 | else |
443 | enable = 0x80; |
444 | |
445 | /* Program the alarm and enable it for each setting */ |
446 | regs[ISL1208_REG_SCA - offs] = bin2bcd(alarm_tm->tm_sec) | enable; |
447 | regs[ISL1208_REG_MNA - offs] = bin2bcd(alarm_tm->tm_min) | enable; |
448 | regs[ISL1208_REG_HRA - offs] = bin2bcd(alarm_tm->tm_hour) | |
449 | ISL1208_REG_HR_MIL | enable; |
450 | |
451 | regs[ISL1208_REG_DTA - offs] = bin2bcd(alarm_tm->tm_mday) | enable; |
452 | regs[ISL1208_REG_MOA - offs] = bin2bcd(alarm_tm->tm_mon + 1) | enable; |
453 | regs[ISL1208_REG_DWA - offs] = bin2bcd(alarm_tm->tm_wday & 7) | enable; |
454 | |
455 | /* write ALARM registers */ |
456 | err = isl1208_i2c_set_regs(client, reg: offs, buf: regs, |
457 | ISL1208_ALARM_SECTION_LEN); |
458 | if (err < 0) { |
459 | dev_err(&client->dev, "%s: writing ALARM section failed\n" , |
460 | __func__); |
461 | return err; |
462 | } |
463 | |
464 | err = isl1208_rtc_toggle_alarm(client, enable); |
465 | if (err) |
466 | return err; |
467 | |
468 | return 0; |
469 | } |
470 | |
471 | static int |
472 | isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm) |
473 | { |
474 | return isl1208_i2c_read_time(to_i2c_client(dev), tm); |
475 | } |
476 | |
477 | static int |
478 | isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) |
479 | { |
480 | int sr; |
481 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; |
482 | |
483 | /* The clock has an 8 bit wide bcd-coded register (they never learn) |
484 | * for the year. tm_year is an offset from 1900 and we are interested |
485 | * in the 2000-2099 range, so any value less than 100 is invalid. |
486 | */ |
487 | if (tm->tm_year < 100) |
488 | return -EINVAL; |
489 | |
490 | regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec); |
491 | regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min); |
492 | regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL; |
493 | |
494 | regs[ISL1208_REG_DT] = bin2bcd(tm->tm_mday); |
495 | regs[ISL1208_REG_MO] = bin2bcd(tm->tm_mon + 1); |
496 | regs[ISL1208_REG_YR] = bin2bcd(tm->tm_year - 100); |
497 | |
498 | regs[ISL1208_REG_DW] = bin2bcd(tm->tm_wday & 7); |
499 | |
500 | sr = isl1208_i2c_get_sr(client); |
501 | if (sr < 0) { |
502 | dev_err(&client->dev, "%s: reading SR failed\n" , __func__); |
503 | return sr; |
504 | } |
505 | |
506 | /* set WRTC */ |
507 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, |
508 | value: sr | ISL1208_REG_SR_WRTC); |
509 | if (sr < 0) { |
510 | dev_err(&client->dev, "%s: writing SR failed\n" , __func__); |
511 | return sr; |
512 | } |
513 | |
514 | /* write RTC registers */ |
515 | sr = isl1208_i2c_set_regs(client, reg: 0, buf: regs, ISL1208_RTC_SECTION_LEN); |
516 | if (sr < 0) { |
517 | dev_err(&client->dev, "%s: writing RTC section failed\n" , |
518 | __func__); |
519 | return sr; |
520 | } |
521 | |
522 | /* clear WRTC again */ |
523 | sr = isl1208_i2c_get_sr(client); |
524 | if (sr < 0) { |
525 | dev_err(&client->dev, "%s: reading SR failed\n" , __func__); |
526 | return sr; |
527 | } |
528 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, |
529 | value: sr & ~ISL1208_REG_SR_WRTC); |
530 | if (sr < 0) { |
531 | dev_err(&client->dev, "%s: writing SR failed\n" , __func__); |
532 | return sr; |
533 | } |
534 | |
535 | return 0; |
536 | } |
537 | |
538 | static int |
539 | isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm) |
540 | { |
541 | return isl1208_i2c_set_time(to_i2c_client(dev), tm); |
542 | } |
543 | |
544 | static int |
545 | isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
546 | { |
547 | return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm); |
548 | } |
549 | |
550 | static int |
551 | isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
552 | { |
553 | return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm); |
554 | } |
555 | |
556 | static ssize_t timestamp0_store(struct device *dev, |
557 | struct device_attribute *attr, |
558 | const char *buf, size_t count) |
559 | { |
560 | struct i2c_client *client = to_i2c_client(dev->parent); |
561 | int sr; |
562 | |
563 | sr = isl1208_i2c_get_sr(client); |
564 | if (sr < 0) { |
565 | dev_err(dev, "%s: reading SR failed\n" , __func__); |
566 | return sr; |
567 | } |
568 | |
569 | sr &= ~ISL1208_REG_SR_EVT; |
570 | |
571 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, value: sr); |
572 | if (sr < 0) |
573 | dev_err(dev, "%s: writing SR failed\n" , |
574 | __func__); |
575 | |
576 | return count; |
577 | }; |
578 | |
579 | static ssize_t timestamp0_show(struct device *dev, |
580 | struct device_attribute *attr, char *buf) |
581 | { |
582 | struct i2c_client *client = to_i2c_client(dev->parent); |
583 | u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, }; |
584 | struct rtc_time tm; |
585 | int sr; |
586 | |
587 | sr = isl1208_i2c_get_sr(client); |
588 | if (sr < 0) { |
589 | dev_err(dev, "%s: reading SR failed\n" , __func__); |
590 | return sr; |
591 | } |
592 | |
593 | if (!(sr & ISL1208_REG_SR_EVT)) |
594 | return 0; |
595 | |
596 | sr = isl1208_i2c_read_regs(client, ISL1219_REG_SCT, buf: regs, |
597 | ISL1219_EVT_SECTION_LEN); |
598 | if (sr < 0) { |
599 | dev_err(dev, "%s: reading event section failed\n" , |
600 | __func__); |
601 | return 0; |
602 | } |
603 | |
604 | /* MSB of each alarm register is an enable bit */ |
605 | tm.tm_sec = bcd2bin(regs[ISL1219_REG_SCT - ISL1219_REG_SCT] & 0x7f); |
606 | tm.tm_min = bcd2bin(regs[ISL1219_REG_MNT - ISL1219_REG_SCT] & 0x7f); |
607 | tm.tm_hour = bcd2bin(regs[ISL1219_REG_HRT - ISL1219_REG_SCT] & 0x3f); |
608 | tm.tm_mday = bcd2bin(regs[ISL1219_REG_DTT - ISL1219_REG_SCT] & 0x3f); |
609 | tm.tm_mon = |
610 | bcd2bin(regs[ISL1219_REG_MOT - ISL1219_REG_SCT] & 0x1f) - 1; |
611 | tm.tm_year = bcd2bin(regs[ISL1219_REG_YRT - ISL1219_REG_SCT]) + 100; |
612 | |
613 | sr = rtc_valid_tm(tm: &tm); |
614 | if (sr) |
615 | return sr; |
616 | |
617 | return sprintf(buf, fmt: "%llu\n" , |
618 | (unsigned long long)rtc_tm_to_time64(tm: &tm)); |
619 | }; |
620 | |
621 | static DEVICE_ATTR_RW(timestamp0); |
622 | |
623 | static irqreturn_t |
624 | isl1208_rtc_interrupt(int irq, void *data) |
625 | { |
626 | unsigned long timeout = jiffies + msecs_to_jiffies(m: 1000); |
627 | struct i2c_client *client = data; |
628 | struct isl1208_state *isl1208 = i2c_get_clientdata(client); |
629 | int handled = 0, sr, err; |
630 | |
631 | /* |
632 | * I2C reads get NAK'ed if we read straight away after an interrupt? |
633 | * Using a mdelay/msleep didn't seem to help either, so we work around |
634 | * this by continually trying to read the register for a short time. |
635 | */ |
636 | while (1) { |
637 | sr = isl1208_i2c_get_sr(client); |
638 | if (sr >= 0) |
639 | break; |
640 | |
641 | if (time_after(jiffies, timeout)) { |
642 | dev_err(&client->dev, "%s: reading SR failed\n" , |
643 | __func__); |
644 | return sr; |
645 | } |
646 | } |
647 | |
648 | if (sr & ISL1208_REG_SR_ALM) { |
649 | dev_dbg(&client->dev, "alarm!\n" ); |
650 | |
651 | rtc_update_irq(rtc: isl1208->rtc, num: 1, RTC_IRQF | RTC_AF); |
652 | |
653 | /* Clear the alarm */ |
654 | sr &= ~ISL1208_REG_SR_ALM; |
655 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, value: sr); |
656 | if (sr < 0) |
657 | dev_err(&client->dev, "%s: writing SR failed\n" , |
658 | __func__); |
659 | else |
660 | handled = 1; |
661 | |
662 | /* Disable the alarm */ |
663 | err = isl1208_rtc_toggle_alarm(client, enable: 0); |
664 | if (err) |
665 | return err; |
666 | } |
667 | |
668 | if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) { |
669 | dev_warn(&client->dev, "event detected" ); |
670 | handled = 1; |
671 | if (isl1208->config->has_timestamp) |
672 | sysfs_notify(kobj: &isl1208->rtc->dev.kobj, NULL, |
673 | attr: dev_attr_timestamp0.attr.name); |
674 | } |
675 | |
676 | return handled ? IRQ_HANDLED : IRQ_NONE; |
677 | } |
678 | |
679 | static const struct rtc_class_ops isl1208_rtc_ops = { |
680 | .proc = isl1208_rtc_proc, |
681 | .read_time = isl1208_rtc_read_time, |
682 | .set_time = isl1208_rtc_set_time, |
683 | .read_alarm = isl1208_rtc_read_alarm, |
684 | .set_alarm = isl1208_rtc_set_alarm, |
685 | }; |
686 | |
687 | /* sysfs interface */ |
688 | |
689 | static ssize_t |
690 | isl1208_sysfs_show_atrim(struct device *dev, |
691 | struct device_attribute *attr, char *buf) |
692 | { |
693 | int atr = isl1208_i2c_get_atr(to_i2c_client(dev->parent)); |
694 | if (atr < 0) |
695 | return atr; |
696 | |
697 | return sprintf(buf, fmt: "%d.%.2d pF\n" , atr >> 2, (atr & 0x3) * 25); |
698 | } |
699 | |
700 | static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL); |
701 | |
702 | static ssize_t |
703 | isl1208_sysfs_show_dtrim(struct device *dev, |
704 | struct device_attribute *attr, char *buf) |
705 | { |
706 | int dtr = isl1208_i2c_get_dtr(to_i2c_client(dev->parent)); |
707 | if (dtr < 0) |
708 | return dtr; |
709 | |
710 | return sprintf(buf, fmt: "%d ppm\n" , dtr - 100); |
711 | } |
712 | |
713 | static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL); |
714 | |
715 | static ssize_t |
716 | isl1208_sysfs_show_usr(struct device *dev, |
717 | struct device_attribute *attr, char *buf) |
718 | { |
719 | int usr = isl1208_i2c_get_usr(to_i2c_client(dev->parent)); |
720 | if (usr < 0) |
721 | return usr; |
722 | |
723 | return sprintf(buf, fmt: "0x%.4x\n" , usr); |
724 | } |
725 | |
726 | static ssize_t |
727 | isl1208_sysfs_store_usr(struct device *dev, |
728 | struct device_attribute *attr, |
729 | const char *buf, size_t count) |
730 | { |
731 | int usr = -1; |
732 | |
733 | if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { |
734 | if (sscanf(buf, "%x" , &usr) != 1) |
735 | return -EINVAL; |
736 | } else { |
737 | if (sscanf(buf, "%d" , &usr) != 1) |
738 | return -EINVAL; |
739 | } |
740 | |
741 | if (usr < 0 || usr > 0xffff) |
742 | return -EINVAL; |
743 | |
744 | if (isl1208_i2c_set_usr(to_i2c_client(dev->parent), usr)) |
745 | return -EIO; |
746 | |
747 | return count; |
748 | } |
749 | |
750 | static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, |
751 | isl1208_sysfs_store_usr); |
752 | |
753 | static struct attribute *isl1208_rtc_attrs[] = { |
754 | &dev_attr_atrim.attr, |
755 | &dev_attr_dtrim.attr, |
756 | &dev_attr_usr.attr, |
757 | NULL |
758 | }; |
759 | |
760 | static const struct attribute_group isl1208_rtc_sysfs_files = { |
761 | .attrs = isl1208_rtc_attrs, |
762 | }; |
763 | |
764 | static struct attribute *isl1219_rtc_attrs[] = { |
765 | &dev_attr_timestamp0.attr, |
766 | NULL |
767 | }; |
768 | |
769 | static const struct attribute_group isl1219_rtc_sysfs_files = { |
770 | .attrs = isl1219_rtc_attrs, |
771 | }; |
772 | |
773 | static int isl1208_nvmem_read(void *priv, unsigned int off, void *buf, |
774 | size_t count) |
775 | { |
776 | struct isl1208_state *isl1208 = priv; |
777 | struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); |
778 | int ret; |
779 | |
780 | /* nvmem sanitizes offset/count for us, but count==0 is possible */ |
781 | if (!count) |
782 | return count; |
783 | ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf, |
784 | len: count); |
785 | return ret == 0 ? count : ret; |
786 | } |
787 | |
788 | static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf, |
789 | size_t count) |
790 | { |
791 | struct isl1208_state *isl1208 = priv; |
792 | struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent); |
793 | int ret; |
794 | |
795 | /* nvmem sanitizes off/count for us, but count==0 is possible */ |
796 | if (!count) |
797 | return count; |
798 | ret = isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf, |
799 | len: count); |
800 | |
801 | return ret == 0 ? count : ret; |
802 | } |
803 | |
804 | static const struct nvmem_config isl1208_nvmem_config = { |
805 | .name = "isl1208_nvram" , |
806 | .word_size = 1, |
807 | .stride = 1, |
808 | /* .size from chip specific config */ |
809 | .reg_read = isl1208_nvmem_read, |
810 | .reg_write = isl1208_nvmem_write, |
811 | }; |
812 | |
813 | static int isl1208_setup_irq(struct i2c_client *client, int irq) |
814 | { |
815 | int rc = devm_request_threaded_irq(dev: &client->dev, irq, NULL, |
816 | thread_fn: isl1208_rtc_interrupt, |
817 | IRQF_SHARED | IRQF_ONESHOT, |
818 | devname: isl1208_driver.driver.name, |
819 | dev_id: client); |
820 | if (!rc) { |
821 | device_init_wakeup(dev: &client->dev, enable: 1); |
822 | enable_irq_wake(irq); |
823 | } else { |
824 | dev_err(&client->dev, |
825 | "Unable to request irq %d, no alarm support\n" , |
826 | irq); |
827 | } |
828 | return rc; |
829 | } |
830 | |
831 | static int |
832 | isl1208_clk_present(struct i2c_client *client, const char *name) |
833 | { |
834 | struct clk *clk; |
835 | |
836 | clk = devm_clk_get_optional(dev: &client->dev, id: name); |
837 | if (IS_ERR(ptr: clk)) |
838 | return PTR_ERR(ptr: clk); |
839 | |
840 | return !!clk; |
841 | } |
842 | |
843 | static int |
844 | isl1208_probe(struct i2c_client *client) |
845 | { |
846 | struct isl1208_state *isl1208; |
847 | int evdet_irq = -1; |
848 | int xtosb_val = 0; |
849 | int rc = 0; |
850 | int sr; |
851 | |
852 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) |
853 | return -ENODEV; |
854 | |
855 | if (isl1208_i2c_validate_client(client) < 0) |
856 | return -ENODEV; |
857 | |
858 | /* Allocate driver state, point i2c client data to it */ |
859 | isl1208 = devm_kzalloc(dev: &client->dev, size: sizeof(*isl1208), GFP_KERNEL); |
860 | if (!isl1208) |
861 | return -ENOMEM; |
862 | i2c_set_clientdata(client, data: isl1208); |
863 | |
864 | /* Determine which chip we have */ |
865 | isl1208->config = i2c_get_match_data(client); |
866 | if (!isl1208->config) |
867 | return -ENODEV; |
868 | |
869 | rc = isl1208_clk_present(client, name: "xin" ); |
870 | if (rc < 0) |
871 | return rc; |
872 | |
873 | if (!rc) { |
874 | rc = isl1208_clk_present(client, name: "clkin" ); |
875 | if (rc < 0) |
876 | return rc; |
877 | |
878 | if (rc) |
879 | xtosb_val = 1; |
880 | } |
881 | |
882 | isl1208->rtc = devm_rtc_allocate_device(dev: &client->dev); |
883 | if (IS_ERR(ptr: isl1208->rtc)) |
884 | return PTR_ERR(ptr: isl1208->rtc); |
885 | |
886 | isl1208->rtc->ops = &isl1208_rtc_ops; |
887 | |
888 | /* Setup nvmem configuration in driver state struct */ |
889 | isl1208->nvmem_config = isl1208_nvmem_config; |
890 | isl1208->nvmem_config.size = isl1208->config->nvmem_length; |
891 | isl1208->nvmem_config.priv = isl1208; |
892 | |
893 | sr = isl1208_i2c_get_sr(client); |
894 | if (sr < 0) { |
895 | dev_err(&client->dev, "reading status failed\n" ); |
896 | return sr; |
897 | } |
898 | |
899 | if (isl1208->config->has_inverted_osc_bit) |
900 | xtosb_val = !xtosb_val; |
901 | |
902 | rc = isl1208_set_xtoscb(client, sr, xtosb_val); |
903 | if (rc) |
904 | return rc; |
905 | |
906 | if (sr & ISL1208_REG_SR_RTCF) |
907 | dev_warn(&client->dev, "rtc power failure detected, " |
908 | "please set clock.\n" ); |
909 | |
910 | if (isl1208->config->has_tamper) { |
911 | struct device_node *np = client->dev.of_node; |
912 | u32 evienb; |
913 | |
914 | rc = i2c_smbus_read_byte_data(client, ISL1219_REG_EV); |
915 | if (rc < 0) { |
916 | dev_err(&client->dev, "failed to read EV reg\n" ); |
917 | return rc; |
918 | } |
919 | rc |= ISL1219_REG_EV_EVEN; |
920 | if (!of_property_read_u32(np, propname: "isil,ev-evienb" , out_value: &evienb)) { |
921 | if (evienb) |
922 | rc |= ISL1219_REG_EV_EVIENB; |
923 | else |
924 | rc &= ~ISL1219_REG_EV_EVIENB; |
925 | } |
926 | rc = i2c_smbus_write_byte_data(client, ISL1219_REG_EV, value: rc); |
927 | if (rc < 0) { |
928 | dev_err(&client->dev, "could not enable tamper detection\n" ); |
929 | return rc; |
930 | } |
931 | evdet_irq = of_irq_get_byname(dev: np, name: "evdet" ); |
932 | } |
933 | if (isl1208->config->has_timestamp) { |
934 | rc = rtc_add_group(rtc: isl1208->rtc, grp: &isl1219_rtc_sysfs_files); |
935 | if (rc) |
936 | return rc; |
937 | } |
938 | |
939 | rc = rtc_add_group(rtc: isl1208->rtc, grp: &isl1208_rtc_sysfs_files); |
940 | if (rc) |
941 | return rc; |
942 | |
943 | if (client->irq > 0) { |
944 | rc = isl1208_setup_irq(client, irq: client->irq); |
945 | if (rc) |
946 | return rc; |
947 | } else { |
948 | clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, addr: isl1208->rtc->features); |
949 | } |
950 | |
951 | if (evdet_irq > 0 && evdet_irq != client->irq) |
952 | rc = isl1208_setup_irq(client, irq: evdet_irq); |
953 | if (rc) |
954 | return rc; |
955 | |
956 | rc = devm_rtc_nvmem_register(rtc: isl1208->rtc, nvmem_config: &isl1208->nvmem_config); |
957 | if (rc) |
958 | return rc; |
959 | |
960 | return devm_rtc_register_device(isl1208->rtc); |
961 | } |
962 | |
963 | static struct i2c_driver isl1208_driver = { |
964 | .driver = { |
965 | .name = "rtc-isl1208" , |
966 | .of_match_table = of_match_ptr(isl1208_of_match), |
967 | }, |
968 | .probe = isl1208_probe, |
969 | .id_table = isl1208_id, |
970 | }; |
971 | |
972 | module_i2c_driver(isl1208_driver); |
973 | |
974 | MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>" ); |
975 | MODULE_DESCRIPTION("Intersil ISL1208 RTC driver" ); |
976 | MODULE_LICENSE("GPL" ); |
977 | |