drivers: interrupt_controller: Add driver for NXP's IRQ_STEER IP
This commit introduces a new interrupt controller driver used for NXP's IRQ_STEER IP. Apart from introducing the driver itself, this commit contains the following changes: 1) Switch i.MX8MP to using the XTENSA core interrupt controller instead of the dummy irqsteer one. * this is required because the binding for the irqsteer driver is no longer a dummy one (since it's being used by the irqsteer driver). As such, to avoid having problems, switch to using another dummy binding. 2) Modify the irqsteer dummy binding such that it serves the IRQ_STEER driver's needs. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
This commit is contained in:
parent
0dab59ab8e
commit
fd8ac9e6cd
7 changed files with 529 additions and 17 deletions
|
@ -37,6 +37,7 @@ zephyr_library_sources_ifdef(CONFIG_NXP_S32_WKPU intc_wkpu_nxp_s32.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RENESAS_RA_ICU intc_ra_icu.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NXP_IRQSTEER intc_nxp_irqsteer.c)
|
||||
|
||||
if(CONFIG_INTEL_VTD_ICTL)
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/arch/x86/include)
|
||||
|
|
|
@ -104,4 +104,6 @@ source "drivers/interrupt_controller/Kconfig.vim"
|
|||
|
||||
source "drivers/interrupt_controller/Kconfig.ra"
|
||||
|
||||
source "drivers/interrupt_controller/Kconfig.nxp_irqsteer"
|
||||
|
||||
endmenu
|
||||
|
|
14
drivers/interrupt_controller/Kconfig.nxp_irqsteer
Normal file
14
drivers/interrupt_controller/Kconfig.nxp_irqsteer
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config NXP_IRQSTEER
|
||||
bool "IRQ_STEER interrupt controller for NXP chips"
|
||||
default y
|
||||
depends on DT_HAS_NXP_IRQSTEER_INTC_ENABLED
|
||||
depends on MULTI_LEVEL_INTERRUPTS
|
||||
depends on XTENSA
|
||||
help
|
||||
The IRQSTEER INTC provides support for MUX-ing
|
||||
multiple interrupts from peripheral to one or
|
||||
more CPU interrupt lines. This is used for CPUs
|
||||
such as XTENSA DSPs.
|
480
drivers/interrupt_controller/intc_nxp_irqsteer.c
Normal file
480
drivers/interrupt_controller/intc_nxp_irqsteer.c
Normal file
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright 2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Driver for NXP's IRQ_STEER IP.
|
||||
*
|
||||
* Below you may find some useful information that will help you better understand how the
|
||||
* driver works. The ">" sign is used to mark ideas that are considered important and should
|
||||
* be taken note of.
|
||||
*
|
||||
* 1) What is the IRQ_STEER IP?
|
||||
* - in Zephyr terminology, the IRQ_STEER can be considered an interrupt aggregator. As such,
|
||||
* its main goal is to multiplex multiple interrupt lines into a single/multiple ones.
|
||||
*
|
||||
* 2) How does the IRQ_STEER IP work?
|
||||
* - below you may find a diagram meant to give you an intuition regarding the IP's structure
|
||||
* and how it works (all of the information below is applicable to i.MX8MP but it can be
|
||||
* extended to any NXP SoC using the IRQ_STEER IP):
|
||||
*
|
||||
* SYSTEM_INTID[0:159]
|
||||
* |
|
||||
* MASK[0:4]------ |
|
||||
* | |
|
||||
* +------+
|
||||
* | |
|
||||
* |32 AND|
|
||||
* | |
|
||||
* +------+
|
||||
* |
|
||||
* SET[0:4]------ |
|
||||
* | |
|
||||
* +------+
|
||||
* | |
|
||||
* |32 OR |
|
||||
* | |
|
||||
* +------+
|
||||
* |__________ STATUS[0:4]
|
||||
* |
|
||||
* +------+
|
||||
* |GROUP |
|
||||
* | BY |
|
||||
* | 64 |
|
||||
* +------+
|
||||
* | | |
|
||||
* _____________| | |________________
|
||||
* | | |
|
||||
* MASTER_IN[0] MASTER_IN[1] MASTER_IN[2]
|
||||
* | | |
|
||||
* | | |
|
||||
* |_____________ | _______________|
|
||||
* | | |
|
||||
* +------+
|
||||
* | |
|
||||
* | AND | ---------- MINTDIS[0:2]
|
||||
* | |
|
||||
* +------+
|
||||
* | | |
|
||||
* _____________| | |________________
|
||||
* | | |
|
||||
* MASTER_OUT[0] MASTER_OUT[1] MASTER_OUT[2]
|
||||
*
|
||||
* - initially, all SYSTEM_INTID are grouped by 32 => 5 groups.
|
||||
*
|
||||
* > each of these groups is controlled by a MASK, SET and STATUS index as follows:
|
||||
*
|
||||
* MASK/SET/STATUS[0] => SYSTEM_INTID[159:128]
|
||||
* MASK/SET/STATUS[1] => SYSTEM_INTID[127:96]
|
||||
* MASK/SET/STATUS[2] => SYSTEM_INTID[95:64]
|
||||
* MASK/SET/STATUS[3] => SYSTEM_INTID[63:32]
|
||||
* MASK/SET/STATUS[4] => SYSTEM_INTID[31:0]
|
||||
*
|
||||
* > after that, all SYSTEM_INTID are grouped by 64 as follows:
|
||||
*
|
||||
* SYSTEM_INTID[159:96] => MASTER_IN[2]
|
||||
* SYSTEM_INTID[95:32] => MASTER_IN[1]
|
||||
* SYSTEM_INTID[31:0] => MASTER_IN[0]
|
||||
*
|
||||
* note: MASTER_IN[0] is only responsible for 32 interrupts
|
||||
*
|
||||
* > the value of MASTER_IN[x] is obtained by OR'ing the input interrupt lines.
|
||||
*
|
||||
* > the value of MASTER_OUT[x] is obtained by AND'ing MASTER_IN[x] with !MINTDIS[x].
|
||||
*
|
||||
* - whenever a SYSTEM_INTID is asserted, its corresponding MASTER_OUT signal will also
|
||||
* be asserted, thus signaling the target processor.
|
||||
*
|
||||
* > please note the difference between an IRQ_STEER channel and an IRQ_STEER master output.
|
||||
* An IRQ_STEER channel refers to an IRQ_STEER instance (e.g: the DSP uses IRQ_STEER channel
|
||||
* 0 a.k.a instance 0). An IRQ_STEER channel has multiple master outputs. For example, in
|
||||
* the case of i.MX8MP each IRQ_STEER channel has 3 master outputs since an IRQ_STEER channel
|
||||
* routes 160 interrupts (32 for first master output, 64 for second master output, and 64 for
|
||||
* the third master output).
|
||||
*
|
||||
* 3) Using Zephyr's multi-level interrupt support
|
||||
* - since Zephyr supports organizing interrupts on multiple levels, we can use this to
|
||||
* separate the interrupts in 2 levels:
|
||||
* 1) LEVEL 1 INTERRUPTS
|
||||
* - these are the interrupts that go directly to the processor (for example,
|
||||
* on i.MX8MP the MU can directly assert the DSP's interrupt line 7)
|
||||
*
|
||||
* 2) LEVEL 2 INTERRUPTS
|
||||
* - these interrupts go through IRQ_STEER and are signaled by a single
|
||||
* processor interrupt line.
|
||||
* - e.g: for i.MX8MP, INTID 34 (SDMA3) goes through IRQ_STEER and is signaled
|
||||
* to the DSP by INTID 20 which is a direct interrupt (or LEVEL 1 interrupt).
|
||||
*
|
||||
* - the following diagram (1) shows the interrupt organization on i.MX8MP:
|
||||
* +------------+
|
||||
* | |
|
||||
* SYSTEM_INTID[31:0] ------ IRQ_STEER_MASTER_0 ---- | 19 |
|
||||
* | |
|
||||
* SYSTEM_INTID[95:32] ----- IRQ_STEER_MASTER_1 ---- | 20 DSP |
|
||||
* | |
|
||||
* SYSTEM_INTID[159:96] ---- IRQ_STEER_MASTER_2 ---- | 21 |
|
||||
* | |
|
||||
* +------------+
|
||||
*
|
||||
* - as such, asserting a system interrupt will lead to asserting its corresponding DSP
|
||||
* interrupt line (for example, if system interrupt 34 is asserted, that would lead to
|
||||
* interrupt 20 being asserted)
|
||||
*
|
||||
* - in the above diagram, SYSTEM_INTID[x] are LEVEL 2 interrupts, while 19, 20, and 21 are
|
||||
* LEVEL 1 interrupts.
|
||||
*
|
||||
* - INTID 19 is the parent of SYSTEM_INTID[31:0] and so on.
|
||||
*
|
||||
* > before going into how the INTIDs are encoded, we need to distinguish between 3 types of
|
||||
* INTIDs:
|
||||
* 1) System INTIDs
|
||||
* - these are the values that can be found in NXP's TRMs for different
|
||||
* SoCs (usually they have the same IDs as the GIC SPIs)
|
||||
* - for example, INTID 34 is a system INTID for SDMA3 (i.MX8MP).
|
||||
*
|
||||
* 2) Zephyr INTIDs
|
||||
* - these are the Zephyr-specific encodings of the system INTIDs.
|
||||
* - these are used to encode multi-level interrupts (for more information
|
||||
* please see [1])
|
||||
* > if you need to register an interrupt dynamically, you need to use this
|
||||
* encoding when specifying the interrupt.
|
||||
*
|
||||
* 3) DTS INTIDs
|
||||
* - these are the encodings of the system INTIDs used in the DTS.
|
||||
* - all of these INTIDs are relative to IRQ_STEER's MASTER_OUTs.
|
||||
*
|
||||
* > encoding an INTID:
|
||||
* 1) SYSTEM INTID => ZEPHYR INTID
|
||||
* - the following steps need to be performed:
|
||||
*
|
||||
* a) Find out which IRQ_STEER MASTER
|
||||
* is in charge of aggregating this interrupt.
|
||||
* * for instance, SYSTEM_INTID 34 (SDMA3 on i.MX8MP) is
|
||||
* aggregated by MASTER 1 as depicted in diagram (1).
|
||||
*
|
||||
* b) After finding the MASTER aggregator, you need
|
||||
* to find the corresponding parent interrupt.
|
||||
* * for example, SYSTEM_INTID 34 (SDMA3 on i.MX8MP) is
|
||||
* aggregated by MASTER 1, which has the parent INTID 20
|
||||
* as depicted in diagram (1) => PARENT_INTID(34) = 20.
|
||||
*
|
||||
* c) Find the INTID relative to the MASTER aggregator. This is done
|
||||
* by subtracting the number of interrupts each of the previous
|
||||
* master aggregators is in charge of. If the master aggregator is
|
||||
* MASTER 0 then RELATIVE_INTID=SYSTEM_INTID.
|
||||
* * for example, SYSTEM_ID 34 is aggregated by MASTER 1.
|
||||
* As such, we need to subtract 32 from 34 (because the
|
||||
* previous master - MASTER 0 - is in charge of aggregating
|
||||
* 32 interrupts) => RELATIVE_INTID(34) = 2.
|
||||
*
|
||||
* * generally speaking, RELATIVE_INTID can be computed using
|
||||
* the following formula (assuming SYSTEM_INTID belongs to
|
||||
* MASTER y):
|
||||
* RELATIVE_INTID(x) = x -
|
||||
* \sum{i=0}^{y - 1} GET_MASTER_INT_NUM(i)
|
||||
* where:
|
||||
* 1) GET_MASTER_INT_NUM(x) computes the number of
|
||||
* interrupts master x aggregates
|
||||
* 2) x is the system interrupt
|
||||
*
|
||||
* * to make sure your computation is correct use the
|
||||
* following restriction:
|
||||
* 0 <= RELATIVE_INTID(x) < GET_MASTER_INT_NUM(y)
|
||||
*
|
||||
* d) To the obtained RELATIVE_INTID you need to add the value of 1,
|
||||
* left shift the result by the number of bits used to encode the
|
||||
* level 1 interrupts (see [1] for details) and OR the parent ID.
|
||||
* * for example, RELATIVE_INTID(34) = 2 (i.MX8MP),
|
||||
* PARENT_INTID(34) = 20 => ZEPHYR_INTID = ((2 + 1) << 8) | 20
|
||||
*
|
||||
* * generally speaking, ZEPHYR_INTID can be computed using
|
||||
* the following formula:
|
||||
* ZEPHYR_INTID(x) = ((RELATIVE_INTID(x) + 1) <<
|
||||
* NUM_LVL1_BITS) | PARENT_INTID(x)
|
||||
* where:
|
||||
* 1) RELATIVE_INTID(x) computes the relative INTID
|
||||
* of system interrupt x (step c).
|
||||
*
|
||||
* 2) NUM_LVL1_BITS is the number of bits used to
|
||||
* encode level 1 interrupts.
|
||||
*
|
||||
* 3) PARENT_INTID(x) computes the parent INTID of a
|
||||
* system interrupt x (step b)
|
||||
*
|
||||
* - all of these steps are performed by to_zephyr_irq().
|
||||
* > for interrupts aggregated by MASTER 0 you may skip step c) as
|
||||
* RELATIVE_INTID(x) = x.
|
||||
*
|
||||
* 2) SYSTEM INTID => DTS INTID
|
||||
* - for this you just have to compute RELATIVE_INTID as described above in
|
||||
* step c).
|
||||
* - for example, if an IP uses INTID 34 you'd write its interrupts property
|
||||
* as follows (i.MX8MP):
|
||||
* interrupts = <&master1 2>;
|
||||
*
|
||||
* 4) Notes and comments
|
||||
* > PLEASE DON'T MISTAKE THE ZEPHYR MULTI-LEVEL INTERRUPT ORGANIZATION WITH THE XTENSA ONE.
|
||||
* THEY ARE DIFFERENT THINGS.
|
||||
*
|
||||
* [1]: https://docs.zephyrproject.org/latest/kernel/services/interrupts.html#multi-level-interrupt-handling
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include <fsl_irqsteer.h>
|
||||
#include <zephyr/cache.h>
|
||||
|
||||
#include "sw_isr_common.h"
|
||||
|
||||
/* used for driver binding */
|
||||
#define DT_DRV_COMPAT nxp_irqsteer_intc
|
||||
|
||||
/* macros used for DTS parsing */
|
||||
#define _IRQSTEER_REGISTER_DISPATCHER(node_id) \
|
||||
IRQ_CONNECT(DT_IRQN(node_id), \
|
||||
DT_IRQ(node_id, priority), \
|
||||
irqsteer_isr_dispatcher, \
|
||||
&dispatchers[DT_REG_ADDR(node_id)], \
|
||||
0)
|
||||
|
||||
#define _IRQSTEER_DECLARE_DISPATCHER(node_id) \
|
||||
{ \
|
||||
.dev = DEVICE_DT_GET(DT_PARENT(node_id)), \
|
||||
.master_index = DT_REG_ADDR(node_id), \
|
||||
.irq = DT_IRQN(node_id), \
|
||||
}
|
||||
|
||||
#define IRQSTEER_DECLARE_DISPATCHERS(parent_id)\
|
||||
DT_FOREACH_CHILD_STATUS_OKAY_SEP(parent_id, _IRQSTEER_DECLARE_DISPATCHER, (,))
|
||||
|
||||
#define IRQSTEER_REGISTER_DISPATCHERS(parent_id)\
|
||||
DT_FOREACH_CHILD_STATUS_OKAY_SEP(parent_id, _IRQSTEER_REGISTER_DISPATCHER, (;))
|
||||
|
||||
/* utility macros */
|
||||
#define UINT_TO_IRQSTEER(x) ((IRQSTEER_Type *)(x))
|
||||
|
||||
struct irqsteer_config {
|
||||
uint32_t regmap_phys;
|
||||
uint32_t regmap_size;
|
||||
struct irqsteer_dispatcher *dispatchers;
|
||||
};
|
||||
|
||||
struct irqsteer_dispatcher {
|
||||
const struct device *dev;
|
||||
/* which set of interrupts is the dispatcher in charge of? */
|
||||
uint32_t master_index;
|
||||
/* which interrupt line is the dispatcher tied to? */
|
||||
uint32_t irq;
|
||||
};
|
||||
|
||||
static struct irqsteer_dispatcher dispatchers[] = {
|
||||
IRQSTEER_DECLARE_DISPATCHERS(DT_NODELABEL(irqsteer))
|
||||
};
|
||||
|
||||
/* used to convert system INTID to zephyr INTID */
|
||||
static int to_zephyr_irq(uint32_t regmap, uint32_t irq,
|
||||
struct irqsteer_dispatcher *dispatcher)
|
||||
{
|
||||
int i, idx;
|
||||
|
||||
idx = irq;
|
||||
|
||||
for (i = dispatcher->master_index - 1; i >= 0; i--) {
|
||||
idx -= IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
|
||||
}
|
||||
|
||||
return irq_to_level_2(idx) | dispatcher->irq;
|
||||
}
|
||||
|
||||
/* used to convert master-relative INTID to system INTID */
|
||||
static int to_system_irq(uint32_t regmap, int irq, int master_index)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = master_index - 1; i >= 0; i--) {
|
||||
irq += IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
/* used to convert zephyr INTID to system INTID */
|
||||
static int from_zephyr_irq(uint32_t regmap, uint32_t irq, uint32_t master_index)
|
||||
{
|
||||
int i, idx;
|
||||
|
||||
idx = irq;
|
||||
|
||||
for (i = 0; i < master_index; i++) {
|
||||
idx += IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void z_soc_irq_enable_disable(uint32_t irq, bool enable)
|
||||
{
|
||||
uint32_t parent_irq;
|
||||
int i, system_irq, level2_irq;
|
||||
const struct irqsteer_config *cfg;
|
||||
|
||||
if (irq_get_level(irq) == 1) {
|
||||
/* LEVEL 1 interrupts are DSP direct */
|
||||
if (enable) {
|
||||
z_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq));
|
||||
} else {
|
||||
z_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
parent_irq = irq_parent_level_2(irq);
|
||||
level2_irq = irq_from_level_2(irq);
|
||||
|
||||
/* find dispatcher responsible for this interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(dispatchers); i++) {
|
||||
if (dispatchers[i].irq != parent_irq) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg = dispatchers[i].dev->config;
|
||||
|
||||
system_irq = from_zephyr_irq(cfg->regmap_phys, level2_irq,
|
||||
dispatchers[i].master_index);
|
||||
|
||||
if (enable) {
|
||||
IRQSTEER_EnableInterrupt(UINT_TO_IRQSTEER(cfg->regmap_phys),
|
||||
system_irq);
|
||||
} else {
|
||||
IRQSTEER_DisableInterrupt(UINT_TO_IRQSTEER(cfg->regmap_phys),
|
||||
system_irq);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void z_soc_irq_enable(uint32_t irq)
|
||||
{
|
||||
z_soc_irq_enable_disable(irq, true);
|
||||
}
|
||||
|
||||
void z_soc_irq_disable(uint32_t irq)
|
||||
{
|
||||
z_soc_irq_enable_disable(irq, false);
|
||||
}
|
||||
|
||||
int z_soc_irq_is_enabled(unsigned int irq)
|
||||
{
|
||||
uint32_t parent_irq;
|
||||
int i, system_irq, level2_irq;
|
||||
const struct irqsteer_config *cfg;
|
||||
|
||||
if (irq_get_level(irq) == 1) {
|
||||
/* LEVEL 1 interrupts are DSP direct */
|
||||
return z_xtensa_irq_is_enabled(XTENSA_IRQ_NUMBER(irq));
|
||||
}
|
||||
|
||||
parent_irq = irq_parent_level_2(irq);
|
||||
level2_irq = irq_from_level_2(irq);
|
||||
|
||||
/* find dispatcher responsible for this interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(dispatchers); i++) {
|
||||
if (dispatchers[i].irq != parent_irq) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg = dispatchers[i].dev->config;
|
||||
|
||||
system_irq = from_zephyr_irq(cfg->regmap_phys, level2_irq,
|
||||
dispatchers[i].master_index);
|
||||
|
||||
return IRQSTEER_InterruptIsEnabled(UINT_TO_IRQSTEER(cfg->regmap_phys), system_irq);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void irqsteer_isr_dispatcher(const void *data)
|
||||
{
|
||||
struct irqsteer_dispatcher *dispatcher;
|
||||
const struct irqsteer_config *cfg;
|
||||
uint32_t table_idx;
|
||||
int system_irq, zephyr_irq, i;
|
||||
uint64_t status;
|
||||
|
||||
dispatcher = (struct irqsteer_dispatcher *)data;
|
||||
cfg = dispatcher->dev->config;
|
||||
|
||||
/* fetch master interrupts status */
|
||||
status = IRQSTEER_GetMasterInterruptsStatus(UINT_TO_IRQSTEER(cfg->regmap_phys),
|
||||
dispatcher->master_index);
|
||||
|
||||
for (i = 0; status; i++) {
|
||||
/* if bit 0 is set then that means relative INTID i is asserted */
|
||||
if (status & 1) {
|
||||
/* convert master-relative INTID to a system INTID */
|
||||
system_irq = to_system_irq(cfg->regmap_phys, i,
|
||||
dispatcher->master_index);
|
||||
|
||||
/* convert system INTID to a Zephyr INTID */
|
||||
zephyr_irq = to_zephyr_irq(cfg->regmap_phys, system_irq, dispatcher);
|
||||
|
||||
/* compute index in the SW ISR table */
|
||||
table_idx = z_get_sw_isr_table_idx(zephyr_irq);
|
||||
|
||||
/* call child's ISR */
|
||||
_sw_isr_table[table_idx].isr(_sw_isr_table[table_idx].arg);
|
||||
}
|
||||
|
||||
status >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void irqsteer_enable_dispatchers(const struct device *dev)
|
||||
{
|
||||
int i;
|
||||
struct irqsteer_dispatcher *dispatcher;
|
||||
const struct irqsteer_config *cfg;
|
||||
|
||||
cfg = dev->config;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dispatchers); i++) {
|
||||
dispatcher = &dispatchers[i];
|
||||
|
||||
IRQSTEER_EnableMasterInterrupt(UINT_TO_IRQSTEER(cfg->regmap_phys),
|
||||
dispatcher->irq);
|
||||
|
||||
z_xtensa_irq_enable(XTENSA_IRQ_NUMBER(dispatcher->irq));
|
||||
}
|
||||
}
|
||||
|
||||
static int irqsteer_init(const struct device *dev)
|
||||
{
|
||||
IRQSTEER_REGISTER_DISPATCHERS(DT_NODELABEL(irqsteer));
|
||||
|
||||
/* enable all dispatchers */
|
||||
irqsteer_enable_dispatchers(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: do we need to add support for MMU-based SoCs? */
|
||||
static struct irqsteer_config irqsteer_config = {
|
||||
.regmap_phys = DT_REG_ADDR(DT_NODELABEL(irqsteer)),
|
||||
.regmap_size = DT_REG_SIZE(DT_NODELABEL(irqsteer)),
|
||||
.dispatchers = dispatchers,
|
||||
};
|
||||
|
||||
/* assumption: only 1 IRQ_STEER instance */
|
||||
DEVICE_DT_INST_DEFINE(0,
|
||||
&irqsteer_init,
|
||||
NULL,
|
||||
NULL, &irqsteer_config,
|
||||
PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
|
||||
NULL);
|
|
@ -2,12 +2,8 @@ description: i.MX DSP interrupt controller
|
|||
|
||||
compatible: "nxp,irqsteer-intc"
|
||||
|
||||
include: [interrupt-controller.yaml, base.yaml]
|
||||
include: [base.yaml]
|
||||
|
||||
properties:
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
interrupt-cells:
|
||||
- irq
|
||||
- priority
|
||||
reg:
|
||||
required: true
|
||||
|
|
15
dts/bindings/interrupt-controller/nxp,irqsteer-master.yaml
Normal file
15
dts/bindings/interrupt-controller/nxp,irqsteer-master.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
description: i.MX IRQ_STEER master
|
||||
|
||||
compatible: "nxp,irqsteer-master"
|
||||
|
||||
include: [interrupt-controller.yaml, base.yaml]
|
||||
|
||||
properties:
|
||||
"#interrupt-cells":
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupt-cells:
|
||||
- irq
|
|
@ -17,6 +17,16 @@
|
|||
device_type = "cpu";
|
||||
compatible = "cdns,tensilica-xtensa-lx6";
|
||||
reg = <0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
clic: interrupt-controller@0 {
|
||||
compatible = "cdns,xtensa-core-intc";
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -33,14 +43,6 @@
|
|||
};
|
||||
|
||||
soc {
|
||||
interrupt-parent = <&irqsteer>;
|
||||
|
||||
irqsteer: interrupt-controller {
|
||||
compatible = "nxp,irqsteer-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
ccm: ccm@30380000 {
|
||||
compatible = "nxp,imx-ccm";
|
||||
reg = <0x30380000 DT_SIZE_K(64)>;
|
||||
|
@ -67,7 +69,8 @@
|
|||
/* TODO: This INTID is just a dummy
|
||||
* until we can support UART interrupts
|
||||
*/
|
||||
interrupts = <29 0>;
|
||||
interrupt-parent = <&clic>;
|
||||
interrupts = <29 0 0>;
|
||||
clocks = <&ccm IMX_CCM_UART4_CLK 0x6c 24>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -75,7 +78,8 @@
|
|||
mailbox0: mailbox@30e70000 {
|
||||
compatible = "nxp,imx-mu";
|
||||
reg = <0x30e70000 0x10000>;
|
||||
interrupts = <7 0>;
|
||||
interrupt-parent = <&clic>;
|
||||
interrupts = <7 0 0>;
|
||||
rdc = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue