Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 360063
b: refs/heads/master
c: 19d3814
h: refs/heads/master
i:
  360061: bf9d650
  360059: c7f7c16
  360055: 86bbb4c
  360047: b4c1e0a
  360031: b010cb1
  359999: a50f5d2
  359935: 6ffb6bd
v: v3
  • Loading branch information
John Crispin committed Feb 17, 2013
1 parent c1d0812 commit 1933d5d
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8563991026ee98bb5e477167236972a45dfea0e3
refs/heads/master: 19d3814e7b325f8965fd71f329b3467a97f8d217
176 changes: 176 additions & 0 deletions trunk/arch/mips/ralink/irq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* 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_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 __cpuinit 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_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;

mips_cpu_irq_init();

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(RALINK_CPU_IRQ_INTC, ralink_intc_irq_handler);
irq_set_handler_data(RALINK_CPU_IRQ_INTC, domain);

cp0_perfcount_irq = irq_create_mapping(domain, 9);

return 0;
}

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

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

0 comments on commit 1933d5d

Please sign in to comment.