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

Commit b7d5b597 authored by David Collins's avatar David Collins
Browse files

regulator: cpr3-regulator: add support for configuring CPR IRQ affinity



Add support to configure the CPR interrupt affinity via a CPR3
controller device tree node.  This can be used to avoid servicing
CPR interrupts triggered by a CPU enterring power collapse on the
CPU that just power collapsed.

Change-Id: I4c04a2c255a6bd249c888c0dd0dbda19b8436be2
CRs-Fixed: 949650
Signed-off-by: default avatarDavid Collins <collinsd@codeaurora.org>
parent edf4d230
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ apcc_cpr: cpr3-ctrl@99e8000 {
	clock-names = "core_clk";
	interrupts = <0 48 0>, <0 47 0>;
	interrupt-names = "cpr", "ceiling";
	qcom,cpr-interrupt-affinity = <&CPU0 &CPU1>;
	qcom,cpr-ctrl-name = "apcc";

	qcom,cpr-sensor-time = <1000>;
+6 −0
Original line number Diff line number Diff line
@@ -104,6 +104,12 @@ Platform independent properties:
		    must be specified.  "ceiling" may be specified for some
		    platforms.

- qcom,cpr-interrupt-affinity
	Usage:      optional
	Value type: <prop-encoded-array>
	Definition: A list of CPU phandles which correspond to the cores that
		    the "cpr" interrupt should have affinity for.

- qcom,cpr-sensor-time
	Usage:      required
	Value type: <u32>
+33 −0
Original line number Diff line number Diff line
@@ -5733,6 +5733,31 @@ int cpr3_regulator_resume(struct cpr3_controller *ctrl)
	return 0;
}

/**
 * cpr3_regulator_cpu_hotplug_callback() - reset CPR IRQ affinity when a CPU is
 *		brought online via hotplug
 * @nb:			Pointer to the notifier block
 * @action:		hotplug action
 * @hcpu:		long value corresponding to the CPU number
 *
 * Return: NOTIFY_OK
 */
static int cpr3_regulator_cpu_hotplug_callback(struct notifier_block *nb,
					    unsigned long action, void *hcpu)
{
	struct cpr3_controller *ctrl = container_of(nb, struct cpr3_controller,
					cpu_hotplug_notifier);
	int cpu = (long)hcpu;

	action &= ~CPU_TASKS_FROZEN;

	if (action == CPU_ONLINE
	    && cpumask_test_cpu(cpu, &ctrl->irq_affinity_mask))
		irq_set_affinity(ctrl->irq, &ctrl->irq_affinity_mask);

	return NOTIFY_OK;
}

/**
 * cpr3_regulator_validate_controller() - verify the data passed in via the
 *		cpr3_controller data structure
@@ -5931,6 +5956,14 @@ int cpr3_regulator_register(struct platform_device *pdev,
		}
	}

	if (ctrl->irq && !cpumask_empty(&ctrl->irq_affinity_mask)) {
		irq_set_affinity(ctrl->irq, &ctrl->irq_affinity_mask);

		ctrl->cpu_hotplug_notifier.notifier_call
			= cpr3_regulator_cpu_hotplug_callback;
		register_hotcpu_notifier(&ctrl->cpu_hotplug_notifier);
	}

	mutex_lock(&cpr3_controller_list_mutex);
	cpr3_regulator_debugfs_ctrl_add(ctrl);
	list_add(&ctrl->list, &cpr3_controller_list);
+6 −0
Original line number Diff line number Diff line
@@ -535,6 +535,10 @@ struct cpr3_aging_sensor_info {
 * @iface_clk:		Pointer to the CPR3 interface clock (platform specific)
 * @bus_clk:		Pointer to the CPR3 bus clock (platform specific)
 * @irq:		CPR interrupt number
 * @irq_affinity_mask:	The cpumask for the CPUs which the CPR interrupt should
 *			have affinity for
 * @cpu_hotplug_notifier: CPU hotplug notifier used to reset IRQ affinity when a
 *			CPU is brought back online
 * @ceiling_irq:	Interrupt number for the interrupt that is triggered
 *			when hardware closed-loop attempts to exceed the ceiling
 *			voltage
@@ -695,6 +699,8 @@ struct cpr3_controller {
	struct clk		*iface_clk;
	struct clk		*bus_clk;
	int			irq;
	struct cpumask		irq_affinity_mask;
	struct notifier_block	cpu_hotplug_notifier;
	int			ceiling_irq;
	struct msm_apm_ctrl_dev *apm;
	int			apm_threshold_volt;
+45 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#define pr_fmt(fmt) "%s: " fmt, __func__

#include <linux/cpumask.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -979,6 +980,46 @@ int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
	return rc;
}

/**
 * cpr3_parse_irq_affinity() - parse CPR IRQ affinity information
 * @ctrl:		Pointer to the CPR3 controller
 *
 * Return: 0 on success, errno on failure
 */
static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl)
{
	struct device_node *cpu_node;
	int i, cpu;
	int len = 0;

	if (!of_find_property(ctrl->dev->of_node, "qcom,cpr-interrupt-affinity",
				&len)) {
		/* No IRQ affinity required */
		return 0;
	}

	len /= sizeof(u32);

	for (i = 0; i < len; i++) {
		cpu_node = of_parse_phandle(ctrl->dev->of_node,
					    "qcom,cpr-interrupt-affinity", i);
		if (!cpu_node) {
			cpr3_err(ctrl, "could not find CPU node %d\n", i);
			return -EINVAL;
		}

		for_each_possible_cpu(cpu) {
			if (of_get_cpu_node(cpu, NULL) == cpu_node) {
				cpumask_set_cpu(cpu, &ctrl->irq_affinity_mask);
				break;
			}
		}
		of_node_put(cpu_node);
	}

	return 0;
}

/**
 * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from
 *		device tree
@@ -1045,6 +1086,10 @@ int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
	ctrl->cpr_allowed_sw = of_property_read_bool(ctrl->dev->of_node,
			"qcom,cpr-enable");

	rc = cpr3_parse_irq_affinity(ctrl);
	if (rc)
		return rc;

	/* Aging reference voltage is optional */
	ctrl->aging_ref_volt = 0;
	of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage",