These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / rtc / rtc-sa1100.c
index b6e1ca0..c2187bf 100644 (file)
 #include <linux/bitops.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
-#include <mach/irqs.h>
+#define RTSR_HZE               BIT(3)  /* HZ interrupt enable */
+#define RTSR_ALE               BIT(2)  /* RTC alarm interrupt enable */
+#define RTSR_HZ                        BIT(1)  /* HZ rising-edge detected */
+#define RTSR_AL                        BIT(0)  /* RTC alarm detected */
 
-#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
-#include <mach/regs-rtc.h>
-#endif
+#include "rtc-sa1100.h"
 
 #define RTC_DEF_DIVIDER                (32768 - 1)
 #define RTC_DEF_TRIM           0
 #define RTC_FREQ               1024
 
-struct sa1100_rtc {
-       spinlock_t              lock;
-       int                     irq_1hz;
-       int                     irq_alarm;
-       struct rtc_device       *rtc;
-       struct clk              *clk;
-};
 
 static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 {
@@ -63,16 +56,16 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 
        spin_lock(&info->lock);
 
-       rtsr = RTSR;
+       rtsr = readl_relaxed(info->rtsr);
        /* clear interrupt sources */
-       RTSR = 0;
+       writel_relaxed(0, info->rtsr);
        /* Fix for a nasty initialization problem the in SA11xx RTSR register.
         * See also the comments in sa1100_rtc_probe(). */
        if (rtsr & (RTSR_ALE | RTSR_HZE)) {
                /* This is the original code, before there was the if test
                 * above. This code does not clear interrupts that were not
                 * enabled. */
-               RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+               writel_relaxed((RTSR_AL | RTSR_HZ) & (rtsr >> 2), info->rtsr);
        } else {
                /* For some reason, it is possible to enter this routine
                 * without interruptions enabled, it has been tested with
@@ -81,13 +74,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
                 * This situation leads to an infinite "loop" of interrupt
                 * routine calling and as a result the processor seems to
                 * lock on its first call to open(). */
-               RTSR = RTSR_AL | RTSR_HZ;
+               writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
        }
 
        /* clear alarm interrupt if it has occurred */
        if (rtsr & RTSR_AL)
                rtsr &= ~RTSR_ALE;
-       RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
+       writel_relaxed(rtsr & (RTSR_ALE | RTSR_HZE), info->rtsr);
 
        /* update irq data & counter */
        if (rtsr & RTSR_AL)
@@ -135,7 +128,7 @@ static void sa1100_rtc_release(struct device *dev)
        struct sa1100_rtc *info = dev_get_drvdata(dev);
 
        spin_lock_irq(&info->lock);
-       RTSR = 0;
+       writel_relaxed(0, info->rtsr);
        spin_unlock_irq(&info->lock);
 
        free_irq(info->irq_alarm, dev);
@@ -144,39 +137,46 @@ static void sa1100_rtc_release(struct device *dev)
 
 static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
+       u32 rtsr;
        struct sa1100_rtc *info = dev_get_drvdata(dev);
 
        spin_lock_irq(&info->lock);
+       rtsr = readl_relaxed(info->rtsr);
        if (enabled)
-               RTSR |= RTSR_ALE;
+               rtsr |= RTSR_ALE;
        else
-               RTSR &= ~RTSR_ALE;
+               rtsr &= ~RTSR_ALE;
+       writel_relaxed(rtsr, info->rtsr);
        spin_unlock_irq(&info->lock);
        return 0;
 }
 
 static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       rtc_time_to_tm(RCNR, tm);
+       struct sa1100_rtc *info = dev_get_drvdata(dev);
+
+       rtc_time_to_tm(readl_relaxed(info->rcnr), tm);
        return 0;
 }
 
 static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
+       struct sa1100_rtc *info = dev_get_drvdata(dev);
        unsigned long time;
        int ret;
 
        ret = rtc_tm_to_time(tm, &time);
        if (ret == 0)
-               RCNR = time;
+               writel_relaxed(time, info->rcnr);
        return ret;
 }
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        u32     rtsr;
+       struct sa1100_rtc *info = dev_get_drvdata(dev);
 
-       rtsr = RTSR;
+       rtsr = readl_relaxed(info->rtsr);
        alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
        alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
        return 0;
