/*
 * 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_TEST				0x0020
#define EIC_NMIC				0x0024

/* Bitfields in TEST */
#define EIC_TESTEN_OFFSET			31
#define EIC_TESTEN_SIZE				1

/* Bitfields in NMIC */
#define EIC_EN_OFFSET				0
#define EIC_EN_SIZE				1

/* 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 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;
		desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
		desc->status |= flow_type;
	}

	return ret;
}

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;
	struct irq_desc *ext_desc;
	unsigned long status, pending;
	unsigned int i, ext_irq;

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

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

		ext_irq = i + eic->first_irq;
		ext_desc = irq_desc + ext_irq;
		if (ext_desc->status & IRQ_LEVEL)
			handle_level_irq(ext_irq, ext_desc);
		else
			handle_edge_irq(ext_irq, ext_desc);
	}
}

static int __init eic_probe(struct platform_device *pdev)
{
	struct eic *eic;
	struct resource *regs;
	unsigned int i;
	unsigned int nr_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_irqs = fls(pattern);

	/* Trigger on falling edge unless overridden by driver */
	eic_writel(eic, MODE, 0UL);
	eic_writel(eic, EDGE, 0UL);

	eic->chip = &eic_chip;

	for (i = 0; i < nr_irqs; i++) {
		/* NOTE the handler we set here is ignored by the demux */
		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);

	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_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);
