diff options
author | Anson Huang <Anson.Huang@nxp.com> | 2017-09-18 12:41:40 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 95c518121580ba316308b2fc1f0a1058ab539d40 (patch) | |
tree | 926a1fde42c48aea1f311ddfd5db93b5038eac84 /drivers/cpufreq | |
parent | d8f214df87f327989fc1416338c672d70040d353 (diff) |
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 <Anson.Huang@nxp.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/imx8-cpufreq.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/cpufreq/imx8-cpufreq.c b/drivers/cpufreq/imx8-cpufreq.c index 10b664cdbbe4..e64b2b01d7ee 100644 --- a/drivers/cpufreq/imx8-cpufreq.c +++ b/drivers/cpufreq/imx8-cpufreq.c @@ -17,10 +17,13 @@ #include <linux/pm_opp.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/syscalls.h> #include <soc/imx/fsl_sip.h> #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; @@ -173,6 +206,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) { |