/*
 * Copyright (c) 2023, Intel Corporation. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT altr_pio_1_0

#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>

#define ALTERA_AVALON_PIO_DATA_OFFSET		0x00
#define ALTERA_AVALON_PIO_DIRECTION_OFFSET	0x04
#define ALTERA_AVALON_PIO_IRQ_OFFSET		0x08
#define ALTERA_AVALON_PIO_SET_BITS		0x10
#define ALTERA_AVALON_PIO_CLEAR_BITS		0x14

typedef void (*altera_cfg_func_t)(void);

struct gpio_altera_config {
	struct gpio_driver_config	common;
	uintptr_t			reg_base;
	uint32_t			irq_num;
	uint8_t				direction;
	uint8_t				outset;
	uint8_t				outclear;
	altera_cfg_func_t		cfg_func;
};

struct gpio_altera_data {
	/* gpio_driver_data needs to be first */
	struct gpio_driver_data common;
	/* list of callbacks */
	sys_slist_t cb;
	struct k_spinlock lock;
};

static bool gpio_pin_direction(const struct device *dev, uint32_t pin_mask)
{
	const struct gpio_altera_config *cfg = dev->config;
	const int direction = cfg->direction;
	uintptr_t reg_base = cfg->reg_base;
	uint32_t addr;
	uint32_t pin_direction;

	if (pin_mask == 0) {
		return -EINVAL;
	}

	/* Check if the direction is Bidirectional */
	if (direction != 0) {
		return -EINVAL;
	}

	addr = reg_base + ALTERA_AVALON_PIO_DIRECTION_OFFSET;

	pin_direction = sys_read32(addr);

	if (!(pin_direction & pin_mask)) {
		return false;
	}

	return true;
}

static int gpio_altera_configure(const struct device *dev,
				 gpio_pin_t pin, gpio_flags_t flags)
{
	const struct gpio_altera_config *cfg = dev->config;
	struct gpio_altera_data * const data = dev->data;
	const int port_pin_mask = cfg->common.port_pin_mask;
	const int direction = cfg->direction;
	uintptr_t reg_base = cfg->reg_base;
	k_spinlock_key_t key;
	uint32_t addr;

	/* Check if pin number is within range */
	if ((port_pin_mask & BIT(pin)) == 0) {
		return -EINVAL;
	}

	/* Check if the direction is Bidirectional */
	if (direction != 0) {
		return -EINVAL;
	}

	addr = reg_base + ALTERA_AVALON_PIO_DIRECTION_OFFSET;

	key = k_spin_lock(&data->lock);

	if (flags == GPIO_INPUT) {
		sys_clear_bits(addr, BIT(pin));
	} else if (flags == GPIO_OUTPUT) {
		sys_set_bits(addr, BIT(pin));
	} else {
		return -EINVAL;
	}

	k_spin_unlock(&data->lock, key);

	return 0;
}

static int gpio_altera_port_get_raw(const struct device *dev, uint32_t *value)
{
	const struct gpio_altera_config *cfg = dev->config;
	uintptr_t reg_base = cfg->reg_base;
	uint32_t addr;

	addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET;

	if (value == NULL) {
		return -EINVAL;
	}

	*value = sys_read32((addr));

	return 0;
}

static int gpio_altera_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask)
{
	const struct gpio_altera_config *cfg = dev->config;
	struct gpio_altera_data * const data = dev->data;
	const uint8_t outset = cfg->outset;
	const int port_pin_mask = cfg->common.port_pin_mask;
	uintptr_t reg_base = cfg->reg_base;
	uint32_t addr;
	k_spinlock_key_t key;

	if ((port_pin_mask & mask) == 0) {
		return -EINVAL;
	}

	if (!gpio_pin_direction(dev, mask)) {
		return -EINVAL;
	}

	key = k_spin_lock(&data->lock);

	if (outset) {
		addr = reg_base + ALTERA_AVALON_PIO_SET_BITS;
		sys_write32(mask, addr);
	} else {
		addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET;
		sys_set_bits(addr, mask);
	}

	k_spin_unlock(&data->lock, key);

	return 0;
}

static int gpio_altera_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask)
{
	const struct gpio_altera_config *cfg = dev->config;
	struct gpio_altera_data * const data = dev->data;
	const uint8_t outclear = cfg->outclear;
	const int port_pin_mask = cfg->common.port_pin_mask;
	uintptr_t reg_base = cfg->reg_base;
	uint32_t addr;
	k_spinlock_key_t key;

	/* Check if mask range within 32 */
	if ((port_pin_mask & mask) == 0) {
		return -EINVAL;
	}

	if (!gpio_pin_direction(dev, mask)) {
		return -EINVAL;
	}

	key = k_spin_lock(&data->lock);

	if (outclear) {
		addr = reg_base + ALTERA_AVALON_PIO_CLEAR_BITS;
		sys_write32(mask, addr);
	} else {
		addr = reg_base + ALTERA_AVALON_PIO_DATA_OFFSET;
		sys_clear_bits(addr, mask);
	}

	k_spin_unlock(&data->lock, key);

	return 0;
}

