/*
 * Copyright (C) 2023 BeagleBoard.org Foundation
 * Copyright (C) 2023 S Prashanth
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT ti_davinci_gpio

#include <errno.h>

#include <zephyr/arch/common/sys_bitops.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/sys_io.h>

/* Helper Macros for GPIO */
#define DEV_CFG(dev) \
		((const struct gpio_davinci_config * const)((dev)->config))
#define DEV_DATA(dev) ((struct gpio_davinci_data *)(dev)->data)
#define DEV_GPIO_CFG_BASE(dev) \
	((struct gpio_davinci_regs *)DEVICE_MMIO_NAMED_GET(dev, port_base))

#define GPIO_DAVINCI_DIR_RESET_VAL	(0xFFFFFFFF)

struct gpio_davinci_regs {
	uint32_t dir;
	uint32_t out_data;
	uint32_t set_data;
	uint32_t clr_data;
	uint32_t in_data;
	uint32_t set_ris_trig;
	uint32_t clr_ris_trig;
	uint32_t set_fal_trig;
	uint32_t clr_fal_trig;
	uint32_t intstat;
};

struct gpio_davinci_data {
	struct gpio_driver_data common;

	DEVICE_MMIO_NAMED_RAM(port_base);

	sys_slist_t cb;
};

struct gpio_davinci_config {
	void (*bank_config)(const struct device *dev);
	struct gpio_driver_config common;

	DEVICE_MMIO_NAMED_ROM(port_base);

	uint32_t port_num;
};

static int gpio_davinci_configure(const struct device *dev, gpio_pin_t pin,
					gpio_flags_t flags)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	if ((flags & GPIO_SINGLE_ENDED) != 0) {
		return -ENOTSUP;
	}

	if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
		return -ENOTSUP;
	}

	if ((flags & GPIO_OUTPUT) != 0) {
		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
			regs->set_data = BIT(pin);
		} else {
			regs->clr_data = BIT(pin);
		}

		regs->dir &= (~(BIT(pin)));

	} else {
		regs->dir |= (BIT(pin));
	}

	return 0;
}

static int gpio_davinci_port_get_raw(const struct device *dev,
					gpio_port_value_t *value)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	*value = regs->in_data;

	return 0;
}

static int gpio_davinci_port_set_masked_raw(const struct device *dev,
		gpio_port_pins_t mask, gpio_port_value_t value)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	regs->out_data = (regs->out_data & (~mask)) | (mask & value);

	return 0;
}

static int gpio_davinci_port_set_bits_raw(const struct device *dev,
						gpio_port_pins_t mask)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	regs->set_data |= mask;

	return 0;
}

static int gpio_davinci_port_clear_bits_raw(const struct device *dev,
						gpio_port_pins_t mask)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	regs->clr_data |= mask;

	return 0;
}

static int gpio_davinci_port_toggle_bits(const struct device *dev,
						gpio_port_pins_t mask)
{
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	regs->out_data ^= mask;

	return 0;
}

static const struct gpio_driver_api gpio_davinci_driver_api = {
	.pin_configure = gpio_davinci_configure,
	.port_get_raw = gpio_davinci_port_get_raw,
	.port_set_masked_raw = gpio_davinci_port_set_masked_raw,
	.port_set_bits_raw = gpio_davinci_port_set_bits_raw,
	.port_clear_bits_raw = gpio_davinci_port_clear_bits_raw,
	.port_toggle_bits = gpio_davinci_port_toggle_bits
};

static int gpio_davinci_init(const struct device *dev)
{
	const struct gpio_davinci_config *config = DEV_CFG(dev);
	volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev);

	DEVICE_MMIO_NAMED_MAP(dev, port_base, K_MEM_CACHE_NONE);

	regs->dir = GPIO_DAVINCI_DIR_RESET_VAL;

	config->bank_config(dev);

	return 0;
}

#define GPIO_DAVINCI_INIT_FUNC(n)	\
	static void gpio_davinci_bank_##n##_config(const struct device *dev)	\
	{	\
		volatile struct gpio_davinci_regs *regs = DEV_GPIO_CFG_BASE(dev); \
		ARG_UNUSED(regs);	\
	}

#define GPIO_DAVINCI_DEVICE_INIT(n)	\
	DEVICE_DT_INST_DEFINE(n, &gpio_davinci_##n##_init,	\
		NULL, &gpio_davinci_##n##_data,	\
		&gpio_davinci_##n##_config,	\
		POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY,	\
		&api_funcs)

#define GPIO_DAVINCI_INIT(n)	\
	\
	GPIO_DAVINCI_INIT_FUNC(n)	\
	static const struct gpio_davinci_config gpio_davinci_##n##_config = {	\
		.bank_config = gpio_davinci_bank_##n##_config,	\
		.common = {	\
			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
		},	\
		DEVICE_MMIO_NAMED_ROM_INIT(port_base, DT_DRV_INST(n)),	\
		.port_num = n	\
	};	\
	\
	static struct gpio_davinci_data gpio_davinci_##n##_data;	\
	\
	DEVICE_DT_INST_DEFINE(n,	\
		&gpio_davinci_init,	\
		NULL,	\
		&gpio_davinci_##n##_data,	\
		&gpio_davinci_##n##_config,	\
		PRE_KERNEL_2,	\
		CONFIG_GPIO_INIT_PRIORITY,	\
		&gpio_davinci_driver_api);

DT_INST_FOREACH_STATUS_OKAY(GPIO_DAVINCI_INIT)
