1919#include <linux/platform_device.h>
2020#include <linux/pm_runtime.h>
2121#include <linux/rtc.h>
22+ #include <linux/spinlock.h>
2223
2324#define RZN1_RTC_CTL0 0x00
2425#define RZN1_RTC_CTL0_SLSB_SUBU 0
2728#define RZN1_RTC_CTL0_CE BIT(7)
2829
2930#define RZN1_RTC_CTL1 0x04
31+ #define RZN1_RTC_CTL1_1SE BIT(3)
3032#define RZN1_RTC_CTL1_ALME BIT(4)
3133
3234#define RZN1_RTC_CTL2 0x08
5860struct rzn1_rtc {
5961 struct rtc_device * rtcdev ;
6062 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 ;
6170};
6271
6372static 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)
135144static irqreturn_t rzn1_rtc_alarm_irq (int irq , void * dev_id )
136145{
137146 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 ;
138154
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+ }
140179
141180 return IRQ_HANDLED ;
142181}
143182
144183static int rzn1_rtc_alarm_irq_enable (struct device * dev , unsigned int enable )
145184{
146185 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 ;
148189
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 );
153191
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+ }
155218
156219 return 0 ;
157220}
@@ -185,7 +248,7 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
185248 }
186249
187250 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 ) );
189252
190253 return 0 ;
191254}
@@ -216,6 +279,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
216279 writel (bin2bcd (tm -> tm_hour ), rtc -> base + RZN1_RTC_ALH );
217280 writel (BIT (wday ), rtc -> base + RZN1_RTC_ALW );
218281
282+ rtc -> tm_alarm = alrm -> time ;
283+
219284 rzn1_rtc_alarm_irq_enable (dev , alrm -> enabled );
220285
221286 return 0 ;
@@ -304,7 +369,7 @@ static const struct rtc_class_ops rzn1_rtc_ops = {
304369static int rzn1_rtc_probe (struct platform_device * pdev )
305370{
306371 struct rzn1_rtc * rtc ;
307- int alarm_irq ;
372+ int irq ;
308373 int ret ;
309374
310375 rtc = devm_kzalloc (& pdev -> dev , sizeof (* rtc ), GFP_KERNEL );
@@ -317,9 +382,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
317382 if (IS_ERR (rtc -> base ))
318383 return dev_err_probe (& pdev -> dev , PTR_ERR (rtc -> base ), "Missing reg\n" );
319384
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 ;
323388
324389 rtc -> rtcdev = devm_rtc_allocate_device (& pdev -> dev );
325390 if (IS_ERR (rtc -> rtcdev ))
@@ -329,8 +394,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
329394 rtc -> rtcdev -> range_max = RTC_TIMESTAMP_END_2099 ;
330395 rtc -> rtcdev -> alarm_offset_max = 7 * 86400 ;
331396 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 );
334397
335398 ret = devm_pm_runtime_enable (& pdev -> dev );
336399 if (ret < 0 )
@@ -349,13 +412,24 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
349412 /* Disable all interrupts */
350413 writel (0 , rtc -> base + RZN1_RTC_CTL1 );
351414
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 );
354418 if (ret ) {
355- dev_err (& pdev -> dev , "RTC timer interrupt not available\n" );
419+ dev_err (& pdev -> dev , "RTC alarm interrupt not available\n" );
356420 goto dis_runtime_pm ;
357421 }
358422
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+
359433 ret = devm_rtc_register_device (rtc -> rtcdev );
360434 if (ret )
361435 goto dis_runtime_pm ;
0 commit comments