From 6058f4972df09b7c530c093a20a6b0e64d490621 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Wed, 7 Sep 2022 11:00:47 +0200 Subject: [PATCH] drivers: pinctrl: Add Silabs Gecko pin controller This commit adds initial support for gecko pinctrl driver Co-authored-by: Mateusz Sierszulski Signed-off-by: Filip Kokosinski --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.gecko | 11 ++ drivers/pinctrl/pinctrl_gecko.c | 103 ++++++++++++++++++ .../pinctrl/silabs,gecko-pinctrl.yaml | 79 ++++++++++++++ .../dt-bindings/pinctrl/gecko-pinctrl.h | 88 +++++++++++++++ 6 files changed, 283 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.gecko create mode 100644 drivers/pinctrl/pinctrl_gecko.c create mode 100644 dts/bindings/pinctrl/silabs,gecko-pinctrl.yaml create mode 100644 include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index a6c8244c880..171dedc88c4 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -27,3 +27,4 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_XLNX_ZYNQ pinctrl_xlnx_zynq.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_SMARTBOND pinctrl_smartbond.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_XMC4XXX pinctrl_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_S32 pinctrl_s32.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_GECKO pinctrl_gecko.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 0647150c806..efc3a2b79f8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -56,5 +56,6 @@ source "drivers/pinctrl/Kconfig.xlnx" source "drivers/pinctrl/Kconfig.smartbond" source "drivers/pinctrl/Kconfig.xmc4xxx" source "drivers/pinctrl/Kconfig.s32" +source "drivers/pinctrl/Kconfig.gecko" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.gecko b/drivers/pinctrl/Kconfig.gecko new file mode 100644 index 00000000000..9bc09b9d8c0 --- /dev/null +++ b/drivers/pinctrl/Kconfig.gecko @@ -0,0 +1,11 @@ +# Copyright (c) 2022 Silicon Labs +# SPDX-License-Identifier: Apache-2.0 +# TODO: copyright changes? + +config PINCTRL_GECKO + bool "Gecko pin controller driver" + default y + depends on DT_HAS_SILABS_GECKO_PINCTRL_ENABLED + select PINCTRL_STORE_REG + help + Gecko pin controller driver diff --git a/drivers/pinctrl/pinctrl_gecko.c b/drivers/pinctrl/pinctrl_gecko.c new file mode 100644 index 00000000000..530044f753d --- /dev/null +++ b/drivers/pinctrl/pinctrl_gecko.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ +#ifdef CONFIG_UART_GECKO + struct soc_gpio_pin rxpin = {0}; + struct soc_gpio_pin txpin = {0}; + USART_TypeDef *base = (USART_TypeDef *)reg; + uint8_t loc; + int usart_num = USART_NUM(base); +#endif /* CONFIG_UART_GECKO */ + + for (uint8_t i = 0U; i < pin_cnt; i++) { + switch (GECKO_GET_FUN(pins[i])) { +#ifdef CONFIG_UART_GECKO + case GECKO_FUN_UART_RX: + rxpin.port = GECKO_GET_PORT(pins[i]); + rxpin.pin = GECKO_GET_PIN(pins[i]); + rxpin.mode = gpioModeInput; + rxpin.out = 1; + GPIO_PinModeSet(rxpin.port, rxpin.pin, rxpin.mode, + rxpin.out); + break; + case GECKO_FUN_UART_TX: + txpin.port = GECKO_GET_PORT(pins[i]); + txpin.pin = GECKO_GET_PIN(pins[i]); + txpin.mode = gpioModePushPull; + txpin.out = 1; + GPIO_PinModeSet(txpin.port, txpin.pin, txpin.mode, + txpin.out); + break; + case GECKO_FUN_UART_LOC: + loc = GECKO_GET_LOC(pins[i]); +#ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION + /* For SOCs with configurable pin locations (set in SOC Kconfig) */ + base->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN; + base->ROUTELOC0 = (loc << _USART_ROUTELOC0_TXLOC_SHIFT) | + (loc << _USART_ROUTELOC0_RXLOC_SHIFT); + base->ROUTELOC1 = _USART_ROUTELOC1_RESETVALUE; +#elif defined(USART_ROUTE_RXPEN) && defined(USART_ROUTE_TXPEN) + /* For olders SOCs with only one pin location */ + base->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (loc << 8); +#elif defined(GPIO_USART_ROUTEEN_RXPEN) && defined(GPIO_USART_ROUTEEN_TXPEN) + GPIO->USARTROUTE[usart_num].ROUTEEN = + GPIO_USART_ROUTEEN_TXPEN | GPIO_USART_ROUTEEN_RXPEN; + GPIO->USARTROUTE[usart_num].TXROUTE = + (txpin.pin << _GPIO_USART_TXROUTE_PIN_SHIFT) | + (txpin.port << _GPIO_USART_TXROUTE_PORT_SHIFT); + GPIO->USARTROUTE[usart_num].RXROUTE = + (rxpin.pin << _GPIO_USART_RXROUTE_PIN_SHIFT) | + (rxpin.port << _GPIO_USART_RXROUTE_PORT_SHIFT); +#endif /* CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION */ + +#ifdef UART_GECKO_HW_FLOW_CONTROL + /* Configure HW flow control (RTS, CTS) */ + if (config->hw_flowcontrol) { + GPIO_PinModeSet(config->pin_rts.port, + config->pin_rts.pin, + config->pin_rts.mode, + config->pin_rts.out); + GPIO_PinModeSet(config->pin_cts.port, + config->pin_cts.pin, + config->pin_cts.mode, + config->pin_cts.out); +#ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION + config->base->ROUTEPEN = + USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN | + USART_ROUTEPEN_RTSPEN | USART_ROUTEPEN_CTSPEN; + + config->base->ROUTELOC1 = + (config->loc_rts << _USART_ROUTELOC1_RTSLOC_SHIFT) | + (config->loc_cts << _USART_ROUTELOC1_CTSLOC_SHIFT); +#elif defined(GPIO_USART_ROUTEEN_RTSPEN) && defined(GPIO_USART_ROUTEEN_CTSPEN) + GPIO->USARTROUTE[usart_num].ROUTEEN = + GPIO_USART_ROUTEEN_TXPEN | GPIO_USART_ROUTEEN_RXPEN | + GPIO_USART_ROUTEPEN_RTSPEN | GPIO_USART_ROUTEPEN_CTSPEN; + + GPIO->USARTROUTE[usart_num].RTSROUTE = + (config->pin_rts.pin << _GPIO_USART_RTSROUTE_PIN_SHIFT) | + (config->pin_rts.port << _GPIO_USART_RTSROUTE_PORT_SHIFT); + GPIO->USARTROUTE[usart_num].CTSROUTE = + (config->pin_cts.pin << _GPIO_USART_CTSROUTE_PIN_SHIFT) | + (config->pin_cts.port << _GPIO_USART_CTSROUTE_PORT_SHIFT); +#endif /* CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION */ + } +#endif /* UART_GECKO_HW_FLOW_CONTROL */ + break; +#endif /* CONFIG_UART_GECKO */ + default: + return -ENOTSUP; + } + } + + return 0; +} diff --git a/dts/bindings/pinctrl/silabs,gecko-pinctrl.yaml b/dts/bindings/pinctrl/silabs,gecko-pinctrl.yaml new file mode 100644 index 00000000000..e986c39c14d --- /dev/null +++ b/dts/bindings/pinctrl/silabs,gecko-pinctrl.yaml @@ -0,0 +1,79 @@ +# Copyright (c) 2022 Silicon Labs +# SPDX-License-Identifier: Apache-2.0 + +description: | + The Silabs 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 usart0 device, default state */ + usart0_default: usart0_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 = , ; + }; + }; + }; + + 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. 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 GECKO_PSEL macro is used to specify a pin function selection. + Available pin functions can be found in the + include/dt-bindings/pinctrl/gecko-pinctrl.h header file. + + 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" + + &usart0 { + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + }; + +compatible: "silabs,gecko-pinctrl" + +include: base.yaml + +child-binding: + description: | + Silabs pin controller pin configuration state nodes. + include: pincfg-node.yaml + child-binding: + description: | + Silabs 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 GECKO_PSEL utility macro that encodes the port, + pin and function. diff --git a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h new file mode 100644 index 00000000000..9eae1c945f9 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Silicon Labs + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ + +/* + * The whole GECKO_pin configuration information is encoded in a 32-bit bitfield + * organized as follows: + * + * - 31..24: Pin function. + * - 23..16: Reserved. + * - 15..8: Port for UART_RX/UART_TX functions. + * - 7..0: Pin number for UART_RX/UART_TX functions. + * - 15..8: Reserved for UART_LOC function. + * - 7..0: Loc for UART_LOC function. + */ + +/** + * @name GECKO_pin configuration bit field positions and masks. + * @{ + */ + +/** Position of the function field. */ +#define GECKO_FUN_POS 24U +/** Mask for the function field. */ +#define GECKO_FUN_MSK 0xFFFU + +/** Position of the pin field. */ +#define GECKO_PIN_POS 0U +/** Mask for the pin field. */ +#define GECKO_PIN_MSK 0xFFU + +/** Position of the port field. */ +#define GECKO_PORT_POS 8U +/** Mask for the port field. */ +#define GECKO_PORT_MSK 0xFFU + +/** Position of the loc field. */ +#define GECKO_LOC_POS 0U +/** Mask for the pin field. */ +#define GECKO_LOC_MSK 0xFFU + +/** @} */ + +/** + * @name GECKO_pinctrl pin functions. + * @{ + */ + +/** UART TX */ +#define GECKO_FUN_UART_TX 0U +/** UART RX */ +#define GECKO_FUN_UART_RX 1U +/** UART RTS */ +#define GECKO_FUN_UART_RTS 2U +/** UART CTS */ +#define GECKO_FUN_UART_CTS 3U +/** UART LOCATION */ +#define GECKO_FUN_UART_LOC 4U + +/** @} */ + +/** + * @brief Utility macro to build GECKO psels property entry. + * + * @param fun Pin function configuration (see GECKO_FUNC_{name} macros). + * @param port Port (0 or 1). + * @param pin Pin (0..31). + */ +#define GECKO_PSEL(fun, port, pin) \ + (((GECKO_PORT_##port & GECKO_PORT_MSK) << GECKO_PORT_POS) | \ + ((GECKO_PIN(##pin##) & GECKO_PIN_MSK) << GECKO_PIN_POS) | \ + ((GECKO_FUN_##fun & GECKO_FUN_MSK) << GECKO_FUN_POS)) + +/** + * @brief Utility macro to build GECKO_psels property entry. + * + * @param fun Pin function configuration (see GECKO_FUNC_{name} macros). + * @param loc Location. + */ +#define GECKO_LOC(fun, loc) \ + (((GECKO_LOCATION(##loc##) & GECKO_LOC_MSK) << GECKO_LOC_POS) | \ + ((GECKO_FUN_##fun##_LOC & GECKO_FUN_MSK) << GECKO_FUN_POS)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ */