1 /**
2  * \file
3  *
4  * \brief SAM GPIO Driver for SAMB11
5  *
6  * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46 #include <gpio.h>
47 
48 /**
49  * \internal
50  * Internal driver device instance struct.
51  */
52 struct gpio_module _gpio_instances[3];
53 static void (*aon_handle_ext_wakeup_isr)(void) = (void (*)(void))0x1bc51;
54 
55 /**
56  *  \brief Initializes a gpio pin/group configuration structure to defaults.
57  *
58  *  Initializes a given gpio pin/group configuration structure to a set of
59  *  known default values. This function should be called on all new
60  *  instances of these configuration structures before being modified by the
61  *  user application.
62  *
63  *  The default configuration is as follows:
64  *   \li Input mode with internal pullup enabled
65  *
66  *  \param[out] config  Configuration structure to initialize to default values.
67  */
gpio_get_config_defaults(struct gpio_config * const config)68 void gpio_get_config_defaults(struct gpio_config *const config)
69 {
70 	/* Default configuration values */
71 	config->direction  = GPIO_PIN_DIR_INPUT;
72 	config->input_pull = GPIO_PIN_PULL_UP;
73 	config->powersave  = false;
74 	config->aon_wakeup = false;
75 }
76 
77 /**
78  *  \brief Writes a gpio pin configuration to the hardware module.
79  *
80  *  Writes out a given configuration of a gpio pin configuration to the hardware
81  *  module. If the configuration is NULL then it releases the gpio pin.
82  *
83  *  \note If the pin direction is set as an output, the pull-up/pull-down input
84  *        configuration setting is ignored. Also certain gpio pin is used by
85  *        FW and not available for user application. Please \ref gpio_pin
86  *        for list of gpio_pin available.
87  *
88  *  \param[in] gpio_pin  Index of the GPIO pin to configure.
89  *  \param[in] config    Configuration settings for the pin.
90  *
91  *  \return Status of initialization.
92  *  \retval STATUS_OK                       gpio configured correctly
93  *  \retval STATUS_ERR_INVALID_ARG          Invalid gpio number, Certain gpios
94  *                                          are used by FW and not allowed to change.
95  *  \retval STATUS_RESOURCE_NOT_AVAILABLE   Requested gpio is already in use.
96  *
97  */
gpio_pin_set_config(const uint8_t gpio_pin,const struct gpio_config * config)98 enum status_code gpio_pin_set_config(const uint8_t gpio_pin,
99 		const struct gpio_config *config)
100 {
101 	enum status_code status = STATUS_OK;
102 
103 	/* Following GPIO's should never be modified by user.
104 	* GPIO_0 & GPIO_1 are used for SWD.
105 	*/
106 	if ((gpio_pin == PIN_LP_GPIO_0) || \
107 		(gpio_pin == PIN_LP_GPIO_1))
108 	{
109 		status = STATUS_ERR_INVALID_ARG;
110 	} else {
111 		if (gpio_pin <= 7) {
112 			LPMCU_MISC_REGS0->PINMUX_SEL_0.reg &= ~(7 << ((gpio_pin % 8) * 4));
113 		} else if (gpio_pin <= 15) {
114 			LPMCU_MISC_REGS0->PINMUX_SEL_1.reg &= ~(7 << ((gpio_pin % 8) * 4));
115 		} else if (gpio_pin <= 23) {
116 			LPMCU_MISC_REGS0->PINMUX_SEL_2.reg &= ~(7 << ((gpio_pin % 8) * 4));
117 		} else if (44 <= gpio_pin  && gpio_pin < 48) {
118 			/* Set GPIO_MSx as digital mode */
119 			AON_GP_REGS0->MS_GPIO_MODE.vec.ANALOG_ENABLE_ &= ~(1 << (gpio_pin - PIN_GPIO_MS4));
120 		}
121 
122 		if ((gpio_pin == PIN_AO_GPIO_0) || (gpio_pin == PIN_AO_GPIO_1) ||
123 				(gpio_pin == PIN_AO_GPIO_2)) {
124 			/* Active Low, Always On Pull Enable Control */
125 			if (config->input_pull == GPIO_PIN_PULL_UP) {
126 				AON_GP_REGS0->AON_PULL_ENABLE.reg &= ~(1 << (31 - gpio_pin));
127 			} else {
128 				AON_GP_REGS0->AON_PULL_ENABLE.reg |= 1 << (31 - gpio_pin);
129 			}
130 			if (config->aon_wakeup) {
131 				/* Enable AON_GPIO_x to be a wakeup MCU from sleep mode */
132 				AON_GP_REGS0->AON_PINMUX_SEL.reg |= 1 << (4 * (31 - gpio_pin));
133 				/* Enable AON_GPIO_x to wake up the BLE domain from sleep mode */
134 				AON_PWR_SEQ0->GPIO_WAKEUP_CTRL.bit.BLE_ENABLE = 1;
135 			}
136 		} else {
137 			if(config->direction == GPIO_PIN_DIR_INPUT) {
138 				if(gpio_pin < 16) {
139 					GPIO0->OUTENCLR.reg = (1 << gpio_pin);
140 				} else if (gpio_pin < 32){
141 					GPIO1->OUTENCLR.reg = (1 << (gpio_pin % 16));
142 				} else {
143 					GPIO2->OUTENCLR.reg = (1 << (gpio_pin % 16));
144 				}
145 				/* pull_enable. */
146 				if (gpio_pin < 32) {
147 					switch(config->input_pull) {
148 						case GPIO_PIN_PULL_NONE:
149 							LPMCU_MISC_REGS0->PULL_ENABLE.reg |= (1 << gpio_pin);
150 							break;
151 						case GPIO_PIN_PULL_UP:
152 							LPMCU_MISC_REGS0->PULL_ENABLE.reg &= ~(1 << gpio_pin);
153 							break;
154 						case GPIO_PIN_PULL_DOWN:
155 							/* Set R-Type */
156 							LPMCU_MISC_REGS0->RTYPE_PAD_0.reg |= (1 << gpio_pin);
157 							/* Set REN */
158 							LPMCU_MISC_REGS0->PULL_ENABLE.reg &= ~(1 << gpio_pin);
159 							break;
160 						default:
161 							status = STATUS_ERR_INVALID_ARG;
162 							break;
163 					}
164 				}
165 			} else if(config->direction == GPIO_PIN_DIR_OUTPUT) {
166 				if (gpio_pin < 16) {
167 					GPIO0->OUTENSET.reg = (1 << gpio_pin);
168 				} else if (gpio_pin < 32) {
169 					GPIO1->OUTENSET.reg = (1 << (gpio_pin % 16));
170 				} else {
171 					GPIO2->OUTENSET.reg = (1 << (gpio_pin % 16));
172 				}
173 			}
174 		}
175 	}
176 	return status;
177 }
178 
179 /**
180  *  \brief Retrieves the state of a gpio pin that is configured as an input.
181  *
182  *  Reads the current logic level of a gpio pin and returns the current
183  *  level as a boolean value.
184  *
185  *  \param[in] gpio_pin  Index of the GPIO pin to read.
186  *
187  *  \return Status of the gpio pin's input buffer.
188  */
gpio_pin_get_input_level(const uint8_t gpio_pin)189 bool gpio_pin_get_input_level(const uint8_t gpio_pin)
190 {
191 	uint32_t regval = 0;
192 
193 	if (gpio_pin < 16) {
194 		regval = GPIO0->DATA.reg;
195 		regval &= (1 << gpio_pin);
196 	} else if (gpio_pin < 32) {
197 		regval = GPIO1->DATA.reg;
198 		regval &= (1 << (gpio_pin % 16));
199 	} else {
200 		regval = GPIO2->DATA.reg;
201 		regval &= (1 << (gpio_pin % 16));
202 	}
203 
204 	return regval;
205 }
206 
207 /**
208  *  \brief Retrieves the state of a gpio pin that is configured as an output.
209  *
210  *  Reads the current logical output level of a gpio pin and returns the current
211  *  level as a boolean value.
212  *
213  *  \param[in] gpio_pin  Index of the GPIO pin to read.
214  *
215  *  \return Status of the gpio pin's output buffer.
216  */
gpio_pin_get_output_level(const uint8_t gpio_pin)217 bool gpio_pin_get_output_level(const uint8_t gpio_pin)
218 {
219 	uint32_t regval = 0;
220 
221 	if (gpio_pin < 16) {
222 		regval = GPIO0->DATAOUT.reg;
223 		regval &= (1 << gpio_pin);
224 	} else if (gpio_pin < 32) {
225 		regval = GPIO1->DATAOUT.reg;
226 		regval &= (1 << (gpio_pin % 16));
227 	} else {
228 		regval = GPIO2->DATAOUT.reg;
229 		regval &= (1 << (gpio_pin % 16));
230 	}
231 
232 	return regval;
233 }
234 
235 /**
236  *  \brief Sets the state of a gpio pin that is configured as an output.
237  *
238  *  Sets the current output level of a gpio pin to a given logic level.
239  *
240  *  \param[in] gpio_pin  Index of the GPIO pin to write to.
241  *  \param[in] level     Logical level to set the given pin to.
242  */
gpio_pin_set_output_level(const uint8_t gpio_pin,const bool level)243 void gpio_pin_set_output_level(const uint8_t gpio_pin, const bool level)
244 {
245 	if (gpio_pin < 16) {
246 		if(level) {
247 			GPIO0->DATAOUT.reg |= (1 << gpio_pin);
248 		} else {
249 			GPIO0->DATAOUT.reg &= ~(1 << gpio_pin);
250 		}
251 	} else if (gpio_pin < 32) {
252 		if(level) {
253 			GPIO1->DATAOUT.reg |= (1 << (gpio_pin % 16));
254 		} else {
255 			GPIO1->DATAOUT.reg &= ~(1 << (gpio_pin % 16));
256 		}
257 	} else {
258 		if(level) {
259 			GPIO2->DATAOUT.reg |= (1 << (gpio_pin % 16));
260 		} else {
261 			GPIO2->DATAOUT.reg &= ~(1 << (gpio_pin % 16));
262 		}
263 	}
264 }
265 
266 /**
267  *  \brief Toggles the state of a gpio pin that is configured as an output.
268  *
269  *  Toggles the current output level of a gpio pin.
270  *
271  *  \param[in] gpio_pin  Index of the GPIO pin to toggle.
272  */
gpio_pin_toggle_output_level(const uint8_t gpio_pin)273 void gpio_pin_toggle_output_level(const uint8_t gpio_pin)
274 {
275 	if (gpio_pin < 16) {
276 		GPIO0->DATAOUT.reg ^= (1 << gpio_pin);
277 	} else if (gpio_pin < 32) {
278 		GPIO1->DATAOUT.reg ^= (1 << (gpio_pin % 16));
279 	} else {
280 		GPIO2->DATAOUT.reg ^= (1 << (gpio_pin % 16));
281 	}
282 }
283 
284 /**
285  *  \brief Writes a GPIO pin configuration to the hardware module.
286  *
287  *  Writes out a given configuration of a GPIO pin configuration to the hardware
288  *  module.
289  *
290  *  \param[in] gpio_pin   Index of the GPIO pin to toggle.
291  *  \param[in] pinmux_sel PINMUX selection.
292  */
gpio_pinmux_cofiguration(const uint8_t gpio_pin,uint16_t pinmux_sel)293 void gpio_pinmux_cofiguration(const uint8_t gpio_pin, uint16_t pinmux_sel)
294 {
295 	uint8_t megamux_sel = (pinmux_sel >> 8) & 0xFF;
296 
297 	pinmux_sel &= 0xFF;
298 
299 	if (gpio_pin <= 7) {
300 		LPMCU_MISC_REGS0->PINMUX_SEL_0.reg &= ~(7 << ((gpio_pin % 8) * 4));
301 		LPMCU_MISC_REGS0->PINMUX_SEL_0.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
302 		if (pinmux_sel == 0x01) {
303 			if (gpio_pin <= 3) {
304 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_0.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
305 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_0.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
306 			} else if (gpio_pin <= 7) {
307 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_1.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
308 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_1.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
309 			}
310 		}
311 	} else if (gpio_pin <= 15) {
312 		LPMCU_MISC_REGS0->PINMUX_SEL_1.reg &= ~(7 << ((gpio_pin % 8) * 4));
313 		LPMCU_MISC_REGS0->PINMUX_SEL_1.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
314 		if (pinmux_sel == 0x01) {
315 			if (gpio_pin <= 11) {
316 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_2.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
317 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_2.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
318 			} else if (gpio_pin <= 15) {
319 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_3.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
320 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_3.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
321 			}
322 		}
323 	} else if (gpio_pin <= 23) {
324 		LPMCU_MISC_REGS0->PINMUX_SEL_2.reg &= ~(7 << ((gpio_pin % 8) * 4));
325 		LPMCU_MISC_REGS0->PINMUX_SEL_2.reg |= (pinmux_sel << ((gpio_pin % 8)*4));
326 		if (pinmux_sel == 0x01) {
327 			if (gpio_pin <= 19) {
328 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_4.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
329 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_4.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
330 			} else if (gpio_pin <= 23) {
331 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_5.reg &= ~(0x3F << ((gpio_pin % 4) * 8));
332 				LPMCU_MISC_REGS0->MEGA_MUX_IO_SEL_5.reg |= (megamux_sel << ((gpio_pin % 4) * 8));
333 			}
334 		}
335 	}
336 }
337 
338 /**
339  * \brief Registers a callback
340  *
341  * Registers a callback function which is implemented by the user.
342  *
343  * \note The callback must be enabled by \ref gpio_enable_callback,
344  *       in order for the interrupt handler to call it when the conditions for
345  *       the callback type are met.
346  *
347  * \param[in]  gpio_pin       GPIO pin number
348  * \param[in]  callback_func  Pointer to callback function
349  * \param[in]  callback_type  Callback type given by an enum
350  *
351  */
gpio_register_callback(uint8_t gpio_pin,gpio_callback_t callback_func,enum gpio_callback callback_type)352 void gpio_register_callback(uint8_t gpio_pin, gpio_callback_t callback_func,
353 				enum gpio_callback callback_type)
354 {
355 	/* Sanity check arguments */
356 	Assert(callback_func);
357 	Assert(gpio_pin < 48);
358 
359 	uint8_t gpio_port = 0;
360 
361 	if (gpio_pin < 16) {
362 		gpio_port = 0;
363 	} else if (gpio_pin < 32) {
364 		gpio_port = 1;
365 	} else {
366 		gpio_port = 2;
367 	}
368 	switch (callback_type) {
369 	case GPIO_CALLBACK_LOW:
370 		_gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
371 		_gpio_instances[gpio_port].hw->INTPOLCLR.reg = 1 << (gpio_pin % 16);
372 		break;
373 
374 	case GPIO_CALLBACK_HIGH:
375 		_gpio_instances[gpio_port].hw->INTTYPECLR.reg = 1 << (gpio_pin % 16);
376 		_gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
377 		break;
378 
379 	case GPIO_CALLBACK_RISING:
380 		_gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
381 		_gpio_instances[gpio_port].hw->INTPOLSET.reg = 1 << (gpio_pin % 16);
382 		break;
383 
384 	case GPIO_CALLBACK_FALLING:
385 		_gpio_instances[gpio_port].hw->INTTYPESET.reg = 1 << (gpio_pin % 16);
386 		_gpio_instances[gpio_port].hw->INTPOLCLR.reg = (1 << (gpio_pin % 16));
387 		break;
388 
389 	case GPIO_CALLBACK_N:
390 		break;
391 	}
392 	/* Register callback function */
393 	_gpio_instances[gpio_port].callback[gpio_pin % 16] = callback_func;
394 	/* Set the bit corresponding to the gpio pin */
395 	_gpio_instances[gpio_port].callback_reg_mask |= (1 << (gpio_pin % 16));
396 }
397 
398 /**
399  * \brief Unregisters a callback
400  *
401  * Unregisters a callback function which is implemented by the user.
402  *
403  *
404  * \param[in]  gpio_pin       GPIO pin number
405  * \param[in]  callback_type  Callback type given by an enum
406  *
407  */
gpio_unregister_callback(uint8_t gpio_pin,enum gpio_callback callback_type)408 void gpio_unregister_callback(uint8_t gpio_pin,
409 				enum gpio_callback callback_type)
410 {
411 	/* Sanity check arguments */
412 	Assert(callback_func);
413 	Assert(gpio_pin < 48);
414 
415 	uint8_t gpio_port = 0;
416 
417 	if (gpio_pin < 16) {
418 		gpio_port = 0;
419 	} else if (gpio_pin < 32) {
420 		gpio_port = 1;
421 	} else {
422 		gpio_port = 2;
423 	}
424 
425 	/* Unregister callback function */
426 	_gpio_instances[gpio_port].callback[gpio_pin % 16] = NULL;
427 	/* Set the bit corresponding to the gpio pin */
428 	_gpio_instances[gpio_port].callback_reg_mask &= ~(1 << (gpio_pin % 16));
429 }
430 
431 /**
432  * \brief Enables callback
433  *
434  * Enables the callback function registered by the \ref gpio_register_callback.
435  * The callback function will be called from the interrupt handler when the
436  * conditions for the callback type are met.
437  *
438  * \param[in]  gpio_pin   GPIO pin
439  */
gpio_enable_callback(uint8_t gpio_pin)440 void gpio_enable_callback(uint8_t gpio_pin)
441 {
442 	Assert(gpio_pin < 48);
443 
444 	uint8_t gpio_port = 0;
445 
446 	if (gpio_pin < 16) {
447 		gpio_port = 0;
448 		NVIC_EnableIRQ(GPIO0_IRQn);
449 	} else if (gpio_pin < 32) {
450 		gpio_port = 1;
451 		NVIC_EnableIRQ(GPIO1_IRQn);
452 	} else {
453 		gpio_port = 2;
454 		NVIC_EnableIRQ(GPIO2_IRQn);
455 	}
456 
457 	/* Enable callback */
458 	_gpio_instances[gpio_port].callback_enable_mask |= (1 << (gpio_pin % 16));
459 	_gpio_instances[gpio_port].hw->INTENSET.reg = (1 << (gpio_pin % 16));
460 }
461 
462 /**
463  * \brief Disables callback
464  *
465  * Disables the callback function registered by the \ref usart_register_callback.
466  * The callback function will not be called from the interrupt handler.
467  *
468  * \param[in]  gpio_pin   GPIO pin
469  */
gpio_disable_callback(uint8_t gpio_pin)470 void gpio_disable_callback(uint8_t gpio_pin)
471 {
472 	Assert(gpio_pin < 48);
473 
474 	uint8_t gpio_port = 0;
475 
476 	if (gpio_pin < 16) {
477 		gpio_port = 0;
478 	} else if (gpio_pin < 32) {
479 		gpio_port = 1;
480 	} else {
481 		gpio_port = 2;
482 	}
483 
484 	/* Enable callback */
485 	_gpio_instances[gpio_port].callback_enable_mask &= ~(1 << (gpio_pin % 16));
486 	_gpio_instances[gpio_port].hw->INTENCLR.reg = (1 << (gpio_pin % 16));
487 }
488 
489 /**
490  * \internal GPIO port0 isr handler.
491  *
492  * This function will enter interrupt.
493  *
494  */
gpio_port0_isr_handler(void)495 static void gpio_port0_isr_handler(void)
496 {
497 	uint32_t flag = _gpio_instances[0].hw->INTSTATUSCLEAR.reg;
498 
499 	for (uint8_t i = 0; i < 16; i++){
500 		if (flag & (1 << i)) {
501 			/* Clear interrupt flag */
502 			_gpio_instances[0].hw->INTSTATUSCLEAR.reg = (1 << i);
503 			if ((_gpio_instances[0].callback_enable_mask & (1 << i)) && \
504                     (_gpio_instances[0].callback_reg_mask & (1 << i)))
505                 _gpio_instances[0].callback[i]();
506 			break;
507 		}
508 	}
509 	NVIC_ClearPendingIRQ(GPIO0_IRQn);
510 }
511 
512 /**
513  * \internal GPIO port1 isr handler.
514  *
515  * This function will enter interrupt.
516  *
517  */
gpio_port1_isr_handler(void)518 static void gpio_port1_isr_handler(void)
519 {
520 	uint32_t flag = _gpio_instances[1].hw->INTSTATUSCLEAR.reg;
521 
522 	for (uint8_t i = 0; i < 16; i++){
523 		/* For AON wakeup pin clear interrupt */
524 		if (flag & ((1<<15) | (1<<14) | (1<<13))) {
525 			aon_handle_ext_wakeup_isr();
526 		}
527 
528 		if (flag & (1 << i)) {
529 			/* Clear interrupt flag */
530 			_gpio_instances[1].hw->INTSTATUSCLEAR.reg = (1 << i);
531 			if ((_gpio_instances[1].callback_enable_mask & (1 << i)) && \
532 			(_gpio_instances[1].callback_reg_mask & (1 << i))) {
533 				_gpio_instances[1].callback[i]();
534 				break;
535 			}
536 		}
537 	}
538 	NVIC_ClearPendingIRQ(GPIO1_IRQn);
539 }
540 
541 /**
542  * \internal GPIO port2 isr handler.
543  *
544  * This function will enter interrupt.
545  *
546  */
gpio_port2_isr_handler(void)547 static void gpio_port2_isr_handler(void)
548 {
549 	uint32_t flag = _gpio_instances[2].hw->INTSTATUSCLEAR.reg;
550 
551 	for (uint8_t i = 12; i < 16; i++){
552 		if (flag & (1 << i)) {
553 			/* Clear interrupt flag */
554 			_gpio_instances[2].hw->INTSTATUSCLEAR.reg = (1 << i);
555 			if ((_gpio_instances[2].callback_enable_mask & (1 << i)) && \
556                     (_gpio_instances[2].callback_reg_mask & (1 << i)))
557                 _gpio_instances[2].callback[i]();
558 			break;
559 		}
560 	}
561 	NVIC_ClearPendingIRQ(GPIO2_IRQn);
562 }
563 
564 /**
565  * \internal GPIO callback init.
566  *
567  * This function will init GPIO callback.
568  *
569  */
gpio_init(void)570 void gpio_init(void)
571 {
572 	uint8_t i, j;
573 
574 	for(i = 0; i < 3; i++) {
575 		for(j = 0; j < 16; j++) {
576 			_gpio_instances[i].callback[j] = NULL;
577 		}
578 		_gpio_instances[i].callback_enable_mask = 0;
579 		_gpio_instances[i].callback_reg_mask = 0;
580 	}
581 	_gpio_instances[0].hw = (void *)GPIO0;
582 	_gpio_instances[1].hw = (void *)GPIO1;
583 	_gpio_instances[2].hw = (void *)GPIO2;
584 	system_register_isr(RAM_ISR_TABLE_PORT0_COMB_INDEX, (uint32_t)gpio_port0_isr_handler);
585 	system_register_isr(RAM_ISR_TABLE_PORT1_COMB_INDEX, (uint32_t)gpio_port1_isr_handler);
586 	system_register_isr(RAM_ISR_TABLE_PORT2_COMB_INDEX, (uint32_t)gpio_port2_isr_handler);
587 }
588 
589