rk29: clock: add display power domain clock support

This commit is contained in:
陈恒明
2011-03-22 16:58:32 +08:00
parent ff842e08da
commit 60488c1a79
2 changed files with 118 additions and 8 deletions

View File

@@ -37,6 +37,7 @@
/* bit 0 is free */
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
#define IS_PD (1 << 2) /* Power Domain */
#define cru_readl(offset) readl(RK29_CRU_BASE + offset)
#define cru_writel(v, offset) writel(v, RK29_CRU_BASE + offset)
@@ -201,7 +202,7 @@ static int gate_mode(struct clk *clk, int on)
v = cru_readl(reg);
if (on)
v &= ~(1 << idx); // clear bit
v &= ~(1 << idx); // clear bit
else
v |= (1 << idx); // set bit
@@ -1697,6 +1698,101 @@ GATE_CLK(hclk_mmc0, hclk_periph, HCLK_MMC0);
GATE_CLK(hclk_mmc1, hclk_periph, HCLK_MMC1);
GATE_CLK(hclk_emmc, hclk_periph, HCLK_EMMC);
static int pd_vcodec_mode(struct clk *clk, int on)
{
if (on) {
u32 gate, gate2;
gate = cru_clkgate3_con_mirror;
gate |= (1 << CLK_GATE_ACLK_DDR_VEPU % 32);
gate &= ~((1 << CLK_GATE_ACLK_VEPU % 32)
| (1 << CLK_GATE_HCLK_VEPU % 32)
| (1 << CLK_GATE_HCLK_CPU_VCODEC % 32));
cru_writel(gate, CRU_CLKGATE3_CON);
pmu_set_power_domain(PD_VCODEC, true);
udelay(10);
cru_writel(cru_clkgate3_con_mirror, CRU_CLKGATE3_CON);
} else {
pmu_set_power_domain(PD_VCODEC, false);
}
return 0;
}
static struct clk pd_vcodec = {
.name = "pd_vcodec",
.flags = IS_PD,
.mode = pd_vcodec_mode,
};
static int pd_display_mode(struct clk *clk, int on)
{
if (on) {
u32 gate, gate2;
gate = cru_clkgate3_con_mirror;
gate |= (1 << CLK_GATE_ACLK_DDR_LCDC % 32);
gate &= ~((1 << CLK_GATE_HCLK_CPU_DISPLAY % 32)
| (1 << CLK_GATE_HCLK_DISP_MATRIX % 32)
| (1 << CLK_GATE_ACLK_DISP_MATRIX % 32)
| (1 << CLK_GATE_DCLK_EBOOK % 32)
| (1 << CLK_GATE_HCLK_EBOOK % 32)
| (1 << CLK_GATE_HCLK_IPP % 32)
| (1 << CLK_GATE_ACLK_IPP % 32)
| (1 << CLK_GATE_DCLK_LCDC % 32)
| (1 << CLK_GATE_HCLK_LCDC % 32)
| (1 << CLK_GATE_ACLK_LCDC % 32));
cru_writel(gate, CRU_CLKGATE3_CON);
gate2 = cru_readl(CRU_CLKGATE2_CON);
gate = gate2;
gate &= ~((1 << CLK_GATE_VIP_OUT % 32)
| (1 << CLK_GATE_VIP_SLAVE % 32)
| (1 << CLK_GATE_VIP_MATRIX % 32)
| (1 << CLK_GATE_VIP_BUS % 32));
cru_writel(gate, CRU_CLKGATE2_CON);
pmu_set_power_domain(PD_DISPLAY, true);
udelay(10);
cru_writel(gate2, CRU_CLKGATE2_CON);
cru_writel(cru_clkgate3_con_mirror, CRU_CLKGATE3_CON);
} else {
pmu_set_power_domain(PD_DISPLAY, false);
}
return 0;
}
static struct clk pd_display = {
.name = "pd_display",
.flags = IS_PD,
.mode = pd_display_mode,
};
static int pd_gpu_mode(struct clk *clk, int on)
{
if (on) {
pmu_set_power_domain(PD_GPU, true);
} else {
pmu_set_power_domain(PD_GPU, false);
}
return 0;
}
static struct clk pd_gpu = {
.name = "pd_gpu",
.flags = IS_PD,
.mode = pd_gpu_mode,
};
#define CLK(dev, con, ck) \
{ \
.dev_id = dev, \
@@ -1874,6 +1970,10 @@ static struct clk_lookup clks[] = {
CLK1(hclk_gpu),
CLK1(hclk_cpu_vcodec),
CLK1(hclk_cpu_display),
CLK(NULL, "pd_vcodec", &pd_vcodec),
CLK(NULL, "pd_display", &pd_display),
CLK(NULL, "pd_gpu", &pd_gpu),
};
static LIST_HEAD(clocks);
@@ -2283,7 +2383,7 @@ static int __init clk_disable_unused(void)
struct clk *ck;
list_for_each_entry(ck, &clocks, node) {
if (ck->usecount > 0 || ck->mode == NULL)
if (ck->usecount > 0 || ck->mode == NULL || (ck->flags & IS_PD))
continue;
LOCK();
@@ -2358,7 +2458,7 @@ static void dump_clock(struct seq_file *s, struct clk *clk, int deep)
v = cru_clkgate3_con_mirror & (1 << idx);
else
v = cru_readl(reg) & (1 << idx);
seq_printf(s, "%s ", v ? "off" : "on ");
}

View File

@@ -195,6 +195,7 @@ struct rk29fb_inf {
struct clk *aclk_ddr_lcdc; //DDR LCDC AXI clock disable.
struct clk *aclk_disp_matrix; //DISPLAY matrix AXI clock disable.
struct clk *hclk_cpu_display; //CPU DISPLAY AHB bus clock disable.
struct clk *pd_display; // display power domain
unsigned long dclk_rate;
/* lcdc reg base address and backup reg */
@@ -455,7 +456,12 @@ int init_lcdc(struct fb_info *info)
inf->aclk_ddr_lcdc = clk_get(NULL, "aclk_ddr_lcdc");
inf->aclk_disp_matrix = clk_get(NULL, "aclk_disp_matrix");
inf->hclk_cpu_display = clk_get(NULL, "hclk_cpu_display");
if ((IS_ERR(inf->clk)) || (IS_ERR(inf->aclk_ddr_lcdc)) || (IS_ERR(inf->aclk_disp_matrix)) ||(IS_ERR(inf->hclk_cpu_display)))
inf->pd_display = clk_get(NULL, "pd_display");
if ((IS_ERR(inf->clk)) ||
(IS_ERR(inf->aclk_ddr_lcdc)) ||
(IS_ERR(inf->aclk_disp_matrix)) ||
(IS_ERR(inf->hclk_cpu_display)) ||
(IS_ERR(inf->pd_display)))
{
printk(KERN_ERR "failed to get lcdc_hclk source\n");
return PTR_ERR(inf->clk);
@@ -463,7 +469,8 @@ int init_lcdc(struct fb_info *info)
clk_enable(inf->aclk_disp_matrix);
clk_enable(inf->hclk_cpu_display);
clk_enable(inf->clk);
pmu_set_power_domain(PD_DISPLAY, 1);
clk_enable(inf->pd_display);
//pmu_set_power_domain(PD_DISPLAY, 1);
clk_enable(inf->aclk_ddr_lcdc);
// set AHB access rule and disable all windows
@@ -2175,7 +2182,8 @@ static int rk29fb_suspend(struct platform_device *pdev, pm_message_t mesg)
if(inf->clk){
clk_disable(inf->aclk);
}
pmu_set_power_domain(PD_DISPLAY, 0);
clk_disable(inf->pd_display);
//pmu_set_power_domain(PD_DISPLAY, 0);
inf->in_suspend = 1;
}
return 0;
@@ -2200,7 +2208,8 @@ static int rk29fb_resume(struct platform_device *pdev)
clk_enable(inf->aclk_disp_matrix);
clk_enable(inf->hclk_cpu_display);
clk_enable(inf->clk);
pmu_set_power_domain(PD_DISPLAY, 1);
clk_enable(inf->pd_display);
//pmu_set_power_domain(PD_DISPLAY, 1);
clk_enable(inf->aclk_ddr_lcdc);
if (inf->dclk){
@@ -2662,7 +2671,8 @@ static void rk29fb_shutdown(struct platform_device *pdev)
if(inf->clk){
clk_disable(inf->aclk);
}
pmu_set_power_domain(PD_DISPLAY, 0);
clk_disable(inf->pd_display);
//pmu_set_power_domain(PD_DISPLAY, 0);
inf->in_suspend = 1;
}