]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/rtc/rtc-sa1100.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-beck.git] / drivers / rtc / rtc-sa1100.c
index abc19abd5f2d298a5f88ccc2314efe35cfc816a7..c2187bf6c7e41e09af3a04aa50a2e2f40eb76c24 100644 (file)
 #include <linux/bitops.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-
-#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
-#include <mach/regs-rtc.h>
-#endif
+#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 */
 
 #include "rtc-sa1100.h"
 
@@ -58,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
@@ -76,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)
@@ -130,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);
@@ -139,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;
@@ -187,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);
 
@@ -201,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;
 }
@@ -241,12 +249,12 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
         * 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);
        }
 
        rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
@@ -279,7 +287,7 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
         *
         * 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;
 }
@@ -288,6 +296,8 @@ 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");
@@ -301,6 +311,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
        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);