Skip to content

Commit

Permalink
MIPS: i8259: DT support
Browse files Browse the repository at this point in the history
Support probing the i8259 programmable interrupt controller, as found on
the Malta board, and using its interrupts via device tree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: devicetree@vger.kernel.org
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Qais Yousef <qais.yousef@imgtec.com>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: linux-kernel@vger.kernel.org
Patchwork: http://patchwork.linux-mips.org/patch/10114/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Paul Burton authored and Ralf Baechle committed Jun 21, 2015
1 parent e8823d2 commit 5f93ef5
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/mips/include/asm/i8259.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extern int i8259A_irq_pending(unsigned int irq);
extern void make_8259A_irq(unsigned int irq);

extern void init_i8259_irqs(void);
extern int i8259_of_init(struct device_node *node, struct device_node *parent);

/*
* Do the traditional i8259 interrupt polling thing. This is for the few
Expand Down
43 changes: 41 additions & 2 deletions arch/mips/kernel/i8259.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
#include <linux/irq.h>

#include <asm/i8259.h>
#include <asm/io.h>

#include "../../drivers/irqchip/irqchip.h"

/*
* This is the 'legacy' 8259A Programmable Interrupt Controller,
* present in the majority of PC/AT boxes.
Expand Down Expand Up @@ -327,7 +330,7 @@ static struct irq_domain_ops i8259A_ops = {
* driver compatibility reasons interrupts 0 - 15 to be the i8259
* interrupts even if the hardware uses a different interrupt numbering.
*/
void __init init_i8259_irqs(void)
struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
{
struct irq_domain *domain;

Expand All @@ -336,10 +339,46 @@ void __init init_i8259_irqs(void)

init_8259A(0);

domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0,
domain = irq_domain_add_legacy(node, 16, I8259A_IRQ_BASE, 0,
&i8259A_ops, NULL);
if (!domain)
panic("Failed to add i8259 IRQ domain");

setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
return domain;
}

void __init init_i8259_irqs(void)
{
__init_i8259_irqs(NULL);
}

static void i8259_irq_dispatch(unsigned int irq, struct irq_desc *desc)
{
struct irq_domain *domain = irq_get_handler_data(irq);
int hwirq = i8259_irq();

if (hwirq < 0)
return;

irq = irq_linear_revmap(domain, hwirq);
generic_handle_irq(irq);
}

int __init i8259_of_init(struct device_node *node, struct device_node *parent)
{
struct irq_domain *domain;
unsigned int parent_irq;

parent_irq = irq_of_parse_and_map(node, 0);
if (!parent_irq) {
pr_err("Failed to map i8259 parent IRQ\n");
return -ENODEV;
}

domain = __init_i8259_irqs(node);
irq_set_handler_data(parent_irq, domain);
irq_set_chained_handler(parent_irq, i8259_irq_dispatch);
return 0;
}
IRQCHIP_DECLARE(i8259, "intel,i8259", i8259_of_init);

0 comments on commit 5f93ef5

Please sign in to comment.