1 /*
2 * Copyright (c) 2023 Antmicro <www.antmicro.com>
3 * Copyright (c) 2023 Ambiq Micro Inc. <www.ambiq.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT ambiq_gpio_bank
9
10 #include <errno.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/drivers/gpio/gpio_utils.h>
14 #include <zephyr/irq.h>
15 #include <zephyr/spinlock.h>
16
17 #include <am_mcu_apollo.h>
18
19 typedef void (*ambiq_gpio_cfg_func_t)(void);
20
21 struct ambiq_gpio_config {
22 struct gpio_driver_config common;
23 uint32_t base;
24 uint32_t offset;
25 uint32_t irq_num;
26 ambiq_gpio_cfg_func_t cfg_func;
27 uint8_t ngpios;
28 };
29
30 struct ambiq_gpio_data {
31 struct gpio_driver_data common;
32 sys_slist_t cb;
33 struct k_spinlock lock;
34 };
35
ambiq_gpio_pin_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)36 static int ambiq_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
37 {
38 const struct ambiq_gpio_config *const dev_cfg = dev->config;
39 int ret = 0;
40
41 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
42 pin += dev_cfg->offset;
43
44 am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT;
45
46 if (flags & GPIO_INPUT) {
47 pincfg = g_AM_HAL_GPIO_INPUT;
48 if (flags & GPIO_PULL_UP) {
49 pincfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
50 } else if (flags & GPIO_PULL_DOWN) {
51 pincfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN;
52 }
53 }
54 if (flags & GPIO_OUTPUT) {
55 if (flags & GPIO_SINGLE_ENDED) {
56 if (flags & GPIO_LINE_OPEN_DRAIN) {
57 pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
58 if (flags & GPIO_PULL_UP) {
59 pincfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
60 } else if (flags & GPIO_PULL_DOWN) {
61 pincfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN;
62 }
63 }
64 } else {
65 pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
66 }
67 }
68 if (flags & GPIO_DISCONNECTED) {
69 pincfg = g_AM_HAL_GPIO_DEFAULT;
70 }
71
72 if (flags & GPIO_OUTPUT_INIT_HIGH) {
73 pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH;
74 am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
75
76 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
77 pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
78 am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
79 }
80 #else
81 pin += (dev_cfg->offset >> 2);
82
83 am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default;
84
85 if (flags & GPIO_INPUT) {
86 pincfg = am_hal_gpio_pincfg_input;
87 if (flags & GPIO_PULL_UP) {
88 pincfg.GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLUP_50K;
89 } else if (flags & GPIO_PULL_DOWN) {
90 pincfg.GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLDOWN_50K;
91 }
92 }
93 if (flags & GPIO_OUTPUT) {
94 if (flags & GPIO_SINGLE_ENDED) {
95 if (flags & GPIO_LINE_OPEN_DRAIN) {
96 pincfg.GP.cfg_b.eGPOutCfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
97 if (flags & GPIO_PULL_UP) {
98 pincfg.GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLUP_50K;
99 } else if (flags & GPIO_PULL_DOWN) {
100 pincfg.GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLDOWN_50K;
101 }
102 }
103 } else {
104 pincfg.GP.cfg_b.eGPOutCfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL;
105 }
106 }
107 if (flags & GPIO_DISCONNECTED) {
108 pincfg = am_hal_gpio_pincfg_disabled;
109 }
110
111 if (flags & GPIO_OUTPUT_INIT_HIGH) {
112 pincfg.GP.cfg_b.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH;
113 am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET);
114
115 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
116 pincfg.GP.cfg_b.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW;
117 am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR);
118 }
119 #endif
120
121 if (am_hal_gpio_pinconfig(pin, pincfg) != AM_HAL_STATUS_SUCCESS) {
122 ret = -ENOTSUP;
123 }
124
125 return ret;
126 }
127
128 #ifdef CONFIG_GPIO_GET_CONFIG
ambiq_gpio_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * out_flags)129 static int ambiq_gpio_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *out_flags)
130 {
131 const struct ambiq_gpio_config *const dev_cfg = dev->config;
132 am_hal_gpio_pincfg_t pincfg;
133
134 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
135 pin += dev_cfg->offset;
136
137 am_hal_gpio_pinconfig_get(pin, &pincfg);
138
139 if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_DISABLE &&
140 pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_NONE) {
141 *out_flags = GPIO_DISCONNECTED;
142 }
143 if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) {
144 *out_flags = GPIO_INPUT;
145 if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_1_5K) {
146 *out_flags |= GPIO_PULL_UP;
147 } else if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN) {
148 *out_flags |= GPIO_PULL_DOWN;
149 }
150 }
151 if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) {
152 *out_flags = GPIO_OUTPUT | GPIO_PUSH_PULL;
153 if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) {
154 *out_flags |= GPIO_OUTPUT_HIGH;
155 } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) {
156 *out_flags |= GPIO_OUTPUT_LOW;
157 }
158 }
159 if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) {
160 *out_flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN;
161 if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) {
162 *out_flags |= GPIO_OUTPUT_HIGH;
163 } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) {
164 *out_flags |= GPIO_OUTPUT_LOW;
165 }
166 }
167 #else
168 pin += (dev_cfg->offset >> 2);
169
170 am_hal_gpio_pinconfig_get(pin, &pincfg);
171
172 if (pincfg.GP.cfg_b.eGPOutCfg == AM_HAL_GPIO_PIN_OUTCFG_DISABLE &&
173 pincfg.GP.cfg_b.eGPInput == AM_HAL_GPIO_PIN_INPUT_NONE) {
174 *out_flags = GPIO_DISCONNECTED;
175 }
176 if (pincfg.GP.cfg_b.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) {
177 *out_flags = GPIO_INPUT;
178 if (pincfg.GP.cfg_b.ePullup == AM_HAL_GPIO_PIN_PULLUP_50K) {
179 *out_flags |= GPIO_PULL_UP;
180 } else if (pincfg.GP.cfg_b.ePullup == AM_HAL_GPIO_PIN_PULLDOWN_50K) {
181 *out_flags |= GPIO_PULL_DOWN;
182 }
183 }
184 if (pincfg.GP.cfg_b.eGPOutCfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) {
185 *out_flags = GPIO_OUTPUT | GPIO_PUSH_PULL;
186 if (pincfg.GP.cfg_b.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) {
187 *out_flags |= GPIO_OUTPUT_HIGH;
188 } else if (pincfg.GP.cfg_b.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) {
189 *out_flags |= GPIO_OUTPUT_LOW;
190 }
191 }
192 if (pincfg.GP.cfg_b.eGPOutCfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) {
193 *out_flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN;
194 if (pincfg.GP.cfg_b.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) {
195 *out_flags |= GPIO_OUTPUT_HIGH;
196 } else if (pincfg.GP.cfg_b.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) {
197 *out_flags |= GPIO_OUTPUT_LOW;
198 }
199 }
200 #endif
201 return 0;
202 }
203 #endif
204
205 #ifdef CONFIG_GPIO_GET_DIRECTION
ambiq_gpio_port_get_direction(const struct device * dev,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)206 static int ambiq_gpio_port_get_direction(const struct device *dev, gpio_port_pins_t map,
207 gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
208 {
209 const struct ambiq_gpio_config *const dev_cfg = dev->config;
210 am_hal_gpio_pincfg_t pincfg;
211 gpio_port_pins_t ip = 0;
212 gpio_port_pins_t op = 0;
213 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
214 uint32_t pin_offset = dev_cfg->offset;
215
216 if (inputs != NULL) {
217 for (int i = 0; i < dev_cfg->ngpios; i++) {
218 if ((map >> i) & 1) {
219 am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg);
220 if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) {
221 ip |= BIT(i);
222 }
223 }
224 }
225 *inputs = ip;
226 }
227 if (outputs != NULL) {
228 for (int i = 0; i < dev_cfg->ngpios; i++) {
229 if ((map >> i) & 1) {
230 am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg);
231 if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ||
232 pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) {
233 op |= BIT(i);
234 }
235 }
236 }
237 *outputs = op;
238 }
239 #else
240 uint32_t pin_offset = dev_cfg->offset >> 2;
241
242 if (inputs != NULL) {
243 for (int i = 0; i < dev_cfg->ngpios; i++) {
244 if ((map >> i) & 1) {
245 am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg);
246 if (pincfg.GP.cfg_b.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) {
247 ip |= BIT(i);
248 }
249 }
250 }
251 *inputs = ip;
252 }
253 if (outputs != NULL) {
254 for (int i = 0; i < dev_cfg->ngpios; i++) {
255 if ((map >> i) & 1) {
256 am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg);
257 if (pincfg.GP.cfg_b.eGPOutCfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL ||
258 pincfg.GP.cfg_b.eGPOutCfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) {
259 op |= BIT(i);
260 }
261 }
262 }
263 *outputs = op;
264 }
265 #endif
266 return 0;
267 }
268 #endif
269
ambiq_gpio_port_get_raw(const struct device * dev,gpio_port_value_t * value)270 static int ambiq_gpio_port_get_raw(const struct device *dev, gpio_port_value_t *value)
271 {
272 const struct ambiq_gpio_config *const dev_cfg = dev->config;
273 uint32_t pin_offset;
274
275 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
276 pin_offset = dev_cfg->offset;
277 #else
278 pin_offset = dev_cfg->offset >> 2;
279 #endif
280 *value = (*AM_HAL_GPIO_RDn(pin_offset)) | (*AM_HAL_GPIO_WTn(pin_offset));
281
282 return 0;
283 }
284
ambiq_gpio_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)285 static int ambiq_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
286 gpio_port_value_t value)
287 {
288 const struct ambiq_gpio_config *const dev_cfg = dev->config;
289 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
290 uint32_t pin_offset = dev_cfg->offset;
291 #else
292 uint32_t pin_offset = dev_cfg->offset >> 2;
293 #endif
294 for (int i = 0; i < dev_cfg->ngpios; i++) {
295 if ((mask >> i) & 1) {
296 am_hal_gpio_state_write(i + pin_offset, ((value >> i) & 1));
297 }
298 }
299
300 return 0;
301 }
302
ambiq_gpio_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)303 static int ambiq_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
304 {
305 const struct ambiq_gpio_config *const dev_cfg = dev->config;
306 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
307 uint32_t pin_offset = dev_cfg->offset;
308 #else
309 uint32_t pin_offset = dev_cfg->offset >> 2;
310 #endif
311
312 for (int i = 0; i < dev_cfg->ngpios; i++) {
313 if ((pins >> i) & 1) {
314 am_hal_gpio_state_write(i + pin_offset, AM_HAL_GPIO_OUTPUT_SET);
315 }
316 }
317
318 return 0;
319 }
320
ambiq_gpio_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)321 static int ambiq_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
322 {
323 const struct ambiq_gpio_config *const dev_cfg = dev->config;
324 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
325 uint32_t pin_offset = dev_cfg->offset;
326 #else
327 uint32_t pin_offset = dev_cfg->offset >> 2;
328 #endif
329
330 for (int i = 0; i < dev_cfg->ngpios; i++) {
331 if ((pins >> i) & 1) {
332 am_hal_gpio_state_write(i + pin_offset, AM_HAL_GPIO_OUTPUT_CLEAR);
333 }
334 }
335
336 return 0;
337 }
338
ambiq_gpio_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)339 static int ambiq_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
340 {
341 const struct ambiq_gpio_config *const dev_cfg = dev->config;
342 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
343 uint32_t pin_offset = dev_cfg->offset;
344 #else
345 uint32_t pin_offset = dev_cfg->offset >> 2;
346 #endif
347
348 for (int i = 0; i < dev_cfg->ngpios; i++) {
349 if ((pins >> i) & 1) {
350 am_hal_gpio_state_write(i + pin_offset, AM_HAL_GPIO_OUTPUT_TOGGLE);
351 }
352 }
353
354 return 0;
355 }
356
357 #define APOLLO3_HANDLE_SHARED_GPIO_IRQ(n) \
358 static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \
359 const struct ambiq_gpio_config *cfg_##n = dev_##n->config; \
360 struct ambiq_gpio_data *const data_##n = dev_##n->data; \
361 uint32_t status_##n = (uint32_t)(ui64Status >> cfg_##n->offset); \
362 if (status_##n) { \
363 gpio_fire_callbacks(&data_##n->cb, dev_##n, status_##n); \
364 }
365
366 #define APOLLO3P_HANDLE_SHARED_GPIO_IRQ(n) \
367 static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \
368 struct ambiq_gpio_data *const data_##n = dev_##n->data; \
369 if (pGpioIntStatusMask->U.Msk[n]) { \
370 gpio_fire_callbacks(&data_##n->cb, dev_##n, pGpioIntStatusMask->U.Msk[n]); \
371 }
372
ambiq_gpio_isr(const struct device * dev)373 static void ambiq_gpio_isr(const struct device *dev)
374 {
375 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
376 ARG_UNUSED(dev);
377
378 #if defined(CONFIG_SOC_APOLLO3_BLUE)
379 uint64_t ui64Status;
380
381 am_hal_gpio_interrupt_status_get(false, &ui64Status);
382 am_hal_gpio_interrupt_clear(ui64Status);
383 DT_INST_FOREACH_STATUS_OKAY(APOLLO3_HANDLE_SHARED_GPIO_IRQ)
384 #elif defined(CONFIG_SOC_APOLLO3P_BLUE)
385 AM_HAL_GPIO_MASKCREATE(GpioIntStatusMask);
386 am_hal_gpio_interrupt_status_get(false, pGpioIntStatusMask);
387 am_hal_gpio_interrupt_clear(pGpioIntStatusMask);
388 DT_INST_FOREACH_STATUS_OKAY(APOLLO3P_HANDLE_SHARED_GPIO_IRQ)
389 #endif
390 #else
391 uint32_t int_status;
392 struct ambiq_gpio_data *const data = dev->data;
393 const struct ambiq_gpio_config *const dev_cfg = dev->config;
394
395 am_hal_gpio_interrupt_irq_status_get(dev_cfg->irq_num, false, &int_status);
396 am_hal_gpio_interrupt_irq_clear(dev_cfg->irq_num, int_status);
397
398 gpio_fire_callbacks(&data->cb, dev, int_status);
399 #endif
400 }
401
ambiq_gpio_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)402 static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
403 enum gpio_int_mode mode, enum gpio_int_trig trig)
404 {
405 const struct ambiq_gpio_config *const dev_cfg = dev->config;
406 struct ambiq_gpio_data *const data = dev->data;
407
408 int ret = 0;
409 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
410 am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT;
411 int gpio_pin = pin + dev_cfg->offset;
412
413 ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg);
414
415 if (mode == GPIO_INT_MODE_DISABLED) {
416 pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE;
417 ret = am_hal_gpio_pinconfig(gpio_pin, pincfg);
418
419 k_spinlock_key_t key = k_spin_lock(&data->lock);
420
421 AM_HAL_GPIO_MASKCREATE(GpioIntMask);
422 ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin));
423 ret = am_hal_gpio_interrupt_disable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin));
424 k_spin_unlock(&data->lock, key);
425
426 } else {
427 if (mode == GPIO_INT_MODE_LEVEL) {
428 return -ENOTSUP;
429 }
430 switch (trig) {
431 case GPIO_INT_TRIG_LOW:
432 pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_HI2LO;
433 break;
434 case GPIO_INT_TRIG_HIGH:
435 pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
436 break;
437 case GPIO_INT_TRIG_BOTH:
438 pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH;
439 break;
440 default:
441 pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE;
442 break;
443 }
444 ret = am_hal_gpio_pinconfig(gpio_pin, pincfg);
445
446 irq_enable(dev_cfg->irq_num);
447
448 k_spinlock_key_t key = k_spin_lock(&data->lock);
449
450 AM_HAL_GPIO_MASKCREATE(GpioIntMask);
451 ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin));
452 ret = am_hal_gpio_interrupt_enable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin));
453 k_spin_unlock(&data->lock, key);
454 }
455 #else
456 am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default;
457 int gpio_pin = pin + (dev_cfg->offset >> 2);
458 uint32_t int_status;
459
460 ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg);
461
462 if (mode == GPIO_INT_MODE_DISABLED) {
463 pincfg.GP.cfg_b.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE;
464 ret = am_hal_gpio_pinconfig(gpio_pin, pincfg);
465
466 k_spinlock_key_t key = k_spin_lock(&data->lock);
467
468 ret = am_hal_gpio_interrupt_irq_status_get(dev_cfg->irq_num, false, &int_status);
469 ret = am_hal_gpio_interrupt_irq_clear(dev_cfg->irq_num, int_status);
470 ret = am_hal_gpio_interrupt_control(AM_HAL_GPIO_INT_CHANNEL_0,
471 AM_HAL_GPIO_INT_CTRL_INDV_DISABLE,
472 (void *)&gpio_pin);
473 k_spin_unlock(&data->lock, key);
474
475 } else {
476 if (mode == GPIO_INT_MODE_LEVEL) {
477 return -ENOTSUP;
478 }
479 switch (trig) {
480 case GPIO_INT_TRIG_LOW:
481 pincfg.GP.cfg_b.eIntDir = AM_HAL_GPIO_PIN_INTDIR_HI2LO;
482 break;
483 case GPIO_INT_TRIG_HIGH:
484 pincfg.GP.cfg_b.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI;
485 break;
486 case GPIO_INT_TRIG_BOTH:
487 /*
488 * GPIO_INT_TRIG_BOTH is not supported on Ambiq Apollo4 Plus Platform
489 * ERR008: GPIO: Dual-edge interrupts are not vectoring
490 */
491 return -ENOTSUP;
492 default:
493 return -EINVAL;
494 }
495 ret = am_hal_gpio_pinconfig(gpio_pin, pincfg);
496
497 irq_enable(dev_cfg->irq_num);
498
499 k_spinlock_key_t key = k_spin_lock(&data->lock);
500
501 ret = am_hal_gpio_interrupt_irq_status_get(dev_cfg->irq_num, false, &int_status);
502 ret = am_hal_gpio_interrupt_irq_clear(dev_cfg->irq_num, int_status);
503 ret = am_hal_gpio_interrupt_control(AM_HAL_GPIO_INT_CHANNEL_0,
504 AM_HAL_GPIO_INT_CTRL_INDV_ENABLE,
505 (void *)&gpio_pin);
506 k_spin_unlock(&data->lock, key);
507 }
508 #endif
509 return ret;
510 }
511
ambiq_gpio_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)512 static int ambiq_gpio_manage_callback(const struct device *dev, struct gpio_callback *callback,
513 bool set)
514 {
515 struct ambiq_gpio_data *const data = dev->data;
516
517 return gpio_manage_callback(&data->cb, callback, set);
518 }
519
520 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
ambiq_gpio_cfg_func(void)521 static void ambiq_gpio_cfg_func(void)
522 {
523 /* Apollo3 GPIO banks share the same irq number, connect to bank0 once when init and handle
524 * different banks in ambiq_gpio_isr
525 */
526 static bool global_irq_init = true;
527
528 if (!global_irq_init) {
529 return;
530 }
531
532 global_irq_init = false;
533
534 /* Shared irq config default to BANK0. */
535 IRQ_CONNECT(GPIO_IRQn, DT_INST_IRQ(0, priority), ambiq_gpio_isr, DEVICE_DT_INST_GET(0), 0);
536 }
537 #endif
538
ambiq_gpio_init(const struct device * port)539 static int ambiq_gpio_init(const struct device *port)
540 {
541 const struct ambiq_gpio_config *const dev_cfg = port->config;
542
543 NVIC_ClearPendingIRQ(dev_cfg->irq_num);
544
545 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
546 ambiq_gpio_cfg_func();
547 #else
548 dev_cfg->cfg_func();
549 #endif
550 return 0;
551 }
552
553 static DEVICE_API(gpio, ambiq_gpio_drv_api) = {
554 .pin_configure = ambiq_gpio_pin_configure,
555 #ifdef CONFIG_GPIO_GET_CONFIG
556 .pin_get_config = ambiq_gpio_get_config,
557 #endif
558 .port_get_raw = ambiq_gpio_port_get_raw,
559 .port_set_masked_raw = ambiq_gpio_port_set_masked_raw,
560 .port_set_bits_raw = ambiq_gpio_port_set_bits_raw,
561 .port_clear_bits_raw = ambiq_gpio_port_clear_bits_raw,
562 .port_toggle_bits = ambiq_gpio_port_toggle_bits,
563 .pin_interrupt_configure = ambiq_gpio_pin_interrupt_configure,
564 .manage_callback = ambiq_gpio_manage_callback,
565 #ifdef CONFIG_GPIO_GET_DIRECTION
566 .port_get_direction = ambiq_gpio_port_get_direction,
567 #endif
568 };
569
570 #if defined(CONFIG_SOC_SERIES_APOLLO3X)
571 /* Apollo3 GPIO banks share the same irq number, connect irq here will cause build error, so we
572 * leave this function blank here and do it in ambiq_gpio_cfg_func
573 */
574 #define AMBIQ_GPIO_CONFIG_FUNC(n) static void ambiq_gpio_cfg_func_##n(void){};
575 #else
576 #define AMBIQ_GPIO_CONFIG_FUNC(n) \
577 static void ambiq_gpio_cfg_func_##n(void) \
578 { \
579 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), ambiq_gpio_isr, \
580 DEVICE_DT_INST_GET(n), 0); \
581 \
582 return; \
583 };
584 #endif
585
586 #define AMBIQ_GPIO_DEFINE(n) \
587 static struct ambiq_gpio_data ambiq_gpio_data_##n; \
588 static void ambiq_gpio_cfg_func_##n(void); \
589 static const struct ambiq_gpio_config ambiq_gpio_config_##n = { \
590 .common = \
591 { \
592 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
593 }, \
594 .base = DT_REG_ADDR(DT_INST_PARENT(n)), \
595 .offset = DT_INST_REG_ADDR(n), \
596 .ngpios = DT_INST_PROP(n, ngpios), \
597 .irq_num = DT_INST_IRQN(n), \
598 .cfg_func = ambiq_gpio_cfg_func_##n}; \
599 AMBIQ_GPIO_CONFIG_FUNC(n) \
600 DEVICE_DT_INST_DEFINE(n, ambiq_gpio_init, NULL, &ambiq_gpio_data_##n, \
601 &ambiq_gpio_config_##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \
602 &ambiq_gpio_drv_api);
603
604 DT_INST_FOREACH_STATUS_OKAY(AMBIQ_GPIO_DEFINE)
605