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