diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index a9119d481ba..c6e21f9b1b3 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -9,6 +9,7 @@ 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_RCAR_PFC pfc_rcar.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_RPI_PICO pinctrl_rpi_pico.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_SAM pinctrl_sam.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_KINETIS pinctrl_kinetis.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_XEC pinctrl_mchp_xec.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 59a3081272d..f871264cb5b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -34,6 +34,7 @@ source "drivers/pinctrl/Kconfig.gd32" source "drivers/pinctrl/Kconfig.nrf" source "drivers/pinctrl/Kconfig.rcar" source "drivers/pinctrl/Kconfig.rpi_pico" +source "drivers/pinctrl/Kconfig.sam" source "drivers/pinctrl/Kconfig.stm32" source "drivers/pinctrl/Kconfig.kinetis" source "drivers/pinctrl/Kconfig.xec" diff --git a/drivers/pinctrl/Kconfig.sam b/drivers/pinctrl/Kconfig.sam new file mode 100644 index 00000000000..5daf67c1a06 --- /dev/null +++ b/drivers/pinctrl/Kconfig.sam @@ -0,0 +1,11 @@ +# Copyright (c) 2022, Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_ATMEL_SAM_PINCTRL := atmel,sam-pinctrl + +config PINCTRL_SAM + bool "Atmel SAM pin controller driver" + depends on SOC_FAMILY_SAM + default $(dt_compat_enabled,$(DT_COMPAT_ATMEL_SAM_PINCTRL)) + help + Atmel pin controller driver is used on SAM and SAM4L SoC series diff --git a/drivers/pinctrl/pinctrl_sam.c b/drivers/pinctrl/pinctrl_sam.c new file mode 100644 index 00000000000..e446cbbe2dd --- /dev/null +++ b/drivers/pinctrl/pinctrl_sam.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** Utility macro that expands to the GPIO port address if it exists */ +#define SAM_PORT_ADDR_OR_NONE(nodelabel) \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),)) + +/** Utility macro that expands to the GPIO Peripheral ID if it exists */ +#define SAM_PORT_PERIPH_ID_OR_NONE(nodelabel) \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_PROP(DT_NODELABEL(nodelabel), peripheral_id),)) + +/** SAM port addresses */ +static const uint32_t sam_port_addrs[] = { +#ifdef ID_GPIO + SAM_PORT_ADDR_OR_NONE(gpioa) + SAM_PORT_ADDR_OR_NONE(gpiob) + SAM_PORT_ADDR_OR_NONE(gpioc) +#else + SAM_PORT_ADDR_OR_NONE(pioa) + SAM_PORT_ADDR_OR_NONE(piob) + SAM_PORT_ADDR_OR_NONE(pioc) + SAM_PORT_ADDR_OR_NONE(piod) + SAM_PORT_ADDR_OR_NONE(pioe) + SAM_PORT_ADDR_OR_NONE(piof) +#endif +}; + +/** SAM port peripheral id */ +static const uint32_t sam_port_periph_id[] = { +#ifdef ID_GPIO + SAM_PORT_PERIPH_ID_OR_NONE(gpioa) + SAM_PORT_PERIPH_ID_OR_NONE(gpiob) + SAM_PORT_PERIPH_ID_OR_NONE(gpioc) +#else + SAM_PORT_PERIPH_ID_OR_NONE(pioa) + SAM_PORT_PERIPH_ID_OR_NONE(piob) + SAM_PORT_PERIPH_ID_OR_NONE(pioc) + SAM_PORT_PERIPH_ID_OR_NONE(piod) + SAM_PORT_PERIPH_ID_OR_NONE(pioe) + SAM_PORT_PERIPH_ID_OR_NONE(piof) +#endif +}; + +static void pinctrl_configure_pin(pinctrl_soc_pin_t pin) +{ + struct soc_gpio_pin soc_pin; + uint8_t port_idx, port_func; + + port_idx = SAM_PINMUX_PORT_GET(pin); + __ASSERT_NO_MSG(port_idx < ARRAY_SIZE(sam_port_addrs)); + port_func = SAM_PINMUX_FUNC_GET(pin); + +#ifdef ID_GPIO + soc_pin.regs = (Gpio *) sam_port_addrs[port_idx]; +#else + soc_pin.regs = (Pio *) sam_port_addrs[port_idx]; +#endif + soc_pin.periph_id = sam_port_periph_id[port_idx]; + soc_pin.mask = 1 << SAM_PINMUX_PIN_GET(pin); + soc_pin.flags = SAM_PINCTRL_FLAGS_GET(pin) << SOC_GPIO_FLAGS_POS; + + if (port_func == SAM_PINMUX_FUNC_periph) { + soc_pin.flags |= (SAM_PINMUX_PERIPH_GET(pin) + << SOC_GPIO_FUNC_POS); + } + + soc_gpio_configure(&soc_pin); +} + +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++) { + pinctrl_configure_pin(*pins++); + } + + return 0; +} diff --git a/dts/bindings/pinctrl/atmel,sam-pinctrl.yaml b/dts/bindings/pinctrl/atmel,sam-pinctrl.yaml index 73fa06398ca..6b40e533ecc 100644 --- a/dts/bindings/pinctrl/atmel,sam-pinctrl.yaml +++ b/dts/bindings/pinctrl/atmel,sam-pinctrl.yaml @@ -1,22 +1,87 @@ # Copyright (c) 2020, Linaro Limited -# Copyright (c) 2021, Gerson Fernando Budke +# Copyright (c) 2021, Teslabs Engineering S.L. +# Copyright (c) 2021-2022, Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: | Atmel SAM Pinctrl container node - The Atmel SAM pins implements following pin configuration option: + The Atmel SAM pin controller is a singleton node responsible for controlling + pin function selection and pin properties. For example, you can use this node + to route USART0 RX to pin PA10 and enable the pull-up resistor on the pin. - * bias-pull-up - * bias-pull-down - * drive-open-drain + The node has the 'pinctrl' node label set in your SoC's devicetree, so you can + modify it like this: - These options define devicetree flags that are converted to SoC flags at - ATMEL_SAM_PIN_FLAGS(). + &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 -pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /** include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + /* configuration for the usart0 "default" state */ + usart0_default: usart0_default { + /* group 1 */ + group1 { + /* configure PA6 as USART0 TX and PA8 as USART0 CTS */ + pinmux = , ; + }; + /* group 2 */ + group2 { + /* configure PA5 as USART0 RX and PA7 as USART0 RTS */ + pinmux = , ; + /* both PA5 and PA7 have pull-up enabled */ + bias-pull-up; + }; + }; + }; + + The 'usart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + 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-pull-up: Enable pull-up resistor. + - bias-pull-down: Enable pull-down resistor. + - drive-open-drain: Open-drain drive mode. + + To link pin configurations 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" + + &usart0 { + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + }; compatible: "atmel,sam-pinctrl" -include: [base.yaml, pincfg-node.yaml] +include: + - name: base.yaml + - name: pincfg-node-group.yaml + child-binding: + child-binding: + property-allowlist: + - bias-pull-up + - bias-pull-down + - drive-open-drain properties: "#address-cells": @@ -27,7 +92,17 @@ properties: const: 1 child-binding: - description: Atmel pins + description: | + Each child node defines the configuration for a particular state. + child-binding: + description: | + The grandchild nodes group pins that share the same pin configuration. properties: - "atmel,pins": - type: phandle-array + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins should + be defined using pre-defined macros or, alternatively, using the + SAM_PINMUX utility macros depending on the pinmux model used by the + SoC series. diff --git a/include/drivers/pinctrl/pinctrl_soc_sam_common.h b/include/drivers/pinctrl/pinctrl_soc_sam_common.h new file mode 100644 index 00000000000..bd3aad5188e --- /dev/null +++ b/include/drivers/pinctrl/pinctrl_soc_sam_common.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022, Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Atmel SAM SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_PINCTRL_PINCTRL_SOC_SAM_COMMON_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PINCTRL_PINCTRL_SOC_SAM_COMMON_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** @brief Type for SAM pin. + * + * Bits: + * - 0-15: SAM pinmux bit field (@ref SAM_PINMUX). + * - 16-21: Pin flags bit field (@ref SAM_PINFLAGS). + * - 22-31: Reserved. + */ +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) << SAM_PINCTRL_PINMUX_POS) \ + | (DT_PROP(node_id, bias_pull_up) << SAM_PINCTRL_PULLUP_POS) \ + | (DT_PROP(node_id, bias_pull_down) << SAM_PINCTRL_PULLDOWN_POS) \ + | (DT_PROP(node_id, drive_open_drain) << SAM_PINCTRL_OPENDRAIN_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, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +/** @endcond */ + + +/** + * @brief Pin flags/attributes + * @anchor SAM_PINFLAGS + * + * @{ + */ + +#define SAM_PINCTRL_FLAGS_DEFAULT (0U) +#define SAM_PINCTRL_FLAGS_POS (0U) +#define SAM_PINCTRL_FLAGS_MASK (0x7 << SAM_PINCTRL_FLAGS_POS) +#define SAM_PINCTRL_FLAG_MASK (1U) +#define SAM_PINCTRL_PULLUP_POS (SAM_PINCTRL_FLAGS_POS) +#define SAM_PINCTRL_PULLUP (1U << SAM_PINCTRL_PULLUP_POS) +#define SAM_PINCTRL_PULLDOWN_POS (SAM_PINCTRL_PULLUP_POS + 1U) +#define SAM_PINCTRL_PULLDOWN (1U << SAM_PINCTRL_PULLDOWN_POS) +#define SAM_PINCTRL_OPENDRAIN_POS (SAM_PINCTRL_PULLDOWN_POS + 1U) +#define SAM_PINCTRL_OPENDRAIN (1U << SAM_PINCTRL_OPENDRAIN_POS) + +/** @} */ + +/** + * Obtain Flag value from pinctrl_soc_pin_t configuration. + * + * @param pincfg pinctrl_soc_pin_t bit field value. + * @param pos attribute/flags bit position (@ref SAM_PINFLAGS). + */ +#define SAM_PINCTRL_FLAG_GET(pincfg, pos) \ + (((pincfg) >> pos) & SAM_PINCTRL_FLAG_MASK) + +#define SAM_PINCTRL_FLAGS_GET(pincfg) \ + (((pincfg) >> SAM_PINCTRL_FLAGS_POS) & SAM_PINCTRL_FLAGS_MASK) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PINCTRL_PINCTRL_SOC_SAM_COMMON_H_ */ diff --git a/soc/arm/atmel_sam/Kconfig.defconfig b/soc/arm/atmel_sam/Kconfig.defconfig index a5b0b196d6c..d103f57d48d 100644 --- a/soc/arm/atmel_sam/Kconfig.defconfig +++ b/soc/arm/atmel_sam/Kconfig.defconfig @@ -10,6 +10,9 @@ if SOC_FAMILY_SAM config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) +config PINCTRL + default y + config WATCHDOG default y diff --git a/soc/arm/atmel_sam/common/pinctrl_soc.h b/soc/arm/atmel_sam/common/pinctrl_soc.h new file mode 100644 index 00000000000..f8e6216878a --- /dev/null +++ b/soc/arm/atmel_sam/common/pinctrl_soc.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Atmel SAM SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_ATMEL_SAM_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_ATMEL_SAM_COMMON_PINCTRL_SOC_H_ + +#include + +#endif /* ZEPHYR_SOC_ARM_ATMEL_SAM_COMMON_PINCTRL_SOC_H_ */