// SPDX-License-Identifier: GPL-2.0+
//
// Synopsys CREG (Control REGisters) GPIO driver
//
// Copyright (C) 2018 Synopsys
// Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>

#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_platform.h>

#define MAX_GPIO	32

struct creg_layout {
	u8 ngpio;
	u8 shift[MAX_GPIO];
	u8 on[MAX_GPIO];
	u8 off[MAX_GPIO];
	u8 bit_per_gpio[MAX_GPIO];
};

struct creg_gpio {
	struct gpio_chip gc;
	void __iomem *regs;
	spinlock_t lock;
	const struct creg_layout *layout;
};

static void creg_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
{
	struct creg_gpio *hcg = gpiochip_get_data(gc);
	const struct creg_layout *layout = hcg->layout;
	u32 reg, reg_shift, value;
	unsigned long flags;
	int i;

	value = val ? hcg->layout->on[offset] : hcg->layout->off[offset];

	reg_shift = layout->shift[offset];
	for (i = 0; i < offset; i++)
		reg_shift += layout->bit_per_gpio[i] + layout->shift[i];

	spin_lock_irqsave(&hcg->lock, flags);
	reg = readl(hcg->regs);
	reg &= ~(GENMASK(layout->bit_per_gpio[i] - 1, 0) << reg_shift);
	reg |=  (value << reg_shift);
	writel(reg, hcg->regs);
	spin_unlock_irqrestore(&hcg->lock, flags);
}

static int creg_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
{
	creg_gpio_set(gc, offset, val);

	return 0;
}

static int creg_gpio_validate_pg(struct device *dev, struct creg_gpio *hcg,
				 int i)
{
	const struct creg_layout *layout = hcg->layout;

	if (layout->bit_per_gpio[i] < 1 || layout->bit_per_gpio[i] > 8)
		return -EINVAL;

	/* Check that on value fits its placeholder */
	if (GENMASK(31, layout->bit_per_gpio[i]) & layout->on[i])
		return -EINVAL;

	/* Check that off value fits its placeholder */
	if (GENMASK(31, layout->bit_per_gpio[i]) & layout->off[i])
		return -EINVAL;

	if (layout->on[i] == layout->off[i])
		return -EINVAL;

	return 0;
}

static int creg_gpio_validate(struct device *dev, struct creg_gpio *hcg,
			      u32 ngpios)
{
	u32 reg_len = 0;
	int i;

	if (hcg->layout->ngpio < 1 || hcg->layout->ngpio > MAX_GPIO)
		return -EINVAL;

	if (ngpios < 1 || ngpios > hcg->layout->ngpio) {
		dev_err(dev, "ngpios must be in [1:%u]\n", hcg->layout->ngpio);
		return -EINVAL;
	}

	for (i = 0; i < hcg->layout->ngpio; i++) {
		if (creg_gpio_validate_pg(dev, hcg, i))
			return -EINVAL;

		reg_len += hcg->layout->shift[i] + hcg->layout->bit_per_gpio[i];
	}

	/* Check that we fit in 32 bit register */
	if (reg_len > 32)
		return -EINVAL;

	return 0;
}

static const struct creg_layout hsdk_cs_ctl = {
	.ngpio		= 10,
	.shift		= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	.off		= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
	.on		= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
	.bit_per_gpio	= { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }
};

static const struct creg_layout axs10x_flsh_cs_ctl = {
	.ngpio		= 1,
	.shift		= { 0 },
	.off		= { 1 },
	.on		= { 3 },
	.bit_per_gpio	= { 2 }
};

static const struct of_device_id creg_gpio_ids[] = {
	{
		.compatible = "snps,creg-gpio-axs10x",
		.data = &axs10x_flsh_cs_ctl
	}, {
		.compatible = "snps,creg-gpio-hsdk",
		.data = &hsdk_cs_ctl
	}, { /* sentinel */ }
};

static int creg_gpio_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	struct device *dev = &pdev->dev;
	struct creg_gpio *hcg;
	u32 ngpios;
	int ret;

	hcg = devm_kzalloc(dev, sizeof(struct creg_gpio), GFP_KERNEL);
	if (!hcg)
		return -ENOMEM;

	hcg->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(hcg->regs))
		return PTR_ERR(hcg->regs);

	match = of_match_node(creg_gpio_ids, pdev->dev.of_node);
	hcg->layout = match->data;
	if (!hcg->layout)
		return -EINVAL;

	ret = of_property_read_u32(dev->of_node, "ngpios", &ngpios);
	if (ret)
		return ret;

	ret = creg_gpio_validate(dev, hcg, ngpios);
	if (ret)
		return ret;

	spin_lock_init(&hcg->lock);

	hcg->gc.label = dev_name(dev);
	hcg->gc.base = -1;
	hcg->gc.ngpio = ngpios;
	hcg->gc.set = creg_gpio_set;
	hcg->gc.direction_output = creg_gpio_dir_out;
	hcg->gc.of_node = dev->of_node;

	ret = devm_gpiochip_add_data(dev, &hcg->gc, hcg);
	if (ret)
		return ret;

	dev_info(dev, "GPIO controller with %d gpios probed\n", ngpios);

	return 0;
}

static struct platform_driver creg_gpio_snps_driver = {
	.driver = {
		.name = "snps-creg-gpio",
		.of_match_table = creg_gpio_ids,
	},
	.probe  = creg_gpio_probe,
};
builtin_platform_driver(creg_gpio_snps_driver);
