Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Nicolas Pitre @ 2011-09-29 18:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E84B80D.2020605@gmail.com>

On Thu, 29 Sep 2011, Rob Herring wrote:

> On 09/29/2011 12:37 PM, Russell King - ARM Linux wrote:
> > My guess would be:
> > 
> >         }, {
> >                 .virtual        =  IO_ADDRESS(VERSATILE_SCTL_BASE),
> >                 .pfn            = __phys_to_pfn(VERSATILE_SCTL_BASE),
> >                 .length         = SZ_4K * 9,
> >                 .type           = MT_DEVICE
> >         },
> > #ifdef CONFIG_MACH_VERSATILE_AB
> >         {
> >                 .virtual        =  IO_ADDRESS(VERSATILE_GPIO0_BASE),
> >                 .pfn            = __phys_to_pfn(VERSATILE_GPIO0_BASE),
> >                 .length         = SZ_4K,
> >                 .type           = MT_DEVICE
> > 
> > #define VERSATILE_SCTL_BASE            0x101E0000	/* System controller */
> > #define VERSATILE_GPIO0_BASE           0x101E4000	/* GPIO port 0 */
> > 
> > I don't see why GPIO0 is explicitly listed here.
> 
> It works for PB and AB with that removed. Here's a patch:
[...]

Thanks for testing and the patch.  I've inserted it in my patch series 
and pushed the result out.


Nicolas

^ permalink raw reply

* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Rob Herring @ 2011-09-29 18:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110929173731.GB21718@n2100.arm.linux.org.uk>

On 09/29/2011 12:37 PM, Russell King - ARM Linux wrote:
> On Thu, Sep 29, 2011 at 10:59:21AM -0500, Rob Herring wrote:
>> commit e0438e2f333005c217a2f65aacab23a39261c64c
>> Author: Nicolas Pitre <nicolas.pitre@linaro.org>
>> Date:   Thu Aug 25 00:35:59 2011 -0400
>>
>>     ARM: move iotable mappings within the vmalloc region
>>
>>     In order to remove the build time variation between different SOCs with
>>     regards to VMALLOC_END, the iotable mappings are now allocated inside
>>     the vmalloc region.  This allows for VMALLOC_END to be identical across
>>     all machines.
>>
>>     The value for VMALLOC_END is now set to 0xff000000 which is right where
>>     the consistent DMA area starts.
>>
>>     To accommodate all static mappings on machines with possible highmem
>> usage,
>>     the default vmalloc area size is changed to 240 MB so that VMALLOC_START
>>     is no higher than 0xf0000000 by default in that case.
>>
>>     Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
>>
>>
>> It dies after "Data cache writeback" with BUG at vmalloc.c:1139.
> 
> My guess would be:
> 
>         }, {
>                 .virtual        =  IO_ADDRESS(VERSATILE_SCTL_BASE),
>                 .pfn            = __phys_to_pfn(VERSATILE_SCTL_BASE),
>                 .length         = SZ_4K * 9,
>                 .type           = MT_DEVICE
>         },
> #ifdef CONFIG_MACH_VERSATILE_AB
>         {
>                 .virtual        =  IO_ADDRESS(VERSATILE_GPIO0_BASE),
>                 .pfn            = __phys_to_pfn(VERSATILE_GPIO0_BASE),
>                 .length         = SZ_4K,
>                 .type           = MT_DEVICE
> 
> #define VERSATILE_SCTL_BASE            0x101E0000	/* System controller */
> #define VERSATILE_GPIO0_BASE           0x101E4000	/* GPIO port 0 */
> 
> I don't see why GPIO0 is explicitly listed here.

It works for PB and AB with that removed. Here's a patch:

Author: Rob Herring <rob.herring@calxeda.com>
Date:   Thu Sep 29 13:18:29 2011 -0500

    ARM: versatile: remove overlapping map_desc entry

    The map_desc for VERSATILE_GPIO0_BASE overlaps with VERSATILE_SCTL_BASE.
    The overlapping entry can be removed.

    Signed-off-by: Rob Herring <rob.herring@calxeda.com>

diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e340a54..4d8dfc1 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -141,11 +141,6 @@ static struct map_desc versatile_io_desc[]
__initdata = {
 	},
 #ifdef CONFIG_MACH_VERSATILE_AB
  	{
-		.virtual	=  IO_ADDRESS(VERSATILE_GPIO0_BASE),
-		.pfn		= __phys_to_pfn(VERSATILE_GPIO0_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	=  IO_ADDRESS(VERSATILE_IB2_BASE),
 		.pfn		= __phys_to_pfn(VERSATILE_IB2_BASE),
 		.length		= SZ_64M,

^ permalink raw reply related

* [PATCHv2 2/2] ARM: debug: Move DEBUG_ICEDCC into the DEBUG_LL choice
From: David Brown @ 2011-09-29 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E84A962.9030806@codeaurora.org>

On Thu, Sep 29, 2011 at 10:22:42AM -0700, Stephen Boyd wrote:
> >> One of the problems you'll encounter is that there's places where we
> >> don't have any timer infrastructure (eg, decompressor) and software
> >> timing loops won't work (they'll be too slow for the lower-end CPUs
> >> and too fast for the upper-end CPUs.)
> > Agreed, software timing loops are the only option and it's impossible to get
> > them right everywhere. I think the Kconfig help text should be updated so
> > that the timeout paragraph is removed.
> 
> Yes if you wait a long time the timeout for each character will expire
> and the execution will continue.

Wouldn't it be better to detect the first timeout and then stop trying
to write to the DCC?

But, do we really want fancy auto-detection stuff in DEBUG_LL?  A
timeout might make sense for a DCC console, but not here.

David

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Russell King - ARM Linux @ 2011-09-29 17:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E8495D9.2030009@gmail.com>

On Thu, Sep 29, 2011 at 10:59:21AM -0500, Rob Herring wrote:
> commit e0438e2f333005c217a2f65aacab23a39261c64c
> Author: Nicolas Pitre <nicolas.pitre@linaro.org>
> Date:   Thu Aug 25 00:35:59 2011 -0400
> 
>     ARM: move iotable mappings within the vmalloc region
> 
>     In order to remove the build time variation between different SOCs with
>     regards to VMALLOC_END, the iotable mappings are now allocated inside
>     the vmalloc region.  This allows for VMALLOC_END to be identical across
>     all machines.
> 
>     The value for VMALLOC_END is now set to 0xff000000 which is right where
>     the consistent DMA area starts.
> 
>     To accommodate all static mappings on machines with possible highmem
> usage,
>     the default vmalloc area size is changed to 240 MB so that VMALLOC_START
>     is no higher than 0xf0000000 by default in that case.
> 
>     Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> 
> 
> It dies after "Data cache writeback" with BUG at vmalloc.c:1139.

My guess would be:

        }, {
                .virtual        =  IO_ADDRESS(VERSATILE_SCTL_BASE),
                .pfn            = __phys_to_pfn(VERSATILE_SCTL_BASE),
                .length         = SZ_4K * 9,
                .type           = MT_DEVICE
        },
#ifdef CONFIG_MACH_VERSATILE_AB
        {
                .virtual        =  IO_ADDRESS(VERSATILE_GPIO0_BASE),
                .pfn            = __phys_to_pfn(VERSATILE_GPIO0_BASE),
                .length         = SZ_4K,
                .type           = MT_DEVICE

#define VERSATILE_SCTL_BASE            0x101E0000	/* System controller */
#define VERSATILE_GPIO0_BASE           0x101E4000	/* GPIO port 0 */

I don't see why GPIO0 is explicitly listed here.

^ permalink raw reply

* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
From: Grant Likely @ 2011-09-29 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87fwjgv9sb.fsf@ti.com>

On Wed, Sep 28, 2011 at 10:47:32AM -0700, Kevin Hilman wrote:
> "Cousson, Benoit" <b-cousson@ti.com> writes:
> 
> > Hi Grant, Kevin,
> >
> > Should I go ahead with this version and repost the series with that
> > third patch?
> 
> Fine with me.
> 
> Grant let me know if you prefer if I merge it (with your ack) with the
> rest of the series or if you want to take it to avoid conflicts.

I'm happy with the way things have gone.  Go ahead and add my Ack and
merge it through your tree.  I'd like to avoid the conflicts.

g.

^ permalink raw reply

* [PATCHv2 2/2] ARM: debug: Move DEBUG_ICEDCC into the DEBUG_LL choice
From: Will Deacon @ 2011-09-29 17:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E84A962.9030806@codeaurora.org>

On Thu, Sep 29, 2011 at 06:22:42PM +0100, Stephen Boyd wrote:
> On 09/29/11 03:39, Will Deacon wrote:
> > Agreed, software timing loops are the only option and it's impossible to get
> > them right everywhere. I think the Kconfig help text should be updated so
> > that the timeout paragraph is removed.
> 
> Yes if you wait a long time the timeout for each character will expire
> and the execution will continue.

Well I got impatient, so I figured it was best to update the help text!

> > diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> > index 32b1be4..bfdf86b 100644
> > --- a/arch/arm/Kconfig.debug
> > +++ b/arch/arm/Kconfig.debug
> > @@ -81,6 +81,14 @@ choice
> >         prompt "Kernel low-level debugging port"
> >         depends on DEBUG_LL
> >  
> > +       config DEBUG_LL_UART_NONE
> > +               bool "No low-level debugging UART"
> 
> Should this grow a long list of platforms that are in this choice menu?
> For example:
> 
>     depends on !FOOTBRIDGE && !ARCH_CLPS711X && ...

It might be nice to avoid that if we can. Once all the platforms have moved
over to the choice, we can delete the dummy option anyway.

> Otherwise
> 
> Acked-by: Stephen Boyd <sboyd@codeaurora.org>

Thanks,

Will

^ permalink raw reply

* [PATCH 12/13] arm/dts: omap3-beagle: Add twl4030 and i2c EEPROM
From: Grant Likely @ 2011-09-29 17:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317055821-20652-13-git-send-email-b-cousson@ti.com>

On Mon, Sep 26, 2011 at 06:50:20PM +0200, Benoit Cousson wrote:
> Add required clock frequencies for the i2c client devices existing
> on beagle board.
> 
> Add the twl4030 basic description with only the twl_rtc module.
> 
> Add the EEPROM node.
> 
> Based on original patch from Manju:
> http://www.spinics.net/lists/linux-omap/msg55831.html
> 
> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
> Cc: G, Manjunath Kondaiah <manjugk@ti.com>
> ---
>  arch/arm/boot/dts/omap3-beagle.dts |   38 ++++++++++++++++++++++++++++++++++++
>  1 files changed, 38 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
> index 9486be6..a65f39d 100644
> --- a/arch/arm/boot/dts/omap3-beagle.dts
> +++ b/arch/arm/boot/dts/omap3-beagle.dts
> @@ -27,3 +27,41 @@
>  		reg = <0x80000000 0x20000000>; /* 512 MB */
>  	};
>  };
> +
> +&i2c1 {
> +	clock-frequency = <2600000>;
> +
> +	/*
> +	 * Integrated Power Management Chip
> +	 */
> +	twl at 48 {
> +		compatible = "ti,twl4030";
> +		reg = <0x48>;
> +		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
> +		interrupt-controller;
> +		#interrupt-cells = <1>;
> +		interrupt-parent = <&intc>;
> +
> +		twl_rtc {

Nit: use the generic names recommended practise for node names (in
this case, simply 'rtc' sounds appropriate, and don't use underscores
(it's not forbidden, just doesn't match the style.

> +			compatible = "ti,twl4030-rtc";
> +			interrupts = <11>;
> +		};
> +	};
> +};
> +
> +&i2c2 {
> +	clock-frequency = <400000>;
> +};
> +
> +&i2c3 {
> +	clock-frequency = <100000>;
> +
> +	/*
> +	 * Display monitor features are burnt in the EEPROM
> +	 * as EDID data.
> +	 */
> +	eeprom at 50 {
> +		compatible = "ti,eeprom";
> +		reg = <0x50>;
> +	};
> +};
> -- 
> 1.7.0.4
> 

^ permalink raw reply

* [PATCHv2 2/2] ARM: debug: Move DEBUG_ICEDCC into the DEBUG_LL choice
From: Stephen Boyd @ 2011-09-29 17:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110929103939.GD25061@e102144-lin.cambridge.arm.com>

On 09/29/11 03:39, Will Deacon wrote:
> Hi Russell,
>
> On Thu, Sep 29, 2011 at 10:46:02AM +0100, Russell King - ARM Linux wrote:
>> On Thu, Sep 29, 2011 at 10:42:43AM +0100, Will Deacon wrote:
>>> Bah, just took this for a spin on my Realview-PBX (Cortex-A9) platform and
>>> the board won't boot unless I have a hardware debugger enabled that can
>>> service the comms channel. This contradicts the Kconfig text which says:
>>>
>>> 	  It does include a timeout to ensure that the system does not
>>> 	  totally freeze when there is nothing connected to read.
>>>
>>> so we certainly need to fix something!
>> One of the problems you'll encounter is that there's places where we
>> don't have any timer infrastructure (eg, decompressor) and software
>> timing loops won't work (they'll be too slow for the lower-end CPUs
>> and too fast for the upper-end CPUs.)
> Agreed, software timing loops are the only option and it's impossible to get
> them right everywhere. I think the Kconfig help text should be updated so
> that the timeout paragraph is removed.

Yes if you wait a long time the timeout for each character will expire
and the execution will continue.

>
>> The best fix is probably to leave that as-is, but introduce a 'default'
>> output entry instead - so platforms which don't have any listed will
>> get that instead of the ICEDDC stuff.
[...]
> ----8<----
>
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index 32b1be4..bfdf86b 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -81,6 +81,14 @@ choice
>         prompt "Kernel low-level debugging port"
>         depends on DEBUG_LL
>  
> +       config DEBUG_LL_UART_NONE
> +               bool "No low-level debugging UART"

Should this grow a long list of platforms that are in this choice menu?
For example:

    depends on !FOOTBRIDGE && !ARCH_CLPS711X && ...

> +               help
> +                 Say Y here if your platform doesn't provide a UART option
> +                 below. This relies on your platform choosing the right UART
> +                 definition internally in order for low-level debugging to
> +                 work.
> +
>         config DEBUG_ICEDCC
>                 bool "Kernel low-level debugging via EmbeddedICE DCC channel"
>                 help
> @@ -89,8 +97,8 @@ choice
>                   co-processor 14. This is known to work on the ARM9 style ICE
>                   channel and on the XScale with the PEEDI.
>  
> -                 It does include a timeout to ensure that the system does not
> -                 totally freeze when there is nothing connected to read.
> +                 Note that this may cause the system to hang during boot if
> +                 there is nothing to read from the DCC.
>  
>         config DEBUG_FOOTBRIDGE_COM1
>                 bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1"
>

Otherwise

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Nicolas Pitre @ 2011-09-29 17:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E8495D9.2030009@gmail.com>

On Thu, 29 Sep 2011, Rob Herring wrote:

> Nicolas,
> 
> On 09/23/2011 08:32 AM, Nicolas Pitre wrote:
> > Russell, please pull
> > 
> > 	git://git.linaro.org/people/nico/linux vmalloc
> > 
> > This patch series removes all instances of mach/vmalloc.h in order to
> > have a more unified memory map across all ARM architectures.  To do so,
> > the static mappings are moved inside the vmalloc area.  And finally this
> > allows for a generic optimization to ioremap where static mappings are
> > reused whenever possible, using common code instead of having this
> > duplicated in a couple places.
> 
> I've found that this breaks on versatile (ab and pb) under QEMU. The
> commit causing it is:
> 
> commit e0438e2f333005c217a2f65aacab23a39261c64c
> Author: Nicolas Pitre <nicolas.pitre@linaro.org>
> Date:   Thu Aug 25 00:35:59 2011 -0400
> 
>     ARM: move iotable mappings within the vmalloc region
> 
>     In order to remove the build time variation between different SOCs with
>     regards to VMALLOC_END, the iotable mappings are now allocated inside
>     the vmalloc region.  This allows for VMALLOC_END to be identical across
>     all machines.
> 
>     The value for VMALLOC_END is now set to 0xff000000 which is right where
>     the consistent DMA area starts.
> 
>     To accommodate all static mappings on machines with possible highmem
> usage,
>     the default vmalloc area size is changed to 240 MB so that VMALLOC_START
>     is no higher than 0xf0000000 by default in that case.
> 
>     Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> 
> 
> It dies after "Data cache writeback" with BUG at vmalloc.c:1139.

Interesting.  Looks like Versatile might have overlapping map_desc 
entries.

Could you add the following line at the top of vm_area_add_early() in 
mm/vmalloc.c to display the area being added:

  printk("%s: called with addr=%p size=0x%lx\n", __func__, vm->addr, vm->size);

This should help determine which entry is wrong.


Nicolas

^ permalink raw reply

* [PATCH 2/2] ARM: gic: add OF based initialization
From: Grant Likely @ 2011-09-29 17:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317268436-1613-3-git-send-email-robherring2@gmail.com>

On Wed, Sep 28, 2011 at 10:53:56PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
> 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> 	{}
> };
> 
> static void __init init_irqs(void)
> {
> 	of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>

Looks good.

g.

^ permalink raw reply

* [PATCH 1/2] ARM: gic: add irq_domain support
From: Grant Likely @ 2011-09-29 17:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317268436-1613-2-git-send-email-robherring2@gmail.com>

On Wed, Sep 28, 2011 at 10:53:55PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Convert the gic interrupt controller to use irq domains in preparation
> for device-tree binding and MULTI_IRQ. This allows for translation between
> GIC interrupt IDs and Linux irq numbers.
> 
> The meaning of irq_offset has changed. It now is just the number of skipped
> GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
> for secondary GICs.

[...]

>  /*
> @@ -81,7 +82,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
>   */
>  static void gic_mask_irq(struct irq_data *d)
>  {
> -	u32 mask = 1 << (d->irq % 32);
> +	u32 mask = 1 << (gic_irq(d) % 32);

This can probably change simply to d->hwirq if irq_offset is
eliminated as I describe below.

>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
>  	void __iomem *dist_base, void __iomem *cpu_base)
>  {
>  	struct gic_chip_data *gic;
> +	struct irq_domain *domain;
> +	int gic_irqs;
>  
>  	BUG_ON(gic_nr >= MAX_GIC_NR);
>  
>  	gic = &gic_data[gic_nr];
> +	domain = &gic->domain;
>  	gic->dist_base = dist_base;
>  	gic->cpu_base = cpu_base;
> -	gic->irq_offset = (irq_start - 1) & ~31;
>  
> -	if (gic_nr == 0)
> +	/*
> +	 * For primary GICs, skip over SGIs.
> +	 * For secondary GICs, skip over PPIs, too.
> +	 */
> +	if (gic_nr == 0) {
>  		gic_cpu_base_addr = cpu_base;
> +		gic->irq_offset = 16;
> +		irq_start = (irq_start & ~31) + 16;

With the switch to irq_domain, there should no longer be any need for
a ~31 mask on the irq_start number.  Yes, you'll want to make sure
that it doesn't allocate below irq 16, but the driver should
completely use the irq_domain to manage the mapping from linux-irq
number to hwirq number.  The ~31 mask appears to have been an
optimization to quickly calculate hwirq number from the linux one, but
that value is now found in irq_data->hwirq.

irq_offset could almost be dropped entirely outside of probe because
it no longer matters.  Instead, populate the to_irq() hook so that the
hwirq value gets set correctly from the outset.

It would be better in general to have a consistent view of what the
hwirq number means regardless of if it is a root GIC.

g.

^ permalink raw reply

* [PATCH v5 3/3] arm/tegra: device tree support for ventana board
From: Stephen Warren @ 2011-09-29 17:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317248978-10829-4-git-send-email-pdeschrijver@nvidia.com>

Peter De Schrijver wrote at Wednesday, September 28, 2011 4:30 PM:
...
> diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
...
> @@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_match[] __initdata = {
>  	{}
>  };
> 
> +static struct {
> +	char *machine;
> +	void (*init)(void);
> +} pinmux_configs[] = {
> +	{ "nvidia,harmony", harmony_pinmux_init() },
> +	{ "nvidia,seaboard", seaboard_pinmux_init() },
> +	{ "nvidia,ventana", ventana_pinmux_init() },
> +};

Do you want the brackets after the function names there? Locally, they
cause the following syntax errors during compilation:

arch/arm/mach-tegra/board-dt.c:85: error: initializer element is not constant
arch/arm/mach-tegra/board-dt.c:85: error: (near initialization for 'pinmux_configs[0].init')
arch/arm/mach-tegra/board-dt.c:86: error: initializer element is not constant
arch/arm/mach-tegra/board-dt.c:86: error: (near initialization for 'pinmux_configs[1].init')
arch/arm/mach-tegra/board-dt.c:87: error: initializer element is not constant
arch/arm/mach-tegra/board-dt.c:87: error: (near initialization for 'pinmux_configs[2].init')

(using gcc version 4.4.3 (gcc-4.4.3_cos_gg_51096))

-- 
nvpublic

^ permalink raw reply

* [PATCHv2 02/10] ARM: vic: MULTI_IRQ_HANDLER handler
From: Grant Likely @ 2011-09-29 16:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110929093009.GM17204@pulham.picochip.com>

On Thu, Sep 29, 2011 at 10:30:09AM +0100, Jamie Iles wrote:
> On Thu, Sep 29, 2011 at 08:55:08AM +0200, Linus Walleij wrote:
> > On Wed, Sep 28, 2011 at 10:39 PM, Grant Likely
> > <grant.likely@secretlab.ca> wrote:
> > 
> > > Why isn't it simply written this way:
> > >
> > > ? ? ? ?stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
> > > ? ? ? ?while (stat) {
> > > ? ? ? ? ? ? ? ?irq = fls(stat) - 1;
> > > ? ? ? ? ? ? ? ?handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
> > > ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
> > > ? ? ? ?}
> > 
> > That is indeed closer to the assembly loop most platforms have
> > implemented.
> > 
> > Jamie can you test this approach? And also use ffs() insteadof
> > fls()...
> 
> OK, here it is (and it works)!  That does make it a lot simpler, thanks 
> guys!  I've updated the vic-dt branch in my repo too.
> 
> Jamie
> 
> 8<------
> From: Jamie Iles <jamie@jamieiles.com>
> Subject: [PATCHv3] ARM: vic: MULTI_IRQ_HANDLER handler
> 
> Add a handler for the VIC that is suitable for MULTI_IRQ_HANDLER
> platforms.  This can replace the ASM entry macros for platforms that use
> the VIC.
> 
> v3:	- simplify irq handling loop as suggested by Grant
> 	- service interrupts from msb->lsb order
> v2:	- allow the handler be used for !CONFIG_OF
> 	- use irq_domain_to_irq()
> 
> Cc: Rob Herring <robherring2@gmail.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>

Acked-by: Grant Likely <grant.likely@secretlab.ca>

> ---
>  arch/arm/common/vic.c               |   22 ++++++++++++++++++++++
>  arch/arm/include/asm/hardware/vic.h |    4 ++++
>  2 files changed, 26 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
> index 3f9c8f2..b22b83d 100644
> --- a/arch/arm/common/vic.c
> +++ b/arch/arm/common/vic.c
> @@ -427,3 +427,25 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
>  	return -EIO;
>  }
>  #endif /* CONFIG OF */
> +
> +#ifdef CONFIG_MULTI_IRQ_HANDLER
> +static void vic_single_handle_irq(struct vic_device *vic, struct pt_regs *regs)
> +{
> +	u32 stat, irq;
> +
> +	stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
> +	while (stat) {
> +		irq = ffs(stat) - 1;
> +		handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
> +		stat &= ~(1 << irq);
> +	}
> +}
> +
> +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
> +{
> +	int i;
> +
> +	for (i = 0; i < vic_id; ++i)
> +		vic_single_handle_irq(&vic_devices[i], regs);
> +}
> +#endif /* CONFIG_MULTI_IRQ_HANDLER */
> diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
> index 0135215..c02fd6f 100644
> --- a/arch/arm/include/asm/hardware/vic.h
> +++ b/arch/arm/include/asm/hardware/vic.h
> @@ -45,11 +45,15 @@
>  #include <linux/types.h>
>  
>  struct device_node;
> +struct pt_regs;
> +
>  void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
>  
>  #ifdef CONFIG_OF
>  int vic_of_init(struct device_node *node, struct device_node *parent);
>  #endif /* CONFIG_OF */
>  
> +void vic_handle_irq(struct pt_regs *regs);
> +
>  #endif /* __ASSEMBLY__ */
>  #endif
> -- 
> 1.7.4.1
> 

^ permalink raw reply

* [PATCH v2 3/5] omap3evm: Add Camera board init/hookup file
From: Tony Lindgren @ 2011-09-29 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317130848-21136-4-git-send-email-deepthy.ravi@ti.com>

Hi,

Few comments below.

* Deepthy Ravi <deepthy.ravi@ti.com> [110927 06:07]:
> +
> +#include <linux/io.h>
> +#include <linux/i2c.h>
> +#include <linux/delay.h>
> +#include <linux/gpio.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <mach/gpio.h>

You can leave out mach/gpio.h as you already have linux/gpio.h
included.

> +static int __init omap3evm_cam_init(void)
> +{
> +	int ret;
> +
> +	ret = gpio_request_array(omap3evm_gpios,
> +			ARRAY_SIZE(omap3evm_gpios));
> +	if (ret < 0) {
> +		printk(KERN_ERR "Unable to get GPIO pins\n");
> +		return ret;
> +	}
> +
> +	omap3_init_camera(&omap3evm_isp_platform_data);
> +
> +	printk(KERN_INFO "omap3evm camera init done successfully...\n");
> +	return 0;
> +}
> +
> +static void __exit omap3evm_cam_exit(void)
> +{
> +	gpio_free_array(omap3evm_gpios,
> +			ARRAY_SIZE(omap3evm_gpios));
> +}
> +
> +module_init(omap3evm_cam_init);
> +module_exit(omap3evm_cam_exit);

Looks like most of this file should be under drivers/media.

For initializing the module you should pass some platform_data
(until we have DT doing it) so you know that the camera is
available on the booted board or not. Now the init tries to
wrongly initialize things on other boards too.


> --- a/arch/arm/mach-omap2/board-omap3evm.c
> +++ b/arch/arm/mach-omap2/board-omap3evm.c
> @@ -573,6 +573,8 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = {
>  				OMAP_PIN_OFF_NONE),
>  	OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
>  				OMAP_PIN_OFF_NONE),
> +	OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
> +				OMAP_PIN_OFF_NONE),
>  #ifdef CONFIG_WL12XX_PLATFORM_DATA
>  	/* WLAN IRQ - GPIO 149 */
>  	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
> @@ -598,6 +600,8 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = {
>  	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
>  				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
>  				OMAP_PIN_OFF_WAKEUPENABLE),
> +	OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
> +				OMAP_PIN_OFF_NONE),
>  	/* AM/DM37x EVM: DSS data bus muxed with sys_boot */
>  	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
>  	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),

