/*
 * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file Driver for the pulpino GPIO controller.
 */

#include <errno.h>
#include <kernel.h>
#include <device.h>
#include <soc.h>
#include <gpio.h>
#include <misc/util.h>

#include "gpio_utils.h"

typedef void (*pulpino_cfg_func_t)(void);

/* pulpino GPIO register-set structure */
struct gpio_pulpino_t {
	u32_t paddir;
	u32_t padin;
	u32_t padout;
	u32_t inten;
	u32_t inttype0;
	u32_t inttype1;
	u32_t intstatus;
};

struct gpio_pulpino_config {
	u32_t              gpio_base_addr;
	pulpino_cfg_func_t    gpio_cfg_func;
};

struct gpio_pulpino_data {
	/* list of callbacks */
	sys_slist_t cb;
};

/* Helper Macros for GPIO */
#define DEV_GPIO_CFG(dev)						\
	((const struct gpio_pulpino_config * const)(dev)->config->config_info)
#define DEV_GPIO(dev)							\
	((volatile struct gpio_pulpino_t *)(DEV_GPIO_CFG(dev))->gpio_base_addr)
#define DEV_GPIO_DATA(dev)					\
	((struct gpio_pulpino_data *)(dev)->driver_data)

static void gpio_pulpino_irq_handler(void *arg)
{
	struct device *dev = (struct device *)arg;
	struct gpio_pulpino_data *data = DEV_GPIO_DATA(dev);
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	_gpio_fire_callbacks(&data->cb, dev, gpio->intstatus);
}

/**
 * @brief Configure pin
 *
 * @param dev Device structure
 * @param access_op Access operation
 * @param pin The pin number
 * @param flags Flags of pin or port
 *
 * @return 0 if successful, failed otherwise
 */
static int gpio_pulpino_config(struct device *dev,
			       int access_op,
			       u32_t pin,
			       int flags)
{
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	if (access_op != GPIO_ACCESS_BY_PIN)
		return -ENOTSUP;

	if (pin > 31)
		return -EINVAL;

	/* Configure pin as gpio */
	PULP_PADMUX |= (PULP_PAD_GPIO << pin);

	/* Configure gpio direction */
	if (flags & GPIO_DIR_OUT)
		gpio->paddir |= BIT(pin);
	else
		gpio->paddir &= ~BIT(pin);

	/*
	 * Configure interrupt if GPIO_INT is set.
	 * Here, we just configure the gpio interrupt behavior,
	 * we do not enable/disable interrupt for a particular
	 * gpio.
	 * Interrupt for a gpio is:
	 * 1) enabled only via a call to gpio_pulpino_enable_callback.
	 * 2) disabled only via a call to gpio_pulpino_disabled_callback.
	 */
	if (!(flags & GPIO_INT))
		return 0;

	/*
	 * Interrupt cannot be set for GPIO_DIR_OUT
	 */
	if (flags & GPIO_DIR_OUT)
		return -EINVAL;

	/* Double edge trigger not supported */
	if (flags & GPIO_INT_DOUBLE_EDGE)
		return -ENOTSUP;

	/* Edge or Level triggered ? */
	if (flags & GPIO_INT_EDGE)
		gpio->inttype1 |= BIT(pin);
	else
		gpio->inttype1 &= ~BIT(pin);

	/* Level High/Rising Edge ? */
	if (flags & GPIO_INT_ACTIVE_HIGH)
		gpio->inttype0 &= ~BIT(pin);
	else
		gpio->inttype0 |= BIT(pin);

	return 0;
}

/**
 * @brief Set the pin
 *
 * @param dev Device struct
 * @param access_op Access operation
 * @param pin The pin number
 * @param value Value to set (0 or 1)
 *
 * @return 0 if successful, failed otherwise
 */
static int gpio_pulpino_write(struct device *dev,
			      int access_op,
			      u32_t pin,
			      u32_t value)
{
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	if (access_op != GPIO_ACCESS_BY_PIN)
		return -ENOTSUP;

	if (value)
		gpio->padout |= BIT(pin);
	else
		gpio->padout &= ~BIT(pin);

	return 0;
}

/**
 * @brief Read the pin
 *
 * @param dev Device struct
 * @param access_op Access operation
 * @param pin The pin number
 * @param value Value of input pin(s)
 *
 * @return 0 if successful, failed otherwise
 */
static int gpio_pulpino_read(struct device *dev,
			     int access_op,
			     u32_t pin,
			     u32_t *value)
{
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	if (access_op != GPIO_ACCESS_BY_PIN)
		return -ENOTSUP;

	/*
	 * If gpio is configured as output,
	 * read gpio value from padout register,
	 * otherwise read gpio value from padin register
	 */
	if (gpio->paddir & BIT(pin))
		*value = !!(gpio->padout & BIT(pin));
	else
		*value = !!(gpio->padin & BIT(pin));

	return 0;
}

static int gpio_pulpino_manage_callback(struct device *dev,
					struct gpio_callback *callback,
					bool set)
{
	struct gpio_pulpino_data *data = DEV_GPIO_DATA(dev);

	_gpio_manage_callback(&data->cb, callback, set);

	return 0;
}

static int gpio_pulpino_enable_callback(struct device *dev,
					int access_op,
					u32_t pin)
{
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	if (access_op != GPIO_ACCESS_BY_PIN)
		return -ENOTSUP;

	/* Enable interrupt for pin */
	gpio->inten |= BIT(pin);

	return 0;
}

static int gpio_pulpino_disable_callback(struct device *dev,
					 int access_op,
					 u32_t pin)
{
	volatile struct gpio_pulpino_t *gpio = DEV_GPIO(dev);

	if (access_op != GPIO_ACCESS_BY_PIN)
		return -ENOTSUP;

	/* Disable interrupt for pin */
	gpio->inten &= ~BIT(pin);

	return 0;
}

static const struct gpio_driver_api gpio_pulpino_driver = {
	.config              = gpio_pulpino_config,
	.write               = gpio_pulpino_write,
	.read                = gpio_pulpino_read,
	.manage_callback     = gpio_pulpino_manage_callback,
	.enable_callback     = gpio_pulpino_enable_callback,
	.disable_callback    = gpio_pulpino_disable_callback,
};

/**
 * @brief Initialize a GPIO controller
 *
 * Perform basic initialization of a GPIO controller
 *
 * @param dev GPIO device struct
 *
 * @return 0
 */
static int gpio_pulpino_init(struct device *dev)
{
	const struct gpio_pulpino_config *cfg = DEV_GPIO_CFG(dev);

	cfg->gpio_cfg_func();

	return 0;
}

static void gpio_pulpino_cfg_0(void);

static const struct gpio_pulpino_config gpio_pulpino_config0 = {
	.gpio_base_addr    = PULP_GPIO_0_BASE,
	.gpio_cfg_func     = gpio_pulpino_cfg_0,
};

static struct gpio_pulpino_data gpio_pulpino_data0;

DEVICE_AND_API_INIT(gpio_pulpino_0, "gpio0", gpio_pulpino_init,
		    &gpio_pulpino_data0, &gpio_pulpino_config0,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &gpio_pulpino_driver);

static void gpio_pulpino_cfg_0(void)
{
	IRQ_CONNECT(PULP_GPIO_0_IRQ,
		    0,
		    gpio_pulpino_irq_handler,
		    DEVICE_GET(gpio_pulpino_0),
		    0);
	irq_enable(PULP_GPIO_0_IRQ);
}
