]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00220370 [MX6]Fix BUS freq suspend/resume fail in low bus mode
authorAnson Huang <b20788@freescale.com>
Sat, 18 Aug 2012 17:12:59 +0000 (01:12 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:16 +0000 (08:35 +0200)
1. BUS freq's set low bus setpoint using delat work, which
didn't have mutex lock, so in some scenarios, set high bus
freq function can be called at the same time, we need to move
mutex lock into these two routine;

2. Using pm notify to make sure bus freq set to high setpoint
before supend and restore after resume.

3. Clear build warning.

Signed-off-by: Anson Huang <b20788@freescale.com>
arch/arm/mach-mx6/board-mx6q_sabresd.c
arch/arm/mach-mx6/bus_freq.c
arch/arm/mach-mx6/clock.c
arch/arm/plat-mxc/cpufreq.c
arch/arm/plat-mxc/dvfs_core.c

index b6b3be93196db9a6547d327395fb630b3bce2e34..1da30f10fe935059adc94effdfdc2bad3dd06e2a 100644 (file)
@@ -1505,11 +1505,10 @@ static struct gpio_led imx6q_gpio_leds[] = {
 /* For the latest B4 board, this GPIO_1 is connected to POR_B,
 which will reset the whole board if this pin's level is changed,
 so, for the latest board, we have to avoid using this pin as
-GPIO. */
-#if 0
+GPIO.
        GPIO_LED(SABRESD_CHARGE_DONE, "chg_done_led", 0, 1,
                        "charger-full"),
-#endif
+*/
 };
 
 static struct gpio_led_platform_data imx6q_gpio_leds_data = {
index b1f9d80bd6d16f4f91af781e47669aa16531683b..b85c8ec8fd7c8ac6cfd666b38d494f16126c7b07 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
 #include "crm_regs.h"
+#include <linux/suspend.h>
 
 #define LPAPM_CLK              24000000
 #define DDR_MED_CLK            400000000
@@ -111,11 +112,16 @@ static struct delayed_work low_bus_freq_handler;
 
 static void reduce_bus_freq_handler(struct work_struct *work)
 {
-       if (low_bus_freq_mode || !low_freq_bus_used())
+       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)
+       if (audio_bus_freq_mode && lp_audio_freq) {
+               mutex_unlock(&bus_freq_mutex);
                return;
+       }
 
        if (!cpu_is_mx6sl()) {
                clk_enable(pll3);
@@ -181,6 +187,7 @@ static void reduce_bus_freq_handler(struct work_struct *work)
        }
 
        high_bus_freq_mode = 0;
+       mutex_unlock(&bus_freq_mutex);
 }
 
 /* Set the DDR, AHB to 24MHz.
@@ -207,29 +214,42 @@ int set_low_bus_freq(void)
  */
 int set_high_bus_freq(int high_bus_freq)
 {
-       if (busfreq_suspended)
+       if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
+               cancel_delayed_work_sync(&low_bus_freq_handler);
+       mutex_lock(&bus_freq_mutex);
+       if (busfreq_suspended) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
+       }
 
-       if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
+       if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
+       }
 
-       if (high_bus_freq_mode && high_bus_freq)
+       if (high_bus_freq_mode && high_bus_freq) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
+       }
 
-       if (med_bus_freq_mode && !high_bus_freq)
+       if (med_bus_freq_mode && !high_bus_freq) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
+       }
 
        if (cpu_is_mx6dl() && high_bus_freq)
                high_bus_freq = 0;
 
-       if (cpu_is_mx6dl() && med_bus_freq_mode)
+       if (cpu_is_mx6dl() && med_bus_freq_mode) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
-
+       }
        if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
            (med_bus_freq_mode && !high_bus_freq && lp_med_freq &&
-            !lp_high_freq))
+            !lp_high_freq)) {
+               mutex_unlock(&bus_freq_mutex);
                return 0;
-
+       }
        if (cpu_is_mx6sl()) {
                u32 reg;
                unsigned long flags;
@@ -291,6 +311,7 @@ int set_high_bus_freq(int high_bus_freq)
        if (cpu_is_mx6sl())
                arm_mem_clked_in_wait = false;
 
+       mutex_unlock(&bus_freq_mutex);
        return 0;
 }
 
@@ -339,15 +360,21 @@ void bus_freq_update(struct clk *clk, bool flag)
                        }
                } else {
                        if ((clk->flags & AHB_MED_SET_POINT)
-                               && !med_bus_freq_mode)
+                               && !med_bus_freq_mode) {
                                /* Set to Medium setpoint */
+                               mutex_unlock(&bus_freq_mutex);
                                set_high_bus_freq(0);
+                               return;
+                       }
                        else if ((clk->flags & AHB_HIGH_SET_POINT)
-                               && !high_bus_freq_mode)
+                               && !high_bus_freq_mode) {
                                /* Currently at low or medium set point,
                                * need to set to high setpoint
                                */
+                               mutex_unlock(&bus_freq_mutex);
                                set_high_bus_freq(1);
+                               return;
+                       }
                        }
                }
        } else {
@@ -363,12 +390,16 @@ void bus_freq_update(struct clk *clk, bool flag)
                        && (clk_get_usecount(clk) == 0)) {
                        if (low_freq_bus_used() && !low_bus_freq_mode)
                                set_low_bus_freq();
-                       else
+                       else {
                                /* Set to either high or medium setpoint. */
+                               mutex_unlock(&bus_freq_mutex);
                                set_high_bus_freq(0);
+                               return;
+                       }
                }
        }
        mutex_unlock(&bus_freq_mutex);
