/*
 * 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 <zephyr/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,
	 * and invert polarity normal.
	 */
	msk |= (BIT(MCHP_GPIO_CTRL_INPAD_DIS_POS) | MCHP_GPIO_CTRL_BUFT_MASK |
			MCHP_GPIO_CTRL_PUD_MASK | MCHP_GPIO_CTRL_MUX_MASK
			| BIT(MCHP_GPIO_CTRL_POL_POS));

	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;
	}

	if (conf & MCHP_XEC_FUNC_INV_MSK) {
		val |= BIT(MCHP_GPIO_CTRL_POL_POS);
	}

	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;
}
