Skip to content

Commit 6664953

Browse files
Dat-NguyenDuycfriedt
authored andcommitted
drivers: gpio: support GPIO input with interrupt for NXP S32Z27
Add support input interrupts for GPIO pins on NXP S32Z27 SoC. The driver will convert GPIO pin to respective interrupt line that will be processed by External Interrupt Controller. Signed-off-by: Dat Nguyen Duy <[email protected]>
1 parent 607358b commit 6664953

File tree

3 files changed

+210
-0
lines changed

3 files changed

+210
-0
lines changed

drivers/gpio/gpio_s32.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,38 @@
1212
#include <Siul2_Port_Ip.h>
1313
#include <Siul2_Dio_Ip.h>
1414

15+
#ifdef CONFIG_NXP_S32_EIRQ
16+
#include <zephyr/drivers/interrupt_controller/intc_eirq_nxp_s32.h>
17+
18+
struct eirq_nxp_s32_info {
19+
const struct device *eirq_dev;
20+
uint8_t num_lines;
21+
struct gpio_pin_line {
22+
uint8_t pin;
23+
uint8_t line;
24+
} gpio_pin_lines[];
25+
};
26+
#endif
27+
1528
struct gpio_s32_config {
1629
/* gpio_driver_config needs to be first */
1730
struct gpio_driver_config common;
1831

1932
Siul2_Dio_Ip_GpioType *gpio_base;
2033
Siul2_Port_Ip_PortType *port_base;
34+
35+
#ifdef CONFIG_NXP_S32_EIRQ
36+
struct eirq_nxp_s32_info *eirq_info;
37+
#endif
2138
};
2239

2340
struct gpio_s32_data {
2441
/* gpio_driver_data needs to be first */
2542
struct gpio_driver_data common;
43+
44+
#ifdef CONFIG_NXP_S32_EIRQ
45+
sys_slist_t callbacks;
46+
#endif
2647
};
2748

2849
static int s32_gpio_configure(const struct device *dev, gpio_pin_t pin,
@@ -131,34 +152,159 @@ static int s32_gpio_port_toggle_bits(const struct device *port,
131152
return 0;
132153
}
133154

155+
#ifdef CONFIG_NXP_S32_EIRQ
156+
157+
static uint8_t s32_gpio_pin_to_line(const struct eirq_nxp_s32_info *eirq_info, uint8_t pin)
158+
{
159+
uint8_t i;
160+
161+
for (i = 0; i < eirq_info->num_lines; i++) {
162+
if (eirq_info->gpio_pin_lines[i].pin == pin) {
163+
return eirq_info->gpio_pin_lines[i].line;
164+
}
165+
}
166+
167+
return SIUL2_ICU_IP_NUM_OF_CHANNELS;
168+
}
169+
170+
static int s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType *edge_type,
171+
enum gpio_int_mode mode,
172+
enum gpio_int_trig trigger)
173+
{
174+
if (mode == GPIO_INT_MODE_DISABLED) {
175+
*edge_type = SIUL2_ICU_DISABLE;
176+
return 0;
177+
}
178+
179+
if (mode == GPIO_INT_MODE_LEVEL) {
180+
return -ENOTSUP;
181+
}
182+
183+
switch (trigger) {
184+
case GPIO_INT_TRIG_LOW:
185+
*edge_type = SIUL2_ICU_FALLING_EDGE;
186+
break;
187+
case GPIO_INT_TRIG_HIGH:
188+
*edge_type = SIUL2_ICU_RISING_EDGE;
189+
break;
190+
case GPIO_INT_TRIG_BOTH:
191+
*edge_type = SIUL2_ICU_BOTH_EDGES;
192+
break;
193+
default:
194+
return -ENOTSUP;
195+
}
196+
197+
return 0;
198+
}
199+
200+
static void s32_gpio_isr(uint8_t pin, void *arg)
201+
{
202+
const struct device *dev = (struct device *)arg;
203+
struct gpio_s32_data *data = dev->data;
204+
205+
gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
206+
}
207+
#endif /* CONFIG_NXP_S32_EIRQ */
208+
134209
static int s32_gpio_pin_interrupt_configure(const struct device *dev,
135210
gpio_pin_t pin,
136211
enum gpio_int_mode mode,
137212
enum gpio_int_trig trig)
138213
{
214+
#ifdef CONFIG_NXP_S32_EIRQ
215+
const struct gpio_s32_config *config = dev->config;
216+
const struct eirq_nxp_s32_info *eirq_info = config->eirq_info;
217+
218+
uint8_t eirq_line;
219+
220+
Siul2_Icu_Ip_EdgeType edge_type;
221+
222+
if (eirq_info == NULL) {
223+
/*
224+
* There is no external interrupt device for
225+
* the GPIO port or exists but is not enabled
226+
*/
227+
return -ENOTSUP;
228+
}
229+
230+
eirq_line = s32_gpio_pin_to_line(eirq_info, pin);
231+
232+
if (eirq_line == SIUL2_ICU_IP_NUM_OF_CHANNELS) {
233+
/*
234+
* GPIO pin cannot be used for processing
235+
* external interrupt signal
236+
*/
237+
return -ENOTSUP;
238+
}
239+
240+
if (s32_gpio_eirq_get_trigger(&edge_type, mode, trig)) {
241+
return -ENOTSUP;
242+
}
243+
244+
if (edge_type == SIUL2_ICU_DISABLE) {
245+
eirq_nxp_s32_disable_interrupt(eirq_info->eirq_dev, eirq_line);
246+
eirq_nxp_s32_unset_callback(eirq_info->eirq_dev, eirq_line);
247+
} else {
248+
if (eirq_nxp_s32_set_callback(eirq_info->eirq_dev, eirq_line,
249+
s32_gpio_isr, pin, (void *)dev)) {
250+
return -EBUSY;
251+
}
252+
253+
eirq_nxp_s32_enable_interrupt(eirq_info->eirq_dev, eirq_line, edge_type);
254+
}
255+
256+
return 0;
257+
#else
139258
ARG_UNUSED(dev);
140259
ARG_UNUSED(pin);
141260
ARG_UNUSED(mode);
142261
ARG_UNUSED(trig);
143262

144263
return -ENOTSUP;
264+
#endif
145265
}
146266

