#include <linux/cpuhotplug.h>
#include <soc/samsung/exynos-cpupm.h>
+#include <soc/samsung/exynos-powermode.h>
#include <soc/samsung/cal-if.h>
/******************************************************************************
/* 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 */
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
if (cpus_busy(mode->target_residency, &mode->siblings))
return 0;
+ if (mode->system_idle && system_busy())
+ return 0;
+
return 1;
}
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);
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
case POWERMODE_TYPE_CLUSTER:
cluster_enable(cpu_topology[cpu].cluster_id);
break;
+ case POWERMODE_TYPE_SYSTEM:
+ exynos_system_idle_exit(cancel);
+ break;
}
}
break;
if (check_state_powerdown(mode))
- exit_mode(cpu, mode);
+ exit_mode(cpu, mode, cancel);
}
/* Set cpu state to RUN */
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);