diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 91bbb8b3d51..1dce91d5977 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -37,5 +37,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCI_IO_MUX pinctrl_mci_io_mux.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_MAX32 pinctrl_max32.c) add_subdirectory(renesas) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ab6ea86bcc9..b919fa0f169 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -65,6 +65,7 @@ source "drivers/pinctrl/Kconfig.eos_s3" source "drivers/pinctrl/Kconfig.mci_io_mux" source "drivers/pinctrl/Kconfig.ene" source "drivers/pinctrl/Kconfig.zynqmp" +source "drivers/pinctrl/Kconfig.max32" rsource "renesas/Kconfig" diff --git a/drivers/pinctrl/Kconfig.max32 b/drivers/pinctrl/Kconfig.max32 new file mode 100644 index 00000000000..13d5ef77a1c --- /dev/null +++ b/drivers/pinctrl/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_MAX32 + bool "Analog Devices MAX32 MCUs pin controller driver" + default y + depends on DT_HAS_ADI_MAX32_PINCTRL_ENABLED + help + Pin controller driver support for max32 SoC series diff --git a/drivers/pinctrl/pinctrl_max32.c b/drivers/pinctrl/pinctrl_max32.c new file mode 100644 index 00000000000..e9fcf65aa85 --- /dev/null +++ b/drivers/pinctrl/pinctrl_max32.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#define ADI_MAX32_GET_PORT_ADDR_OR_NONE(nodelabel) \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),)) + +/** GPIO port addresses */ +static const uint32_t gpios[] = { + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio0) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio1) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio2) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio3) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio4) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio5) +}; + +static int pinctrl_configure_pin(pinctrl_soc_pin_t soc_pin) +{ + uint32_t port; + uint32_t pin; + uint32_t afx; + int pincfg; + mxc_gpio_cfg_t gpio_cfg; + + port = MAX32_PINMUX_PORT(soc_pin.pinmux); + pin = MAX32_PINMUX_PIN(soc_pin.pinmux); + afx = MAX32_PINMUX_MODE(soc_pin.pinmux); + pincfg = soc_pin.pincfg; + + if (gpios[port] == 0) { + return -EINVAL; + } + + gpio_cfg.port = (mxc_gpio_regs_t *)gpios[port]; + gpio_cfg.mask = BIT(pin); + + if (pincfg & BIT(MAX32_BIAS_PULL_UP_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_UP; + } else if (pincfg & BIT(MAX32_BIAS_PULL_DOWN_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_DOWN; + } else { + gpio_cfg.pad = MXC_GPIO_PAD_NONE; + } + + if (pincfg & BIT(MAX32_INPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_IN; + } else if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_OUT; + } else { + /* Add +1 to index match */ + gpio_cfg.func = (mxc_gpio_func_t)(afx + 1); + } + + if (pincfg & BIT(MAX32_POWER_SOURCE_SHIFT)) { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIOH; + } else { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIO; + } + + switch (pincfg & MAX32_GPIO_DRV_STRENGTH_MASK) { + case MAX32_GPIO_DRV_STRENGTH_1: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_1; + break; + case MAX32_GPIO_DRV_STRENGTH_2: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_2; + break; + case MAX32_GPIO_DRV_STRENGTH_3: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_3; + break; + default: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_0; + break; + } + + if (MXC_GPIO_Config(&gpio_cfg) != 0) { + return -ENOTSUP; + } + + if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + if (pincfg & BIT(MAX32_OUTPUT_HIGH_SHIFT)) { + MXC_GPIO_OutSet(gpio_cfg.port, BIT(pin)); + } else { + MXC_GPIO_OutClr(gpio_cfg.port, BIT(pin)); + } + } + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + int ret; + + for (uint8_t i = 0U; i < pin_cnt; i++) { + ret = pinctrl_configure_pin(*pins++); + if (ret) { + return ret; + } + } + + return 0; +} diff --git a/dts/bindings/pinctrl/adi,max32-pinctrl.yaml b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml new file mode 100644 index 00000000000..d40926ca772 --- /dev/null +++ b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml @@ -0,0 +1,90 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + MAX32 Pin controller Node + Based on pincfg-node.yaml binding. + + Note: `bias-disable` are default pin configurations. + +compatible: "adi,max32-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + + +child-binding: + description: | + Base binding configuration for ADI MAX32xxx MCUs + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - output-low + - output-high + - input-enable + - output-enable + - power-source + - drive-strength + + properties: + pinmux: + required: true + type: int + description: | + Integer array, represents gpio pin number and mux setting. + These defines are calculated as: (pin<<8 | port<<4 | function<<0) + With: + - port: The gpio port index (0, 1, ...) + - pin: The pin offset within the port (0, 1, 2, ...) + - function: The function number, can be: + * 0 : GPIO + * 1 : Alternate Function 1 + * 2 : Alternate Function 2 + * 3 : Alternate Function 3 + * 4 : Alternate Function 4 + In case selected pin function is GPIO, pin is statically configured as + a plain input/output GPIO. Default configuration is input. Output value + can be configured by adding 'ouptut-low' or 'output-high' properties + to the pin configuration. + + To simplify the usage, macro is available to generate "pinmux" field. + This macro is available here: + -include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h + Some examples of macro usage: + P0.9 set as alernate function 1 + { + pinmux = ; + }; + P0.9 set as alernate function 2 + { + pinmux = ; + }; + P0.9 set as GPIO output high + { + pinmux = ; + output-high; + }; + power-source: + enum: [0, 1] + description: | + GPIO Supply Voltage Select, Selects the voltage rail used for the pin. + 0 or MAX32_VSEL_VDDIO + 1 or MAX32_VSEL_VDDIOH + drive-strength: + default: 0 + enum: [0, 1, 2, 3] + description: | + There are 4 drive strength mode. + Mode 0: 1mA + Mode 1: 2mA + Mode 2: 4mA + Mode 3: 8mA + Default GPIO output drive strength is mode 0 for MAX32 MCUs. + For more information please take a look device user guide, datasheet. diff --git a/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h new file mode 100644 index 00000000000..97a3ab76748 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ + +/** + * @brief Pin modes + */ +#define MAX32_MODE_GPIO 0x00 +#define MAX32_MODE_AF1 0x01 +#define MAX32_MODE_AF2 0x02 +#define MAX32_MODE_AF3 0x03 +#define MAX32_MODE_AF4 0x04 +#define MAX32_MODE_AF5 0x05 + +/** + * @brief Mode, port, pin shift number + */ +#define MAX32_MODE_SHIFT 0U +#define MAX32_MODE_MASK 0x0FU +#define MAX32_PORT_SHIFT 4U +#define MAX32_PORT_MASK 0x0FU +#define MAX32_PIN_SHIFT 8U +#define MAX32_PIN_MASK 0xFFU + +/** + * @brief Pin configuration bit field. + * + * Fields: + * + * - mode [ 0 : 3 ] + * - port [ 4 : 7 ] + * - pin [ 8 : 15 ] + * + * @param port Port (0 .. 15) + * @param pin Pin (0..31) + * @param mode Mode (GPIO, AF1, AF2...). + */ +#define MAX32_PINMUX(port, pin, mode) \ + ((((port)&MAX32_PORT_MASK) << MAX32_PORT_SHIFT) | \ + (((pin)&MAX32_PIN_MASK) << MAX32_PIN_SHIFT) | \ + (((MAX32_MODE_##mode) & MAX32_MODE_MASK) << MAX32_MODE_SHIFT)) + +#define MAX32_PINMUX_PORT(pinmux) (((pinmux) >> MAX32_PORT_SHIFT) & MAX32_PORT_MASK) +#define MAX32_PINMUX_PIN(pinmux) (((pinmux) >> MAX32_PIN_SHIFT) & MAX32_PIN_MASK) +#define MAX32_PINMUX_MODE(pinmux) (((pinmux) >> MAX32_MODE_SHIFT) & MAX32_MODE_MASK) + +/* Selects the voltage rail used for the pin */ +#define MAX32_VSEL_VDDIO 0 +#define MAX32_VSEL_VDDIOH 1 + +/** + * @brief Pin configuration + */ +#define MAX32_INPUT_ENABLE_SHIFT 0x00 +#define MAX32_BIAS_PULL_UP_SHIFT 0x01 +#define MAX32_BIAS_PULL_DOWN_SHIFT 0x02 +#define MAX32_OUTPUT_ENABLE_SHIFT 0x03 +#define MAX32_POWER_SOURCE_SHIFT 0x04 +#define MAX32_OUTPUT_HIGH_SHIFT 0x05 +#define MAX32_DRV_STRENGTH_SHIFT 0x06 /* 2 bits */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ */ diff --git a/soc/adi/max32/common/pinctrl_soc.h b/soc/adi/max32/common/pinctrl_soc.h new file mode 100644 index 00000000000..d9a56f422b2 --- /dev/null +++ b/soc/adi/max32/common/pinctrl_soc.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pinctrl_soc_pin { + uint32_t pinmux; + uint32_t pincfg; +} pinctrl_soc_pin_t; + +#define Z_PINCTRL_MAX32_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) + +#define Z_PINCTRL_MAX32_PINCFG_INIT(node) \ + ((DT_PROP_OR(node, input_enable, 0) << MAX32_INPUT_ENABLE_SHIFT) | \ + (DT_PROP_OR(node, output_enable, 0) << MAX32_OUTPUT_ENABLE_SHIFT) | \ + (DT_PROP_OR(node, bias_pull_up, 0) << MAX32_BIAS_PULL_UP_SHIFT) | \ + (DT_PROP_OR(node, bias_pull_down, 0) << MAX32_BIAS_PULL_DOWN_SHIFT) | \ + (DT_PROP_OR(node, power_source, 0) << MAX32_POWER_SOURCE_SHIFT) | \ + (DT_PROP_OR(node, output_high, 0) << MAX32_OUTPUT_HIGH_SHIFT) | \ + (DT_PROP_OR(node, drive_strength, 0) << MAX32_DRV_STRENGTH_SHIFT)) + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \ + {.pinmux = Z_PINCTRL_MAX32_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pincfg = Z_PINCTRL_MAX32_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))}, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ */