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

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

Merge changes I67dbfa8e,I866b4c0c,I566985a4 into msm-4.14

* changes:
  drivers: thermal: lmh-dcvs: Register the cooling device in order
  ARM: dts: msm: Add a test thermal zone for SM8150
  drivers: thermal: lmh-dcvsh: Add multiple clock plan support
parents 7892838f 2656dad6
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -2197,4 +2197,51 @@
			};
		};
	};

	pop-mem-test {
		polling-delay-passive = <10>;
		polling-delay = <0>;
		thermal-sensors = <&tsens1 3>;
		thermal-governor = "step_wise";
		disable-thermal-zone;
		trips {
			pop_test_trip: pop-test-trip {
				temperature = <95000>;
				hysteresis = <0>;
				type = "passive";
			};
		};
		cooling-maps {
			pop_test_cdev0 {
				trip = <&pop_test_trip>;
				cooling-device =
					<&modem_pa THERMAL_NO_LIMIT
						THERMAL_NO_LIMIT>;
			};
			pop_test_cdev1 {
				trip = <&pop_test_trip>;
				cooling-device =
					<&modem_proc THERMAL_NO_LIMIT
						THERMAL_NO_LIMIT>;
			};
			pop_test_cdev2 {
				trip = <&pop_test_trip>;
				cooling-device =
					<&modem_current THERMAL_NO_LIMIT
						THERMAL_NO_LIMIT>;
			};
			pop_test_cdev3 {
				trip = <&pop_test_trip>;
				cooling-device =
					<&modem_skin THERMAL_NO_LIMIT
						THERMAL_NO_LIMIT>;
			};
			pop_test_cdev4 {
				trip = <&pop_test_trip>;
				cooling-device =
					<&mdss_mdp THERMAL_NO_LIMIT
						THERMAL_NO_LIMIT>;
			};
		};
	};
};
+106 −83
Original line number Diff line number Diff line
@@ -88,15 +88,15 @@ struct limits_dcvs_hw {
	void *int_clr_reg;
	void *min_freq_reg;
	cpumask_t core_map;
	cpumask_t online_mask;
	struct delayed_work freq_poll_work;
	unsigned long max_freq;
	unsigned long min_freq;
	unsigned long max_freq[NR_CPUS];
	unsigned long min_freq[NR_CPUS];
	unsigned long hw_freq_limit;
	struct device_attribute lmh_freq_attr;
	struct list_head list;
	bool is_irq_enabled;
	struct mutex access_lock;
	struct mutex cdev_reg_lock;
	struct __limits_cdev_data *cdev_data;
	uint32_t cdev_registered;
	struct regulator *isens_reg[2];
@@ -106,38 +106,42 @@ struct limits_dcvs_hw {
LIST_HEAD(lmh_dcvs_hw_list);
DEFINE_MUTEX(lmh_dcvs_list_access);

static int limits_dcvs_get_freq_limits(uint32_t cpu, unsigned long *max_freq,
					 unsigned long *min_freq)
static void limits_dcvs_get_freq_limits(struct limits_dcvs_hw *hw)
{
	unsigned long freq_ceil = UINT_MAX, freq_floor = 0;
	struct device *cpu_dev = NULL;
	int ret = 0;
	uint32_t cpu, idx = 0;

	for_each_cpu(cpu, &hw->core_map) {
		freq_ceil = UINT_MAX;
		freq_floor = 0;
		cpu_dev = get_cpu_device(cpu);
		if (!cpu_dev) {
			pr_err("Error in get CPU%d device\n", cpu);
		return -ENODEV;
			idx++;
			continue;
		}

		dev_pm_opp_find_freq_floor(cpu_dev, &freq_ceil);
		dev_pm_opp_find_freq_ceil(cpu_dev, &freq_floor);

	*max_freq = freq_ceil / 1000;
	*min_freq = freq_floor / 1000;

	return ret;
		hw->max_freq[idx] = freq_ceil / 1000;
		hw->min_freq[idx] = freq_floor / 1000;
		idx++;
	}
}

static unsigned long limits_mitigation_notify(struct limits_dcvs_hw *hw)
{
	uint32_t val = 0;
	uint32_t val = 0, max_cpu_ct = 0, max_cpu_limit = 0, idx = 0, cpu = 0;
	struct device *cpu_dev = NULL;
	unsigned long freq_val, max_limit = 0;
	struct dev_pm_opp *opp_entry;

	val = readl_relaxed(hw->osm_hw_reg);
	dcvsh_get_frequency(val, max_limit);
	cpu_dev = get_cpu_device(cpumask_first(&hw->core_map));
	for_each_cpu(cpu, &hw->core_map) {
		cpu_dev = get_cpu_device(cpu);
		if (!cpu_dev) {
			pr_err("Error in get CPU%d device\n",
				cpumask_first(&hw->core_map));
@@ -156,13 +160,26 @@ static unsigned long limits_mitigation_notify(struct limits_dcvs_hw *hw)
		 * frequency using freq_ceil.
		 */
		if (IS_ERR(opp_entry) && PTR_ERR(opp_entry) == -ERANGE) {
		opp_entry = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_val);
			opp_entry = dev_pm_opp_find_freq_ceil(cpu_dev,
								&freq_val);
			if (IS_ERR(opp_entry))
			dev_err(cpu_dev, "frequency:%lu. opp error:%ld\n",
				dev_err(cpu_dev,
					"frequency:%lu. opp error:%ld\n",
					freq_val, PTR_ERR(opp_entry));
		}
		if (FREQ_HZ_TO_KHZ(freq_val) == hw->max_freq[idx]) {
			max_cpu_ct++;
			if (max_cpu_limit < hw->max_freq[idx])
				max_cpu_limit = hw->max_freq[idx];
			idx++;
			continue;
		}
		max_limit = FREQ_HZ_TO_KHZ(freq_val);
		break;
	}

	if (max_cpu_ct == cpumask_weight(&hw->core_map))
		max_limit = max_cpu_limit;
	sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit);
	pr_debug("CPU:%d max limit:%lu\n", cpumask_first(&hw->core_map),
			max_limit);
@@ -179,13 +196,18 @@ static void limits_dcvs_poll(struct work_struct *work)
	struct limits_dcvs_hw *hw = container_of(work,
					struct limits_dcvs_hw,
					freq_poll_work.work);
	int cpu_ct = 0, cpu = 0, idx = 0;

	mutex_lock(&hw->access_lock);
	if (hw->max_freq == U32_MAX)
		limits_dcvs_get_freq_limits(cpumask_first(&hw->core_map),
			&hw->max_freq, &hw->min_freq);
	if (hw->max_freq[0] == U32_MAX)
		limits_dcvs_get_freq_limits(hw);
	max_limit = limits_mitigation_notify(hw);
	if (max_limit >= hw->max_freq) {
	for_each_cpu(cpu, &hw->core_map) {
		if (max_limit >= hw->max_freq[idx])
			cpu_ct++;
		idx++;
	}
	if (cpu_ct >= cpumask_weight(&hw->core_map)) {
		writel_relaxed(0xFF, hw->int_clr_reg);
		hw->is_irq_enabled = true;
		enable_irq(hw->irq_num);
@@ -313,14 +335,10 @@ static struct limits_dcvs_hw *get_dcvsh_hw_from_cpu(int cpu)
{
	struct limits_dcvs_hw *hw;

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

	return NULL;
}
@@ -343,7 +361,7 @@ static int lmh_set_max_limit(int cpu, u32 freq)
		 * the CPU to use the boost frequencies.
		 */
			hw->cdev_data[idx].max_freq =
				(freq == hw->max_freq) ? U32_MAX : freq;
				(freq == hw->max_freq[idx]) ? U32_MAX : freq;
		if (max_freq > hw->cdev_data[idx].max_freq)
			max_freq = hw->cdev_data[idx].max_freq;
		idx++;
@@ -360,8 +378,7 @@ static int lmh_set_max_limit(int cpu, u32 freq)
static int lmh_set_min_limit(int cpu, u32 freq)
{
	struct limits_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);
	int cpu_idx, idx = 0;
	u32 min_freq = 0;
	int cpu_idx, idx = 0, cpu_ct = 0;

	if (!hw)
		return -EINVAL;
@@ -370,11 +387,11 @@ static int lmh_set_min_limit(int cpu, u32 freq)
	for_each_cpu(cpu_idx, &hw->core_map) {
		if (cpu_idx == cpu)
			hw->cdev_data[idx].min_freq = freq;
		if (min_freq < hw->cdev_data[idx].min_freq)
			min_freq = hw->cdev_data[idx].min_freq;
		if (hw->cdev_data[idx].min_freq <= hw->min_freq[idx])
			cpu_ct++;
		idx++;
	}
	if (min_freq != hw->min_freq)
	if (cpu_ct < cpumask_weight(&hw->core_map))
		writel_relaxed(0x01, hw->min_freq_reg);
	else
		writel_relaxed(0x00, hw->min_freq_reg);
@@ -389,15 +406,17 @@ static struct cpu_cooling_ops cd_ops = {

static void register_cooling_device(struct work_struct *work)
{
	struct limits_dcvs_hw *hw = container_of(work, struct limits_dcvs_hw,
						cdev_register_work);
	struct limits_dcvs_hw *hw;
	unsigned int cpu = 0, idx = 0;

	mutex_lock(&hw->cdev_reg_lock);
	if (hw->max_freq == U32_MAX)
		limits_dcvs_get_freq_limits(cpumask_first(&hw->core_map),
			&hw->max_freq, &hw->min_freq);
	mutex_lock(&lmh_dcvs_list_access);
	list_for_each_entry(hw, &lmh_dcvs_hw_list, list) {
		if (hw->max_freq[0] == U32_MAX)
			limits_dcvs_get_freq_limits(hw);

		if (cpumask_weight(&hw->online_mask) == 0)
			continue;
		idx = 0;
		for_each_cpu(cpu, &hw->core_map) {
			cpumask_t cpu_mask  = { CPU_BITS_NONE };

@@ -408,19 +427,21 @@ static void register_cooling_device(struct work_struct *work)
			cpumask_set_cpu(cpu, &cpu_mask);
			hw->cdev_data[idx].max_freq = U32_MAX;
			hw->cdev_data[idx].min_freq = 0;
		hw->cdev_data[idx].cdev = cpufreq_platform_cooling_register(
			hw->cdev_data[idx].cdev =
					cpufreq_platform_cooling_register(
							&cpu_mask, &cd_ops);
			if (IS_ERR_OR_NULL(hw->cdev_data[idx].cdev)) {
			pr_err("CPU:%u cooling device register error:%ld\n",
				pr_err("CPU:%u cdev register error:%ld\n",
					cpu, PTR_ERR(hw->cdev_data[idx].cdev));
				hw->cdev_data[idx].cdev = NULL;
			} else {
			pr_debug("CPU:%u cooling device registered\n", cpu);
				pr_debug("CPU:%u cdev registered\n", cpu);
				hw->cdev_registered++;
			}
			idx++;
		}
	mutex_unlock(&hw->cdev_reg_lock);
	}
	mutex_unlock(&lmh_dcvs_list_access);
}

static int limits_cpu_online(unsigned int online_cpu)
@@ -429,6 +450,7 @@ static int limits_cpu_online(unsigned int online_cpu)

	if (!hw)
		return 0;
	cpumask_set_cpu(online_cpu, &hw->online_mask);
	if (hw->cdev_registered != cpumask_weight(&hw->core_map))
		queue_work(system_highpri_wq, &hw->cdev_register_work);

@@ -542,11 +564,14 @@ static int limits_dcvs_probe(struct platform_device *pdev)
		return -ENOMEM;

	cpumask_copy(&hw->core_map, &mask);
	cpumask_clear(&hw->online_mask);
	hw->cdev_registered = 0;
	for_each_cpu(cpu, &hw->core_map) {
		hw->cdev_data[idx].cdev = NULL;
		hw->cdev_data[idx].max_freq = U32_MAX;
		hw->cdev_data[idx].min_freq = 0;
		hw->max_freq[idx] = U32_MAX;
		hw->min_freq[idx] = 0;
		idx++;
	}
	ret = of_property_read_u32(dn, "qcom,affinity", &affinity);
@@ -586,8 +611,7 @@ static int limits_dcvs_probe(struct platform_device *pdev)
	 */
	hw->temp_limits[LIMITS_TRIP_HI] = INT_MAX;
	hw->temp_limits[LIMITS_TRIP_ARM] = 0;
	hw->hw_freq_limit = hw->max_freq = U32_MAX;
	hw->min_freq = 0;
	hw->hw_freq_limit = U32_MAX;
	snprintf(hw->sensor_name, sizeof(hw->sensor_name), "limits_sensor-%02d",
			affinity);
	tzdev = thermal_zone_of_sensor_register(&pdev->dev, 0, hw,
@@ -603,7 +627,6 @@ static int limits_dcvs_probe(struct platform_device *pdev)
	}

	mutex_init(&hw->access_lock);
	mutex_init(&hw->cdev_reg_lock);
	INIT_WORK(&hw->cdev_register_work, register_cooling_device);
	INIT_DEFERRABLE_WORK(&hw->freq_poll_work, limits_dcvs_poll);
	hw->osm_hw_reg = devm_ioremap(&pdev->dev, request_reg, 0x4);
@@ -640,7 +663,7 @@ static int limits_dcvs_probe(struct platform_device *pdev)
probe_exit:
	mutex_lock(&lmh_dcvs_list_access);
	INIT_LIST_HEAD(&hw->list);
	list_add(&hw->list, &lmh_dcvs_hw_list);
	list_add_tail(&hw->list, &lmh_dcvs_hw_list);
	mutex_unlock(&lmh_dcvs_list_access);
	lmh_debug_register(pdev);