diff options
Diffstat (limited to 'nuttx/arch/arm/src/nuc1xx/nuc_gpio.c')
-rw-r--r-- | nuttx/arch/arm/src/nuc1xx/nuc_gpio.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/nuc1xx/nuc_gpio.c b/nuttx/arch/arm/src/nuc1xx/nuc_gpio.c new file mode 100644 index 000000000..be5919157 --- /dev/null +++ b/nuttx/arch/arm/src/nuc1xx/nuc_gpio.c @@ -0,0 +1,253 @@ +/**************************************************************************** + * arch/arm/src/nuc1xx/nuc_gpio.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <assert.h> +#include <debug.h> + +#include "up_arch.h" + +#include "chip.h" +#include "chip/nuc_gpio.h" + +#include "nuc_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nuc_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...) + * function, it must be unconfigured with nuc_unconfiggpio() with + * the same cfgset first before it can be set to non-alternative function. + * + * Returns: + * OK on success + * ERROR on invalid port, or when pin is locked as ALT function. + * + ****************************************************************************/ + +int nuc_configgpio(gpio_cfgset_t cfgset) +{ + uintptr_t base; + uint32_t regaddr; + uint32_t regval; + uint32_t isrc; + uint32_t imd; + uint32_t ien; + uint32_t value; + int port; + int pin; + + /* Decode the port and pin. Use the port number to get the GPIO base + * address. + */ + + port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + DEBUGASSERT((unsigned)port <= NUC_GPIO_PORTE); + base = NUC_GPIO_CTRL_BASE(port); + + /* Set the the GPIO PMD register */ + + regaddr = base + NUC_GPIOA_PMD_OFFSET; + regval = getreg32(regaddr); + regval &= ~GPIO_PMD_MASK(pin); + + switch (cfgset & GPIO_MODE_MASK) + { + default: + case GPIO_INPUT: /* Input */ + value = GPIO_PMD_INPUT; + break; + + case GPIO_OUTPUT: /* Push-pull output */ + value = GPIO_PMD_OUTPUT; + break; + + case GPIO_OPENDRAIN: /* Open drain output */ + value = GPIO_PMD_OPENDRAIN; + break; + + case GPIO_BIDI: /* Quasi bi-directional */ + value = GPIO_PMD_BIDI; + break; + } + + regval |= GPIO_PMD(pin, value); + putreg32(regval, regaddr); + + /* Check if we need to disable the digital input path */ + + regaddr = base + NUC_GPIO_OFFD_OFFSET; + regval = getreg32(regaddr); + regval &= ~GPIO_OFFD(pin); + + if ((cfgset & GPIO_ANALOG) != 0) + { + regval |= GPIO_OFFD(pin); + } + + putreg32(regval, regaddr); + + /* Check if we need to enable debouncing */ + + regaddr = base + NUC_GPIO_DBEN_OFFSET; + regval = getreg32(regaddr); + regval &= ~GPIO_DBEN(pin); + + if ((cfgset & GPIO_DEBOUNCE) != 0) + { + regval |= GPIO_DBEN(pin); + } + + putreg32(regval, regaddr); + + /* Configure interrupting pins */ + + isrc = getreg32(base + NUC_GPIO_ISRC_OFFSET); + isrc &= ~GPIO_ISRC(pin); + + imd = getreg32(base + NUC_GPIO_IMD_OFFSET); + imd &= ~GPIO_IMD(pin); + + ien = getreg32(base + NUC_GPIO_IEN_OFFSET); + ien &= ~(GPIO_IF_EN(pin) | GPIO_IR_EN(pin)); + + switch (cfgset & GPIO_INTERRUPT_MASK) + { + case GPIO_INTERRUPT_RISING_EDGE: + isrc |= GPIO_ISRC(pin); + ien |= GPIO_IR_EN(pin); + break; + + case GPIO_INTERRUPT_FALLING_EDGE: + isrc |= GPIO_ISRC(pin); + ien |= GPIO_IF_EN(pin); + break; + + case GPIO_INTERRUPT_BOTH_EDGES: + isrc |= GPIO_ISRC(pin); + ien |= (GPIO_IF_EN(pin) | GPIO_IR_EN(pin)); + break; + + case GPIO_INTERRUPT_HIGH_LEVEL: + isrc |= GPIO_ISRC(pin); + imd |= GPIO_IMD(pin); + ien |= GPIO_IR_EN(pin); + break; + + case GPIO_INTERRUPT_LOW_LEVEL: + isrc |= GPIO_ISRC(pin); + imd |= GPIO_IMD(pin); + ien |= GPIO_IF_EN(pin); + break; + + default: + break; + } + + putreg32(ien, base + NUC_GPIO_IEN_OFFSET); + putreg32(imd, base + NUC_GPIO_IMD_OFFSET); + putreg32(isrc, base + NUC_GPIO_ISRC_OFFSET); + return 0; +} + +/**************************************************************************** + * Name: nuc_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void nuc_gpiowrite(gpio_cfgset_t pinset, bool value) +{ + int port; + int pin; + + /* Decode the port and pin. Use the port number to get the GPIO base + * address. + */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + DEBUGASSERT((unsigned)port <= NUC_GPIO_PORTE); + putreg32((uint32_t)value, NUC_PORT_PDIO(port, pin)); +} + +/**************************************************************************** + * Name: nuc_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool nuc_gpioread(gpio_cfgset_t pinset) +{ + int port; + int pin; + + /* Decode the port and pin. Use the port number to get the GPIO base + * address. + */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + DEBUGASSERT((unsigned)port <= NUC_GPIO_PORTE); + return (getreg32(NUC_PORT_PDIO(port, pin)) & PORT_MASK) != 0; +} |