// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 2019, Jiaxun Yang <jiaxun.yang@flygoat.com>
 *  Loongson-1 platform IRQ support
 */

#include <linux/errno.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irqchip.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/irqchip/chained_irq.h>

#define LS_REG_INTC_STATUS	0x00
#define LS_REG_INTC_EN	0x04
#define LS_REG_INTC_SET	0x08
#define LS_REG_INTC_CLR	0x0c
#define LS_REG_INTC_POL	0x10
#define LS_REG_INTC_EDGE	0x14

/**
 * struct ls1x_intc_priv - private ls1x-intc data.
 * @domain:		IRQ domain.
 * @intc_base:	IO Base of intc registers.
 */

struct ls1x_intc_priv {
	struct irq_domain	*domain;
	void __iomem		*intc_base;
};


static void ls1x_chained_handle_irq(struct irq_desc *desc)
{
	struct ls1x_intc_priv *priv = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	u32 pending;

	chained_irq_enter(chip, desc);
	pending = readl(priv->intc_base + LS_REG_INTC_STATUS) &
			readl(priv->intc_base + LS_REG_INTC_EN);

	if (!pending)
		spurious_interrupt();

	while (pending) {
		int bit = __ffs(pending);

		generic_handle_irq(irq_find_mapping(priv->domain, bit));
		pending &= ~BIT(bit);
	}

	chained_irq_exit(chip, desc);
}

static void ls_intc_set_bit(struct irq_chip_generic *gc,
							unsigned int offset,
							u32 mask, bool set)
{
	if (set)
		writel(readl(gc->reg_base + offset) | mask,
		gc->reg_base + offset);
	else
		writel(readl(gc->reg_base + offset) & ~mask,
		gc->reg_base + offset);
}

static int ls_intc_set_type(struct irq_data *data, unsigned int type)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
	u32 mask = data->mask;

	switch (type) {
	case IRQ_TYPE_LEVEL_HIGH:
		ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
		ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
		break;
	case IRQ_TYPE_LEVEL_LOW:
		ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, false);
		ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
		break;
	case IRQ_TYPE_EDGE_RISING:
		ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
		ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, true);
		break;
	case IRQ_TYPE_EDGE_FALLING:
		ls_intc_set_bit(gc, LS_REG_INTC_EDGE, mask, true);
		ls_intc_set_bit(gc, LS_REG_INTC_POL, mask, false);
		break;
	default:
		return -EINVAL;
	}

	irqd_set_trigger_type(data, type);
	return irq_setup_alt_chip(data, type);
}


static int __init ls1x_intc_of_init(struct device_node *node,
				       struct device_node *parent)
{
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;
	struct ls1x_intc_priv *priv;
	int parent_irq, err = 0;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->intc_base = of_iomap(node, 0);
	if (!priv->intc_base) {
		err = -ENODEV;
		goto out_free_priv;
	}

	parent_irq = irq_of_parse_and_map(node, 0);
	if (!parent_irq) {
		pr_err("ls1x-irq: unable to get parent irq\n");
		err =  -ENODEV;
		goto out_iounmap;
	}

	/* Set up an IRQ domain */
	priv->domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops,
					     NULL);
	if (!priv->domain) {
		pr_err("ls1x-irq: cannot add IRQ domain\n");
		err = -ENOMEM;
		goto out_iounmap;
	}

	err = irq_alloc_domain_generic_chips(priv->domain, 32, 2,
		node->full_name, handle_level_irq,
		IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN, 0,
		IRQ_GC_INIT_MASK_CACHE);
	if (err) {
		pr_err("ls1x-irq: unable to register IRQ domain\n");
		goto out_free_domain;
	}

	/* Mask all irqs */
	writel(0x0, priv->intc_base + LS_REG_INTC_EN);

	/* Ack all irqs */
	writel(0xffffffff, priv->intc_base + LS_REG_INTC_CLR);

	/* Set all irqs to high level triggered */
	writel(0xffffffff, priv->intc_base + LS_REG_INTC_POL);

	gc = irq_get_domain_generic_chip(priv->domain, 0);

	gc->reg_base = priv->intc_base;

	ct = gc->chip_types;
	ct[0].type = IRQ_TYPE_LEVEL_MASK;
	ct[0].regs.mask = LS_REG_INTC_EN;
	ct[0].regs.ack = LS_REG_INTC_CLR;
	ct[0].chip.irq_unmask = irq_gc_mask_set_bit;
	ct[0].chip.irq_mask = irq_gc_mask_clr_bit;
	ct[0].chip.irq_ack = irq_gc_ack_set_bit;
	ct[0].chip.irq_set_type = ls_intc_set_type;
	ct[0].handler = handle_level_irq;

	ct[1].type = IRQ_TYPE_EDGE_BOTH;
	ct[1].regs.mask = LS_REG_INTC_EN;
	ct[1].regs.ack = LS_REG_INTC_CLR;
	ct[1].chip.irq_unmask = irq_gc_mask_set_bit;
	ct[1].chip.irq_mask = irq_gc_mask_clr_bit;
	ct[1].chip.irq_ack = irq_gc_ack_set_bit;
	ct[1].chip.irq_set_type = ls_intc_set_type;
	ct[1].handler = handle_edge_irq;

	irq_set_chained_handler_and_data(parent_irq,
		ls1x_chained_handle_irq, priv);

	return 0;

out_free_domain:
	irq_domain_remove(priv->domain);
out_iounmap:
	iounmap(priv->intc_base);
out_free_priv:
	kfree(priv);

	return err;
}

IRQCHIP_DECLARE(ls1x_intc, "loongson,ls1x-intc", ls1x_intc_of_init);
