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: David Collins <collinsd@codeaurora.org>
This commit is contained in:
parent
666151fd60
commit
d9a90463d3
5 changed files with 91 additions and 0 deletions
|
@ -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>;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -5778,6 +5778,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
|
||||
|
@ -5975,6 +6000,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Reference in a new issue