These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / rtc / rtc-sirfsoc.c
index edc3b43..7367f61 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 #include <linux/rtc/sirfsoc_rtciobrg.h>
 
 
@@ -48,12 +49,27 @@ struct sirfsoc_rtc_drv {
        /* Overflow for every 8 years extra time */
        u32                     overflow_rtc;
        spinlock_t              lock;
+       struct regmap *regmap;
 #ifdef CONFIG_PM
        u32             saved_counter;
        u32             saved_overflow_rtc;
 #endif
 };
 
+static u32 sirfsoc_rtc_readl(struct sirfsoc_rtc_drv *rtcdrv, u32 offset)
+{
+       u32 val;
+
+       regmap_read(rtcdrv->regmap, rtcdrv->rtc_base + offset, &val);
+       return val;
+}
+
+static void sirfsoc_rtc_writel(struct sirfsoc_rtc_drv *rtcdrv,
+                              u32 offset, u32 val)
+{
+       regmap_write(rtcdrv->regmap, rtcdrv->rtc_base + offset, val);
+}
+
 static int sirfsoc_rtc_read_alarm(struct device *dev,
                struct rtc_wkalrm *alrm)
 {
@@ -64,9 +80,9 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
 
        spin_lock_irq(&rtcdrv->lock);
 
-       rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+       rtc_count = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
 
-       rtc_alarm = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_ALARM0);
+       rtc_alarm = sirfsoc_rtc_readl(rtcdrv, RTC_ALARM0);
        memset(alrm, 0, sizeof(struct rtc_wkalrm));
 
        /*
@@ -82,8 +98,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
                rtc_time_to_tm(rtcdrv->overflow_rtc
                                << (BITS_PER_LONG - RTC_SHIFT)
                                | rtc_alarm >> RTC_SHIFT, &(alrm->time));
-       if (sirfsoc_rtc_iobrg_readl(
-                       rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E)
+       if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E)
                alrm->enabled = 1;
 
        spin_unlock_irq(&rtcdrv->lock);
@@ -103,8 +118,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
 
                spin_lock_irq(&rtcdrv->lock);
 
-               rtc_status_reg = sirfsoc_rtc_iobrg_readl(
-                               rtcdrv->rtc_base + RTC_STATUS);
+               rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
                if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
                        /*
                         * An ongoing alarm in progress - ingore it and not
@@ -113,8 +127,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                        dev_info(dev, "An old alarm was set, will be replaced by a new one\n");
                }
 
-               sirfsoc_rtc_iobrg_writel(
-                       rtc_alarm << RTC_SHIFT, rtcdrv->rtc_base + RTC_ALARM0);
+               sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, rtc_alarm << RTC_SHIFT);
                rtc_status_reg &= ~0x07; /* mask out the lower status bits */
                /*
                 * This bit RTC_AL sets it as a wake-up source for Sleep Mode
@@ -123,8 +136,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                rtc_status_reg |= SIRFSOC_RTC_AL0;
                /* enable the RTC alarm interrupt */
                rtc_status_reg |= SIRFSOC_RTC_AL0E;
-               sirfsoc_rtc_iobrg_writel(
-                       rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+               sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
 
                spin_unlock_irq(&rtcdrv->lock);
        } else {
@@ -135,8 +147,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                 */
                spin_lock_irq(&rtcdrv->lock);
 
-               rtc_status_reg = sirfsoc_rtc_iobrg_readl(
-                               rtcdrv->rtc_base + RTC_STATUS);
+               rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
                if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
                        /* clear the RTC status register's alarm bit */
                        rtc_status_reg &= ~0x07;
@@ -145,8 +156,8 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
                        /* Clear the Alarm enable bit */
                        rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
 
-                       sirfsoc_rtc_iobrg_writel(rtc_status_reg,
-                                       rtcdrv->rtc_base + RTC_STATUS);
+                       sirfsoc_rtc_writel(rtcdrv, RTC_STATUS,
+                                          rtc_status_reg);
                }
 
                spin_unlock_irq(&rtcdrv->lock);
@@ -167,9 +178,9 @@ static int sirfsoc_rtc_read_time(struct device *dev,
         * fail, read several times to make sure get stable value.
         */
        do {
-               tmp_rtc = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+               tmp_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
                cpu_relax();
-       } while (tmp_rtc != sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN));
+       } while (tmp_rtc != sirfsoc_rtc_readl(rtcdrv, RTC_CN));
 
        rtc_time_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) |
                                        tmp_rtc >> RTC_SHIFT, tm);
@@ -187,10 +198,8 @@ static int sirfsoc_rtc_set_time(struct device *dev,
 
        rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT);
 
-       sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
-                       rtcdrv->rtc_base + RTC_SW_VALUE);
-       sirfsoc_rtc_iobrg_writel(
-                       rtc_time << RTC_SHIFT, rtcdrv->rtc_base + RTC_CN);
+       sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
+       sirfsoc_rtc_writel(rtcdrv, RTC_CN, rtc_time << RTC_SHIFT);
 
        return 0;
 }
