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

Commit bab8b376 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "driver: thermal: msm_lmh_dcvs: Register LMH DCVS cooling device"

parents 448d10ae b8af6bb4
Loading
Loading
Loading
Loading
+49 −7
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ struct cpufreq_cooling_device {
	int dyn_power_table_entries;
	struct device *cpu_dev;
	get_static_t plat_get_static_power;
	struct cpu_cooling_ops *plat_ops;
};
static DEFINE_IDR(cpufreq_idr);
static DEFINE_MUTEX(cooling_cpufreq_lock);
@@ -504,7 +505,12 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
				 unsigned long *state)
{
	struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
	unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus);

	if (cpufreq_device->plat_ops
			&& cpufreq_device->plat_ops->get_cur_state)
		cpufreq_device->plat_ops->get_cur_state(cpu, state);
	else
		*state = cpufreq_device->cpufreq_state;

	return 0;
@@ -539,7 +545,17 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
	cpufreq_device->cpufreq_state = state;
	cpufreq_device->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_device->plat_ops) {
		if (cpufreq_device->plat_ops->ceil_limit)
			cpufreq_device->plat_ops->ceil_limit(cpu,
						clip_freq);
	} else {
		cpufreq_update_policy(cpu);
	}

	return 0;
}
@@ -773,6 +789,9 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
 * @capacitance: dynamic power coefficient for these cpus
 * @plat_static_func: function to calculate the static power consumed by these
 *                    cpus (optional)
 * @plat_mitig_func: function that does the mitigation by changing the
 *                   frequencies (Optional). By default, cpufreq framweork 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
@@ -785,7 +804,8 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
static struct thermal_cooling_device *
__cpufreq_cooling_register(struct device_node *np,
			const struct cpumask *clip_cpus, u32 capacitance,
			get_static_t plat_static_func)
			get_static_t plat_static_func,
			struct cpu_cooling_ops *plat_ops)
{
	struct thermal_cooling_device *cool_dev;
	struct cpufreq_cooling_device *cpufreq_dev;
@@ -851,6 +871,8 @@ __cpufreq_cooling_register(struct device_node *np,
		}
	}

	cpufreq_dev->plat_ops = plat_ops;

	ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
	if (ret) {
		cool_dev = ERR_PTR(ret);
@@ -924,7 +946,7 @@ free_cdev:
struct thermal_cooling_device *
cpufreq_cooling_register(const struct cpumask *clip_cpus)
{
	return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL);
	return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL, NULL);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);

@@ -948,7 +970,7 @@ of_cpufreq_cooling_register(struct device_node *np,
	if (!np)
		return ERR_PTR(-EINVAL);

	return __cpufreq_cooling_register(np, clip_cpus, 0, NULL);
	return __cpufreq_cooling_register(np, clip_cpus, 0, NULL, NULL);
}
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);

@@ -978,10 +1000,30 @@ cpufreq_power_cooling_register(const struct cpumask *clip_cpus, u32 capacitance,
			       get_static_t plat_static_func)
{
	return __cpufreq_cooling_register(NULL, clip_cpus, capacitance,
				plat_static_func);
				plat_static_func, NULL);
}
EXPORT_SYMBOL(cpufreq_power_cooling_register);