static int gpio_init(const struct device *dev)
{
	const struct gpio_altera_config *cfg = dev->config;

	/* Configure GPIO device */
	cfg->cfg_func();

	return 0;
}

static int gpio_altera_pin_interrupt_configure(const struct device *dev,
						gpio_pin_t pin,
						enum gpio_int_mode mode,
						enum gpio_int_trig trig)
{
	ARG_UNUSED(trig);

	const struct gpio_altera_config *cfg = dev->config;
	struct gpio_altera_data * const data = dev->data;
	uintptr_t reg_base = cfg->reg_base;
	const int port_pin_mask = cfg->common.port_pin_mask;
	uint32_t addr;
	k_spinlock_key_t key;

	/* Check if pin number is within range */
	if ((port_pin_mask & BIT(pin)) == 0) {
		return -EINVAL;
	}

	if (!gpio_pin_direction(dev, BIT(pin))) {
		return -EINVAL;
	}

	addr = reg_base + ALTERA_AVALON_PIO_IRQ_OFFSET;

	key = k_spin_lock(&data->lock);

	switch (mode) {
	case GPIO_INT_MODE_DISABLED:
		/* Disable interrupt of pin */
		sys_clear_bits(addr, BIT(pin));
		irq_disable(cfg->irq_num);
		break;
	case GPIO_INT_MODE_LEVEL:
	case GPIO_INT_MODE_EDGE:
		/* Enable interrupt of pin */
		sys_set_bits(addr, BIT(pin));
		irq_enable(cfg->irq_num);
		break;
	default:
		return -EINVAL;
	}

	k_spin_unlock(&data->lock, key);

	return 0;
}

static int gpio_altera_manage_callback(const struct device *dev,
					struct gpio_callback *callback,
					bool set)
{

	struct gpio_altera_data * const data = dev->data;

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

static void gpio_altera_irq_handler(const struct device *dev)
{
	const struct gpio_altera_config *cfg = dev->config;
	struct gpio_altera_data *data = dev->data;
	uintptr_t reg_base = cfg->reg_base;
	uint32_t port_value;
	uint32_t addr;
	k_spinlock_key_t key;

	addr = reg_base + ALTERA_AVALON_PIO_IRQ_OFFSET;

	key = k_spin_lock(&data->lock);

	port_value = sys_read32(addr);

	sys_clear_bits(addr, port_value);

	k_spin_unlock(&data->lock, key);

	/* Call the corresponding callback registered for the pin */
	gpio_fire_callbacks(&data->cb, dev, port_value);
}

static const struct gpio_driver_api gpio_altera_driver_api = {
	.pin_configure		 = gpio_altera_configure,
	.port_get_raw		 = gpio_altera_port_get_raw,
	.port_set_masked_raw	 = NULL,
	.port_set_bits_raw	 = gpio_altera_port_set_bits_raw,
	.port_clear_bits_raw	 = gpio_altera_port_clear_bits_raw,
	.port_toggle_bits	 = NULL,
	.pin_interrupt_configure = gpio_altera_pin_interrupt_configure,
	.manage_callback	 = gpio_altera_manage_callback
};

#define GPIO_CFG_IRQ(idx, n)							\
		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, idx, irq),			\
			    COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, priority), \
				DT_INST_IRQ(n, priority), (0)), gpio_altera_irq_handler,	\
			    DEVICE_DT_INST_GET(n), 0);				\

#define CREATE_GPIO_DEVICE(n)						\
	static void gpio_altera_cfg_func_##n(void);			\
	static struct gpio_altera_data gpio_altera_data_##n;		\
	static struct gpio_altera_config gpio_config_##n = {		\
		.common		= {					\
		.port_pin_mask	=					\
				  GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
		},						        \
		.reg_base	= DT_INST_REG_ADDR(n),			\
		.direction	= DT_INST_ENUM_IDX(n, direction),	\
		.irq_num	= COND_CODE_1(DT_INST_IRQ_HAS_IDX(n, 0), (DT_INST_IRQN(n)), (0)),\
		.cfg_func	= gpio_altera_cfg_func_##n,		\
		.outset		= DT_INST_PROP(n, outset),	\
		.outclear	= DT_INST_PROP(n, outclear),	\
	};								\
							\
	DEVICE_DT_INST_DEFINE(n,			\
			      gpio_init,		\
			      NULL,			\
			      &gpio_altera_data_##n,	\
			      &gpio_config_##n,		\
			      POST_KERNEL,		\
			      CONFIG_GPIO_INIT_PRIORITY,	\
			      &gpio_altera_driver_api);		        \
									\
	static void gpio_altera_cfg_func_##n(void)			\
	{								\
		LISTIFY(DT_NUM_IRQS(DT_DRV_INST(n)), GPIO_CFG_IRQ, (), n)\
	}

DT_INST_FOREACH_STATUS_OKAY(CREATE_GPIO_DEVICE)
