diff options
-rw-r--r-- | arch/arm/mach-mx5/bus_freq.c | 48 | ||||
-rw-r--r-- | arch/arm/mach-mx5/clock_mx50.c | 4 |
2 files changed, 49 insertions, 3 deletions
diff --git a/arch/arm/mach-mx5/bus_freq.c b/arch/arm/mach-mx5/bus_freq.c index 08f5f5cab62b..a2ef4796949e 100644 --- a/arch/arm/mach-mx5/bus_freq.c +++ b/arch/arm/mach-mx5/bus_freq.c @@ -61,6 +61,7 @@ static unsigned long lp_med_rate; static unsigned long ddr_normal_rate; static unsigned long ddr_med_rate; static unsigned long ddr_low_rate; +static int cur_ddr_rate; static struct clk *ddr_clk; static struct clk *pll1_sw_clk; @@ -79,6 +80,8 @@ static struct clk *periph_apm_clk; static struct clk *lp_apm; static struct clk *gpc_dvfs_clk; static struct clk *emi_garb_clk; +static struct clk *epdc_clk; + static void __iomem *pll1_base; static void __iomem *pll4_base; @@ -136,6 +139,9 @@ struct dvfs_wp dvfs_core_setpoint[] = { static DEFINE_SPINLOCK(voltage_lock); struct mutex bus_freq_mutex; +struct timeval start_time; +struct timeval end_time; + static void voltage_work_handler(struct work_struct *work) { if (lp_regulator != NULL) { @@ -306,6 +312,7 @@ void enter_lpapm_mode_mx50() /* Set the divider to ARM_PODF to 1. */ __raw_writel(0x0, MXC_CCM_CACRR); } + udelay(100); } @@ -434,6 +441,12 @@ int set_high_bus_freq(int high_bus_freq) if (!high_bus_freq_mode && high_bus_freq) { if (cpu_is_mx50()) { if (med_bus_freq_mode) { + /* Increase SYS_CLK */ + reg = __raw_readl(MXC_CCM_CLK_SYS); + reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK; + reg |= 4 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET; + __raw_writel(reg, MXC_CCM_CLK_SYS); + /* Set the dividers to the default dividers */ reg = __raw_readl(MXC_CCM_CBCDR); reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK @@ -477,6 +490,11 @@ int set_high_bus_freq(int high_bus_freq) while (__raw_readl(MXC_CCM_CDHIPR) & 0xF) udelay(10); + /* Reduce SYS_CLK */ + reg = __raw_readl(MXC_CCM_CLK_SYS); + reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK; + reg |= 8 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET; + __raw_writel(reg, MXC_CCM_CLK_SYS); } else { clk_set_rate(ddr_hf_clk, clk_round_rate(ddr_hf_clk, @@ -489,6 +507,14 @@ int set_high_bus_freq(int high_bus_freq) low_bus_freq_mode = 0; med_bus_freq_mode = 1; } + if (cpu_is_mx50()) { + if (med_bus_freq_mode && + (cur_ddr_rate != ddr_med_rate)) + set_ddr_freq(ddr_med_rate); + if (high_bus_freq_mode && + (cur_ddr_rate != ddr_normal_rate)) + set_ddr_freq(ddr_normal_rate); + } } start_sdram_autogating(); mutex_unlock(&bus_freq_mutex); @@ -577,6 +603,7 @@ void exit_lpapm_mode_mx50(int high_bus_freq) high_bus_freq_mode = 0; low_bus_freq_mode = 0; med_bus_freq_mode = 1; + set_ddr_freq(ddr_med_rate); } else { /* Set the dividers to the default dividers */ reg = __raw_readl(MXC_CCM_CBCDR); @@ -600,8 +627,8 @@ void exit_lpapm_mode_mx50(int high_bus_freq) high_bus_freq_mode = 1; low_bus_freq_mode = 0; med_bus_freq_mode = 0; + set_ddr_freq(ddr_normal_rate); } - set_ddr_freq(ddr_normal_rate); spin_unlock_irqrestore(&ddr_freq_lock, flags); @@ -665,11 +692,21 @@ void exit_lpapm_mode_mx51() clk_round_rate(ddr_hf_clk, ddr_normal_rate)); } +int can_change_ddr_freq() +{ + if (clk_get_usecount(epdc_clk) == 0) + return 1; + return 0; +} + void set_ddr_freq(int ddr_rate) { u32 reg; unsigned long flags; + if (!can_change_ddr_freq()) + return; + spin_lock_irqsave(&ddr_freq_lock, flags); local_flush_tlb_all(); flush_cache_all(); @@ -688,6 +725,7 @@ void set_ddr_freq(int ddr_rate) __raw_writel(reg, qosc_base + HW_QOS_DISABLE_CLR); spin_unlock_irqrestore(&ddr_freq_lock, flags); + cur_ddr_rate = ddr_rate; udelay(100); } @@ -943,6 +981,7 @@ static int __devinit busfreq_probe(struct platform_device *pdev) SZ_8K, MT_HIGH_VECTORS); memcpy(ddr_freq_change_iram_base, mx50_ddr_freq_change, SZ_8K); change_ddr_freq = (void *)ddr_freq_change_iram_base; + cur_ddr_rate = ddr_normal_rate; lp_regulator = regulator_get(NULL, "SW2"); if (IS_ERR(lp_regulator)) { @@ -961,6 +1000,13 @@ static int __devinit busfreq_probe(struct platform_device *pdev) INIT_WORK(&voltage_change_handler, voltage_work_handler); init_completion(&voltage_change_cmpl); + + epdc_clk = clk_get(NULL, "epdc_axi"); + if (IS_ERR(epdc_clk)) { + printk(KERN_DEBUG "%s: failed to get epdc_axi_clk\n", + __func__); + return PTR_ERR(epdc_clk); + } } cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); low_bus_freq_mode = 0; diff --git a/arch/arm/mach-mx5/clock_mx50.c b/arch/arm/mach-mx5/clock_mx50.c index a66230146f7b..af9e4e58d7e9 100644 --- a/arch/arm/mach-mx5/clock_mx50.c +++ b/arch/arm/mach-mx5/clock_mx50.c @@ -3198,8 +3198,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "display_axi", display_axi_clk), _REGISTER_CLOCK(NULL, "elcdif_axi", elcdif_axi_clk), _REGISTER_CLOCK(NULL, "pxp_axi", pxp_axi_clk), - _REGISTER_CLOCK("mxc_epdc_fb", "epdc_axi", epdc_axi_clk), - _REGISTER_CLOCK("mxc_epdc_fb", "epdc_pix", epdc_pix_clk), + _REGISTER_CLOCK(NULL, "epdc_axi", epdc_axi_clk), + _REGISTER_CLOCK(NULL, "epdc_pix", epdc_pix_clk), }; static struct mxc_clk mxc_clks[ARRAY_SIZE(lookups)]; |