ARM: OMAP2+: hwmod: RTC: Add lock and unlock functions
authorLokesh Vutla <lokeshvutla@ti.com>
Sun, 10 Apr 2016 19:20:10 +0000 (13:20 -0600)
committerPaul Walmsley <paul@pwsan.com>
Sun, 10 Apr 2016 19:20:10 +0000 (13:20 -0600)
RTC IP have kicker feature which prevents spurious writes to its registers.
In order to write into any of the RTC registers, KICK values has to be
written to KICK registers. Also, RTC busy flag needs to be polled for
non-TC registers as well, without which update is not proper and confirmed
it by testing on DRA7-evm.
Introduce omap_hwmod_rtc_unlock/lock functions, which  writes into these
KICK registers inorder to lock and unlock RTC registers.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[paul@pwsan.com: fixed subject line]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_reset.c

index 7c7a31169475b72bc8fbbe2f0dabf015b395f257..4041bad79a9abbe9bc4ca74abd29027c01bf5d57 100644 (file)
@@ -754,6 +754,8 @@ const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh);
  */
 
 extern int omap_hwmod_aess_preprogram(struct omap_hwmod *oh);
+void omap_hwmod_rtc_unlock(struct omap_hwmod *oh);
+void omap_hwmod_rtc_lock(struct omap_hwmod *oh);
 
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
index 65e186c9df55da7e5b662242ae8066430ded0e1d..b68f9c0aff0b594d97af0c004c2525a7072197f0 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();
+}