// SPDX-License-Identifier: GPL-2.0-only
/*
 * RDA Micro GPIO driver
 *
 * Copyright (C) 2012 RDA Micro Inc.
 * Copyright (C) 2019 Manivannan Sadhasivam
 */

#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>

#define RDA_GPIO_OEN_VAL		0x00
#define RDA_GPIO_OEN_SET_OUT		0x04
#define RDA_GPIO_OEN_SET_IN		0x08
#define RDA_GPIO_VAL			0x0c
#define RDA_GPIO_SET			0x10
#define RDA_GPIO_CLR			0x14
#define RDA_GPIO_INT_CTRL_SET		0x18
#define RDA_GPIO_INT_CTRL_CLR		0x1c
#define RDA_GPIO_INT_CLR		0x20
#define RDA_GPIO_INT_STATUS		0x24

#define RDA_GPIO_IRQ_RISE_SHIFT		0
#define RDA_GPIO_IRQ_FALL_SHIFT		8
#define RDA_GPIO_DEBOUCE_SHIFT		16
#define RDA_GPIO_LEVEL_SHIFT		24

#define RDA_GPIO_IRQ_MASK		0xff

/* Each bank consists of 32 GPIOs */
#define RDA_GPIO_BANK_NR	32

struct rda_gpio {
	struct gpio_chip chip;
	void __iomem *base;
	spinlock_t lock;
	int irq;
};

static inline void rda_gpio_update(struct gpio_chip *chip, unsigned int offset,
				   u16 reg, int val)
{
	struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
	void __iomem *base = rda_gpio->base;
	unsigned long flags;
	u32 tmp;

	spin_lock_irqsave(&rda_gpio->lock, flags);
	tmp = readl_relaxed(base + reg);

	if (val)
		tmp |= BIT(offset);
	else
		tmp &= ~BIT(offset);

	writel_relaxed(tmp, base + reg);
	spin_unlock_irqrestore(&rda_gpio->lock, flags);
}

static void rda_gpio_irq_mask(struct irq_data *data)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
	void __iomem *base = rda_gpio->base;
	u32 offset = irqd_to_hwirq(data);
	u32 value;

	value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
	value |= BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;

	writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
	gpiochip_disable_irq(chip, offset);
}

static void rda_gpio_irq_ack(struct irq_data *data)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	u32 offset = irqd_to_hwirq(data);

	rda_gpio_update(chip, offset, RDA_GPIO_INT_CLR, 1);
}

static int rda_gpio_set_irq(struct gpio_chip *chip, u32 offset,
			    unsigned int flow_type)
{
	struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
	void __iomem *base = rda_gpio->base;
	u32 value;

	switch (flow_type) {
	case IRQ_TYPE_EDGE_RISING:
		/* Set rising edge trigger */
		value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);

		/* Switch to edge trigger interrupt */
		value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
		break;

	case IRQ_TYPE_EDGE_FALLING:
		/* Set falling edge trigger */
		value = BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);

		/* Switch to edge trigger interrupt */
		value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
		break;

	case IRQ_TYPE_EDGE_BOTH:
		/* Set both edge trigger */
		value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
		value |= BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);

		/* Switch to edge trigger interrupt */
		value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
		break;

	case IRQ_TYPE_LEVEL_HIGH:
		/* Set high level trigger */
		value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;

		/* Switch to level trigger interrupt */
		value |= BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
		break;

	case IRQ_TYPE_LEVEL_LOW:
		/* Set low level trigger */
		value = BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;

		/* Switch to level trigger interrupt */
		value |= BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
		writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
		break;

	default:
		return -EINVAL;
	}

	return 0;
}

static void rda_gpio_irq_unmask(struct irq_data *data)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	u32 offset = irqd_to_hwirq(data);
	u32 trigger = irqd_get_trigger_type(data);

	gpiochip_enable_irq(chip, offset);
	rda_gpio_set_irq(chip, offset, trigger);
}

