/*
 * 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.
 *
 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
 */

#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>

#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>

#include "common.h"

/* INTC register offsets */
#define INTC_REG_STATUS0	0x00
#define INTC_REG_STATUS1	0x04
#define INTC_REG_TYPE		0x20
#define INTC_REG_RAW_STATUS	0x30
#define INTC_REG_ENABLE		0x34
#define INTC_REG_DISABLE	0x38

#define INTC_INT_GLOBAL		BIT(31)

#define RALINK_CPU_IRQ_INTC	(MIPS_CPU_IRQ_BASE + 2)
#define RALINK_CPU_IRQ_PCI	(MIPS_CPU_IRQ_BASE + 4)
#define RALINK_CPU_IRQ_FE	(MIPS_CPU_IRQ_BASE + 5)
#define RALINK_CPU_IRQ_WIFI	(MIPS_CPU_IRQ_BASE + 6)
#define RALINK_CPU_IRQ_COUNTER	(MIPS_CPU_IRQ_BASE + 7)

/* we have a cascade of 8 irqs */
#define RALINK_INTC_IRQ_BASE	8

/* we have 32 SoC irqs */
#define RALINK_INTC_IRQ_COUNT	32

#define RALINK_INTC_IRQ_PERFC   (RALINK_INTC_IRQ_BASE + 9)

static void __iomem *rt_intc_membase;

static inline void rt_intc_w32(u32 val, unsigned reg)
{
	__raw_writel(val, rt_intc_membase + reg);
}

static inline u32 rt_intc_r32(unsigned reg)
{
	return __raw_readl(rt_intc_membase + reg);
}

static void ralink_intc_irq_unmask(struct irq_data *d)
{
	rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE);
}

static void ralink_intc_irq_mask(struct irq_data *d)
{
	rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE);
}

static struct irq_chip ralink_intc_irq_chip = {
	.name		= "INTC",
	.irq_unmask	= ralink_intc_irq_unmask,
	.irq_mask	= ralink_intc_irq_mask,
	.irq_mask_ack	= ralink_intc_irq_mask,
};

unsigned int get_c0_compare_int(void)
{
	return CP0_LEGACY_COMPARE_IRQ;
}

static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	u32 pending = rt_intc_r32(INTC_REG_STATUS0);

	if (pending) {
		struct irq_domain *domain = irq_get_handler_data(irq);
		generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
	} else {
		spurious_interrupt();
	}
}

asmlinkage void plat_irq_dispatch(void)
{
	unsigned long pending;

	pending = read_c0_status() & read_c0_cause() & ST0_IM;

	if (pending & STATUSF_IP7)
		do_IRQ(RALINK_CPU_IRQ_COUNTER);

	else if (pending & STATUSF_IP5)
		do_IRQ(RALINK_CPU_IRQ_FE);

	else if (pending & STATUSF_IP6)
		do_IRQ(RALINK_CPU_IRQ_WIFI);

	else if (pending & STATUSF_IP4)
		do_IRQ(RALINK_CPU_IRQ_PCI);

	else if (pending & STATUSF_IP2)
		do_IRQ(RALINK_CPU_IRQ_INTC);

	else
		spurious_interrupt();
}

static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
	irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq);

	return 0;
}

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

static int __init intc_of_init(struct device_node *node,
			       struct device_node *parent)
{
	struct resource res;
	struct irq_domain *domain;
	int irq;

	irq = irq_of_parse_and_map(node, 0);
	if (!irq)
		panic("Failed to get INTC IRQ");

	if (of_address_to_resource(node, 0, &res))
		panic("Failed to get intc memory range");

	if (request_mem_region(res.start, resource_size(&res),
				res.name) < 0)
		pr_err("Failed to request intc memory");

	rt_intc_membase = ioremap_nocache(res.start,
					resource_size(&res));
	if (!rt_intc_membase)
		panic("Failed to remap intc memory");

	/* disable all interrupts */
	rt_intc_w32(~0, INTC_REG_DISABLE);

	/* route all INTC interrupts to MIPS HW0 interrupt */
	rt_intc_w32(0, INTC_REG_TYPE);

	domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT,
			RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL);
	if (!domain)
		panic("Failed to add irqdomain");

	rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);

	irq_set_chained_handler(irq, ralink_intc_irq_handler);
	irq_set_handler_data(irq, domain);

	/* tell the kernel which irq is used for performance monitoring */
	cp0_perfcount_irq = irq_create_mapping(domain, 9);

	return 0;
}

static struct of_device_id __initdata of_irq_ids[] = {
	{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
	{ .compatible = "ralink,rt2880-intc", .data = intc_of_init },
	{},
};

void __init arch_init_irq(void)
{
	of_irq_init(of_irq_ids);
}

