Skip to content

Commit 451faf7

Browse files
Sandor YuNitin Garg
authored andcommitted
MLK-10117-1: gpc: add dispmix power save feature
Add dispmix power save feature to generic power domain. Signed-off-by: Sandor Yu <R01008@freescale.com>
1 parent 5567ef2 commit 451faf7

File tree

1 file changed

+103
-14
lines changed

1 file changed

+103
-14
lines changed

arch/arm/mach-imx/gpc.c

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
#define GPC_PGC_GPU_PUPSCR 0x264
3636
#define GPC_PGC_GPU_PDNSCR 0x268
3737
#define GPC_PGC_CPU_PDN 0x2a0
38+
#define GPC_PGC_DISP_PGCR_OFFSET 0x240
39+
#define GPC_PGC_DISP_PUPSCR_OFFSET 0x244
40+
#define GPC_PGC_DISP_PDNSCR_OFFSET 0x248
41+
#define GPC_PGC_DISP_SR_OFFSET 0x24c
3842
#define GPC_M4_LPSR 0x2c
3943
#define GPC_M4_LPSR_M4_SLEEPING_SHIFT 4
4044
#define GPC_M4_LPSR_M4_SLEEPING_MASK 0x1
@@ -48,7 +52,7 @@
4852
#define GPU_VPU_PUP_REQ BIT(1)
4953
#define GPU_VPU_PDN_REQ BIT(0)
5054

51-
#define GPC_CLK_MAX 6
55+
#define GPC_CLK_MAX 10
5256

5357
struct pu_domain {
5458
struct generic_pm_domain base;
@@ -57,6 +61,12 @@ struct pu_domain {
5761
int num_clks;
5862
};
5963

64+
struct disp_domain {
65+
struct generic_pm_domain base;
66+
struct clk *clk[GPC_CLK_MAX];
67+
int num_clks;
68+
};
69+
6070
static void __iomem *gpc_base;
6171
static u32 gpc_mf_irqs[IMR_NUM];
6272
static u32 gpc_wake_irqs[IMR_NUM];
@@ -374,6 +384,62 @@ static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
374384
return 0;
375385
}
376386

387+
static int imx_pm_dispmix_on(struct generic_pm_domain *genpd)
388+
{
389+
struct disp_domain *disp = container_of(genpd, struct disp_domain, base);
390+
u32 val = readl_relaxed(gpc_base + GPC_CNTR);
391+
int i;
392+
393+
if ((cpu_is_imx6sl() &&
394+
imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
395+
396+
/* Enable reset clocks for all devices in the disp domain */
397+
for (i = 0; i < disp->num_clks; i++)
398+
clk_prepare_enable(disp->clk[i]);
399+
400+
writel_relaxed(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
401+
writel_relaxed(0x20 | val, gpc_base + GPC_CNTR);
402+
while (readl_relaxed(gpc_base + GPC_CNTR) & 0x20)
403+
;
404+
405+
writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
406+
407+
/* Disable reset clocks for all devices in the disp domain */
408+
for (i = 0; i < disp->num_clks; i++)
409+
clk_disable_unprepare(disp->clk[i]);
410+
}
411+
return 0;
412+
}
413+
414+
static int imx_pm_dispmix_off(struct generic_pm_domain *genpd)
415+
{
416+
struct disp_domain *disp = container_of(genpd, struct disp_domain, base);
417+
u32 val = readl_relaxed(gpc_base + GPC_CNTR);
418+
int i;
419+
420+
if ((cpu_is_imx6sl() &&
421+
imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
422+
423+
/* Enable reset clocks for all devices in the disp domain */
424+
for (i = 0; i < disp->num_clks; i++)
425+
clk_prepare_enable(disp->clk[i]);
426+
427+
writel_relaxed(0xFFFFFFFF,
428+
gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET);
429+
writel_relaxed(0xFFFFFFFF,
430+
gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET);
431+
writel_relaxed(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
432+
writel_relaxed(0x10 | val, gpc_base + GPC_CNTR);
433+
while (readl_relaxed(gpc_base + GPC_CNTR) & 0x10)
434+
;
435+
436+
/* Disable reset clocks for all devices in the disp domain */
437+
for (i = 0; i < disp->num_clks; i++)
438+
clk_disable_unprepare(disp->clk[i]);
439+
}
440+
return 0;
441+
}
442+
377443
static struct generic_pm_domain imx6q_arm_domain = {
378444
.name = "ARM",
379445
};
@@ -388,14 +454,18 @@ static struct pu_domain imx6q_pu_domain = {
388454
},
389455
};
390456

391-
static struct generic_pm_domain imx6sl_display_domain = {
392-
.name = "DISPLAY",
457+
static struct disp_domain imx6s_display_domain = {
458+
.base = {
459+
.name = "DISPLAY",
460+
.power_off = imx_pm_dispmix_off,
461+
.power_on = imx_pm_dispmix_on,
462+
},
393463
};
394464

395465
static struct generic_pm_domain *imx_gpc_domains[] = {
396466
&imx6q_arm_domain,
397467
&imx6q_pu_domain.base,
398-
&imx6sl_display_domain,
468+
&imx6s_display_domain.base,
399469
};
400470

401471
static struct genpd_onecell_data imx_gpc_onecell_data = {
@@ -407,35 +477,54 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
407477
{
408478
struct clk *clk;
409479
bool is_off;
410-
int i;
480+
int pu_clks, disp_clks;
481+
int i = 0, k = 0;
411482

412483
imx6q_pu_domain.base.of_node = dev->of_node;
413484
imx6q_pu_domain.reg = pu_reg;
414485

415-
for (i = 0; ; i++) {
486+
imx6s_display_domain.base.of_node = dev->of_node;
487+
488+
if ((cpu_is_imx6sl() &&
489+
imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2)) {
490+
pu_clks = 2 ;
491+
disp_clks = 6;
492+
} else if (cpu_is_imx6sx()) {
493+
pu_clks = 1;
494+
disp_clks = 7;
495+
} else {
496+
pu_clks = GPC_CLK_MAX;
497+
disp_clks = 0;
498+
}
499+
500+
/* Get pu domain clks */
501+
for (i = 0; i < pu_clks ; i++) {
416502
clk = of_clk_get(dev->of_node, i);
417503
if (IS_ERR(clk))
418504
break;
419-
if (i >= GPC_CLK_MAX) {
420-
dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
421-
goto clk_err;
422-
}
423505
imx6q_pu_domain.clk[i] = clk;
424506
}
425507
imx6q_pu_domain.num_clks = i;
426508

509+
/* Get disp domain clks */
510+
for (k = 0, i = pu_clks; i < pu_clks + disp_clks ; i++, k++) {
511+
clk = of_clk_get(dev->of_node, i);
512+
if (IS_ERR(clk))
513+
break;
514+
imx6s_display_domain.clk[k] = clk;
515+
}
516+
imx6s_display_domain.num_clks = k;
517+
427518
is_off = IS_ENABLED(CONFIG_PM_RUNTIME);
428519
if (is_off)
429520
imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
430521

431522
pm_genpd_init(&imx6q_pu_domain.base, NULL, is_off);
523+
pm_genpd_init(&imx6s_display_domain.base, NULL, is_off);
524+
432525
return of_genpd_add_provider(dev->of_node, of_genpd_xlate_onecell,
433526
&imx_gpc_onecell_data);
434527

435-
clk_err:
436-
while (i--)
437-
clk_put(imx6q_pu_domain.clk[i]);
438-
return -EINVAL;
439528
}
440529

441530
#else

0 commit comments

Comments
 (0)