19
19
#include <linux/platform_device.h>
20
20
#include <linux/pm_runtime.h>
21
21
#include <linux/rtc.h>
22
+ #include <linux/spinlock.h>
22
23
23
24
#define RZN1_RTC_CTL0 0x00
24
25
#define RZN1_RTC_CTL0_SLSB_SUBU 0
27
28
#define RZN1_RTC_CTL0_CE BIT(7)
28
29
29
30
#define RZN1_RTC_CTL1 0x04
31
+ #define RZN1_RTC_CTL1_1SE BIT(3)
30
32
#define RZN1_RTC_CTL1_ALME BIT(4)
31
33
32
34
#define RZN1_RTC_CTL2 0x08
58
60
struct rzn1_rtc {
59
61
struct rtc_device * rtcdev ;
60
62
void __iomem * base ;
63
+ /*
64
+ * Protects access to RZN1_RTC_CTL1 reg. rtc_lock with threaded_irqs
65
+ * would introduce race conditions when switching interrupts because
66
+ * of potential sleeps
67
+ */
68
+ spinlock_t ctl1_access_lock ;
69
+ struct rtc_time tm_alarm ;
61
70
};
62
71
63
72
static void rzn1_rtc_get_time_snapshot (struct rzn1_rtc * rtc , struct rtc_time * tm )
@@ -135,23 +144,77 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
135
144
static irqreturn_t rzn1_rtc_alarm_irq (int irq , void * dev_id )
136
145
{
137
146
struct rzn1_rtc * rtc = dev_id ;
147
+ u32 ctl1 , set_irq_bits = 0 ;
148
+
149
+ if (rtc -> tm_alarm .tm_sec == 0 )
150
+ rtc_update_irq (rtc -> rtcdev , 1 , RTC_AF | RTC_IRQF );
151
+ else
152
+ /* Switch to 1s interrupts */
153
+ set_irq_bits = RZN1_RTC_CTL1_1SE ;
138
154
139
- rtc_update_irq (rtc -> rtcdev , 1 , RTC_AF | RTC_IRQF );
155
+ guard (spinlock )(& rtc -> ctl1_access_lock );
156
+
157
+ ctl1 = readl (rtc -> base + RZN1_RTC_CTL1 );
158
+ ctl1 &= ~RZN1_RTC_CTL1_ALME ;
159
+ ctl1 |= set_irq_bits ;
160
+ writel (ctl1 , rtc -> base + RZN1_RTC_CTL1 );
161
+
162
+ return IRQ_HANDLED ;
163
+ }
164
+
165
+ static irqreturn_t rzn1_rtc_1s_irq (int irq , void * dev_id )
166
+ {
167
+ struct rzn1_rtc * rtc = dev_id ;
168
+ u32 ctl1 ;
169
+
170
+ if (readl (rtc -> base + RZN1_RTC_SECC ) == bin2bcd (rtc -> tm_alarm .tm_sec )) {
171
+ guard (spinlock )(& rtc -> ctl1_access_lock );
172
+
173
+ ctl1 = readl (rtc -> base + RZN1_RTC_CTL1 );
174
+ ctl1 &= ~RZN1_RTC_CTL1_1SE ;
175
+ writel (ctl1 , rtc -> base + RZN1_RTC_CTL1 );
176
+
177
+ rtc_update_irq (rtc -> rtcdev , 1 , RTC_AF | RTC_IRQF );
178
+ }
140
179
141
180
return IRQ_HANDLED ;
142
181
}
143
182
144
183
static int rzn1_rtc_alarm_irq_enable (struct device * dev , unsigned int enable )
145
184
{
146
185
struct rzn1_rtc * rtc = dev_get_drvdata (dev );
147
- u32 ctl1 = readl (rtc -> base + RZN1_RTC_CTL1 );
186
+ struct rtc_time * tm = & rtc -> tm_alarm , tm_now ;
187
+ u32 ctl1 ;
188
+ int ret ;
148
189
149
- if (enable )
150
- ctl1 |= RZN1_RTC_CTL1_ALME ;
151
- else
152
- ctl1 &= ~RZN1_RTC_CTL1_ALME ;
190
+ guard (spinlock_irqsave )(& rtc -> ctl1_access_lock );
153
191
154
- writel (ctl1 , rtc -> base + RZN1_RTC_CTL1 );
192
+ ctl1 = readl (rtc -> base + RZN1_RTC_CTL1 );
193
+
194
+ if (enable ) {
195
+ /*
196
+ * Use alarm interrupt if alarm time is at least a minute away
197
+ * or less than a minute but in the next minute. Otherwise use
198
+ * 1 second interrupt to wait for the proper second
199
+ */
200
+ do {
201
+ ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE );
202
+
203
+ ret = rzn1_rtc_read_time (dev , & tm_now );
204
+ if (ret )
205
+ return ret ;
206
+
207
+ if (rtc_tm_sub (tm , & tm_now ) > 59 || tm -> tm_min != tm_now .tm_min )
208
+ ctl1 |= RZN1_RTC_CTL1_ALME ;
209
+ else
210
+ ctl1 |= RZN1_RTC_CTL1_1SE ;
211
+
212
+ writel (ctl1 , rtc -> base + RZN1_RTC_CTL1 );
213
+ } while (readl (rtc -> base + RZN1_RTC_SECC ) != bin2bcd (tm_now .tm_sec ));
214
+ } else {
215
+ ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE );
216
+ writel (ctl1 , rtc -> base + RZN1_RTC_CTL1 );
217
+ }
155
218
156
219
return 0 ;
157
220
}
@@ -185,7 +248,7 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
185
248
}
186
249
187
250
ctl1 = readl (rtc -> base + RZN1_RTC_CTL1 );
188
- alrm -> enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME );
251
+ alrm -> enabled = !!(ctl1 & ( RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE ) );
189
252
190
253
return 0 ;
191
254
}
@@ -216,6 +279,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
216
279
writel (bin2bcd (tm -> tm_hour ), rtc -> base + RZN1_RTC_ALH );
217
280
writel (BIT (wday ), rtc -> base + RZN1_RTC_ALW );
218
281
282
+ rtc -> tm_alarm = alrm -> time ;
283
+
219
284
rzn1_rtc_alarm_irq_enable (dev , alrm -> enabled );
220
285
221
286
return 0 ;
@@ -304,7 +369,7 @@ static const struct rtc_class_ops rzn1_rtc_ops = {
304
369
static int rzn1_rtc_probe (struct platform_device * pdev )
305
370
{
306
371
struct rzn1_rtc * rtc ;
307
- int alarm_irq ;
372
+ int irq ;
308
373
int ret ;
309
374
310
375
rtc = devm_kzalloc (& pdev -> dev , sizeof (* rtc ), GFP_KERNEL );
@@ -317,9 +382,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
317
382
if (IS_ERR (rtc -> base ))
318
383
return dev_err_probe (& pdev -> dev , PTR_ERR (rtc -> base ), "Missing reg\n" );
319
384
320
- alarm_irq = platform_get_irq (pdev , 0 );
321
- if (alarm_irq < 0 )
322
- return alarm_irq ;
385
+ irq = platform_get_irq_byname (pdev , "alarm" );
386
+ if (irq < 0 )
387
+ return irq ;
323
388
324
389
rtc -> rtcdev = devm_rtc_allocate_device (& pdev -> dev );
325
390
if (IS_ERR (rtc -> rtcdev ))
@@ -329,8 +394,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
329
394
rtc -> rtcdev -> range_max = RTC_TIMESTAMP_END_2099 ;
330
395
rtc -> rtcdev -> alarm_offset_max = 7 * 86400 ;
331
396
rtc -> rtcdev -> ops = & rzn1_rtc_ops ;
332
- set_bit (RTC_FEATURE_ALARM_RES_MINUTE , rtc -> rtcdev -> features );
333
- clear_bit (RTC_FEATURE_UPDATE_INTERRUPT , rtc -> rtcdev -> features );
334
397
335
398
ret = devm_pm_runtime_enable (& pdev -> dev );
336
399
if (ret < 0 )
@@ -349,13 +412,24 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
349
412
/* Disable all interrupts */
350
413
writel (0 , rtc -> base + RZN1_RTC_CTL1 );
351
414
352
- ret = devm_request_irq (& pdev -> dev , alarm_irq , rzn1_rtc_alarm_irq , 0 ,
353
- dev_name (& pdev -> dev ), rtc );
415
+ spin_lock_init (& rtc -> ctl1_access_lock );
416
+
417
+ ret = devm_request_irq (& pdev -> dev , irq , rzn1_rtc_alarm_irq , 0 , "RZN1 RTC Alarm" , rtc );
354
418
if (ret ) {
355
- dev_err (& pdev -> dev , "RTC timer interrupt not available\n" );
419
+ dev_err (& pdev -> dev , "RTC alarm interrupt not available\n" );
356
420
goto dis_runtime_pm ;
357
421
}
358
422
423
+ irq = platform_get_irq_byname_optional (pdev , "pps" );
424
+ if (irq >= 0 )
425
+ ret = devm_request_irq (& pdev -> dev , irq , rzn1_rtc_1s_irq , 0 , "RZN1 RTC 1s" , rtc );
426
+
427
+ if (irq < 0 || ret ) {
428
+ set_bit (RTC_FEATURE_ALARM_RES_MINUTE , rtc -> rtcdev -> features );
429
+ clear_bit (RTC_FEATURE_UPDATE_INTERRUPT , rtc -> rtcdev -> features );
430
+ dev_warn (& pdev -> dev , "RTC pps interrupt not available. Alarm has only minute accuracy\n" );
431
+ }
432
+
359
433
ret = devm_rtc_register_device (rtc -> rtcdev );
360
434
if (ret )
361
435
goto dis_runtime_pm ;
0 commit comments