Merge tag 'rtc-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[cascardo/linux.git] / arch / arm / mach-omap2 / omap_hwmod_reset.c
index 65e186c..b68f9c0 100644 (file)
 #include <sound/aess.h>
 
 #include "omap_hwmod.h"
+#include "common.h"
+
+#define OMAP_RTC_STATUS_REG    0x44
+#define OMAP_RTC_KICK0_REG     0x6c
+#define OMAP_RTC_KICK1_REG     0x70
+
+#define OMAP_RTC_KICK0_VALUE   0x83E70B13
+#define OMAP_RTC_KICK1_VALUE   0x95A4F1E0
+#define OMAP_RTC_STATUS_BUSY   BIT(0)
+#define OMAP_RTC_MAX_READY_TIME        50
 
 /**
  * omap_hwmod_aess_preprogram - enable AESS internal autogating
@@ -51,3 +61,58 @@ int omap_hwmod_aess_preprogram(struct omap_hwmod *oh)
 
        return 0;
 }
+
+/**
+ * omap_rtc_wait_not_busy - Wait for the RTC BUSY flag
+ * @oh: struct omap_hwmod *
+ *
+ * For updating certain RTC registers, the MPU must wait
+ * for the BUSY status in OMAP_RTC_STATUS_REG to become zero.
+ * Once the BUSY status is zero, there is a 15 microseconds access
+ * period in which the MPU can program.
+ */
+static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
+{
+       int i;
+
+       /* BUSY may stay active for 1/32768 second (~30 usec) */
+       omap_test_timeout(omap_hwmod_read(oh, OMAP_RTC_STATUS_REG)
+                         & OMAP_RTC_STATUS_BUSY, OMAP_RTC_MAX_READY_TIME, i);
+       /* now we have ~15 microseconds to read/write various registers */
+}
+
+/**
+ * omap_hwmod_rtc_unlock - Unlock the Kicker mechanism.
+ * @oh: struct omap_hwmod *
+ *
+ * RTC IP have kicker feature. This prevents spurious writes to its registers.
+ * In order to write into any of the RTC registers, KICK values has te be
+ * written in respective KICK registers. This is needed for hwmod to write into
+ * sysconfig register.
+ */
+void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
+{
+       local_irq_disable();
+       omap_rtc_wait_not_busy(oh);
+       omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
+       omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
+       local_irq_enable();
+}
+
+/**
+ * omap_hwmod_rtc_lock - Lock the Kicker mechanism.
+ * @oh: struct omap_hwmod *
+ *
+ * RTC IP have kicker feature. This prevents spurious writes to its registers.
+ * Once the RTC registers are written, KICK mechanism needs to be locked,
+ * in order to prevent any spurious writes. This function locks back the RTC
+ * registers once hwmod completes its write into sysconfig register.
+ */
+void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
+{
+       local_irq_disable();
+       omap_rtc_wait_not_busy(oh);
+       omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
+       omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
+       local_irq_enable();
+}