diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 45fc7c2fa36..9fc433f8d38 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -5,4 +5,5 @@ zephyr_library() zephyr_library_sources(common.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_NRF pinctrl_nrf.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index fbdc1f13495..f4e84142a71 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -30,6 +30,7 @@ config PINCTRL_DYNAMIC peripheral at early boot stages depending on a certain input. source "drivers/pinctrl/Kconfig.gd32" +source "drivers/pinctrl/Kconfig.nrf" source "drivers/pinctrl/Kconfig.stm32" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.nrf b/drivers/pinctrl/Kconfig.nrf new file mode 100644 index 00000000000..58b8ba9784d --- /dev/null +++ b/drivers/pinctrl/Kconfig.nrf @@ -0,0 +1,10 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_NRF + bool "nRF pin controller driver" + depends on SOC_FAMILY_NRF + select PINCTRL_STORE_REG + default y + help + nRF pin controller driver diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c new file mode 100644 index 00000000000..66197032769 --- /dev/null +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +BUILD_ASSERT(((NRF_PULL_NONE == NRF_GPIO_PIN_NOPULL) && + (NRF_PULL_DOWN == NRF_GPIO_PIN_PULLDOWN) && + (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"); + +/** + * @brief Configure pin settings. + * + * @param pin Pin configuration. + * @param dir Pin direction. + * @param input Pin input buffer connection. + */ +__unused static void nrf_pin_configure(pinctrl_soc_pin_t pin, + nrf_gpio_pin_dir_t dir, + nrf_gpio_pin_input_t input) +{ + /* force input direction and disconnected buffer for low power */ + if (NRF_GET_LP(pin) == NRF_LP_ENABLE) { + dir = NRF_GPIO_PIN_DIR_INPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + } + + nrf_gpio_cfg(NRF_GET_PIN(pin), dir, input, NRF_GET_PULL(pin), + NRF_GET_DRIVE(pin), NRF_GPIO_PIN_NOSENSE); +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + switch (NRF_GET_FUN(pins[i])) { + default: + return -ENOTSUP; + } + } + + return 0; +} diff --git a/dts/arm/nordic/nrf_common.dtsi b/dts/arm/nordic/nrf_common.dtsi index 3a3ae156fe3..85bdff5d711 100644 --- a/dts/arm/nordic/nrf_common.dtsi +++ b/dts/arm/nordic/nrf_common.dtsi @@ -6,6 +6,7 @@ #include #include +#include #include /* @@ -16,6 +17,16 @@ #define NRF_DEFAULT_IRQ_PRIORITY 1 #endif +/ { + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since nRF SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "nordic,nrf-pinctrl"; + }; +}; + &systick { /* * Nordic SoCs rely by default on the RTC for system clock diff --git a/dts/bindings/pinctrl/nordic,nrf-pinctrl.yaml b/dts/bindings/pinctrl/nordic,nrf-pinctrl.yaml new file mode 100644 index 00000000000..c3daa63cf81 --- /dev/null +++ b/dts/bindings/pinctrl/nordic,nrf-pinctrl.yaml @@ -0,0 +1,110 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + The nRF pin controller is a singleton node responsible for controlling + pin function selection and pin properties. For example, you can use this + node to route UART0 RX to pin P0.1 and enable the pull-up resistor on the + pin. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + &pinctrl { + /* configuration for uart0 device, default state */ + uart0_default: uart0_default { + /* group 1 ('group1' name is arbitrary) */ + group1 { + /* configure P0.1 as UART_TX and P0.2 as UART_RTS */ + psels = , ; + }; + /* group 2 */ + group2 { + /* configure P0.3 as UART_RX and P0.4 as UART_CTS */ + psels = , ; + /* both P0.3 and P0.4 are configured with pull-up */ + bias-pull-up; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. You would specify the low-power configuration for the same device + in a separate child node. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'psels' + property. The NRF_PSEL macro is used to specify a pin function selection. + Available pin functions can be found in the + include/dt-bindings/pinctrl/nrf-pinctrl.h header file. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'bias-pull-up' property in group 2. Here is a list of + supported standard pin properties: + + - bias-disable: Disable pull-up/down (default behavior, not required). + - bias-pull-up: Enable pull-up resistor. + - bias-pull-down: Enable pull-down resistor. + - low-power-enable: Configure pin as an input with input buffer + disconnected. + + Note that bias options are mutually exclusive. + + To link this pin configuration with a device, use a pinctrl-N property + for some number N, like this example you could place in your board's DTS + file: + + #include "board-pinctrl.dtsi" + + &uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + }; + +compatible: "nordic,nrf-pinctrl" + +include: + - name: base.yaml + - name: pincfg-node-group.yaml + child-binding: + child-binding: + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - low-power-enable + +child-binding: + description: | + nRF pin controller pin configuration state nodes. + child-binding: + description: | + nRF pin controller pin configuration group. + properties: + psels: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins should + be defined using the NRF_PSEL utility macro that encodes the port, + pin and function. + + drive-mode: + type: int + default: 0 + description: | + Pin output drive mode. Available drive modes are pre-defined in + nrf-pinctrl.h. Note that extra modes may not be available on certain + devices. Defaults to standard mode for 0 and 1 (NRF_DRIVE_S0S1), the + SoC default. diff --git a/include/dt-bindings/pinctrl/nrf-pinctrl.h b/include/dt-bindings/pinctrl/nrf-pinctrl.h new file mode 100644 index 00000000000..d477a8509c3 --- /dev/null +++ b/include/dt-bindings/pinctrl/nrf-pinctrl.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_NRF_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_NRF_PINCTRL_H_ + +/* + * The whole nRF pin configuration information is encoded in a 32-bit bitfield + * organized as follows: + * + * - 31..16: Pin function. + * - 15..13: Reserved. + * - 12: Pin low power mode. + * - 11..8: Pin output drive configuration. + * - 7..6: Pin pull configuration. + * - 5..0: Pin number (combination of port and pin). + */ + +/** + * @name nRF pin configuration bit field positions and masks. + * @{ + */ + +/** Position of the function field. */ +#define NRF_FUN_POS 16U +/** Mask for the function field. */ +#define NRF_FUN_MSK 0xFFFFU +/** Position of the low power field. */ +#define NRF_LP_POS 12U +/** Mask for the low power field. */ +#define NRF_LP_MSK 0x1U +/** Position of the drive configuration field. */ +#define NRF_DRIVE_POS 8U +/** Mask for the drive configuration field. */ +#define NRF_DRIVE_MSK 0xFU +/** Position of the pull configuration field. */ +#define NRF_PULL_POS 6U +/** Mask for the pull configuration field. */ +#define NRF_PULL_MSK 0x3U +/** Position of the pin field. */ +#define NRF_PIN_POS 0U +/** Mask for the pin field. */ +#define NRF_PIN_MSK 0x3FU + +/** @} */ + +/** + * @name nRF pinctrl pin functions. + * @{ + */ + +/** @} */ + +/** + * @name nRF pinctrl output drive. + * @note Values match nrf_gpio_pin_drive_t constants. + * @{ + */ + +/** Standard '0', standard '1'. */ +#define NRF_DRIVE_S0S1 0U +/** High drive '0', standard '1'. */ +#define NRF_DRIVE_H0S1 1U +/** Standard '0', high drive '1'. */ +#define NRF_DRIVE_S0H1 2U +/** High drive '0', high drive '1'. */ +#define NRF_DRIVE_H0H1 3U +/** Disconnect '0' standard '1'. */ +#define NRF_DRIVE_D0S1 4U +/** Disconnect '0', high drive '1'. */ +#define NRF_DRIVE_D0H1 5U +/** Standard '0', disconnect '1'. */ +#define NRF_DRIVE_S0D1 6U +/** High drive '0', disconnect '1'. */ +#define NRF_DRIVE_H0D1 7U +/** Extra high drive '0', extra high drive '1'. */ +#define NRF_DRIVE_E0E1 11U + +/** @} */ + +/** + * @name nRF pinctrl pull-up/down. + * @note Values match nrf_gpio_pin_pull_t constants. + * @{ + */ + +/** Pull-up disabled. */ +#define NRF_PULL_NONE 0U +/** Pull-down enabled. */ +#define NRF_PULL_DOWN 1U +/** Pull-up enabled. */ +#define NRF_PULL_UP 3U + +/** @} */ + +/** + * @name nRF pinctrl low power mode. + * @{ + */ + +/** Input. */ +#define NRF_LP_DISABLE 0U +/** Output. */ +#define NRF_LP_ENABLE 1U + +/** @} */ + +/** + * @brief Utility macro to build nRF psels property entry. + * + * @param fun Pin function configuration (see NRF_FUNC_{name} macros). + * @param port Port (0 or 1). + * @param pin Pin (0..31). + */ +#define NRF_PSEL(fun, port, pin) \ + ((((((port) * 32U) + (pin)) & NRF_PIN_MSK) << NRF_PIN_POS) | \ + ((NRF_FUN_ ## fun & NRF_FUN_MSK) << NRF_FUN_POS)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_NRF_PINCTRL_H_ */ diff --git a/soc/arm/nordic_nrf/common/CMakeLists.txt b/soc/arm/nordic_nrf/common/CMakeLists.txt index 8e6b4287a15..b568fd2f29c 100644 --- a/soc/arm/nordic_nrf/common/CMakeLists.txt +++ b/soc/arm/nordic_nrf/common/CMakeLists.txt @@ -2,3 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_NRF soc_nrf_common.S) +zephyr_include_directories(.) diff --git a/soc/arm/nordic_nrf/common/pinctrl_soc.h b/soc/arm/nordic_nrf/common/pinctrl_soc.h new file mode 100644 index 00000000000..231b525de36 --- /dev/null +++ b/soc/arm/nordic_nrf/common/pinctrl_soc.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * nRF SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_NORDIC_NRF_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_NORDIC_NRF_COMMON_PINCTRL_SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** Type for nRF pin. */ +typedef uint32_t pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + (DT_PROP_BY_IDX(node_id, prop, idx) | \ + ((NRF_PULL_DOWN * DT_PROP(node_id, bias_pull_down)) << NRF_PULL_POS) |\ + ((NRF_PULL_UP * DT_PROP(node_id, bias_pull_up)) << NRF_PULL_POS) | \ + (DT_PROP(node_id, drive_mode) << NRF_DRIVE_POS) | \ + ((NRF_LP_ENABLE * DT_PROP(node_id, low_power_enable)) << NRF_LP_POS) \ + ), + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, psels, \ + Z_PINCTRL_STATE_PIN_INIT)} + +/** + * @brief Utility macro to obtain pin function. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_FUN(pincfg) (((pincfg) >> NRF_FUN_POS) & NRF_FUN_MSK) + +/** + * @brief Utility macro to obtain pin low power flag. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_LP(pincfg) (((pincfg) >> NRF_LP_POS) & NRF_LP_MSK) + +/** + * @brief Utility macro to obtain pin drive mode. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_DRIVE(pincfg) (((pincfg) >> NRF_DRIVE_POS) & NRF_DRIVE_MSK) + +/** + * @brief Utility macro to obtain pin pull configuration. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_PULL(pincfg) (((pincfg) >> NRF_PULL_POS) & NRF_PULL_MSK) + +/** + * @brief Utility macro to obtain port and pin combination. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_PIN(pincfg) (((pincfg) >> NRF_PIN_POS) & NRF_PIN_MSK) + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_NORDIC_NRF_COMMON_PINCTRL_SOC_H_ */