@@ -222,14 +231,13 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
 
        spin_lock_irq(&rtcdrv->lock);
 
-       rtc_status_reg = sirfsoc_rtc_iobrg_readl(
-                               rtcdrv->rtc_base + RTC_STATUS);
+       rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, 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);
+       sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
 
        spin_unlock_irq(&rtcdrv->lock);
 
@@ -254,7 +262,7 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
 
        spin_lock(&rtcdrv->lock);
 
-       rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS);
+       rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
        /* this bit will be set ONLY if an alarm was active
         * and it expired NOW
         * So this is being used as an ASSERT
@@ -270,7 +278,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
                /* Clear the Alarm enable bit */
                rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
        }
-       sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+
+       sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
 
        spin_unlock(&rtcdrv->lock);
 
@@ -287,6 +296,13 @@ static const struct of_device_id sirfsoc_rtc_of_match[] = {
        { .compatible = "sirf,prima2-sysrtc"},
        {},
 };
+
+const struct regmap_config sysrtc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .fast_io = true,
+};
+
 MODULE_DEVICE_TABLE(of, sirfsoc_rtc_of_match);
 
 static int sirfsoc_rtc_probe(struct platform_device *pdev)
@@ -314,27 +330,35 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
        /* Register rtc alarm as a wakeup source */
        device_init_wakeup(&pdev->dev, 1);
 
+       rtcdrv->regmap = devm_regmap_init_iobg(&pdev->dev,
+                       &sysrtc_regmap_config);
+       if (IS_ERR(rtcdrv->regmap)) {
+               err = PTR_ERR(rtcdrv->regmap);
+               dev_err(&pdev->dev, "Failed to allocate register map: %d\n",
+                       err);
+               return err;
+       }
+
        /*
         * Set SYS_RTC counter in RTC_HZ HZ Units
         * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
         * If 16HZ, therefore RTC_DIV = 1023;
         */
        rtc_div = ((32768 / RTC_HZ) / 2) - 1;
-       sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
+       sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
 
        /* 0x3 -> RTC_CLK */
-       sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
-                       rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
+       sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
 
        /* reset SYS RTC ALARM0 */
-       sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0);
+       sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
 
        /* reset SYS RTC ALARM1 */
-       sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1);
+       sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
 
        /* Restore RTC Overflow From Register After Command Reboot */
        rtcdrv->overflow_rtc =
-               sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
+               sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
 
        rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                        &sirfsoc_rtc_ops, THIS_MODULE);
@@ -372,10 +396,10 @@ static int sirfsoc_rtc_suspend(struct device *dev)
 {
        struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
        rtcdrv->overflow_rtc =
-               sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
+               sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
 
        rtcdrv->saved_counter =
-               sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+               sirfsoc_rtc_readl(rtcdrv, RTC_CN);
        rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
        if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq))
                rtcdrv->irq_wake = 1;
@@ -392,12 +416,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
         * if resume from snapshot and the rtc power is lost,
         * restroe the rtc settings
         */
-       if (SIRFSOC_RTC_CLK != sirfsoc_rtc_iobrg_readl(
-                       rtcdrv->rtc_base + RTC_CLOCK_SWITCH)) {
+       if (SIRFSOC_RTC_CLK != sirfsoc_rtc_readl(rtcdrv, RTC_CLOCK_SWITCH)) {
                u32 rtc_div;
                /* 0x3 -> RTC_CLK */
-               sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
-                       rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
+               sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
                /*
                 * Set SYS_RTC counter in RTC_HZ HZ Units
                 * We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
@@ -405,13 +427,13 @@ static int sirfsoc_rtc_resume(struct device *dev)
                 */
                rtc_div = ((32768 / RTC_HZ) / 2) - 1;
 
-               sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
+               sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
 
                /* reset SYS RTC ALARM0 */
-               sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0);
+               sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
 
                /* reset SYS RTC ALARM1 */
-               sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1);
+               sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
        }
        rtcdrv->overflow_rtc = rtcdrv->saved_overflow_rtc;
 
@@ -419,15 +441,14 @@ static int sirfsoc_rtc_resume(struct device *dev)
         * if current counter is small than previous,
         * it means overflow in sleep
         */
-       tmp = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+       tmp = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
        if (tmp <= rtcdrv->saved_counter)
                rtcdrv->overflow_rtc++;
        /*
         *PWRC Value Be Changed When Suspend, Restore Overflow
         * In Memory To Register
         */
-       sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
-                       rtcdrv->rtc_base + RTC_SW_VALUE);
+       sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
 
        if (device_may_wakeup(dev) && rtcdrv->irq_wake) {
                disable_irq_wake(rtcdrv->irq);