]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00270573-1 [MX6SL]Add support for dynamic Power Gating of the display MIX
authorRanjani Vaidyanathan <ra5478@freescale.com>
Fri, 12 Jul 2013 22:24:11 +0000 (17:24 -0500)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:14:16 +0000 (14:14 +0200)
The display MIX can be power gated when EPDC, PXP and LCDIF are all inactive.
This will save around 1.5mW-1.8mW of power in system IDLE mode.

Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
arch/arm/mach-mx6/board-mx6sl_arm2.c
arch/arm/mach-mx6/board-mx6sl_evk.c
arch/arm/mach-mx6/clock_mx6sl.c
arch/arm/mach-mx6/pm.c
arch/arm/plat-mxc/include/mach/epdc.h

index 63fd57960cb8f48dbe336757542426cdd2843548..9d4b3e37799bd0fde09fb85c032fffbf8ab01368 100755 (executable)
@@ -877,6 +877,7 @@ static struct imx_epdc_fb_platform_data epdc_data = {
        .put_pins = epdc_put_pins,
        .enable_pins = epdc_enable_pins,
        .disable_pins = epdc_disable_pins,
+       .pg_display_mix = true,
 };
 
 static int spdc_get_pins(void)
@@ -1104,6 +1105,7 @@ static struct mxc_fb_platform_data fb_data[] = {
         .mode_str = "SEIKO-WVGA",
         .mode = video_modes,
         .num_modes = ARRAY_SIZE(video_modes),
+        .pg_display_mix = true,
         },
 };
 
index 082845ba22a3fea1e7116ae12ad321606f0020ae..ef92719ef79db3dac92a4547ba6376d9873d3896 100644 (file)
@@ -1084,6 +1084,7 @@ static struct imx_epdc_fb_platform_data epdc_data = {
        .put_pins = epdc_put_pins,
        .enable_pins = epdc_enable_pins,
        .disable_pins = epdc_disable_pins,
+       .pg_display_mix = true,
 };
 
 static int spdc_get_pins(void)
@@ -1316,6 +1317,7 @@ static struct mxc_fb_platform_data wvga_fb_data[] = {
         .mode_str = "SEIKO-WVGA",
         .mode = wvga_video_modes,
         .num_modes = ARRAY_SIZE(wvga_video_modes),
+        .pg_display_mix = true,
         },
 };
 
index f375b4ac9dd402dce7ddfcaf90caa577e4f8d220..e95c45484362e062f4418aadc6ece75ae3e4eb37 100755 (executable)
@@ -89,6 +89,11 @@ DEFINE_SPINLOCK(mx6sl_clk_lock);
 #define MXC_TPRER              0x04
 #define V2_TPRER_PRE24M_OFFSET 12
 #define V2_TPRER_PRE24M_MASK   0xF
