Merge tag '5.11-rc-smb3' of git://git.samba.org/sfrench/cifs-2.6
[linux-2.6-microblaze.git] / drivers / rtc / rtc-zynqmp.c
index 5786866..4b1077e 100644 (file)
@@ -38,6 +38,8 @@
 
 #define RTC_CALIB_DEF          0x198233
 #define RTC_CALIB_MASK         0x1FFFFF
+#define RTC_ALRM_MASK          BIT(1)
+#define RTC_MSEC               1000
 
 struct xlnx_rtc_dev {
        struct rtc_device       *rtc;
@@ -123,11 +125,28 @@ static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
 {
        struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+       unsigned int status;
+       ulong timeout;
+
+       timeout = jiffies + msecs_to_jiffies(RTC_MSEC);
+
+       if (enabled) {
+               while (1) {
+                       status = readl(xrtcdev->reg_base + RTC_INT_STS);
+                       if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK))
+                               break;
+
+                       if (time_after_eq(jiffies, timeout)) {
+                               dev_err(dev, "Time out occur, while clearing alarm status bit\n");
+                               return -ETIMEDOUT;
+                       }
+                       writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
+               }
 
-       if (enabled)
                writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);
-       else
+       } else {
                writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
+       }
 
        return 0;
 }
@@ -183,8 +202,8 @@ static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
        if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))
                return IRQ_NONE;
 
-       /* Clear RTC_INT_ALRM interrupt only */
-       writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
+       /* Disable RTC_INT_ALRM interrupt only */
+       writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
 
        if (status & RTC_INT_ALRM)
                rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);