cpufreq: imx6q/thermal: imx: register cooling device depending on OF
authorBastian Stender <bst@pengutronix.de>
Fri, 8 Jun 2018 09:06:39 +0000 (11:06 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 2 Jul 2018 09:26:36 +0000 (11:26 +0200)
The cooling device should be part of the i.MX cpufreq driver, but it
cannot be removed for the sake of DT stability. So turn the cooling
device registration into a separate function and perform the
registration only if the CPU OF node does not have the #cooling-cells
property.

Use of_cpufreq_power_cooling_register in imx_thermal code to link the
cooling device to the device tree node provided.

This makes it possible to bind the cpufreq cooling device to a custom
thermal zone via a cooling-maps entry like:

cooling-maps {
map0 {
trip = <&board_alert>;
cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};

Assuming a cpu node exists with label "cpu0" and #cooling-cells
property.

Signed-off-by: Bastian Stender <bst@pengutronix.de>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/imx6q-cpufreq.c
drivers/thermal/imx_thermal.c

index 8b3c2a7..b2ff423 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/clk.h>
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu_cooling.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -50,6 +51,7 @@ static struct clk_bulk_data clks[] = {
 };
 
 static struct device *cpu_dev;
+static struct thermal_cooling_device *cdev;
 static bool free_opp;
 static struct cpufreq_frequency_table *freq_table;
 static unsigned int max_freq;
@@ -191,6 +193,16 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
        return 0;
 }
 
+static void imx6q_cpufreq_ready(struct cpufreq_policy *policy)
+{
+       cdev = of_cpufreq_cooling_register(policy);
+
+       if (!cdev)
+               dev_err(cpu_dev,
+                       "running cpufreq without cooling device: %ld\n",
+                       PTR_ERR(cdev));
+}
+
 static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
 {
        int ret;
@@ -202,13 +214,22 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
        return ret;
 }
 
+static int imx6q_cpufreq_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_cooling_unregister(cdev);
+
+       return 0;
+}
+
 static struct cpufreq_driver imx6q_cpufreq_driver = {
        .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
        .verify = cpufreq_generic_frequency_table_verify,
        .target_index = imx6q_set_target,
        .get = cpufreq_generic_get,
        .init = imx6q_cpufreq_init,
+       .exit = imx6q_cpufreq_exit,
        .name = "imx6q-cpufreq",
+       .ready = imx6q_cpufreq_ready,
        .attr = cpufreq_generic_attr,
        .suspend = cpufreq_generic_suspend,
 };
index 334d98b..cbfcca8 100644 (file)
@@ -3,6 +3,7 @@
 // Copyright 2013 Freescale Semiconductor, Inc.
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/cpu_cooling.h>
 #include <linux/delay.h>
@@ -644,6 +645,27 @@ static const struct of_device_id of_imx_thermal_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
 
+/*
+ * Create cooling device in case no #cooling-cells property is available in
+ * CPU node
+ */
+static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
+{
+       struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL);
+       int ret;
+
+       if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
+               data->cdev = cpufreq_cooling_register(data->policy);
+               if (IS_ERR(data->cdev)) {
+                       ret = PTR_ERR(data->cdev);
+                       cpufreq_cpu_put(data->policy);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 static int imx_thermal_probe(struct platform_device *pdev)
 {
        struct imx_thermal_data *data;
@@ -724,12 +746,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
                return -EPROBE_DEFER;
        }
 
-       data->cdev = cpufreq_cooling_register(data->policy);
-       if (IS_ERR(data->cdev)) {
-               ret = PTR_ERR(data->cdev);
+       ret = imx_thermal_register_legacy_cooling(data);
+       if (ret) {
                dev_err(&pdev->dev,
                        "failed to register cpufreq cooling device: %d\n", ret);
-               cpufreq_cpu_put(data->policy);
                return ret;
        }