Is this safe to do on all boards, or only if you have the camera
board attached?

Regards,

Tony

^ permalink raw reply

* [PATCH 5/5] ARM: pxa: move gpio driver into drivers directory
From: Russell King - ARM Linux @ 2011-09-29 16:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317309546-19682-5-git-send-email-haojian.zhuang@marvell.com>

On Thu, Sep 29, 2011 at 11:19:06PM +0800, Haojian Zhuang wrote:
> +#include <linux/gpio-pxa.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/io.h>

linux/gpio.h please.

^ permalink raw reply

* [PATCH 1/2] arm: omap4: hsmmc: Fix Pbias configuration on regulator OFF
From: Tony Lindgren @ 2011-09-29 16:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317307500-5514-2-git-send-email-balajitk@ti.com>

* Balaji T K <balajitk@ti.com> [110929 07:11]:
> MMC1 data line IO's are powered down in before set regulator function.
> IO's should not be powered ON when regulator is OFF.
> Keep the IO's in power pown mode after regulator OFF.
> Delete incorrect comments which are not applicable for OMAP4.

Care to check how this is different from what I added into fixes
branch as commit 3fe8df93b0992199e3a0026fc51e90b705f94e40?

Is this a separate issue?

Tony

 
> Signed-off-by: Balaji T K <balajitk@ti.com>
> Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com>
> Reported-by: Viswanath Puttagunta <vishp@ti.com>
> ---
>  arch/arm/mach-omap2/hsmmc.c |   14 ++------------
>  1 files changed, 2 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
> index 097a42d..9cc2eb7 100644
> --- a/arch/arm/mach-omap2/hsmmc.c
> +++ b/arch/arm/mach-omap2/hsmmc.c
> @@ -129,15 +129,11 @@ static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
>  	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
>  	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
>  	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
> -	 *
> -	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
> -	 * is most naturally TWL VSIM; those pins also use PBIAS.
> -	 *
> -	 * FIXME handle VMMC1A as needed ...
>  	 */
>  	reg = omap4_ctrl_pad_readl(control_pbias_offset);
>  	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
> -		OMAP4_MMC1_PWRDNZ_MASK);
> +		OMAP4_MMC1_PWRDNZ_MASK |
> +		OMAP4_MMC1_PBIASLITE_VMODE_MASK);
>  	omap4_ctrl_pad_writel(reg, control_pbias_offset);
>  }
>  
> @@ -172,12 +168,6 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
>  			reg &= ~(OMAP4_MMC1_PWRDNZ_MASK);
>  			omap4_ctrl_pad_writel(reg, control_pbias_offset);
>  		}
> -	} else {
> -		reg = omap4_ctrl_pad_readl(control_pbias_offset);
> -		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
> -			OMAP4_MMC1_PWRDNZ_MASK |
> -			OMAP4_MMC1_PBIASLITE_VMODE_MASK);
> -		omap4_ctrl_pad_writel(reg, control_pbias_offset);
>  	}
>  }
>  
> -- 
> 1.7.0.4
> 

