mvebu: drop support for old kernels
[openwrt.git] / target / linux / mvebu / patches-3.18 / 600-armada_38x_rtc.patch
diff --git a/target/linux/mvebu/patches-3.18/600-armada_38x_rtc.patch b/target/linux/mvebu/patches-3.18/600-armada_38x_rtc.patch
deleted file mode 100644 (file)
index 399421d..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
---- /dev/null
-+++ b/Documentation/devicetree/bindings/rtc/armada-380-rtc.txt
-@@ -0,0 +1,22 @@
-+* Real Time Clock of the Armada 38x SoCs
-+
-+RTC controller for the Armada 38x SoCs
-+
-+Required properties:
-+- compatible : Should be "marvell,armada-380-rtc"
-+- reg: a list of base address and size pairs, one for each entry in
-+  reg-names
-+- reg names: should contain:
-+  * "rtc" for the RTC registers
-+  * "rtc-soc" for the SoC related registers and among them the one
-+    related to the interrupt.
-+- interrupts: IRQ line for the RTC.
-+
-+Example:
-+
-+rtc@a3800 {
-+      compatible = "marvell,armada-380-rtc";
-+      reg = <0xa3800 0x20>, <0x184a0 0x0c>;
-+      reg-names = "rtc", "rtc-soc";
-+      interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-+};
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -1262,6 +1262,16 @@ config RTC_DRV_MV
-         This driver can also be built as a module. If so, the module
-         will be called rtc-mv.
-+config RTC_DRV_ARMADA38X
-+      tristate "Armada 38x Marvell SoC RTC"
-+      depends on ARCH_MVEBU
-+      help
-+        If you say yes here you will get support for the in-chip RTC
-+        that can be found in the Armada 38x Marvell's SoC device
-+
-+        This driver can also be built as a module. If so, the module
-+        will be called armada38x-rtc.
-+
- config RTC_DRV_PS3
-       tristate "PS3 RTC"
-       depends on PPC_PS3
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-8
- obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
- obj-$(CONFIG_RTC_DRV_AB3100)  += rtc-ab3100.o
- obj-$(CONFIG_RTC_DRV_AB8500)  += rtc-ab8500.o
-+obj-$(CONFIG_RTC_DRV_ARMADA38X)       += rtc-armada38x.o
- obj-$(CONFIG_RTC_DRV_AS3722)  += rtc-as3722.o
- obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
- obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
---- /dev/null
-+++ b/drivers/rtc/rtc-armada38x.c
-@@ -0,0 +1,320 @@
-+/*
-+ * RTC driver for the Armada 38x Marvell SoCs
-+ *
-+ * Copyright (C) 2015 Marvell
-+ *
-+ * Gregory Clement <gregory.clement@free-electrons.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of the
-+ * License, or (at your option) any later version.
-+ *
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/rtc.h>
-+
-+#define RTC_STATUS        0x0
-+#define RTC_STATUS_ALARM1         BIT(0)
-+#define RTC_STATUS_ALARM2         BIT(1)
-+#define RTC_IRQ1_CONF     0x4
-+#define RTC_IRQ1_AL_EN                    BIT(0)
-+#define RTC_IRQ1_FREQ_EN          BIT(1)
-+#define RTC_IRQ1_FREQ_1HZ         BIT(2)
-+#define RTC_TIME          0xC
-+#define RTC_ALARM1        0x10
-+
-+#define SOC_RTC_INTERRUPT   0x8
-+#define SOC_RTC_ALARM1                BIT(0)
-+#define SOC_RTC_ALARM2                BIT(1)
-+#define SOC_RTC_ALARM1_MASK   BIT(2)
-+#define SOC_RTC_ALARM2_MASK   BIT(3)
-+
-+struct armada38x_rtc {
-+      struct rtc_device   *rtc_dev;
-+      void __iomem        *regs;
-+      void __iomem        *regs_soc;
-+      spinlock_t          lock;
-+      int                 irq;
-+};
-+
-+/*
-+ * According to the datasheet, the OS should wait 5us after every
-+ * register write to the RTC hard macro so that the required update
-+ * can occur without holding off the system bus
-+ */
-+static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
-+{
-+      writel(val, rtc->regs + offset);
-+      udelay(5);
-+}
-+
-+static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+      unsigned long time, time_check, flags;
-+
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      time = readl(rtc->regs + RTC_TIME);
-+      /*
-+       * WA for failing time set attempts. As stated in HW ERRATA if
-+       * more than one second between two time reads is detected
-+       * then read once again.
-+       */
-+      time_check = readl(rtc->regs + RTC_TIME);
-+      if ((time_check - time) > 1)
-+              time_check = readl(rtc->regs + RTC_TIME);
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+
-+      rtc_time_to_tm(time_check, tm);
-+
-+      return 0;
-+}
-+
-+static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+      int ret = 0;
-+      unsigned long time, flags;
-+
-+      ret = rtc_tm_to_time(tm, &time);
-+
-+      if (ret)
-+              goto out;
-+      /*
-+       * Setting the RTC time not always succeeds. According to the
-+       * errata we need to first write on the status register and
-+       * then wait for 100ms before writing to the time register to be
-+       * sure that the data will be taken into account.
-+       */
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      rtc_delayed_write(0, rtc, RTC_STATUS);
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+
-+      msleep(100);
-+
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      rtc_delayed_write(time, rtc, RTC_TIME);
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+out:
-+      return ret;
-+}
-+
-+static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+      struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+      unsigned long time, flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      time = readl(rtc->regs + RTC_ALARM1);
-+      val = readl(rtc->regs + RTC_IRQ1_CONF) & RTC_IRQ1_AL_EN;
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+
-+      alrm->enabled = val ? 1 : 0;
-+      rtc_time_to_tm(time,  &alrm->time);
-+
-+      return 0;
-+}
-+
-+static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-+{
-+      struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+      unsigned long time, flags;
-+      int ret = 0;
-+      u32 val;
-+
-+      ret = rtc_tm_to_time(&alrm->time, &time);
-+
-+      if (ret)
-+              goto out;
-+
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      rtc_delayed_write(time, rtc, RTC_ALARM1);
-+
-+      if (alrm->enabled) {
-+                      rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
-+                      val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
-+                      writel(val | SOC_RTC_ALARM1_MASK,
-+                             rtc->regs_soc + SOC_RTC_INTERRUPT);
-+      }
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+
-+out:
-+      return ret;
-+}
-+
-+static int armada38x_rtc_alarm_irq_enable(struct device *dev,
-+                                       unsigned int enabled)
-+{
-+      struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&rtc->lock, flags);
-+
-+      if (enabled)
-+              rtc_delayed_write(RTC_IRQ1_AL_EN, rtc, RTC_IRQ1_CONF);
-+      else
-+              rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
-+
-+      spin_unlock_irqrestore(&rtc->lock, flags);
-+
-+      return 0;
-+}
-+
-+static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
-+{
-+      struct armada38x_rtc *rtc = data;
-+      u32 val;
-+      int event = RTC_IRQF | RTC_AF;
-+
-+      dev_dbg(&rtc->rtc_dev->dev, "%s:irq(%d)\n", __func__, irq);
-+
-+      spin_lock(&rtc->lock);
-+
-+      val = readl(rtc->regs_soc + SOC_RTC_INTERRUPT);
-+
-+      writel(val & ~SOC_RTC_ALARM1, rtc->regs_soc + SOC_RTC_INTERRUPT);
-+      val = readl(rtc->regs + RTC_IRQ1_CONF);
-+      /* disable all the interrupts for alarm 1 */
-+      rtc_delayed_write(0, rtc, RTC_IRQ1_CONF);
-+      /* Ack the event */
-+      rtc_delayed_write(RTC_STATUS_ALARM1, rtc, RTC_STATUS);
-+
-+      spin_unlock(&rtc->lock);
-+
-+      if (val & RTC_IRQ1_FREQ_EN) {
-+              if (val & RTC_IRQ1_FREQ_1HZ)
-+                      event |= RTC_UF;
-+              else
-+                      event |= RTC_PF;
-+      }
-+
-+      rtc_update_irq(rtc->rtc_dev, 1, event);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static struct rtc_class_ops armada38x_rtc_ops = {
-+      .read_time = armada38x_rtc_read_time,
-+      .set_time = armada38x_rtc_set_time,
-+      .read_alarm = armada38x_rtc_read_alarm,
-+      .set_alarm = armada38x_rtc_set_alarm,
-+      .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
-+};
-+
-+static __init int armada38x_rtc_probe(struct platform_device *pdev)
-+{
-+      struct resource *res;
-+      struct armada38x_rtc *rtc;
-+      int ret;
-+
-+      rtc = devm_kzalloc(&pdev->dev, sizeof(struct armada38x_rtc),
-+                          GFP_KERNEL);
-+      if (!rtc)
-+              return -ENOMEM;
-+
-+      spin_lock_init(&rtc->lock);
-+
-+      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
-+      rtc->regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(rtc->regs))
-+              return PTR_ERR(rtc->regs);
-+      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc-soc");
-+      rtc->regs_soc = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(rtc->regs_soc))
-+              return PTR_ERR(rtc->regs_soc);
-+
-+      rtc->irq = platform_get_irq(pdev, 0);
-+
-+      if (rtc->irq < 0) {
-+              dev_err(&pdev->dev, "no irq\n");
-+              return rtc->irq;
-+      }
-+      if (devm_request_irq(&pdev->dev, rtc->irq, armada38x_rtc_alarm_irq,
-+                              0, pdev->name, rtc) < 0) {
-+              dev_warn(&pdev->dev, "Interrupt not available.\n");
-+              rtc->irq = -1;
-+              /*
-+               * If there is no interrupt available then we can't
-+               * use the alarm
-+               */
-+              armada38x_rtc_ops.set_alarm = NULL;
-+              armada38x_rtc_ops.alarm_irq_enable = NULL;
-+      }
-+      platform_set_drvdata(pdev, rtc);
-+      if (rtc->irq != -1)
-+              device_init_wakeup(&pdev->dev, 1);
-+
-+      rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
-+                                      &armada38x_rtc_ops, THIS_MODULE);
-+      if (IS_ERR(rtc->rtc_dev)) {
-+              ret = PTR_ERR(rtc->rtc_dev);
-+              dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
-+              return ret;
-+      }
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int armada38x_rtc_suspend(struct device *dev)
-+{
-+      if (device_may_wakeup(dev)) {
-+              struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+
-+              return enable_irq_wake(rtc->irq);
-+      }
-+
-+      return 0;
-+}
-+
-+static int armada38x_rtc_resume(struct device *dev)
-+{
-+      if (device_may_wakeup(dev)) {
-+              struct armada38x_rtc *rtc = dev_get_drvdata(dev);
-+
-+              return disable_irq_wake(rtc->irq);
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
-+static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
-+                       armada38x_rtc_suspend, armada38x_rtc_resume);
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id armada38x_rtc_of_match_table[] = {
-+      { .compatible = "marvell,armada-380-rtc", },
-+      {}
-+};
-+#endif
-+
-+static struct platform_driver armada38x_rtc_driver = {
-+      .driver         = {
-+              .name   = "armada38x-rtc",
-+              .pm     = &armada38x_rtc_pm_ops,
-+              .of_match_table = of_match_ptr(armada38x_rtc_of_match_table),
-+      },
-+};
-+
-+module_platform_driver_probe(armada38x_rtc_driver, armada38x_rtc_probe);
-+
-+MODULE_DESCRIPTION("Marvell Armada 38x RTC driver");
-+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
-+MODULE_LICENSE("GPL");
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -1136,6 +1136,7 @@ M:       Sebastian Hesselbarth <sebastian.hess
- L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
- S:    Maintained
- F:    arch/arm/mach-mvebu/
-+F:    drivers/rtc/armada38x-rtc
- ARM/Marvell Berlin SoC support
- M:    Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---- a/arch/arm/boot/dts/armada-38x.dtsi
-+++ b/arch/arm/boot/dts/armada-38x.dtsi
-@@ -420,6 +420,13 @@
-                               clocks = <&gateclk 4>;
-                       };
-+                      rtc@a3800 {
-+                              compatible = "marvell,armada-380-rtc";
-+                              reg = <0xa3800 0x20>, <0x184a0 0x0c>;
-+                              reg-names = "rtc", "rtc-soc";
-+                              interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-+                      };
-+
-                       sata@a8000 {
-                               compatible = "marvell,armada-380-ahci";
-                               reg = <0xa8000 0x2000>;