diff mbox

[v4,01/12] microblaze: irqchip: Move intc driver to irqchip

Message ID 1472748665-47774-2-git-send-email-Zubair.Kakakhel@imgtec.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Zubair Lutfullah Kakakhel Sept. 1, 2016, 4:50 p.m. UTC
The Xilinx AXI Interrupt Controller IP block is used by the MIPS
based xilfpga platform.

Move the interrupt controller code out of arch/microblaze so that
it can be used by everyone

Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>

---
V3 -> V4
No change

V2 -> V3
No change here. Cleanup patches follow after this patch.
Its debatable to cleanup before/after move. Decided to place cleanup
after move to put history in new place.

V1 -> V2

Renamed irq-xilinx to irq-axi-intc
Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
Patch is now without rename flag so as to facilitate review
---
 arch/microblaze/Kconfig         |   1 +
 arch/microblaze/kernel/Makefile |   2 +-
 arch/microblaze/kernel/intc.c   | 196 ----------------------------------------
 drivers/irqchip/Kconfig         |   4 +
 drivers/irqchip/Makefile        |   1 +
 drivers/irqchip/irq-axi-intc.c  | 196 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 203 insertions(+), 197 deletions(-)
 delete mode 100644 arch/microblaze/kernel/intc.c
 create mode 100644 drivers/irqchip/irq-axi-intc.c

Comments

Michal Simek Sept. 2, 2016, 6:25 a.m. UTC | #1
On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
> based xilfpga platform.
> 
> Move the interrupt controller code out of arch/microblaze so that
> it can be used by everyone
> 
> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
> 
> ---
> V3 -> V4
> No change
> 
> V2 -> V3
> No change here. Cleanup patches follow after this patch.
> Its debatable to cleanup before/after move. Decided to place cleanup
> after move to put history in new place.
> 
> V1 -> V2
> 
> Renamed irq-xilinx to irq-axi-intc
> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC


I see that this was suggested by Jason Cooper but using axi name here is
not correct.
There is xps-intc name which is the name used on old OPB hardware
designs. It means this driver can be still used only on system which
uses it.
Also there is another copy of this driver in the tree which was using
old ppc405 and ppc440 xilinx platforms.

arch/powerpc/include/asm/xilinx_intc.h
arch/powerpc/sysdev/xilinx_intc.c

These should be also removed by moving this driver to generic folder.

Thanks,
Michal
Zubair Lutfullah Kakakhel Sept. 2, 2016, 10:06 a.m. UTC | #2
Hi,

On 09/02/2016 07:25 AM, Michal Simek wrote:
> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
>> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
>> based xilfpga platform.
>>
>> Move the interrupt controller code out of arch/microblaze so that
>> it can be used by everyone
>>
>> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
>>
>> ---
>> V3 -> V4
>> No change
>>
>> V2 -> V3
>> No change here. Cleanup patches follow after this patch.
>> Its debatable to cleanup before/after move. Decided to place cleanup
>> after move to put history in new place.
>>
>> V1 -> V2
>>
>> Renamed irq-xilinx to irq-axi-intc
>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
>
>
> I see that this was suggested by Jason Cooper but using axi name here is
> not correct.
> There is xps-intc name which is the name used on old OPB hardware
> designs. It means this driver can be still used only on system which
> uses it.

Wouldn't axi-intc be more suitable moving forwards?
The IP block is now known as axi intc for 5 years as far as I can tell.

Searching "axi intc" online results in the right docs for current and
future platforms.

The binding is still xps-intc as that won't change. So older systems
should still be able to find their way.

> Also there is another copy of this driver in the tree which was using
> old ppc405 and ppc440 xilinx platforms.
>
> arch/powerpc/include/asm/xilinx_intc.h
> arch/powerpc/sysdev/xilinx_intc.c
>
> These should be also removed by moving this driver to generic folder.

I didn't know about that drivers existence.

This patch series already touches microblaze, mips and irqchip.
Both microblaze and mips platforms using this driver are little-endian.

Adding a big-endian powerpc driver + platform to the mix is going to complicate
the series further and make it super hard to synchronize various subsystems,
test stuff, and then move the drivers without breakage.

I'd highly recommend letting this move happen. And then the powerpc driver can
transition over time to this driver.

