Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 763658b9 authored by Ram Chandrasekar's avatar Ram Chandrasekar
Browse files

drivers: thermal: cpu_cooling: Snapshot of cpu cooling driver



Add a snapshot of CPU cooling device driver changes from
msm-4.14 from 'commit <2c89a516da31> ("drivers: cpu_cooling: Remove
cooling list lock during post suspend handling")'. This snapshot
includes just the support for platform cooling device and doesn't include
core isolation.

Change-Id: Ib3befb0a813693b1cfe4a338c1cb57e75b39f9ea
Signed-off-by: default avatarRam Chandrasekar <rkumbako@codeaurora.org>
parent 3b3e314b
Loading
Loading
Loading
Loading
+151 −12
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/cpu_cooling.h>
#include <linux/of_device.h>

#include <trace/events/thermal.h>

@@ -80,6 +81,10 @@ struct time_in_idle {
 *	cooling	devices.
 * @clipped_freq: integer value representing the absolute value of the clipped
 *	frequency.
 * @cpufreq_floor_state: integer value representing the frequency floor state
 *	of cpufreq cooling devices.
 * @floor_freq: integer value representing the absolute value of the floor
 *	frequency.
 * @max_level: maximum cooling level. One less than total number of valid
 *	cpufreq frequencies.
 * @freq_table: Freq table in descending order of frequencies
@@ -97,12 +102,15 @@ struct cpufreq_cooling_device {
	u32 last_load;
	unsigned int cpufreq_state;
	unsigned int clipped_freq;
	unsigned int cpufreq_floor_state;
	unsigned int floor_freq;
	unsigned int max_level;
	struct freq_table *freq_table;	/* In descending order */
	struct thermal_cooling_device *cdev;
	struct cpufreq_policy *policy;
	struct list_head node;
	struct time_in_idle *idle_time;
	struct cpu_cooling_ops *plat_ops;
};

static DEFINE_IDA(cpufreq_ida);
@@ -165,7 +173,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
				    unsigned long event, void *data)
{
	struct cpufreq_policy *policy = data;
	unsigned long clipped_freq;
	unsigned long clipped_freq = ULONG_MAX, floor_freq = 0;
	struct cpufreq_cooling_device *cpufreq_cdev;

	if (event != CPUFREQ_ADJUST)
@@ -190,13 +198,18 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
		 *
		 * But, if clipped_freq is greater than policy->max, we don't
		 * need to do anything.
		 *
		 * Similarly, if policy minimum set by the user is less than
		 * the floor_frequency, then adjust the policy->min.
		 */
		clipped_freq = cpufreq_cdev->clipped_freq;

		if (policy->max > clipped_freq)
			cpufreq_verify_within_limits(policy, 0, clipped_freq);
		floor_freq = cpufreq_cdev->floor_freq;
		if (policy->max > clipped_freq || policy->min < floor_freq)
			cpufreq_verify_within_limits(policy, floor_freq,
							clipped_freq);
		break;
	}

	mutex_unlock(&cooling_list_lock);

	return NOTIFY_OK;
@@ -372,6 +385,67 @@ static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
	return 0;
}

/**
 * cpufreq_get_min_state - callback function to get the device floor state.
 * @cdev: thermal cooling device pointer.
 * @state: fill this variable with the cooling device floor.
 *
 * Callback for the thermal cooling device to return the cpufreq
 * floor state.
 *
 * Return: 0 on success, an error code otherwise.
 */
static int cpufreq_get_min_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{
	struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;

	*state = cpufreq_cdev->cpufreq_floor_state;

	return 0;
}

/**
 * cpufreq_set_min_state - callback function to set the device floor state.
 * @cdev: thermal cooling device pointer.
 * @state: set this variable to the current cooling state.
 *
 * Callback for the thermal cooling device to change the cpufreq
 * floor state.
 *
 * Return: 0 on success, an error code otherwise.
 */
static int cpufreq_set_min_state(struct thermal_cooling_device *cdev,
				 unsigned long state)
{
	struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
	unsigned int cpu = cpufreq_cdev->policy->cpu;
	unsigned int floor_freq;

	if (state > cpufreq_cdev->max_level)
		state = cpufreq_cdev->max_level;

	if (cpufreq_cdev->cpufreq_floor_state == state)
		return 0;

	cpufreq_cdev->cpufreq_floor_state = state;
	floor_freq = cpufreq_cdev->freq_table[state].frequency;
	cpufreq_cdev->floor_freq = floor_freq;

	/*
	 * Check if the device has a platform mitigation function that
	 * can handle the CPU freq mitigation, if not, notify cpufreq
	 * framework.
	 */
	if (cpufreq_cdev->plat_ops &&
		cpufreq_cdev->plat_ops->floor_limit)
		cpufreq_cdev->plat_ops->floor_limit(cpu, floor_freq);
	else
		cpufreq_update_policy(cpu);

	return 0;
}

/**
 * cpufreq_get_cur_state - callback function to get the current cooling state.
 * @cdev: thermal cooling device pointer.
@@ -420,6 +494,15 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
	cpufreq_cdev->cpufreq_state = state;
	cpufreq_cdev->clipped_freq = clip_freq;

	/* Check if the device has a platform mitigation function that
	 * can handle the CPU freq mitigation, if not, notify cpufreq
	 * framework.
	 */
	if (cpufreq_cdev->plat_ops &&
		cpufreq_cdev->plat_ops->ceil_limit)
		cpufreq_cdev->plat_ops->ceil_limit(cpufreq_cdev->policy->cpu,
							clip_freq);
	else
		cpufreq_update_policy(cpufreq_cdev->policy->cpu);

	return 0;
