Merge tag 'trace-seq-buf-3.19-v2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / rtc / rtc-sirfsoc.c
index 76e3800..d2ac668 100644 (file)
@@ -47,6 +47,7 @@ struct sirfsoc_rtc_drv {
        unsigned                irq_wake;
        /* Overflow for every 8 years extra time */
        u32                     overflow_rtc;
+       spinlock_t              lock;
 #ifdef CONFIG_PM
        u32             saved_counter;
        u32             saved_overflow_rtc;
@@ -61,7 +62,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
 
        rtcdrv = dev_get_drvdata(dev);
 
-       local_irq_disable();
+       spin_lock_irq(&rtcdrv->lock);
 
        rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
 
@@ -84,7 +85,8 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
        if (sirfsoc_rtc_iobrg_readl(
                        rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E)
                alrm->enabled = 1;
-       local_irq_enable();
+
+       spin_unlock_irq(&rtcdrv->lock);
 
        return 0;
 }
@@ -99,7 +101,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
        if (alrm->enabled) {
                rtc_tm_to_time(&(alrm->time), &rtc_alarm);
 
-               local_irq_disable();
+               spin_lock_irq(&rtcdrv->lock);
 
                rtc_status_reg = sirfsoc_rtc_iobrg_readl(
                                rtcdrv->rtc_base + RTC_STATUS);
@@ -123,14 +125,15 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                rtc_status_reg |= SIRFSOC_RTC_AL0E;
                sirfsoc_rtc_iobrg_writel(
                        rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
-               local_irq_enable();
+
+               spin_unlock_irq(&rtcdrv->lock);
        } else {
                /*
                 * if this function was called with enabled=0
                 * then it could mean that the application is
                 * trying to cancel an ongoing alarm
                 */
-               local_irq_disable();
+               spin_lock_irq(&rtcdrv->lock);
 
                rtc_status_reg = sirfsoc_rtc_iobrg_readl(
                                rtcdrv->rtc_base + RTC_STATUS);
@@ -146,7 +149,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                                        rtcdrv->rtc_base + RTC_STATUS);
                }
 
-               local_irq_enable();
+               spin_unlock_irq(&rtcdrv->lock);
        }
 
        return 0;
@@ -209,12 +212,38 @@ static int sirfsoc_rtc_ioctl(struct device *dev, unsigned int cmd,
        }
 }
 
+static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
+               unsigned int enabled)
+{
+       unsigned long rtc_status_reg = 0x0;
+       struct sirfsoc_rtc_drv *rtcdrv;
+
+       rtcdrv = dev_get_drvdata(dev);
+
+       spin_lock_irq(&rtcdrv->lock);
+
+       rtc_status_reg = sirfsoc_rtc_iobrg_readl(
+                               rtcdrv->rtc_base + RTC_STATUS);
+       if (enabled)
+               rtc_status_reg |= SIRFSOC_RTC_AL0E;
+       else
+               rtc_status_reg &= ~SIRFSOC_RTC_AL0E;
+
+       sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+
+       spin_unlock_irq(&rtcdrv->lock);
+
+       return 0;
+
+}
+
 static const struct rtc_class_ops sirfsoc_rtc_ops = {
        .read_time = sirfsoc_rtc_read_time,
        .set_time = sirfsoc_rtc_set_time,
        .read_alarm = sirfsoc_rtc_read_alarm,
        .set_alarm = sirfsoc_rtc_set_alarm,
-       .ioctl = sirfsoc_rtc_ioctl
+       .ioctl = sirfsoc_rtc_ioctl,
+       .alarm_irq_enable = sirfsoc_rtc_alarm_irq_enable
 };
 
 static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
@@ -223,6 +252,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
        unsigned long rtc_status_reg = 0x0;
        unsigned long events = 0x0;
 
+       spin_lock(&rtcdrv->lock);
+
        rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS);
        /* this bit will be set ONLY if an alarm was active
         * and it expired NOW
@@ -240,6 +271,9 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
                rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
        }
        sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+
+       spin_unlock(&rtcdrv->lock);
+
        /* this should wake up any apps polling/waiting on the read
         * after setting the alarm
         */
@@ -267,6 +301,8 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        if (rtcdrv == NULL)
                return -ENOMEM;
 
+       spin_lock_init(&rtcdrv->lock);
+
        err = of_property_read_u32(np, "reg", &rtcdrv->rtc_base);
        if (err) {
                dev_err(&pdev->dev, "unable to find base address of rtc node in dtb\n");
@@ -286,14 +322,6 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        rtc_div = ((32768 / RTC_HZ) / 2) - 1;
        sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
 
-       rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
-                       &sirfsoc_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtcdrv->rtc)) {
-               err = PTR_ERR(rtcdrv->rtc);
-               dev_err(&pdev->dev, "can't register RTC device\n");
-               return err;
-       }
-
        /* 0x3 -> RTC_CLK */
        sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
                        rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
@@ -308,6 +336,14 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        rtcdrv->overflow_rtc =
                sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
 
+       rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+                       &sirfsoc_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtcdrv->rtc)) {
+               err = PTR_ERR(rtcdrv->rtc);
+               dev_err(&pdev->dev, "can't register RTC device\n");
+               return err;
+       }
+
        rtcdrv->irq = platform_get_irq(pdev, 0);
        err = devm_request_irq(
                        &pdev->dev,