^ permalink raw reply

* [PATCH 2/2 v2] plat-pxa: break out GPIO driver specifics
From: Linus Walleij @ 2011-09-29 16:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAN1soZyCLc-vA5heAWGKkajUx58a2BuiJskB6FApzGb+y0ZO0A@mail.gmail.com>

On 09/29/2011 05:26 PM, Haojian Zhuang wrote:
> I think that we can move gpio out of plat-pxa directory.

Patch [1/2] in this series does that?

> And gpio
> driver needs to be simplified by supporting both pxa and mmp.
>
> I sent a new patch series for review.
>    

Sure I'll have a look...

Yours,
Linus Walleij

^ permalink raw reply

* Git pull request: mach/vmalloc.h removal, and ioremap optimizations
From: Rob Herring @ 2011-09-29 15:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1109230908410.12663@xanadu.home>

Nicolas,

On 09/23/2011 08:32 AM, Nicolas Pitre wrote:
> Russell, please pull
> 
> 	git://git.linaro.org/people/nico/linux vmalloc
> 
> This patch series removes all instances of mach/vmalloc.h in order to
> have a more unified memory map across all ARM architectures.  To do so,
> the static mappings are moved inside the vmalloc area.  And finally this
> allows for a generic optimization to ioremap where static mappings are
> reused whenever possible, using common code instead of having this
> duplicated in a couple places.
> 
> This also provides a net reduction of more than 1200 lines of code.
> 
> One regression was discovered on shmobile during testing because that 
> platform asks for 158MB of consistent DMA memory while the documented 
> maximum is 14MB.  Inspection of the code doesn't tell why this is 
> required, and listed maintainers did not respond yet after a couple 
> days.  So a temporary exception to the definition of VMALLOC_END was 
> added for CONFIG_SHMOBILE and a noisy warning to get those maintainers' 
> attention.
> 
> Based on v3.1-rc4.
> 
> Nicolas Pitre (21):
>       ARM: mach-dove: remove inclusion of <mach/vmalloc.h>
>       ARM: mach-prima2: don't define SIRFSOC_VA in terms of VMALLOC_END
>       ARM: plat-mxc: remove inclusion of <mach/vmalloc.h>
>       ARM: plat-omap: don't define OMAP1_SRAM_VA in terms of VMALLOC_END
>       ARM: mach-at91: remove arch specific special handling for ioremap
>       ARM: mach-davinci: remove arch specific special handling for ioremap
>       ARM: mach-tegra: remove arch specific special handling for ioremap
>       ARM: plat-omap: remove arch specific special handling for ioremap
>       ARM: mach-bcmring: use proper constant to identify DMA memory area
>       ARM: mach-orion5x: remove arch specific special handling for ioremap
>       ARM: mach-kirkwood: remove arch specific special handling for ioremap
>       ARM: mach-ixp23xx: remove arch specific special handling for ioremap
>       ARM: plat-iop: remove arch specific special handling for ioremap
>       ARM: sort the meminfo array earlier
>       ARM: move initialization of the high_memory variable earlier
>       mm: add vm_area_add_early()
>       ARM: move iotable mappings within the vmalloc region
>       ARM: simplify __iounmap() when dealing with section based mapping
>       ARM: add generic ioremap optimization by reusing static mappings
>       ARM: big removal of now unused vmalloc.h files
>       ARM: move VMALLOC_END down temporarily for shmobile
> 
>  Documentation/arm/memory.txt                    |   11 +-
>  arch/arm/include/asm/pgtable.h                  |   13 +-
>  arch/arm/kernel/setup.c                         |    8 +
>  arch/arm/mach-at91/include/mach/io.h            |    8 -
>  arch/arm/mach-at91/include/mach/vmalloc.h       |   26 ---
>  arch/arm/mach-at91/setup.c                      |   18 --
>  arch/arm/mach-bcmring/dma.c                     |    2 +-
>  arch/arm/mach-bcmring/include/mach/vmalloc.h    |   25 ---
>  arch/arm/mach-clps711x/include/mach/vmalloc.h   |   20 ---
>  arch/arm/mach-cns3xxx/include/mach/vmalloc.h    |   11 --
>  arch/arm/mach-davinci/Makefile                  |    2 +-
>  arch/arm/mach-davinci/include/mach/io.h         |    8 -
>  arch/arm/mach-davinci/include/mach/vmalloc.h    |   14 --
>  arch/arm/mach-davinci/io.c                      |   48 ------
>  arch/arm/mach-dove/include/mach/dove.h          |    2 -
>  arch/arm/mach-dove/include/mach/vmalloc.h       |    5 -
>  arch/arm/mach-ebsa110/include/mach/vmalloc.h    |   10 --
>  arch/arm/mach-ep93xx/include/mach/vmalloc.h     |    5 -
>  arch/arm/mach-exynos4/include/mach/vmalloc.h    |   22 ---
>  arch/arm/mach-footbridge/include/mach/vmalloc.h |   10 --
>  arch/arm/mach-gemini/include/mach/vmalloc.h     |   10 --
>  arch/arm/mach-h720x/include/mach/vmalloc.h      |   10 --
>  arch/arm/mach-integrator/include/mach/vmalloc.h |   20 ---
>  arch/arm/mach-iop13xx/include/mach/vmalloc.h    |    4 -
>  arch/arm/mach-iop32x/include/mach/io.h          |    7 -
>  arch/arm/mach-iop32x/include/mach/vmalloc.h     |    5 -
>  arch/arm/mach-iop33x/include/mach/io.h          |    7 -
>  arch/arm/mach-iop33x/include/mach/vmalloc.h     |    5 -
>  arch/arm/mach-ixp2000/include/mach/vmalloc.h    |   20 ---
>  arch/arm/mach-ixp23xx/include/mach/io.h         |   29 ----
>  arch/arm/mach-ixp23xx/include/mach/vmalloc.h    |   10 --
>  arch/arm/mach-ixp4xx/include/mach/vmalloc.h     |    5 -
>  arch/arm/mach-kirkwood/include/mach/io.h        |   25 ---
>  arch/arm/mach-kirkwood/include/mach/vmalloc.h   |    5 -
>  arch/arm/mach-ks8695/include/mach/vmalloc.h     |   19 ---
>  arch/arm/mach-lpc32xx/include/mach/vmalloc.h    |   24 ---
>  arch/arm/mach-mmp/include/mach/vmalloc.h        |    5 -
>  arch/arm/mach-msm/include/mach/vmalloc.h        |   22 ---
>  arch/arm/mach-mv78xx0/include/mach/vmalloc.h    |    5 -
>  arch/arm/mach-mxs/include/mach/vmalloc.h        |   22 ---
>  arch/arm/mach-netx/include/mach/vmalloc.h       |   19 ---
>  arch/arm/mach-nomadik/include/mach/vmalloc.h    |    2 -
>  arch/arm/mach-nuc93x/include/mach/vmalloc.h     |   23 ---
>  arch/arm/mach-omap1/include/mach/vmalloc.h      |   20 ---
>  arch/arm/mach-omap2/include/mach/vmalloc.h      |   20 ---
>  arch/arm/mach-orion5x/include/mach/io.h         |   25 ---
>  arch/arm/mach-orion5x/include/mach/vmalloc.h    |    5 -
>  arch/arm/mach-pnx4008/include/mach/vmalloc.h    |   20 ---
>  arch/arm/mach-prima2/include/mach/map.h         |    6 +-
>  arch/arm/mach-prima2/include/mach/vmalloc.h     |   16 --
>  arch/arm/mach-pxa/include/mach/vmalloc.h        |   11 --
>  arch/arm/mach-realview/include/mach/vmalloc.h   |   21 ---
>  arch/arm/mach-rpc/include/mach/vmalloc.h        |   10 --
>  arch/arm/mach-s3c2410/include/mach/vmalloc.h    |   20 ---
>  arch/arm/mach-s3c64xx/include/mach/vmalloc.h    |   20 ---
>  arch/arm/mach-s5p64x0/include/mach/vmalloc.h    |   20 ---
>  arch/arm/mach-s5pc100/include/mach/vmalloc.h    |   17 --
>  arch/arm/mach-s5pv210/include/mach/vmalloc.h    |   22 ---
>  arch/arm/mach-sa1100/include/mach/vmalloc.h     |    4 -
>  arch/arm/mach-shark/include/mach/vmalloc.h      |    4 -
>  arch/arm/mach-shmobile/include/mach/vmalloc.h   |    7 -
>  arch/arm/mach-spear3xx/include/mach/vmalloc.h   |   19 ---
>  arch/arm/mach-spear6xx/include/mach/vmalloc.h   |   19 ---
>  arch/arm/mach-tegra/include/mach/io.h           |    6 -
>  arch/arm/mach-tegra/include/mach/vmalloc.h      |   28 ----
>  arch/arm/mach-tegra/io.c                        |   21 ---
>  arch/arm/mach-u300/include/mach/vmalloc.h       |   12 --
>  arch/arm/mach-ux500/include/mach/vmalloc.h      |   18 --
>  arch/arm/mach-versatile/include/mach/vmalloc.h  |   21 ---
>  arch/arm/mach-vexpress/include/mach/vmalloc.h   |   21 ---
>  arch/arm/mach-vt8500/include/mach/vmalloc.h     |   20 ---
>  arch/arm/mach-w90x900/include/mach/vmalloc.h    |   23 ---
>  arch/arm/mach-zynq/include/mach/vmalloc.h       |   20 ---
>  arch/arm/mm/init.c                              |   40 +----
>  arch/arm/mm/ioremap.c                           |   70 ++++++---
>  arch/arm/mm/mm.h                                |   14 ++
>  arch/arm/mm/mmu.c                               |   48 ++++--
>  arch/arm/mm/nommu.c                             |    2 +
>  arch/arm/plat-iop/Makefile                      |    2 -
>  arch/arm/plat-iop/io.c                          |   59 -------
>  arch/arm/plat-mxc/include/mach/mx1.h            |    2 -
>  arch/arm/plat-mxc/include/mach/vmalloc.h        |   22 ---
>  arch/arm/plat-omap/Makefile                     |    2 +-
>  arch/arm/plat-omap/include/plat/io.h            |    6 -
>  arch/arm/plat-omap/io.c                         |  141 -----------------
>  arch/arm/plat-omap/sram.c                       |    2 +-
>  arch/arm/plat-spear/include/plat/vmalloc.h      |   19 ---
>  arch/arm/plat-tcc/include/mach/vmalloc.h        |   10 --
>  include/linux/vmalloc.h                         |    1 +
>  mm/vmalloc.c                                    |   28 +++-
>  90 files changed, 159 insertions(+), 1376 deletions(-)
> 

