| /* |
| * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com> |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file |
| * @brief Atmel SAM MCU family General-Purpose Input/Output Controller (GPIO) |
| * module HAL driver. |
| */ |
| |
| #include <zephyr/sys/__assert.h> |
| #include "soc_gpio.h" |
| |
| static void configure_common_attr(volatile Gpio *gpio, |
| uint32_t mask, uint32_t flags) |
| { |
| flags &= SOC_GPIO_FLAGS_MASK; |
| |
| /* Disable interrupts on the pin(s) */ |
| gpio->IERC = mask; |
| |
| /* Configure pull-up(s) */ |
| if (flags & SOC_GPIO_PULLUP) { |
| gpio->PUERS = mask; |
| } else { |
| gpio->PUERC = mask; |
| } |
| |
| /* Configure pull-down(s) */ |
| if (flags & SOC_GPIO_PULLDOWN) { |
| gpio->PDERS = mask; |
| } else { |
| gpio->PDERC = mask; |
| } |
| |
| /* Configure open drain (multi-drive) */ |
| if (flags & SOC_GPIO_OPENDRAIN) { |
| gpio->ODMERS = mask; |
| } else { |
| gpio->ODMERC = mask; |
| } |
| } |
| |
| static void configure_input_attr(volatile Gpio *gpio, |
| uint32_t mask, uint32_t flags) |
| { |
| /* Configure input filter */ |
| if ((flags & SOC_GPIO_IN_FILTER_MASK) != 0U) { |
| if ((flags & SOC_GPIO_IN_FILTER_MASK) == |
| SOC_GPIO_IN_FILTER_DEBOUNCE) { |
| /* Enable de-bounce, disable de-glitch */ |
| gpio->GFERC = mask; |
| } else { |
| /* Disable de-bounce, enable de-glitch */ |
| gpio->GFERS = mask; |
| } |
| } else { |
| gpio->GFERC = mask; |
| } |
| |
| /* Configure interrupt */ |
| if (flags & SOC_GPIO_INT_ENABLE) { |
| if ((flags & SOC_GPIO_INT_TRIG_MASK) == |
| SOC_GPIO_INT_TRIG_DOUBLE_EDGE) { |
| gpio->IMR0C = mask; |
| gpio->IMR1C = mask; |
| } else { |
| if (flags & SOC_GPIO_INT_ACTIVE_HIGH) { |
| /* Rising Edge*/ |
| gpio->IMR0S = mask; |
| gpio->IMR1C = mask; |
| } else { |
| /* Falling Edge */ |
| gpio->IMR0C = mask; |
| gpio->IMR1S = mask; |
| } |
| } |
| /* Enable interrupts on the pin(s) */ |
| gpio->IERS = mask; |
| } else { |
| gpio->IERC = mask; |
| } |
| } |
| |
| void soc_gpio_configure(const struct soc_gpio_pin *pin) |
| { |
| uint32_t mask = pin->mask; |
| volatile Gpio *gpio = pin->regs; |
| uint8_t periph_id = pin->periph_id; |
| uint32_t flags = pin->flags; |
| uint32_t type = pin->flags & SOC_GPIO_FUNC_MASK; |
| |
| /* Configure pin attributes common to all functions */ |
| configure_common_attr(gpio, mask, flags); |
| |
| switch (type) { |
| case SOC_GPIO_FUNC_A: |
| gpio->PMR0C = mask; |
| gpio->PMR1C = mask; |
| gpio->PMR2C = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_B: |
| gpio->PMR0S = mask; |
| gpio->PMR1C = mask; |
| gpio->PMR2C = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_C: |
| gpio->PMR0C = mask; |
| gpio->PMR1S = mask; |
| gpio->PMR2C = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_D: |
| gpio->PMR0S = mask; |
| gpio->PMR1S = mask; |
| gpio->PMR2C = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_E: |
| gpio->PMR0C = mask; |
| gpio->PMR1C = mask; |
| gpio->PMR2S = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_F: |
| gpio->PMR0S = mask; |
| gpio->PMR1C = mask; |
| gpio->PMR2S = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_G: |
| gpio->PMR0C = mask; |
| gpio->PMR1S = mask; |
| gpio->PMR2S = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_H: |
| gpio->PMR0S = mask; |
| gpio->PMR1S = mask; |
| gpio->PMR2S = mask; |
| gpio->GPERC = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_IN: |
| soc_pmc_peripheral_enable(periph_id); |
| configure_input_attr(gpio, mask, flags); |
| |
| gpio->ODERC = mask; |
| gpio->STERS = mask; |
| gpio->GPERS = mask; |
| break; |
| |
| case SOC_GPIO_FUNC_OUT_1: |
| case SOC_GPIO_FUNC_OUT_0: |
| if (type == SOC_GPIO_FUNC_OUT_1) { |
| gpio->OVRS = mask; |
| } else { |
| gpio->OVRC = mask; |
| } |
| |
| gpio->ODCR0S = mask; |
| gpio->ODCR1S = mask; |
| gpio->ODERS = mask; |
| gpio->STERC = mask; |
| gpio->GPERS = mask; |
| break; |
| |
| default: |
| __ASSERT(0, "Unsupported pin function, check pin.flags value"); |
| return; |
| } |
| } |
| |
| void soc_gpio_list_configure(const struct soc_gpio_pin pins[], |
| unsigned int size) |
| { |
| for (int i = 0; i < size; i++) { |
| soc_gpio_configure(&pins[i]); |
| } |
| } |