These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / arm / mach-imx / pm-imx6.c
index 6a7c6fc..4470376 100644 (file)
@@ -93,6 +93,7 @@ struct imx6_pm_socdata {
        const char *src_compat;
        const char *iomuxc_compat;
        const char *gpc_compat;
+       const char *pl310_compat;
        const u32 mmdc_io_num;
        const u32 *mmdc_io_offset;
 };
@@ -137,11 +138,19 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
        0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
 };
 
+static const u32 imx6ul_mmdc_io_offset[] __initconst = {
+       0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
+       0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
+       0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */
+       0x494, 0x4b0,               /* MODE_CTL, MODE, */
+};
+
 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
        .mmdc_compat = "fsl,imx6q-mmdc",
        .src_compat = "fsl,imx6q-src",
        .iomuxc_compat = "fsl,imx6q-iomuxc",
        .gpc_compat = "fsl,imx6q-gpc",
+       .pl310_compat = "arm,pl310-cache",
        .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
        .mmdc_io_offset = imx6q_mmdc_io_offset,
 };
@@ -151,6 +160,7 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
        .src_compat = "fsl,imx6q-src",
        .iomuxc_compat = "fsl,imx6dl-iomuxc",
        .gpc_compat = "fsl,imx6q-gpc",
+       .pl310_compat = "arm,pl310-cache",
        .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
        .mmdc_io_offset = imx6dl_mmdc_io_offset,
 };
@@ -160,6 +170,7 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
        .src_compat = "fsl,imx6sl-src",
        .iomuxc_compat = "fsl,imx6sl-iomuxc",
        .gpc_compat = "fsl,imx6sl-gpc",
+       .pl310_compat = "arm,pl310-cache",
        .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
        .mmdc_io_offset = imx6sl_mmdc_io_offset,
 };
@@ -169,10 +180,21 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
        .src_compat = "fsl,imx6sx-src",
        .iomuxc_compat = "fsl,imx6sx-iomuxc",
        .gpc_compat = "fsl,imx6sx-gpc",
+       .pl310_compat = "arm,pl310-cache",
        .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
        .mmdc_io_offset = imx6sx_mmdc_io_offset,
 };
 
+static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
+       .mmdc_compat = "fsl,imx6ul-mmdc",
+       .src_compat = "fsl,imx6ul-src",
+       .iomuxc_compat = "fsl,imx6ul-iomuxc",
+       .gpc_compat = "fsl,imx6ul-gpc",
+       .pl310_compat = NULL,
+       .mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
+       .mmdc_io_offset = imx6ul_mmdc_io_offset,
+};
+
 /*
  * This structure is for passing necessary data for low level ocram
  * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
@@ -255,7 +277,7 @@ static void imx6q_enable_wb(bool enable)
        writel_relaxed(val, ccm_base + CCR);
 }
 
-int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
 {
        u32 val = readl_relaxed(ccm_base + CLPCR);
 
@@ -290,7 +312,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
                val |= BM_CLPCR_SBYOS;
                if (cpu_is_imx6sl())
                        val |= BM_CLPCR_BYPASS_PMIC_READY;
-               if (cpu_is_imx6sl() || cpu_is_imx6sx())
+               if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
                        val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
                else
                        val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -330,6 +352,10 @@ static int imx6q_suspend_finish(unsigned long val)
                 * as we need to float DDR IO.
                 */
                local_flush_tlb_all();
+               /* check if need to flush internal L2 cache */
+               if (!((struct imx6_cpu_pm_info *)
+                       suspend_ocram_base)->l2_base.vbase)
+                       flush_cache_all();
                imx6_suspend_in_ocram_fn(suspend_ocram_base);
        }
 
