Skip to content

Commit c8a5cf6

Browse files
manuarguefabiobaltieri
authored andcommitted
intc: add NXP S32 WKPU interrupt controller driver
Introduce an interrupt controller for the NXP S32 WKPU peripheral that can be integrated with GPIO to trigger interrupts through external interrupt pad inputs. WKPU can trigger interrupts from certain input pads that support this function, as well as wake-up events to the power management domain. This patch only adds WKPU functionality as an interrupt controller to extend the number of input pads that can interrupt the core. Power management functionalities are not supported. Signed-off-by: Manuel Argüelles <[email protected]>
1 parent 125e65a commit c8a5cf6

File tree

5 files changed

+300
-1
lines changed

5 files changed

+300
-1
lines changed

drivers/interrupt_controller/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex.
3333
zephyr_library_sources_ifdef(CONFIG_VIM intc_vim.c)
3434
zephyr_library_sources_ifdef(CONFIG_NUCLEI_ECLIC intc_nuclei_eclic.c)
3535
zephyr_library_sources_ifdef(CONFIG_NXP_S32_EIRQ intc_eirq_nxp_s32.c)
36+
zephyr_library_sources_ifdef(CONFIG_NXP_S32_WKPU intc_wkpu_nxp_s32.c)
3637
zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c)
3738
zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c)
3839

drivers/interrupt_controller/Kconfig.nxp_s32

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Configuration for NXP S32 external interrupt controller
22

3-
# Copyright 2022 NXP
3+
# Copyright 2022-2023 NXP
44
# SPDX-License-Identifier: Apache-2.0
55

