/*
 * Copyright 2022 Google LLC
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT richtek_rt1718s_gpio_port

/**
 * @file Driver for RS1718S TCPC chip GPIOs.
 */

#include "gpio_rt1718s.h"

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(gpio_rt1718s_port, CONFIG_GPIO_LOG_LEVEL);

/* Driver config */
struct gpio_rt1718s_port_config {
	/* gpio_driver_config needs to be first */
	struct gpio_driver_config common;
	/* RT1718S chip device */
	const struct device *rt1718s_dev;
};

/* Driver data */
struct gpio_rt1718s_port_data {
	/* gpio_driver_data needs to be first */
	struct gpio_driver_data common;
	/* GPIO callback list */
	sys_slist_t cb_list_gpio;
	/* lock GPIO registers access */
	struct k_sem lock;
};

/* GPIO api functions */
static int gpio_rt1718s_pin_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	uint8_t new_reg = 0;
	int ret = 0;

	/* Don't support simultaneous in/out mode */
	if ((flags & GPIO_INPUT) && (flags & GPIO_OUTPUT)) {
		return -ENOTSUP;
	}

	/* Don't support "open source" mode */
	if ((flags & GPIO_SINGLE_ENDED) && !(flags & GPIO_LINE_OPEN_DRAIN)) {
		return -ENOTSUP;
	}

	/* RT1718S has 3 GPIOs so check range */
	if (pin >= RT1718S_GPIO_NUM) {
		return -EINVAL;
	}

	/* Configure pin as input. */
	if (flags & GPIO_INPUT) {
		/* Do not set RT1718S_REG_GPIO_CTRL_OE bit for input */
		/* Set pull-high/low input */
		if (flags & GPIO_PULL_UP) {
			new_reg |= RT1718S_REG_GPIO_CTRL_PU;
		}
		if (flags & GPIO_PULL_DOWN) {
			new_reg |= RT1718S_REG_GPIO_CTRL_PD;
		}
	} else if (flags & GPIO_OUTPUT) {
		/* Set GPIO as output */
		new_reg |= RT1718S_REG_GPIO_CTRL_OE;

		/* Set push-pull or open-drain */
		if (!(flags & GPIO_SINGLE_ENDED)) {
			new_reg |= RT1718S_REG_GPIO_CTRL_OD_N;
		}

		/* Set init state */
		if (flags & GPIO_OUTPUT_INIT_HIGH) {
			new_reg |= RT1718S_REG_GPIO_CTRL_O;
		}
	}

	k_sem_take(&data->lock, K_FOREVER);
	ret = rt1718s_reg_write_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin), new_reg);
	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_port_get_raw(const struct device *dev, gpio_port_value_t *value)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	uint8_t reg;
	int ret;

	ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_RT_ST8, &reg);
	*value = reg & (RT1718S_REG_RT_ST8_GPIO1_I | RT1718S_REG_RT_ST8_GPIO2_I |
			RT1718S_REG_RT_ST8_GPIO3_I);

	return ret;
}

static int gpio_rt1718s_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
					    gpio_port_value_t value)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	uint8_t new_reg, reg;
	int ret = 0;

	k_sem_take(&data->lock, K_FOREVER);

	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
		if (mask & BIT(pin)) {
			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						    &reg);
			if (ret < 0) {
				break;
			}

			if (value & BIT(pin)) {
				new_reg = reg | RT1718S_REG_GPIO_CTRL_O;
			} else {
				new_reg = reg & ~RT1718S_REG_GPIO_CTRL_O;
			}
			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						 reg, new_reg);
		}
	}

	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	uint8_t new_reg, reg;
	int ret = 0;

	k_sem_take(&data->lock, K_FOREVER);

	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
		if (mask & BIT(pin)) {
			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						    &reg);
			if (ret < 0) {
				break;
			}
			new_reg = reg | RT1718S_REG_GPIO_CTRL_O;
			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						 reg, new_reg);
		}
	}

	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	uint8_t new_reg, reg;
	int ret = 0;

	k_sem_take(&data->lock, K_FOREVER);

	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
		if (mask & BIT(pin)) {
			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						    &reg);
			if (ret < 0) {
				break;
			}
			new_reg = reg & ~RT1718S_REG_GPIO_CTRL_O;
			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						 reg, new_reg);
		}
	}

	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_port_toggle_bits(const struct device *dev, gpio_port_pins_t mask)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	uint8_t new_reg, reg;
	int ret = 0;

	k_sem_take(&data->lock, K_FOREVER);

	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
		if (mask & BIT(pin)) {
			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						    &reg);
			if (ret < 0) {
				break;
			}
			new_reg = reg ^ RT1718S_REG_GPIO_CTRL_O;
			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
						 reg, new_reg);
		}
	}

	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
						enum gpio_int_mode mode, enum gpio_int_trig trig)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;
	struct rt1718s_data *const data_rt1718s = config->rt1718s_dev->data;
	uint8_t reg_int8, reg_mask8, new_reg_mask8 = 0;
	uint8_t mask_rise = BIT(pin), mask_fall = BIT(4 + pin);
	uint16_t alert_mask;
	int ret;

	/* Check passed arguments */
	if (mode == GPIO_INT_MODE_LEVEL || pin >= RT1718S_GPIO_NUM) {
		return -ENOTSUP;
	}

	k_sem_take(&data->lock, K_FOREVER);
	k_sem_take(&data_rt1718s->lock_tcpci, K_FOREVER);

	ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_RT_MASK8, &reg_mask8);
	if (ret < 0) {
		goto done;
	}

	/* Disable GPIO interrupt */
	if (mode == GPIO_INT_MODE_DISABLED) {
		new_reg_mask8 = reg_mask8 & ~(mask_rise | mask_fall);
	} else if (mode == GPIO_INT_MODE_EDGE) {
		switch (trig) {
		case GPIO_INT_TRIG_BOTH:
			new_reg_mask8 = reg_mask8 | mask_rise | mask_fall;
			break;
		case GPIO_INT_TRIG_HIGH:
			new_reg_mask8 = (reg_mask8 | mask_rise) & ~mask_fall;
			break;
		case GPIO_INT_TRIG_LOW:
			new_reg_mask8 = (reg_mask8 | mask_fall) & ~mask_rise;
			break;
		default:
			ret = -EINVAL;
			goto done;
		}

		ret = rt1718s_reg_burst_read(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
					     (uint8_t *)&alert_mask, sizeof(alert_mask));
		if (ret) {
			goto done;
		}

		/* Enable Vendor Defined Alert for GPIO interrupts */
		if (!(alert_mask & RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT)) {
			alert_mask |= RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT;
			ret = rt1718s_reg_burst_write(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
						      (uint8_t *)&alert_mask, sizeof(alert_mask));

			if (ret) {
				goto done;
			}
		}

		/* Clear pending interrupts, which were trigger before enabling the pin
		 * interrupt by user.
		 */
		reg_int8 = mask_rise | mask_fall;
		rt1718s_reg_write_byte(config->rt1718s_dev, RT1718S_REG_RT_INT8, reg_int8);
	}

	/* MASK8 handles 3 GPIOs interrupts, both edges */
	ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_RT_MASK8, reg_mask8,
				 new_reg_mask8);

