diff mbox

irqchip: add support for Marvell Orion SoCs

Message ID 1367519104-19677-1-git-send-email-sebastian.hesselbarth@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sebastian Hesselbarth May 2, 2013, 6:25 p.m. UTC
This patch adds an irqchip driver for the main interrupt controller found
on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
Corresponding device tree documentation is also added.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Note: This patch triggers a checkpatch warning for
  WARNING: Avoid CamelCase: <handle_IRQ>

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 .../interrupt-controller/marvell,orion-mpic.txt    |   22 ++++
 drivers/irqchip/Kconfig                            |    5 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-orion.c                        |  129 ++++++++++++++++++++
 include/linux/irqchip/orion.h                      |   18 +++
 5 files changed, 175 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
 create mode 100644 drivers/irqchip/irq-orion.c
 create mode 100644 include/linux/irqchip/orion.h

Comments

Sebastian Hesselbarth May 2, 2013, 6:33 p.m. UTC | #1
On 05/02/2013 08:25 PM, Sebastian Hesselbarth wrote:
> This patch adds an irqchip driver for the main interrupt controller found
> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
> Corresponding device tree documentation is also added.
>
> Signed-off-by: Sebastian Hesselbarth<sebastian.hesselbarth@gmail.com>
> ---
> Note: This patch triggers a checkpatch warning for
>    WARNING: Avoid CamelCase:<handle_IRQ>
>
[...]
> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
> new file mode 100644
> index 0000000..04f7bab
> --- /dev/null
> +++ b/include/linux/irqchip/orion.h
> @@ -0,0 +1,18 @@
> +/*
> + * Marvell Orion SoCs IRQ chip driver header.
> + *
> + * Sebastian Hesselbarth<sebastian.hesselbarth@gmail.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.
> + */
> +
> +#ifndef __LINUX_IRQCHIP_ORION_H
> +#define __LINUX_IRQCHIP_ORION_H
> +
> +#include<asm/exception.h>

First review by myself. The above include is a left-over and
will be removed in a v2.

> +
> +extern void orion_init_irq(void);
> +
> +#endif
Russell King - ARM Linux May 2, 2013, 6:45 p.m. UTC | #2
On Thu, May 02, 2013 at 08:33:48PM +0200, Sebastian Hesselbarth wrote:
> On 05/02/2013 08:25 PM, Sebastian Hesselbarth wrote:
>> This patch adds an irqchip driver for the main interrupt controller found
>> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
>> Corresponding device tree documentation is also added.
>>
>> Signed-off-by: Sebastian Hesselbarth<sebastian.hesselbarth@gmail.com>
>> ---
>> Note: This patch triggers a checkpatch warning for
>>    WARNING: Avoid CamelCase:<handle_IRQ>
>>
> [...]
>> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
>> new file mode 100644
>> index 0000000..04f7bab
>> --- /dev/null
>> +++ b/include/linux/irqchip/orion.h
>> @@ -0,0 +1,18 @@
>> +/*
>> + * Marvell Orion SoCs IRQ chip driver header.
>> + *
>> + * Sebastian Hesselbarth<sebastian.hesselbarth@gmail.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.
>> + */
>> +
>> +#ifndef __LINUX_IRQCHIP_ORION_H
>> +#define __LINUX_IRQCHIP_ORION_H
>> +
>> +#include<asm/exception.h>
>
> First review by myself. The above include is a left-over and
> will be removed in a v2.

You still need your first level IRQ handlers marked with __exception_irq_entry
which is defined in the above file.
Jason Gunthorpe May 2, 2013, 6:53 p.m. UTC | #3
On Thu, May 02, 2013 at 08:25:04PM +0200, Sebastian Hesselbarth wrote:
> +
> +static void __iomem *orion_irq_base[ORION_MAX_IRQREG];
> +static unsigned int orion_irq_regs;
> +static struct irq_domain *orion_irq_domain;
> +
> +asmlinkage void __exception_irq_entry orion_handle_irq(struct
> pt_regs *regs)

This can be static?

