From 13f2a095023585ce46a55c375f7fec472899893b Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 18 Sep 2017 12:41:40 +0800 Subject: [PATCH] MLK-16477 cpufreq: imx8: switch cpufreq governor to schedutil for multi-cluster For multi-cluster platforms like i.MX8QM, the best cpufreq governor is schedutil, as common cpufreq framework decides default cpufreq governor in static compile, so this patch adds dynamic switch of cpufreq governor according to cluster number, changing it via sysfs interface, although it is ugly, but it realizes dynamic cpufreq governor select for users. Signed-off-by: Anson Huang --- drivers/cpufreq/imx8-cpufreq.c | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/cpufreq/imx8-cpufreq.c b/drivers/cpufreq/imx8-cpufreq.c index 10e77d05f7bf..5cefb4500303 100644 --- a/drivers/cpufreq/imx8-cpufreq.c +++ b/drivers/cpufreq/imx8-cpufreq.c @@ -17,10 +17,13 @@ #include #include #include +#include #include #define MAX_CLUSTER_NUM 2 +static struct delayed_work cpufreq_governor_daemon; + static DEFINE_SPINLOCK(cpufreq_psci_lock); struct imx8_cpufreq { @@ -33,6 +36,36 @@ static unsigned int transition_latency[MAX_CLUSTER_NUM]; struct device *cpu_dev; static struct thermal_cooling_device *cdev[2]; +static void cpufreq_governor_daemon_handler(struct work_struct *work) +{ + int fd, i; + unsigned char cluster_governor[MAX_CLUSTER_NUM][54] = { + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", + "", + }; + + /* generate second cluster's cpufreq governor path */ + sprintf(cluster_governor[MAX_CLUSTER_NUM - 1], + "%s%d%s", "/sys/devices/system/cpu/cpu", num_online_cpus() - 1, + "/cpufreq/scaling_governor"); + + for (i = 0; i < MAX_CLUSTER_NUM; i++) { + fd = sys_open((const char __user __force *)cluster_governor[i], + O_RDWR, 0700); + if (fd >= 0) { + sys_write(fd, "schedutil", strlen("schedutil")); + sys_close(fd); + pr_info("switch cluster %d cpu-freq governor to schedutil\n", + i); + } else { + /* re-schedule if sys write is NOT ready */ + schedule_delayed_work(&cpufreq_governor_daemon, + msecs_to_jiffies(3000)); + break; + } + } +} + static int imx8_set_target(struct cpufreq_policy *policy, unsigned int index) { struct arm_smccc_res res; @@ -172,6 +205,11 @@ static int imx8_cpufreq_probe(struct platform_device *pdev) for (i = 1; i < num_online_cpus(); i++) { if (topology_physical_package_id(i) == topology_physical_package_id(0)) continue; + + INIT_DELAYED_WORK(&cpufreq_governor_daemon, + cpufreq_governor_daemon_handler); + schedule_delayed_work(&cpufreq_governor_daemon, + msecs_to_jiffies(3000)); first_cpu_dev = cpu_dev; cpu_dev = get_cpu_device(i); if (!cpu_dev) {