It starts from updating cpu_pm to support CPU_LAST_PM_ENTER (and
CPU_FIRST_PM_EXIT) event, and then adds DT binding and driver support
for Qualcomm MPM (MSM Power Manager) interrupt controller.
Changes for v6:
- Add new event CPU_LAST_PM_ENTER (and CPU_FIRST_PM_EXIT) in cpu_pm
- Drop vendor driver notes from commit log
- Check NULL mpm_gic_map instead to save the use of MPM_NO_PARENT_IRQ
- Add lock protection for register read in qcom_mpm_handler()
- Return IRQ_NONE if there is no pending interrupt
- Drop IRQF_TRIGGER_RISING flag from devm_request_irq() call since it's
being specified in DT
- Drop dev_set_drvdata() call which is a leftover from previous version
- Fix dt_binding_check errors reported by upgraded dtschema
Changes for v5:
- Drop inline attributes and let compiler to decide
- Use _irqsave/_irqrestore flavour for spin lock
- Assignment on a single for irq_resolve_mapping() call
- Add documentation to explain vMPM ownership transition
- Move MPM pin map data into device tree and so use a generic compatible
- Drop the code that counts CPUs in PM and use CPU_CLUSTER_PM_ENTER
notification instead
Changes for v4:
- Add the missing include of <linux/interrupt.h> to fix build errors
on arm architecture.
- Leave IRQCHIP_PLATFORM_DRIVER infrastructural unchanged, and use
of_find_device_by_node() to get platform_device pointer.
Changes for v3:
- Support module build
- Use relaxed accessors
- Add barrier call to ensure MMIO write completes
- Use d->chip_data to pass driver private data
- Use raw spinlock
- USe BIT() for bit shift
- Create a single irq domain to cover both types of MPM pins
- Call irq_resolve_mapping() to find out Linux irq number
- Save the use of ternary conditional operator and use switch/case for
.irq_set_type call
- Drop unnecessary .irq_disable hook
- Align qcom_mpm_chip and qcom_mpm_ops members vertically
- Use helper irq_domain_translate_twocell()
- Move mailbox requesting forward in probe function
- Improve the documentation on qcm2290_gic_pins[]
- Use IRQCHIP_PLATFORM_DRIVER infrastructural
- Use cpu_pm notifier instead of .suspend_late hook to write MPM for
sleep, so that MPM can be set up for both suspend and idle context.
The TIMER0/1 setup is currently omitted for idle use case though,
as I haven't been able to successfully test the idle context.
Shawn Guo (3):
PM: cpu: Add CPU_LAST_PM_ENTER and CPU_FIRST_PM_EXIT support
dt-bindings: interrupt-controller: Add Qualcomm MPM support
irqchip: Add Qualcomm MPM controller driver
.../interrupt-controller/qcom,mpm.yaml | 96 ++++
drivers/irqchip/Kconfig | 8 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/qcom-mpm.c | 439 ++++++++++++++++++
include/linux/cpu_pm.h | 15 +
kernel/cpu_pm.c | 33 +-
6 files changed, 590 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml
create mode 100644 drivers/irqchip/qcom-mpm.c
--
2.25.1
It becomes a common situation on some platforms that certain hardware
setup needs to be done on the last standing cpu, and rpmh-rsc[1] is such
an existing example. As figuring out the last standing cpu is really
something generic, it adds CPU_LAST_PM_ENTER (and CPU_FIRST_PM_EXIT)
event support to cpu_pm helper, so that individual driver can be
notified when the last standing cpu is about to enter low power state.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/soc/qcom/rpmh-rsc.c?id=v5.16#n773
Signed-off-by: Shawn Guo <[email protected]>
---
include/linux/cpu_pm.h | 15 +++++++++++++++
kernel/cpu_pm.c | 33 +++++++++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/include/linux/cpu_pm.h b/include/linux/cpu_pm.h
index 552b8f9ea05e..153344307b7c 100644
--- a/include/linux/cpu_pm.h
+++ b/include/linux/cpu_pm.h
@@ -55,6 +55,21 @@ enum cpu_pm_event {
/* A cpu power domain is exiting a low power state */
CPU_CLUSTER_PM_EXIT,
+
+ /*
+ * A cpu is entering a low power state after all other cpus
+ * in the system have entered the lower power state.
+ */
+ CPU_LAST_PM_ENTER,
+
+ /* The last cpu failed to enter a low power state */
+ CPU_LAST_PM_ENTER_FAILED,
+
+ /*
+ * A cpu is exiting a low power state before any other cpus
+ * in the system exits the low power state.
+ */
+ CPU_FIRST_PM_EXIT,
};
#ifdef CONFIG_CPU_PM
diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c
index 246efc74e3f3..7c104446e1e9 100644
--- a/kernel/cpu_pm.c
+++ b/kernel/cpu_pm.c
@@ -26,6 +26,8 @@ static struct {
.lock = __RAW_SPIN_LOCK_UNLOCKED(cpu_pm_notifier.lock),
};
+static atomic_t cpus_in_pm;
+
static int cpu_pm_notify(enum cpu_pm_event event)
{
int ret;
@@ -116,7 +118,20 @@ EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
*/
int cpu_pm_enter(void)
{
- return cpu_pm_notify_robust(CPU_PM_ENTER, CPU_PM_ENTER_FAILED);
+ int ret;
+
+ ret = cpu_pm_notify_robust(CPU_PM_ENTER, CPU_PM_ENTER_FAILED);
+ if (ret)
+ return ret;
+
+ if (atomic_inc_return(&cpus_in_pm) == num_online_cpus()) {
+ ret = cpu_pm_notify_robust(CPU_LAST_PM_ENTER,
+ CPU_LAST_PM_ENTER_FAILED);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
EXPORT_SYMBOL_GPL(cpu_pm_enter);
@@ -134,7 +149,21 @@ EXPORT_SYMBOL_GPL(cpu_pm_enter);
*/
int cpu_pm_exit(void)
{
- return cpu_pm_notify(CPU_PM_EXIT);
+ int ret;
+
+ ret = cpu_pm_notify(CPU_PM_EXIT);
+ if (ret)
+ return ret;
+
+ if (atomic_read(&cpus_in_pm) == num_online_cpus()) {
+ ret = cpu_pm_notify(CPU_FIRST_PM_EXIT);
+ if (ret)
+ return ret;
+ }
+
+ atomic_dec(&cpus_in_pm);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(cpu_pm_exit);
--
2.25.1
On Wed, May 04, 2022 at 04:08:58PM +0200, Ulf Hansson wrote:
> On Wed, 23 Feb 2022 at 13:57, Shawn Guo <[email protected]> wrote:
> >
> > It starts from updating cpu_pm to support CPU_LAST_PM_ENTER (and
> > CPU_FIRST_PM_EXIT) event, and then adds DT binding and driver support
> > for Qualcomm MPM (MSM Power Manager) interrupt controller.
> >
> > Changes for v6:
> > - Add new event CPU_LAST_PM_ENTER (and CPU_FIRST_PM_EXIT) in cpu_pm
> > - Drop vendor driver notes from commit log
> > - Check NULL mpm_gic_map instead to save the use of MPM_NO_PARENT_IRQ
> > - Add lock protection for register read in qcom_mpm_handler()
> > - Return IRQ_NONE if there is no pending interrupt
> > - Drop IRQF_TRIGGER_RISING flag from devm_request_irq() call since it's
> > being specified in DT
> > - Drop dev_set_drvdata() call which is a leftover from previous version
> > - Fix dt_binding_check errors reported by upgraded dtschema
>
> My apologies for the late reply to this series. FYI, I fully agree
> with the responses from Sudeep, etc, that have been made on this
> series.
>
> The proper thing is to use genpd on/off notifiers, which should get
> fired if you model the PM domain topology correctly in DT - and use
> PSCI OSI.
>
> That said, please keep me posted when/if you submit a new version for
> this. I will make sure to pay more attention next time.
>
[1] is the latest I believe. It now implements power domain as I requested and
I was happy with that version.
--
Regards,
Sudeep
[1] https://lore.kernel.org/lkml/[email protected]
On Wed, 23 Feb 2022 at 13:57, Shawn Guo <[email protected]> wrote:
>
> It starts from updating cpu_pm to support CPU_LAST_PM_ENTER (and
> CPU_FIRST_PM_EXIT) event, and then adds DT binding and driver support
> for Qualcomm MPM (MSM Power Manager) interrupt controller.
>
> Changes for v6:
> - Add new event CPU_LAST_PM_ENTER (and CPU_FIRST_PM_EXIT) in cpu_pm
> - Drop vendor driver notes from commit log
> - Check NULL mpm_gic_map instead to save the use of MPM_NO_PARENT_IRQ
> - Add lock protection for register read in qcom_mpm_handler()
> - Return IRQ_NONE if there is no pending interrupt
> - Drop IRQF_TRIGGER_RISING flag from devm_request_irq() call since it's
> being specified in DT
> - Drop dev_set_drvdata() call which is a leftover from previous version
> - Fix dt_binding_check errors reported by upgraded dtschema
My apologies for the late reply to this series. FYI, I fully agree
with the responses from Sudeep, etc, that have been made on this
series.
The proper thing is to use genpd on/off notifiers, which should get
fired if you model the PM domain topology correctly in DT - and use
PSCI OSI.
That said, please keep me posted when/if you submit a new version for
this. I will make sure to pay more attention next time.
Kind regards
Uffe
>
> Changes for v5:
> - Drop inline attributes and let compiler to decide
> - Use _irqsave/_irqrestore flavour for spin lock
> - Assignment on a single for irq_resolve_mapping() call
> - Add documentation to explain vMPM ownership transition
> - Move MPM pin map data into device tree and so use a generic compatible
> - Drop the code that counts CPUs in PM and use CPU_CLUSTER_PM_ENTER
> notification instead
>
> Changes for v4:
> - Add the missing include of <linux/interrupt.h> to fix build errors
> on arm architecture.
> - Leave IRQCHIP_PLATFORM_DRIVER infrastructural unchanged, and use
> of_find_device_by_node() to get platform_device pointer.
>
> Changes for v3:
> - Support module build
> - Use relaxed accessors
> - Add barrier call to ensure MMIO write completes
> - Use d->chip_data to pass driver private data
> - Use raw spinlock
> - USe BIT() for bit shift
> - Create a single irq domain to cover both types of MPM pins
> - Call irq_resolve_mapping() to find out Linux irq number
> - Save the use of ternary conditional operator and use switch/case for
> .irq_set_type call
> - Drop unnecessary .irq_disable hook
> - Align qcom_mpm_chip and qcom_mpm_ops members vertically
> - Use helper irq_domain_translate_twocell()
> - Move mailbox requesting forward in probe function
> - Improve the documentation on qcm2290_gic_pins[]
> - Use IRQCHIP_PLATFORM_DRIVER infrastructural
> - Use cpu_pm notifier instead of .suspend_late hook to write MPM for
> sleep, so that MPM can be set up for both suspend and idle context.
> The TIMER0/1 setup is currently omitted for idle use case though,
> as I haven't been able to successfully test the idle context.
>
> Shawn Guo (3):
> PM: cpu: Add CPU_LAST_PM_ENTER and CPU_FIRST_PM_EXIT support
> dt-bindings: interrupt-controller: Add Qualcomm MPM support
> irqchip: Add Qualcomm MPM controller driver
>
> .../interrupt-controller/qcom,mpm.yaml | 96 ++++
> drivers/irqchip/Kconfig | 8 +
> drivers/irqchip/Makefile | 1 +
> drivers/irqchip/qcom-mpm.c | 439 ++++++++++++++++++
> include/linux/cpu_pm.h | 15 +
> kernel/cpu_pm.c | 33 +-
> 6 files changed, 590 insertions(+), 2 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml
> create mode 100644 drivers/irqchip/qcom-mpm.c
>
> --
> 2.25.1
>