/*
 * Copyright (C) 2016 Marvell
 *
 * Yehuda Yitschak <yehuday@marvell.com>
 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/interrupt.h>
#include <linux/io.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_irq.h>
#include <linux/platform_device.h>

#define PIC_CAUSE	       0x0
#define PIC_MASK	       0x4

#define PIC_MAX_IRQS		32
#define PIC_MAX_IRQ_MASK	((1UL << PIC_MAX_IRQS) - 1)

struct mvebu_pic {
	void __iomem *base;
	u32 parent_irq;
	struct irq_domain *domain;
	struct irq_chip irq_chip;
};

static void mvebu_pic_reset(struct mvebu_pic *pic)
{
	/* ACK and mask all interrupts */
	writel(0, pic->base + PIC_MASK);
	writel(PIC_MAX_IRQ_MASK, pic->base + PIC_CAUSE);
}

static void mvebu_pic_eoi_irq(struct irq_data *d)
{
	struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);

	writel(1 << d->hwirq, pic->base + PIC_CAUSE);
}

static void mvebu_pic_mask_irq(struct irq_data *d)
{
	struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);
	u32 reg;

	reg =  readl(pic->base + PIC_MASK);
	reg |= (1 << d->hwirq);
	writel(reg, pic->base + PIC_MASK);
}

static void mvebu_pic_unmask_irq(struct irq_data *d)
{
	struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);
	u32 reg;

	reg = readl(pic->base + PIC_MASK);
	reg &= ~(1 << d->hwirq);
	writel(reg, pic->base + PIC_MASK);
}

static int mvebu_pic_irq_map(struct irq_domain *domain, unsigned int virq,
			     irq_hw_number_t hwirq)
{
	struct mvebu_pic *pic = domain->host_data;

	irq_set_percpu_devid(virq);
	irq_set_chip_data(virq, pic);
	irq_set_chip_and_handler(virq, &pic->irq_chip,
				 handle_percpu_devid_irq);
	irq_set_status_flags(virq, IRQ_LEVEL);
	irq_set_probe(virq);

	return 0;
}

static const struct irq_domain_ops mvebu_pic_domain_ops = {
	.map = mvebu_pic_irq_map,
	.xlate = irq_domain_xlate_onecell,
};

static void mvebu_pic_handle_cascade_irq(struct irq_desc *desc)
{
	struct mvebu_pic *pic = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	unsigned long irqmap, irqn;

	irqmap = readl_relaxed(pic->base + PIC_CAUSE);
	chained_irq_enter(chip, desc);

	for_each_set_bit(irqn, &irqmap, BITS_PER_LONG)
		generic_handle_domain_irq(pic->domain, irqn);

	chained_irq_exit(chip, desc);
}

static void mvebu_pic_enable_percpu_irq(void *data)
{
	struct mvebu_pic *pic = data;

	mvebu_pic_reset(pic);
	enable_percpu_irq(pic->parent_irq, IRQ_TYPE_NONE);
}

static void mvebu_pic_disable_percpu_irq(void *data)
{
	struct mvebu_pic *pic = data;

	disable_percpu_irq(pic->parent_irq);
}

static int mvebu_pic_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct mvebu_pic *pic;
	struct irq_chip *irq_chip;

	pic = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pic), GFP_KERNEL);
	if (!pic)
		return -ENOMEM;

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

	irq_chip = &pic->irq_chip;
	irq_chip->name = dev_name(&pdev->dev);
	irq_chip->irq_mask = mvebu_pic_mask_irq;
	irq_chip->irq_unmask = mvebu_pic_unmask_irq;
	irq_chip->irq_eoi = mvebu_pic_eoi_irq;

	pic->parent_irq = irq_of_parse_and_map(node, 0);
	if (pic->parent_irq <= 0) {
		dev_err(&pdev->dev, "Failed to parse parent interrupt\n");
		return -EINVAL;
	}

	pic->domain = irq_domain_add_linear(node, PIC_MAX_IRQS,
					    &mvebu_pic_domain_ops, pic);
	if (!pic->domain) {
		dev_err(&pdev->dev, "Failed to allocate irq domain\n");
		return -ENOMEM;
	}

	irq_set_chained_handler(pic->parent_irq, mvebu_pic_handle_cascade_irq);
	irq_set_handler_data(pic->parent_irq, pic);

	on_each_cpu(mvebu_pic_enable_percpu_irq, pic, 1);

	platform_set_drvdata(pdev, pic);

	return 0;
}

static int mvebu_pic_remove(struct platform_device *pdev)
{
	struct mvebu_pic *pic = platform_get_drvdata(pdev);

	on_each_cpu(mvebu_pic_disable_percpu_irq, pic, 1);
	irq_domain_remove(pic->domain);

	return 0;
}

static const struct of_device_id mvebu_pic_of_match[] = {
	{ .compatible = "marvell,armada-8k-pic", },
	{},
};
MODULE_DEVICE_TABLE(of, mvebu_pic_of_match);

static struct platform_driver mvebu_pic_driver = {
	.probe  = mvebu_pic_probe,
	.remove = mvebu_pic_remove,
	.driver = {
		.name = "mvebu-pic",
		.of_match_table = mvebu_pic_of_match,
	},
};
module_platform_driver(mvebu_pic_driver);

MODULE_AUTHOR("Yehuda Yitschak <yehuday@marvell.com>");
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:mvebu_pic");

