Commit 2cd02bd8 authored by Jay Vasanth's avatar Jay Vasanth Committed by Carles Cufi
Browse files

drivers: pinctrl: Microchip MEC172x pinctrl driver



Add core files for Microchip MEC172x pinctrl driver

Signed-off-by: default avatarJay Vasanth <jay.vasanth@microchip.com>
parent 935e6752
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
# 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
+150 −0
Original line number Diff line number Diff line
/*
 * 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 <drivers/pinctrl.h>
#include <soc.h>

/* 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;
}
Loading