/*
 * arch/arm/mach-orion5x/irq.c
 *
 * Core IRQ functions for Marvell Orion System On Chip
 *
 * Maintainer: Tzachi Perelstein <tzachi@marvell.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/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/gpio.h>
#include <mach/orion5x.h>
#include <plat/irq.h>
#include "common.h"

/*****************************************************************************
 * Orion GPIO IRQ
 *
 * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
 * value of the line or the opposite value.
 *
 * Level IRQ handlers: DATA_IN is used directly as cause register.
 *                     Interrupt are masked by LEVEL_MASK registers.
 * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
 *                     Interrupt are masked by EDGE_MASK registers.
 * Both-edge handlers: Similar to regular Edge handlers, but also swaps
 *                     the polarity to catch the next line transaction.
 *                     This is a race condition that might not perfectly
 *                     work on some use cases.
 *
 * Every eight GPIO lines are grouped (OR'ed) before going up to main
 * cause register.
 *
 *                    EDGE  cause    mask
 *        data-in   /--------| |-----| |----\
 *     -----| |-----                         ---- to main cause reg
 *           X      \----------------| |----/
 *        polarity    LEVEL          mask
 *
 ****************************************************************************/
static void orion5x_gpio_irq_ack(u32 irq)
{
	int pin = irq_to_gpio(irq);
	if (irq_desc[irq].status & IRQ_LEVEL)
		/*
		 * Mask bit for level interrupt
		 */
		orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
	else
		/*
		 * Clear casue bit for egde interrupt
		 */
		orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
}

static void orion5x_gpio_irq_mask(u32 irq)
{
	int pin = irq_to_gpio(irq);
	if (irq_desc[irq].status & IRQ_LEVEL)
		orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
	else
		orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
}

static void orion5x_gpio_irq_unmask(u32 irq)
{
	int pin = irq_to_gpio(irq);
	if (irq_desc[irq].status & IRQ_LEVEL)
		orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
	else
		orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
}

static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
{
	int pin = irq_to_gpio(irq);
	struct irq_desc *desc;

	if ((readl(GPIO_IO_CONF(pin)) & (1 << pin)) == 0) {
		printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
				"(irq %d, pin %d).\n", irq, pin);
		return -EINVAL;
	}

	desc = irq_desc + irq;

	switch (type) {
	case IRQ_TYPE_LEVEL_HIGH:
		desc->handle_irq = handle_level_irq;
		desc->status |= IRQ_LEVEL;
		orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin));
		break;
	case IRQ_TYPE_LEVEL_LOW:
		desc->handle_irq = handle_level_irq;
		desc->status |= IRQ_LEVEL;
		orion5x_setbits(GPIO_IN_POL(pin), (1 << pin));
		break;
	case IRQ_TYPE_EDGE_RISING:
		desc->handle_irq = handle_edge_irq;
		desc->status &= ~IRQ_LEVEL;
		orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin));
		break;
	case IRQ_TYPE_EDGE_FALLING:
		desc->handle_irq = handle_edge_irq;
		desc->status &= ~IRQ_LEVEL;
		orion5x_setbits(GPIO_IN_POL(pin), (1 << pin));
		break;
	case IRQ_TYPE_EDGE_BOTH:
		desc->handle_irq = handle_edge_irq;
		desc->status &= ~IRQ_LEVEL;
		/*
		 * set initial polarity based on current input level
		 */
		if ((readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin)))
		    & (1 << pin))
			orion5x_setbits(GPIO_IN_POL(pin), (1 << pin)); /* falling */
		else
			orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin)); /* rising */

		break;
	default:
		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
		return -EINVAL;
	}

	desc->status &= ~IRQ_TYPE_SENSE_MASK;
	desc->status |= type & IRQ_TYPE_SENSE_MASK;

	return 0;
}

static struct irq_chip orion5x_gpio_irq_chip = {
	.name		= "Orion-IRQ-GPIO",
	.ack		= orion5x_gpio_irq_ack,
	.mask		= orion5x_gpio_irq_mask,
	.unmask		= orion5x_gpio_irq_unmask,
	.set_type	= orion5x_gpio_set_irq_type,
};

static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	u32 cause, offs, pin;

	BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
	offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
	cause = (readl(GPIO_DATA_IN(offs)) & readl(GPIO_LEVEL_MASK)) |
		(readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK));

	for (pin = offs; pin < offs + 8; pin++) {
		if (cause & (1 << pin)) {
			irq = gpio_to_irq(pin);
			desc = irq_desc + irq;
			if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
				/* Swap polarity (race with GPIO line) */
				u32 polarity = readl(GPIO_IN_POL(pin));
				polarity ^= 1 << pin;
				writel(polarity, GPIO_IN_POL(pin));
			}
			generic_handle_irq(irq);
		}
	}
}

static void __init orion5x_init_gpio_irq(void)
{
	int i;
	struct irq_desc *desc;

	/*
	 * Mask and clear GPIO IRQ interrupts
	 */
	writel(0x0, GPIO_LEVEL_MASK);
	writel(0x0, GPIO_EDGE_MASK);
	writel(0x0, GPIO_EDGE_CAUSE);

	/*
	 * Register chained level handlers for GPIO IRQs by default.
	 * User can use set_type() if he wants to use edge types handlers.
	 */
	for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
		set_irq_chip(i, &orion5x_gpio_irq_chip);
		set_irq_handler(i, handle_level_irq);
		desc = irq_desc + i;
		desc->status |= IRQ_LEVEL;
		set_irq_flags(i, IRQF_VALID);
	}
	set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
	set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
	set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
	set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
}

/*****************************************************************************
 * Orion Main IRQ
 ****************************************************************************/
static void __init orion5x_init_main_irq(void)
{
	orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
}

void __init orion5x_init_irq(void)
{
	orion5x_init_main_irq();
	orion5x_init_gpio_irq();
}