+       return;
 }
 void setup_pll(void)
 {
@@ -404,16 +435,28 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
 
 static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
 {
-       set_high_bus_freq(1);
-       busfreq_suspended = 1;
        return 0;
 }
 
+static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event,
+       void *dummy)
+{
+       if (event == PM_SUSPEND_PREPARE) {
+               set_high_bus_freq(1);
+               busfreq_suspended = 1;
+       } else if (event == PM_POST_SUSPEND) {
+               busfreq_suspended = 0;
+       }
+
+       return NOTIFY_OK;
+}
 static int busfreq_resume(struct platform_device *pdev)
 {
-       busfreq_suspended = 0;
        return  0;
 }
+static struct notifier_block imx_bus_freq_pm_notifier = {
+       .notifier_call = bus_freq_pm_notify,
+};
 
 static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
                        bus_freq_scaling_enable_store);
@@ -570,6 +613,7 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
        }
 
        INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
+       register_pm_notifier(&imx_bus_freq_pm_notifier);
 
        if (!cpu_is_mx6sl())
                init_mmdc_settings();
index d9af9f6909c1cd4fc5d19d70acc23f2c7533b8f6..08e80dc88a2cd1ef5baea78e92c4344e345d80f5 100644 (file)
@@ -1280,11 +1280,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
                                else
                                        pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk);
                        }
-                       if (cpu_op_tbl[i].cpu_podf) {
-                               __raw_writel(cpu_op_tbl[i].cpu_podf, MXC_CCM_CACRR);
-                               while (__raw_readl(MXC_CCM_CDHIPR))
-                                                       ;
-                       }
                        pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate);
                }
                /* Make sure pll1_sw_clk is from pll1_sys_main_clk */
@@ -2005,7 +2000,7 @@ static struct clk vdoa_clk[] = {
        },
 };
 
-static unsigned long mx6_timer_rate()
+static unsigned long mx6_timer_rate(void)
 {
        u32 parent_rate = clk_get_rate(&osc_clk);
 
index 52112ef599390d46720ac14aee476e030900e227..ee041507038ead93746a48a5f1338cfd642c44a5 100755 (executable)
@@ -96,9 +96,11 @@ int set_cpu_freq(int freq)
        /*Set the voltage for the GP domain. */
        if (freq > org_cpu_rate) {
                mutex_lock(&bus_freq_mutex);
-               if (low_bus_freq_mode || audio_bus_freq_mode)
+               if (low_bus_freq_mode || audio_bus_freq_mode) {
+                       mutex_unlock(&bus_freq_mutex);
                        set_high_bus_freq(0);
-               mutex_unlock(&bus_freq_mutex);
+               } else
+                       mutex_unlock(&bus_freq_mutex);
                if (freq == cpu_op_tbl[0].cpu_rate && !IS_ERR(soc_regulator) && !IS_ERR(pu_regulator)) {
                        ret = regulator_set_voltage(soc_regulator, soc_volt,
                                                        soc_volt);
index 9018b49511cc0374abf6c19d1ed95ee4eac35823..a4a15482c71fe717acc9e214c094a4538dbb039e 100755 (executable)
@@ -647,22 +647,22 @@ static void dvfs_core_work_handler(struct work_struct *work)
        mutex_lock(&bus_freq_mutex);
        if ((curr_op == cpu_op_nr - 1) && (!low_bus_freq_mode)
            && (low_freq_bus_ready) && !bus_incr) {
-               mutex_unlock(&bus_freq_mutex);
                if (!minf)
                        set_cpu_freq(curr_op);
                /* If dvfs_core_op is greater than cpu_op_nr, it implies
                 * we support LPAPM mode for this platform.
                 */
                if (dvfs_core_op > cpu_op_nr) {
-                       mutex_lock(&bus_freq_mutex);
                        set_low_bus_freq();
-                       mutex_unlock(&bus_freq_mutex);
                        dvfs_load_config(cpu_op_nr + 1);
                }
+               mutex_unlock(&bus_freq_mutex);
        } else {
-               if (!high_bus_freq_mode)
+               if (!high_bus_freq_mode) {
+                       mutex_unlock(&bus_freq_mutex);
                        set_high_bus_freq(1);
-               mutex_unlock(&bus_freq_mutex);
+               } else
+                       mutex_unlock(&bus_freq_mutex);
                if (!bus_incr)
                        ret = set_cpu_freq(curr_op);
                bus_incr = 0;
@@ -735,9 +735,11 @@ void stop_dvfs(void)
 
                curr_op = 0;
                mutex_lock(&bus_freq_mutex);
-               if (!high_bus_freq_mode)
+               if (!high_bus_freq_mode) {
+                       mutex_unlock(&bus_freq_mutex);
                        set_high_bus_freq(1);
-               mutex_unlock(&bus_freq_mutex);
+               } else
+                       mutex_unlock(&bus_freq_mutex);
 
                curr_cpu = clk_get_rate(cpu_clk);
                if (curr_cpu != cpu_op_tbl[curr_op].cpu_rate) {