I've found that this breaks on versatile (ab and pb) under QEMU. The
commit causing it is:

commit e0438e2f333005c217a2f65aacab23a39261c64c
Author: Nicolas Pitre <nicolas.pitre@linaro.org>
Date:   Thu Aug 25 00:35:59 2011 -0400

    ARM: move iotable mappings within the vmalloc region

    In order to remove the build time variation between different SOCs with
    regards to VMALLOC_END, the iotable mappings are now allocated inside
    the vmalloc region.  This allows for VMALLOC_END to be identical across
    all machines.

    The value for VMALLOC_END is now set to 0xff000000 which is right where
    the consistent DMA area starts.

    To accommodate all static mappings on machines with possible highmem
usage,
    the default vmalloc area size is changed to 240 MB so that VMALLOC_START
    is no higher than 0xf0000000 by default in that case.

    Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>


It dies after "Data cache writeback" with BUG at vmalloc.c:1139.

Rob

^ permalink raw reply

* [PATCH] PM: HIBERNATION: add resume_wait param to support MMC-like devices as resume file
From: Luca Tettamanti @ 2011-09-29 15:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKPcRGr3EzjS2es6HniuQziEivpsfH2r=d_Y=nkrsFW59g6xSw@mail.gmail.com>

On Thu, Sep 29, 2011 at 5:47 PM, Luca Tettamanti <kronos.it@gmail.com> wrote:
> On Thu, Sep 29, 2011 at 11:29 AM, Barry Song <Barry.Song@csr.com> wrote:
>> From: Barry Song <baohua.song@csr.com>
>>
>> Some devices like mmc are async detected very slow. For example,
>> drivers/mmc/host/sdhci.c launchs a 200ms delayed work to detect
>> mmc partitions then add disk.
>>
>> we do have wait_for_device_probe and scsi_complete_async_scans
>> before calling swsusp_check, but it is not enough to wait mmc.
>>
>> This patch adds resumewait kernel param just like rootwait so
>> that we have enough time to wait mmc ready. The differene is
>> here we wait for resume partition but rootwait waits for rootfs
>> partition.
>
> I assume that such a device would need "rootwait" to boot in the first
> place; why don't you "overload" the param to also enable waiting in
> the resume path?