done:
	k_sem_give(&data_rt1718s->lock_tcpci);
	k_sem_give(&data->lock);

	return ret;
}

static int gpio_rt1718s_manage_callback(const struct device *dev, struct gpio_callback *callback,
					bool set)
{
	struct gpio_rt1718s_port_data *const data = dev->data;

	return gpio_manage_callback(&data->cb_list_gpio, callback, set);
}

void rt1718s_gpio_alert_handler(const struct device *dev)
{
	const struct rt1718s_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data_port = config->gpio_port_dev->data;
	uint8_t reg_int8, reg_mask8;

	k_sem_take(&data_port->lock, K_FOREVER);

	/* Get mask and state of GPIO interrupts */
	if (rt1718s_reg_read_byte(dev, RT1718S_REG_RT_INT8, &reg_int8) ||
	    rt1718s_reg_read_byte(dev, RT1718S_REG_RT_MASK8, &reg_mask8)) {
		k_sem_give(&data_port->lock);
		LOG_ERR("i2c access failed");
		return;
	}

	reg_int8 &= reg_mask8;
	/* Clear the interrupts */
	if (reg_int8) {
		if (rt1718s_reg_write_byte(dev, RT1718S_REG_RT_INT8, reg_int8)) {
			k_sem_give(&data_port->lock);
			LOG_ERR("i2c access failed");
			return;
		}
	}

	k_sem_give(&data_port->lock);

	if (reg_int8 & RT1718S_GPIO_INT_MASK)
		/* Call the GPIO callbacks for rising *or* falling edge */
		gpio_fire_callbacks(&data_port->cb_list_gpio, config->gpio_port_dev,
				    (reg_int8 & 0x7) | ((reg_int8 >> 4) & 0x7));
}

static const struct gpio_driver_api gpio_rt1718s_driver = {
	.pin_configure = gpio_rt1718s_pin_config,
	.port_get_raw = gpio_rt1718s_port_get_raw,
	.port_set_masked_raw = gpio_rt1718s_port_set_masked_raw,
	.port_set_bits_raw = gpio_rt1718s_port_set_bits_raw,
	.port_clear_bits_raw = gpio_rt1718s_port_clear_bits_raw,
	.port_toggle_bits = gpio_rt1718s_port_toggle_bits,
	.pin_interrupt_configure = gpio_rt1718s_pin_interrupt_configure,
	.manage_callback = gpio_rt1718s_manage_callback,
};

static int gpio_rt1718s_port_init(const struct device *dev)
{
	const struct gpio_rt1718s_port_config *const config = dev->config;
	struct gpio_rt1718s_port_data *const data = dev->data;

	if (!device_is_ready(config->rt1718s_dev)) {
		LOG_ERR("%s is not ready", config->rt1718s_dev->name);
		return -ENODEV;
	}

	k_sem_init(&data->lock, 1, 1);

	return 0;
}

/* RT1718S GPIO port driver must be initialized after RT1718S chip driver */
BUILD_ASSERT(CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY > CONFIG_RT1718S_INIT_PRIORITY);

#define GPIO_RT1718S_PORT_DEVICE_INSTANCE(inst)                                                    \
	static const struct gpio_rt1718s_port_config gpio_rt1718s_port_cfg_##inst = {              \
		.common = {.port_pin_mask = 0x7},                                                  \
		.rt1718s_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                \
	};                                                                                         \
	static struct gpio_rt1718s_port_data gpio_rt1718s_port_data_##inst;                        \
	DEVICE_DT_INST_DEFINE(inst, gpio_rt1718s_port_init, NULL, &gpio_rt1718s_port_data_##inst,  \
			      &gpio_rt1718s_port_cfg_##inst, POST_KERNEL,                          \
			      CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY, &gpio_rt1718s_driver);

DT_INST_FOREACH_STATUS_OKAY(GPIO_RT1718S_PORT_DEVICE_INSTANCE)
