diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index c6e21f9b1b3..a922c5ee83c 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -10,6 +10,7 @@ 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_SAM0 pinctrl_sam0.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 f871264cb5b..833ac288d9f 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -35,6 +35,7 @@ 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.sam0" source "drivers/pinctrl/Kconfig.stm32" source "drivers/pinctrl/Kconfig.kinetis" source "drivers/pinctrl/Kconfig.xec" diff --git a/drivers/pinctrl/Kconfig.sam0 b/drivers/pinctrl/Kconfig.sam0 new file mode 100644 index 00000000000..18a4d2402bd --- /dev/null +++ b/drivers/pinctrl/Kconfig.sam0 @@ -0,0 +1,11 @@ +# Copyright (c) 2022, Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_ATMEL_SAM0_PINCTRL := atmel,sam0-pinctrl + +config PINCTRL_SAM0 + bool "Atmel SAM0 pin controller driver" + depends on SOC_FAMILY_SAM0 + default $(dt_compat_enabled,$(DT_COMPAT_ATMEL_SAM0_PINCTRL)) + help + Atmel pin controller driver is used on SAM0 SoC series diff --git a/drivers/pinctrl/pinctrl_sam0.c b/drivers/pinctrl/pinctrl_sam0.c new file mode 100644 index 00000000000..12adfc2a16e --- /dev/null +++ b/drivers/pinctrl/pinctrl_sam0.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** Utility macro that expands to the PORT 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)),)) + +/** SAM0 port addresses */ +static const uint32_t sam_port_addrs[] = { + SAM_PORT_ADDR_OR_NONE(porta) + SAM_PORT_ADDR_OR_NONE(portb) + SAM_PORT_ADDR_OR_NONE(portc) + SAM_PORT_ADDR_OR_NONE(portd) + SAM_PORT_ADDR_OR_NONE(porte) + SAM_PORT_ADDR_OR_NONE(portf) +}; + +static void pinctrl_configure_pin(pinctrl_soc_pin_t pin) +{ + struct soc_port_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); + + soc_pin.regs = (PortGroup *) sam_port_addrs[port_idx]; + soc_pin.pinum = SAM_PINMUX_PIN_GET(pin); + soc_pin.flags = SAM_PINCTRL_FLAGS_GET(pin) << SOC_PORT_FLAGS_POS; + + if (port_func == SAM_PINMUX_FUNC_periph) { + soc_pin.flags |= (SAM_PINMUX_PERIPH_GET(pin) + << SOC_PORT_FUNC_POS) + | SOC_PORT_PMUXEN_ENABLE; + } + + soc_port_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,sam0-pinctrl.yaml b/dts/bindings/pinctrl/atmel,sam0-pinctrl.yaml index 8a1081feb21..d3ad25a9f41 100644 --- a/dts/bindings/pinctrl/atmel,sam0-pinctrl.yaml +++ b/dts/bindings/pinctrl/atmel,sam0-pinctrl.yaml @@ -1,34 +1,91 @@ # Copyright (c) 2020, Linaro Limited -# Copyright (c) 2021, Gerson Fernando Budke +# Copyright (c) 2021-2022, Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: | Atmel SAM0 Pinctrl container node - The Atmel SAM0 pins implements following pin configuration option: + The Atmel SAM0 pin controller is a singleton node responsible for controlling + pin function selection and pin properties. For example, you can use this node + to route SERCOM0 as UART were RX to pin PAD1 and enable the pull-up resistor + on the pin. - * bias-pull-up - * bias-pull-down - * drive-strength - * input-enable - * output-enable - * pinmux-enable + 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_SAM0_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 */ + sercom0_uart_default: sercom0_uart_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-strength: Increase sink current. + - input-enable: Enable input on pin. + - output-enable: Enable output on a pin without actively driving it. + + 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,sam0-pinctrl" include: - name: base.yaml - - name: pincfg-node.yaml + - name: pincfg-node-group.yaml child-binding: - property-allowlist: - - bias-pull-up - - bias-pull-down - - drive-strength - - input-enable - - output-enable + child-binding: + property-allowlist: + - bias-pull-up + - bias-pull-down + - drive-strength + - input-enable + - output-enable properties: reg: @@ -43,13 +100,27 @@ 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-enable: - required: false - type: boolean + pinmux: + required: true + type: array description: | - Assign pin to an embedded device peripheral + 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. + drive-strength: + enum: + - 0 + - 1 + default: 0 + description: | + The drive strength controls the output driver strength of an I/O pin + configured as an output. + 0: Pin drive strength is set to normal drive strength. + 1: Pin drive strength is set to stronger drive strength. diff --git a/include/drivers/pinctrl/pinctrl_soc_sam_common.h b/include/drivers/pinctrl/pinctrl_soc_sam_common.h index bd3aad5188e..31cdc197132 100644 --- a/include/drivers/pinctrl/pinctrl_soc_sam_common.h +++ b/include/drivers/pinctrl/pinctrl_soc_sam_common.h @@ -38,12 +38,23 @@ typedef uint32_t pinctrl_soc_pin_t; * @param prop Property name. * @param idx Property entry index. */ +#if defined(CONFIG_SOC_FAMILY_SAM) #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) \ ), +#else /* CONFIG_SOC_FAMILY_SAM0 */ +#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, input_enable) << SAM_PINCTRL_INPUTENABLE_POS) \ + | (DT_PROP(node_id, output_enable) << SAM_PINCTRL_OUTPUTENABLE_POS) \ + | (DT_ENUM_IDX(node_id, drive_strength) << SAM_PINCTRL_DRIVESTRENGTH_POS)\ + ), +#endif /** * @brief Utility macro to initialize state pins contained in a given property. @@ -68,7 +79,7 @@ typedef uint32_t pinctrl_soc_pin_t; #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_FLAGS_MASK (0x3F << 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) @@ -76,6 +87,12 @@ typedef uint32_t pinctrl_soc_pin_t; #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) +#define SAM_PINCTRL_INPUTENABLE_POS (SAM_PINCTRL_OPENDRAIN_POS + 1U) +#define SAM_PINCTRL_INPUTENABLE (1U << SAM_PINCTRL_INPUTENABLE_POS) +#define SAM_PINCTRL_OUTPUTENABLE_POS (SAM_PINCTRL_INPUTENABLE_POS + 1U) +#define SAM_PINCTRL_OUTPUTENABLE (1U << SAM_PINCTRL_OUTPUTENABLE_POS) +#define SAM_PINCTRL_DRIVESTRENGTH_POS (SAM_PINCTRL_OUTPUTENABLE_POS + 1U) +#define SAM_PINCTRL_DRIVESTRENGTH (1U << SAM_PINCTRL_DRIVESTRENGTH_POS) /** @} */ diff --git a/soc/arm/atmel_sam0/Kconfig.defconfig b/soc/arm/atmel_sam0/Kconfig.defconfig index 0569ef9281d..b4f25f92c75 100644 --- a/soc/arm/atmel_sam0/Kconfig.defconfig +++ b/soc/arm/atmel_sam0/Kconfig.defconfig @@ -4,3 +4,10 @@ # SPDX-License-Identifier: Apache-2.0 source "soc/arm/atmel_sam0/*/Kconfig.defconfig.series" + +if SOC_FAMILY_SAM0 + +config PINCTRL + default y + +endif # SOC_FAMILY_SAM0 diff --git a/soc/arm/atmel_sam0/common/pinctrl_soc.h b/soc/arm/atmel_sam0/common/pinctrl_soc.h new file mode 100644 index 00000000000..f8e6216878a --- /dev/null +++ b/soc/arm/atmel_sam0/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_ */ diff --git a/soc/arm/atmel_sam0/common/soc_port.h b/soc/arm/atmel_sam0/common/soc_port.h index 2c90fd9bd5d..f7beba6ea92 100644 --- a/soc/arm/atmel_sam0/common/soc_port.h +++ b/soc/arm/atmel_sam0/common/soc_port.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2017 Piotr Mienkowski - * Copyright (c) 2020-2021 Gerson Fernando Budke + * Copyright (c) 2020-2022 Gerson Fernando Budke * SPDX-License-Identifier: Apache-2.0 */ @@ -19,26 +19,28 @@ #define SOC_PORT_DEFAULT (0) #define SOC_PORT_FLAGS_POS (0) -#define SOC_PORT_FLAGS_MASK (0x3F << SOC_PORT_FLAGS_POS) -#define SOC_PORT_PULLUP_POS (0) +#define SOC_PORT_FLAGS_MASK (0x7B << SOC_PORT_FLAGS_POS) +#define SOC_PORT_PULLUP_POS (SOC_PORT_FLAGS_POS) #define SOC_PORT_PULLUP (1 << SOC_PORT_PULLUP_POS) -#define SOC_PORT_PULLDOWN_POS (1) +#define SOC_PORT_PULLDOWN_POS (SOC_PORT_PULLUP_POS + 1U) #define SOC_PORT_PULLDOWN (1 << SOC_PORT_PULLDOWN_POS) +/* Open-Drain is a reserved entry at pinctrl driver */ +#define SOC_GPIO_OPENDRAIN_POS (SOC_PORT_PULLDOWN_POS + 1U) /* Input-Enable means Input-Buffer, see dts/pinctrl/pincfg-node.yaml */ -#define SOC_PORT_INPUT_ENABLE_POS (2) +#define SOC_PORT_INPUT_ENABLE_POS (SOC_GPIO_OPENDRAIN_POS + 1U) #define SOC_PORT_INPUT_ENABLE (1 << SOC_PORT_INPUT_ENABLE_POS) /* Output-Enable, see dts/pinctrl/pincfg-node.yaml */ -#define SOC_PORT_OUTPUT_ENABLE_POS (3) +#define SOC_PORT_OUTPUT_ENABLE_POS (SOC_PORT_INPUT_ENABLE_POS + 1U) #define SOC_PORT_OUTPUT_ENABLE (1 << SOC_PORT_OUTPUT_ENABLE_POS) /* Drive-Strength, 0mA means normal, any other value means stronger */ -#define SOC_PORT_STRENGTH_STRONGER_POS (4) +#define SOC_PORT_STRENGTH_STRONGER_POS (SOC_PORT_OUTPUT_ENABLE_POS + 1U) #define SOC_PORT_STRENGTH_STRONGER (1 << SOC_PORT_STRENGTH_STRONGER_POS) /* Peripheral Multiplexer Enable */ -#define SOC_PORT_PMUXEN_ENABLE_POS (5) +#define SOC_PORT_PMUXEN_ENABLE_POS (SOC_PORT_STRENGTH_STRONGER_POS + 1U) #define SOC_PORT_PMUXEN_ENABLE (1 << SOC_PORT_PMUXEN_ENABLE_POS) /* Bit field: SOC_PORT_FUNC */ -#define SOC_PORT_FUNC_POS (16) +#define SOC_PORT_FUNC_POS (16U) #define SOC_PORT_FUNC_MASK (0xF << SOC_PORT_FUNC_POS) /** Connect pin to peripheral A. */