/*
 * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* Include esp-idf headers first to avoid redefining BIT() macro */
#include <hal/gpio_ll.h>
#include <hal/rtc_io_hal.h>

#include <soc.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/pinctrl/pinctrl_esp32_common.h>

#ifdef CONFIG_SOC_ESP32C3
/* gpio structs in esp32c3 series are different from xtensa ones */
#define out out.data
#define in in.data
#define out_w1ts out_w1ts.val
#define out_w1tc out_w1tc.val
#endif

#ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT
#define SOC_GPIO_SUPPORT_RTC_INDEPENDENT 0
#endif

#define ESP32_INVALID_PORT_ADDR          0UL

#define ESP32_GPIO_PORT_ADDR(nodelabel)				\
	COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)),	\
		(DT_REG_ADDR(DT_NODELABEL(nodelabel)),),	\
		(ESP32_INVALID_PORT_ADDR))

/**
 * @brief Array containing each GPIO port address.
 *
 * Entries will be an invalid address if the port is not enabled.
 */
static const uint32_t esp32_gpio_ports_addrs[] = {
	ESP32_GPIO_PORT_ADDR(gpio0)
	ESP32_GPIO_PORT_ADDR(gpio1)
};

/** Number of GPIO ports. */
static const size_t esp32_gpio_ports_cnt = ARRAY_SIZE(esp32_gpio_ports_addrs);

static inline bool rtc_gpio_is_valid_gpio(uint32_t gpio_num)
{
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
	return (gpio_num < SOC_GPIO_PIN_COUNT && rtc_io_num_map[gpio_num] >= 0);
#else
	return false;
#endif
}

static inline bool esp32_pin_is_valid(uint32_t pin)
{
	return ((BIT(pin) & SOC_GPIO_VALID_GPIO_MASK) != 0);
}

static inline bool esp32_pin_is_output_capable(uint32_t pin)
{
	return ((BIT(pin) & SOC_GPIO_VALID_OUTPUT_GPIO_MASK) != 0);
}

static int esp32_pin_apply_config(uint32_t pin, uint32_t flags)
{
	gpio_dev_t *const gpio_base = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
	uint32_t io_pin = (uint32_t) pin + ((ESP32_PORT_IDX(pin) == 1 && pin < 32) ? 32 : 0);
	int ret = 0;

	if (!esp32_pin_is_valid(io_pin)) {
		return -EINVAL;
	}

#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
	if (rtc_gpio_is_valid_gpio(io_pin)) {
		rtcio_hal_function_select(rtc_io_num_map[io_pin], RTCIO_FUNC_DIGITAL);
	}
#endif

	if (io_pin >= GPIO_NUM_MAX) {
		ret = -EINVAL;
		goto end;
	}

	/* Set pin function as GPIO */
	gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[io_pin], PIN_FUNC_GPIO);

	if (flags & ESP32_PULL_UP_FLAG) {
		if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
			gpio_ll_pulldown_dis(&GPIO, io_pin);
			gpio_ll_pullup_en(&GPIO, io_pin);
		} else {
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
			int rtcio_num = rtc_io_num_map[io_pin];

			rtcio_hal_pulldown_disable(rtc_io_num_map[io_pin]);

			if (rtc_io_desc[rtcio_num].pullup) {
				rtcio_hal_pullup_enable(rtc_io_num_map[io_pin]);
			} else {
				ret = -ENOTSUP;
				goto end;
			}
#endif
		}
	} else if (flags & ESP32_PULL_DOWN_FLAG) {
		if (!rtc_gpio_is_valid_gpio(io_pin) || SOC_GPIO_SUPPORT_RTC_INDEPENDENT) {
			gpio_ll_pullup_dis(&GPIO, io_pin);
			gpio_ll_pulldown_en(&GPIO, io_pin);
		} else {
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
			int rtcio_num = rtc_io_num_map[io_pin];

			rtcio_hal_pulldown_enable(rtc_io_num_map[io_pin]);

			if (rtc_io_desc[rtcio_num].pullup) {
				rtcio_hal_pullup_disable(rtc_io_num_map[io_pin]);
			} else {
				ret = -ENOTSUP;
				goto end;
			}
#endif
		}
	}

	if (flags & ESP32_DIR_OUT_FLAG) {
		if (!esp32_pin_is_output_capable(pin)) {
			ret = -EINVAL;
			goto end;
		}

		if (flags & ESP32_OPEN_DRAIN_FLAG) {
			gpio_ll_od_enable(gpio_base, io_pin);
		} else {
			gpio_ll_od_disable(gpio_base, io_pin);
		}

		/* Set output pin initial value */
		if (flags & ESP32_PIN_OUT_HIGH_FLAG) {
			gpio_ll_set_level(gpio_base, io_pin, 1);
		} else if (flags & ESP32_PIN_OUT_LOW_FLAG) {
			gpio_ll_set_level(gpio_base, io_pin, 0);
		}

		gpio_ll_output_enable(&GPIO, io_pin);
		esp_rom_gpio_matrix_out(io_pin, SIG_GPIO_OUT_IDX, false, false);
	} else {
		gpio_ll_output_disable(&GPIO, io_pin);
	}

	if (flags & ESP32_DIR_INP_FLAG) {
		gpio_ll_input_enable(&GPIO, io_pin);
	} else {
		gpio_ll_input_disable(&GPIO, io_pin);
	}

