/*
 * 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 <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(unsigned int irq)
{
	struct eic *eic = get_irq_chip_data(irq);
	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
}

static void eic_mask_irq(unsigned int irq)
{
	struct eic *eic = get_irq_chip_data(irq);
	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
}

static void eic_mask_ack_irq(unsigned int irq)
{
	struct eic *eic = get_irq_chip_data(irq);
	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
}

static void eic_unmask_irq(unsigned int irq)
{
	struct eic *eic = get_irq_chip_data(irq);
	eic_writel(eic, IER, 1 << (irq - eic->first_irq));
}

static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
{
	struct eic *eic = get_irq_chip_data(irq);
	struct irq_desc *desc;
	unsigned int i = irq - eic->first_irq;
	u32 mode, edge, level;
	int ret = 0;

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

	desc = &irq_desc[irq];

	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:
		ret = -EINVAL;
		break;
	}

	if (ret == 0) {
		eic_writel(eic, MODE, mode);
		eic_writel(eic, EDGE, edge);
		eic_writel(eic, LEVEL, level);

		if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
			flow_type |= IRQ_LEVEL;
			__set_irq_handler_unlocked(irq, handle_level_irq);
		} else
			__set_irq_handler_unlocked(irq, handle_edge_irq);
		desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
		desc->status |= flow_type;
	}

	return ret;
}

static struct irq_chip eic_chip = {
	.name		= "eic",
	.ack		= eic_ack_irq,
	.mask		= eic_mask_irq,
	.mask_ack	= eic_mask_ack_irq,
	.unmask		= eic_unmask_irq,
	.set_type	= eic_set_irq_type,
};

static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
{
	struct eic *eic = desc->handler_data;
	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_irq) {
		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++) {
		set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
					 handle_level_irq);
		set_irq_chip_data(eic->first_irq + i, eic);
	}

	set_irq_chained_handler(int_irq, demux_eic_irq);
	set_irq_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);
