soc: cpupm: support system idle
authorPark Bumgyu <bumgyu.park@samsung.com>
Mon, 19 Feb 2018 04:50:19 +0000 (13:50 +0900)
committerChungwoo Park <cww.park@samsung.com>
Mon, 21 May 2018 08:30:31 +0000 (17:30 +0900)
Change-Id: Id861005931eff43e61c9cd7b98aed8d00adc61b1
Signed-off-by: Park Bumgyu <bumgyu.park@samsung.com>
drivers/soc/samsung/exynos-cpupm.c
include/soc/samsung/exynos-cpupm.h

index 821316c6c9a384e144a9313dff1781b229b06619..a69d0023f913be38f040badf42b12db4e6bfa00a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/cpuhotplug.h>
 
 #include <soc/samsung/exynos-cpupm.h>
+#include <soc/samsung/exynos-powermode.h>
 #include <soc/samsung/cal-if.h>
 
 /******************************************************************************
@@ -106,6 +107,12 @@ struct power_mode {
 
        /* disable count */
        atomic_t        disable;
+
+       /*
+        * Some power modes can determine whether to enter power mode
+        * depending on system idle state
+        */
+       bool            system_idle;
 };
 
 /* Maximum number of power modes manageable per cpu */
@@ -231,6 +238,11 @@ static int cpus_busy(int target_residency, const struct cpumask *cpus)
        return 0;
 }
 
+static int system_busy(void)
+{
+       return 0;
+}
+
 /*
  * In order to enter the power mode, the following conditions must be met:
  * 1. power mode should not be disabled
@@ -250,6 +262,9 @@ static int can_enter_power_mode(int cpu, struct power_mode *mode)
        if (cpus_busy(mode->target_residency, &mode->siblings))
                return 0;
 
+       if (mode->system_idle && system_busy())
+               return 0;
+
        return 1;
 }
 
@@ -272,6 +287,10 @@ static int try_to_enter_power_mode(int cpu, struct power_mode *mode)
        case POWERMODE_TYPE_CLUSTER:
                cluster_disable(cpu_topology[cpu].cluster_id);
                break;
+       case POWERMODE_TYPE_SYSTEM:
+               if (unlikely(exynos_system_idle_enter()))
+                       return 0;
+               break;
        }
 
        exynos_ss_cpuidle(mode->name, 0, 0, ESS_FLAG_IN);
@@ -280,7 +299,7 @@ static int try_to_enter_power_mode(int cpu, struct power_mode *mode)
        return 1;
 }
 
-static void exit_mode(int cpu, struct power_mode *mode)
+static void exit_mode(int cpu, struct power_mode *mode, int cancel)
 {
        /*
         * Configure settings to exit power mode. This is executed by the
@@ -293,6 +312,9 @@ static void exit_mode(int cpu, struct power_mode *mode)
        case POWERMODE_TYPE_CLUSTER:
                cluster_enable(cpu_topology[cpu].cluster_id);
                break;
+       case POWERMODE_TYPE_SYSTEM:
+               exynos_system_idle_exit(cancel);
+               break;
        }
 }
 
@@ -344,7 +366,7 @@ void exynos_cpu_pm_exit(int cpu, int cancel)
                        break;
 
                if (check_state_powerdown(mode))
-                       exit_mode(cpu, mode);
+                       exit_mode(cpu, mode, cancel);
        }
 
        /* Set cpu state to RUN */
@@ -429,6 +451,9 @@ static int __init cpu_power_mode_init(void)
                of_property_read_u32(dn, "psci-index", &mode->psci_index);
                of_property_read_u32(dn, "type", &mode->type);
 
+               if (of_property_read_bool(dn, "system-idle"))
+                       mode->system_idle = true;
+
                if (!of_property_read_string(dn, "siblings", &buf))
                        cpulist_parse(buf, &mode->siblings);
 
index 12b0a3ca40c1b584310102846b89f72d052f9ae2..765b6404c02717c6555b03dfe462d3e560ae286a 100644 (file)
@@ -14,6 +14,7 @@ extern void exynos_cpu_pm_exit(int cpu, int cancel);
 
 enum {
        POWERMODE_TYPE_CLUSTER = 0,
+       POWERMODE_TYPE_SYSTEM,
 };
 
 extern void disable_mode(int cpu, int type);