]> Pileus Git - ~andy/linux/blobdiff - arch/arm/mach-imx/clk-imx6q.c
ARM: imx: enable RBC to support anatop LPM mode
[~andy/linux] / arch / arm / mach-imx / clk-imx6q.c
index 262b7b6c79aa30e6d9020d84734e9bb29a955a85..23b799a51e6cf4bcb46abcaddc71ae66bda4d636 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -25,6 +26,8 @@
 
 #define CCR                            0x0
 #define BM_CCR_WB_COUNT                        (0x7 << 16)
+#define BM_CCR_RBC_BYPASS_COUNT                (0x3f << 21)
+#define BM_CCR_RBC_EN                  (0x1 << 27)
 
 #define CCGR0                          0x68
 #define CCGR1                          0x6c
@@ -70,6 +73,44 @@ void imx6q_set_chicken_bit(void)
        writel_relaxed(val, ccm_base + CGPR);
 }
 
+static void imx6q_enable_rbc(bool enable)
+{
+       u32 val;
+       static bool last_rbc_mode;
+
+       if (last_rbc_mode == enable)
+               return;
+       /*
+        * need to mask all interrupts in GPC before
+        * operating RBC configurations
+        */
+       imx_gpc_mask_all();
+
+       /* configure RBC enable bit */
+       val = readl_relaxed(ccm_base + CCR);
+       val &= ~BM_CCR_RBC_EN;
+       val |= enable ? BM_CCR_RBC_EN : 0;
+       writel_relaxed(val, ccm_base + CCR);
+
+       /* configure RBC count */
+       val = readl_relaxed(ccm_base + CCR);
+       val &= ~BM_CCR_RBC_BYPASS_COUNT;
+       val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
+       writel(val, ccm_base + CCR);
+
+       /*
+        * need to delay at least 2 cycles of CKIL(32K)
+        * due to hardware design requirement, which is
+        * ~61us, here we use 65us for safe
+        */
+       udelay(65);
+
+       /* restore GPC interrupt mask settings */
+       imx_gpc_restore_all();
+
+       last_rbc_mode = enable;
+}
+
 static void imx6q_enable_wb(bool enable)
 {
        u32 val;
@@ -101,6 +142,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
        switch (mode) {
        case WAIT_CLOCKED:
                imx6q_enable_wb(false);
+               imx6q_enable_rbc(false);
                break;
        case WAIT_UNCLOCKED:
                val |= 0x1 << BP_CLPCR_LPM;
@@ -120,6 +162,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
                val |= BM_CLPCR_VSTBY;
                val |= BM_CLPCR_SBYOS;
                imx6q_enable_wb(true);
+               imx6q_enable_rbc(true);
                break;
        default:
                return -EINVAL;