From 8012800357a3be70acac9d1b4c1008a7bce67def Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Thu, 30 Aug 2012 22:55:14 -0500 Subject: ENGR00222157 MX6x-Fix bug in transitioning from low_bus to audio_bus mode. Ensure that the transtion from low bus freq mode to audio bus freq mode happens instantly. Don't schedule the delayed work in this case else there will be a pause in the audio playback. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/mach-mx6/bus_freq.c | 70 ++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index 151b4ee27eb6..9d18423c85c5 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -115,19 +115,8 @@ static struct clk *pll3_540; static struct delayed_work low_bus_freq_handler; -static void reduce_bus_freq_handler(struct work_struct *work) +void reduce_bus_freq(void) { - mutex_lock(&bus_freq_mutex); - if (low_bus_freq_mode || !low_freq_bus_used()) { - mutex_unlock(&bus_freq_mutex); - return; - } - - if (audio_bus_freq_mode && lp_audio_freq) { - mutex_unlock(&bus_freq_mutex); - return; - } - if (!cpu_is_mx6sl()) { if (cpu_is_mx6dl() && (clk_get_parent(axi_clk) != periph_clk)) @@ -196,6 +185,10 @@ static void reduce_bus_freq_handler(struct work_struct *work) reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR); while (__raw_readl(MXC_CCM_CDHIPR)) ; + /* We have enabled PLL1 in the code below when + * ARM is from PLL1, so disable it here. + */ + clk_disable(pll1); } low_bus_freq_mode = 0; audio_bus_freq_mode = 1; @@ -230,6 +223,35 @@ static void reduce_bus_freq_handler(struct work_struct *work) spin_unlock_irqrestore(&freq_lock, flags); } high_bus_freq_mode = 0; + +} + +static void reduce_bus_freq_handler(struct work_struct *work) +{ + mutex_lock(&bus_freq_mutex); + + if (!low_freq_bus_used()) { + mutex_unlock(&bus_freq_mutex); + return; + } + /* If we are already in audio bus freq mode, + * just return if lp_audio_freq is true. + */ + if (audio_bus_freq_mode && lp_audio_freq) { + mutex_unlock(&bus_freq_mutex); + return; + } + + /* If we dont want to transition from low bus to + * audio bus mode and are already in + *low bus mode, then return. + */ + if (!lp_audio_freq && low_bus_freq_mode) { + mutex_unlock(&bus_freq_mutex); + return; + } + reduce_bus_freq(); + mutex_unlock(&bus_freq_mutex); } @@ -245,10 +267,19 @@ int set_low_bus_freq(void) if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) return 0; - /* Don't lower the frequency immediately. Instead scheduled a delayed - * work and drop the freq if the conditions still remain the same. + /* Check to see if we need to got from + * low bus freq mode to audio bus freq mode. + * If so, the change needs to be done immediately. */ - schedule_delayed_work(&low_bus_freq_handler, usecs_to_jiffies(3000000)); + if (lp_audio_freq && low_bus_freq_mode) + reduce_bus_freq(); + else + /* Don't lower the frequency immediately. Instead + * scheduled a delayed work and drop the freq if + * the conditions still remain the same. + */ + schedule_delayed_work(&low_bus_freq_handler, + usecs_to_jiffies(3000000)); return 0; } @@ -395,13 +426,8 @@ void bus_freq_update(struct clk *clk, bool flag) && (clk_get_usecount(clk) == 0)) { if (!(clk->flags & (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) { - if (low_freq_bus_used()) { - if ((clk->flags & AHB_AUDIO_SET_POINT) & - !audio_bus_freq_mode) - set_low_bus_freq(); - else if (!low_bus_freq_mode) - set_low_bus_freq(); - } + if (low_freq_bus_used()) + set_low_bus_freq(); } else { if ((clk->flags & AHB_MED_SET_POINT) && !med_bus_freq_mode) { -- cgit v1.2.3 From f28276c1190e967ae00f1db53a58a431f15ea368 Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Sat, 1 Sep 2012 02:06:39 -0500 Subject: ENGR00222257 MX6x-Prime TLB entries before DDR enters self-refresh. Need to ensure that no page table walk occurs in DDR when it is in self refresh and its IO pads are floated during suspend. Hence we need to make sure that the translation of all the addresses that the suspend code will access is in the TLB before DDR cannot be accessed anymore. So do a dummy read of IOMUX, MMDC, SRC and ANATOP regsiters. Also need to add a dsb to drain all the write buffers before DDR enters self-refresh. Also ensure that the LDO bypass enable is reset if an interrupt is pending before the system enters suspend. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/mach-mx6/mx6_suspend.S | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S index a9b7e30cd85a..0b9dc57b0091 100644 --- a/arch/arm/mach-mx6/mx6_suspend.S +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -777,6 +777,22 @@ ddr_io_save_done: /**************************************************************** set ddr iomux to low power mode ****************************************************************/ + /* Make sure TLBs are primed. */ + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r0, [r1] + ldr r1, =SRC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r0, [r1] +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + ldr r1, =ANATOP_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r0, [r1] +#endif + + /* Do a DSB to drain the buffers. */ + dsb + ldr r1, =MMDC_P0_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r0, [r1, #MMDC_MAPSR_OFFSET] @@ -817,12 +833,12 @@ save resume pointer into SRC_GPR1 add r1, r1, #PERIPBASE_VIRT str r3, [r1, #SRC_GPR1_OFFSET] #ifdef CONFIG_MX6_INTER_LDO_BYPASS - ldr r1, =0x20c8140 + ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT - ldr r3, [r1] + ldr r3, [r1, #0x140] bic r3, r3, #0x1f orr r3, r3, #0x1e - str r3, [r1] + str r3, [r1, #0x140] #endif /**************************************************************** execute a wfi instruction to let SOC go into stop mode. @@ -838,6 +854,14 @@ execute a wfi instruction to let SOC go into stop mode. if go here, means there is a wakeup irq pending, we should resume system immediately. ****************************************************************/ +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + ldr r1, =ANATOP_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r3, [r1, #0x140] + orr r3, r3, #0x1f + str r3, [r1, #0x140] +#endif + mov r0, r2 /* get suspend_iram_base */ add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */ @@ -873,10 +897,10 @@ are running with MMU off. ****************************************************************/ resume: #ifdef CONFIG_MX6_INTER_LDO_BYPASS - ldr r1, =0x20c8140 - ldr r3, [r1] + ldr r1, =ANATOP_BASE_ADDR + ldr r3, [r1, #0x140] orr r3, r3, #0x1f - str r3, [r1] + str r3, [r1, #0x140] #endif /* Invalidate L1 I-cache first */ mov r1, #0x0 -- cgit v1.2.3 From d81da79b27f8205c915b9ab78972742964e6436a Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Sat, 1 Sep 2012 21:31:02 -0500 Subject: ENGR00222835 MX6x-Fix incorrect enabling/disabling of PLL1 PLL1 was enabled without incrementing the usecount, and was thus not getting disabled under certain conditions. This causes 2 issues: 1. Increases the power. 2. Causes crashes on MX6SL in audio mode as ARM is switched to PLL1 assuming its in bypass when entering WAIT mode. But PLL1 is enabled and not in bypass state. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/mach-mx6/clock.c | 3 --- arch/arm/mach-mx6/clock_mx6sl.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 8b75aee78964..a3dc7e4aeb1e 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -1334,9 +1334,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) spin_unlock_irqrestore(&clk_lock, flags); return -1; } - /* Need PLL1-MAIN to be ON to write to ARM-PODF bit. */ - if (!pll1_enabled) - pll1_sys_main_clk.enable(&pll1_sys_main_clk); cur_arm_podf = div; diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index 6bd818ae7139..08212c3c3ecb 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -1239,9 +1239,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) return -1; } - if (!pll1_enabled) - pll1_sys_main_clk.enable(&pll1_sys_main_clk); - cur_arm_podf = div; __raw_writel(div - 1, MXC_CCM_CACRR); -- cgit v1.2.3 From f3ff4c24af4d5bff0bb275e79c779c22d1263797 Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Sun, 2 Sep 2012 10:32:35 -0500 Subject: ENGR00222834 MX6x-A9 prefetcher should not access DDR before IO is restored Add enough nops to suspend code when exiting due to a pending interrupt. This is required so that we can guarantee that the prefetch unit will not bring DDR out of self-refresh before all of the DDR's IO pads are restored. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/mach-mx6/mx6_suspend.S | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S index 0b9dc57b0091..0533ad1b20ef 100644 --- a/arch/arm/mach-mx6/mx6_suspend.S +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -884,6 +884,40 @@ sl_io_restore: sl_ddr_io_restore ddr_io_restore_done: + /* Add enough nops so that the + * prefetcher will not get instructions + * from DDR before its IO pads + * are restored. + */ + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #(1 << 2) @ Enable the C bit -- cgit v1.2.3 From f96b367fdd4b1db2c01e6aa59a825c5e6873efa4 Mon Sep 17 00:00:00 2001 From: Robby Cai Date: Mon, 3 Sep 2012 13:54:33 +0800 Subject: ENGR00222841: mx6sl: pgc: display power gating causes PxP processing timeout For safety, DO NOT enable display power gating feature for MX6SL EVK. Otherwise will meet PxP processing timeout when run EPDC unit test. The cause is under investigation. Signed-off-by: Robby Cai --- arch/arm/mach-mx6/pm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index dd5db57c984b..711972cca799 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -235,8 +235,14 @@ static void gpu_power_up(void) udelay(10); } +/* + * For safety, DO NOT define ENABLE_DISP_POWER_GATING for MX6SL EVK. + * Otherwise will meet PxP processing timeout When run EPDC unit test. + * The cause is under investigation. + */ static void disp_power_down(void) { +#ifdef ENABLE_DISP_POWER_GATING if (cpu_is_mx6sl()) { __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET); __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET); @@ -244,15 +250,18 @@ static void disp_power_down(void) __raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET); __raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET); } +#endif } static void disp_power_up(void) { +#ifdef ENABLE_DISP_POWER_GATING if (cpu_is_mx6sl()) { __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); } +#endif } static void mx6_suspend_store(void) -- cgit v1.2.3 From d97b871cc396738ff62293df6b4ba78ade44b6d2 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 3 Sep 2012 15:17:01 +0800 Subject: ENGR00222855 MX6 CPUFREQ: support three VDDSOC setpoints On MX6Q/DL , there is only two set point of VDDSOC/VDDPU, one is 1.25V(1GHz), another is 1.175V. And in arch/arm/plat-mxc/cpufreq.c will judge whether the current cpu frequency is the highest set point(1G) or not to set the right VDDSOC/VDDPU. The logic is also match to dynamic ldo bypass function, since the change point is the highest set point too. But there is three set points of VDDSOC/VDDPU in MX6SL , so the logic in cpufreq.c need to change. Now VDDSOC/VDDPU will track with VDDARM fully. Signed-off-by: Robin Gong --- arch/arm/plat-mxc/cpufreq.c | 59 ++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index bdc89f007349..7a06aaec02e7 100755 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -42,7 +42,6 @@ static int cpu_freq_suspend_in; static struct mutex set_cpufreq_lock; #endif -static int soc_regulator_set; static int cpu_freq_khz_min; static int cpu_freq_khz_max; @@ -92,24 +91,21 @@ int set_cpu_freq(int freq) /* Check if the bus freq needs to be increased first */ bus_freq_update(cpu_clk, true); - if (freq == cpu_op_tbl[0].cpu_rate) { - if (!IS_ERR(soc_regulator)) { - ret = regulator_set_voltage(soc_regulator, soc_volt, - soc_volt); - if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE!!!!\n"); - return ret; - } + if (!IS_ERR(soc_regulator)) { + ret = regulator_set_voltage(soc_regulator, soc_volt, + soc_volt); + if (ret < 0) { + printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE!!!!\n"); + return ret; } - if (!IS_ERR(pu_regulator)) { - ret = regulator_set_voltage(pu_regulator, pu_volt, - pu_volt); - if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n"); - return ret; - } + } + if (!IS_ERR(pu_regulator)) { + ret = regulator_set_voltage(pu_regulator, pu_volt, + pu_volt); + if (ret < 0) { + printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n"); + return ret; } - soc_regulator_set = 1; } ret = regulator_set_voltage(cpu_regulator, gp_volt, gp_volt); @@ -132,24 +128,21 @@ int set_cpu_freq(int freq) printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n"); return ret; } - if (soc_regulator_set) { - if (!IS_ERR(soc_regulator)) { - ret = regulator_set_voltage(soc_regulator, soc_volt, - soc_volt); - if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE BACK!!!!\n"); - return ret; - } + if (!IS_ERR(soc_regulator)) { + ret = regulator_set_voltage(soc_regulator, soc_volt, + soc_volt); + if (ret < 0) { + printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE BACK!!!!\n"); + return ret; } - if (!IS_ERR(pu_regulator)) { - ret = regulator_set_voltage(pu_regulator, pu_volt, - pu_volt); - if (ret < 0) { - printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n"); - return ret; - } + } + if (!IS_ERR(pu_regulator)) { + ret = regulator_set_voltage(pu_regulator, pu_volt, + pu_volt); + if (ret < 0) { + printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n"); + return ret; } - soc_regulator_set = 0; } /* Check if the bus freq can be decreased.*/ bus_freq_update(cpu_clk, false); -- cgit v1.2.3