Regards,
ZubairLK

>
> Thanks,
> Michal
>
Michal Simek Sept. 2, 2016, 10:27 a.m. UTC | #3
On 2.9.2016 12:06, Zubair Lutfullah Kakakhel wrote:
> Hi,
> 
> On 09/02/2016 07:25 AM, Michal Simek wrote:
>> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
>>> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
>>> based xilfpga platform.
>>>
>>> Move the interrupt controller code out of arch/microblaze so that
>>> it can be used by everyone
>>>
>>> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
>>>
>>> ---
>>> V3 -> V4
>>> No change
>>>
>>> V2 -> V3
>>> No change here. Cleanup patches follow after this patch.
>>> Its debatable to cleanup before/after move. Decided to place cleanup
>>> after move to put history in new place.
>>>
>>> V1 -> V2
>>>
>>> Renamed irq-xilinx to irq-axi-intc
>>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
>>
>>
>> I see that this was suggested by Jason Cooper but using axi name here is
>> not correct.
>> There is xps-intc name which is the name used on old OPB hardware
>> designs. It means this driver can be still used only on system which
>> uses it.
> 
> Wouldn't axi-intc be more suitable moving forwards?
> The IP block is now known as axi intc for 5 years as far as I can tell.
> 
> Searching "axi intc" online results in the right docs for current and
> future platforms.

yes but we still should support older platform and it is more then this.
This is soft-IP core and in future when there is new bus then IP will
just change bus interface, etc.

> 
> The binding is still xps-intc as that won't change. So older systems
> should still be able to find their way.

yes that's not a problem. But in general having bus name in name is not
a good way to go.

> 
>> Also there is another copy of this driver in the tree which was using
>> old ppc405 and ppc440 xilinx platforms.
>>
>> arch/powerpc/include/asm/xilinx_intc.h
>> arch/powerpc/sysdev/xilinx_intc.c
>>
>> These should be also removed by moving this driver to generic folder.
> 
> I didn't know about that drivers existence.
> 
> This patch series already touches microblaze, mips and irqchip.
> Both microblaze and mips platforms using this driver are little-endian.

MB is big ending too and as you see there is big endian support in the
driver already.

> 
> Adding a big-endian powerpc driver + platform to the mix is going to
> complicate
> the series further and make it super hard to synchronize various
> subsystems,
> test stuff, and then move the drivers without breakage.
> 
> I'd highly recommend letting this move happen. And then the powerpc
> driver can
> transition over time to this driver.

I have no problem with this but you should be aware about it.
PPC will remain to use big endiand PLB bus. It means it is not axi too.

Thanks,
Michal
Zubair Lutfullah Kakakhel Sept. 2, 2016, 11:46 a.m. UTC | #4
Hi,

Thanks for the valuable feedback.
Comments inline


On 09/02/2016 11:27 AM, Michal Simek wrote:
> On 2.9.2016 12:06, Zubair Lutfullah Kakakhel wrote:
>> Hi,
>>
>> On 09/02/2016 07:25 AM, Michal Simek wrote:
>>> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
>>>> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
>>>> based xilfpga platform.
>>>>
>>>> Move the interrupt controller code out of arch/microblaze so that
>>>> it can be used by everyone
>>>>
>>>> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
>>>>
>>>> ---
>>>> V3 -> V4
>>>> No change
>>>>
>>>> V2 -> V3
>>>> No change here. Cleanup patches follow after this patch.
>>>> Its debatable to cleanup before/after move. Decided to place cleanup
>>>> after move to put history in new place.
>>>>
>>>> V1 -> V2
>>>>
>>>> Renamed irq-xilinx to irq-axi-intc
>>>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
>>>
>>>
>>> I see that this was suggested by Jason Cooper but using axi name here is
>>> not correct.
>>> There is xps-intc name which is the name used on old OPB hardware
>>> designs. It means this driver can be still used only on system which
>>> uses it.
>>
>> Wouldn't axi-intc be more suitable moving forwards?
>> The IP block is now known as axi intc for 5 years as far as I can tell.
>>
>> Searching "axi intc" online results in the right docs for current and
>> future platforms.
>
> yes but we still should support older platform and it is more then this.
> This is soft-IP core and in future when there is new bus then IP will
> just change bus interface, etc.