And in case that makes sense, it might be worthwhile to refactor a
common helper to be also used in do_mounts.c, e.g.
dev_t wait_for_device(char *name)

L

^ permalink raw reply

* [PATCH] ARM: imx/mx31moboard: use mc13xxx structs instead of removed mc13783 structs
From: Samuel Ortiz @ 2011-09-29 15:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110926115212.GZ20550@pengutronix.de>

Hi Uwe,

On Mon, Sep 26, 2011 at 01:52:12PM +0200, Uwe Kleine-K?nig wrote:
> Hi Samuel,
> 
> On Mon, Sep 26, 2011 at 12:05:11PM +0200, Samuel Ortiz wrote:
> > On Mon, Sep 26, 2011 at 08:50:55AM +0200, Uwe Kleine-K?nig wrote:
> > > This is needed with patch
> > > 
> > > 	mfd: Remove mc13783 API functions and symbols
> > > 
> > > (currently cde41c030 in next)
> > Sorry, I missed this one.
> > Applied now, thanks a lot.
> It's me who missed it, isn't it?
And me who applied it without noticing, so I blame us :)

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

^ permalink raw reply

* [PATCH] PM: HIBERNATION: add resume_wait param to support MMC-like devices as resume file
From: Luca Tettamanti @ 2011-09-29 15:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317288548-19560-1-git-send-email-Barry.Song@csr.com>

On Thu, Sep 29, 2011 at 11:29 AM, Barry Song <Barry.Song@csr.com> wrote:
> From: Barry Song <baohua.song@csr.com>
>
> Some devices like mmc are async detected very slow. For example,
> drivers/mmc/host/sdhci.c launchs a 200ms delayed work to detect
> mmc partitions then add disk.
>
> we do have wait_for_device_probe and scsi_complete_async_scans
> before calling swsusp_check, but it is not enough to wait mmc.
>
> This patch adds resumewait kernel param just like rootwait so
> that we have enough time to wait mmc ready. The differene is
> here we wait for resume partition but rootwait waits for rootfs
> partition.

I assume that such a device would need "rootwait" to boot in the first
place; why don't you "overload" the param to also enable waiting in
the resume path?

Luca

^ permalink raw reply

* [PATCH v5 2/3] arm/tegra: add support for ventana pinmuxing
From: Olof Johansson @ 2011-09-29 15:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110929152752.GO21166@tbergstrom-lnx.Nvidia.com>

On Thu, Sep 29, 2011 at 8:27 AM, Peter De Schrijver
<pdeschrijver@nvidia.com> wrote:
> On Thu, Sep 29, 2011 at 11:29:51AM +0200, Russell King - ARM Linux wrote:
>> On Thu, Sep 29, 2011 at 01:29:35AM +0300, Peter De Schrijver wrote:
>> > diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
>> > index f11b910..91a07e1 100644
>> > --- a/arch/arm/mach-tegra/Makefile
>> > +++ b/arch/arm/mach-tegra/Makefile
>> > @@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD} ? ? ? ? ? ? += board-seaboard-pinmux.o
>> >
>> > ?obj-${CONFIG_MACH_TEGRA_DT} ? ? ? ? ? ? += board-dt.o
>> > ?obj-${CONFIG_MACH_TEGRA_DT} ? ? ? ? ? ? += board-harmony-pinmux.o
>> > +obj-${CONFIG_MACH_TEGRA_DT} ? ? ? ? ? ? += board-seaboard-pinmux.o
>>
>> Since when did Tegra start using braces instead of parens in its Makefile?
>> I note some of Tegra's makefile is using braces and some of it parens.
>> What's the reason for this alternative style to the rest of kbuild?
>
> I have no idea. I just followed the style used for the other CONFIG_MACH_TEGRA_DT entries. Colin or Olof, any idea?

^ permalink raw reply

* [PATCH v5 2/3] arm/tegra: add support for ventana pinmuxing
From: Peter De Schrijver @ 2011-09-29 15:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110929092951.GE23944@n2100.arm.linux.org.uk>

On Thu, Sep 29, 2011 at 11:29:51AM +0200, Russell King - ARM Linux wrote:
> On Thu, Sep 29, 2011 at 01:29:35AM +0300, Peter De Schrijver wrote:
> > diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
> > index f11b910..91a07e1 100644
> > --- a/arch/arm/mach-tegra/Makefile
> > +++ b/arch/arm/mach-tegra/Makefile
> > @@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
> >  
> >  obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
> >  obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
> > +obj-${CONFIG_MACH_TEGRA_DT}             += board-seaboard-pinmux.o
> 
> Since when did Tegra start using braces instead of parens in its Makefile?
> I note some of Tegra's makefile is using braces and some of it parens.
> What's the reason for this alternative style to the rest of kbuild?

I have no idea. I just followed the style used for the other CONFIG_MACH_TEGRA_DT entries. Colin or Olof, any idea?

Thanks,

Peter.

^ permalink raw reply

* [PATCH 2/2 v2] plat-pxa: break out GPIO driver specifics
From: Haojian Zhuang @ 2011-09-29 15:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317121014-4749-1-git-send-email-linus.walleij@stericsson.com>

On Tue, Sep 27, 2011 at 6:56 PM, Linus Walleij
<linus.walleij@stericsson.com> wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
>
> The <mach/gpio.h> file is included from upper directories
> and deal with generic GPIO and gpiolib stuff. Break out the
> platform and driver specific defines and functions into its own
> header file.
>
> Cc: Eric Miao <eric.y.miao@gmail.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-mmp/brownstone.c ? ? ? ? ? ? | ? ?1 -
> ?arch/arm/mach-mmp/gplugd.c ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-mmp/include/mach/gpio-pxa.h ?| ? 30 ++++++
> ?arch/arm/mach-mmp/include/mach/gpio.h ? ? ?| ? 23 -----
> ?arch/arm/mach-mmp/jasper.c ? ? ? ? ? ? ? ? | ? ?1 -
> ?arch/arm/mach-mmp/mmp2.c ? ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-mmp/pxa168.c ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-mmp/pxa910.c ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-mmp/tavorevb.c ? ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-pxa/cm-x255.c ? ? ? ? ? ? ? ?| ? ?1 -
> ?arch/arm/mach-pxa/include/mach/gpio-pxa.h ?| ?133 ++++++++++++++++++++++++++++
> ?arch/arm/mach-pxa/include/mach/gpio.h ? ? ?| ?110 +----------------------
> ?arch/arm/mach-pxa/include/mach/littleton.h | ? ?2 +-
> ?arch/arm/mach-pxa/irq.c ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
> ?arch/arm/mach-pxa/mfp-pxa2xx.c ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-pxa/pxa25x.c ? ? ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-pxa/pxa27x.c ? ? ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/mach-pxa/pxa3xx.c ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-pxa/pxa95x.c ? ? ? ? ? ? ? ? | ? ?2 +-
> ?arch/arm/mach-pxa/saarb.c ? ? ? ? ? ? ? ? ?| ? ?1 +
> ?arch/arm/plat-pxa/include/plat/gpio-pxa.h ?| ? 44 +++++++++
> ?arch/arm/plat-pxa/include/plat/gpio.h ? ? ?| ? 40 +--------
> ?drivers/gpio/gpio-pxa.c ? ? ? ? ? ? ? ? ? ?| ? ?2 +
> ?24 files changed, 227 insertions(+), 180 deletions(-)
> ?create mode 100644 arch/arm/mach-mmp/include/mach/gpio-pxa.h
> ?create mode 100644 arch/arm/mach-pxa/include/mach/gpio-pxa.h
> ?create mode 100644 arch/arm/plat-pxa/include/plat/gpio-pxa.h
>
I think that we can move gpio out of plat-pxa directory. And gpio
driver needs to be simplified by supporting both pxa and mmp.

I sent a new patch series for review.

Thanks
Haojian

^ permalink raw reply

* [PATCH 5/5] ARM: pxa: move gpio driver into drivers directory
From: Haojian Zhuang @ 2011-09-29 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2011092901>

