1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * pm8xxx RTC driver |
4 | * |
5 | * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. |
6 | * Copyright (c) 2023, Linaro Limited |
7 | */ |
8 | #include <linux/of.h> |
9 | #include <linux/module.h> |
10 | #include <linux/nvmem-consumer.h> |
11 | #include <linux/init.h> |
12 | #include <linux/rtc.h> |
13 | #include <linux/platform_device.h> |
14 | #include <linux/pm.h> |
15 | #include <linux/pm_wakeirq.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/spinlock.h> |
19 | |
20 | #include <asm/unaligned.h> |
21 | |
22 | /* RTC_CTRL register bit fields */ |
23 | #define PM8xxx_RTC_ENABLE BIT(7) |
24 | #define PM8xxx_RTC_ALARM_CLEAR BIT(0) |
25 | #define PM8xxx_RTC_ALARM_ENABLE BIT(7) |
26 | |
27 | #define NUM_8_BIT_RTC_REGS 0x4 |
28 | |
29 | /** |
30 | * struct pm8xxx_rtc_regs - describe RTC registers per PMIC versions |
31 | * @ctrl: address of control register |
32 | * @write: base address of write registers |
33 | * @read: base address of read registers |
34 | * @alarm_ctrl: address of alarm control register |
35 | * @alarm_ctrl2: address of alarm control2 register |
36 | * @alarm_rw: base address of alarm read-write registers |
37 | * @alarm_en: alarm enable mask |
38 | */ |
39 | struct pm8xxx_rtc_regs { |
40 | unsigned int ctrl; |
41 | unsigned int write; |
42 | unsigned int read; |
43 | unsigned int alarm_ctrl; |
44 | unsigned int alarm_ctrl2; |
45 | unsigned int alarm_rw; |
46 | unsigned int alarm_en; |
47 | }; |
48 | |
49 | /** |
50 | * struct pm8xxx_rtc - RTC driver internal structure |
51 | * @rtc: RTC device |
52 | * @regmap: regmap used to access registers |
53 | * @allow_set_time: whether the time can be set |
54 | * @alarm_irq: alarm irq number |
55 | * @regs: register description |
56 | * @dev: device structure |
57 | * @nvmem_cell: nvmem cell for offset |
58 | * @offset: offset from epoch in seconds |
59 | */ |
60 | struct pm8xxx_rtc { |
61 | struct rtc_device *rtc; |
62 | struct regmap *regmap; |
63 | bool allow_set_time; |
64 | int alarm_irq; |
65 | const struct pm8xxx_rtc_regs *regs; |
66 | struct device *dev; |
67 | struct nvmem_cell *nvmem_cell; |
68 | u32 offset; |
69 | }; |
70 | |
71 | static int pm8xxx_rtc_read_nvmem_offset(struct pm8xxx_rtc *rtc_dd) |
72 | { |
73 | size_t len; |
74 | void *buf; |
75 | int rc; |
76 | |
77 | buf = nvmem_cell_read(cell: rtc_dd->nvmem_cell, len: &len); |
78 | if (IS_ERR(ptr: buf)) { |
79 | rc = PTR_ERR(ptr: buf); |
80 | dev_dbg(rtc_dd->dev, "failed to read nvmem offset: %d\n" , rc); |
81 | return rc; |
82 | } |
83 | |
84 | if (len != sizeof(u32)) { |
85 | dev_dbg(rtc_dd->dev, "unexpected nvmem cell size %zu\n" , len); |
86 | kfree(objp: buf); |
87 | return -EINVAL; |
88 | } |
89 | |
90 | rtc_dd->offset = get_unaligned_le32(p: buf); |
91 | |
92 | kfree(objp: buf); |
93 | |
94 | return 0; |
95 | } |
96 | |
97 | static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset) |
98 | { |
99 | u8 buf[sizeof(u32)]; |
100 | int rc; |
101 | |
102 | put_unaligned_le32(val: offset, p: buf); |
103 | |
104 | rc = nvmem_cell_write(cell: rtc_dd->nvmem_cell, buf, len: sizeof(buf)); |
105 | if (rc < 0) { |
106 | dev_dbg(rtc_dd->dev, "failed to write nvmem offset: %d\n" , rc); |
107 | return rc; |
108 | } |
109 | |
110 | return 0; |
111 | } |
112 | |
113 | static int pm8xxx_rtc_read_offset(struct pm8xxx_rtc *rtc_dd) |
114 | { |
115 | if (!rtc_dd->nvmem_cell) |
116 | return 0; |
117 | |
118 | return pm8xxx_rtc_read_nvmem_offset(rtc_dd); |
119 | } |
120 | |
121 | static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs) |
122 | { |
123 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
124 | u8 value[NUM_8_BIT_RTC_REGS]; |
125 | unsigned int reg; |
126 | int rc; |
127 | |
128 | rc = regmap_bulk_read(map: rtc_dd->regmap, reg: regs->read, val: value, val_count: sizeof(value)); |
129 | if (rc) |
130 | return rc; |
131 | |
132 | /* |
133 | * Read the LSB again and check if there has been a carry over. |
134 | * If there has, redo the read operation. |
135 | */ |
136 | rc = regmap_read(map: rtc_dd->regmap, reg: regs->read, val: ®); |
137 | if (rc < 0) |
138 | return rc; |
139 | |
140 | if (reg < value[0]) { |
141 | rc = regmap_bulk_read(map: rtc_dd->regmap, reg: regs->read, val: value, |
142 | val_count: sizeof(value)); |
143 | if (rc) |
144 | return rc; |
145 | } |
146 | |
147 | *secs = get_unaligned_le32(p: value); |
148 | |
149 | return 0; |
150 | } |
151 | |
152 | static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs) |
153 | { |
154 | u32 raw_secs; |
155 | u32 offset; |
156 | int rc; |
157 | |
158 | if (!rtc_dd->nvmem_cell) |
159 | return -ENODEV; |
160 | |
161 | rc = pm8xxx_rtc_read_raw(rtc_dd, secs: &raw_secs); |
162 | if (rc) |
163 | return rc; |
164 | |
165 | offset = secs - raw_secs; |
166 | |
167 | if (offset == rtc_dd->offset) |
168 | return 0; |
169 | |
170 | rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset); |
171 | if (rc) |
172 | return rc; |
173 | |
174 | rtc_dd->offset = offset; |
175 | |
176 | return 0; |
177 | } |
178 | |
179 | /* |
180 | * Steps to write the RTC registers. |
181 | * 1. Disable alarm if enabled. |
182 | * 2. Disable rtc if enabled. |
183 | * 3. Write 0x00 to LSB. |
184 | * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0]. |
185 | * 5. Enable rtc if disabled in step 2. |
186 | * 6. Enable alarm if disabled in step 1. |
187 | */ |
188 | static int __pm8xxx_rtc_set_time(struct pm8xxx_rtc *rtc_dd, u32 secs) |
189 | { |
190 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
191 | u8 value[NUM_8_BIT_RTC_REGS]; |
192 | bool alarm_enabled; |
193 | int rc; |
194 | |
195 | put_unaligned_le32(val: secs, p: value); |
196 | |
197 | rc = regmap_update_bits_check(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
198 | mask: regs->alarm_en, val: 0, change: &alarm_enabled); |
199 | if (rc) |
200 | return rc; |
201 | |
202 | /* Disable RTC */ |
203 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->ctrl, PM8xxx_RTC_ENABLE, val: 0); |
204 | if (rc) |
205 | return rc; |
206 | |
207 | /* Write 0 to Byte[0] */ |
208 | rc = regmap_write(map: rtc_dd->regmap, reg: regs->write, val: 0); |
209 | if (rc) |
210 | return rc; |
211 | |
212 | /* Write Byte[1], Byte[2], Byte[3] */ |
213 | rc = regmap_bulk_write(map: rtc_dd->regmap, reg: regs->write + 1, |
214 | val: &value[1], val_count: sizeof(value) - 1); |
215 | if (rc) |
216 | return rc; |
217 | |
218 | /* Write Byte[0] */ |
219 | rc = regmap_write(map: rtc_dd->regmap, reg: regs->write, val: value[0]); |
220 | if (rc) |
221 | return rc; |
222 | |
223 | /* Enable RTC */ |
224 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->ctrl, PM8xxx_RTC_ENABLE, |
225 | PM8xxx_RTC_ENABLE); |
226 | if (rc) |
227 | return rc; |
228 | |
229 | if (alarm_enabled) { |
230 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
231 | mask: regs->alarm_en, val: regs->alarm_en); |
232 | if (rc) |
233 | return rc; |
234 | } |
235 | |
236 | return 0; |
237 | } |
238 | |
239 | static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) |
240 | { |
241 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
242 | u32 secs; |
243 | int rc; |
244 | |
245 | secs = rtc_tm_to_time64(tm); |
246 | |
247 | if (rtc_dd->allow_set_time) |
248 | rc = __pm8xxx_rtc_set_time(rtc_dd, secs); |
249 | else |
250 | rc = pm8xxx_rtc_update_offset(rtc_dd, secs); |
251 | |
252 | if (rc) |
253 | return rc; |
254 | |
255 | dev_dbg(dev, "set time: %ptRd %ptRt (%u + %u)\n" , tm, tm, |
256 | secs - rtc_dd->offset, rtc_dd->offset); |
257 | return 0; |
258 | } |
259 | |
260 | static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) |
261 | { |
262 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
263 | u32 secs; |
264 | int rc; |
265 | |
266 | rc = pm8xxx_rtc_read_raw(rtc_dd, secs: &secs); |
267 | if (rc) |
268 | return rc; |
269 | |
270 | secs += rtc_dd->offset; |
271 | rtc_time64_to_tm(time: secs, tm); |
272 | |
273 | dev_dbg(dev, "read time: %ptRd %ptRt (%u + %u)\n" , tm, tm, |
274 | secs - rtc_dd->offset, rtc_dd->offset); |
275 | return 0; |
276 | } |
277 | |
278 | static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
279 | { |
280 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
281 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
282 | u8 value[NUM_8_BIT_RTC_REGS]; |
283 | u32 secs; |
284 | int rc; |
285 | |
286 | secs = rtc_tm_to_time64(tm: &alarm->time); |
287 | secs -= rtc_dd->offset; |
288 | put_unaligned_le32(val: secs, p: value); |
289 | |
290 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
291 | mask: regs->alarm_en, val: 0); |
292 | if (rc) |
293 | return rc; |
294 | |
295 | rc = regmap_bulk_write(map: rtc_dd->regmap, reg: regs->alarm_rw, val: value, |
296 | val_count: sizeof(value)); |
297 | if (rc) |
298 | return rc; |
299 | |
300 | if (alarm->enabled) { |
301 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
302 | mask: regs->alarm_en, val: regs->alarm_en); |
303 | if (rc) |
304 | return rc; |
305 | } |
306 | |
307 | dev_dbg(dev, "set alarm: %ptRd %ptRt\n" , &alarm->time, &alarm->time); |
308 | |
309 | return 0; |
310 | } |
311 | |
312 | static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
313 | { |
314 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
315 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
316 | u8 value[NUM_8_BIT_RTC_REGS]; |
317 | unsigned int ctrl_reg; |
318 | u32 secs; |
319 | int rc; |
320 | |
321 | rc = regmap_bulk_read(map: rtc_dd->regmap, reg: regs->alarm_rw, val: value, |
322 | val_count: sizeof(value)); |
323 | if (rc) |
324 | return rc; |
325 | |
326 | secs = get_unaligned_le32(p: value); |
327 | secs += rtc_dd->offset; |
328 | rtc_time64_to_tm(time: secs, tm: &alarm->time); |
329 | |
330 | rc = regmap_read(map: rtc_dd->regmap, reg: regs->alarm_ctrl, val: &ctrl_reg); |
331 | if (rc) |
332 | return rc; |
333 | |
334 | alarm->enabled = !!(ctrl_reg & PM8xxx_RTC_ALARM_ENABLE); |
335 | |
336 | dev_dbg(dev, "read alarm: %ptRd %ptRt\n" , &alarm->time, &alarm->time); |
337 | |
338 | return 0; |
339 | } |
340 | |
341 | static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) |
342 | { |
343 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); |
344 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
345 | u8 value[NUM_8_BIT_RTC_REGS] = {0}; |
346 | unsigned int val; |
347 | int rc; |
348 | |
349 | if (enable) |
350 | val = regs->alarm_en; |
351 | else |
352 | val = 0; |
353 | |
354 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
355 | mask: regs->alarm_en, val); |
356 | if (rc) |
357 | return rc; |
358 | |
359 | /* Clear alarm register */ |
360 | if (!enable) { |
361 | rc = regmap_bulk_write(map: rtc_dd->regmap, reg: regs->alarm_rw, val: value, |
362 | val_count: sizeof(value)); |
363 | if (rc) |
364 | return rc; |
365 | } |
366 | |
367 | return 0; |
368 | } |
369 | |
370 | static const struct rtc_class_ops pm8xxx_rtc_ops = { |
371 | .read_time = pm8xxx_rtc_read_time, |
372 | .set_time = pm8xxx_rtc_set_time, |
373 | .set_alarm = pm8xxx_rtc_set_alarm, |
374 | .read_alarm = pm8xxx_rtc_read_alarm, |
375 | .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, |
376 | }; |
377 | |
378 | static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) |
379 | { |
380 | struct pm8xxx_rtc *rtc_dd = dev_id; |
381 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
382 | int rc; |
383 | |
384 | rtc_update_irq(rtc: rtc_dd->rtc, num: 1, RTC_IRQF | RTC_AF); |
385 | |
386 | /* Disable alarm */ |
387 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl, |
388 | mask: regs->alarm_en, val: 0); |
389 | if (rc) |
390 | return IRQ_NONE; |
391 | |
392 | /* Clear alarm status */ |
393 | rc = regmap_update_bits(map: rtc_dd->regmap, reg: regs->alarm_ctrl2, |
394 | PM8xxx_RTC_ALARM_CLEAR, val: 0); |
395 | if (rc) |
396 | return IRQ_NONE; |
397 | |
398 | return IRQ_HANDLED; |
399 | } |
400 | |
401 | static int pm8xxx_rtc_enable(struct pm8xxx_rtc *rtc_dd) |
402 | { |
403 | const struct pm8xxx_rtc_regs *regs = rtc_dd->regs; |
404 | |
405 | return regmap_update_bits(map: rtc_dd->regmap, reg: regs->ctrl, PM8xxx_RTC_ENABLE, |
406 | PM8xxx_RTC_ENABLE); |
407 | } |
408 | |
409 | static const struct pm8xxx_rtc_regs pm8921_regs = { |
410 | .ctrl = 0x11d, |
411 | .write = 0x11f, |
412 | .read = 0x123, |
413 | .alarm_rw = 0x127, |
414 | .alarm_ctrl = 0x11d, |
415 | .alarm_ctrl2 = 0x11e, |
416 | .alarm_en = BIT(1), |
417 | }; |
418 | |
419 | static const struct pm8xxx_rtc_regs pm8058_regs = { |
420 | .ctrl = 0x1e8, |
421 | .write = 0x1ea, |
422 | .read = 0x1ee, |
423 | .alarm_rw = 0x1f2, |
424 | .alarm_ctrl = 0x1e8, |
425 | .alarm_ctrl2 = 0x1e9, |
426 | .alarm_en = BIT(1), |
427 | }; |
428 | |
429 | static const struct pm8xxx_rtc_regs pm8941_regs = { |
430 | .ctrl = 0x6046, |
431 | .write = 0x6040, |
432 | .read = 0x6048, |
433 | .alarm_rw = 0x6140, |
434 | .alarm_ctrl = 0x6146, |
435 | .alarm_ctrl2 = 0x6148, |
436 | .alarm_en = BIT(7), |
437 | }; |
438 | |
439 | static const struct pm8xxx_rtc_regs pmk8350_regs = { |
440 | .ctrl = 0x6146, |
441 | .write = 0x6140, |
442 | .read = 0x6148, |
443 | .alarm_rw = 0x6240, |
444 | .alarm_ctrl = 0x6246, |
445 | .alarm_ctrl2 = 0x6248, |
446 | .alarm_en = BIT(7), |
447 | }; |
448 | |
449 | static const struct of_device_id pm8xxx_id_table[] = { |
450 | { .compatible = "qcom,pm8921-rtc" , .data = &pm8921_regs }, |
451 | { .compatible = "qcom,pm8058-rtc" , .data = &pm8058_regs }, |
452 | { .compatible = "qcom,pm8941-rtc" , .data = &pm8941_regs }, |
453 | { .compatible = "qcom,pmk8350-rtc" , .data = &pmk8350_regs }, |
454 | { }, |
455 | }; |
456 | MODULE_DEVICE_TABLE(of, pm8xxx_id_table); |
457 | |
458 | static int pm8xxx_rtc_probe(struct platform_device *pdev) |
459 | { |
460 | const struct of_device_id *match; |
461 | struct pm8xxx_rtc *rtc_dd; |
462 | int rc; |
463 | |
464 | match = of_match_node(matches: pm8xxx_id_table, node: pdev->dev.of_node); |
465 | if (!match) |
466 | return -ENXIO; |
467 | |
468 | rtc_dd = devm_kzalloc(dev: &pdev->dev, size: sizeof(*rtc_dd), GFP_KERNEL); |
469 | if (rtc_dd == NULL) |
470 | return -ENOMEM; |
471 | |
472 | rtc_dd->regmap = dev_get_regmap(dev: pdev->dev.parent, NULL); |
473 | if (!rtc_dd->regmap) |
474 | return -ENXIO; |
475 | |
476 | rtc_dd->alarm_irq = platform_get_irq(pdev, 0); |
477 | if (rtc_dd->alarm_irq < 0) |
478 | return -ENXIO; |
479 | |
480 | rtc_dd->allow_set_time = of_property_read_bool(np: pdev->dev.of_node, |
481 | propname: "allow-set-time" ); |
482 | |
483 | rtc_dd->nvmem_cell = devm_nvmem_cell_get(dev: &pdev->dev, id: "offset" ); |
484 | if (IS_ERR(ptr: rtc_dd->nvmem_cell)) { |
485 | rc = PTR_ERR(ptr: rtc_dd->nvmem_cell); |
486 | if (rc != -ENOENT) |
487 | return rc; |
488 | rtc_dd->nvmem_cell = NULL; |
489 | } |
490 | |
491 | rtc_dd->regs = match->data; |
492 | rtc_dd->dev = &pdev->dev; |
493 | |
494 | if (!rtc_dd->allow_set_time) { |
495 | rc = pm8xxx_rtc_read_offset(rtc_dd); |
496 | if (rc) |
497 | return rc; |
498 | } |
499 | |
500 | rc = pm8xxx_rtc_enable(rtc_dd); |
501 | if (rc) |
502 | return rc; |
503 | |
504 | platform_set_drvdata(pdev, data: rtc_dd); |
505 | |
506 | device_init_wakeup(dev: &pdev->dev, enable: 1); |
507 | |
508 | rtc_dd->rtc = devm_rtc_allocate_device(dev: &pdev->dev); |
509 | if (IS_ERR(ptr: rtc_dd->rtc)) |
510 | return PTR_ERR(ptr: rtc_dd->rtc); |
511 | |
512 | rtc_dd->rtc->ops = &pm8xxx_rtc_ops; |
513 | rtc_dd->rtc->range_max = U32_MAX; |
514 | |
515 | rc = devm_request_any_context_irq(dev: &pdev->dev, irq: rtc_dd->alarm_irq, |
516 | handler: pm8xxx_alarm_trigger, |
517 | IRQF_TRIGGER_RISING, |
518 | devname: "pm8xxx_rtc_alarm" , dev_id: rtc_dd); |
519 | if (rc < 0) |
520 | return rc; |
521 | |
522 | rc = devm_rtc_register_device(rtc_dd->rtc); |
523 | if (rc) |
524 | return rc; |
525 | |
526 | rc = dev_pm_set_wake_irq(dev: &pdev->dev, irq: rtc_dd->alarm_irq); |
527 | if (rc) |
528 | return rc; |
529 | |
530 | return 0; |
531 | } |
532 | |
533 | static void pm8xxx_remove(struct platform_device *pdev) |
534 | { |
535 | dev_pm_clear_wake_irq(dev: &pdev->dev); |
536 | } |
537 | |
538 | static struct platform_driver pm8xxx_rtc_driver = { |
539 | .probe = pm8xxx_rtc_probe, |
540 | .remove_new = pm8xxx_remove, |
541 | .driver = { |
542 | .name = "rtc-pm8xxx" , |
543 | .of_match_table = pm8xxx_id_table, |
544 | }, |
545 | }; |
546 | |
547 | module_platform_driver(pm8xxx_rtc_driver); |
548 | |
549 | MODULE_ALIAS("platform:rtc-pm8xxx" ); |
550 | MODULE_DESCRIPTION("PMIC8xxx RTC driver" ); |
551 | MODULE_LICENSE("GPL v2" ); |
552 | MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>" ); |
553 | MODULE_AUTHOR("Johan Hovold <johan@kernel.org>" ); |
554 | |