// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Congatec Board Controller GPIO driver
 *
 * Copyright (C) 2024 Bootlin
 * Author: Thomas Richard <thomas.richard@bootlin.com>
 */

#include <linux/gpio/driver.h>
#include <linux/mfd/cgbc.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>

#define CGBC_GPIO_NGPIO	14

#define CGBC_GPIO_CMD_GET	0x64
#define CGBC_GPIO_CMD_SET	0x65
#define CGBC_GPIO_CMD_DIR_GET	0x66
#define CGBC_GPIO_CMD_DIR_SET	0x67

struct cgbc_gpio_data {
	struct gpio_chip	chip;
	struct cgbc_device_data	*cgbc;
	struct mutex lock;
};

static int cgbc_gpio_cmd(struct cgbc_device_data *cgbc,
			 u8 cmd0, u8 cmd1, u8 cmd2, u8 *value)
{
	u8 cmd[3] = {cmd0, cmd1, cmd2};

	return cgbc_command(cgbc, cmd, sizeof(cmd), value, 1, NULL);
}

static int cgbc_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	int ret;
	u8 val;

	scoped_guard(mutex, &gpio->lock)
		ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);

	offset %= 8;

	if (ret)
		return ret;

	return !!(val & BIT(offset));
}

static int __cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset,
			   int value)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	u8 val;
	int ret;

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_GET, (offset > 7) ? 1 : 0, 0, &val);
	if (ret)
		return ret;

	if (value)
		val |= BIT(offset % 8);
	else
		val &= ~(BIT(offset % 8));

	return cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_SET, (offset > 7) ? 1 : 0, val, &val);
}

static int cgbc_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);

	guard(mutex)(&gpio->lock);

	return __cgbc_gpio_set(chip, offset, value);
}

static int cgbc_gpio_direction_set(struct gpio_chip *chip,
				   unsigned int offset, int direction)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	int ret;
	u8 val;

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_GET, (offset > 7) ? 1 : 0, 0, &val);
	if (ret)
		goto end;

	if (direction == GPIO_LINE_DIRECTION_IN)
		val &= ~(BIT(offset % 8));
	else
		val |= BIT(offset % 8);

	ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_SET, (offset > 7) ? 1 : 0, val, &val);

end:
	return ret;
}

static int cgbc_gpio_direction_input(struct gpio_chip *chip,
				     unsigned int offset)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);

	guard(mutex)(&gpio->lock);
	return cgbc_gpio_direction_set(chip, offset, GPIO_LINE_DIRECTION_IN);
}

static int cgbc_gpio_direction_output(struct gpio_chip *chip,
				      unsigned int offset, int value)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	int ret;

	guard(mutex)(&gpio->lock);

	ret = __cgbc_gpio_set(chip, offset, value);
	if (ret)
		return ret;

	return cgbc_gpio_direction_set(chip, offset, GPIO_LINE_DIRECTION_OUT);
}

static int cgbc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
	struct cgbc_gpio_data *gpio = gpiochip_get_data(chip);
	struct cgbc_device_data *cgbc = gpio->cgbc;
	int ret;
	u8 val;

	scoped_guard(mutex, &gpio->lock)
		ret = cgbc_gpio_cmd(cgbc, CGBC_GPIO_CMD_DIR_GET, (offset > 7) ? 1 : 0, 0, &val);

	if (ret)
		return ret;

	if (val & BIT(offset % 8))
		return GPIO_LINE_DIRECTION_OUT;
	else
		return GPIO_LINE_DIRECTION_IN;
}

static int cgbc_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct cgbc_device_data *cgbc = dev_get_drvdata(dev->parent);
	struct cgbc_gpio_data *gpio;
	struct gpio_chip *chip;
	int ret;

	gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
	if (!gpio)
		return -ENOMEM;

	gpio->cgbc = cgbc;

	platform_set_drvdata(pdev, gpio);

	chip = &gpio->chip;
	chip->label = dev_name(&pdev->dev);
	chip->owner = THIS_MODULE;
	chip->parent = dev;
	chip->base = -1;
	chip->direction_input = cgbc_gpio_direction_input;
	chip->direction_output = cgbc_gpio_direction_output;
	chip->get_direction = cgbc_gpio_get_direction;
	chip->get = cgbc_gpio_get;
	chip->set = cgbc_gpio_set;
	chip->ngpio = CGBC_GPIO_NGPIO;

	ret = devm_mutex_init(dev, &gpio->lock);
	if (ret)
		return ret;

	ret = devm_gpiochip_add_data(dev, chip, gpio);
	if (ret)
		return dev_err_probe(dev, ret, "Could not register GPIO chip\n");

	return 0;
}

static struct platform_driver cgbc_gpio_driver = {
	.driver = {
		.name = "cgbc-gpio",
	},
	.probe	= cgbc_gpio_probe,
};

module_platform_driver(cgbc_gpio_driver);

MODULE_DESCRIPTION("Congatec Board Controller GPIO Driver");
MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:cgbc-gpio");
