// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 */

#include <linux/bitfield.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

/* FIC Registers */
#define AL_FIC_CAUSE		0x00
#define AL_FIC_MASK		0x10
#define AL_FIC_CONTROL		0x28

#define CONTROL_TRIGGER_RISING	BIT(3)
#define CONTROL_MASK_MSI_X	BIT(5)

#define NR_FIC_IRQS 32

MODULE_AUTHOR("Talel Shenhar");
MODULE_DESCRIPTION("Amazon's Annapurna Labs Interrupt Controller Driver");
MODULE_LICENSE("GPL v2");

enum al_fic_state {
	AL_FIC_UNCONFIGURED = 0,
	AL_FIC_CONFIGURED_LEVEL,
	AL_FIC_CONFIGURED_RISING_EDGE,
};

struct al_fic {
	void __iomem *base;
	struct irq_domain *domain;
	const char *name;
	unsigned int parent_irq;
	enum al_fic_state state;
};

static void al_fic_set_trigger(struct al_fic *fic,
			       struct irq_chip_generic *gc,
			       enum al_fic_state new_state)
{
	irq_flow_handler_t handler;
	u32 control = readl_relaxed(fic->base + AL_FIC_CONTROL);

	if (new_state == AL_FIC_CONFIGURED_LEVEL) {
		handler = handle_level_irq;
		control &= ~CONTROL_TRIGGER_RISING;
	} else {
		handler = handle_edge_irq;
		control |= CONTROL_TRIGGER_RISING;
	}
	gc->chip_types->handler = handler;
	fic->state = new_state;
	writel_relaxed(control, fic->base + AL_FIC_CONTROL);
}