That makes sense. I'll rename the driver to irq-xps-intc.c
and CONFIG_XILINX_XPS_INTC

Please shout now if anybody has issues with this.

Regards,
ZubairLK
Michal Simek Sept. 2, 2016, 12:06 p.m. UTC | #5
On 2.9.2016 13:46, Zubair Lutfullah Kakakhel wrote:
> Hi,
> 
> Thanks for the valuable feedback.
> Comments inline
> 
> 
> On 09/02/2016 11:27 AM, Michal Simek wrote:
>> On 2.9.2016 12:06, Zubair Lutfullah Kakakhel wrote:
>>> Hi,
>>>
>>> On 09/02/2016 07:25 AM, Michal Simek wrote:
>>>> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
>>>>> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
>>>>> based xilfpga platform.
>>>>>
>>>>> Move the interrupt controller code out of arch/microblaze so that
>>>>> it can be used by everyone
>>>>>
>>>>> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
>>>>>
>>>>> ---
>>>>> V3 -> V4
>>>>> No change
>>>>>
>>>>> V2 -> V3
>>>>> No change here. Cleanup patches follow after this patch.
>>>>> Its debatable to cleanup before/after move. Decided to place cleanup
>>>>> after move to put history in new place.
>>>>>
>>>>> V1 -> V2
>>>>>
>>>>> Renamed irq-xilinx to irq-axi-intc
>>>>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
>>>>
>>>>
>>>> I see that this was suggested by Jason Cooper but using axi name
>>>> here is
>>>> not correct.
>>>> There is xps-intc name which is the name used on old OPB hardware
>>>> designs. It means this driver can be still used only on system which
>>>> uses it.
>>>
>>> Wouldn't axi-intc be more suitable moving forwards?
>>> The IP block is now known as axi intc for 5 years as far as I can tell.
>>>
>>> Searching "axi intc" online results in the right docs for current and
>>> future platforms.
>>
>> yes but we still should support older platform and it is more then this.
>> This is soft-IP core and in future when there is new bus then IP will
>> just change bus interface, etc.
> 
> That makes sense. I'll rename the driver to irq-xps-intc.c
> and CONFIG_XILINX_XPS_INTC
> 
> Please shout now if anybody has issues with this.

XPS was shortcut for design tools. You had CONFIG_XILINX_INTC which is
IMHO the best name you can have.

Thanks,
Michal
Jason Cooper Sept. 2, 2016, 12:48 p.m. UTC | #6
Hi Michal,

On Fri, Sep 02, 2016 at 02:06:40PM +0200, Michal Simek wrote:
> On 2.9.2016 13:46, Zubair Lutfullah Kakakhel wrote:
> > On 09/02/2016 11:27 AM, Michal Simek wrote:
> >> On 2.9.2016 12:06, Zubair Lutfullah Kakakhel wrote:
> >>> On 09/02/2016 07:25 AM, Michal Simek wrote:
> >>>> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
> >>>>> V1 -> V2
> >>>>>
> >>>>> Renamed irq-xilinx to irq-axi-intc
> >>>>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
> >>>>
> >>>>
> >>>> I see that this was suggested by Jason Cooper but using axi name
> >>>> here is
> >>>> not correct.
> >>>> There is xps-intc name which is the name used on old OPB hardware
> >>>> designs. It means this driver can be still used only on system which
> >>>> uses it.
> >>>
> >>> Wouldn't axi-intc be more suitable moving forwards?
> >>> The IP block is now known as axi intc for 5 years as far as I can tell.
> >>>
> >>> Searching "axi intc" online results in the right docs for current and
> >>> future platforms.

Please add links to the relevant docs in the comments of the code.

> >>
> >> yes but we still should support older platform and it is more then this.
> >> This is soft-IP core and in future when there is new bus then IP will
> >> just change bus interface, etc.
> > 
> > That makes sense. I'll rename the driver to irq-xps-intc.c
> > and CONFIG_XILINX_XPS_INTC
> > 
> > Please shout now if anybody has issues with this.
> 
> XPS was shortcut for design tools. You had CONFIG_XILINX_INTC which is
> IMHO the best name you can have.

Michal, thanks for the background info!

Zubair, any problem with CONFIG_XILINX_INTC/irq-xilinx-intc.c ?