147267
static int s32_gpio_manage_callback(const struct device *dev,
148268
struct gpio_callback *cb, bool set)
149269
{
270+
#ifdef CONFIG_NXP_S32_EIRQ
271+
struct gpio_s32_data *data = dev->data;
272+
273+
return gpio_manage_callback(&data->callbacks, cb, set);
274+
#else
150275
ARG_UNUSED(dev);
151276
ARG_UNUSED(cb);
152277
ARG_UNUSED(set);
153278

154279
return -ENOTSUP;
280+
#endif
155281
}
156282

157283
static uint32_t s32_gpio_get_pending_int(const struct device *dev)
158284
{
285+
#ifdef CONFIG_NXP_S32_EIRQ
286+
const struct gpio_s32_config *config = dev->config;
287+
const struct eirq_nxp_s32_info *eirq_info = config->eirq_info;
288+
289+
if (eirq_info == NULL) {
290+
/*
291+
* There is no external interrupt device for
292+
* the GPIO port or exists but is not enabled
293+
*/
294+
return 0;
295+
}
296+
297+
/*
298+
* Return all pending lines of the interrupt controller
299+
* that GPIO port belongs to
300+
*/
301+
return eirq_nxp_s32_get_pending(eirq_info->eirq_dev);
302+
303+
#else
159304
ARG_UNUSED(dev);
160305

161306
return -ENOTSUP;
307+
#endif
162308
}
163309

164310
static const struct gpio_driver_api gpio_s32_driver_api = {
@@ -204,13 +350,49 @@ static const struct gpio_driver_api gpio_s32_driver_api = {
204350
#define GPIO_S32_PORT_REG_ADDR(n) \
205351
((Siul2_Port_Ip_PortType *)DT_INST_REG_ADDR_BY_NAME(n, mscr))
206352

353+
#ifdef CONFIG_NXP_S32_EIRQ
354+
#define GPIO_S32_EIRQ_NODE(n) \
355+
DT_INST_PHANDLE(n, interrupt_parent)
356+
357+
#define GPIO_S32_EIRQ_PIN_LINE(idx, n) \
358+
{ \
359+
.pin = DT_INST_IRQ_BY_IDX(n, idx, gpio_pin), \
360+
.line = DT_INST_IRQ_BY_IDX(n, idx, eirq_line), \
361+
}
362+
363+
#define GPIO_S32_SET_EIRQ_INFO(n) \
364+
BUILD_ASSERT((DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupt_parent) == \
365+
DT_NODE_HAS_PROP(DT_DRV_INST(n), interrupts)), \
366+
"interrupts and interrupt-parent must be set when" \
367+
" using external interrupts"); \
368+
IF_ENABLED(DT_NODE_HAS_STATUS(GPIO_S32_EIRQ_NODE(n), okay), \
369+
(static struct eirq_nxp_s32_info eirq_nxp_s32_info_##n = { \
370+
.eirq_dev = DEVICE_DT_GET(GPIO_S32_EIRQ_NODE(n)), \
371+
.gpio_pin_lines = { \
372+
LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), \
373+
GPIO_S32_EIRQ_PIN_LINE, (,), n) \
374+
}, \
375+
.num_lines = DT_NUM_IRQS(DT_DRV_INST(n)) \
376+
}; \
377+
))
378+
379+
#define GPIO_S32_GET_EIRQ_INFO(n) \
380+
.eirq_info = UTIL_AND(DT_NODE_HAS_STATUS(GPIO_S32_EIRQ_NODE(n), okay), \
381+
&eirq_nxp_s32_info_##n)
382+
#else
383+
#define GPIO_S32_SET_EIRQ_INFO(n)
384+
#define GPIO_S32_GET_EIRQ_INFO(n)
385+
#endif /* CONFIG_NXP_S32_EIRQ */
386+
207387
#define GPIO_S32_DEVICE_INIT(n) \
388+
GPIO_S32_SET_EIRQ_INFO(n) \
208389
static const struct gpio_s32_config gpio_s32_config_##n = { \
209390
.common = { \
210391
.port_pin_mask = GPIO_S32_PORT_PIN_MASK(n), \
211392
}, \
212393
.gpio_base = GPIO_S32_REG_ADDR(n), \
213394
.port_base = GPIO_S32_PORT_REG_ADDR(n), \
395+
GPIO_S32_GET_EIRQ_INFO(n) \
214396
}; \
215397
static struct gpio_s32_data gpio_s32_data_##n; \
216398
static int gpio_s32_init_##n(const struct device *dev) \