Move gpio driver from plat-pxa to drivers/gpio directory. Only leave
gpio number macro in mach/gpio.h.

Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
 arch/arm/mach-mmp/Kconfig             |    3 +
 arch/arm/mach-mmp/Makefile            |    2 +-
 arch/arm/mach-mmp/aspenite.c          |    4 +-
 arch/arm/mach-mmp/flint.c             |    4 +-
 arch/arm/mach-mmp/gpio.c              |   89 ++++++
 arch/arm/mach-mmp/gplugd.c            |    2 +-
 arch/arm/mach-mmp/include/mach/gpio.h |   24 +--
 arch/arm/mach-mmp/include/mach/irqs.h |    4 +-
 arch/arm/mach-mmp/mmp2.c              |   17 --
 arch/arm/mach-mmp/pxa168.c            |   17 --
 arch/arm/mach-mmp/pxa910.c            |   17 --
 arch/arm/mach-mmp/tavorevb.c          |    4 +-
 arch/arm/mach-mmp/teton_bga.c         |    2 +-
 arch/arm/mach-mmp/ttc_dkb.c           |    2 +-
 arch/arm/mach-pxa/Kconfig             |    6 +
 arch/arm/mach-pxa/Makefile            |    2 +-
 arch/arm/mach-pxa/gpio.c              |   92 ++++++
 arch/arm/mach-pxa/include/mach/gpio.h |   64 -----
 arch/arm/mach-pxa/pxa25x.c            |    3 -
 arch/arm/mach-pxa/pxa27x.c            |    2 -
 arch/arm/mach-pxa/pxa3xx.c            |    2 -
 arch/arm/mach-pxa/pxa95x.c            |    2 -
 arch/arm/plat-pxa/Makefile            |    1 -
 arch/arm/plat-pxa/gpio.c              |  352 -----------------------
 arch/arm/plat-pxa/include/plat/gpio.h |   65 -----
 drivers/gpio/Kconfig                  |    6 +
 drivers/gpio/Makefile                 |    1 +
 drivers/gpio/gpio-pxa.c               |  500 +++++++++++++++++++++++++++++++++
 include/linux/gpio-pxa.h              |  105 +++++++
 29 files changed, 816 insertions(+), 578 deletions(-)
 create mode 100644 arch/arm/mach-mmp/gpio.c
 create mode 100644 arch/arm/mach-pxa/gpio.c
 delete mode 100644 arch/arm/plat-pxa/gpio.c
 delete mode 100644 arch/arm/plat-pxa/include/plat/gpio.h
 create mode 100644 drivers/gpio/gpio-pxa.c
 create mode 100644 include/linux/gpio-pxa.h

diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 56ef5f6..47810fb 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -89,18 +89,21 @@ endmenu
 config CPU_PXA168
 	bool
 	select CPU_MOHAWK
+	select GPIO_PXA
 	help
 	  Select code specific to PXA168
 
 config CPU_PXA910
 	bool
 	select CPU_MOHAWK
+	select GPIO_PXA
 	help
 	  Select code specific to PXA910
 
 config CPU_MMP2
 	bool
 	select CPU_PJ4
+	select GPIO_PXA
 	help
 	  Select code specific to MMP2. MMP2 is ARMv7 compatible.
 endif
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index b0ac942..5af46eb 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Marvell's PXA168 processors line
 #
 
-obj-y				+= common.o clock.o devices.o time.o
+obj-y				+= common.o clock.o devices.o time.o gpio.o
 
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 6b19812..88770cf 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -119,8 +119,8 @@ static struct resource smc91x_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= pxa_gpio_to_irq(27),
-		.end	= pxa_gpio_to_irq(27),
+		.start	= mmp_gpio_to_irq(27),
+		.end	= mmp_gpio_to_irq(27),
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index f466a2c..19dfdf5 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -87,8 +87,8 @@ static struct resource smc91x_resources[] = {
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = pxa_gpio_to_irq(155),
-		.end    = pxa_gpio_to_irq(155),
+		.start  = mmp_gpio_to_irq(155),
+		.end    = mmp_gpio_to_irq(155),
 		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/gpio.c b/arch/arm/mach-mmp/gpio.c
new file mode 100644
index 0000000..345341d5
--- /dev/null
+++ b/arch/arm/mach-mmp/gpio.c
@@ -0,0 +1,89 @@
+/*
+ *  linux/arch/arm/mach-mmp/gpio.c
+ *
+ *  MMP series specific gpio init
+ *
+ *  Copyright (C) 2011 Marvell International Ltd.
+ *
+ *  Author:
+ *  	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ *  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.
+ */
+
+#include <linux/gpio-pxa.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <mach/cputype.h>
+#include <mach/irqs.h>
+#include <mach/regs-apbc.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
+
+static struct __initdata pxa_gpio_platform_data mmp_gpio_config;
+
+static struct __initdata resource mmp_resources_gpio[] = {
+	{
+		.start	= 0xd4010000,
+		.end	= 0xd401ffff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PXA168_GPIOX,
+		.end	= IRQ_PXA168_GPIOX,
+		.name	= "gpio_mux",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mmp_gpio = {
+	.name		= "pxa-gpio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mmp_resources_gpio),
+	.resource	= mmp_resources_gpio,
+};
+
+static int __init mmp_gpio_init(void)
+{
+	int size = sizeof(struct pxa_gpio_platform_data);
+	u32 reg_base = GPIO_REGS_VIRT;
+	int i;
+
+	if (cpu_is_pxa168() || cpu_is_pxa910()) {
+		/* enable GPIO clock */
+		__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO);
+		
+		/* unmask GPIO edge detection for all 4 banks - APMASKx */
+		for (i = 0; i < 4; i++)
+			__raw_writel(0xffffffff, APMASK(i));
+		mmp_gpio_config.gpio_type = MMP_GPIO;
+		mmp_gpio_config.gpio_end = 127;
+	} else if (cpu_is_mmp2()) {
+		/* enable GPIO clock */
+		__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO);
+		
+		/* unmask GPIO edge detection for all 6 banks -- APMASKx */
+		for (i = 0; i < 6; i++)
+			__raw_writel(0xffffffff, APMASK(i));
+		mmp_gpio_config.gpio_type = MMP2_GPIO;
+		mmp_gpio_config.gpio_end = 191;
+	} else
+		return 0;
+
+	pxa_gpio_regs.gplr = reg_base + GPLR_OFFSET;
+	pxa_gpio_regs.gpdr = reg_base + GPDR_OFFSET;
+	pxa_gpio_regs.gpsr = reg_base + GPSR_OFFSET;
+	pxa_gpio_regs.gpcr = reg_base + GPCR_OFFSET;
+	pxa_gpio_regs.grer = reg_base + GRER_OFFSET;
+	pxa_gpio_regs.gfer = reg_base + GFER_OFFSET;
+	pxa_gpio_regs.gedr = reg_base + GEDR_OFFSET;
+
+	platform_device_add_data(&mmp_gpio, &mmp_gpio_config, size);
+	platform_device_register(&mmp_gpio);
+	return 0;
+}
+postcore_initcall(mmp_gpio_init);
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 98e25d9..32776f3 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -9,11 +9,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
 
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
index 89d499e..9a2f4e1 100644
--- a/arch/arm/mach-mmp/include/mach/gpio.h
+++ b/arch/arm/mach-mmp/include/mach/gpio.h
@@ -3,31 +3,9 @@
 
 #include <mach/addr-map.h>
 #include <mach/irqs.h>
-#include <asm-generic/gpio.h>
 
-#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
+#define GPIO_REGS_VIRT		(APB_VIRT_BASE + 0x19000)
 
 #define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
 
-#define gpio_to_bank(gpio)	((gpio) >> 5)
-
-#define __gpio_is_inverted(gpio)	(0)
-#define __gpio_is_occupied(gpio)	(0)
-
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
-#include <plat/gpio.h>
 #endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index 2971a00..6a72198 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -220,8 +220,8 @@
 
 #define IRQ_GPIO_START			128
 #define IRQ_GPIO_NUM			192
-#define pxa_gpio_to_irq(gpio)		(IRQ_GPIO_START + (gpio))
-#define pxa_irq_to_gpio(irq)		((irq) - IRQ_GPIO_START)
+#define mmp_gpio_to_irq(gpio)		(IRQ_GPIO_START + (gpio))
+#define mmp_irq_to_gpio(irq)		((irq) - IRQ_GPIO_START)
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 1935834..5d31333 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -33,8 +33,6 @@
 
 #define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c)
-
 static struct mfp_addr_map mmp2_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0, GPIO58, 0x54),
@@ -94,24 +92,9 @@ void mmp2_clear_pmic_int(void)
 	__raw_writel(data, mfpr_pmic);
 }
 
-static void __init mmp2_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO);
-
-	/* unmask GPIO edge detection for all 6 banks -- APMASKx */
-	for (i = 0; i < 6; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_MMP2_GPIO, 0, 167, NULL);
-}
-
 void __init mmp2_init_irq(void)
 {
 	mmp2_init_icu();
-	mmp2_init_gpio();
 }
 
 static void sdhc_clk_enable(struct clk *clk)
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index e6f6789..630453a 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -43,26 +43,9 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata =
 	MFP_ADDR_END,
 };
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
-
-static void __init pxa168_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO);
-
-	/* unmask GPIO edge detection for all 4 banks - APMASKx */
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL);
-}
-
 void __init pxa168_init_irq(void)
 {
 	icu_init_irq();
-	pxa168_init_gpio();
 }
 
 /* APB peripheral clocks */
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index c70b4dd..19ebfe3 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -77,26 +77,9 @@ static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata =
 	MFP_ADDR_END,
 };
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
-
-static void __init pxa910_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO);
-
-	/* unmask GPIO edge detection for all 4 banks - APMASKx */
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL);
-}
-
 void __init pxa910_init_irq(void)
 {
 	icu_init_irq();
-	pxa910_init_gpio();
 }
 
 /* APB peripheral clocks */
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index c5e1529..c15fa2b 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -70,8 +70,8 @@ static struct resource smc91x_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= pxa_gpio_to_irq(80),
-		.end	= pxa_gpio_to_irq(80),
+		.start	= mmp_gpio_to_irq(80),
+		.end	= mmp_gpio_to_irq(80),
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
index 79bbbc2..4539fe3 100644
--- a/arch/arm/mach-mmp/teton_bga.c
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -66,7 +66,7 @@ static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
 static struct i2c_board_info teton_bga_i2c_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
-		.irq = pxa_gpio_to_irq(RTC_INT_GPIO)
+		.irq = mmp_gpio_to_irq(RTC_INT_GPIO)
 	},
 };
 
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index a420b07..b27e17e 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -136,7 +136,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 	{
 		.type		= "max7312",
 		.addr		= 0x23,
-		.irq		= pxa_gpio_to_irq(80),
+		.irq		= mmp_gpio_to_irq(80),
 		.platform_data	= &max7312_data,
 	},
 };
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index cd19309..2b81f95 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -604,24 +604,28 @@ endmenu
 config PXA25x
 	bool
 	select CPU_XSCALE
