/*
 * Texas Instruments Keystone IRQ controller IP driver
 *
 * Copyright (C) 2014 Texas Instruments, Inc.
 * Author: Sajesh Kumar Saran <sajesh@ti.com>
 *	   Grygorii Strashko <grygorii.strashko@ti.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>

/* The source ID bits start from 4 to 31 (total 28 bits)*/
#define BIT_OFS			4
#define KEYSTONE_N_IRQ		(32 - BIT_OFS)

struct keystone_irq_device {
	struct device		*dev;
	struct irq_chip		 chip;
	u32			 mask;
	int			 irq;
	struct irq_domain	*irqd;
	struct regmap		*devctrl_regs;
	u32			devctrl_offset;
	raw_spinlock_t		wa_lock;
};

static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
{
	int ret;
	u32 val = 0;

	ret = regmap_read(kirq->devctrl_regs, kirq->devctrl_offset, &val);
	if (ret < 0)
		dev_dbg(kirq->dev, "irq read failed ret(%d)\n", ret);
	return val;
}

static inline void
keystone_irq_writel(struct keystone_irq_device *kirq, u32 value)
{
	int ret;

	ret = regmap_write(kirq->devctrl_regs, kirq->devctrl_offset, value);
	if (ret < 0)
		dev_dbg(kirq->dev, "irq write failed ret(%d)\n", ret);
}

static void keystone_irq_setmask(struct irq_data *d)
{
	struct keystone_irq_device *kirq = irq_data_get_irq_chip_data(d);

	kirq->mask |= BIT(d->hwirq);
	dev_dbg(kirq->dev, "mask %lu [%x]\n", d->hwirq, kirq->mask);
}

static void keystone_irq_unmask(struct irq_data *d)
{
	struct keystone_irq_device *kirq = irq_data_get_irq_chip_data(d);

	kirq->mask &= ~BIT(d->hwirq);
	dev_dbg(kirq->dev, "unmask %lu [%x]\n", d->hwirq, kirq->mask);
}

static void keystone_irq_ack(struct irq_data *d)
{
	/* nothing to do here */
}

static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
{
	struct keystone_irq_device *kirq = keystone_irq;
	unsigned long wa_lock_flags;
	unsigned long pending;
	int src, err;

	dev_dbg(kirq->dev, "start irq %d\n", irq);

	pending = keystone_irq_readl(kirq);
	keystone_irq_writel(kirq, pending);

	dev_dbg(kirq->dev, "pending 0x%lx, mask 0x%x\n", pending, kirq->mask);

	pending = (pending >> BIT_OFS) & ~kirq->mask;

	dev_dbg(kirq->dev, "pending after mask 0x%lx\n", pending);

	for (src = 0; src < KEYSTONE_N_IRQ; src++) {
		if (BIT(src) & pending) {
			raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
			err = generic_handle_domain_irq(kirq->irqd, src);
			raw_spin_unlock_irqrestore(&kirq->wa_lock,
						   wa_lock_flags);

			if (err)
				dev_warn_ratelimited(kirq->dev, "spurious irq detected hwirq %d\n",
						     src);
		}
	}

	dev_dbg(kirq->dev, "end irq %d\n", irq);
	return IRQ_HANDLED;
}

static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
				irq_hw_number_t hw)
{
	struct keystone_irq_device *kirq = h->host_data;

	irq_set_chip_data(virq, kirq);
	irq_set_chip_and_handler(virq, &kirq->chip, handle_level_irq);
	irq_set_probe(virq);
	return 0;
}

static const struct irq_domain_ops keystone_irq_ops = {
	.map	= keystone_irq_map,
	.xlate	= irq_domain_xlate_onecell,
};

static int keystone_irq_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct keystone_irq_device *kirq;
	int ret;

	if (np == NULL)
		return -EINVAL;

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

	kirq->devctrl_regs =
		syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");
	if (IS_ERR(kirq->devctrl_regs))
		return PTR_ERR(kirq->devctrl_regs);

	ret = of_property_read_u32_index(np, "ti,syscon-dev", 1,
					 &kirq->devctrl_offset);
	if (ret) {
		dev_err(dev, "couldn't read the devctrl_offset offset!\n");
		return ret;
	}

	kirq->irq = platform_get_irq(pdev, 0);
	if (kirq->irq < 0)
		return kirq->irq;

	kirq->dev = dev;
	kirq->mask = ~0x0;
	kirq->chip.name		= "keystone-irq";
	kirq->chip.irq_ack	= keystone_irq_ack;
	kirq->chip.irq_mask	= keystone_irq_setmask;
	kirq->chip.irq_unmask	= keystone_irq_unmask;

	kirq->irqd = irq_domain_add_linear(np, KEYSTONE_N_IRQ,
					   &keystone_irq_ops, kirq);
	if (!kirq->irqd) {
		dev_err(dev, "IRQ domain registration failed\n");
		return -ENODEV;
	}

	raw_spin_lock_init(&kirq->wa_lock);

	platform_set_drvdata(pdev, kirq);

	ret = request_irq(kirq->irq, keystone_irq_handler,
			  0, dev_name(dev), kirq);
	if (ret) {
		irq_domain_remove(kirq->irqd);
		return ret;
	}

	/* clear all source bits */
	keystone_irq_writel(kirq, ~0x0);

	dev_info(dev, "irqchip registered, nr_irqs %u\n", KEYSTONE_N_IRQ);

	return 0;
}

static int keystone_irq_remove(struct platform_device *pdev)
{
	struct keystone_irq_device *kirq = platform_get_drvdata(pdev);
	int hwirq;

	free_irq(kirq->irq, kirq);

	for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++)
		irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq));

	irq_domain_remove(kirq->irqd);
	return 0;
}

static const struct of_device_id keystone_irq_dt_ids[] = {
	{ .compatible = "ti,keystone-irq", },
	{},
};
MODULE_DEVICE_TABLE(of, keystone_irq_dt_ids);

static struct platform_driver keystone_irq_device_driver = {
	.probe		= keystone_irq_probe,
	.remove		= keystone_irq_remove,
	.driver		= {
		.name	= "keystone_irq",
		.of_match_table	= of_match_ptr(keystone_irq_dt_ids),
	}
};

module_platform_driver(keystone_irq_device_driver);

MODULE_AUTHOR("Texas Instruments");
MODULE_AUTHOR("Sajesh Kumar Saran");
MODULE_AUTHOR("Grygorii Strashko");
MODULE_DESCRIPTION("Keystone IRQ chip");
MODULE_LICENSE("GPL v2");
