// SPDX-License-Identifier: GPL-2.0-only
/*
 * PQ2 ADS-style PCI interrupt controller
 *
 * Copyright 2007 Freescale Semiconductor, Inc.
 * Author: Scott Wood <scottwood@freescale.com>
 *
 * Loosely based on mpc82xx ADS support by Vitaly Bordug <vbordug@ru.mvista.com>
 * Copyright (c) 2006 MontaVista Software, Inc.
 */

#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/slab.h>

#include <asm/io.h>
#include <asm/prom.h>
#include <asm/cpm2.h>

#include "pq2.h"

static DEFINE_RAW_SPINLOCK(pci_pic_lock);

struct pq2ads_pci_pic {
	struct device_node *node;
	struct irq_domain *host;

	struct {
		u32 stat;
		u32 mask;
	} __iomem *regs;
};

#define NUM_IRQS 32

static void pq2ads_pci_mask_irq(struct irq_data *d)
{
	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
	int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;

	if (irq != -1) {
		unsigned long flags;
		raw_spin_lock_irqsave(&pci_pic_lock, flags);

		setbits32(&priv->regs->mask, 1 << irq);
		mb();

		raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
	}
}

static void pq2ads_pci_unmask_irq(struct irq_data *d)
{
	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
	int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;

	if (irq != -1) {
		unsigned long flags;

		raw_spin_lock_irqsave(&pci_pic_lock, flags);
		clrbits32(&priv->regs->mask, 1 << irq);
		raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
	}
}

static struct irq_chip pq2ads_pci_ic = {
	.name = "PQ2 ADS PCI",
	.irq_mask = pq2ads_pci_mask_irq,
	.irq_mask_ack = pq2ads_pci_mask_irq,
	.irq_ack = pq2ads_pci_mask_irq,
	.irq_unmask = pq2ads_pci_unmask_irq,
	.irq_enable = pq2ads_pci_unmask_irq,
	.irq_disable = pq2ads_pci_mask_irq
};

static void pq2ads_pci_irq_demux(struct irq_desc *desc)
{
	struct pq2ads_pci_pic *priv = irq_desc_get_handler_data(desc);
	u32 stat, mask, pend;
	int bit;

	for (;;) {
		stat = in_be32(&priv->regs->stat);
		mask = in_be32(&priv->regs->mask);

		pend = stat & ~mask;

		if (!pend)
			break;

		for (bit = 0; pend != 0; ++bit, pend <<= 1) {
			if (pend & 0x80000000) {
				int virq = irq_linear_revmap(priv->host, bit);
				generic_handle_irq(virq);
			}
		}
	}
}

static int pci_pic_host_map(struct irq_domain *h, unsigned int virq,
			    irq_hw_number_t hw)
{
	irq_set_status_flags(virq, IRQ_LEVEL);
	irq_set_chip_data(virq, h->host_data);
	irq_set_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
	return 0;
}

static const struct irq_domain_ops pci_pic_host_ops = {
	.map = pci_pic_host_map,
};

int __init pq2ads_pci_init_irq(void)
{
	struct pq2ads_pci_pic *priv;
	struct irq_domain *host;
	struct device_node *np;
	int ret = -ENODEV;
	int irq;

	np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic");
	if (!np) {
		printk(KERN_ERR "No pci pic node in device tree.\n");
		of_node_put(np);
		goto out;
	}

	irq = irq_of_parse_and_map(np, 0);
	if (!irq) {
		printk(KERN_ERR "No interrupt in pci pic node.\n");
		of_node_put(np);
		goto out;
	}

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		of_node_put(np);
		ret = -ENOMEM;
		goto out_unmap_irq;
	}

	/* PCI interrupt controller registers: status and mask */
	priv->regs = of_iomap(np, 0);
	if (!priv->regs) {
		printk(KERN_ERR "Cannot map PCI PIC registers.\n");
		goto out_free_kmalloc;
	}

	/* mask all PCI interrupts */
	out_be32(&priv->regs->mask, ~0);
	mb();

	host = irq_domain_add_linear(np, NUM_IRQS, &pci_pic_host_ops, priv);
	if (!host) {
		ret = -ENOMEM;
		goto out_unmap_regs;
	}

	priv->host = host;
	irq_set_handler_data(irq, priv);
	irq_set_chained_handler(irq, pq2ads_pci_irq_demux);

	of_node_put(np);
	return 0;

out_unmap_regs:
	iounmap(priv->regs);
out_free_kmalloc:
	kfree(priv);
	of_node_put(np);
out_unmap_irq:
	irq_dispose_mapping(irq);
out:
	return ret;
}