/**
 * cpufreq_platform_cooling_register() - create cpufreq cooling device with
 * additional platform specific mitigation function.
 *
 * @clip_cpus: cpumask of cpus where the frequency constraints will happen
 * @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(const struct cpumask *clip_cpus,
				struct cpu_cooling_ops *plat_ops)
{
	return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL,
						plat_ops);
}
EXPORT_SYMBOL(cpufreq_platform_cooling_register);

/**
 * of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions
 * @np:	a valid struct device_node to the cooling device device tree node
@@ -1015,7 +1057,7 @@ of_cpufreq_power_cooling_register(struct device_node *np,
		return ERR_PTR(-EINVAL);

	return __cpufreq_cooling_register(np, clip_cpus, capacitance,
				plat_static_func);
				plat_static_func, NULL);
}
EXPORT_SYMBOL(of_cpufreq_power_cooling_register);

+57 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/pm_opp.h>
#include <linux/cpu_cooling.h>

#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
@@ -40,6 +41,7 @@
#define MSM_LIMITS_NODE_DCVS		0x44435653

#define MSM_LIMITS_SUB_FN_THERMAL	0x54484D4C
#define MSM_LIMITS_SUB_FN_GENERAL	0x47454E00

#define MSM_LIMITS_ALGO_MODE_ENABLE	0x454E424C

@@ -49,6 +51,8 @@
#define MSM_LIMITS_CLUSTER_0		0x6370302D
#define MSM_LIMITS_CLUSTER_1		0x6370312D

#define MSM_LIMITS_DOMAIN_MAX		0x444D4158

#define MSM_LIMITS_HIGH_THRESHOLD_VAL	95000
#define MSM_LIMITS_ARM_THRESHOLD_VAL	65000
#define MSM_LIMITS_POLLING_DELAY_MS	10
@@ -77,8 +81,12 @@ struct msm_lmh_dcvs_hw {
	cpumask_t core_map;
	struct timer_list poll_timer;
	uint32_t max_freq;
	uint32_t hw_freq_limit;
	struct list_head list;
};

LIST_HEAD(lmh_dcvs_hw_list);

static void msm_lmh_dcvs_get_max_freq(uint32_t cpu, uint32_t *max_freq)
{
	unsigned long freq_ceil = UINT_MAX;
@@ -104,6 +112,7 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw)
	dcvsh_get_frequency(val, max_limit);
	sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit);
	trace_lmh_dcvs_freq(cpumask_first(&hw->core_map), max_limit);
	hw->hw_freq_limit = max_limit;

	return max_limit;
}
@@ -250,6 +259,45 @@ static int trip_notify(enum thermal_trip_type type, int temp, void *data)
	return 0;
}

static struct msm_lmh_dcvs_hw *get_dcvsh_hw_from_cpu(int cpu)
{
	struct msm_lmh_dcvs_hw *hw;

	list_for_each_entry(hw, &lmh_dcvs_hw_list, list) {
		if (cpumask_test_cpu(cpu, &hw->core_map))
			return hw;
	}

	return NULL;
}

static int lmh_set_max_limit(int cpu, u32 freq)
{
	struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);

	if (!hw)
		return -EINVAL;

	return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_GENERAL,
				MSM_LIMITS_DOMAIN_MAX, freq);
}

static int lmh_get_cur_limit(int cpu, unsigned long *freq)
{
	struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);

	if (!hw)
		return -EINVAL;
	*freq = hw->hw_freq_limit;

	return 0;
}

static struct cpu_cooling_ops cd_ops = {
	.get_cur_state = lmh_get_cur_limit,
	.ceil_limit = lmh_set_max_limit,
};

static int msm_lmh_dcvs_probe(struct platform_device *pdev)
{
	int ret;
@@ -257,6 +305,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
	struct msm_lmh_dcvs_hw *hw;
	char sensor_name[] = "limits_sensor-00";
	struct thermal_zone_device *tzdev;
	struct thermal_cooling_device *cdev;
	struct device_node *dn = pdev->dev.of_node;
	struct device_node *cpu_node, *lmh_node;
	uint32_t id, max_freq, request_reg, clear_reg;
@@ -331,6 +380,10 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
	if (IS_ERR_OR_NULL(tzdev))
		return PTR_ERR(tzdev);

	/* Setup cooling devices to request mitigation states */
	cdev = cpufreq_platform_cooling_register(&hw->core_map, &cd_ops);
	if (IS_ERR_OR_NULL(cdev))
		return PTR_ERR(cdev);
	/*
	 * Driver defaults to for low and hi thresholds.
	 * Since we make a check for hi > lo value, set the hi threshold
@@ -356,7 +409,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
			return ret;
	}

	hw->max_freq = max_freq;
	hw->hw_freq_limit = hw->max_freq = max_freq;

	switch (affinity) {
	case 0:
@@ -399,6 +452,9 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
		return ret;
	}

	INIT_LIST_HEAD(&hw->list);
	list_add(&hw->list, &lmh_dcvs_hw_list);

	return ret;
}

+16 −0
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@
typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
			    unsigned long voltage, u32 *power);

struct cpu_cooling_ops {
	int (*ceil_limit)(int, u32);
	int (*get_cur_state)(int, unsigned long *);
};

#ifdef CONFIG_CPU_THERMAL
/**
 * cpufreq_cooling_register - function to create cpufreq cooling device.
@@ -43,6 +48,10 @@ struct thermal_cooling_device *
cpufreq_power_cooling_register(const struct cpumask *clip_cpus,
			       u32 capacitance, get_static_t plat_static_func);

struct thermal_cooling_device *
cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
					struct cpu_cooling_ops *ops);

/**
 * of_cpufreq_cooling_register - create cpufreq cooling device based on DT.
 * @np: a valid struct device_node to the cooling device device tree node.
@@ -112,6 +121,13 @@ of_cpufreq_power_cooling_register(struct device_node *np,
	return NULL;
}

static inline struct thermal_cooling_device *
cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
					struct cpu_cooling_ops *ops)
{
	return NULL;
}

static inline
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
{