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
wkpu_nxp_s32_set_callback(const struct device * dev,uint8_t line,wkpu_nxp_s32_callback_t cb,uint8_t pin,void * arg)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
wkpu_nxp_s32_unset_callback(const struct device * dev,uint8_t line)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
wkpu_nxp_s32_enable_interrupt(const struct device * dev,uint8_t line,Wkpu_Ip_EdgeType edge_type)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
wkpu_nxp_s32_disable_interrupt(const struct device * dev,uint8_t line)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
wkpu_nxp_s32_get_pending(const struct device * dev)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
wkpu_nxp_s32_callback(const struct device * dev,uint8 line)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
wkpu_nxp_s32_init(const struct device * dev)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)
195