thx,

Jason.
Jason Cooper Sept. 2, 2016, 1:28 p.m. UTC | #7
Hi Michal, Zubair,

On Fri, Sep 02, 2016 at 12:27:54PM +0200, Michal Simek wrote:
> On 2.9.2016 12:06, Zubair Lutfullah Kakakhel wrote:
> > On 09/02/2016 07:25 AM, Michal Simek wrote:
...
> >> Also there is another copy of this driver in the tree which was using
> >> old ppc405 and ppc440 xilinx platforms.
> >>
> >> arch/powerpc/include/asm/xilinx_intc.h
> >> arch/powerpc/sysdev/xilinx_intc.c
> >>
> >> These should be also removed by moving this driver to generic folder.
> > 
> > I didn't know about that drivers existence.
> > 
> > This patch series already touches microblaze, mips and irqchip.
> > Both microblaze and mips platforms using this driver are little-endian.
> 
> MB is big ending too and as you see there is big endian support in the
> driver already.
> 
> > 
> > Adding a big-endian powerpc driver + platform to the mix is going to
> > complicate the series further and make it super hard to synchronize
> > various subsystems, test stuff, and then move the drivers without
> > breakage.

The whole point of Linus' push to move drivers out of arch/ is to
reduce code duplication and create more robust drivers.

> > I'd highly recommend letting this move happen. And then the powerpc
> > driver can transition over time to this driver.