end:
	return ret;
}

static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg)
{
	uint32_t port_addr;
	uint32_t pin_num = ESP32_PIN_NUM(pin_mux);
	uint32_t sig_in = ESP32_PIN_SIGI(pin_mux);
	uint32_t sig_out = ESP32_PIN_SIGO(pin_mux);
	uint32_t flags = 0;

	if (ESP32_PORT_IDX(pin_num) >= esp32_gpio_ports_cnt) {
		return -EINVAL;
	}

	port_addr = esp32_gpio_ports_addrs[ESP32_PORT_IDX(pin_num)];

	if (port_addr == ESP32_INVALID_PORT_ADDR) {
		return -EINVAL;
	}

	switch (ESP32_PIN_BIAS(pin_cfg)) {
	case ESP32_PULL_UP:
		flags |= ESP32_PULL_UP_FLAG;
		break;
	case ESP32_PULL_DOWN:
		flags |= ESP32_PULL_DOWN_FLAG;
		break;
	default:
		break;
	}

	switch (ESP32_PIN_DRV(pin_cfg)) {
	case ESP32_PUSH_PULL:
		flags |= ESP32_PUSH_PULL_FLAG;
		break;
	case ESP32_OPEN_DRAIN:
		flags |= ESP32_OPEN_DRAIN_FLAG;
		break;
	default:
		break;
	}

	if (sig_in == ESP_SIG_INVAL && sig_out == ESP_SIG_INVAL) {
		return -ENOTSUP;
	}

	if (sig_in != ESP_SIG_INVAL) {
		flags |= ESP32_DIR_INP_FLAG;
	}

	if (sig_out != ESP_SIG_INVAL) {
		flags |= ESP32_DIR_OUT_FLAG;
	}

	switch (ESP32_PIN_MODE_OUT(pin_cfg)) {
	case ESP32_PIN_OUT_HIGH:
		flags |= ESP32_PIN_OUT_HIGH_FLAG;
		break;
	case ESP32_PIN_OUT_LOW:
		flags |= ESP32_PIN_OUT_LOW_FLAG;
		break;
	default:
		break;
	}

	if (flags & ESP32_PIN_OUT_HIGH_FLAG) {
		if (ESP32_PORT_IDX(pin_num) == 0) {
			gpio_dev_t *const gpio_dev =
				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
			gpio_dev->out_w1ts = pin_num;
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
		} else {
			gpio_dev_t *const gpio_dev =
				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1));
			gpio_dev->out1_w1ts.data = pin_num;
#endif
		}
	}

	if (flags & ESP32_PIN_OUT_LOW_FLAG) {
		if (ESP32_PORT_IDX(pin_num) == 0) {
			gpio_dev_t *const gpio_dev =
				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0));
			gpio_dev->out_w1tc = pin_num;
#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay)
		} else {
			gpio_dev_t *const gpio_dev =
				(gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1));
			gpio_dev->out1_w1tc.data = pin_num;
#endif
		}
	}

	esp32_pin_apply_config(pin_num, flags);

	if (flags & ESP32_DIR_OUT_FLAG) {
		esp_rom_gpio_matrix_out(pin_num, sig_out, 0, 0);
	}

	if (flags & ESP32_DIR_INP_FLAG) {
		esp_rom_gpio_matrix_in(pin_num, sig_in, 0);
	}

	return 0;
}

int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
			   uintptr_t reg)
{
	uint32_t pin_mux, pin_cfg;
	int ret = 0;

	ARG_UNUSED(reg);

	for (uint8_t i = 0U; i < pin_cnt; i++) {
		pin_mux = pins[i].pinmux;
		pin_cfg = pins[i].pincfg;

		ret = esp32_pin_configure(pin_mux, pin_cfg);
		if (ret < 0) {
			return ret;
		}
	}

	return 0;
}
