diff --git a/arch/arm/src/nrf52/nrf52_gpio.c b/arch/arm/src/nrf52/nrf52_gpio.c index 6f5625c532..83e70b038b 100644 --- a/arch/arm/src/nrf52/nrf52_gpio.c +++ b/arch/arm/src/nrf52/nrf52_gpio.c @@ -100,6 +100,11 @@ static inline void nrf52_gpio_input(unsigned int port, unsigned int pin) /* Configure the pin as an input */ putreg32(1U << pin, offset); + + /* Enable input buffer */ + + offset = nrf52_gpio_regget(port, NRF52_GPIO_PIN_CNF_OFFSET(pin)); + modifyreg32(offset, GPIO_CNF_INPUT, 0); } /**************************************************************************** @@ -115,6 +120,11 @@ static inline void nrf52_gpio_output(nrf52_pinset_t cfgset, { uint32_t offset; + /* Disable input buffer */ + + offset = nrf52_gpio_regget(port, NRF52_GPIO_PIN_CNF_OFFSET(pin)); + modifyreg32(offset, 0, GPIO_CNF_INPUT); + offset = nrf52_gpio_regget(port, NRF52_GPIO_DIRSET_OFFSET); nrf52_gpio_write(cfgset, ((cfgset & GPIO_VALUE) != GPIO_VALUE_ZERO)); @@ -192,6 +202,59 @@ static inline void nrf52_gpio_sense(nrf52_pinset_t cfgset, putreg32(regval, offset); } +/**************************************************************************** + * Name: nrf52_gpio_drive + * + * Description: + * Set DRIVE configuration for a pin + * + ****************************************************************************/ + +static inline void nrf52_gpio_drive(nrf52_pinset_t cfgset, + unsigned int port, unsigned int pin) +{ + uint32_t drive; + uint32_t regval; + uint32_t offset; + + drive = cfgset & GPIO_DRIVE_MASK; + + offset = nrf52_gpio_regget(port, NRF52_GPIO_PIN_CNF_OFFSET(pin)); + regval = getreg32(offset); + + regval &= ~GPIO_CNF_DRIVE_MASK; + + switch (drive) + { + case GPIO_DRIVE_S0S1: + regval |= GPIO_CNF_DRIVE_S0S1; + break; + case GPIO_DRIVE_S0H1: + regval |= GPIO_CNF_DRIVE_S0H1; + break; + case GPIO_DRIVE_S0D1: + regval |= GPIO_CNF_DRIVE_S0D1; + break; + case GPIO_DRIVE_H0D1: + regval |= GPIO_CNF_DRIVE_H0D1; + break; + case GPIO_DRIVE_H0H1: + regval |= GPIO_CNF_DRIVE_H0H1; + break; + case GPIO_DRIVE_H0S1: + regval |= GPIO_CNF_DRIVE_H0S1; + break; + case GPIO_DRIVE_D0H1: + regval |= GPIO_CNF_DRIVE_D0H1; + break; + case GPIO_DRIVE_D0S1: + regval |= GPIO_CNF_DRIVE_D0S1; + break; + } + + putreg32(regval, offset); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -208,6 +271,8 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset) { unsigned int port; unsigned int pin; + irqstate_t flags; + int ret = OK; /* Verify that this hardware supports the select GPIO port */ @@ -220,6 +285,8 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset) pin = GPIO_PIN_DECODE(cfgset); + flags = spin_lock_irqsave(); + /* First, configure the port as a generic input so that we have a * known starting point and consistent behavior during the re- * configuration. @@ -231,6 +298,12 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset) nrf52_gpio_mode(cfgset, port, pin); + /* Set the drive bits (needed also for input pins + * for some peripherals). + */ + + nrf52_gpio_drive(cfgset, port, pin); + /* Handle according to pin function */ switch (cfgset & GPIO_FUNC_MASK) @@ -244,11 +317,17 @@ int nrf52_gpio_config(nrf52_pinset_t cfgset) break; default: - return -EINVAL; + ret = -EINVAL; } + + spin_unlock_irqrestore(flags); + } + else + { + ret = -EINVAL; } - return OK; + return ret; } /****************************************************************************