+	select GPIO_PXA
 	help
 	  Select code specific to PXA21x/25x/26x variants
 
 config PXA27x
 	bool
 	select CPU_XSCALE
+	select GPIO_PXA
 	help
 	  Select code specific to PXA27x variants
 
 config CPU_PXA26x
 	bool
 	select PXA25x
+	select GPIO_PXA
 	help
 	  Select code specific to PXA26x (codename Dalhart)
 
 config PXA3xx
 	bool
 	select CPU_XSC3
+	select GPIO_PXA
 	help
 	  Select code specific to PXA3xx variants
 
@@ -647,6 +651,7 @@ config CPU_PXA320
 config CPU_PXA930
 	bool
 	select PXA3xx
+	select GPIO_PXA
 	help
 	  PXA930 (codename Tavor-P)
 
@@ -659,6 +664,7 @@ config CPU_PXA935
 config PXA95x
 	bool
 	select CPU_PJ4
+	select GPIO_PXA
 	help
 	  Select code specific to PXA95x variants
 
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index cc39d17..ab34cae 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y				+= clock.o devices.o generic.o irq.o \
+obj-y				+= clock.o devices.o generic.o irq.o gpio.o\
 				   time.o reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
new file mode 100644
index 0000000..de65c59
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,92 @@
+/*
+ *  linux/arch/arm/mach-pxa/gpio.c
+ *
+ *  PXA series specific gpio init
+ *
+ *  Copyright (C) 2011 Marvell International Ltd.
+ *
+ *  Author:
+ *  	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ *  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.
+ */
+
+#include <linux/gpio-pxa.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+static struct __initdata pxa_gpio_platform_data pxa_gpio_config;
+
+static struct __initdata resource pxa_resources_gpio[] = {
+	{
+		.start	= 0x40e00000,
+		.end	= 0x40e0ffff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_GPIO0,
+		.end	= IRQ_GPIO0,
+		.name	= "gpio0",
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= IRQ_GPIO1,
+		.end	= IRQ_GPIO1,
+		.name	= "gpio1",
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= IRQ_GPIO_2_x,
+		.end	= IRQ_GPIO_2_x,
+		.name	= "gpio_mux",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pxa_gpio = {
+	.name		= "pxa-gpio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pxa_resources_gpio),
+	.resource	= pxa_resources_gpio,
+};
+
+static int __init pxa_gpio_init(void)
+{
+	int size = sizeof(struct pxa_gpio_platform_data);
+	u32 reg_base = io_p2v(0x40E00000);
+
+	if (cpu_is_pxa25x()) {
+#ifdef CONFIG_PXA26x
+		pxa_gpio_config.gpio_type = PXA26X_GPIO;
+		pxa_gpio_config.gpio_end = 89;
+#else
+		pxa_gpio_config.gpio_type = PXA25X_GPIO;
+		pxa_gpio_config.gpio_end = 84;
+#endif
+	} else if (cpu_is_pxa27x()) {
+		pxa_gpio_config.gpio_type = PXA27X_GPIO;
+		pxa_gpio_config.gpio_end = 120;
+	} else if (cpu_is_pxa93x() || cpu_is_pxa95x()) {
+		pxa_gpio_config.gpio_type = PXA93X_GPIO;
+		pxa_gpio_config.gpio_end = 191;
+	} else if (cpu_is_pxa3xx()) {
+		pxa_gpio_config.gpio_type = PXA3XX_GPIO;
+		pxa_gpio_config.gpio_end = 127;
+	} else
+		return 0;
+
+	pxa_gpio_regs.gplr = reg_base + GPLR_OFFSET;
+	pxa_gpio_regs.gpdr = reg_base + GPDR_OFFSET;
+	pxa_gpio_regs.gpsr = reg_base + GPSR_OFFSET;
+	pxa_gpio_regs.gpcr = reg_base + GPCR_OFFSET;
+	pxa_gpio_regs.grer = reg_base + GRER_OFFSET;
+	pxa_gpio_regs.gfer = reg_base + GFER_OFFSET;
+	pxa_gpio_regs.gedr = reg_base + GEDR_OFFSET;
+	pxa_gpio_regs.gafr = reg_base + GAFR_OFFSET;
+
+	platform_device_add_data(&pxa_gpio, &pxa_gpio_config, size);
+	platform_device_register(&pxa_gpio);
+	return 0;
+}
+postcore_initcall(pxa_gpio_init);
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index d58efb5..6db7f59 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -25,71 +25,7 @@
 #define __ASM_ARCH_PXA_GPIO_H
 
 #include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-/* GPIO Pin Level Registers */
-#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-/* GPIO Pin Direction Registers */
-#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-/* GPIO Pin Output Set Registers */
-#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-/* GPIO Pin Output Clear Registers */
-#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-/* GPIO Rising Edge Detect Registers */
-#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-/* GPIO Falling Edge Detect Registers */
-#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-/* GPIO Edge Detect Status Registers */
-#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-/* GPIO Alternate Function Select Registers */
-#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
 
 #define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
 
-#define gpio_to_bank(gpio)	((gpio) >> 5)
-
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
-	return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-		int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-		if (__gpio_is_inverted(gpio))
-			return af != 1 || dir == 0;
-		else
-			return af != 0 || dir != 0;
-	} else
-		return GPDR(gpio) & GPIO_bit(gpio);
-}
-
-#include <plat/gpio.h>
 #endif
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 2ae1739..1c5070d 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -311,14 +311,12 @@ set_pwer:
 void __init pxa25x_init_irq(void)
 {
 	pxa_init_irq(32, pxa25x_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake);
 }
 
 #ifdef CONFIG_CPU_PXA26x
 void __init pxa26x_init_irq(void)
 {
 	pxa_init_irq(32, pxa25x_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake);
 }
 #endif
 
