/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT nordic_npm6001_gpio

#include <errno.h>

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/dt-bindings/gpio/nordic-npm6001-gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/toolchain.h>

/* nPM6001 GPIO related registers */
#define NPM6001_GPIOOUTSET 0x69U
#define NPM6001_GPIOOUTCLR 0x6AU
#define NPM6001_GPIOIN	   0x6BU
#define NPM6001_GPIO0CONF  0x6CU
#define NPM6001_GPIO1CONF  0x6DU
#define NPM6001_GPIO2CONF  0x6EU

/* GPIO(0|1|2)CONF fields */
#define NPM6001_CONF_DIRECTION_OUTPUT BIT(0)
#define NPM6001_CONF_INPUT_ENABLED    BIT(1)
#define NPM6001_CONF_PULLDOWN_ENABLED BIT(2)
#define NPM6001_CONF_DRIVE_HIGH	      BIT(5)
#define NPM6001_CONF_SENSE_CMOS	      BIT(6)

#define NPM6001_PIN_MAX 2U
#define NPM6001_PIN_MSK 0x7U

struct gpio_npm6001_config {
	struct gpio_driver_config common;
	struct i2c_dt_spec bus;
};

struct gpio_npm6001_data {
	struct gpio_driver_data common;
};

static int gpio_npm6001_port_get_raw(const struct device *dev, uint32_t *value)
{
	const struct gpio_npm6001_config *config = dev->config;
	uint8_t reg = NPM6001_GPIOIN;
	uint8_t val;
	int ret;

	if (k_is_in_isr()) {
		return -EWOULDBLOCK;
	}

	ret = i2c_write_read_dt(&config->bus, &reg, sizeof(reg), &val,
				sizeof(val));
	if (ret < 0) {
		return ret;
	}

	*value = val;

	return 0;
}

static int gpio_npm6001_port_set_bits_raw(const struct device *dev,
					  gpio_port_pins_t pins)
{
	const struct gpio_npm6001_config *config = dev->config;
	uint8_t buf[2] = {NPM6001_GPIOOUTSET, (uint8_t)pins & NPM6001_PIN_MSK};

	if (k_is_in_isr()) {
		return -EWOULDBLOCK;
	}

	return i2c_write_dt(&config->bus, buf, sizeof(buf));
}

static int gpio_npm6001_port_clear_bits_raw(const struct device *dev,
					    gpio_port_pins_t pins)
{
	const struct gpio_npm6001_config *config = dev->config;
	uint8_t buf[2] = {NPM6001_GPIOOUTCLR, (uint8_t)pins & NPM6001_PIN_MSK};

	if (k_is_in_isr()) {
		return -EWOULDBLOCK;
	}

	return i2c_write_dt(&config->bus, buf, sizeof(buf));
}

