Skip to content

Commit 2027942

Browse files
LaurentiuM1234carlescufi
authored andcommitted
drivers: intc: irqstr: add PM support
Add support for PM. The strategy is as follows: 1) For level 1 interrupts: don't care, these don't require the PM domain of irqsteer to be turned on since they are, well, direct. 2) For level 2 interrupts: use the reference count of the dispatchers. Upon doing a get() on a dispatcher with its reference count set to 0, before enabling the IRQ (meaning accessing the reg. space) increment the reference count of the irqstr device (which will result in the PM domain being enabled if 0). Upon doin a put() on a dispatcher with its reference count set to 1, after disabling the IRQ (meaning accessing the reg. space) decrement the reference count of the irqstr device (which will result in the PM domain being disabled if 0). In summary, the PM domain of the device will be enabled if at least one dispatcher is in use. On the other hand, the PM domain of the device will be disabled if there's no dispatchers in use (assuming there's no other dependencies). Signed-off-by: Laurentiu Mihalcea <[email protected]>
1 parent 4fba1d4 commit 2027942

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

drivers/interrupt_controller/intc_nxp_irqsteer.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@
229229
#include <zephyr/cache.h>
230230
#include <zephyr/sw_isr_table.h>
231231
#include <zephyr/logging/log.h>
232+
#include <zephyr/pm/device_runtime.h>
233+
#include <zephyr/pm/device.h>
232234

233235
#include "sw_isr_common.h"
234236

@@ -346,12 +348,20 @@ static void _irqstr_disp_enable_disable(struct irqsteer_dispatcher *disp,
346348

347349
static void _irqstr_disp_get_unlocked(struct irqsteer_dispatcher *disp)
348350
{
351+
int ret;
352+
349353
if (disp->refcnt == UINT8_MAX) {
350354
LOG_WRN("disp for irq %d reference count reached limit", disp->irq);
351355
return;
352356
}
353357

354358
if (!disp->refcnt) {
359+
ret = pm_device_runtime_get(disp->dev);
360+
if (ret < 0) {
361+
LOG_ERR("failed to enable PM resources: %d", ret);
362+
return;
363+
}
364+
355365
_irqstr_disp_enable_disable(disp, true);
356366
}
357367

@@ -363,6 +373,8 @@ static void _irqstr_disp_get_unlocked(struct irqsteer_dispatcher *disp)
363373

364374
static void _irqstr_disp_put_unlocked(struct irqsteer_dispatcher *disp)
365375
{
376+
int ret;
377+
366378
if (!disp->refcnt) {
367379
LOG_WRN("disp for irq %d already put", disp->irq);
368380
return;
@@ -372,6 +384,12 @@ static void _irqstr_disp_put_unlocked(struct irqsteer_dispatcher *disp)
372384

373385
if (!disp->refcnt) {
374386
_irqstr_disp_enable_disable(disp, false);
387+
388+
ret = pm_device_runtime_put(disp->dev);
389+
if (ret < 0) {
390+
LOG_ERR("failed to disable PM resources: %d", ret);
391+
return;
392+
}
375393
}
376394

377395
LOG_DBG("put on disp for irq %d results in refcnt: %d",
@@ -556,11 +574,18 @@ static void irqsteer_isr_dispatcher(const void *data)
556574
}
557575
}
558576

577+
__maybe_unused static int irqstr_pm_action(const struct device *dev,
578+
enum pm_device_action action)
579+
{
580+
/* nothing to be done here */
581+
return 0;
582+
}
583+
559584
static int irqsteer_init(const struct device *dev)
560585
{
561586
IRQSTEER_REGISTER_DISPATCHERS(DT_NODELABEL(irqsteer));
562587

563-
return 0;
588+
return pm_device_runtime_enable(dev);
564589
}
565590

566591

@@ -572,9 +597,10 @@ static struct irqsteer_config irqsteer_config = {
572597
};
573598

574599
/* assumption: only 1 IRQ_STEER instance */
600+
PM_DEVICE_DT_INST_DEFINE(0, irqstr_pm_action);
575601
DEVICE_DT_INST_DEFINE(0,
576602
&irqsteer_init,
577-
NULL,
603+
PM_DEVICE_DT_INST_GET(0),
578604
NULL, &irqsteer_config,
579605
PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
580606
NULL);

0 commit comments

Comments
 (0)