drivers: pinctrl_nrf: Fix pin drive configuration

With the introduction of nrfx 3.0.0, values of `nrf_gpio_pin_drive_t`
constants may be defined differently, depending on the SoC family.
Since the nrf-pinctrl.h file is included also from dts files, it is
not possible to use there different definitions of `NRF_GPIO_PIN_*`
values based on Kconfig symbols that indicate given SoC family (as
Kconfig is processed after devicetree) so that those values could
still match `nrf_gpio_pin_drive_t` constants.
To solve this problem, the pinctrl_nrf driver now uses a lookup table
for mapping `NRF_GPIO_PIN_*` indexes to drive configuration values
required by the GPIO HAL.

Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
Andrzej Głąbek 2023-10-30 15:56:34 +01:00 committed by Carles Cufí
parent ea1be7f242
commit 7a9ff701d4
2 changed files with 31 additions and 20 deletions

View File

@ -13,19 +13,24 @@ BUILD_ASSERT(((NRF_PULL_NONE == NRF_GPIO_PIN_NOPULL) &&
(NRF_PULL_UP == NRF_GPIO_PIN_PULLUP)),
"nRF pinctrl pull settings do not match HAL values");
BUILD_ASSERT(((NRF_DRIVE_S0S1 == NRF_GPIO_PIN_S0S1) &&
(NRF_DRIVE_H0S1 == NRF_GPIO_PIN_H0S1) &&
(NRF_DRIVE_S0H1 == NRF_GPIO_PIN_S0H1) &&
(NRF_DRIVE_H0H1 == NRF_GPIO_PIN_H0H1) &&
(NRF_DRIVE_D0S1 == NRF_GPIO_PIN_D0S1) &&
(NRF_DRIVE_D0H1 == NRF_GPIO_PIN_D0H1) &&
(NRF_DRIVE_S0D1 == NRF_GPIO_PIN_S0D1) &&
(NRF_DRIVE_H0D1 == NRF_GPIO_PIN_H0D1) &&
#if defined(GPIO_PIN_CNF_DRIVE_E0E1)
(NRF_DRIVE_E0E1 == NRF_GPIO_PIN_E0E1) &&
#endif /* defined(GPIO_PIN_CNF_DRIVE_E0E1) */
(1U)),
"nRF pinctrl drive settings do not match HAL values");
#if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0)
#define NRF_DRIVE_COUNT (NRF_DRIVE_E0E1 + 1)
#else
#define NRF_DRIVE_COUNT (NRF_DRIVE_H0D1 + 1)
#endif
static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = {
[NRF_DRIVE_S0S1] = NRF_GPIO_PIN_S0S1,
[NRF_DRIVE_H0S1] = NRF_GPIO_PIN_H0S1,
[NRF_DRIVE_S0H1] = NRF_GPIO_PIN_S0H1,
[NRF_DRIVE_H0H1] = NRF_GPIO_PIN_H0H1,
[NRF_DRIVE_D0S1] = NRF_GPIO_PIN_D0S1,
[NRF_DRIVE_D0H1] = NRF_GPIO_PIN_D0H1,
[NRF_DRIVE_S0D1] = NRF_GPIO_PIN_S0D1,
[NRF_DRIVE_H0D1] = NRF_GPIO_PIN_H0D1,
#if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0)
[NRF_DRIVE_E0E1] = NRF_GPIO_PIN_E0E1,
#endif
};
/* value to indicate pin level doesn't need initialization */
#define NO_WRITE UINT32_MAX
@ -86,12 +91,19 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
uintptr_t reg)
{
for (uint8_t i = 0U; i < pin_cnt; i++) {
nrf_gpio_pin_drive_t drive = NRF_GET_DRIVE(pins[i]);
nrf_gpio_pin_drive_t drive;
uint8_t drive_idx = NRF_GET_DRIVE(pins[i]);
uint32_t psel = NRF_GET_PIN(pins[i]);
uint32_t write = NO_WRITE;
nrf_gpio_pin_dir_t dir;
nrf_gpio_pin_input_t input;
if (drive_idx < ARRAY_SIZE(drive_modes)) {
drive = drive_modes[drive_idx];
} else {
return -EINVAL;
}
if (psel == NRF_PIN_DISCONNECTED) {
psel = PSEL_DISCONNECTED;
}
@ -165,22 +177,22 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
#if defined(NRF_PSEL_TWIM)
case NRF_FUN_TWIM_SCL:
NRF_PSEL_TWIM(reg, SCL) = psel;
if (drive == NRF_DRIVE_S0S1) {
if (drive == NRF_GPIO_PIN_S0S1) {
/* Override the default drive setting with one
* suitable for TWI/TWIM peripherals (S0D1).
* This drive cannot be used always so that
* users are able to select e.g. H0D1 or E0E1
* in devicetree.
*/
drive = NRF_DRIVE_S0D1;
drive = NRF_GPIO_PIN_S0D1;
}
dir = NRF_GPIO_PIN_DIR_INPUT;
input = NRF_GPIO_PIN_INPUT_CONNECT;
break;
case NRF_FUN_TWIM_SDA:
NRF_PSEL_TWIM(reg, SDA) = psel;
if (drive == NRF_DRIVE_S0S1) {
drive = NRF_DRIVE_S0D1;
if (drive == NRF_GPIO_PIN_S0S1) {
drive = NRF_GPIO_PIN_S0D1;
}
dir = NRF_GPIO_PIN_DIR_INPUT;
input = NRF_GPIO_PIN_INPUT_CONNECT;

View File

@ -131,7 +131,6 @@
/**
* @name nRF pinctrl output drive.
* @note Values match nrf_gpio_pin_drive_t constants.
* @{
*/
@ -152,7 +151,7 @@
/** High drive '0', disconnect '1'. */
#define NRF_DRIVE_H0D1 7U
/** Extra high drive '0', extra high drive '1'. */
#define NRF_DRIVE_E0E1 11U
#define NRF_DRIVE_E0E1 8U
/** @} */