@@ -368,7 +366,6 @@ static int __init pxa25x_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
 		ret = platform_add_devices(pxa25x_devices,
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 03d0728..638edf4 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -385,7 +385,6 @@ static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 void __init pxa27x_init_irq(void)
 {
 	pxa_init_irq(34, pxa27x_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
 static struct map_desc pxa27x_io_desc[] __initdata = {
@@ -454,7 +453,6 @@ static int __init pxa27x_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index f18a6eb..fe4db28 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -389,7 +389,6 @@ void __init pxa3xx_init_irq(void)
 
 	pxa_init_irq(56, pxa3xx_set_wake);
 	pxa_init_ext_wakeup_irq(pxa3xx_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 static struct map_desc pxa3xx_io_desc[] __initdata = {
@@ -461,7 +460,6 @@ static int __init pxa3xx_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa3xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index de25ceb..b115829 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -235,7 +235,6 @@ static struct clk_lookup pxa95x_clkregs[] = {
 void __init pxa95x_init_irq(void)
 {
 	pxa_init_irq(96, NULL);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 /*
@@ -282,7 +281,6 @@ static int __init pxa95x_init(void)
 			return ret;
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 3aca5ba..f302d04 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -4,7 +4,6 @@
 
 obj-y	:= dma.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
deleted file mode 100644
index d667d8d..0000000
--- a/arch/arm/plat-pxa/gpio.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  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.
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-#include <linux/slab.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem	*regbase;
-	char label[10];
-
-	unsigned long	irq_mask;
-	unsigned long	irq_edge_rise;
-	unsigned long	irq_edge_fall;
-
-#ifdef CONFIG_PM
-	unsigned long	saved_gplr;
-	unsigned long	saved_gpdr;
-	unsigned long	saved_grer;
-	unsigned long	saved_gfer;
-#endif
-};
-
-static DEFINE_SPINLOCK(gpio_lock);
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c)			\
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
-{
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
-}
-
-static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
-{
-	return &pxa_gpio_chips[gpio_to_bank(gpio)];
-}
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t value, mask = 1 << offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	value = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t tmp, mask = 1 << offset;
-	unsigned long flags;
-
-	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	tmp = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
-}
-
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	__raw_writel(1 << offset, gpio_chip_base(chip) +
-				(value ? GPSR_OFFSET : GPCR_OFFSET));
-}
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
-
-		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-
-		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
-		gpiochip_add(c);
-	}
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-/* Update only those GRERx and GFERx edge detection register bits if those
- * bits are set in c->irq_mask
- */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
-{
-	uint32_t grer, gfer;
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct pxa_gpio_chip *c;
-	int gpio = pxa_irq_to_gpio(d->irq);
-	unsigned long gpdr, mask = GPIO_bit(gpio);
-
-	c = gpio_to_pxachip(gpio);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-
-	if (__gpio_is_inverted(gpio))
-		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
-	else
-		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
-	else
-		c->irq_edge_rise &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
-	else
-		c->irq_edge_fall &= ~mask;
-
-	update_edge_detect(c);
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pxa_gpio_chip *c;
-	int loop, gpio, gpio_base, n;
-	unsigned long gedr;
-
-	do {
-		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
-
-			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
-
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
-				loop = 1;
-
-				generic_handle_irq(pxa_gpio_to_irq(gpio_base + n));
-				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
-			}
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
-}
-
-static void pxa_mask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-	uint32_t grer, gfer;
-
-	c->irq_mask &= ~GPIO_bit(gpio);
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static void pxa_unmask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= pxa_ack_muxed_gpio,
-	.irq_mask	= pxa_mask_muxed_gpio,
-	.irq_unmask	= pxa_unmask_muxed_gpio,
-	.irq_set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int mux_irq, int start, int end,
-			  int (*fn)(struct irq_data *, unsigned int))
-{
-	struct pxa_gpio_chip *c;
-	int gpio, irq;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	pxa_init_gpio_chip(end);
-
-	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0,c->regbase + GEDR_OFFSET);
-	}
-
-#ifdef CONFIG_ARCH_PXA
-	irq = gpio_to_irq(0);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
-	irq = gpio_to_irq(1);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
-
-	for (irq  = pxa_gpio_to_irq(start); irq <= pxa_gpio_to_irq(end);
-		irq++) {
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Install handler for GPIO>=2 edge detect interrupts */
-	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.irq_set_wake = fn;
-}
-
-#ifdef CONFIG_PM
-static int pxa_gpio_suspend(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
-		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
-
-		/* Clear GPIO transition detect bits */
-		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
-	}
-	return 0;
-}
-
-static void pxa_gpio_resume(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		/* restore level with set/clear */
-		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
-
-		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
-		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
-		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
-	}
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct syscore_ops pxa_gpio_syscore_ops = {
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h
deleted file mode 100644
index d31c2a5..0000000
--- a/arch/arm/plat-pxa/include/plat/gpio.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef __PLAT_GPIO_H
-#define __PLAT_GPIO_H
-
-#define __ARM_GPIOLIB_COMPLEX
-
-struct irq_data;
-
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
- * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
- * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
- * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
- *
- * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
- * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
- * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
- *
- * NOTE:
- *   BANK 3 is only available on PXA27x and later processors.
- *   BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
-
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
-		return GPLR(gpio) & GPIO_bit(gpio);
-	else
-		return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
-		if (value)
-			GPSR(gpio) = GPIO_bit(gpio);
-		else
-			GPCR(gpio) = GPIO_bit(gpio);
-	} else
-		__gpio_set_value(gpio, value);
-}
-
-#define gpio_cansleep		__gpio_cansleep
-
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-extern void pxa_init_gpio(int mux_irq, int start, int end,
-			  int (*fn)(struct irq_data *, unsigned int));
-#endif /* __PLAT_GPIO_H */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 6465030..08fe9f6 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -141,6 +141,12 @@ config GPIO_PL061
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
 
+config GPIO_PXA
+	def_bool y
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  Say yes here to support the PXA GPIO device
+
 config GPIO_XILINX
 	bool "Xilinx GPIO support"
 	depends on PPC_OF || MICROBLAZE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a4c8ac9..194899f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
new file mode 100644
index 0000000..21d1394
--- /dev/null
+++ b/drivers/gpio/gpio-pxa.c
@@ -0,0 +1,500 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  Copyright (C) 2011 Marvell Technology
+ *  Moved to drivers/gpio - Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ *  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.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+static int pxa_last_gpio;
+
+struct pxa_gpio_irq_data {
+	int	gpio_type;
+	int	irq_gpio0;
+	int	irq_gpio1;
+	int	irq_mux;
+};
+
+struct pxa_gpio_chip {
+	struct gpio_chip		chip;
+	void __iomem			*regbase;
+	char				label[10];
+
+	unsigned long			irq_mask;
+	unsigned long			irq_edge_rise;
+	unsigned long			irq_edge_fall;
+	struct pxa_gpio_irq_data	*data;
+
+#ifdef CONFIG_PM
+	unsigned long			saved_gplr;
+	unsigned long			saved_gpdr;
+	unsigned long			saved_grer;
+	unsigned long			saved_gfer;
+#endif
+};
+
+struct pxa_gpio_regs pxa_gpio_regs;
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int __gpio_is_inverted(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type)) {
+		if (data->gpio_type == PXA26X_GPIO && gpio > 84)
+			return 1;
+		else
+			return 0;
+	}
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return 0;
+#endif
+	return 0;
+}
+
+static int __gpio_is_irq(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+	int af = 0, dir = 0;
+	int ret;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+	switch (data->gpio_type) {
+	case PXA25X_GPIO:
+	case PXA26X_GPIO:
+	case PXA27X_GPIO:
+		af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		dir = GPDR(gpio) & GPIO_bit(gpio);
+		if ((data->gpio_type == PXA26X_GPIO) && (gpio > 84))
+			ret = (af != 1) || (dir == 0);
+		else
+			ret = (af != 0) || (dir != 0);
+		break;
+	default:
+		ret = GPDR(gpio) & GPIO_bit(gpio);
+		break;
+	}
+	return ret;
+}
+
+static inline int mgpio_to_irq(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type))
+		return pxa_gpio_to_irq(gpio);
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return mmp_gpio_to_irq(gpio);
+#endif
+	return 0;
+}
+
+static inline int mirq_to_gpio(struct irq_data *d)
+{
+	struct pxa_gpio_irq_data *data = irq_data_get_irq_chip_data(d);
+
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type))
+		return pxa_irq_to_gpio(d->irq);
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return mmp_irq_to_gpio(d->irq);
+#endif
+	return 0;
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end,
+				     struct pxa_gpio_irq_data *data)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+		chips[i].data = data;
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+	uint32_t grer, gfer;
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+	grer |= c->irq_edge_rise & c->irq_mask;
+	gfer |= c->irq_edge_fall & c->irq_mask;
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = mirq_to_gpio(d);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_pxachip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (!__gpio_is_irq(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	update_edge_detect(c);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				irq = mgpio_to_irq(gpio_base + n);
+				generic_handle_irq(irq);
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(c);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.irq_ack	= pxa_ack_muxed_gpio,
+	.irq_mask	= pxa_mask_muxed_gpio,
+	.irq_unmask	= pxa_unmask_muxed_gpio,
+	.irq_set_type	= pxa_gpio_irq_type,
+};
+
+
+static int __init pxa_gpio_probe(struct platform_device *pdev)
+{
+	struct pxa_gpio_platform_data *pdata;
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *mux_data;
+	int gpio, irq;
+	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+	pdata = pdev->dev.platform_data;
+	pxa_last_gpio = pdata->gpio_end;
+
+	mux_data = kzalloc(sizeof(struct pxa_gpio_irq_data), GFP_KERNEL);
+	if (mux_data < 0)
+		return -ENOMEM;
+
+	irq0 = platform_get_irq_byname(pdev, "gpio0");
+	irq1 = platform_get_irq_byname(pdev, "gpio1");
+	irq_mux = platform_get_irq_byname(pdev, "gpio_mux");
+	if ((irq0 > 0 && irq1 < 0) || (irq0 < 0 && irq1 > 0) || (irq_mux < 0))
+		return -EINVAL;
+
+	if (irq0 > 0) {
+		mux_data->irq_gpio0 = irq0;
+		mux_data->irq_gpio1 = irq1;
+		gpio_offset = 2;
+	}
+	mux_data->irq_mux = irq_mux;
+	mux_data->gpio_type = pdata->gpio_type;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(pdata->gpio_end, mux_data);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+#ifdef CONFIG_ARCH_PXA
+	if (irq0 > 0) {
+		irq = pxa_gpio_to_irq(0);
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
+
+		irq = pxa_gpio_to_irq(1);
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
+	}
+#endif	/* CONFIG_ARCH_PXA */
+
+	for (irq = mgpio_to_irq(gpio_offset);
+		irq <= mgpio_to_irq(pdata->gpio_end); irq++) {
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
+	return 0;
+}
+
+static struct platform_driver pxa_gpio_driver = {
+	.probe		= pxa_gpio_probe,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "pxa-gpio",
+	},
+};
+
+static int __init pxa_gpio_init(void)
+{
+	return platform_driver_register(&pxa_gpio_driver);
+}
+postcore_initcall(pxa_gpio_init);
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static void pxa_gpio_resume(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct syscore_ops pxa_gpio_syscore_ops = {
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
+
+static int __init pxa_gpio_sysinit(void)
+{
+	register_syscore_ops(&pxa_gpio_syscore_ops);
+	return 0;
+}
+postcore_initcall(pxa_gpio_sysinit);
diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h
new file mode 100644
index 0000000..97d89af
--- /dev/null
+++ b/include/linux/gpio-pxa.h
@@ -0,0 +1,105 @@
+#ifndef __GPIO_PXA_H
+#define __GPIO_PXA_H
+
+#include <asm/io.h>
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ * GPLR -- GPIO Pin Level Registers
+ * GPDR -- GPIO Pin Direction Registers
+ * GPSR -- GPIO Pin Output Set Registers
+ * GPCR -- GPIO Pin Output Clear Registers
+ * GRER -- GPIO Rising Edge Detect Registers
+ * GFER -- GPIO Falling Edge Detect Registers
+ * GEDR -- GPIO Edge Detect Status Registers
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+
+#define gpio_to_bank(x)	((x) >> 5)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+#define GAFR_OFFSET	0x54
+
+enum {
+	/*
+	 * Interrupt of GPIO0 & GPIO1 is dependant in PXA series.
+	 * Interrupt of all GPIO is muxed into one in MMP series.
+	 */
+	PXA25X_GPIO = 0,
+	PXA26X_GPIO,
+	PXA27X_GPIO,
+	PXA3XX_GPIO,
+	PXA93X_GPIO,
+	MMP_GPIO = 0x10,
+	MMP2_GPIO,
+};
+
+#define MASK_GPIO_PXA				0x0f
+#define MASK_GPIO_MMP				0xf0
+
+struct pxa_gpio_platform_data {
+	int	gpio_end;
+	int	gpio_type;
+};
+
+static inline int gpio_is_pxa_type(int type)
+{
+	return type & MASK_GPIO_PXA;
+}
+
+static inline int gpio_is_mmp_type(int type)
+{
+	return type & MASK_GPIO_MMP;
+}
+
+struct pxa_gpio_regs {
+	u32	gplr;
+	u32	gpdr;
+	u32	gpsr;
+	u32	gpcr;
+	u32	grer;
+	u32	gfer;
+	u32	gedr;
+	u32	gafr;
+};
+
+extern struct pxa_gpio_regs pxa_gpio_regs;
+
+#define GPLR(x)		(*(volatile u32 *)(pxa_gpio_regs.gplr + BANK_OFF((x >> 5))))
+#define GPDR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpdr + BANK_OFF((x >> 5))))
+#define GPSR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpsr + BANK_OFF((x >> 5))))
+#define GPCR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpcr + BANK_OFF((x >> 5))))
+#define GRER(x)		(*(volatile u32 *)(pxa_gpio_regs.grer + BANK_OFF((x >> 5))))
+#define GFER(x)		(*(volatile u32 *)(pxa_gpio_regs.gfer + BANK_OFF((x >> 5))))
+#define GEDR(x)		(*(volatile u32 *)(pxa_gpio_regs.gedr + BANK_OFF((x >> 5))))
+#define GAFR(x)		(*(volatile u32 *)(pxa_gpio_regs.gafr + (((x) & 0x70) >> 2)))
+
+#define GPIO_BANK(n)	(pxa_gpio_regs.gplr + BANK_OFF(n))
+
+#endif	/* __GPIO_PXA_H */
-- 
1.7.2.5

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox