/*
 * Copyright (c) 2016 Linaro Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief Driver to provide the GPIO API for a simple 32-bit i/o register
 *
 * This is a driver for accessing a simple, fixed purpose, 32-bit
 * memory-mapped i/o register using the same APIs as GPIO drivers. This is
 * useful when an SoC or board has registers that aren't part of a GPIO IP
 * block and these registers are used to control things that Zephyr normally
 * expects to be specified using a GPIO pin, e.g. for driving an LED, or
 * chip-select line for an SPI device.
 *
 * The implementation expects that all bits of the hardware register are both
 * readable and writable, and that for any bits that act as outputs, the value
 * read will have the value that was last written to it. This requirement
 * stems from the use of a read-modify-write method for all changes.
 *
 * It is possible to specify a restricted mask of bits that are valid for
 * access, and whenever the register is written, the value of bits outside this
 * mask will be preserved, even when the whole port is written to using
 * gpio_port_write.
 */

#include <drivers/gpio/gpio_mmio32.h>
#include <errno.h>

static int gpio_mmio32_config(const struct device *dev,
			      gpio_pin_t pin, gpio_flags_t flags)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;

	if ((config->mask & (1 << pin)) == 0) {
		return -EINVAL; /* Pin not in our validity mask */
	}

	if (flags & ~(GPIO_INPUT | GPIO_OUTPUT |
		      GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH |
		      GPIO_ACTIVE_LOW)) {
		/* We ignore direction and fake polarity, rest is unsupported */
		return -ENOTSUP;
	}

	if ((flags & GPIO_OUTPUT) != 0) {
		unsigned int key;
		volatile uint32_t *reg = config->reg;

		key = irq_lock();
		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
			*reg = (*reg | (1 << pin));
		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
			*reg = (*reg & (config->mask & ~(1 << pin)));
		}
		irq_unlock(key);
	}

	return 0;
}

static int gpio_mmio32_port_get_raw(const struct device *dev, uint32_t *value)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;

	*value = *config->reg & config->mask;

	return 0;
}

static int gpio_mmio32_port_set_masked_raw(const struct device *dev,
					   uint32_t mask,
					   uint32_t value)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;
	volatile uint32_t *reg = config->reg;
	unsigned int key;

	mask &= config->mask;
	value &= mask;

	/* Update pin state atomically */
	key = irq_lock();
	*reg = (*reg & ~mask) | value;
	irq_unlock(key);

	return 0;
}

static int gpio_mmio32_port_set_bits_raw(const struct device *dev,
					 uint32_t mask)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;
	volatile uint32_t *reg = config->reg;
	unsigned int key;

	mask &= config->mask;

	/* Update pin state atomically */
	key = irq_lock();
	*reg = (*reg | mask);
	irq_unlock(key);

	return 0;
}

static int gpio_mmio32_port_clear_bits_raw(const struct device *dev,
					   uint32_t mask)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;
	volatile uint32_t *reg = config->reg;
	unsigned int key;

	mask &= config->mask;

	/* Update pin state atomically */
	key = irq_lock();
	*reg = (*reg & ~mask);
	irq_unlock(key);

	return 0;
}

static int gpio_mmio32_port_toggle_bits(const struct device *dev,
					uint32_t mask)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = context->config;
	volatile uint32_t *reg = config->reg;
	unsigned int key;

	mask &= config->mask;

	/* Update pin state atomically */
	key = irq_lock();
	*reg = (*reg ^ mask);
	irq_unlock(key);

	return 0;
}

static int gpio_mmio32_pin_interrupt_configure(const struct device *dev,
					       gpio_pin_t pin,
					       enum gpio_int_mode mode,
					       enum gpio_int_trig trig)
{
	if (mode != GPIO_INT_MODE_DISABLED) {
		return -ENOTSUP;
	}

	return 0;
}

const struct gpio_driver_api gpio_mmio32_api = {
	.pin_configure = gpio_mmio32_config,
	.port_get_raw = gpio_mmio32_port_get_raw,
	.port_set_masked_raw = gpio_mmio32_port_set_masked_raw,
	.port_set_bits_raw = gpio_mmio32_port_set_bits_raw,
	.port_clear_bits_raw = gpio_mmio32_port_clear_bits_raw,
	.port_toggle_bits = gpio_mmio32_port_toggle_bits,
	.pin_interrupt_configure = gpio_mmio32_pin_interrupt_configure,
};

int gpio_mmio32_init(const struct device *dev)
{
	struct gpio_mmio32_context *context = dev->data;
	const struct gpio_mmio32_config *config = dev->config;

	context->config = config;

	return 0;
}