static inline int gpio_npm6001_configure(const struct device *dev,
					 gpio_pin_t pin, gpio_flags_t flags)
{
	const struct gpio_npm6001_config *config = dev->config;
	uint8_t buf[2] = {NPM6001_GPIO0CONF, 0U};

	if (k_is_in_isr()) {
		return -EWOULDBLOCK;
	}

	if (pin > NPM6001_PIN_MAX) {
		return -EINVAL;
	}

	/* select GPIO0CONF/GPIO1CONF/GPIO2CONF */
	buf[0] += pin;

	if ((flags & GPIO_OUTPUT) != 0U) {
		/* input buffer enabled to allow reading output level */
		buf[1] |= NPM6001_CONF_DIRECTION_OUTPUT |
			  NPM6001_CONF_INPUT_ENABLED;

		/* open-drain/open-source not supported */
		if ((flags & GPIO_SINGLE_ENDED) != 0U) {
			return -ENOTSUP;
		}

		/* drive strength (defaults to normal) */
		if ((flags & NPM6001_GPIO_DRIVE_MSK) ==
		    NPM6001_GPIO_DRIVE_HIGH) {
			buf[1] |= NPM6001_CONF_DRIVE_HIGH;
		}

		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
			int ret;

			ret = gpio_npm6001_port_set_bits_raw(
				dev, (gpio_port_pins_t)BIT(pin));
			if (ret < 0) {
				return ret;
			}
		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
			int ret;

			ret = gpio_npm6001_port_clear_bits_raw(
				dev, (gpio_port_pins_t)BIT(pin));
			if (ret < 0) {
				return ret;
			}
		}
	} else if ((flags & GPIO_INPUT) != 0U) {
		buf[1] |= NPM6001_CONF_INPUT_ENABLED;

		/* pull resistor */
		if ((flags & GPIO_PULL_DOWN) != 0U) {
			buf[1] |= NPM6001_CONF_PULLDOWN_ENABLED;
		} else if ((flags & GPIO_PULL_UP) != 0U) {
			return -ENOTSUP;
		}

		/* input type (defaults to schmitt trigger) */
		if ((flags & NPM6001_GPIO_SENSE_MSK) ==
		    NPM6001_GPIO_SENSE_CMOS) {
			buf[1] |= NPM6001_CONF_SENSE_CMOS;
		}
	} else {
		return -ENOTSUP;
	}

	return i2c_write_dt(&config->bus, buf, sizeof(buf));
}

static int gpio_npm6001_port_set_masked_raw(const struct device *dev,
					    gpio_port_pins_t mask,
					    gpio_port_value_t value)
{
	int ret;

	ret = gpio_npm6001_port_set_bits_raw(dev, mask & value);
	if (ret < 0) {
		return ret;
	}

	return gpio_npm6001_port_clear_bits_raw(
		dev, mask & (~value & NPM6001_PIN_MSK));
}

static int gpio_npm6001_port_toggle_bits(const struct device *dev,
					 gpio_port_pins_t pins)
{
	uint32_t val;
	int ret;

	ret = gpio_npm6001_port_get_raw(dev, &val);
	if (ret < 0) {
		return ret;
	}

	return gpio_npm6001_port_set_masked_raw(dev, pins,
						~val & NPM6001_PIN_MSK);
}

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

	return -ENOTSUP;
}

static const struct gpio_driver_api gpio_npm6001_api = {
	.pin_configure = gpio_npm6001_configure,
	.port_get_raw = gpio_npm6001_port_get_raw,
	.port_set_masked_raw = gpio_npm6001_port_set_masked_raw,
	.port_set_bits_raw = gpio_npm6001_port_set_bits_raw,
	.port_clear_bits_raw = gpio_npm6001_port_clear_bits_raw,
	.port_toggle_bits = gpio_npm6001_port_toggle_bits,
	.pin_interrupt_configure = gpio_npm6001_pin_interrupt_configure,
};

static int gpio_npm6001_init(const struct device *dev)
{
	const struct gpio_npm6001_config *config = dev->config;

	if (!device_is_ready(config->bus.bus)) {
		return -ENODEV;
	}

	return 0;
}

#define GPIO_NPM6001_DEFINE(n)                                                 \
	static const struct gpio_npm6001_config gpio_npm6001_config##n = {     \
		.common =                                                      \
			{                                                      \
				.port_pin_mask =                               \
					GPIO_PORT_PIN_MASK_FROM_DT_INST(n),    \
			},                                                     \
		.bus = I2C_DT_SPEC_GET(DT_INST_PARENT(n))};                    \
                                                                               \
	static struct gpio_npm6001_data gpio_npm6001_data##n;                  \
                                                                               \
	DEVICE_DT_INST_DEFINE(n, &gpio_npm6001_init, NULL,                     \
			      &gpio_npm6001_data##n, &gpio_npm6001_config##n,  \
			      POST_KERNEL, CONFIG_GPIO_NPM6001_INIT_PRIORITY,  \
			      &gpio_npm6001_api);

DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM6001_DEFINE)