@@ -192,12 +192,13 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        ret = rtc_tm_to_time(&alrm->time, &time);
        if (ret != 0)
                goto out;
-       RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
-       RTAR = time;
+       writel_relaxed(readl_relaxed(info->rtsr) &
+               (RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr);
+       writel_relaxed(time, info->rtar);
        if (alrm->enabled)
-               RTSR |= RTSR_ALE;
+               writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr);
        else
-               RTSR &= ~RTSR_ALE;
+               writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr);
 out:
        spin_unlock_irq(&info->lock);
 
@@ -206,8 +207,10 @@ out:
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-       seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
-       seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
+       struct sa1100_rtc *info = dev_get_drvdata(dev);
+
+       seq_printf(seq, "trim/divider\t\t: 0x%08x\n", readl_relaxed(info->rttr));
+       seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", readl_relaxed(info->rtsr));
 
        return 0;
 }
@@ -223,29 +226,18 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
        .alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
 };
 
-static int sa1100_rtc_probe(struct platform_device *pdev)
+int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
 {
        struct rtc_device *rtc;
-       struct sa1100_rtc *info;
-       int irq_1hz, irq_alarm, ret = 0;
+       int ret;
 
-       irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
-       irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
-       if (irq_1hz < 0 || irq_alarm < 0)
-               return -ENODEV;
+       spin_lock_init(&info->lock);
 
-       info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
        info->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(info->clk)) {
                dev_err(&pdev->dev, "failed to find rtc clock source\n");
                return PTR_ERR(info->clk);
        }
-       info->irq_1hz = irq_1hz;
-       info->irq_alarm = irq_alarm;
-       spin_lock_init(&info->lock);
-       platform_set_drvdata(pdev, info);
 
        ret = clk_prepare_enable(info->clk);
        if (ret)
@@ -257,22 +249,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
         * If the clock divider is uninitialized then reset it to the
         * default value to get the 1Hz clock.
         */
-       if (RTTR == 0) {
-               RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+       if (readl_relaxed(info->rttr) == 0) {
+               writel_relaxed(RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16), info->rttr);
                dev_warn(&pdev->dev, "warning: "
                        "initializing default clock divider/trim value\n");
                /* The current RTC value probably doesn't make sense either */
-               RCNR = 0;
+               writel_relaxed(0, info->rcnr);
        }
 
-       device_init_wakeup(&pdev->dev, 1);
-
        rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
                                        THIS_MODULE);
-
        if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               goto err_dev;
+               clk_disable_unprepare(info->clk);
+               return PTR_ERR(rtc);
        }
        info->rtc = rtc;
 
@@ -298,12 +287,52 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
         *
         * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
         * the corresponding bits in RTSR. */
-       RTSR = RTSR_AL | RTSR_HZ;
+       writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
 
        return 0;
-err_dev:
-       clk_disable_unprepare(info->clk);
-       return ret;
+}
+EXPORT_SYMBOL_GPL(sa1100_rtc_init);
+
+static int sa1100_rtc_probe(struct platform_device *pdev)
+{
+       struct sa1100_rtc *info;
+       struct resource *iores;
+       void __iomem *base;
+       int irq_1hz, irq_alarm;
+
+       irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
+       irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
+       if (irq_1hz < 0 || irq_alarm < 0)
+               return -ENODEV;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+       info->irq_1hz = irq_1hz;
+       info->irq_alarm = irq_alarm;
+
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, iores);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       if (IS_ENABLED(CONFIG_ARCH_SA1100) ||
+           of_device_is_compatible(pdev->dev.of_node, "mrvl,sa1100-rtc")) {
+               info->rcnr = base + 0x04;
+               info->rtsr = base + 0x10;
+               info->rtar = base + 0x00;
+               info->rttr = base + 0x08;
+       } else {
+               info->rcnr = base + 0x0;
+               info->rtsr = base + 0x8;
+               info->rtar = base + 0x4;
+               info->rttr = base + 0xc;
+       }
+
+       platform_set_drvdata(pdev, info);
+       device_init_wakeup(&pdev->dev, 1);
+
+       return sa1100_rtc_init(pdev, info);
 }
 
 static int sa1100_rtc_remove(struct platform_device *pdev)