diff --git a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig index 1d662ffe260..7487c8f9c29 100644 --- a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig +++ b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906_defconfig @@ -12,6 +12,7 @@ CONFIG_RTOS_TIMER=y CONFIG_CLOCK_CONTROL=y CONFIG_GPIO=y CONFIG_PINMUX=y +CONFIG_PINCTRL=y CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 0fd6d21796f..df5cbb1bb7e 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -11,3 +11,4 @@ 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) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCHP_XEC pinctrl_mchp_xec.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 9ae5df91103..c55f6b4f3d9 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -36,5 +36,6 @@ source "drivers/pinctrl/Kconfig.rcar" source "drivers/pinctrl/Kconfig.rpi_pico" source "drivers/pinctrl/Kconfig.stm32" source "drivers/pinctrl/Kconfig.kinetis" +source "drivers/pinctrl/Kconfig.xec" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.xec b/drivers/pinctrl/Kconfig.xec new file mode 100644 index 00000000000..fdcdf627cb4 --- /dev/null +++ b/drivers/pinctrl/Kconfig.xec @@ -0,0 +1,11 @@ +# Copyright (c) 2021 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_ST_PINCTRL_XEC := microchip,xec-pinctrl + +config PINCTRL_MCHP_XEC + bool "Pin controller driver for MCHP XEC MCUs" + depends on SOC_SERIES_MEC172X + default $(dt_compat_enabled,$(DT_COMPAT_ST_PINCTRL_XEC)) + help + Enable pin controller driver for Microchip XEC MCUs diff --git a/drivers/pinctrl/pinctrl_mchp_xec.c b/drivers/pinctrl/pinctrl_mchp_xec.c new file mode 100644 index 00000000000..05fece95283 --- /dev/null +++ b/drivers/pinctrl/pinctrl_mchp_xec.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Open-RnD Sp. z o.o. + * Copyright (c) 2021 Linaro Limited + * Copyright (c) 2021 Nordic Semiconductor ASA + * Copyright (c) 2021 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_xec_pinctrl + +#include +#include + +/* Microchip XEC: each GPIO pin has two 32-bit control register. + * The first 32-bit register contains all pin features except + * slew rate and driver strength in the second control register. + * We compute the register index from the beginning of the GPIO + * control address space which is the same range of the PINCTRL + * parent node. + */ + +static void config_drive_slew(struct gpio_regs * const regs, uint32_t idx, uint32_t conf) +{ + uint32_t slew = conf & (MCHP_XEC_OSPEEDR_MASK << MCHP_XEC_OSPEEDR_POS); + uint32_t drvstr = conf & (MCHP_XEC_ODRVSTR_MASK << MCHP_XEC_ODRVSTR_POS); + uint32_t val = 0; + uint32_t mask = 0; + + if (slew != MCHP_XEC_OSPEEDR_NO_CHG) { + mask |= MCHP_GPIO_CTRL2_SLEW_MASK; + if (slew == MCHP_XEC_OSPEEDR_FAST) { + val |= MCHP_GPIO_CTRL2_SLEW_FAST; + } + } + if (drvstr != MCHP_XEC_ODRVSTR_NO_CHG) { + mask |= MCHP_GPIO_CTRL2_DRV_STR_MASK; + val |= (drvstr << MCHP_GPIO_CTRL2_DRV_STR_POS); + } + + if (!mask) { + return; + } + + regs->CTRL2[idx] = (regs->CTRL2[idx] & ~mask) | (val & mask); +} + +/* Configure pin by writing GPIO Control and Control2 registers. + * NOTE: Disable alternate output feature since the GPIO driver does. + * While alternate output is enabled (default state of pin) HW does not + * ignores writes to the parallel output bit for the pin. To set parallel + * output value we must keep pin direction as input, set alternate output + * disable, program pin value to parallel output bit, and then disable + * alternate output mode. + */ +static int xec_config_pin(uint32_t portpin, uint32_t conf, uint32_t altf) +{ + struct gpio_regs * const regs = (struct gpio_regs * const)DT_INST_REG_ADDR(0); + uint32_t port = MCHP_XEC_PINMUX_PORT(portpin); + uint32_t pin = (uint32_t)MCHP_XEC_PINMUX_PIN(portpin); + uint32_t msk = MCHP_GPIO_CTRL_AOD_MASK; + uint32_t val = MCHP_GPIO_CTRL_AOD_DIS; + uint32_t idx = 0u; + uint32_t temp = 0u; + + if (port >= NUM_MCHP_GPIO_PORTS) { + return -EINVAL; + } + + /* MCHP XEC family is 32 pins per port */ + idx = (port * 32U) + pin; + + config_drive_slew(regs, idx, conf); + + /* default input pad enabled, buffer type push-pull, no internal pulls */ + msk |= (BIT(MCHP_GPIO_CTRL_INPAD_DIS_POS) | MCHP_GPIO_CTRL_BUFT_MASK | + MCHP_GPIO_CTRL_PUD_MASK | MCHP_GPIO_CTRL_DIR_MASK | + MCHP_GPIO_CTRL_MUX_MASK); + + if (conf & BIT(MCHP_XEC_PIN_LOW_POWER_POS)) { + msk |= MCHP_GPIO_CTRL_PWRG_MASK; + val |= MCHP_GPIO_CTRL_PWRG_OFF; + } + + temp = (conf & MCHP_XEC_PUPDR_MASK) >> MCHP_XEC_PUPDR_POS; + switch (temp) { + case MCHP_XEC_PULL_UP: + val |= MCHP_GPIO_CTRL_PUD_PU; + break; + case MCHP_XEC_PULL_DOWN: + val |= MCHP_GPIO_CTRL_PUD_PD; + break; + case MCHP_XEC_REPEATER: + val |= MCHP_GPIO_CTRL_PUD_RPT; + break; + default: + val |= MCHP_GPIO_CTRL_PUD_NONE; + break; + } + + if ((conf >> MCHP_XEC_OTYPER_POS) & MCHP_XEC_OTYPER_MASK) { + val |= MCHP_GPIO_CTRL_BUFT_OPENDRAIN; + } + + regs->CTRL[idx] = (regs->CTRL[idx] & ~msk) | val; + + temp = (conf >> MCHP_XEC_OVAL_POS) & MCHP_XEC_OVAL_MASK; + if (temp) { + if (temp == MCHP_XEC_OVAL_DRV_HIGH) { + regs->PAROUT[port] |= BIT(pin); + } else { + regs->PAROUT[port] &= ~BIT(pin); + } + + regs->CTRL[idx] |= MCHP_GPIO_CTRL_DIR_OUTPUT; + } + + val = (uint32_t)((altf & MCHP_GPIO_CTRL_MUX_MASK0) << MCHP_GPIO_CTRL_MUX_POS); + regs->CTRL[idx] |= val; + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ + uint32_t portpin, mux, cfg, func; + int ret; + + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + mux = pins[i].pinmux; + + func = MCHP_XEC_PINMUX_FUNC(mux); + if (func >= MCHP_AFMAX) { + return -EINVAL; + } + + cfg = pins[i].pincfg; + portpin = MEC_XEC_PINMUX_PORT_PIN(mux); + + ret = xec_config_pin(portpin, cfg, func); + if (ret < 0) { + return ret; + } + } + + return 0; +} diff --git a/include/dt-bindings/pinctrl/mchp-xec-pinctrl.h b/include/dt-bindings/pinctrl/mchp-xec-pinctrl.h new file mode 100644 index 00000000000..08725a4d8e1 --- /dev/null +++ b/include/dt-bindings/pinctrl/mchp-xec-pinctrl.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MCHP_XEC_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MCHP_XEC_PINCTRL_H_ + +#include + +#define MCHP_GPIO 0x0 +#define MCHP_AF0 0x0 +#define MCHP_AF1 0x1 +#define MCHP_AF2 0x2 +#define MCHP_AF3 0x3 +#define MCHP_AF4 0x4 +#define MCHP_AF5 0x5 +#define MCHP_AF6 0x6 +#define MCHP_AF7 0x7 +#define MCHP_AFMAX 0x8 + +#define MCHP_XEC_PUPDR_POS 0 +#define MCHP_XEC_PUPDR_MASK 0x3 +#define MCHP_XEC_OTYPER_POS 4 +#define MCHP_XEC_OTYPER_MASK 0x1 +#define MCHP_XEC_OTYPER_PUSHPULL 0 +#define MCHP_XEC_OTYPER_OPENDRAIN 0x1 +#define MCHP_XEC_OVAL_POS 6 +#define MCHP_XEC_OVAL_MASK 0x3 +#define MCHP_XEC_OVAL_DRV_LOW 0x1 +#define MCHP_XEC_OVAL_DRV_HIGH 0x2 +#define MCHP_XEC_OSPEEDR_POS 8 +#define MCHP_XEC_OSPEEDR_MASK 0x3 +#define MCHP_XEC_OSPEEDR_SLOW 0x0 +#define MCHP_XEC_OSPEEDR_FAST 0x1 +#define MCHP_XEC_OSPEEDR_NO_CHG 0x3 /* Do not modify slew rate */ +#define MCHP_XEC_ODRVSTR_POS 12 +#define MCHP_XEC_ODRVSTR_MASK 0x7 +#define MCHP_XEC_ODRVSTR_1X 0x0 /* 2 or 4(PIO-24) mA */ +#define MCHP_XEC_ODRVSTR_2X 0x1 /* 4 or 8(PIO-24) mA */ +#define MCHP_XEC_ODRVSTR_4X 0x2 /* 8 or 16(PIO-24) mA */ +#define MCHP_XEC_ODRVSTR_6X 0x3 /* 12 or 24(PIO-24) mA */ +#define MCHP_XEC_ODRVSTR_NO_CHG 0x7 /* Do not modify drive strength */ +#define MCHP_XEC_PIN_LOW_POWER_POS 15 +#define MCHP_XEC_PIN_LOW_POWER 1 + +#define MCHP_XEC_PINMUX_PORT_POS 0 +#define MCHP_XEC_PINMUX_PORT_MSK 0xf +#define MCHP_XEC_PINMUX_PIN_POS 4 +#define MCHP_XEC_PINMUX_PIN_MSK 0x1f +#define MCHP_XEC_PINMUX_FUNC_POS 9 +#define MCHP_XEC_PINMUX_FUNC_MSK 0x7 + +/* n is octal pin number or equivalent in another base. + * MCHP XEC documentation specifies pin numbers in octal. + * f is function number + * b[3:0] = pin bank + * b[8:4] = pin position in bank + * b[11:9] = function + */ +#define MCHP_XEC_PINMUX(n, f) \ + (((((n) >> 5) & MCHP_XEC_PINMUX_PORT_MSK) << MCHP_XEC_PINMUX_PORT_POS) | \ + (((n) & MCHP_XEC_PINMUX_PIN_MSK) << MCHP_XEC_PINMUX_PIN_POS) | \ + (((f) & MCHP_XEC_PINMUX_FUNC_MSK) << MCHP_XEC_PINMUX_FUNC_POS)) + + +#define MCHP_XEC_PINMUX_PORT(p) \ + (((p) >> MCHP_XEC_PINMUX_PORT_POS) & MCHP_XEC_PINMUX_PORT_MSK) + +#define MCHP_XEC_PINMUX_PIN(p) \ + (((p) >> MCHP_XEC_PINMUX_PIN_POS) & MCHP_XEC_PINMUX_PIN_MSK) + +#define MCHP_XEC_PINMUX_FUNC(p) \ + (((p) >> MCHP_XEC_PINMUX_FUNC_POS) & MCHP_XEC_PINMUX_FUNC_MSK) + +#define MEC_XEC_PINMUX_PORT_PIN(p) \ + ((p) & ((MCHP_XEC_PINMUX_PORT_MSK << MCHP_XEC_PINMUX_PORT_POS) | \ + (MCHP_XEC_PINMUX_PIN_MSK << MCHP_XEC_PINMUX_PIN_POS))) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MCHP_XEC_PINCTRL_H_ */ diff --git a/soc/arm/microchip_mec/CMakeLists.txt b/soc/arm/microchip_mec/CMakeLists.txt index 226f3bd626f..ae6495b7b0a 100644 --- a/soc/arm/microchip_mec/CMakeLists.txt +++ b/soc/arm/microchip_mec/CMakeLists.txt @@ -1,3 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 add_subdirectory(${SOC_SERIES}) +add_subdirectory(common) diff --git a/soc/arm/microchip_mec/common/CMakeLists.txt b/soc/arm/microchip_mec/common/CMakeLists.txt new file mode 100644 index 00000000000..7b4e1e885b8 --- /dev/null +++ b/soc/arm/microchip_mec/common/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories_ifdef(CONFIG_SOC_SERIES_MEC172X .) diff --git a/soc/arm/microchip_mec/common/pinctrl_soc.h b/soc/arm/microchip_mec/common/pinctrl_soc.h new file mode 100644 index 00000000000..23c55a4f535 --- /dev/null +++ b/soc/arm/microchip_mec/common/pinctrl_soc.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Linaro Ltd. + * Copyright (c) 2021 Nordic Semiconductor ASA + * Copyright (c) 2021 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Microchip XEC SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_MICROCHIP_XEC_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_MICROCHIP_XEC_COMMON_PINCTRL_SOC_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/* Type for MCHP XEC pin. */ +typedef struct { + /** Pinmux settings (port, pin and function). */ + uint16_t pinmux; + /** Pin configuration (bias, drive and slew rate). */ + uint16_t pincfg; +} pinctrl_soc_pin_t; + +/* initialize pinmux member fields of pinctrl_pin_t */ +#define Z_PINCTRL_MCHP_XEC_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) + +#define MCHP_XEC_BIAS_DIS_VAL(nid) \ + (MCHP_XEC_NO_PULL * DT_PROP(nid, bias_disable)) + +#define MCHP_XEC_BIAS_PU_VAL(nid) \ + (MCHP_XEC_PULL_UP * DT_PROP(nid, bias_pull_up)) + +#define MCHP_XEC_BIAS_PD_VAL(nid) \ + (MCHP_XEC_PULL_DOWN * DT_PROP(nid, bias_pull_down)) + +#define MCHP_XEC_DRV_PP_VAL(nid) \ + (MCHP_XEC_PUSH_PULL * DT_PROP(nid, drive_push_pull)) + +#define MCHP_XEC_DRV_OD_VAL(nid) \ + (MCHP_XEC_OPEN_DRAIN * DT_PROP(nid, drive_open_drain)) + +#define MCHP_XEC_OVAL_DRV_LO(nid) \ + (MCHP_XEC_OVAL_LOW * DT_PROP(nid, output_low)) + +#define MCHP_XEC_OVAL_DRV_HI(nid) \ + (MCHP_XEC_OVAL_HIGH * DT_PROP(nid, output_high)) + +#define MCHP_XEC_LOW_POWER_EN(nid) \ + (MCHP_XEC_PIN_LOW_POWER * DT_PROP(nid, low_power_enable)) + +#define MCHP_XEC_SLEW_VAL(nid) \ + (DT_ENUM_IDX_OR(nid, slew_rate, MCHP_XEC_OSPEEDR_NO_CHG) << \ + MCHP_XEC_OSPEEDR_POS) + +#define MCHP_XEC_DRVSTR_VAL(nid) \ + (DT_ENUM_IDX_OR(nid, drive_strength, MCHP_XEC_ODRVSTR_NO_CHG) << \ + MCHP_XEC_ODRVSTR_POS) + +/* initialize pincfg field in structure pinctrl_pin_t */ +#define Z_PINCTRL_MCHP_XEC_PINCFG_INIT(node_id) \ + ((MCHP_XEC_BIAS_DIS_VAL(node_id) << MCHP_XEC_PUPDR_POS) | \ + (MCHP_XEC_BIAS_PU_VAL(node_id) << MCHP_XEC_PUPDR_POS) | \ + (MCHP_XEC_BIAS_PD_VAL(node_id) << MCHP_XEC_PUPDR_POS) | \ + (MCHP_XEC_DRV_PP_VAL(node_id) << MCHP_XEC_OTYPER_POS) | \ + (MCHP_XEC_DRV_OD_VAL(node_id) << MCHP_XEC_OTYPER_POS) | \ + (MCHP_XEC_OVAL_DRV_LO(node_id) << MCHP_XEC_OVAL_POS) | \ + (MCHP_XEC_OVAL_DRV_HI(node_id) << MCHP_XEC_OVAL_POS) | \ + (MCHP_XEC_LOW_POWER_EN(node_id) << MCHP_XEC_PIN_LOW_POWER_POS) | \ + MCHP_XEC_SLEW_VAL(node_id) | \ + MCHP_XEC_DRVSTR_VAL(node_id)) + +/* initialize pin structure members */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \ + { .pinmux = Z_PINCTRL_MCHP_XEC_PINMUX_INIT( \ + DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pincfg = Z_PINCTRL_MCHP_XEC_PINCFG_INIT( \ + DT_PROP_BY_IDX(node_id, state_prop, idx)), }, + +/* Use DT FOREACH macro to initialize each used pin */ +#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_MICROCHIP_XEC_COMMON_PINCTRL_SOC_H_ */ diff --git a/soc/arm/microchip_mec/common/soc_dt.h b/soc/arm/microchip_mec/common/soc_dt.h new file mode 100644 index 00000000000..86354aa8fb9 --- /dev/null +++ b/soc/arm/microchip_mec/common/soc_dt.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 Microchip Technology Inc. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _MICROCHIP_XEC_SOC_DT_H_ +#define _MICROCHIP_XEC_SOC_DT_H_ + +#define MCHP_XEC_NO_PULL 0x0 +#define MCHP_XEC_PULL_UP 0x1 +#define MCHP_XEC_PULL_DOWN 0x2 +#define MCHP_XEC_REPEATER 0x3 +#define MCHP_XEC_PUSH_PULL 0x0 +#define MCHP_XEC_OPEN_DRAIN 0x1 +#define MCHP_XEC_NO_OVAL 0x0 +#define MCHP_XEC_OVAL_LOW 0x1 +#define MCHP_XEC_OVAL_HIGH 0x2 +#define MCHP_XEC_DRVSTR_NONE 0x0 +#define MCHP_XEC_DRVSTR_2MA 0x1 +#define MCHP_XEC_DRVSTR_4MA 0x2 +#define MCHP_XEC_DRVSTR_8MA 0x3 +#define MCHP_XEC_DRVSTR_12MA 0x4 + +#endif /* _MICROCHIP_XEC_SOC_DT_H_ */ diff --git a/soc/arm/microchip_mec/mec172x/soc.h b/soc/arm/microchip_mec/mec172x/soc.h index c9451b77d6c..d33ae1d56fb 100644 --- a/soc/arm/microchip_mec/mec172x/soc.h +++ b/soc/arm/microchip_mec/mec172x/soc.h @@ -276,6 +276,7 @@ typedef enum { #include "../common/reg/mec_wdt.h" /* common SoC API */ +#include "../common/soc_dt.h" #include "../common/soc_gpio.h" #include "../common/soc_pcr.h" #include "../common/soc_pins.h"