@@ -340,7 +366,7 @@ static int imx6q_pm_enter(suspend_state_t state)
 {
        switch (state) {
        case PM_SUSPEND_STANDBY:
-               imx6q_set_lpm(STOP_POWER_ON);
+               imx6_set_lpm(STOP_POWER_ON);
                imx6q_set_int_mem_clk_lpm(true);
                imx_gpc_pre_suspend(false);
                if (cpu_is_imx6sl())
@@ -350,10 +376,10 @@ static int imx6q_pm_enter(suspend_state_t state)
                if (cpu_is_imx6sl())
                        imx6sl_set_wait_clk(false);
                imx_gpc_post_resume();
-               imx6q_set_lpm(WAIT_CLOCKED);
+               imx6_set_lpm(WAIT_CLOCKED);
                break;
        case PM_SUSPEND_MEM:
-               imx6q_set_lpm(STOP_POWER_OFF);
+               imx6_set_lpm(STOP_POWER_OFF);
                imx6q_set_int_mem_clk_lpm(false);
                imx6q_enable_wb(true);
                /*
@@ -373,7 +399,7 @@ static int imx6q_pm_enter(suspend_state_t state)
                imx6_enable_rbc(false);
                imx6q_enable_wb(false);
                imx6q_set_int_mem_clk_lpm(true);
-               imx6q_set_lpm(WAIT_CLOCKED);
+               imx6_set_lpm(WAIT_CLOCKED);
                break;
        default:
                return -EINVAL;
@@ -392,11 +418,6 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
        .valid = imx6q_pm_valid,
 };
 
-void __init imx6q_pm_set_ccm_base(void __iomem *base)
-{
-       ccm_base = base;
-}
-
 static int __init imx6_pm_get_base(struct imx6_pm_base *base,
                                const char *compat)
 {
@@ -456,7 +477,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
                goto put_node;
        }
 
-       ocram_pool = dev_get_gen_pool(&pdev->dev);
+       ocram_pool = gen_pool_get(&pdev->dev, NULL);
        if (!ocram_pool) {
                pr_warn("%s: ocram pool unavailable!\n", __func__);
                ret = -ENODEV;
@@ -475,6 +496,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
        suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
                MX6Q_SUSPEND_OCRAM_SIZE, false);
 
+       memset(suspend_ocram_base, 0, sizeof(*pm_info));
        pm_info = suspend_ocram_base;
        pm_info->pbase = ocram_pbase;
        pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
@@ -482,8 +504,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
 
        /*
         * ccm physical address is not used by asm code currently,
-        * so get ccm virtual address directly, as we already have
-        * it from ccm driver.
+        * so get ccm virtual address directly.
         */
        pm_info->ccm_base.vbase = ccm_base;
 
@@ -511,11 +532,13 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
                goto gpc_map_failed;
        }
 
-       ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
-       if (ret) {
-               pr_warn("%s: failed to get pl310-cache base %d!\n",
-                       __func__, ret);
-               goto pl310_cache_map_failed;
+       if (socdata->pl310_compat) {
+               ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
+               if (ret) {
+                       pr_warn("%s: failed to get pl310-cache base %d!\n",
+                               __func__, ret);
+                       goto pl310_cache_map_failed;
+               }
        }
 
        pm_info->ddr_type = imx_mmdc_get_ddr_type();
@@ -568,7 +591,7 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
 
        /*
         * This is for SW workaround step #1 of ERR007265, see comments
-        * in imx6q_set_lpm for details of this errata.
+        * in imx6_set_lpm for details of this errata.
         * Force IOMUXC irq pending, so that the interrupt to GPC can be
         * used to deassert dsm_request signal when the signal gets
         * asserted unexpectedly.
@@ -579,6 +602,24 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
                                   IMX6Q_GPR1_GINT);
 }
 
+void __init imx6_pm_ccm_init(const char *ccm_compat)
+{
+       struct device_node *np;
+       u32 val;
+
+       np = of_find_compatible_node(NULL, NULL, ccm_compat);
+       ccm_base = of_iomap(np, 0);
+       BUG_ON(!ccm_base);
+
+       /*
+        * Initialize CCM_CLPCR_LPM into RUN mode to avoid ARM core
+        * clock being shut down unexpectedly by WAIT mode.
+        */
+       val = readl_relaxed(ccm_base + CLPCR);
+       val &= ~BM_CLPCR_LPM;
+       writel_relaxed(val, ccm_base + CLPCR);
+}
+
 void __init imx6q_pm_init(void)
 {
        imx6_pm_common_init(&imx6q_pm_data);
@@ -598,3 +639,8 @@ void __init imx6sx_pm_init(void)
 {
        imx6_pm_common_init(&imx6sx_pm_data);
 }
+
+void __init imx6ul_pm_init(void)
+{
+       imx6_pm_common_init(&imx6ul_pm_data);
+}