From fc8877187e0f9a8f6b88f855a670c3d7a49cdc04 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 21 Feb 2022 12:54:05 -0600 Subject: [PATCH] drivers: pinctrl: Add kinetis pinctrl driver Add kinetis pinctrl driver. Driver initializes clocks for each port, and exposes the pinctrl_configure_pins function required for pinctrl support. Signed-off-by: Daniel DeGrasse --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.kinetis | 11 +++++ drivers/pinctrl/pinctrl_kinetis.c | 82 +++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.kinetis create mode 100644 drivers/pinctrl/pinctrl_kinetis.c diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 8e3bf4df6d8..0fd6d21796f 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -10,3 +10,4 @@ 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_STM32 pinctrl_stm32.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_KINETIS pinctrl_kinetis.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 96adf043b05..9ae5df91103 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -35,5 +35,6 @@ source "drivers/pinctrl/Kconfig.nrf" source "drivers/pinctrl/Kconfig.rcar" source "drivers/pinctrl/Kconfig.rpi_pico" source "drivers/pinctrl/Kconfig.stm32" +source "drivers/pinctrl/Kconfig.kinetis" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.kinetis b/drivers/pinctrl/Kconfig.kinetis new file mode 100644 index 00000000000..d8265eb05a5 --- /dev/null +++ b/drivers/pinctrl/Kconfig.kinetis @@ -0,0 +1,11 @@ +# Copyright (c) 2022 NXP +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_NXP_KINETIS_PINCTRL := nxp,kinetis-pinctrl + +config PINCTRL_NXP_KINETIS + bool "Pin controller driver for NXP Kinetis MCUs" + depends on SOC_FAMILY_KINETIS + default $(dt_compat_enabled,$(DT_COMPAT_NXP_KINETIS_PINCTRL)) + help + Enable pin controller driver for NXP Kinetis MCUs diff --git a/drivers/pinctrl/pinctrl_kinetis.c b/drivers/pinctrl/pinctrl_kinetis.c new file mode 100644 index 00000000000..78df9c4b90e --- /dev/null +++ b/drivers/pinctrl/pinctrl_kinetis.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#define DT_DRV_COMPAT nxp_kinetis_pinmux + +#include +#include + +/* Port register addresses. */ +static PORT_Type *ports[] = { + (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(porta)), + (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(portb)), + (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(portc)), +#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 5 + (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(portd)), + (PORT_Type *)DT_REG_ADDR(DT_NODELABEL(porte)), +#endif +}; + +#define PIN(mux) (((mux) & 0xFC00000) >> 22) +#define PORT(mux) (((mux) & 0xF0000000) >> 28) +#define PINCFG(mux) ((mux) & Z_PINCTRL_KINETIS_PCR_MASK) + +struct pinctrl_mcux_config { + clock_ip_name_t clock_ip_name; +}; + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ + for (uint8_t i = 0; i < pin_cnt; i++) { + PORT_Type *base = ports[PORT(pins[i])]; + uint8_t pin = PIN(pins[i]); + uint16_t mux = PINCFG(pins[i]); + + base->PCR[pin] = (base->PCR[pin] & (~Z_PINCTRL_KINETIS_PCR_MASK)) | mux; + } + return 0; +} + +/* Kinetis pinmux driver binds to the same DTS nodes, + * and handles clock init. Only bind to these nodes if pinmux driver + * is disabled. + */ +#ifndef CONFIG_PINMUX +static int pinctrl_mcux_init(const struct device *dev) +{ + const struct pinctrl_mcux_config *config = dev->config; + + CLOCK_EnableClock(config->clock_ip_name); + + return 0; +} + +#if DT_NODE_HAS_STATUS(DT_INST(0, nxp_kinetis_ke1xf_sim), okay) +#define INST_DT_CLOCK_IP_NAME(n) \ + DT_REG_ADDR(DT_INST_PHANDLE(n, clocks)) + DT_INST_CLOCKS_CELL(n, name) +#else +#define INST_DT_CLOCK_IP_NAME(n) \ + CLK_GATE_DEFINE(DT_INST_CLOCKS_CELL(n, offset), \ + DT_INST_CLOCKS_CELL(n, bits)) +#endif + +#define PINCTRL_MCUX_INIT(n) \ + static const struct pinctrl_mcux_config pinctrl_mcux_##n##_config = {\ + .clock_ip_name = INST_DT_CLOCK_IP_NAME(n), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &pinctrl_mcux_init, \ + NULL, \ + NULL, &pinctrl_mcux_##n##_config, \ + PRE_KERNEL_1, \ + 0, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(PINCTRL_MCUX_INIT) +#endif