/*
 * Copyright (c) 2018 Justin Watson
 * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT atmel_sam4l_gpio

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <soc.h>
#include <zephyr/drivers/gpio.h>

#include "gpio_utils.h"

typedef void (*config_func_t)(const struct device *dev);

struct gpio_sam_config {
	/* gpio_driver_config needs to be first */
	struct gpio_driver_config common;
	Gpio *regs;
	config_func_t config_func;
	uint32_t periph_id;
};

struct gpio_sam_runtime {
	/* gpio_driver_data needs to be first */
	struct gpio_driver_data common;
	sys_slist_t cb;
};

#define GPIO_SAM_ALL_PINS    0xFFFFFFFF

static int gpio_sam_port_configure(const struct device *dev,
				   uint32_t mask,
				   gpio_flags_t flags)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	/* No hardware support */
	if (flags & GPIO_SINGLE_ENDED) {
		return -ENOTSUP;
	}

	if (!(flags & (GPIO_OUTPUT | GPIO_INPUT))) {
		gpio->IERC = mask;
		gpio->PUERC = mask;
		gpio->PDERC = mask;
		gpio->GPERS = mask;
		gpio->ODERC = mask;
		gpio->STERC = mask;

		return 0;
	}

	/*
	 * Always enable schmitt-trigger because SAM4L GPIO Ctrl
	 * is Input only or Input/Output.
	 */
	gpio->STERS = mask;

	if (flags & GPIO_OUTPUT) {
		if (flags & GPIO_OUTPUT_INIT_HIGH) {
			gpio->OVRS = mask;
		}
		if (flags & GPIO_OUTPUT_INIT_LOW) {
			gpio->OVRC = mask;
		}
		gpio->ODERS = mask;
	} else {
		gpio->ODERC = mask;
	}

	gpio->PUERC = mask;
	gpio->PDERC = mask;
	if (flags & GPIO_PULL_UP) {
		gpio->PUERS = mask;
	} else if (flags & GPIO_PULL_DOWN) {
		gpio->PDERS = mask;
	}

	/* Enable the GPIO to control the pin (instead of a peripheral). */
	gpio->GPERS = mask;

	return 0;
}

static int gpio_sam_config(const struct device *dev,
			   gpio_pin_t pin,
			   gpio_flags_t flags)
{
	return gpio_sam_port_configure(dev, BIT(pin), flags);
}

static int gpio_sam_port_get_raw(const struct device *dev,
				 uint32_t *value)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	*value = gpio->PVR;

	return 0;
}

static int gpio_sam_port_set_masked_raw(const struct device *dev,
					uint32_t mask,
					uint32_t value)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	gpio->OVR = (gpio->PVR & ~mask) | (mask & value);

	return 0;
}

static int gpio_sam_port_set_bits_raw(const struct device *dev,
				      uint32_t mask)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	gpio->OVRS = mask;

	return 0;
}

static int gpio_sam_port_clear_bits_raw(const struct device *dev,
					uint32_t mask)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	gpio->OVRC = mask;

	return 0;
}

static int gpio_sam_port_toggle_bits(const struct device *dev,
				     uint32_t mask)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	gpio->OVRT = mask;

	return 0;
}

static int gpio_sam_port_interrupt_configure(const struct device *dev,
					     uint32_t mask,
					     enum gpio_int_mode mode,
					     enum gpio_int_trig trig)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;

	if (mode == GPIO_INT_MODE_LEVEL) {
		return -ENOTSUP;
	}

	gpio->IERC = mask;
	gpio->IMR0C = mask;
	gpio->IMR1C = mask;

	if (trig != GPIO_INT_TRIG_BOTH) {
		if (trig == GPIO_INT_TRIG_HIGH) {
			gpio->IMR0S = mask;
		} else {
			gpio->IMR1S = mask;
		}
	}

	if (mode != GPIO_INT_MODE_DISABLED) {
		gpio->IFRC = mask;
		gpio->IERS = mask;
	}

	return 0;
}

static int gpio_sam_pin_interrupt_configure(const struct device *dev,
					    gpio_pin_t pin,
					    enum gpio_int_mode mode,
					    enum gpio_int_trig trig)
{
	return gpio_sam_port_interrupt_configure(dev, BIT(pin), mode, trig);
}

static void gpio_sam_isr(const struct device *dev)
{
	const struct gpio_sam_config * const cfg = dev->config;
	Gpio * const gpio = cfg->regs;
	struct gpio_sam_runtime *context = dev->data;
	uint32_t int_stat;

	int_stat = gpio->IFR;
	gpio->IFRC = int_stat;

	gpio_fire_callbacks(&context->cb, dev, int_stat);
}

static int gpio_sam_manage_callback(const struct device *port,
				    struct gpio_callback *callback,
				    bool set)
{
	struct gpio_sam_runtime *context = port->data;

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

static const struct gpio_driver_api gpio_sam_api = {
	.pin_configure = gpio_sam_config,
	.port_get_raw = gpio_sam_port_get_raw,
	.port_set_masked_raw = gpio_sam_port_set_masked_raw,
	.port_set_bits_raw = gpio_sam_port_set_bits_raw,
	.port_clear_bits_raw = gpio_sam_port_clear_bits_raw,
	.port_toggle_bits = gpio_sam_port_toggle_bits,
	.pin_interrupt_configure = gpio_sam_pin_interrupt_configure,
	.manage_callback = gpio_sam_manage_callback,
};

int gpio_sam_init(const struct device *dev)
{
	const struct gpio_sam_config * const cfg = dev->config;

	soc_pmc_peripheral_enable(cfg->periph_id);

	cfg->config_func(dev);

	return 0;
}

#define GPIO_SAM_IRQ_CONNECT(n, m)					\
	do {								\
		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, m, irq),		\
			    DT_INST_IRQ_BY_IDX(n, m, priority),		\
			    gpio_sam_isr,				\
			    DEVICE_DT_INST_GET(n), 0);			\
		irq_enable(DT_INST_IRQ_BY_IDX(n, m, irq));		\
	} while (false)

#define GPIO_SAM_INIT(n)						\
	static void port_##n##_sam_config_func(const struct device *dev);\
									\
	static const struct gpio_sam_config port_##n##_sam_config = {	\
		.common = {						\
			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),\
		},							\
		.regs = (Gpio *)DT_INST_REG_ADDR(n),			\
		.periph_id = DT_INST_PROP(n, peripheral_id),		\
		.config_func = port_##n##_sam_config_func,		\
	};								\
									\
	static struct gpio_sam_runtime port_##n##_sam_runtime;		\
									\
	DEVICE_DT_INST_DEFINE(n, gpio_sam_init, NULL,			\
			    &port_##n##_sam_runtime,			\
			    &port_##n##_sam_config, PRE_KERNEL_1,	\
			    CONFIG_GPIO_INIT_PRIORITY,			\
			    &gpio_sam_api);				\
									\
	static void port_##n##_sam_config_func(const struct device *dev)\
	{								\
		GPIO_SAM_IRQ_CONNECT(n, 0);				\
		GPIO_SAM_IRQ_CONNECT(n, 1);				\
		GPIO_SAM_IRQ_CONNECT(n, 2);				\
		GPIO_SAM_IRQ_CONNECT(n, 3);				\
	}

DT_INST_FOREACH_STATUS_OKAY(GPIO_SAM_INIT)