+#define GPC_CNTR_OFFSET                                0x0
+#define GPC_PGC_DISP_PGCR_OFFSET               0x240
+#define GPC_PGC_DISP_PUPSCR_OFFSET     0x244
+#define GPC_PGC_DISP_PDNSCR_OFFSET     0x248
+#define GPC_PGC_DISP_SR_OFFSET         0x24c
 
 /* We need to check the exp status again after timer expiration,
  * as there might be interrupt coming between the first time exp
@@ -1899,6 +1904,33 @@ static struct clk i2c_clk[] = {
         },
 };
 
+static int _display_mix_enable(struct clk *clk)
+{
+       if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
+               __raw_writel(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+               __raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET);
+               __raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
+       }
+       return 0;
+}
+
+static void _display_mix_disable(struct clk *clk)
+{
+       if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
+               __raw_writel(0x101, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
+               __raw_writel(0x101, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
+
+               __raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
+               __raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
+       }
+}
+
+static struct clk display_mix = {
+        __INIT_CLK_DEBUG(display_mix)
+       .enable = _display_mix_enable,
+       .disable = _display_mix_disable,
+};
+
 static int _clk_ipu1_set_parent(struct clk *clk, struct clk *parent)
 {
        int mux;
@@ -2037,6 +2069,7 @@ static struct clk ipu2_clk = {
        .set_rate = _clk_ipu2_set_rate,
        .get_rate = _clk_ipu2_get_rate,
        .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       .secondary = &display_mix,
 };
 
 static struct clk usdhc_dep_clk = {
@@ -2803,6 +2836,7 @@ static struct clk pxp_axi_clk = {
        .round_rate = _clk_pxp_epdc_axi_round_rate,
        .get_rate = _clk_pxp_axi_get_rate,
        .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       .secondary = &display_mix,
 };
 
 static struct clk epdc_axi_clk = {
@@ -2818,6 +2852,7 @@ static struct clk epdc_axi_clk = {
        .round_rate = _clk_pxp_epdc_axi_round_rate,
        .get_rate = _clk_epdc_axi_get_rate,
        .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       .secondary = &display_mix,
 };
 
 static unsigned long _clk_lcdif_pix_get_rate(struct clk *clk)
@@ -2967,6 +3002,7 @@ static struct clk lcdif_pix_clk = {
        .round_rate = _clk_epdc_lcdif_pix_round_rate,
        .get_rate = _clk_lcdif_pix_get_rate,
        .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       .secondary = &display_mix,
 };
 
 static struct clk epdc_pix_clk = {
@@ -2982,6 +3018,7 @@ static struct clk epdc_pix_clk = {
        .round_rate = _clk_epdc_lcdif_pix_round_rate,
        .get_rate = _clk_epdc_pix_get_rate,
        .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+       .secondary = &display_mix,
 };
 static unsigned long _clk_spdif_round_rate(struct clk *clk,
                                                unsigned long rate)
index d9c04e11bed0a221efc840727972c4f3750bab2b..f2efa00efb479d8be3496b70c97bae481b17cee3 100644 (file)
 #define GPC_ISR3_OFFSET                                0x20
 #define GPC_ISR4_OFFSET                                0x24
 #define GPC_CNTR_OFFSET                                0x0
-#define GPC_PGC_DISP_PGCR_OFFSET       0x240
-#define GPC_PGC_DISP_PUPSCR_OFFSET     0x244
-#define GPC_PGC_DISP_PDNSCR_OFFSET     0x248
-#define GPC_PGC_DISP_SR_OFFSET         0x24c
-#define GPC_PGC_GPU_PGCR_OFFSET                0x260
+#define GPC_PGC_DISP_PGCR_OFFSET               0x240
 #define GPC_PGC_CPU_PDN_OFFSET         0x2a0
 #define GPC_PGC_CPU_PUPSCR_OFFSET      0x2a4
 #define GPC_PGC_CPU_PDNSCR_OFFSET      0x2a8
@@ -174,47 +170,6 @@ static void usb_power_up_handler(void)
 }
 
 
-static void disp_power_down(void)
-{
-       if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
-
-               __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
-               __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
-
-               __raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
-               __raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
-
-               /* Disable EPDC/LCDIF pix clock, and EPDC/LCDIF/PXP axi clock */
-               __raw_writel(ccgr3 &
-                       ~MXC_CCM_CCGRx_CG5_MASK &
-                       ~MXC_CCM_CCGRx_CG4_MASK &
-                       ~MXC_CCM_CCGRx_CG3_MASK &
-                       ~MXC_CCM_CCGRx_CG2_MASK &
-                       ~MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
-
-       }
-}
-
-static void disp_power_up(void)
-{
-       if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) {
-               /*
-                * Need to enable EPDC/LCDIF pix clock, and
-                * EPDC/LCDIF/PXP axi clock before power up.
-                */
-               __raw_writel(ccgr3 |
-                       MXC_CCM_CCGRx_CG5_MASK |
-                       MXC_CCM_CCGRx_CG4_MASK |
-                       MXC_CCM_CCGRx_CG3_MASK |
-                       MXC_CCM_CCGRx_CG2_MASK |
-                       MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
-
-               __raw_writel(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
-               __raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET);
-               __raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
-       }
-}
-
 static void mx6_suspend_store(void)
 {
        /* save some settings before suspend */
@@ -319,14 +274,12 @@ static int mx6_suspend_enter(suspend_state_t state)
 
        switch (state) {
        case PM_SUSPEND_MEM:
-               disp_power_down();
                usb_power_down_handler();
                mxc_cpu_lp_set(ARM_POWER_OFF);
                arm_pg = true;
                break;
        case PM_SUSPEND_STANDBY:
                if (cpu_is_mx6sl()) {
-                       disp_power_down();
                        usb_power_down_handler();
                        mxc_cpu_lp_set(STOP_XTAL_ON);
                        arm_pg = true;
@@ -394,10 +347,8 @@ static int mx6_suspend_enter(suspend_state_t state)
                        restore_gic_dist_state(0, &gds);
                        restore_gic_cpu_state(0, &gcs);
                }
-               if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) {
+               if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl()))
                        usb_power_up_handler();
-                       disp_power_up();
-               }
 
                mx6_suspend_restore();
 
index 36aac88230c8b2eae8f3b4a7b5c2a0ceb328c01c..08fef76148f330836dd4f4346a6dc734049cb956 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  *
  * 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
@@ -36,6 +36,7 @@ struct imx_epdc_fb_platform_data {
     void (*put_pins) (void);
     void (*enable_pins) (void);
     void (*disable_pins) (void);
+    bool pg_display_mix;
 };
 
 struct imx_spdc_panel_init_set {