@@ -577,6 +660,8 @@ static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
	.get_max_state = cpufreq_get_max_state,
	.get_cur_state = cpufreq_get_cur_state,
	.set_cur_state = cpufreq_set_cur_state,
	.set_min_state = cpufreq_set_min_state,
	.get_min_state = cpufreq_get_min_state,
};

static struct thermal_cooling_device_ops cpufreq_power_cooling_ops = {
@@ -613,6 +698,9 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
 * @policy: cpufreq policy
 * Normally this should be same as cpufreq policy->related_cpus.
 * @capacitance: dynamic power coefficient for these cpus
 * @plat_ops: function that does the mitigation by changing the
 *                   frequencies (Optional). By default, cpufreq framework will
 *                   be notified of the new limits.
 *
 * This interface function registers the cpufreq cooling device with the name
 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
@@ -624,7 +712,8 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
 */
static struct thermal_cooling_device *
__cpufreq_cooling_register(struct device_node *np,
			struct cpufreq_policy *policy, u32 capacitance)
			struct cpufreq_policy *policy, u32 capacitance,
			struct cpu_cooling_ops *plat_ops)
{
	struct thermal_cooling_device *cdev;
	struct cpufreq_cooling_device *cpufreq_cdev;
@@ -705,12 +794,17 @@ __cpufreq_cooling_register(struct device_node *np,
		cooling_ops = &cpufreq_cooling_ops;
	}

	cpufreq_cdev->plat_ops = plat_ops;

	cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev,
						  cooling_ops);
	if (IS_ERR(cdev))
		goto remove_ida;

	cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency;
	cpufreq_cdev->floor_freq =
		cpufreq_cdev->freq_table[cpufreq_cdev->max_level].frequency;
	cpufreq_cdev->cpufreq_floor_state = cpufreq_cdev->max_level;
	cpufreq_cdev->cdev = cdev;

	mutex_lock(&cooling_list_lock);
@@ -719,7 +813,7 @@ __cpufreq_cooling_register(struct device_node *np,
	list_add(&cpufreq_cdev->node, &cpufreq_cdev_list);
	mutex_unlock(&cooling_list_lock);

	if (first)
	if (first && !cpufreq_cdev->plat_ops)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);

@@ -750,7 +844,7 @@ __cpufreq_cooling_register(struct device_node *np,
struct thermal_cooling_device *
cpufreq_cooling_register(struct cpufreq_policy *policy)
{
	return __cpufreq_cooling_register(NULL, policy, 0);
	return __cpufreq_cooling_register(NULL, policy, 0, NULL);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);

@@ -790,7 +884,8 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
		of_property_read_u32(np, "dynamic-power-coefficient",
				     &capacitance);

		cdev = __cpufreq_cooling_register(np, policy, capacitance);
		cdev = __cpufreq_cooling_register(np, policy, capacitance,
						NULL);
		if (IS_ERR(cdev)) {
			pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
			       policy->cpu, PTR_ERR(cdev));
@@ -803,6 +898,47 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
}
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);

/**
 * cpufreq_platform_cooling_register() - create cpufreq cooling device with
 * additional platform specific mitigation function.
 *
 * @policy: cpufreq policy
 * @plat_ops: the platform mitigation functions that will be called insted of
 * cpufreq, if provided.
 *
 * Return: a valid struct thermal_cooling_device pointer on success,
 * on failure, it returns a corresponding ERR_PTR().
 */
struct thermal_cooling_device *
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
				struct cpu_cooling_ops *plat_ops)
{
	struct device_node *cpu_node = NULL;
	u32 capacitance = 0;
	struct thermal_cooling_device *cdev = NULL;

	cpu_node = of_cpu_device_node_get(policy->cpu);
	if (!cpu_node) {
		pr_err("No cpu node\n");
		return ERR_PTR(-EINVAL);
	}
	if (of_find_property(cpu_node, "#cooling-cells", NULL)) {
		of_property_read_u32(cpu_node, "dynamic-power-coefficient",
				     &capacitance);

		cdev = __cpufreq_cooling_register(cpu_node, policy, capacitance,
							plat_ops);
		if (IS_ERR(cdev))
			pr_err("cpu_cooling: cpu%d cooling device err: %ld\n",
			       policy->cpu, PTR_ERR(cdev));
	}

	of_node_put(cpu_node);
	return cdev;
}
EXPORT_SYMBOL(cpufreq_platform_cooling_register);


/**
 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
 * @cdev: thermal cooling device pointer.
@@ -825,9 +961,12 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
	last = list_empty(&cpufreq_cdev_list);
	mutex_unlock(&cooling_list_lock);

	if (last)
		cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
	if (last) {
		if (!cpufreq_cdev->plat_ops)
			cpufreq_unregister_notifier(
					&thermal_cpufreq_notifier_block,
					CPUFREQ_POLICY_NOTIFIER);
	}

	thermal_cooling_device_unregister(cpufreq_cdev->cdev);
	ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
+17 −0
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@

struct cpufreq_policy;

typedef int (*plat_mitig_t)(int cpu, u32 clip_freq);

struct cpu_cooling_ops {
	plat_mitig_t ceil_limit, floor_limit;
};

#ifdef CONFIG_CPU_THERMAL
/**
 * cpufreq_cooling_register - function to create cpufreq cooling device.
@@ -38,6 +44,10 @@ struct cpufreq_policy;
struct thermal_cooling_device *
cpufreq_cooling_register(struct cpufreq_policy *policy);

struct thermal_cooling_device *
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
					struct cpu_cooling_ops *ops);

/**
 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
 * @cdev: thermal cooling device pointer.
@@ -74,6 +84,13 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
{
	return NULL;
}

static inline struct thermal_cooling_device *
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
					struct cpu_cooling_ops *ops)
{
	return NULL;
}
#endif /* defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) */

#endif /* __CPU_COOLING_H__ */