/*
 * Copyright (c) 2020 ITE Corporation. All Rights Reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief PINMUX driver for the IT8xxx2
 */

#include <errno.h>
#include <device.h>
#include <drivers/pinmux.h>
#include <soc.h>

#define DT_DRV_COMPAT ite_it8xxx2_pinmux

#include <logging/log.h>
LOG_MODULE_REGISTER(pinmux_ite_it8xxx2, LOG_LEVEL_ERR);

struct pinmux_it8xxx2_config {
	/* gpio port control register (byte mapping to pin) */
	uintptr_t reg_gpcr;
	/* function 3 general control register */
	uintptr_t func3_gcr[8];
	/* function 4 general control register */
	uintptr_t func4_gcr[8];
	/* function 3 enable mask */
	uint8_t func3_en_mask[8];
	/* function 4 enable mask */
	uint8_t func4_en_mask[8];
};

#define DEV_CFG(dev)					\
	((const struct pinmux_it8xxx2_config * const)	\
	 (dev)->config)

static int pinmux_it8xxx2_set(const struct device *dev,
			      uint32_t pin, uint32_t func)
{
	const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);

	volatile uint8_t *reg_gpcr =
		(uint8_t *)(pinmux_config->reg_gpcr + pin);
	volatile uint8_t *reg_func3_gcr =
		(uint8_t *)(pinmux_config->func3_gcr[pin]);
	volatile uint8_t *reg_func4_gcr =
		(uint8_t *)(pinmux_config->func4_gcr[pin]);

	if (pin >= IT8XXX2_PINMUX_PINS) {
		return -EINVAL;
	}

	/* Common settings for alternate function. */
	*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT |
		GPCR_PORT_PIN_MODE_OUTPUT);

	switch (func) {
	case IT8XXX2_PINMUX_FUNC_1:
		/* Func1: Alternate function has been set above. */
		break;
	case IT8XXX2_PINMUX_FUNC_2:
		/* Func2: WUI function: turn the pin into an input */
		*reg_gpcr |= GPCR_PORT_PIN_MODE_INPUT;
		break;
	case IT8XXX2_PINMUX_FUNC_3:
		/*
		 * Func3: In addition to the alternate setting above,
		 *        Func3 also need to set the general control.
		 */
		*reg_func3_gcr |= pinmux_config->func3_en_mask[pin];
		break;
	case IT8XXX2_PINMUX_FUNC_4:
		/*
		 * Func4: In addition to the alternate setting above,
		 *        Func4 also need to set the general control.
		 */
		*reg_func4_gcr |= pinmux_config->func4_en_mask[pin];
		break;
	default:
		LOG_ERR("This function is not supported");
		return -EINVAL;
	}

	return 0;
}

static int pinmux_it8xxx2_get(const struct device *dev,
			      uint32_t pin, uint32_t *func)
{
	const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);

	volatile uint8_t *reg_gpcr =
		(uint8_t *)(pinmux_config->reg_gpcr + pin);

	if (pin >= IT8XXX2_PINMUX_PINS || func == NULL) {
		return -EINVAL;
	}

	*func = (*reg_gpcr & (GPCR_PORT_PIN_MODE_INPUT |
		GPCR_PORT_PIN_MODE_OUTPUT)) == GPCR_PORT_PIN_MODE_INPUT ?
		IT8XXX2_PINMUX_FUNC_2 : IT8XXX2_PINMUX_FUNC_1;

	/* TODO: IT8XXX2_PINMUX_FUNC_3 & IT8XXX2_PINMUX_FUNC_4 */

	return 0;
}

static int pinmux_it8xxx2_pullup(const struct device *dev,
				 uint32_t pin, uint8_t func)
{
	const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);

	volatile uint8_t *reg_gpcr =
		(uint8_t *)(pinmux_config->reg_gpcr + pin);

	if (func == PINMUX_PULLUP_ENABLE) {
		*reg_gpcr = (*reg_gpcr | GPCR_PORT_PIN_MODE_PULLUP) &
			~GPCR_PORT_PIN_MODE_PULLDOWN;
	} else if (func == PINMUX_PULLUP_DISABLE) {
		*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_PULLUP |
			GPCR_PORT_PIN_MODE_PULLDOWN);
	} else {
		return -EINVAL;
	}

	return 0;
}

static int pinmux_it8xxx2_input(const struct device *dev,
				uint32_t pin, uint8_t func)
{
	const struct pinmux_it8xxx2_config *pinmux_config = DEV_CFG(dev);

	volatile uint8_t *reg_gpcr =
		(uint8_t *)(pinmux_config->reg_gpcr + pin);

	*reg_gpcr &= ~(GPCR_PORT_PIN_MODE_INPUT |
		GPCR_PORT_PIN_MODE_OUTPUT);

	if (func == PINMUX_INPUT_ENABLED) {
		*reg_gpcr |= GPCR_PORT_PIN_MODE_INPUT;
	} else if (func == PINMUX_OUTPUT_ENABLED) {
		*reg_gpcr |= GPCR_PORT_PIN_MODE_OUTPUT;
	} else {
		return -EINVAL;
	}

	return 0;
}

static int pinmux_it8xxx2_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	/*
	 * The default value of LPCRSTEN is bit2:1 = 10b(GPD2) in GCR.
	 * If LPC reset is enabled on GPB7, we have to clear bit2:1
	 * to 00b.
	 */
	IT8XXX2_GPIO_GCR &= ~(BIT(1) | BIT(2));

	/*
	 * TODO: If SMBUS3 swaps from H group to F group, we have to
	 * set SMB3PSEL = 1 in PMER3 register.
	 */

	/*
	 * TODO: If UART2 swaps from bit2:1 to bit6:5 in H group, we
	 * have to set UART1PSEL = 1 in UART1PMR register.
	 */

	return 0;
}

static const struct pinmux_driver_api pinmux_it8xxx2_driver_api = {
	.set = pinmux_it8xxx2_set,
	.get = pinmux_it8xxx2_get,
	.pullup = pinmux_it8xxx2_pullup,
	.input = pinmux_it8xxx2_input,
};

#define PINMUX_ITE_INIT(inst)							\
	static const struct pinmux_it8xxx2_config pinmux_it8xxx2_cfg_##inst = {	\
		.reg_gpcr = DT_INST_REG_ADDR(inst),				\
		.func3_gcr = DT_INST_PROP(inst, func3_gcr),			\
		.func3_en_mask = DT_INST_PROP(inst, func3_en_mask),		\
		.func4_gcr = DT_INST_PROP(inst, func4_gcr),			\
		.func4_en_mask = DT_INST_PROP(inst, func4_en_mask),		\
	};									\
										\
	DEVICE_DT_INST_DEFINE(inst,						\
			    &pinmux_it8xxx2_init,				\
			    NULL, NULL, &pinmux_it8xxx2_cfg_##inst,		\
			    PRE_KERNEL_1,					\
			    CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,		\
			    &pinmux_it8xxx2_driver_api);

DT_INST_FOREACH_STATUS_OKAY(PINMUX_ITE_INIT)