dts/arm/nxp/nxp_s32z27x_r52.dtsi

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@
209209
compatible = "nxp,s32-gpio";
210210
reg = <0x40521702 0x02>, <0x40520240 0x40>;
211211
reg-names = "pgpdo", "mscr";
212+
interrupt-parent = <&eirq0>;
213+
interrupts = <1 1>, <3 0>, <5 2>, <12 3>,
214+
<13 4>, <14 5>, <15 6>;
212215
gpio-controller;
213216
#gpio-cells = <2>;
214217
ngpios = <16>;
@@ -219,6 +222,8 @@
219222
compatible = "nxp,s32-gpio";
220223
reg = <0x40521700 0x02>, <0x40520280 0x40>;
221224
reg-names = "pgpdo", "mscr";
225+
interrupt-parent = <&eirq0>;
226+
interrupts = <0 7>;
222227
gpio-controller;
223228
#gpio-cells = <2>;
224229
ngpios = <15>;
@@ -256,6 +261,8 @@
256261
compatible = "nxp,s32-gpio";
257262
reg = <0x40d21700 0x02>, <0x40d20280 0x40>;
258263
reg-names = "pgpdo", "mscr";
264+
interrupt-parent = <&eirq1>;
265+
interrupts = <3 0>, <5 1>;
259266
gpio-controller;
260267
#gpio-cells = <2>;
261268
ngpios = <16>;
@@ -297,6 +304,9 @@
297304
compatible = "nxp,s32-gpio";
298305
reg = <0x40d21708 0x02>, <0x40d20380 0x40>;
299306
reg-names = "pgpdo", "mscr";
307+
interrupt-parent = <&eirq1>;
308+
interrupts = <0 2>, <1 3>, <4 4>,
309+
<5 5>, <10 6>, <11 7>;
300310
gpio-controller;
301311
#gpio-cells = <2>;
302312
ngpios = <12>;
@@ -338,6 +348,8 @@
338348
compatible = "nxp,s32-gpio";
339349
reg = <0x4252170e 0x02>, <0x425203c0 0x40>;
340350
reg-names = "pgpdo", "mscr";
351+
interrupt-parent = <&eirq4>;
352+
interrupts = <11 0>, <13 1>;
341353
gpio-controller;
342354
#gpio-cells = <2>;
343355
ngpios = <16>;
@@ -348,6 +360,8 @@
348360
compatible = "nxp,s32-gpio";
349361
reg = <0x4252170c 0x02>, <0x42520400 0x40>;
350362
reg-names = "pgpdo", "mscr";
363+
interrupt-parent = <&eirq4>;
364+
interrupts = <12 2>;
351365
gpio-controller;
352366
#gpio-cells = <2>;
353367
ngpios = <16>;
@@ -358,6 +372,9 @@
358372
compatible = "nxp,s32-gpio";
359373
reg = <0x42521712 0x02>, <0x42520440 0x40>;
360374
reg-names = "pgpdo", "mscr";
375+
interrupt-parent = <&eirq4>;
376+
interrupts = <4 3>, <6 4>, <9 5>,
377+
<11 6>, <13 7>;
361378
gpio-controller;
362379
#gpio-cells = <2>;
363380
ngpios = <16>;
@@ -395,6 +412,8 @@
395412
compatible = "nxp,s32-gpio";
396413
reg = <0x42d21710 0x02>, <0x42d20480 0x40>;
397414
reg-names = "pgpdo", "mscr";
415+
interrupt-parent = <&eirq5>;
416+
interrupts = <1 0>, <3 1>, <5 2>, <7 3>;
398417
gpio-controller;
399418
#gpio-cells = <2>;
400419
ngpios = <16>;
@@ -406,6 +425,8 @@
406425
compatible = "nxp,s32-gpio";
407426
reg = <0x42d21716 0x02>, <0x42d204c0 0x40>;
408427
reg-names = "pgpdo", "mscr";
428+
interrupt-parent = <&eirq5>;
429+
interrupts = <0 4>, <2 5>, <5 6>, <6 7>;
409430
gpio-controller;
410431
#gpio-cells = <2>;
411432
ngpios = <10>;

dts/bindings/gpio/nxp,s32-gpio.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ properties:
1414
reg-names:
1515
required: true
1616

17+
interrupts:
18+
required: false
19+
description: |
20+
For GPIO ports that have pins can be used for processing
21+
external interrupt signal, this is a list of GPIO pins and
22+
respective external interrupt lines (<gpio-pin eirq-line>).
23+
1724
"#gpio-cells":
1825
const: 2
1926

0 commit comments

Comments
 (0)