> +static int __init orion_of_init(struct device_node *np,
> +				struct device_node *parent)
> +{
> +	int n;
> +
> +	for (n = 0; n < ORION_MAX_IRQREG; n++) {
> +		orion_irq_base[n] = of_iomap(np, n);

Is it possible to also reserve the resources for these registers at
this point in the boot sequence?

> +static struct of_device_id orion_irq_dt_ids[] __initconst = {
> +	{ .compatible = "marvell,orion-mpic", .data = orion_of_init },
> +	{ }

Is there a strong reason to change the compatible string? Looks to me
like either the new driver or the old driver will bind depending on
what is in the machine description. No need for a new string?

> +};
> +
> +void __init orion_init_irq(void)
> +{
> +	of_irq_init(orion_irq_dt_ids);
> +}

Shouldn't this use the new IRQCHIP_DECLARE mechanism?

> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h

> +extern void orion_init_irq(void);

.. which lets this go away, use the generic irqchip_init instead of
orion_init_irq.

Regards,
Jason
Sebastian Hesselbarth May 2, 2013, 6:54 p.m. UTC | #4
On 05/02/13 20:45, Russell King - ARM Linux wrote:
> On Thu, May 02, 2013 at 08:33:48PM +0200, Sebastian Hesselbarth wrote:
>> On 05/02/2013 08:25 PM, Sebastian Hesselbarth wrote:
>>> This patch adds an irqchip driver for the main interrupt controller found
>>> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
>>> Corresponding device tree documentation is also added.
>>>
>>> Signed-off-by: Sebastian Hesselbarth<sebastian.hesselbarth@gmail.com>
>>> ---
>>> Note: This patch triggers a checkpatch warning for
>>>     WARNING: Avoid CamelCase:<handle_IRQ>
>>>
>> [...]
>>> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
>>> new file mode 100644
>>> index 0000000..04f7bab
>>> --- /dev/null
>>> +++ b/include/linux/irqchip/orion.h
>>> @@ -0,0 +1,18 @@
>>> +/*
>>> + * Marvell Orion SoCs IRQ chip driver header.
>>> + *
>>> + * Sebastian Hesselbarth<sebastian.hesselbarth@gmail.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.
>>> + */
>>> +
>>> +#ifndef __LINUX_IRQCHIP_ORION_H
>>> +#define __LINUX_IRQCHIP_ORION_H
>>> +
>>> +#include<asm/exception.h>
>>
>> First review by myself. The above include is a left-over and
>> will be removed in a v2.
>
> You still need your first level IRQ handlers marked with __exception_irq_entry
> which is defined in the above file.
>

Russell,

I know and it is marked with __exception_irq_entry. The above is in
include/linux/irqchip/orion.h and only used for .init_irq in machine
descriptor later.

The irq handler is never exposed to the board file itself, but set
within orion_init_irq. This approach has been taked by
irqchip/irq-gic.c and irqchip/irq-vic.c rather than adding
.handle_irq to the machine descriptor.

Sebastian
Russell King - ARM Linux May 2, 2013, 6:56 p.m. UTC | #5
On Thu, May 02, 2013 at 08:54:20PM +0200, Sebastian Hesselbarth wrote:
> On 05/02/13 20:45, Russell King - ARM Linux wrote:
>> On Thu, May 02, 2013 at 08:33:48PM +0200, Sebastian Hesselbarth wrote:
>>> On 05/02/2013 08:25 PM, Sebastian Hesselbarth wrote:
>>>> This patch adds an irqchip driver for the main interrupt controller found
>>>> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
>>>> Corresponding device tree documentation is also added.
>>>>
>>>> Signed-off-by: Sebastian Hesselbarth<sebastian.hesselbarth@gmail.com>
>>>> ---
>>>> Note: This patch triggers a checkpatch warning for
>>>>     WARNING: Avoid CamelCase:<handle_IRQ>
>>>>
>>> [...]
>>>> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
>>>> new file mode 100644
>>>> index 0000000..04f7bab
>>>> --- /dev/null
>>>> +++ b/include/linux/irqchip/orion.h
>>>> @@ -0,0 +1,18 @@
>>>> +/*
>>>> + * Marvell Orion SoCs IRQ chip driver header.
>>>> + *
>>>> + * Sebastian Hesselbarth<sebastian.hesselbarth@gmail.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.
>>>> + */
>>>> +
>>>> +#ifndef __LINUX_IRQCHIP_ORION_H
>>>> +#define __LINUX_IRQCHIP_ORION_H
>>>> +
>>>> +#include<asm/exception.h>
>>>
>>> First review by myself. The above include is a left-over and
>>> will be removed in a v2.
>>
>> You still need your first level IRQ handlers marked with __exception_irq_entry
>> which is defined in the above file.
>>
>
> Russell,
>
> I know and it is marked with __exception_irq_entry. The above is in
> include/linux/irqchip/orion.h and only used for .init_irq in machine
> descriptor later.
>
> The irq handler is never exposed to the board file itself, but set
> within orion_init_irq. This approach has been taked by
> irqchip/irq-gic.c and irqchip/irq-vic.c rather than adding
> .handle_irq to the machine descriptor.

But I don't find an asm/exception.h include in drivers/irqchip/whateveryour.cfileiscalled
Sebastian Hesselbarth May 2, 2013, 7:04 p.m. UTC | #6
On 05/02/13 20:56, Russell King - ARM Linux wrote:
> On Thu, May 02, 2013 at 08:54:20PM +0200, Sebastian Hesselbarth wrote:
>> On 05/02/13 20:45, Russell King - ARM Linux wrote:
>>> On Thu, May 02, 2013 at 08:33:48PM +0200, Sebastian Hesselbarth wrote:
>>>> On 05/02/2013 08:25 PM, Sebastian Hesselbarth wrote:
>>>>> This patch adds an irqchip driver for the main interrupt controller found
>>>>> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
>>>>> Corresponding device tree documentation is also added.
>>>>>
>>>>> Signed-off-by: Sebastian Hesselbarth<sebastian.hesselbarth@gmail.com>
>>>>> ---
>>>>> Note: This patch triggers a checkpatch warning for
>>>>>      WARNING: Avoid CamelCase:<handle_IRQ>
>>>>>
>>>> [...]
>>>>> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
>>>>> new file mode 100644
>>>>> index 0000000..04f7bab
>>>>> --- /dev/null
>>>>> +++ b/include/linux/irqchip/orion.h
>>>>> @@ -0,0 +1,18 @@
>>>>> +/*
>>>>> + * Marvell Orion SoCs IRQ chip driver header.
>>>>> + *
>>>>> + * Sebastian Hesselbarth<sebastian.hesselbarth@gmail.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.
>>>>> + */
>>>>> +
>>>>> +#ifndef __LINUX_IRQCHIP_ORION_H
>>>>> +#define __LINUX_IRQCHIP_ORION_H
>>>>> +
>>>>> +#include<asm/exception.h>
>>>>
>>>> First review by myself. The above include is a left-over and
>>>> will be removed in a v2.
>>>
>>> You still need your first level IRQ handlers marked with __exception_irq_entry
>>> which is defined in the above file.
>>>
>>
>> Russell,
>>
>> I know and it is marked with __exception_irq_entry. The above is in
>> include/linux/irqchip/orion.h and only used for .init_irq in machine
>> descriptor later.
>>
>> The irq handler is never exposed to the board file itself, but set
>> within orion_init_irq. This approach has been taked by
>> irqchip/irq-gic.c and irqchip/irq-vic.c rather than adding
>> .handle_irq to the machine descriptor.
>
> But I don't find an asm/exception.h include in drivers/irqchip/whateveryour.cfileiscalled
>

Well, that might be because you can magically _see_ compiler warnings
while I have to actually run the compiler ;)

With the review from Jason Gunthorpe things will move anyway and I
expect include/irqchip/orion.h to vanish in v2.

Sebastian
Sebastian Hesselbarth May 2, 2013, 7:05 p.m. UTC | #7
On 05/02/13 20:53, Jason Gunthorpe wrote:
> On Thu, May 02, 2013 at 08:25:04PM +0200, Sebastian Hesselbarth wrote:
>> +
>> +static void __iomem *orion_irq_base[ORION_MAX_IRQREG];
>> +static unsigned int orion_irq_regs;
>> +static struct irq_domain *orion_irq_domain;
>> +
>> +asmlinkage void __exception_irq_entry orion_handle_irq(struct
>> pt_regs *regs)
>
> This can be static?

True, corresponds with the left-over #include in linux/irqchip/orion.h.

>> +static int __init orion_of_init(struct device_node *np,
>> +				struct device_node *parent)
>> +{
>> +	int n;
>> +
>> +	for (n = 0; n < ORION_MAX_IRQREG; n++) {
>> +		orion_irq_base[n] = of_iomap(np, n);
>
> Is it possible to also reserve the resources for these registers at
> this point in the boot sequence?

I see what I can do.

>> +static struct of_device_id orion_irq_dt_ids[] __initconst = {
>> +	{ .compatible = "marvell,orion-mpic", .data = orion_of_init },
>> +	{ }
>
> Is there a strong reason to change the compatible string? Looks to me
> like either the new driver or the old driver will bind depending on
> what is in the machine description. No need for a new string?

The reason for a new compatible string is, that we will also need an
secondary irq controller for bridge irqs. That could be called
marvell,orion-spic. Dove is again a little bit different than the
others and this will require timer and especially rtc not to share
bridge irqs here. RTC irq is located in PMU regs on Dove instead of
bridge regs.

But I don't have a strong opinion here and we can also reuse
marvell,orion-intc for the irqchip driver.

>> +};
>> +
>> +void __init orion_init_irq(void)
>> +{
>> +	of_irq_init(orion_irq_dt_ids);
>> +}
>
> Shouldn't this use the new IRQCHIP_DECLARE mechanism?

I didn't follow irqchip discussion lately, but will catch up.

>
>> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
>
>> +extern void orion_init_irq(void);
>
> .. which lets this go away, use the generic irqchip_init instead of
> orion_init_irq.

Same as above.

Thanks for the review,
   Sebastian
Arnd Bergmann May 2, 2013, 7:11 p.m. UTC | #8
On Thursday 02 May 2013, Jason Gunthorpe wrote:
> > +static struct of_device_id orion_irq_dt_ids[] __initconst = {
> > +     { .compatible = "marvell,orion-mpic", .data = orion_of_init },
> > +     { }
> 
> Is there a strong reason to change the compatible string? Looks to me
> like either the new driver or the old driver will bind depending on
> what is in the machine description. No need for a new string?
> 

The compatible string should change if the binding changes in an
incomptible way, and we should try not to change it unless it's
fundamentally flawed.

	Arnd
Jason Cooper May 2, 2013, 7:22 p.m. UTC | #9
On Thu, May 02, 2013 at 08:25:04PM +0200, Sebastian Hesselbarth wrote:
> This patch adds an irqchip driver for the main interrupt controller found
> on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation).
> Corresponding device tree documentation is also added.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> Note: This patch triggers a checkpatch warning for
>   WARNING: Avoid CamelCase: <handle_IRQ>
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Rob Landley <rob@landley.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Gregory Clement <gregory.clement@free-electrons.com>
> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> Cc: Jean-Francois Moine <moinejf@free.fr>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  .../interrupt-controller/marvell,orion-mpic.txt    |   22 ++++
>  drivers/irqchip/Kconfig                            |    5 +
>  drivers/irqchip/Makefile                           |    1 +
>  drivers/irqchip/irq-orion.c                        |  129 ++++++++++++++++++++
>  include/linux/irqchip/orion.h                      |   18 +++
>  5 files changed, 175 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
>  create mode 100644 drivers/irqchip/irq-orion.c
>  create mode 100644 include/linux/irqchip/orion.h

Sebastian,

Could you please include this patch in the next version of the series
depending on it.  I'd like to get an Ack from the irqchip folks for us
to take this patch through mvebu/arm-soc.

This will prevent an external tree dependency, and any resulting merge
conflict will be a trivial add in Kconfig or Makefile.

thx,

Jason.

> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
> new file mode 100644
> index 0000000..3b303ec
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
> @@ -0,0 +1,22 @@
> +Marvell Orion SoC main interrupt controller
> +
> +Required properties:
> +- compatible: shall be "marvell,orion-mpic"
> +- reg: base address(es) of interrupt registers starting with CAUSE register
> +- interrupt-controller: identifies the node as an interrupt controller
> +- #interrupt-cells: number of cells to encode an interrupt source, shall be 1.
> +
> +The interrupt sources map to the corresponding bits in the interrupt
> +registers, i.e.
> +- 0 maps to bit 0 of first base address,
> +- 1 maps to bit 1 of first base address,
> +- 32 maps to bit 0 of second base address, and so on.
> +
> +Example:
> +	intc: interrupt-controller {
> +		compatible = "marvell,orion-mpic";
> +		interrupt-controller;
> +		#interrupt-cells = <1>;
> +                /* Dove has 64 primary interrupts */
> +		reg = <0x20200 0x10>, <0x20210 0x10>;
> +	};
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index a350969..8da3559 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -2,6 +2,11 @@ config IRQCHIP
>  	def_bool y
>  	depends on OF_IRQ
>  
> +config IRQCHIP_ORION
> +	bool
> +	select IRQ_DOMAIN
> +	select MULTI_IRQ_HANDLER
> +
>  config ARM_GIC
>  	bool
>  	select IRQ_DOMAIN
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 98e3b87..8adbd43 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP)			+= irqchip.o
>  
>  obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
>  obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
> +obj-$(CONFIG_IRQCHIP_ORION)		+= irq-orion.o
>  obj-$(CONFIG_METAG)			+= irq-metag-ext.o
>  obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
>  obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
> diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c
> new file mode 100644
> index 0000000..ea02e11
> --- /dev/null
> +++ b/drivers/irqchip/irq-orion.c
> @@ -0,0 +1,129 @@
> +/*
> + * Marvell Orion SoCs IRQ chip driver.
> + *
> + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/io.h>
> +#include <linux/irq.h>
> +#include <linux/irqchip/orion.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/mach/irq.h>
> +
> +/* max number of handled irq register blocks */
> +#define ORION_MAX_IRQREG		2
> +
> +#define ORION_IRQ_CAUSE			0x00
> +#define ORION_IRQ_MASK			0x04
> +#define ORION_IRQ_FIQ_MASK		0x08
> +#define ORION_IRQ_ENDP_MASK		0x0c
> +
> +static void __iomem *orion_irq_base[ORION_MAX_IRQREG];
> +static unsigned int orion_irq_regs;
> +static struct irq_domain *orion_irq_domain;
> +
> +asmlinkage void __exception_irq_entry orion_handle_irq(struct pt_regs *regs)
> +{
> +	int n;
> +	for (n = 0; n < orion_irq_regs; n++) {
> +		u32 hwirq_base = n * 32;
> +		u32 stat = readl_relaxed(orion_irq_base[n] + ORION_IRQ_CAUSE) &
> +			   readl_relaxed(orion_irq_base[n] + ORION_IRQ_MASK);
> +		while (stat) {
> +			u32 hwirq = ffs(stat) - 1;
> +			u32 irq = irq_find_mapping(orion_irq_domain,
> +						hwirq_base + hwirq);
> +			handle_IRQ(irq, regs);
> +			stat &= ~(1 << hwirq);
> +		}
> +	}
> +}
> +
> +static void orion_irq_mask(struct irq_data *irqd)
> +{
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +	unsigned int irq_off = irq % 32;
> +	int reg = irq / 32;
> +	u32 val;
> +
> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
> +	writel(val & ~(1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
> +}
> +
> +static void orion_irq_unmask(struct irq_data *irqd)
> +{
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +	unsigned int irq_off = irq % 32;
> +	int reg = irq / 32;
> +	u32 val;
> +
> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
> +	writel(val | (1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
> +}
> +
> +static struct irq_chip orion_irq_chip = {
> +	.name		= "orion_irq",
> +	.irq_mask	= orion_irq_mask,
> +	.irq_unmask	= orion_irq_unmask,
> +};
> +
> +static int orion_irq_map(struct irq_domain *d, unsigned int virq,
> +			 irq_hw_number_t hw)
> +{
> +	irq_set_chip_and_handler(virq, &orion_irq_chip,
> +				 handle_level_irq);
> +	set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
> +
> +	return 0;
> +}
> +
> +static struct irq_domain_ops orion_irq_ops = {
> +	.map = orion_irq_map,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int __init orion_of_init(struct device_node *np,
> +				struct device_node *parent)
> +{
> +	int n;
> +
> +	for (n = 0; n < ORION_MAX_IRQREG; n++) {
> +		orion_irq_base[n] = of_iomap(np, n);
> +
> +		if (!orion_irq_base[n])
> +			continue;
> +
> +		/* mask all interrupts */
> +		writel(0, orion_irq_base[n] + ORION_IRQ_MASK);
> +		orion_irq_regs++;
> +	}
> +
> +	/* at least one irq reg must be set */
> +	if (!orion_irq_regs)
> +		panic("%s: unable to map IRQC registers\n", np->full_name);
> +
> +	orion_irq_domain = irq_domain_add_linear(np, orion_irq_regs * 32,
> +						 &orion_irq_ops, NULL);
> +	if (!orion_irq_domain)
> +		panic("%s: unable to create IRQ domain\n", np->full_name);
> +
> +	set_handle_irq(orion_handle_irq);
> +
> +	return 0;
> +}
> +
> +static struct of_device_id orion_irq_dt_ids[] __initconst = {
> +	{ .compatible = "marvell,orion-mpic", .data = orion_of_init },
> +	{ }
> +};
> +
> +void __init orion_init_irq(void)
> +{
> +	of_irq_init(orion_irq_dt_ids);
> +}
> diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
> new file mode 100644
> index 0000000..04f7bab
> --- /dev/null
> +++ b/include/linux/irqchip/orion.h
> @@ -0,0 +1,18 @@
> +/*
> + * Marvell Orion SoCs IRQ chip driver header.
> + *
> + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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.
> + */
> +
> +#ifndef __LINUX_IRQCHIP_ORION_H
> +#define __LINUX_IRQCHIP_ORION_H
> +
> +#include <asm/exception.h>
> +
> +extern void orion_init_irq(void);
> +
> +#endif
> -- 
> 1.7.2.5
>
Sebastian Hesselbarth May 2, 2013, 7:34 p.m. UTC | #10
On 05/02/2013 09:11 PM, Arnd Bergmann wrote:
> On Thursday 02 May 2013, Jason Gunthorpe wrote:
>>> +static struct of_device_id orion_irq_dt_ids[] __initconst = {
>>> +     { .compatible = "marvell,orion-mpic", .data = orion_of_init },
>>> +     { }
>>
>> Is there a strong reason to change the compatible string? Looks to me
>> like either the new driver or the old driver will bind depending on
>> what is in the machine description. No need for a new string?
>>
>
> The compatible string should change if the binding changes in an
> incomptible way, and we should try not to change it unless it's
> fundamentally flawed.

Well, there is no _fundamental_ change in the binding syntax as it
is only reg, interrupts, and clocks. But there is a semantic change
in reg properties, as current orion irq controller wants the mask
registers (0x04,0x08) only while this also needs cause register
(0x00).

Nothing that couldn't be handled while moving Orion arch to irqchip
but if there are no further objections, I'd like to stick with the new
compatible string - also having orion-spic in mind.

Sebastian
Jason Gunthorpe May 2, 2013, 7:35 p.m. UTC | #11
On Thu, May 02, 2013 at 09:05:38PM +0200, Sebastian Hesselbarth wrote:

> >>+static struct of_device_id orion_irq_dt_ids[] __initconst = {
> >>+	{ .compatible = "marvell,orion-mpic", .data = orion_of_init },
> >>+	{ }
> >
> >Is there a strong reason to change the compatible string? Looks to me
> >like either the new driver or the old driver will bind depending on
> >what is in the machine description. No need for a new string?
> 
> The reason for a new compatible string is, that we will also need an
> secondary irq controller for bridge irqs. That could be called
> marvell,orion-spic. Dove is again a little bit different than the
> others and this will require timer and especially rtc not to share
> bridge irqs here. RTC irq is located in PMU regs on Dove instead of
> bridge regs.

As Arnd mentioned, I would keep the old name then..

The bridge controller can be called marvell,orion-intc-bridge, and if
Dove needs a pmu controller, marvell,dove-intc-pmu ?

> >.. which lets this go away, use the generic irqchip_init instead of
> >orion_init_irq.
> 
> Same as above.

I have kirkwood HW but I haven't had time to make newer kernels run on
it, otherwise I'd test it too :(

Jason
Jason Gunthorpe May 2, 2013, 7:37 p.m. UTC | #12
On Thu, May 02, 2013 at 09:34:30PM +0200, Sebastian Hesselbarth wrote:

> >The compatible string should change if the binding changes in an
> >incomptible way, and we should try not to change it unless it's
> >fundamentally flawed.
> 
> Well, there is no _fundamental_ change in the binding syntax as it
> is only reg, interrupts, and clocks. But there is a semantic change
> in reg properties, as current orion irq controller wants the mask
> registers (0x04,0x08) only while this also needs cause register
> (0x00).

Oh, I didn't notice that, good point - the original binding was flawed
in that regard :|

Jason
Sebastian Hesselbarth May 2, 2013, 7:39 p.m. UTC | #13
On 05/02/2013 09:34 PM, Sebastian Hesselbarth wrote:
> On 05/02/2013 09:11 PM, Arnd Bergmann wrote:
>> On Thursday 02 May 2013, Jason Gunthorpe wrote:
>>>> +static struct of_device_id orion_irq_dt_ids[] __initconst = {
>>>> + { .compatible = "marvell,orion-mpic", .data = orion_of_init },
>>>> + { }
>>>
>>> Is there a strong reason to change the compatible string? Looks to me
>>> like either the new driver or the old driver will bind depending on
>>> what is in the machine description. No need for a new string?
>>>
>>
>> The compatible string should change if the binding changes in an
>> incomptible way, and we should try not to change it unless it's
>> fundamentally flawed.
>
> Well, there is no _fundamental_ change in the binding syntax as it
> is only reg, interrupts, and clocks. But there is a semantic change
> in reg properties, as current orion irq controller wants the mask
> registers (0x04,0x08) only while this also needs cause register
> (0x00).
>
> Nothing that couldn't be handled while moving Orion arch to irqchip
> but if there are no further objections, I'd like to stick with the new
> compatible string - also having orion-spic in mind.

Taking Jason Gunthorpe's last reply, I will stick to the _old_
compatible string and name the bridge irq handler as Jason suggested.

I will send a v2 soon.

Sebastian
Sebastian Hesselbarth May 2, 2013, 7:48 p.m. UTC | #14
On 05/02/2013 09:35 PM, Jason Gunthorpe wrote:
> I have kirkwood HW but I haven't had time to make newer kernels run on
> it, otherwise I'd test it too :(

I also have kirkwood HW but that will cut me from email as I use it as
relay server ;) Maybe I can turn it into a test bed for a while.

There is also Orion5x and Discovery Innovation (mv78xx0) to be tested.

@Jason Cooper: I will merge both irqchip and dove patches into one
patch set. I wasn't earlier because I didn't want the above SoCs to
slow down patch integration. And I will split dtsi changes into
separate patches as requested.

Sebastian
Andrew Lunn May 2, 2013, 8:02 p.m. UTC | #15
On Thu, May 02, 2013 at 09:48:50PM +0200, Sebastian Hesselbarth wrote:
> On 05/02/2013 09:35 PM, Jason Gunthorpe wrote:
> >I have kirkwood HW but I haven't had time to make newer kernels run on
> >it, otherwise I'd test it too :(
> 
> I also have kirkwood HW but that will cut me from email as I use it as
> relay server ;) Maybe I can turn it into a test bed for a while.
> 
> There is also Orion5x and Discovery Innovation (mv78xx0) to be tested.

I can test kirkwood and Orion5x.

  Andrew
Gregory CLEMENT May 2, 2013, 8:08 p.m. UTC | #16
On 05/02/2013 10:02 PM, Andrew Lunn wrote:
> On Thu, May 02, 2013 at 09:48:50PM +0200, Sebastian Hesselbarth wrote:
>> On 05/02/2013 09:35 PM, Jason Gunthorpe wrote:
>>> I have kirkwood HW but I haven't had time to make newer kernels run on
>>> it, otherwise I'd test it too :(
>>
>> I also have kirkwood HW but that will cut me from email as I use it as
>> relay server ;) Maybe I can turn it into a test bed for a while.
>>
>> There is also Orion5x and Discovery Innovation (mv78xx0) to be tested.
> 
> I can test kirkwood and Orion5x.

And I can test mv78xx0

Gregory
Thomas Gleixner May 2, 2013, 9:34 p.m. UTC | #17
Sebastian,

please do not take the rant below personally. You just happen to
trigger it.

On Thu, 2 May 2013, Sebastian Hesselbarth wrote:

> +static void orion_irq_mask(struct irq_data *irqd)
> +{
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +	unsigned int irq_off = irq % 32;
> +	int reg = irq / 32;
> +	u32 val;
> +
> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
> +	writel(val & ~(1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
> +}
> +
> +static void orion_irq_unmask(struct irq_data *irqd)
> +{
> +	unsigned int irq = irqd_to_hwirq(irqd);
> +	unsigned int irq_off = irq % 32;
> +	int reg = irq / 32;
> +	u32 val;
> +
> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
> +	writel(val | (1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
> +}

I'm really tired of looking at the next incarnation of an OF/DT irq
chip driver, which reimplements stuff which I have consolidated in the
generic irq chip implementation with a lot of effort.

Just look at the various implementations in drivers/irqchip/ and find
out how similar they are. Moving code to drivers/irqchip/ does not
make an excuse for reestablishing the mess which was addressed by the
generic irq chip implementation.

Can you - and that means all of you ARM folks - please get your gear
together and add the missing features to the generic irq chip
implementation? I'm not going to accept more of that OF/DT frenzy.

Thanks,

	tglx
Sebastian Hesselbarth May 2, 2013, 9:56 p.m. UTC | #18
On 05/02/2013 11:34 PM, Thomas Gleixner wrote:
> please do not take the rant below personally. You just happen to
> trigger it.

Thomas,

it is okay for me - but thanks for the notice! I will comment below.

> On Thu, 2 May 2013, Sebastian Hesselbarth wrote:
>> +static void orion_irq_mask(struct irq_data *irqd)
>> +{
>> +	unsigned int irq = irqd_to_hwirq(irqd);
>> +	unsigned int irq_off = irq % 32;
>> +	int reg = irq / 32;
>> +	u32 val;
>> +
>> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
>> +	writel(val&  ~(1<<  irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
>> +}
>> +
>> +static void orion_irq_unmask(struct irq_data *irqd)
>> +{
>> +	unsigned int irq = irqd_to_hwirq(irqd);
>> +	unsigned int irq_off = irq % 32;
>> +	int reg = irq / 32;
>> +	u32 val;
>> +
>> +	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
>> +	writel(val | (1<<  irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
>> +}
>
> I'm really tired of looking at the next incarnation of an OF/DT irq
> chip driver, which reimplements stuff which I have consolidated in the
> generic irq chip implementation with a lot of effort.

Actually, non-irqchip implementation of orion intc was based on generic
irq chip already. I took a look at drivers/irqchip and realized that
at least sunxi (ARM again) was reimplementing mask/unmask the way
above. So I took the short path and copied that.

> Just look at the various implementations in drivers/irqchip/ and find
> out how similar they are. Moving code to drivers/irqchip/ does not
> make an excuse for reestablishing the mess which was addressed by the
> generic irq chip implementation.
>
> Can you - and that means all of you ARM folks - please get your gear
> together and add the missing features to the generic irq chip
> implementation? I'm not going to accept more of that OF/DT frenzy.

So you are suggesting to have a "linux,generic-intc" or you want me
to have "marvell,orion-intc" make use of generic irq chip again?

The second is easy, the first will take me a while to think about
proper DT properties how to encode mask/unmask/ack/.. availability
and offsets.

Regards,
   Sebastian
Arnd Bergmann May 2, 2013, 10:09 p.m. UTC | #19
On Thursday 02 May 2013, Sebastian Hesselbarth wrote:
> > Just look at the various implementations in drivers/irqchip/ and find
> > out how similar they are. Moving code to drivers/irqchip/ does not
> > make an excuse for reestablishing the mess which was addressed by the
> > generic irq chip implementation.
> >
> > Can you - and that means all of you ARM folks - please get your gear
> > together and add the missing features to the generic irq chip
> > implementation? I'm not going to accept more of that OF/DT frenzy.
> 
> So you are suggesting to have a "linux,generic-intc" or you want me
> to have "marvell,orion-intc" make use of generic irq chip again?
> 
> The second is easy, the first will take me a while to think about
> proper DT properties how to encode mask/unmask/ack/.. availability
> and offsets.

I think it should not be "linux,..." since the description can
well be OS independent. I don't have a good idea for a generic
name, but it's not very important.

The main missing piece in the generic irqchip code at the moment
is support for the linear irqdomain. Once we have that, a lot of
code can be simplified significantly.

	Arnd
Sebastian Hesselbarth May 2, 2013, 10:37 p.m. UTC | #20
On 05/03/2013 12:09 AM, Arnd Bergmann wrote:
> On Thursday 02 May 2013, Sebastian Hesselbarth wrote:
>>> Just look at the various implementations in drivers/irqchip/ and find
>>> out how similar they are. Moving code to drivers/irqchip/ does not
>>> make an excuse for reestablishing the mess which was addressed by the
>>> generic irq chip implementation.
>>>
>>> Can you - and that means all of you ARM folks - please get your gear
>>> together and add the missing features to the generic irq chip
>>> implementation? I'm not going to accept more of that OF/DT frenzy.
>>
>> So you are suggesting to have a "linux,generic-intc" or you want me
>> to have "marvell,orion-intc" make use of generic irq chip again?
>>
>> The second is easy, the first will take me a while to think about
>> proper DT properties how to encode mask/unmask/ack/.. availability
>> and offsets.
>
> I think it should not be "linux,..." since the description can
> well be OS independent. I don't have a good idea for a generic
> name, but it's not very important.
>
> The main missing piece in the generic irqchip code at the moment
> is support for the linear irqdomain. Once we have that, a lot of
> code can be simplified significantly.

Arnd, Thomas,

I still don't get it completely. Are you requesting a full blown
DT-enabled generic irq chip driver that can be setup by DT properties?

Or is it just to have current generic irq chip play with linear
irqdomain?

If it is just linear irqdomain, then I can have a look at it
now. I would first send v2 to allow the others to integrate
Kirkwood, Orion5x, and Discovery Innovation. Then v3 will
touch generic irq and merge that with orion irqchip.

(@Jason C: Are you sure that I should merge dove and orion
irqchip patches? I doubt that anything touching generic irq
will not go through irq tree.)

Sebastian
Sebastian Hesselbarth May 2, 2013, 11:48 p.m. UTC | #21
This patch set adds an irqchip driver for the main interrupt controller
found on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, Discovery Innovation)
and the corresponding device tree documentation.

It also moves Dove as the first Orion SoC to this irqchip driver. 
As legacy non-DT drivers don't know about virtual irqs provided by irqchip
drivers, init code for timer and mv643xx_eth is added until true DT enabled
drivers are available. Finally, DT enabled boards for Dove are moved to the
orion irqchip driver.

*Note:*
This patch set is _not_ feature complete. There has been a request for
irqdomain support for generic irq and perhaps even a DT enabled generic
irq chip driver.

The patch set still can be used to port other Orion SoCs as I did with Dove.
It also merges irqchip driver patches with Dove patches to use this driver.

Sebastian Hesselbarth (5):
  irqchip: add support for Marvell Orion SoCs
  ARM: dove: add DT parsing for legacy mv643xx_eth
  ARM: dove: add DT parsing for legacy timer
  ARM: dove: move DT boards to orion irqchip driver
  ARM: dove: add DT nodes for irqchip conversion

 .../interrupt-controller/marvell,orion-intc.txt    |   22 ++++
 arch/arm/boot/dts/dove.dtsi                        |   16 ++-
 arch/arm/mach-dove/Kconfig                         |    1 +
 arch/arm/mach-dove/Makefile                        |    4 +-
 arch/arm/mach-dove/board-dt.c                      |   77 ++++++++++--
 drivers/irqchip/Kconfig                            |    5 +
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-orion.c                        |  133 ++++++++++++++++++++
 8 files changed, 247 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt
 create mode 100644 drivers/irqchip/irq-orion.c
---
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Cc: Jean-Francois Moine <moinejf@free.fr>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Jason Cooper May 4, 2013, 5:58 p.m. UTC | #22
On Thu, May 02, 2013 at 09:48:50PM +0200, Sebastian Hesselbarth wrote:
> On 05/02/2013 09:35 PM, Jason Gunthorpe wrote:
> >I have kirkwood HW but I haven't had time to make newer kernels run on
> >it, otherwise I'd test it too :(
> 
> I also have kirkwood HW but that will cut me from email as I use it as
> relay server ;) Maybe I can turn it into a test bed for a while.
> 
> There is also Orion5x and Discovery Innovation (mv78xx0) to be tested.
> 
> @Jason Cooper: I will merge both irqchip and dove patches into one
> patch set. I wasn't earlier because I didn't want the above SoCs to
> slow down patch integration. And I will split dtsi changes into
> separate patches as requested.

Understood.  I'd prefer to keep patches developed together in the same
series, that way, discussions about who is taking what and which patch
depends on what are all in the same thread of the archives.

It's difficult because some series (eg pcie) touch many different areas
and _need_ to be kept together because of the chain of dependencies.
Most other series though, aren't in that situation.

thx,

Jason.
Jason Cooper May 4, 2013, 6:12 p.m. UTC | #23
On Fri, May 03, 2013 at 12:37:20AM +0200, Sebastian Hesselbarth wrote:
> (@Jason C: Are you sure that I should merge dove and orion
> irqchip patches? I doubt that anything touching generic irq
> will not go through irq tree.)

Putting them in the same patch series does not imply they have to go
through the same tree.  But it *does* allow us to see relationships,
conflicts, etc.

Based on how the finally dependencies work out, we may ask the irq
maintainers for an Ack to take it through arm-soc.  This would happen if
we can't remove the dependency between the trees.  The resulting
potential merge conflicts weigh into it, and that's where the irqchip
maintainer's Ack get decided.

If the changes to irqchip are just Makefile/Kconfig, then it's easy.
However, if several other files are changed and conflicting, then we let
it go through irqchip and wait one merge window for the board changes
depending on it.

The goal here is to identify and remove branch dependencies within
arm-soc and between arm-soc and other trees.  A secondary goal is to
identify high-risk series (risk of being dropped), and keep them
in separate branches from other changes.

thx,

Jason.
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
new file mode 100644
index 0000000..3b303ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/marvell,orion-mpic.txt
@@ -0,0 +1,22 @@ 
+Marvell Orion SoC main interrupt controller
+
+Required properties:
+- compatible: shall be "marvell,orion-mpic"
+- reg: base address(es) of interrupt registers starting with CAUSE register
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: number of cells to encode an interrupt source, shall be 1.
+
+The interrupt sources map to the corresponding bits in the interrupt
+registers, i.e.
+- 0 maps to bit 0 of first base address,
+- 1 maps to bit 1 of first base address,
+- 32 maps to bit 0 of second base address, and so on.
+
+Example:
+	intc: interrupt-controller {
+		compatible = "marvell,orion-mpic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+                /* Dove has 64 primary interrupts */
+		reg = <0x20200 0x10>, <0x20210 0x10>;
+	};
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a350969..8da3559 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -2,6 +2,11 @@  config IRQCHIP
 	def_bool y
 	depends on OF_IRQ
 
+config IRQCHIP_ORION
+	bool
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+
 config ARM_GIC
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 98e3b87..8adbd43 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -2,6 +2,7 @@  obj-$(CONFIG_IRQCHIP)			+= irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
+obj-$(CONFIG_IRQCHIP_ORION)		+= irq-orion.o
 obj-$(CONFIG_METAG)			+= irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c
new file mode 100644
index 0000000..ea02e11
--- /dev/null
+++ b/drivers/irqchip/irq-orion.c
@@ -0,0 +1,129 @@ 
+/*
+ * Marvell Orion SoCs IRQ chip driver.
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip/orion.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/mach/irq.h>
+
+/* max number of handled irq register blocks */
+#define ORION_MAX_IRQREG		2
+
+#define ORION_IRQ_CAUSE			0x00
+#define ORION_IRQ_MASK			0x04
+#define ORION_IRQ_FIQ_MASK		0x08
+#define ORION_IRQ_ENDP_MASK		0x0c
+
+static void __iomem *orion_irq_base[ORION_MAX_IRQREG];
+static unsigned int orion_irq_regs;
+static struct irq_domain *orion_irq_domain;
+
+asmlinkage void __exception_irq_entry orion_handle_irq(struct pt_regs *regs)
+{
+	int n;
+	for (n = 0; n < orion_irq_regs; n++) {
+		u32 hwirq_base = n * 32;
+		u32 stat = readl_relaxed(orion_irq_base[n] + ORION_IRQ_CAUSE) &
+			   readl_relaxed(orion_irq_base[n] + ORION_IRQ_MASK);
+		while (stat) {
+			u32 hwirq = ffs(stat) - 1;
+			u32 irq = irq_find_mapping(orion_irq_domain,
+						hwirq_base + hwirq);
+			handle_IRQ(irq, regs);
+			stat &= ~(1 << hwirq);
+		}
+	}
+}
+
+static void orion_irq_mask(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+	unsigned int irq_off = irq % 32;
+	int reg = irq / 32;
+	u32 val;
+
+	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
+	writel(val & ~(1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
+}
+
+static void orion_irq_unmask(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+	unsigned int irq_off = irq % 32;
+	int reg = irq / 32;
+	u32 val;
+
+	val = readl(orion_irq_base[reg] + ORION_IRQ_MASK);
+	writel(val | (1 << irq_off), orion_irq_base[reg] + ORION_IRQ_MASK);
+}
+
+static struct irq_chip orion_irq_chip = {
+	.name		= "orion_irq",
+	.irq_mask	= orion_irq_mask,
+	.irq_unmask	= orion_irq_unmask,
+};
+
+static int orion_irq_map(struct irq_domain *d, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &orion_irq_chip,
+				 handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+	return 0;
+}
+
+static struct irq_domain_ops orion_irq_ops = {
+	.map = orion_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int __init orion_of_init(struct device_node *np,
+				struct device_node *parent)
+{
+	int n;
+
+	for (n = 0; n < ORION_MAX_IRQREG; n++) {
+		orion_irq_base[n] = of_iomap(np, n);
+
+		if (!orion_irq_base[n])
+			continue;
+
+		/* mask all interrupts */
+		writel(0, orion_irq_base[n] + ORION_IRQ_MASK);
+		orion_irq_regs++;
+	}
+
+	/* at least one irq reg must be set */
+	if (!orion_irq_regs)
+		panic("%s: unable to map IRQC registers\n", np->full_name);
+
+	orion_irq_domain = irq_domain_add_linear(np, orion_irq_regs * 32,
+						 &orion_irq_ops, NULL);
+	if (!orion_irq_domain)
+		panic("%s: unable to create IRQ domain\n", np->full_name);
+
+	set_handle_irq(orion_handle_irq);
+
+	return 0;
+}
+
+static struct of_device_id orion_irq_dt_ids[] __initconst = {
+	{ .compatible = "marvell,orion-mpic", .data = orion_of_init },
+	{ }
+};
+
+void __init orion_init_irq(void)
+{
+	of_irq_init(orion_irq_dt_ids);
+}
diff --git a/include/linux/irqchip/orion.h b/include/linux/irqchip/orion.h
new file mode 100644
index 0000000..04f7bab
--- /dev/null
+++ b/include/linux/irqchip/orion.h
@@ -0,0 +1,18 @@ 
+/*
+ * Marvell Orion SoCs IRQ chip driver header.
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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.
+ */
+
+#ifndef __LINUX_IRQCHIP_ORION_H
+#define __LINUX_IRQCHIP_ORION_H
+
+#include <asm/exception.h>
+
+extern void orion_init_irq(void);
+
+#endif