/*
 * Copyright (c) 2022 Nuvoton Technology Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <assert.h>
#include <zephyr/drivers/pinctrl.h>
#include <soc.h>

/* Driver config */
struct npcx_pinctrl_config {
	/* Device base address used for pinctrl driver */
	uintptr_t base_scfg;
	uintptr_t base_glue;
};

static const struct npcx_pinctrl_config npcx_pinctrl_cfg = {
	.base_scfg = NPCX_SCFG_REG_ADDR,
	.base_glue = NPCX_GLUE_REG_ADDR,
};

/* PWM pinctrl config */
struct npcx_pwm_pinctrl_config {
	uintptr_t base;
	int channel;
};

#define NPCX_PWM_PINCTRL_CFG_INIT(node_id)			\
	{							\
		.base = DT_REG_ADDR(node_id),			\
		.channel = DT_PROP(node_id, pwm_channel),	\
	},

static const struct npcx_pwm_pinctrl_config pwm_pinctrl_cfg[] = {
	DT_FOREACH_STATUS_OKAY(nuvoton_npcx_pwm, NPCX_PWM_PINCTRL_CFG_INIT)
};

/* Pin-control local functions for peripheral devices */
static bool npcx_periph_pinmux_has_lock(int group)
{
	if ((BIT(group) & NPCX_DEVALT_LK_GROUP_MASK) != 0) {
		return true;
	}

	return false;
}

static void npcx_periph_pinmux_configure(const struct npcx_periph *alt, bool is_alternate,
	bool is_locked)
{
	const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;
	uint8_t alt_mask = BIT(alt->bit);

	/*
	 * is_alternate == 0 means select GPIO, otherwise Alternate Func.
	 * inverted == 0:
	 *    Set devalt bit to select Alternate Func.
	 * inverted == 1:
	 *    Clear devalt bit to select Alternate Func.
	 */
	if (is_alternate != alt->inverted) {
		NPCX_DEVALT(scfg_base, alt->group) |=  alt_mask;
	} else {
		NPCX_DEVALT(scfg_base, alt->group) &= ~alt_mask;
	}

	if (is_locked && npcx_periph_pinmux_has_lock(alt->group)) {
		NPCX_DEVALT_LK(scfg_base, alt->group) |= alt_mask;
	}
}

static void npcx_periph_pupd_configure(const struct npcx_periph *pupd,
	enum npcx_io_bias_type type)
{
	const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;

	if (type == NPCX_BIAS_TYPE_NONE) {
		NPCX_PUPD_EN(scfg_base, pupd->group) &= ~BIT(pupd->bit);
	} else {
		NPCX_PUPD_EN(scfg_base, pupd->group) |=  BIT(pupd->bit);
	}
}

static void npcx_periph_pwm_drive_mode_configure(const struct npcx_periph *periph,
	bool is_od)
{
	uintptr_t reg = 0;

	/* Find selected pwm module which enables open-drain prop. */
	for (int i = 0; i < ARRAY_SIZE(pwm_pinctrl_cfg); i++) {
		if (periph->group == pwm_pinctrl_cfg[i].channel) {
			reg = pwm_pinctrl_cfg[i].base;
			break;
		}
	}

	if (reg == 0) {
		return;
	}

	struct pwm_reg *const inst = (struct pwm_reg *)(reg);

	if (is_od) {
		inst->PWMCTLEX |= BIT(NPCX_PWMCTLEX_OD_OUT);
	} else {
		inst->PWMCTLEX &= ~BIT(NPCX_PWMCTLEX_OD_OUT);
	}
}

static void npcx_periph_configure(const pinctrl_soc_pin_t *pin, uintptr_t reg)
{
	if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_PINMUX) {
		/* Configure peripheral device's pinmux functionality */
		npcx_periph_pinmux_configure(&pin->cfg.periph,
					     !pin->flags.pinmux_gpio,
					     pin->flags.pinmux_lock);
	} else if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_PUPD) {
		/* Configure peripheral device's internal PU/PD */
		npcx_periph_pupd_configure(&pin->cfg.periph,
			pin->flags.io_bias_type);
	} else if (pin->cfg.periph.type == NPCX_PINCTRL_TYPE_PERIPH_DRIVE) {
		/* Configure peripheral device's drive mode. (Only PWM pads support it) */
		npcx_periph_pwm_drive_mode_configure(&pin->cfg.periph,
			pin->flags.io_drive_type == NPCX_DRIVE_TYPE_OPEN_DRAIN);
	}
}

static void npcx_psl_input_detection_configure(const pinctrl_soc_pin_t *pin)
{
	struct glue_reg *inst_glue = (struct glue_reg *)(npcx_pinctrl_cfg.base_glue);
	const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;
	const struct npcx_psl_input *psl_in = (const struct npcx_psl_input *)&pin->cfg.psl_in;

	/* Configure detection polarity of PSL input pads */
	if (pin->flags.psl_in_polarity == NPCX_PSL_IN_POL_HIGH) {
		NPCX_DEVALT(scfg_base, psl_in->pol_group) |=  BIT(psl_in->pol_bit);
	} else {
		NPCX_DEVALT(scfg_base, psl_in->pol_group) &= ~BIT(psl_in->pol_bit);
	}

	/* Configure detection mode of PSL input pads */
	if (pin->flags.psl_in_mode == NPCX_PSL_IN_MODE_EDGE) {
		inst_glue->PSL_CTS |= NPCX_PSL_CTS_MODE_BIT(psl_in->port);
	} else {
		inst_glue->PSL_CTS &= ~NPCX_PSL_CTS_MODE_BIT(psl_in->port);
	}
}

static void npcx_device_control_configure(const pinctrl_soc_pin_t *pin)
{
	const struct npcx_dev_ctl *ctrl = (const struct npcx_dev_ctl *)&pin->cfg.dev_ctl;
	const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg;

	SET_FIELD(NPCX_DEV_CTL(scfg_base, ctrl->offest),
			      FIELD(ctrl->field_offset, ctrl->field_size),
			      ctrl->field_value);
}

/* Pinctrl API implementation */
int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
			   uintptr_t reg)
{
	ARG_UNUSED(reg);

	/* Configure all peripheral devices' properties here. */
	for (uint8_t i = 0; i < pin_cnt; i++) {
		if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PERIPH) {
			/* Configure peripheral device's pinmux functionality */
			npcx_periph_configure(&pins[i], reg);
		} else if (pins[i].flags.type == NPCX_PINCTRL_TYPE_DEVICE_CTRL) {
			/* Configure device's io characteristics */
			npcx_device_control_configure(&pins[i]);
		} else if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PSL_IN) {
			/* Configure SPL input's detection mode */
			npcx_psl_input_detection_configure(&pins[i]);
		} else {
			return -ENOTSUP;
		}
	}

	return 0;
}
