diff --git a/boards/arm/frdm_k22f/pinmux.c b/boards/arm/frdm_k22f/pinmux.c index 1342f91df9d29..8a2209bf34731 100644 --- a/boards/arm/frdm_k22f/pinmux.c +++ b/boards/arm/frdm_k22f/pinmux.c @@ -38,22 +38,6 @@ static int frdm_k22f_pinmux_init(const struct device *dev) __ASSERT_NO_MSG(device_is_ready(porte)); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL -#error "No UART0 is used" -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay) && CONFIG_SERIAL - /* UART1 RX, TX */ - pinmux_pin_set(porte, 0, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(porte, 1, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay) && CONFIG_SERIAL - /* UART2 RX, TX */ - pinmux_pin_set(portd, 2, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portd, 3, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ftm0), nxp_kinetis_ftm_pwm, okay) && CONFIG_PWM /* Red, green, blue LEDs as PWM channels*/ pinmux_pin_set(porta, 1, PORT_PCR_MUX(kPORT_MuxAlt3)); diff --git a/boards/arm/frdm_k64f/pinmux.c b/boards/arm/frdm_k64f/pinmux.c index 1636231e4228a..d254dfd7017ce 100644 --- a/boards/arm/frdm_k64f/pinmux.c +++ b/boards/arm/frdm_k64f/pinmux.c @@ -38,26 +38,6 @@ static int frdm_k64f_pinmux_init(const struct device *dev) __ASSERT_NO_MSG(device_is_ready(porte)); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL - /* UART0 RX, TX */ - pinmux_pin_set(portb, 16, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portb, 17, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart2), okay) && CONFIG_SERIAL - /* UART2 RX, TX */ - pinmux_pin_set(portd, 0, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portd, 1, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portd, 2, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portd, 3, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart3), okay) && CONFIG_SERIAL - /* UART3 RX, TX */ - pinmux_pin_set(portc, 16, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portc, 17, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi0), okay) && CONFIG_SPI /* SPI0 CS0, SCK, SOUT, SIN */ pinmux_pin_set(portd, 0, PORT_PCR_MUX(kPORT_MuxAlt2)); diff --git a/boards/arm/frdm_kl25z/pinmux.c b/boards/arm/frdm_kl25z/pinmux.c index 8ecd70c62a944..d2fb116d9fc07 100644 --- a/boards/arm/frdm_kl25z/pinmux.c +++ b/boards/arm/frdm_kl25z/pinmux.c @@ -38,12 +38,6 @@ static int frdm_kl25z_pinmux_init(const struct device *dev) __ASSERT_NO_MSG(device_is_ready(porte)); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL - /* UART0 RX, TX */ - pinmux_pin_set(porta, 1, PORT_PCR_MUX(kPORT_MuxAlt2)); - pinmux_pin_set(porta, 2, PORT_PCR_MUX(kPORT_MuxAlt2)); -#endif - #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c0), okay) && CONFIG_I2C /* I2C0 SCL, SDA */ pinmux_pin_set(porte, 24, PORT_PCR_MUX(kPORT_MuxAlt5) diff --git a/boards/arm/hexiwear_k64/pinmux.c b/boards/arm/hexiwear_k64/pinmux.c index aa1c8a9593439..d593f7271c6cc 100644 --- a/boards/arm/hexiwear_k64/pinmux.c +++ b/boards/arm/hexiwear_k64/pinmux.c @@ -62,18 +62,6 @@ static int hexiwear_k64_pinmux_init(const struct device *dev) | PORT_PCR_ODE_MASK); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL - /* UART0 RX, TX */ - pinmux_pin_set(portb, 16, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(portb, 17, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart4), okay) && CONFIG_SERIAL - /* UART4 RX, TX - BLE */ - pinmux_pin_set(porte, 24, PORT_PCR_MUX(kPORT_MuxAlt3)); - pinmux_pin_set(porte, 25, PORT_PCR_MUX(kPORT_MuxAlt3)); -#endif - #if defined(CONFIG_MAX30101) && DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) const struct device *gpioa = device_get_binding(DT_LABEL(DT_NODELABEL(gpioa))); diff --git a/boards/arm/twr_kv58f220m/pinmux.c b/boards/arm/twr_kv58f220m/pinmux.c index ca5031247d71e..3c112418871fb 100644 --- a/boards/arm/twr_kv58f220m/pinmux.c +++ b/boards/arm/twr_kv58f220m/pinmux.c @@ -46,12 +46,6 @@ static int twr_kv58f220m_pinmux_init(const struct device *dev) | PORT_PCR_ODE_MASK); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL - /* UART0 RX, TX */ - pinmux_pin_set(portb, 0, PORT_PCR_MUX(kPORT_MuxAlt7)); - pinmux_pin_set(portb, 1, PORT_PCR_MUX(kPORT_MuxAlt7)); -#endif - return 0; } diff --git a/boards/arm/usb_kw24d512/pinmux.c b/boards/arm/usb_kw24d512/pinmux.c index fd23091163f9a..69af39ff139e1 100644 --- a/boards/arm/usb_kw24d512/pinmux.c +++ b/boards/arm/usb_kw24d512/pinmux.c @@ -38,12 +38,6 @@ static int usb_kw24d512_pinmux_init(const struct device *dev) __ASSERT_NO_MSG(device_is_ready(porte)); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) && CONFIG_SERIAL - /* UART0 RX, TX */ - pinmux_pin_set(porta, 1, PORT_PCR_MUX(kPORT_MuxAlt2)); - pinmux_pin_set(porta, 2, PORT_PCR_MUX(kPORT_MuxAlt2)); -#endif - #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay) && CONFIG_SPI /* SPI1 CS0, SCK, SOUT, SIN */ pinmux_pin_set(portb, 10, PORT_PCR_MUX(kPORT_MuxAlt2)); diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index cd3eca95d8d74..db00a3f0204ef 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -3,3 +3,4 @@ zephyr_library() zephyr_library_sources(common.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_MCUX pinctrl_nxp_mcux.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7e1a67175b84c..64d7f78363bf0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -29,4 +29,11 @@ config PINCTRL_DYNAMIC runtime. This can be useful, for example, to change the pins assigned to a peripheral at early boot stages depending on a certain input. +config PINCTRL_NXP_MCUX + bool "Pin controller driver for NXP Kinetis MCUs" + depends on SOC_FAMILY_KINETIS + default y + help + Enable pin controller driver for NXP Kinetis MCUs + endif # PINCTRL diff --git a/drivers/pinctrl/pinctrl_nxp_mcux.c b/drivers/pinctrl/pinctrl_nxp_mcux.c new file mode 100644 index 0000000000000..2d146d99344fa --- /dev/null +++ b/drivers/pinctrl/pinctrl_nxp_mcux.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021 Linaro Limited. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +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++) { + pins[i].port_reg->PCR[pins[i].pin] = pins[i].mux; + } + + return 0; +} diff --git a/drivers/serial/uart_mcux.c b/drivers/serial/uart_mcux.c index 0e9ca5c097291..046e91d401d14 100644 --- a/drivers/serial/uart_mcux.c +++ b/drivers/serial/uart_mcux.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,7 @@ struct uart_mcux_config { #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); #endif + const struct pinctrl_dev_config *pincfg; }; struct uart_mcux_data { @@ -39,6 +41,12 @@ static int uart_mcux_configure(const struct device *dev, uart_config_t uart_config; uint32_t clock_freq; status_t retval; + int ret; + + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_freq)) { @@ -359,10 +367,13 @@ static const struct uart_driver_api uart_mcux_driver_api = { }; #define UART_MCUX_DECLARE_CFG(n, IRQ_FUNC_INIT) \ + PINCTRL_DT_INST_DEFINE(n) \ + \ static const struct uart_mcux_config uart_mcux_##n##_config = { \ .base = (UART_Type *)DT_INST_REG_ADDR(n), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ IRQ_FUNC_INIT \ } diff --git a/dts/bindings/pinctrl/nxp,kinetis-pinmux.yaml b/dts/bindings/pinctrl/nxp,kinetis-pinmux.yaml index fc236da138a77..52f3a39b4ab37 100644 --- a/dts/bindings/pinctrl/nxp,kinetis-pinmux.yaml +++ b/dts/bindings/pinctrl/nxp,kinetis-pinmux.yaml @@ -5,6 +5,11 @@ compatible: "nxp,kinetis-pinmux" include: - name: base.yaml - name: pincfg-node.yaml + child-binding: + property-allowlist: + - bias-pull-down + - bias-pull-up + - drive-open-drain properties: reg: diff --git a/dts/bindings/serial/nxp,kinetis-uart.yaml b/dts/bindings/serial/nxp,kinetis-uart.yaml index ae3ed052e8c7b..fda90a5c9f984 100644 --- a/dts/bindings/serial/nxp,kinetis-uart.yaml +++ b/dts/bindings/serial/nxp,kinetis-uart.yaml @@ -2,7 +2,7 @@ description: Kinetis UART compatible: "nxp,kinetis-uart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: @@ -14,6 +14,5 @@ properties: clocks: required: true - pinctrl-0: - type: phandles + pinctrl-names: required: true diff --git a/soc/arm/nxp_kinetis/CMakeLists.txt b/soc/arm/nxp_kinetis/CMakeLists.txt index 64b24a7cd1bb0..1db1ea6b6bc89 100644 --- a/soc/arm/nxp_kinetis/CMakeLists.txt +++ b/soc/arm/nxp_kinetis/CMakeLists.txt @@ -4,6 +4,9 @@ zephyr_sources_ifdef(CONFIG_KINETIS_FLASH_CONFIG flash_configuration.c) add_subdirectory(${SOC_SERIES}) +# This is for access to pinmux macros +zephyr_include_directories(common) + zephyr_linker_sources_ifdef(CONFIG_KINETIS_FLASH_CONFIG ROM_START SORT_KEY ${CONFIG_KINETIS_FLASH_CONFIG_OFFSET} diff --git a/soc/arm/nxp_kinetis/Kconfig b/soc/arm/nxp_kinetis/Kconfig index 0c6a2b50b632d..ccf3b0783b88e 100644 --- a/soc/arm/nxp_kinetis/Kconfig +++ b/soc/arm/nxp_kinetis/Kconfig @@ -5,6 +5,7 @@ config SOC_FAMILY_KINETIS bool select HAS_SEGGER_RTT + select PINCTRL if SOC_FAMILY_KINETIS diff --git a/soc/arm/nxp_kinetis/common/pinctrl_soc.h b/soc/arm/nxp_kinetis/common/pinctrl_soc.h new file mode 100644 index 0000000000000..07224cdac5085 --- /dev/null +++ b/soc/arm/nxp_kinetis/common/pinctrl_soc.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Linaro Limited. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Public APIs for pin control drivers + */ + +#ifndef ZEPHYR_SOC_ARM_NXP_KINETIS_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_NXP_KINETIS_COMMON_PINCTRL_SOC_H_ + +/** + * @brief Pin Controller Interface (NXP Kinetis) + * @defgroup pinctrl_interface_nxp_kinetis Pin Controller Interface + * @ingroup pinctrl_interface + * @{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** Type for NXP Kinetis pin. */ +typedef struct pinctrl_soc_pin { + PORT_Type *port_reg; + uint8_t pin; + uint16_t mux; +} pinctrl_soc_pin_t; + +#define PINCTRL_SOC_PINS_ELEM_INIT(node_id) \ +{ \ + .port_reg = (PORT_Type *)DT_REG_ADDR(DT_PARENT(node_id)), \ + .pin = DT_PROP_BY_IDX(node_id, nxp_kinetis_port_pins, 0), \ + .mux = PORT_PCR_MUX(DT_PROP_BY_IDX(node_id, nxp_kinetis_port_pins, 1)) | \ + (DT_PROP(node_id, bias_pull_up) & (PORT_PCR_PE_MASK | PORT_PCR_PS_MASK)) | \ + (DT_PROP(node_id, bias_pull_down) & PORT_PCR_PS_MASK) | \ + (DT_PROP(node_id, drive_open_drain) & PORT_PCR_ODE_MASK), \ +}, + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param state_prop State property name. + * @param idx State property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \ + PINCTRL_SOC_PINS_ELEM_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)) + +/** + * @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_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT)} + +/** @endcond */ + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_SOC_ARM_NXP_KINETIS_COMMON_PINCTRL_SOC_H_ */