|
@@ -35,12 +35,10 @@
|
|
|
#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);
|
|
|
|