static int rda_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	u32 offset = irqd_to_hwirq(data);
	int ret;

	ret = rda_gpio_set_irq(chip, offset, flow_type);
	if (ret)
		return ret;

	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
		irq_set_handler_locked(data, handle_level_irq);
	else if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
		irq_set_handler_locked(data, handle_edge_irq);

	return 0;
}

static void rda_gpio_irq_handler(struct irq_desc *desc)
{
	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
	struct irq_chip *ic = irq_desc_get_chip(desc);
	struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
	unsigned long status;
	u32 n;

	chained_irq_enter(ic, desc);

	status = readl_relaxed(rda_gpio->base + RDA_GPIO_INT_STATUS);
	/* Only lower 8 bits are capable of generating interrupts */
	status &= RDA_GPIO_IRQ_MASK;

	for_each_set_bit(n, &status, RDA_GPIO_BANK_NR)
		generic_handle_domain_irq(chip->irq.domain, n);

	chained_irq_exit(ic, desc);
}

static const struct irq_chip rda_gpio_irq_chip = {
	.name = "rda-gpio",
	.irq_ack = rda_gpio_irq_ack,
	.irq_mask = rda_gpio_irq_mask,
	.irq_unmask = rda_gpio_irq_unmask,
	.irq_set_type = rda_gpio_irq_set_type,
	.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE,
	GPIOCHIP_IRQ_RESOURCE_HELPERS,
};

static int rda_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct gpio_irq_chip *girq;
	struct rda_gpio *rda_gpio;
	u32 ngpios;
	int ret;

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

	ret = device_property_read_u32(dev, "ngpios", &ngpios);
	if (ret < 0)
		return ret;

	/*
	 * Not all ports have interrupt capability. For instance, on
	 * RDA8810PL, GPIOC doesn't support interrupt. So we must handle
	 * those also.
	 */
	rda_gpio->irq = platform_get_irq(pdev, 0);

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

	spin_lock_init(&rda_gpio->lock);

	ret = bgpio_init(&rda_gpio->chip, dev, 4,
			 rda_gpio->base + RDA_GPIO_VAL,
			 rda_gpio->base + RDA_GPIO_SET,
			 rda_gpio->base + RDA_GPIO_CLR,
			 rda_gpio->base + RDA_GPIO_OEN_SET_OUT,
			 rda_gpio->base + RDA_GPIO_OEN_SET_IN,
			 BGPIOF_READ_OUTPUT_REG_SET);
	if (ret) {
		dev_err(dev, "bgpio_init failed\n");
		return ret;
	}

	rda_gpio->chip.label = dev_name(dev);
	rda_gpio->chip.ngpio = ngpios;
	rda_gpio->chip.base = -1;

	if (rda_gpio->irq >= 0) {
		girq = &rda_gpio->chip.irq;
		gpio_irq_chip_set_chip(girq, &rda_gpio_irq_chip);
		girq->handler = handle_bad_irq;
		girq->default_type = IRQ_TYPE_NONE;
		girq->parent_handler = rda_gpio_irq_handler;
		girq->parent_handler_data = rda_gpio;
		girq->num_parents = 1;
		girq->parents = devm_kcalloc(dev, 1,
					     sizeof(*girq->parents),
					     GFP_KERNEL);
		if (!girq->parents)
			return -ENOMEM;
		girq->parents[0] = rda_gpio->irq;
	}

	platform_set_drvdata(pdev, rda_gpio);

	return devm_gpiochip_add_data(dev, &rda_gpio->chip, rda_gpio);
}

static const struct of_device_id rda_gpio_of_match[] = {
	{ .compatible = "rda,8810pl-gpio", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rda_gpio_of_match);

static struct platform_driver rda_gpio_driver = {
	.probe = rda_gpio_probe,
	.driver = {
		.name = "rda-gpio",
		.of_match_table	= rda_gpio_of_match,
	},
};

module_platform_driver_probe(rda_gpio_driver, rda_gpio_probe);

MODULE_DESCRIPTION("RDA Micro GPIO driver");
MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
