// SPDX-License-Identifier: GPL-2.0-only
/* Abilis Systems MODULE DESCRIPTION
 *
 * Copyright (C) Abilis Systems 2013
 *
 * Authors: Sascha Leuenberger <sascha.leuenberger@abilis.com>
 *          Christian Ruppert <christian.ruppert@abilis.com>
 */

#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/generic.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#define TB10X_GPIO_DIR_IN	(0x00000000)
#define TB10X_GPIO_DIR_OUT	(0x00000001)
#define OFFSET_TO_REG_DDR	(0x00)
#define OFFSET_TO_REG_DATA	(0x04)
#define OFFSET_TO_REG_INT_EN	(0x08)
#define OFFSET_TO_REG_CHANGE	(0x0C)
#define OFFSET_TO_REG_WRMASK	(0x10)
#define OFFSET_TO_REG_INT_TYPE	(0x14)


/**
 * @base: register base address
 * @domain: IRQ domain of GPIO generated interrupts managed by this controller
 * @irq: Interrupt line of parent interrupt controller
 * @chip: Generic GPIO chip structure associated with this GPIO controller
 */
struct tb10x_gpio {
	void __iomem *base;
	struct irq_domain *domain;
	int irq;
	struct gpio_generic_chip chip;
};

static inline u32 tb10x_reg_read(struct tb10x_gpio *gpio, unsigned int offs)
{
	return ioread32(gpio->base + offs);
}

static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
	struct tb10x_gpio *tb10x_gpio = gpiochip_get_data(chip);

	return irq_create_mapping(tb10x_gpio->domain, offset);
}

static int tb10x_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
	if ((type & IRQF_TRIGGER_MASK) != IRQ_TYPE_EDGE_BOTH) {
		pr_err("Only (both) edge triggered interrupts supported.\n");
		return -EINVAL;
	}

	irqd_set_trigger_type(data, type);

	return IRQ_SET_MASK_OK;
}

static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data)
{
	struct tb10x_gpio *tb10x_gpio = data;
	u32 r = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_CHANGE);
	u32 m = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_INT_EN);
	const unsigned long bits = r & m;
	int i;

	for_each_set_bit(i, &bits, 32)
		generic_handle_domain_irq(tb10x_gpio->domain, i);

	return IRQ_HANDLED;
}

static int tb10x_gpio_probe(struct platform_device *pdev)
{
	struct gpio_generic_chip_config config;
	struct tb10x_gpio *tb10x_gpio;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	int ret = -EBUSY;
	u32 ngpio;

	if (!np)
		return -EINVAL;

	if (of_property_read_u32(np, "abilis,ngpio", &ngpio))
		return -EINVAL;

	tb10x_gpio = devm_kzalloc(dev, sizeof(*tb10x_gpio), GFP_KERNEL);
	if (tb10x_gpio == NULL)
		return -ENOMEM;

	tb10x_gpio->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(tb10x_gpio->base))
		return PTR_ERR(tb10x_gpio->base);

	tb10x_gpio->chip.gc.label =
		devm_kasprintf(dev, GFP_KERNEL, "%pOF", pdev->dev.of_node);
	if (!tb10x_gpio->chip.gc.label)
		return -ENOMEM;

	/*
	 * Initialize generic GPIO with one single register for reading and setting
	 * the lines, no special set or clear registers and a data direction register
	 * wher 1 means "output".
	 */
	config = (struct gpio_generic_chip_config) {
		.dev = dev,
		.sz = 4,
		.dat = tb10x_gpio->base + OFFSET_TO_REG_DATA,
		.dirout = tb10x_gpio->base + OFFSET_TO_REG_DDR,
	};

	ret = gpio_generic_chip_init(&tb10x_gpio->chip, &config);
	if (ret) {
		dev_err(dev, "unable to init generic GPIO\n");
		return ret;
	}
	tb10x_gpio->chip.gc.base = -1;
	tb10x_gpio->chip.gc.parent = dev;
	tb10x_gpio->chip.gc.owner = THIS_MODULE;
	/*
	 * ngpio is set by gpio_generic_chip_init() but we override it, this
	 * .request() callback also overrides the one set up by generic GPIO.
	 */
	tb10x_gpio->chip.gc.ngpio = ngpio;
	tb10x_gpio->chip.gc.request = gpiochip_generic_request;
	tb10x_gpio->chip.gc.free = gpiochip_generic_free;

	ret = devm_gpiochip_add_data(dev, &tb10x_gpio->chip.gc, tb10x_gpio);
	if (ret < 0) {
		dev_err(dev, "Could not add gpiochip.\n");
		return ret;
	}

	platform_set_drvdata(pdev, tb10x_gpio);

	if (of_property_read_bool(np, "interrupt-controller")) {
		struct irq_chip_generic *gc;

		ret = platform_get_irq(pdev, 0);
		if (ret < 0)
			return ret;

		tb10x_gpio->chip.gc.to_irq = tb10x_gpio_to_irq;
		tb10x_gpio->irq		= ret;

		ret = devm_request_irq(dev, ret, tb10x_gpio_irq_cascade,
				IRQF_TRIGGER_NONE | IRQF_SHARED,
				dev_name(dev), tb10x_gpio);
		if (ret != 0)
			return ret;

		tb10x_gpio->domain = irq_domain_create_linear(dev_fwnode(dev),
							      tb10x_gpio->chip.gc.ngpio,
							      &irq_generic_chip_ops, NULL);
		if (!tb10x_gpio->domain) {
			return -ENOMEM;
		}

		ret = irq_alloc_domain_generic_chips(tb10x_gpio->domain,
				tb10x_gpio->chip.gc.ngpio, 1, tb10x_gpio->chip.gc.label,
				handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE,
				IRQ_GC_INIT_MASK_CACHE);
		if (ret)
			goto err_remove_domain;

		gc = tb10x_gpio->domain->gc->gc[0];
		gc->reg_base                         = tb10x_gpio->base;
		gc->chip_types[0].type               = IRQ_TYPE_EDGE_BOTH;
		gc->chip_types[0].chip.irq_ack       = irq_gc_ack_set_bit;
		gc->chip_types[0].chip.irq_mask      = irq_gc_mask_clr_bit;
		gc->chip_types[0].chip.irq_unmask    = irq_gc_mask_set_bit;
		gc->chip_types[0].chip.irq_set_type  = tb10x_gpio_irq_set_type;
		gc->chip_types[0].regs.ack           = OFFSET_TO_REG_CHANGE;
		gc->chip_types[0].regs.mask          = OFFSET_TO_REG_INT_EN;
	}

	return 0;

err_remove_domain:
	irq_domain_remove(tb10x_gpio->domain);
	return ret;
}

static void tb10x_gpio_remove(struct platform_device *pdev)
{
	struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);

	if (tb10x_gpio->chip.gc.to_irq) {
		irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0],
					BIT(tb10x_gpio->chip.gc.ngpio) - 1, 0, 0);
		kfree(tb10x_gpio->domain->gc);
		irq_domain_remove(tb10x_gpio->domain);
	}
}

static const struct of_device_id tb10x_gpio_dt_ids[] = {
	{ .compatible = "abilis,tb10x-gpio" },
	{ }
};
MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids);

static struct platform_driver tb10x_gpio_driver = {
	.probe		= tb10x_gpio_probe,
	.remove		= tb10x_gpio_remove,
	.driver = {
		.name	= "tb10x-gpio",
		.of_match_table = tb10x_gpio_dt_ids,
	}
};

module_platform_driver(tb10x_gpio_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("tb10x gpio.");