static int al_fic_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
	struct al_fic *fic = gc->private;
	enum al_fic_state new_state;
	int ret = 0;

	irq_gc_lock(gc);

	if (((flow_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_HIGH) &&
	    ((flow_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_EDGE_RISING)) {
		pr_debug("fic doesn't support flow type %d\n", flow_type);
		ret = -EINVAL;
		goto err;
	}

	new_state = (flow_type & IRQ_TYPE_LEVEL_HIGH) ?
		AL_FIC_CONFIGURED_LEVEL : AL_FIC_CONFIGURED_RISING_EDGE;

	/*
	 * A given FIC instance can be either all level or all edge triggered.
	 * This is generally fixed depending on what pieces of HW it's wired up
	 * to.
	 *
	 * We configure it based on the sensitivity of the first source
	 * being setup, and reject any subsequent attempt at configuring it in a
	 * different way.
	 */
	if (fic->state == AL_FIC_UNCONFIGURED) {
		al_fic_set_trigger(fic, gc, new_state);
	} else if (fic->state != new_state) {
		pr_debug("fic %s state already configured to %d\n",
			 fic->name, fic->state);
		ret = -EINVAL;
		goto err;
	}

err:
	irq_gc_unlock(gc);

	return ret;
}

static void al_fic_irq_handler(struct irq_desc *desc)
{
	struct al_fic *fic = irq_desc_get_handler_data(desc);
	struct irq_domain *domain = fic->domain;
	struct irq_chip *irqchip = irq_desc_get_chip(desc);
	struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
	unsigned long pending;
	unsigned int irq;
	u32 hwirq;

	chained_irq_enter(irqchip, desc);

	pending = readl_relaxed(fic->base + AL_FIC_CAUSE);
	pending &= ~gc->mask_cache;

	for_each_set_bit(hwirq, &pending, NR_FIC_IRQS) {
		irq = irq_find_mapping(domain, hwirq);
		generic_handle_irq(irq);
	}

	chained_irq_exit(irqchip, desc);
}

static int al_fic_register(struct device_node *node,
			   struct al_fic *fic)
{
	struct irq_chip_generic *gc;
	int ret;

	fic->domain = irq_domain_add_linear(node,
					    NR_FIC_IRQS,
					    &irq_generic_chip_ops,
					    fic);
	if (!fic->domain) {
		pr_err("fail to add irq domain\n");
		return -ENOMEM;
	}

	ret = irq_alloc_domain_generic_chips(fic->domain,
					     NR_FIC_IRQS,
					     1, fic->name,
					     handle_level_irq,
					     0, 0, IRQ_GC_INIT_MASK_CACHE);
	if (ret) {
		pr_err("fail to allocate generic chip (%d)\n", ret);
		goto err_domain_remove;
	}

	gc = irq_get_domain_generic_chip(fic->domain, 0);
	gc->reg_base = fic->base;
	gc->chip_types->regs.mask = AL_FIC_MASK;
	gc->chip_types->regs.ack = AL_FIC_CAUSE;
	gc->chip_types->chip.irq_mask = irq_gc_mask_set_bit;
	gc->chip_types->chip.irq_unmask = irq_gc_mask_clr_bit;
	gc->chip_types->chip.irq_ack = irq_gc_ack_clr_bit;
	gc->chip_types->chip.irq_set_type = al_fic_irq_set_type;
	gc->chip_types->chip.flags = IRQCHIP_SKIP_SET_WAKE;
	gc->private = fic;

	irq_set_chained_handler_and_data(fic->parent_irq,
					 al_fic_irq_handler,
					 fic);
	return 0;

err_domain_remove:
	irq_domain_remove(fic->domain);

	return ret;
}

/*
 * al_fic_wire_init() - initialize and configure fic in wire mode
 * @of_node: optional pointer to interrupt controller's device tree node.
 * @base: mmio to fic register
 * @name: name of the fic
 * @parent_irq: interrupt of parent
 *
 * This API will configure the fic hardware to to work in wire mode.
 * In wire mode, fic hardware is generating a wire ("wired") interrupt.
 * Interrupt can be generated based on positive edge or level - configuration is
 * to be determined based on connected hardware to this fic.
 */
static struct al_fic *al_fic_wire_init(struct device_node *node,
				       void __iomem *base,
				       const char *name,
				       unsigned int parent_irq)
{
	struct al_fic *fic;
	int ret;
	u32 control = CONTROL_MASK_MSI_X;

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

	fic->base = base;
	fic->parent_irq = parent_irq;
	fic->name = name;

	/* mask out all interrupts */
	writel_relaxed(0xFFFFFFFF, fic->base + AL_FIC_MASK);

	/* clear any pending interrupt */
	writel_relaxed(0, fic->base + AL_FIC_CAUSE);

	writel_relaxed(control, fic->base + AL_FIC_CONTROL);

	ret = al_fic_register(node, fic);
	if (ret) {
		pr_err("fail to register irqchip\n");
		goto err_free;
	}

	pr_debug("%s initialized successfully in Legacy mode (parent-irq=%u)\n",
		 fic->name, parent_irq);

	return fic;

err_free:
	kfree(fic);
	return ERR_PTR(ret);
}

static int __init al_fic_init_dt(struct device_node *node,
				 struct device_node *parent)
{
	int ret;
	void __iomem *base;
	unsigned int parent_irq;
	struct al_fic *fic;

	if (!parent) {
		pr_err("%s: unsupported - device require a parent\n",
		       node->name);
		return -EINVAL;
	}

	base = of_iomap(node, 0);
	if (!base) {
		pr_err("%s: fail to map memory\n", node->name);
		return -ENOMEM;
	}

	parent_irq = irq_of_parse_and_map(node, 0);
	if (!parent_irq) {
		pr_err("%s: fail to map irq\n", node->name);
		ret = -EINVAL;
		goto err_unmap;
	}

	fic = al_fic_wire_init(node,
			       base,
			       node->name,
			       parent_irq);
	if (IS_ERR(fic)) {
		pr_err("%s: fail to initialize irqchip (%lu)\n",
		       node->name,
		       PTR_ERR(fic));
		ret = PTR_ERR(fic);
		goto err_irq_dispose;
	}

	return 0;

err_irq_dispose:
	irq_dispose_mapping(parent_irq);
err_unmap:
	iounmap(base);

	return ret;
}

IRQCHIP_DECLARE(al_fic, "amazon,al-fic", al_fic_init_dt);