I've seen this argument before, and despite everyone's best intentions,
it never happens. :(

We have linux-next, 0-day and other resources to test these sorts of
changes and catch errors before they hit mainline.

Let's take our time and do it right.

thx,

Jason.
Marc Zyngier Sept. 2, 2016, 1:31 p.m. UTC | #8
On 02/09/16 11:06, Zubair Lutfullah Kakakhel wrote:
> Hi,
> 
> On 09/02/2016 07:25 AM, Michal Simek wrote:
>> On 1.9.2016 18:50, Zubair Lutfullah Kakakhel wrote:
>>> The Xilinx AXI Interrupt Controller IP block is used by the MIPS
>>> based xilfpga platform.
>>>
>>> Move the interrupt controller code out of arch/microblaze so that
>>> it can be used by everyone
>>>
>>> Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
>>>
>>> ---
>>> V3 -> V4
>>> No change
>>>
>>> V2 -> V3
>>> No change here. Cleanup patches follow after this patch.
>>> Its debatable to cleanup before/after move. Decided to place cleanup
>>> after move to put history in new place.
>>>
>>> V1 -> V2
>>>
>>> Renamed irq-xilinx to irq-axi-intc
>>> Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC
>>
>>
>> I see that this was suggested by Jason Cooper but using axi name here is
>> not correct.
>> There is xps-intc name which is the name used on old OPB hardware
>> designs. It means this driver can be still used only on system which
>> uses it.
> 
> Wouldn't axi-intc be more suitable moving forwards?
> The IP block is now known as axi intc for 5 years as far as I can tell.
> 
> Searching "axi intc" online results in the right docs for current and
> future platforms.
> 
> The binding is still xps-intc as that won't change. So older systems
> should still be able to find their way.
> 
>> Also there is another copy of this driver in the tree which was using
>> old ppc405 and ppc440 xilinx platforms.
>>
>> arch/powerpc/include/asm/xilinx_intc.h
>> arch/powerpc/sysdev/xilinx_intc.c
>>
>> These should be also removed by moving this driver to generic folder.
> 
> I didn't know about that drivers existence.
> 
> This patch series already touches microblaze, mips and irqchip.
> Both microblaze and mips platforms using this driver are little-endian.
> 
> Adding a big-endian powerpc driver + platform to the mix is going to complicate
> the series further and make it super hard to synchronize various subsystems,
> test stuff, and then move the drivers without breakage.
> 
> I'd highly recommend letting this move happen. And then the powerpc driver can
> transition over time to this driver.

In my experience, doing something later means not doing it. Since you're
motivated enough to make this driver common to two architectures, doing
it for 3 shouldn't be that hard.

This will force you to have separate series, but that's hardly an issue.

Thanks,

	M.
diff mbox

Patch

diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 86f6572..a9ddcaa 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -27,6 +27,7 @@  config MICROBLAZE
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_OPROFILE
 	select IRQ_DOMAIN
+	select XILINX_AXI_INTC
 	select MODULES_USE_ELF_RELA
 	select OF
 	select OF_EARLY_FLATTREE
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index f08baca..e098381 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -15,7 +15,7 @@  endif
 extra-y := head.o vmlinux.lds
 
 obj-y += dma.o exceptions.o \
-	hw_exception_handler.o intc.o irq.o \
+	hw_exception_handler.o irq.o \
 	platform.o process.o prom.o ptrace.o \
 	reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
 
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
deleted file mode 100644
index 90bec7d..0000000
--- a/arch/microblaze/kernel/intc.c
+++ /dev/null
@@ -1,196 +0,0 @@ 
-/*
- * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2012-2013 Xilinx, Inc.
- * Copyright (C) 2007-2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-static void __iomem *intc_baseaddr;
-
-/* No one else should require these constants, so define them locally here. */
-#define ISR 0x00			/* Interrupt Status Register */
-#define IPR 0x04			/* Interrupt Pending Register */
-#define IER 0x08			/* Interrupt Enable Register */
-#define IAR 0x0c			/* Interrupt Acknowledge Register */
-#define SIE 0x10			/* Set Interrupt Enable bits */
-#define CIE 0x14			/* Clear Interrupt Enable bits */
-#define IVR 0x18			/* Interrupt Vector Register */
-#define MER 0x1c			/* Master Enable Register */
-
-#define MER_ME (1<<0)
-#define MER_HIE (1<<1)
-
-static unsigned int (*read_fn)(void __iomem *);
-static void (*write_fn)(u32, void __iomem *);
-
-static void intc_write32(u32 val, void __iomem *addr)
-{
-	iowrite32(val, addr);
-}
-
-static unsigned int intc_read32(void __iomem *addr)
-{
-	return ioread32(addr);
-}
-
-static void intc_write32_be(u32 val, void __iomem *addr)
-{
-	iowrite32be(val, addr);
-}
-
-static unsigned int intc_read32_be(void __iomem *addr)
-{
-	return ioread32be(addr);
-}
-
-static void intc_enable_or_unmask(struct irq_data *d)
-{
-	unsigned long mask = 1 << d->hwirq;
-
-	pr_debug("enable_or_unmask: %ld\n", d->hwirq);
-
-	/* ack level irqs because they can't be acked during
-	 * ack function since the handle_level_irq function
-	 * acks the irq before calling the interrupt handler
-	 */
-	if (irqd_is_level_type(d))
-		write_fn(mask, intc_baseaddr + IAR);
-
-	write_fn(mask, intc_baseaddr + SIE);
-}
-
-static void intc_disable_or_mask(struct irq_data *d)
-{
-	pr_debug("disable: %ld\n", d->hwirq);
-	write_fn(1 << d->hwirq, intc_baseaddr + CIE);
-}
-
-static void intc_ack(struct irq_data *d)
-{
-	pr_debug("ack: %ld\n", d->hwirq);
-	write_fn(1 << d->hwirq, intc_baseaddr + IAR);
-}
-
-static void intc_mask_ack(struct irq_data *d)
-{
-	unsigned long mask = 1 << d->hwirq;
-
-	pr_debug("disable_and_ack: %ld\n", d->hwirq);
-	write_fn(mask, intc_baseaddr + CIE);
-	write_fn(mask, intc_baseaddr + IAR);
-}
-
-static struct irq_chip intc_dev = {
-	.name = "Xilinx INTC",
-	.irq_unmask = intc_enable_or_unmask,
-	.irq_mask = intc_disable_or_mask,
-	.irq_ack = intc_ack,
-	.irq_mask_ack = intc_mask_ack,
-};
-
-static struct irq_domain *root_domain;
-
-unsigned int get_irq(void)
-{
-	unsigned int hwirq, irq = -1;
-
-	hwirq = read_fn(intc_baseaddr + IVR);
-	if (hwirq != -1U)
-		irq = irq_find_mapping(root_domain, hwirq);
-
-	pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
-
-	return irq;
-}
-
-static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
-{
-	u32 intr_mask = (u32)d->host_data;
-
-	if (intr_mask & (1 << hw)) {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
-						handle_edge_irq, "edge");
-		irq_clear_status_flags(irq, IRQ_LEVEL);
-	} else {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
-						handle_level_irq, "level");
-		irq_set_status_flags(irq, IRQ_LEVEL);
-	}
-	return 0;
-}
-
-static const struct irq_domain_ops xintc_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onetwocell,
-	.map = xintc_map,
-};
-
-static int __init xilinx_intc_of_init(struct device_node *intc,
-					     struct device_node *parent)
-{
-	u32 nr_irq, intr_mask;
-	int ret;
-
-	intc_baseaddr = of_iomap(intc, 0);
-	BUG_ON(!intc_baseaddr);
-
-	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
-	if (ret < 0) {
-		pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
-		return ret;
-	}
-
-	ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
-	if (ret < 0) {
-		pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
-		return ret;
-	}
-
-	if (intr_mask >> nr_irq)
-		pr_warn("%s: mismatch in kind-of-intr param\n", __func__);
-
-	pr_info("%s: num_irq=%d, edge=0x%x\n",
-		intc->full_name, nr_irq, intr_mask);
-
-	write_fn = intc_write32;
-	read_fn = intc_read32;
-
-	/*
-	 * Disable all external interrupts until they are
-	 * explicity requested.
-	 */
-	write_fn(0, intc_baseaddr + IER);
-
-	/* Acknowledge any pending interrupts just in case. */
-	write_fn(0xffffffff, intc_baseaddr + IAR);
-
-	/* Turn on the Master Enable. */
-	write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
-	if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
-		write_fn = intc_write32_be;
-		read_fn = intc_read32_be;
-		write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
-	}
-
-	/* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
-	 * lazy and Michal can clean it up to something nicer when he tests
-	 * and commits this patch.  ~~gcl */
-	root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
-							(void *)intr_mask);
-
-	irq_set_default_host(root_domain);
-
-	return 0;
-}
-
-IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7f87289..4429888 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -203,6 +203,10 @@  config XTENSA_MX
 	bool
 	select IRQ_DOMAIN
 
