/*
 * External interrupt handling for AT32AP CPUs
 *
 * Copyright (C) 2006 Atmel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <linux/slab.h>

#include <asm/io.h>

/* EIC register offsets */
#define EIC_IER					0x0000
#define EIC_IDR					0x0004
#define EIC_IMR					0x0008
#define EIC_ISR					0x000c
#define EIC_ICR					0x0010
#define EIC_MODE				0x0014
#define EIC_EDGE				0x0018
#define EIC_LEVEL				0x001c
#define EIC_NMIC				0x0024

/* Bitfields in NMIC */
#define EIC_NMIC_ENABLE				(1 << 0)

/* Bit manipulation macros */
#define EIC_BIT(name)					\
	(1 << EIC_##name##_OFFSET)
#define EIC_BF(name,value)				\
	(((value) & ((1 << EIC_##name##_SIZE) - 1))	\
	 << EIC_##name##_OFFSET)
#define EIC_BFEXT(name,value)				\
	(((value) >> EIC_##name##_OFFSET)		\
	 & ((1 << EIC_##name##_SIZE) - 1))
#define EIC_BFINS(name,value,old)			\
	(((old) & ~(((1 << EIC_##name##_SIZE) - 1)	\
		    << EIC_##name##_OFFSET))		\
	 | EIC_BF(name,value))

/* Register access macros */
#define eic_readl(port,reg)				\
	__raw_readl((port)->regs + EIC_##reg)
#define eic_writel(port,reg,value)			\
	__raw_writel((value), (port)->regs + EIC_##reg)

struct eic {
	void __iomem *regs;
	struct irq_chip *chip;
	unsigned int first_irq;
};

static struct eic *nmi_eic;
static bool nmi_enabled;

static void eic_ack_irq(struct irq_data *d)
{
	struct eic *eic = irq_data_get_irq_chip_data(d);
	eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
}

static void eic_mask_irq(struct irq_data *d)
{
	struct eic *eic = irq_data_get_irq_chip_data(d);
	eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
}

static void eic_mask_ack_irq(struct irq_data *d)
{
	struct eic *eic = irq_data_get_irq_chip_data(d);
	eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
	eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
}

static void eic_unmask_irq(struct irq_data *d)
{
	struct eic *eic = irq_data_get_irq_chip_data(d);
	eic_writel(eic, IER, 1 << (d->irq - eic->first_irq));
}

static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
	struct eic *eic = irq_data_get_irq_chip_data(d);
	unsigned int irq = d->irq;
	unsigned int i = irq - eic->first_irq;
	u32 mode, edge, level;

	flow_type &= IRQ_TYPE_SENSE_MASK;
	if (flow_type == IRQ_TYPE_NONE)
		flow_type = IRQ_TYPE_LEVEL_LOW;

	mode = eic_readl(eic, MODE);
	edge = eic_readl(eic, EDGE);
	level = eic_readl(eic, LEVEL);

	switch (flow_type) {
	case IRQ_TYPE_LEVEL_LOW:
		mode |= 1 << i;
		level &= ~(1 << i);
		break;
	case IRQ_TYPE_LEVEL_HIGH:
		mode |= 1 << i;
		level |= 1 << i;
		break;
	case IRQ_TYPE_EDGE_RISING:
		mode &= ~(1 << i);
		edge |= 1 << i;
		break;
	case IRQ_TYPE_EDGE_FALLING:
		mode &= ~(1 << i);
		edge &= ~(1 << i);
		break;
	default:
		return -EINVAL;
	}

	eic_writel(eic, MODE, mode);
	eic_writel(eic, EDGE, edge);
	eic_writel(eic, LEVEL, level);

	irqd_set_trigger_type(d, flow_type);
	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
		__irq_set_handler_locked(irq, handle_level_irq);
	else
		__irq_set_handler_locked(irq, handle_edge_irq);

	return IRQ_SET_MASK_OK_NOCOPY;
}

static struct irq_chip eic_chip = {
	.name		= "eic",
	.irq_ack	= eic_ack_irq,
	.irq_mask	= eic_mask_irq,
	.irq_mask_ack	= eic_mask_ack_irq,
	.irq_unmask	= eic_unmask_irq,
	.irq_set_type	= eic_set_irq_type,
};

static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
{
	struct eic *eic = irq_desc_get_handler_data(desc);
	unsigned long status, pending;
	unsigned int i;

	status = eic_readl(eic, ISR);
	pending = status & eic_readl(eic, IMR);

	while (pending) {
		i = fls(pending) - 1;
		pending &= ~(1 << i);

		generic_handle_irq(i + eic->first_irq);
	}
}

int nmi_enable(void)
{
	nmi_enabled = true;

	if (nmi_eic)
		eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE);

	return 0;
}

void nmi_disable(void)
{
	if (nmi_eic)
		eic_writel(nmi_eic, NMIC, 0);

	nmi_enabled = false;
}

static int __init eic_probe(struct platform_device *pdev)
{
	struct eic *eic;
	struct resource *regs;
	unsigned int i;
	unsigned int nr_of_irqs;
	unsigned int int_irq;
	int ret;
	u32 pattern;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	int_irq = platform_get_irq(pdev, 0);
	if (!regs || (int)int_irq <= 0) {
		dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
		return -ENXIO;
	}

	ret = -ENOMEM;
	eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
	if (!eic) {
		dev_dbg(&pdev->dev, "no memory for eic structure\n");
		goto err_kzalloc;
	}

	eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
	eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
	if (!eic->regs) {
		dev_dbg(&pdev->dev, "failed to map regs\n");
		goto err_ioremap;
	}

	/*
	 * Find out how many interrupt lines that are actually
	 * implemented in hardware.
	 */
	eic_writel(eic, IDR, ~0UL);
	eic_writel(eic, MODE, ~0UL);
	pattern = eic_readl(eic, MODE);
	nr_of_irqs = fls(pattern);

	/* Trigger on low level unless overridden by driver */
	eic_writel(eic, EDGE, 0UL);
	eic_writel(eic, LEVEL, 0UL);

	eic->chip = &eic_chip;

	for (i = 0; i < nr_of_irqs; i++) {
		irq_set_chip_and_handler(eic->first_irq + i, &eic_chip,
					 handle_level_irq);
		irq_set_chip_data(eic->first_irq + i, eic);
	}

	irq_set_chained_handler(int_irq, demux_eic_irq);
	irq_set_handler_data(int_irq, eic);

	if (pdev->id == 0) {
		nmi_eic = eic;
		if (nmi_enabled)
			/*
			 * Someone tried to enable NMI before we were
			 * ready. Do it now.
			 */
			nmi_enable();
	}

	dev_info(&pdev->dev,
		 "External Interrupt Controller at 0x%p, IRQ %u\n",
		 eic->regs, int_irq);
	dev_info(&pdev->dev,
		 "Handling %u external IRQs, starting with IRQ %u\n",
		 nr_of_irqs, eic->first_irq);

	return 0;

err_ioremap:
	kfree(eic);
err_kzalloc:
	return ret;
}

static struct platform_driver eic_driver = {
	.driver = {
		.name = "at32_eic",
	},
};

static int __init eic_init(void)
{
	return platform_driver_probe(&eic_driver, eic_probe);
}
arch_initcall(eic_init);
