aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobby Cai <R63905@freescale.com>2013-11-14 05:15:53 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:14 -0400
commit8dfdc91887fc4ff52181875ef44a425cf2e8959e (patch)
tree7f59b85ecd9ba8f36328da30f88238c8474aea0a
parent8c1d1a071947fec0819881cf5ce91b53614ad763 (diff)
ENGR00283186 imx6sl: Add support for power gating of display MIX
The display MIX can be power gated when EPDC, PXP and LCDIF are all inactive. For safety, this feature is only supported when system enters suspend/standby mode, in other words, this patch does not support run-time gating. Signed-off-by: Robby Cai <R63905@freescale.com> Signed-off-by: Robin Gong <b38343@freescale.com>
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi7
-rw-r--r--arch/arm/mach-imx/gpc.c69
2 files changed, 73 insertions, 3 deletions
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index b751542f71c7..605fefbc99d8 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -601,8 +601,11 @@
601 reg = <0x020dc000 0x4000>; 601 reg = <0x020dc000 0x4000>;
602 interrupts = <0 89 0x04>; 602 interrupts = <0 89 0x04>;
603 clocks = <&clks IMX6SL_CLK_GPU2D_PODF>, <&clks IMX6SL_CLK_GPU2D_OVG>, 603 clocks = <&clks IMX6SL_CLK_GPU2D_PODF>, <&clks IMX6SL_CLK_GPU2D_OVG>,
604 <&clks IMX6SL_CLK_IPG>; 604 <&clks IMX6SL_CLK_IPG>, <&clks IMX6SL_CLK_LCDIF_AXI>,
605 clock-names = "gpu2d_podf", "gpu2d_ovg", "ipg"; 605 <&clks IMX6SL_CLK_LCDIF_PIX>, <&clks IMX6SL_CLK_EPDC_AXI>,
606 <&clks IMX6SL_CLK_EPDC_PIX>, <&clks IMX6SL_CLK_PXP_AXI>;
607 clock-names = "gpu2d_podf", "gpu2d_ovg", "ipg", "lcd_axi",
608 "lcd_pix", "epdc_axi", "epdc_pix", "pxp_axi";
606 pu-supply = <&reg_pu>; 609 pu-supply = <&reg_pu>;
607 }; 610 };
608 611
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 2a3646b4d027..97343277d1e8 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -31,6 +31,10 @@
31#define GPC_PGC_GPU_PDN 0x260 31#define GPC_PGC_GPU_PDN 0x260
32#define GPC_PGC_GPU_PUPSCR 0x264 32#define GPC_PGC_GPU_PUPSCR 0x264
33#define GPC_PGC_GPU_PDNSCR 0x268 33#define GPC_PGC_GPU_PDNSCR 0x268
34#define GPC_PGC_DISP_PGCR_OFFSET 0x240
35#define GPC_PGC_DISP_PUPSCR_OFFSET 0x244
36#define GPC_PGC_DISP_PDNSCR_OFFSET 0x248
37#define GPC_PGC_DISP_SR_OFFSET 0x24c
34#define GPC_PGC_GPU_SW_SHIFT 0 38#define GPC_PGC_GPU_SW_SHIFT 0
35#define GPC_PGC_GPU_SW_MASK 0x3f 39#define GPC_PGC_GPU_SW_MASK 0x3f
36#define GPC_PGC_GPU_SW2ISO_SHIFT 8 40#define GPC_PGC_GPU_SW2ISO_SHIFT 8
@@ -51,6 +55,8 @@ static void __iomem *gpc_base;
51static u32 gpc_wake_irqs[IMR_NUM]; 55static u32 gpc_wake_irqs[IMR_NUM];
52static u32 gpc_saved_imrs[IMR_NUM]; 56static u32 gpc_saved_imrs[IMR_NUM];
53static struct clk *gpu3d_clk, *gpu3d_shader_clk, *gpu2d_clk, *gpu2d_axi_clk; 57static struct clk *gpu3d_clk, *gpu3d_shader_clk, *gpu2d_clk, *gpu2d_axi_clk;
58static struct clk *lcd_axi_clk, *lcd_pix_clk, *epdc_axi_clk, *epdc_pix_clk;
59static struct clk *pxp_axi_clk;
54static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk; 60static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk;
55static struct device *gpc_dev; 61static struct device *gpc_dev;
56struct regulator *pu_reg; 62struct regulator *pu_reg;
@@ -65,11 +71,63 @@ static struct regulator_init_data pu_dummy_initdata = {
65}; 71};
66static int pu_dummy_enable; 72static int pu_dummy_enable;
67 73
74static void imx_disp_clk(bool enable)
75{
76 if (enable) {
77 clk_prepare_enable(lcd_axi_clk);
78 clk_prepare_enable(lcd_pix_clk);
79 clk_prepare_enable(epdc_axi_clk);
80 clk_prepare_enable(epdc_pix_clk);
81 clk_prepare_enable(pxp_axi_clk);
82 } else {
83 clk_disable_unprepare(lcd_axi_clk);
84 clk_disable_unprepare(lcd_pix_clk);
85 clk_disable_unprepare(epdc_axi_clk);
86 clk_disable_unprepare(epdc_pix_clk);
87 clk_disable_unprepare(pxp_axi_clk);
88 }
89}
90
91static void imx_gpc_dispmix_on(void)
92{
93 if (cpu_is_imx6sl()) {
94 imx_disp_clk(true);
95
96 writel_relaxed(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
97 writel_relaxed(0x20, gpc_base + GPC_CNTR);
98 while (readl_relaxed(gpc_base + GPC_CNTR) & 0x20)
99 ;
100 writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
101
102 imx_disp_clk(false);
103 }
104}
105
106static void imx_gpc_dispmix_off(void)
107{
108 if (cpu_is_imx6sl()) {
109 imx_disp_clk(true);
110
111 writel_relaxed(0xFFFFFFFF,
112 gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
113 writel_relaxed(0xFFFFFFFF,
114 gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
115 writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
116 writel_relaxed(0x10, gpc_base + GPC_CNTR);
117 while (readl_relaxed(gpc_base + GPC_CNTR) & 0x10)
118 ;
119
120 imx_disp_clk(false);
121 }
122}
123
68void imx_gpc_pre_suspend(bool arm_power_off) 124void imx_gpc_pre_suspend(bool arm_power_off)
69{ 125{
70 void __iomem *reg_imr1 = gpc_base + GPC_IMR1; 126 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
71 int i; 127 int i;
72 128
129 imx_gpc_dispmix_off();
130
73 if (arm_power_off) 131 if (arm_power_off)
74 /* Tell GPC to power off ARM core when suspend */ 132 /* Tell GPC to power off ARM core when suspend */
75 writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); 133 writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
@@ -90,6 +148,8 @@ void imx_gpc_post_resume(void)
90 148
91 for (i = 0; i < IMR_NUM; i++) 149 for (i = 0; i < IMR_NUM; i++)
92 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); 150 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
151
152 imx_gpc_dispmix_on();
93} 153}
94 154
95static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) 155static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -420,8 +480,15 @@ static int imx_gpc_probe(struct platform_device *pdev)
420 gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_podf"); 480 gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_podf");
421 openvg_axi_clk = devm_clk_get(gpc_dev, "gpu2d_ovg"); 481 openvg_axi_clk = devm_clk_get(gpc_dev, "gpu2d_ovg");
422 ipg_clk = devm_clk_get(gpc_dev, "ipg"); 482 ipg_clk = devm_clk_get(gpc_dev, "ipg");
483 lcd_axi_clk = devm_clk_get(gpc_dev, "lcd_axi");
484 lcd_pix_clk = devm_clk_get(gpc_dev, "lcd_pix");
485 epdc_axi_clk = devm_clk_get(gpc_dev, "epdc_axi");
486 epdc_pix_clk = devm_clk_get(gpc_dev, "epdc_pix");
487 pxp_axi_clk = devm_clk_get(gpc_dev, "pxp_axi");
423 if (IS_ERR(gpu2d_clk) || IS_ERR(openvg_axi_clk) 488 if (IS_ERR(gpu2d_clk) || IS_ERR(openvg_axi_clk)
424 || IS_ERR(ipg_clk)) { 489 || IS_ERR(ipg_clk) || IS_ERR(lcd_axi_clk)
490 || IS_ERR(lcd_pix_clk) || IS_ERR(epdc_axi_clk)
491 || IS_ERR(epdc_pix_clk) || IS_ERR(pxp_axi_clk)) {
425 dev_err(gpc_dev, "failed to get clk!\n"); 492 dev_err(gpc_dev, "failed to get clk!\n");
426 return -ENOENT; 493 return -ENOENT;
427 } 494 }