+config XILINX_AXI_INTC
+	bool
+	select IRQ_DOMAIN
+
 config IRQ_CROSSBAR
 	bool
 	help
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6..bf21f55 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -51,6 +51,7 @@  obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
 obj-$(CONFIG_TS4800_IRQ)		+= irq-ts4800.o
 obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
+obj-$(CONFIG_XILINX_AXI_INTC)		+= irq-axi-intc.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)			+= irq-vf610-mscm-ir.o
 obj-$(CONFIG_BCM6345_L1_IRQ)		+= irq-bcm6345-l1.o
diff --git a/drivers/irqchip/irq-axi-intc.c b/drivers/irqchip/irq-axi-intc.c
new file mode 100644
index 0000000..90bec7d
--- /dev/null
+++ b/drivers/irqchip/irq-axi-intc.c
@@ -0,0 +1,196 @@ 
+/*
+ * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012-2013 Xilinx, Inc.
+ * Copyright (C) 2007-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/bug.h>
+
+static void __iomem *intc_baseaddr;
+
+/* No one else should require these constants, so define them locally here. */
+#define ISR 0x00			/* Interrupt Status Register */
+#define IPR 0x04			/* Interrupt Pending Register */
+#define IER 0x08			/* Interrupt Enable Register */
+#define IAR 0x0c			/* Interrupt Acknowledge Register */
+#define SIE 0x10			/* Set Interrupt Enable bits */
+#define CIE 0x14			/* Clear Interrupt Enable bits */
+#define IVR 0x18			/* Interrupt Vector Register */
+#define MER 0x1c			/* Master Enable Register */
+
+#define MER_ME (1<<0)
+#define MER_HIE (1<<1)
+
+static unsigned int (*read_fn)(void __iomem *);
+static void (*write_fn)(u32, void __iomem *);
+
+static void intc_write32(u32 val, void __iomem *addr)
+{
+	iowrite32(val, addr);
+}
+
+static unsigned int intc_read32(void __iomem *addr)
+{
+	return ioread32(addr);
+}
+
+static void intc_write32_be(u32 val, void __iomem *addr)
+{
+	iowrite32be(val, addr);
+}
+
+static unsigned int intc_read32_be(void __iomem *addr)
+{
+	return ioread32be(addr);
+}
+
+static void intc_enable_or_unmask(struct irq_data *d)
+{
+	unsigned long mask = 1 << d->hwirq;
+
+	pr_debug("enable_or_unmask: %ld\n", d->hwirq);
+
+	/* ack level irqs because they can't be acked during
+	 * ack function since the handle_level_irq function
+	 * acks the irq before calling the interrupt handler
+	 */
+	if (irqd_is_level_type(d))
+		write_fn(mask, intc_baseaddr + IAR);
+
+	write_fn(mask, intc_baseaddr + SIE);
+}
+
+static void intc_disable_or_mask(struct irq_data *d)
+{
+	pr_debug("disable: %ld\n", d->hwirq);
+	write_fn(1 << d->hwirq, intc_baseaddr + CIE);
+}
+
+static void intc_ack(struct irq_data *d)
+{
+	pr_debug("ack: %ld\n", d->hwirq);
+	write_fn(1 << d->hwirq, intc_baseaddr + IAR);
+}
+
+static void intc_mask_ack(struct irq_data *d)
+{
+	unsigned long mask = 1 << d->hwirq;
+
+	pr_debug("disable_and_ack: %ld\n", d->hwirq);
+	write_fn(mask, intc_baseaddr + CIE);
+	write_fn(mask, intc_baseaddr + IAR);
+}
+
+static struct irq_chip intc_dev = {
+	.name = "Xilinx INTC",
+	.irq_unmask = intc_enable_or_unmask,
+	.irq_mask = intc_disable_or_mask,
+	.irq_ack = intc_ack,
+	.irq_mask_ack = intc_mask_ack,
+};
+
+static struct irq_domain *root_domain;
+
+unsigned int get_irq(void)
+{
+	unsigned int hwirq, irq = -1;
+
+	hwirq = read_fn(intc_baseaddr + IVR);
+	if (hwirq != -1U)
+		irq = irq_find_mapping(root_domain, hwirq);
+
+	pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
+
+	return irq;
+}
+
+static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+	u32 intr_mask = (u32)d->host_data;
+
+	if (intr_mask & (1 << hw)) {
+		irq_set_chip_and_handler_name(irq, &intc_dev,
+						handle_edge_irq, "edge");
+		irq_clear_status_flags(irq, IRQ_LEVEL);
+	} else {
+		irq_set_chip_and_handler_name(irq, &intc_dev,
+						handle_level_irq, "level");
+		irq_set_status_flags(irq, IRQ_LEVEL);
+	}
+	return 0;
+}
+
+static const struct irq_domain_ops xintc_irq_domain_ops = {
+	.xlate = irq_domain_xlate_onetwocell,
+	.map = xintc_map,
+};
+
+static int __init xilinx_intc_of_init(struct device_node *intc,
+					     struct device_node *parent)
+{
+	u32 nr_irq, intr_mask;
+	int ret;
+
+	intc_baseaddr = of_iomap(intc, 0);
+	BUG_ON(!intc_baseaddr);
+
+	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
+	if (ret < 0) {
+		pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
+	if (ret < 0) {
+		pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
+		return ret;
+	}
+
+	if (intr_mask >> nr_irq)
+		pr_warn("%s: mismatch in kind-of-intr param\n", __func__);
+
+	pr_info("%s: num_irq=%d, edge=0x%x\n",
+		intc->full_name, nr_irq, intr_mask);
+
+	write_fn = intc_write32;
+	read_fn = intc_read32;
+
+	/*
+	 * Disable all external interrupts until they are
+	 * explicity requested.
+	 */
+	write_fn(0, intc_baseaddr + IER);
+
+	/* Acknowledge any pending interrupts just in case. */
+	write_fn(0xffffffff, intc_baseaddr + IAR);
+
+	/* Turn on the Master Enable. */
+	write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
+	if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
+		write_fn = intc_write32_be;
+		read_fn = intc_read32_be;
+		write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
+	}
+
+	/* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
+	 * lazy and Michal can clean it up to something nicer when he tests
+	 * and commits this patch.  ~~gcl */
+	root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
+							(void *)intr_mask);
+
+	irq_set_default_host(root_domain);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);