1
1
// SPDX-License-Identifier: GPL-2.0-only
2
- /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2
+ /*
3
+ * pm8xxx RTC driver
4
+ *
5
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
6
+ * Copyright (c) 2023, Linaro Limited
3
7
*/
4
8
#include <linux/of.h>
5
9
#include <linux/module.h>
10
+ #include <linux/nvmem-consumer.h>
6
11
#include <linux/init.h>
7
12
#include <linux/rtc.h>
8
13
#include <linux/platform_device.h>
@@ -49,6 +54,8 @@ struct pm8xxx_rtc_regs {
49
54
* @alarm_irq: alarm irq number
50
55
* @regs: register description
51
56
* @dev: device structure
57
+ * @nvmem_cell: nvmem cell for offset
58
+ * @offset: offset from epoch in seconds
52
59
*/
53
60
struct pm8xxx_rtc {
54
61
struct rtc_device * rtc ;
@@ -57,8 +64,60 @@ struct pm8xxx_rtc {
57
64
int alarm_irq ;
58
65
const struct pm8xxx_rtc_regs * regs ;
59
66
struct device * dev ;
67
+ struct nvmem_cell * nvmem_cell ;
68
+ u32 offset ;
60
69
};
61
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 (rtc_dd -> nvmem_cell , & len );
78
+ if (IS_ERR (buf )) {
79
+ rc = PTR_ERR (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 (buf );
87
+ return - EINVAL ;
88
+ }
89
+
90
+ rtc_dd -> offset = get_unaligned_le32 (buf );
91
+
92
+ kfree (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 (offset , buf );
103
+
104
+ rc = nvmem_cell_write (rtc_dd -> nvmem_cell , buf , 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
+
62
121
static int pm8xxx_rtc_read_raw (struct pm8xxx_rtc * rtc_dd , u32 * secs )
63
122
{
64
123
const struct pm8xxx_rtc_regs * regs = rtc_dd -> regs ;
@@ -90,6 +149,33 @@ static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs)
90
149
return 0 ;
91
150
}
92
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 , & 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
+
93
179
/*
94
180
* Steps to write the RTC registers.
95
181
* 1. Disable alarm if enabled.
@@ -99,23 +185,15 @@ static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs)
99
185
* 5. Enable rtc if disabled in step 2.
100
186
* 6. Enable alarm if disabled in step 1.
101
187
*/
102
- static int pm8xxx_rtc_set_time (struct device * dev , struct rtc_time * tm )
188
+ static int __pm8xxx_rtc_set_time (struct pm8xxx_rtc * rtc_dd , u32 secs )
103
189
{
104
- struct pm8xxx_rtc * rtc_dd = dev_get_drvdata (dev );
105
190
const struct pm8xxx_rtc_regs * regs = rtc_dd -> regs ;
106
191
u8 value [NUM_8_BIT_RTC_REGS ];
107
192
bool alarm_enabled ;
108
- u32 secs ;
109
193
int rc ;
110
194
111
- if (!rtc_dd -> allow_set_time )
112
- return - ENODEV ;
113
-
114
- secs = rtc_tm_to_time64 (tm );
115
195
put_unaligned_le32 (secs , value );
116
196
117
- dev_dbg (dev , "set time: %ptRd %ptRt (%u)\n" , tm , tm , secs );
118
-
119
197
rc = regmap_update_bits_check (rtc_dd -> regmap , regs -> alarm_ctrl ,
120
198
regs -> alarm_en , 0 , & alarm_enabled );
121
199
if (rc )
@@ -158,6 +236,27 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
158
236
return 0 ;
159
237
}
160
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
+
161
260
static int pm8xxx_rtc_read_time (struct device * dev , struct rtc_time * tm )
162
261
{
163
262
struct pm8xxx_rtc * rtc_dd = dev_get_drvdata (dev );
@@ -168,10 +267,11 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
168
267
if (rc )
169
268
return rc ;
170
269
270
+ secs += rtc_dd -> offset ;
171
271
rtc_time64_to_tm (secs , tm );
172
272
173
- dev_dbg (dev , "read time: %ptRd %ptRt (%u)\n" , tm , tm , secs );
174
-
273
+ dev_dbg (dev , "read time: %ptRd %ptRt (%u + %u )\n" , tm , tm ,
274
+ secs - rtc_dd -> offset , rtc_dd -> offset );
175
275
return 0 ;
176
276
}
177
277
@@ -184,6 +284,7 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
184
284
int rc ;
185
285
186
286
secs = rtc_tm_to_time64 (& alarm -> time );
287
+ secs -= rtc_dd -> offset ;
187
288
put_unaligned_le32 (secs , value );
188
289
189
290
rc = regmap_update_bits (rtc_dd -> regmap , regs -> alarm_ctrl ,
@@ -223,6 +324,7 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
223
324
return rc ;
224
325
225
326
secs = get_unaligned_le32 (value );
327
+ secs += rtc_dd -> offset ;
226
328
rtc_time64_to_tm (secs , & alarm -> time );
227
329
228
330
rc = regmap_read (rtc_dd -> regmap , regs -> alarm_ctrl , & ctrl_reg );
@@ -378,9 +480,23 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
378
480
rtc_dd -> allow_set_time = of_property_read_bool (pdev -> dev .of_node ,
379
481
"allow-set-time" );
380
482
483
+ rtc_dd -> nvmem_cell = devm_nvmem_cell_get (& pdev -> dev , "offset" );
484
+ if (IS_ERR (rtc_dd -> nvmem_cell )) {
485
+ rc = PTR_ERR (rtc_dd -> nvmem_cell );
486
+ if (rc != - ENOENT )
487
+ return rc ;
488
+ rtc_dd -> nvmem_cell = NULL ;
489
+ }
490
+
381
491
rtc_dd -> regs = match -> data ;
382
492
rtc_dd -> dev = & pdev -> dev ;
383
493
494
+ if (!rtc_dd -> allow_set_time ) {
495
+ rc = pm8xxx_rtc_read_offset (rtc_dd );
496
+ if (rc )
497
+ return rc ;
498
+ }
499
+
384
500
rc = pm8xxx_rtc_enable (rtc_dd );
385
501
if (rc )
386
502
return rc ;
@@ -435,3 +551,4 @@ MODULE_ALIAS("platform:rtc-pm8xxx");
435
551
MODULE_DESCRIPTION ("PMIC8xxx RTC driver" );
436
552
MODULE_LICENSE ("GPL v2" );
437
553
MODULE_AUTHOR (
"Anirudh Ghayal <[email protected] >" );
554
+ MODULE_AUTHOR (
"Johan Hovold <[email protected] >" );
0 commit comments