66
config NXP_S32_EIRQ
@@ -10,3 +10,11 @@ config NXP_S32_EIRQ
1010
select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT
1111
help
1212
External interrupt controller driver for NXP S32 MCUs
13+
14+
config NXP_S32_WKPU
15+
bool "Wake-up Unit interrupt controller driver for NXP S32 MCUs"
16+
default y
17+
depends on DT_HAS_NXP_S32_WKPU_ENABLED
18+
select NOCACHE_MEMORY
19+
help
20+
Wake-up Unit interrupt controller driver for NXP S32 MCUs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright 2023 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT nxp_s32_wkpu
8+
9+
#include <zephyr/kernel.h>
10+
#include <zephyr/device.h>
11+
#include <zephyr/irq.h>
12+
#include <zephyr/sys/sys_io.h>
13+
#include <zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h>
14+
15+
#include <Wkpu_Ip_Irq.h>
16+
17+
#define NXP_S32_NUM_CHANNELS WKPU_IP_NUM_OF_CHANNELS
18+
#define NXP_S32_NUM_CHANNELS_DEBRACKET __DEBRACKET WKPU_IP_NUM_OF_CHANNELS
19+
20+
struct wkpu_nxp_s32_config {
21+
uint8_t instance;
22+
23+
const WKPU_Type *base;
24+
25+
const Wkpu_Ip_IrqConfigType *wkpu_cfg;
26+
};
27+
28+
/* Wrapper callback for each WKPU line, from low level driver callback to GPIO callback */
29+
struct wkpu_nxp_s32_cb {
30+
wkpu_nxp_s32_callback_t cb;
31+
uint8_t pin;
32+
void *data;
33+
};
34+
35+
struct wkpu_nxp_s32_data {
36+
struct wkpu_nxp_s32_cb *cb;
37+
};
38+
39+
int wkpu_nxp_s32_set_callback(const struct device *dev, uint8_t line,
40+
wkpu_nxp_s32_callback_t cb, uint8_t pin, void *arg)
41+
{
42+
struct wkpu_nxp_s32_data *data = dev->data;
43+
44+
__ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range");
45+
46+
if (data->cb[line].cb) {
47+
return -EBUSY;
48+
}
49+
50+
data->cb[line].cb = cb;
51+
data->cb[line].pin = pin;
52+
data->cb[line].data = arg;
53+
54+
return 0;
55+
}
56+
57+
void wkpu_nxp_s32_unset_callback(const struct device *dev, uint8_t line)
58+
{
59+
struct wkpu_nxp_s32_data *data = dev->data;
60+
61+
__ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range");
62+
63+
data->cb[line].cb = NULL;
64+
data->cb[line].pin = 0;
65+
data->cb[line].data = NULL;
66+
}
67+
68+
void wkpu_nxp_s32_enable_interrupt(const struct device *dev, uint8_t line,
69+
Wkpu_Ip_EdgeType edge_type)
70+
{
71+
const struct wkpu_nxp_s32_config *config = dev->config;
72+
73+
__ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range");
74+
75+
Wkpu_Ip_SetActivationCondition(config->instance, line, edge_type);
76+
Wkpu_Ip_EnableNotification(line);
77+
Wkpu_Ip_EnableInterrupt(config->instance, line);
78+
}
79+
80+
void wkpu_nxp_s32_disable_interrupt(const struct device *dev, uint8_t line)
81+
{
82+
const struct wkpu_nxp_s32_config *config = dev->config;
83+
84+
__ASSERT(line < NXP_S32_NUM_CHANNELS, "Interrupt line is out of range");
85+
86+
Wkpu_Ip_DisableInterrupt(config->instance, line);
87+
Wkpu_Ip_DisableNotification(line);
88+
Wkpu_Ip_SetActivationCondition(config->instance, line, WKPU_IP_NONE_EDGE);
89+
}
90+
91+
uint64_t wkpu_nxp_s32_get_pending(const struct device *dev)
92+
{
93+
const struct wkpu_nxp_s32_config *config = dev->config;
94+
uint64_t flags;
95+
96+
flags = config->base->WISR & config->base->IRER;
97+
#if defined(WKPU_IP_64_CH_USED) && (WKPU_IP_64_CH_USED == STD_ON)
98+
flags |= ((uint64_t)(config->base->WISR_64 & config->base->IRER_64)) << 32U;
99+
#endif
100+
101+
return flags;
102+
}
103+
104+
static void wkpu_nxp_s32_callback(const struct device *dev, uint8 line)
105+
{
106+
const struct wkpu_nxp_s32_data *data = dev->data;
107+
108+
if (data->cb[line].cb != NULL) {
109+
data->cb[line].cb(data->cb[line].pin, data->cb[line].data);
110+
}
111+
}
112+
113+
static int wkpu_nxp_s32_init(const struct device *dev)
114+
{
115+
const struct wkpu_nxp_s32_config *config = dev->config;
116+
117+
if (Wkpu_Ip_Init(config->instance, config->wkpu_cfg)) {
118+
return -EINVAL;
119+
}
120+
121+
return 0;
122+
}
123+
124+
#define WKPU_NXP_S32_CALLBACK(line, n) \
125+
void nxp_s32_wkpu_##n##wkpu_line_##line##_callback(void) \
126+
{ \
127+
const struct device *dev = DEVICE_DT_INST_GET(n); \
128+
\
129+
wkpu_nxp_s32_callback(dev, line); \
130+
}
131+
132+
#define WKPU_NXP_S32_CHANNEL_CONFIG(idx, n) \
133+
{ \
134+
.hwChannel = idx, \
135+
.filterEn = DT_INST_PROP_OR(DT_INST_CHILD(n, line_##idx), filter_enable, 0), \
136+
.edgeEvent = WKPU_IP_NONE_EDGE, \
137+
.WkpuChannelNotification = nxp_s32_wkpu_##n##wkpu_line_##idx##_callback, \
138+
.callback = NULL, \
139+
.callbackParam = 0U \
140+
}
141+
142+
#define WKPU_NXP_S32_CHANNELS_CONFIG(n) \
143+
static const Wkpu_Ip_ChannelConfigType wkpu_##n##_channel_nxp_s32_cfg[] = { \
144+
LISTIFY(NXP_S32_NUM_CHANNELS_DEBRACKET, WKPU_NXP_S32_CHANNEL_CONFIG, (,), n) \
145+
}
146+
147+
#define WKPU_NXP_S32_INSTANCE_CONFIG(n) \
148+
static const Wkpu_Ip_IrqConfigType wkpu_##n##_nxp_s32_cfg = { \
149+
.numChannels = NXP_S32_NUM_CHANNELS, \
150+
.pChannelsConfig = &wkpu_##n##_channel_nxp_s32_cfg, \
151+
}
152+
153+
#define WKPU_NXP_S32_CONFIG(n) \
154+
LISTIFY(NXP_S32_NUM_CHANNELS_DEBRACKET, WKPU_NXP_S32_CALLBACK, (), n) \
155+
WKPU_NXP_S32_CHANNELS_CONFIG(n); \
156+
WKPU_NXP_S32_INSTANCE_CONFIG(n);
157+
158+
#define WKPU_NXP_S32_INIT_DEVICE(n) \
159+
WKPU_NXP_S32_CONFIG(n) \
160+
static const struct wkpu_nxp_s32_config wkpu_nxp_s32_conf_##n = { \
161+
.instance = n, \
162+
.base = (WKPU_Type *)DT_INST_REG_ADDR(n), \
163+
.wkpu_cfg = (Wkpu_Ip_IrqConfigType *)&wkpu_##n##_nxp_s32_cfg, \
164+
}; \
165+
static struct wkpu_nxp_s32_cb wkpu_nxp_s32_cb_##n[NXP_S32_NUM_CHANNELS]; \
166+
static struct wkpu_nxp_s32_data wkpu_nxp_s32_data_##n = { \
167+
.cb = wkpu_nxp_s32_cb_##n, \
168+
}; \
169+
static int wkpu_nxp_s32_init##n(const struct device *dev) \
170+
{ \
171+
int err; \
172+
\
173+
err = wkpu_nxp_s32_init(dev); \
174+
if (err) { \
175+
return err; \
176+
} \
177+
\
178+
IRQ_CONNECT(DT_INST_IRQ(n, irq), DT_INST_IRQ(n, priority), \
179+
WKPU_EXT_IRQ_SINGLE_ISR, NULL, \
180+
COND_CODE_1(CONFIG_GIC, (DT_INST_IRQ(n, flags)), (0))); \
181+
irq_enable(DT_INST_IRQ(n, irq)); \
182+
\
183+
return 0; \
184+
} \
185+
DEVICE_DT_INST_DEFINE(n, \
186+
wkpu_nxp_s32_init##n, \
187+
NULL, \
188+
&wkpu_nxp_s32_data_##n, \
189+
&wkpu_nxp_s32_conf_##n, \
190+
PRE_KERNEL_2, \
191+
CONFIG_INTC_INIT_PRIORITY, \
192+
NULL);
193+
194+
DT_INST_FOREACH_STATUS_OKAY(WKPU_NXP_S32_INIT_DEVICE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2023 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: NXP S32 Wake-up Unit
5+
6+
compatible: "nxp,s32-wkpu"
7+
8+
include: base.yaml
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
child-binding:
15+
description: |
16+
NXP S32 WKPU interrupt line configuration. Specific requirements for each
17+
interrupt line can be specified by adding children nodes to this controller,
18+
labeled `line_<line_number>`. For example:
19+
20+
line_0: line_0 {
21+
filter-enable;
22+
};
23+
24+
properties:
25+
filter-enable:
26+
type: boolean
27+
description: |
28+
Enable analog glitch filter on the external interrupt pad input.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2023 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @brief Driver for Wake-up interrupt/event controller in NXP S32 MCUs
9+
*/
10+
11+
#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_
12+
#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_
13+
14+
#include <Wkpu_Ip.h>
15+
16+
/* Wrapper callback for WKPU line */
17+
typedef void (*wkpu_nxp_s32_callback_t)(uint8_t pin, void *arg);
18+
19+
/**
20+
* @brief Unset WKPU callback for line
21+
*
22+
* @param dev WKPU device
23+
* @param line WKPU line
24+
*/
25+
void wkpu_nxp_s32_unset_callback(const struct device *dev, uint8_t line);
26+
27+
/**
28+
* @brief Set WKPU callback for line
29+
*
30+
* @param dev WKPU device
31+
* @param line WKPU line
32+
* @param cb Callback
33+
* @param pin GPIO pin
34+
* @param arg Callback data
35+
*
36+
* @retval 0 on SUCCESS
37+
* @retval -EBUSY if callback for the line is already set
38+
*/
39+
int wkpu_nxp_s32_set_callback(const struct device *dev, uint8_t line,
40+
wkpu_nxp_s32_callback_t cb, uint8_t pin, void *arg);
41+
42+
/**
43+
* @brief Set edge event and enable interrupt for WKPU line
44+
*
45+
* @param dev WKPU device
46+
* @param line WKPU line
47+
* @param edge_type Type of edge event
48+
*/
49+
void wkpu_nxp_s32_enable_interrupt(const struct device *dev, uint8_t line,
50+
Wkpu_Ip_EdgeType edge_type);
51+
52+
/**
53+
* @brief Disable interrupt for WKPU line
54+
*
55+
* @param dev WKPU device
56+
* @param line WKPU line
57+
*/
58+
void wkpu_nxp_s32_disable_interrupt(const struct device *dev, uint8_t line);
59+
60+
/**
61+
* @brief Get pending interrupt for WKPU device
62+
*
63+
* @param dev WKPU device
64+
* @return A mask contains pending flags
65+
*/
66+
uint64_t wkpu_nxp_s32_get_pending(const struct device *dev);
67+
68+
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_WKPU_NXP_S32_H_ */

0 commit comments

Comments
 (0)