Patchwork [U-Boot,v4,2/7] gpio: Add Multi-Function-Pin configuration driver for Marvell SoCs

login
register
mail settings
Submitter Prafulla Wadaskar
Date Dec. 7, 2010, 5:06 p.m.
Message ID <1291741587-12484-2-git-send-email-prafulla@marvell.com>
Download mbox | patch
Permalink /patch/74534/
State Superseded
Headers show

Comments

Lei Wen - Dec. 7, 2010, 3:23 p.m.
Hi Prafulla,

On Wed, Dec 8, 2010 at 1:06 AM, Prafulla Wadaskar <prafulla@marvell.com> wrote:
> Most of the Marvell SoCs has Multi Function Pin (MFP) configuration registers
> For ex. ARMADA100.
>
> These registers are programmed to expose the specific functionality
> associated with respective SoC Pins
>
> This driver provides configuration APIs,
> using them, configuration need to be done in board specific code
>
> for ex- following code configures MFPs 107 and 108 for UART_TX/RX functionality
>
> int board_early_init_f(void)
> {
>        u32 mfp_cfg[] = {
>                /* Console on UART1 */
>                MFP107_UART1_RXD,
>                MFP108_UART1_TXD,
>                MFP_EOC         /*End of configureation*/
>        };
>        /* configure MFP's */
>        mfp_config(mfp_cfg);
>        return 0;
> }
>
> Signed-off-by: Prafulla Wadaskar <prafulla@marvell.com>
> ---
> Changelog v4:
> 1. Driver renamed as mvmfp
> 2. Re-architected mvmfp driver as per review feedback
>
>  drivers/gpio/Makefile |    1 +
>  drivers/gpio/mvmfp.c  |   90 ++++++++++++++++++++++++++++++++++++++++++++
>  include/mvmfp.h       |  100 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 191 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/gpio/mvmfp.c
>  create mode 100644 include/mvmfp.h
>
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 398024c..a5fa2b5 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -27,6 +27,7 @@ LIB   := $(obj)libgpio.o
>
>  COBJS-$(CONFIG_AT91_GPIO)      += at91_gpio.o
>  COBJS-$(CONFIG_KIRKWOOD_GPIO)  += kw_gpio.o
> +COBJS-$(CONFIG_MARVELL_MFP)    += mvmfp.o
>  COBJS-$(CONFIG_MXC_GPIO)       += mxc_gpio.o
>  COBJS-$(CONFIG_PCA953X)                += pca953x.o
>  COBJS-$(CONFIG_S5P)            += s5p_gpio.o
> diff --git a/drivers/gpio/mvmfp.c b/drivers/gpio/mvmfp.c
> new file mode 100644
> index 0000000..3472278
> --- /dev/null
> +++ b/drivers/gpio/mvmfp.c
> @@ -0,0 +1,90 @@
> +/*
> + * (C) Copyright 2010
> + * Marvell Semiconductor <www.marvell.com>
> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com>,
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <mvmfp.h>
> +#include <asm/arch/mfp.h>
> +#ifdef CONFIG_ARMADA100
> +#include <asm/arch/armada100.h>
> +#define MFPR_BASE      ARMD1_MFPR_BASE
> +#else
> +#error Unsupported SoC...
> +#endif

Why not directly name a CONFIG_MFPR_BASE, and define its value in the
config file?
If we do like this ifdef, we may need do add each arch here, seems
some kind of redundant?


> +
> +/*
> + * mfp_config
> + *
> + * On most of Marvell SoCs (ex. ARMADA100) there is Multi-Funtion-Pin
> + * configuration registers to configure each GPIO/Function pin on the
> + * SoC.
> + *
> + * This function reads the array of values for
> + * MFPR_X registers and programms them into respective
> + * Multi-Function Pin registers.
> + * It supports - Alternate Function Selection programming.
> + *
> + * Whereas,
> + * The Configureation value is constructed using MFP()
> + * array consists of 32bit values as defined in MFP(xx,xx..) macro
> + */
> +void mfp_config(u32 *mfp_cfgs)
> +{
> +       u32 *p_mfpr = NULL;
> +       u32 cfg_val, val=0;
> +
> +       do {
> +               cfg_val = *mfp_cfgs++;
> +               /* exit if End of configuration table detected */
> +               if (cfg_val == MFP_EOC)
> +                       break;
> +
> +               p_mfpr = (u32 *)(MFPR_BASE + MFP_REG_GET_OFFSET(cfg_val));



> +
> +               /* Write a mfg register as per configuration */
> +               if (cfg_val & MFP_AF_FLAG) {
> +                       /* Abstract and program Afternate-Func Selection */
> +                       val &= ~MFP_AF_MASK;
Do we need to do this & here? For val is only 0 here...
Should not it be more concise like:
writel(cfg_val, p_mfpr);


> +                       val |= cfg_val & MFP_AF_MASK;
> +               } if (cfg_val & MFP_EDGE_FLAG) {
> +                       /* Abstract and program Edge configuration */
> +                       val &= ~MFP_LPM_EDGE_MASK;
> +                       val |= cfg_val & MFP_LPM_EDGE_MASK;
> +               } if (cfg_val & MFP_DRIVE_FLAG) {
> +                       /* Abstract and program Drive configuration */
> +                       val &= ~MFP_DRIVE_MASK;
> +                       val |= cfg_val & MFP_DRIVE_MASK;
> +               } if (cfg_val & MFP_PULL_FLAG) {
> +                       /* Abstract and program Pullup/down configuration */
> +                       val &= ~MFP_PULL_MASK;
> +                       val |= cfg_val & MFP_PULL_MASK;
> +               }
> +               writel(val, p_mfpr);
> +       } while (1);
> +       /*
> +        * perform a read-back of any MFPR register to make sure the
> +        * previous writings are finished
> +        */
> +       readl(p_mfpr);
> +}
> diff --git a/include/mvmfp.h b/include/mvmfp.h
> new file mode 100644
> index 0000000..0b36393
> --- /dev/null
> +++ b/include/mvmfp.h
> @@ -0,0 +1,100 @@
> +/*
> + * (C) Copyright 2010
> + * Marvell Semiconductor <www.marvell.com>
> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef __MVMFP_H
> +#define __MVMFP_H
> +
> +/*
> + * Header file for MultiFunctionPin (MFP) Configururation framework
> + *
> + * Processors Supported:
> + * 1. Marvell ARMADA100 Processors
> + *
> + * processor to be supported should be added here
> + */
> +
> +/*
> + * MFP configuration is represented by a 32-bit unsigned integer
> + */
> +#define MFP(_off, _pull, _pF, _drv, _dF, _edge, _eF, _afn, _aF) ( \
> +       /* bits 31..16 - MFP Register Offset */ (((_off) & 0xffff) << 16) | \
> +       /* bits 15..13 - Run Mode Pull State */ (((_pull) & 0x7) << 13) | \
> +       /* bit  12     - Unused */ \
> +       /* bits 11..10 - Driver Strength */     (((_drv) & 0x3) << 10) | \
> +       /* bit  09     - Pull State flag */     (((_pF) & 0x1) << 9) | \
> +       /* bit  08     - Drv-strength flag */   (((_dF) & 0x1) << 8) | \
> +       /* bit  07     - Edge-det flag */       (((_eF) & 0x1) << 7) | \
> +       /* bits 06..04 - Edge Detection */      (((_edge) & 0x7) << 4) | \
> +       /* bits 03..00 - Alt-fun flag */        (((_aF) & 0x1) << 3) | \
> +       /* bits Alternate-fun select */         ((_afn) & 0x7))
> +
> +/*
> + * to facilitate the definition, the following macros are provided
> + *
> + *                                 offset, pull,pF, drv,dF, edge,eF ,afn,aF
> + */
> +#define MFP_OFFSET_MASK                MFP(0xffff,    0,0,    0,0,     0,0,   0,0)
> +#define MFP_REG(x)             MFP(x,         0,0,    0,0,     0,0,   0,0)
> +#define MFP_REG_GET_OFFSET(x)  ((x & MFP_OFFSET_MASK) >> 16)
> +
> +#define MFP_AF_FLAG            MFP(0x0000,    0,0,    0,0,     0,0,   0,1)
> +#define MFP_DRIVE_FLAG         MFP(0x0000,    0,0,    0,1,     0,0,   0,0)
> +#define MFP_EDGE_FLAG          MFP(0x0000,    0,0,    0,0,     0,1,   0,0)
> +#define MFP_PULL_FLAG          MFP(0x0000,    0,1,    0,0,     0,0,   0,0)
> +
> +#define MFP_AF0                        MFP(0x0000,    0,0,    0,0,     0,0,   0,1)
> +#define MFP_AF1                        MFP(0x0000,    0,0,    0,0,     0,0,   1,1)
> +#define MFP_AF2                        MFP(0x0000,    0,0,    0,0,     0,0,   2,1)
> +#define MFP_AF3                        MFP(0x0000,    0,0,    0,0,     0,0,   3,1)
> +#define MFP_AF4                        MFP(0x0000,    0,0,    0,0,     0,0,   4,1)
> +#define MFP_AF5                        MFP(0x0000,    0,0,    0,0,     0,0,   5,1)
> +#define MFP_AF6                        MFP(0x0000,    0,0,    0,0,     0,0,   6,1)
> +#define MFP_AF7                        MFP(0x0000,    0,0,    0,0,     0,0,   7,1)
> +#define MFP_AF_MASK            MFP(0x0000,    0,0,    0,0,     0,0,   7,0)
> +
> +#define MFP_LPM_EDGE_NONE      MFP(0x0000,    0,0,    0,0,     0,1,   0,0)
> +#define MFP_LPM_EDGE_RISE      MFP(0x0000,    0,0,    0,0,     1,1,   0,0)
> +#define MFP_LPM_EDGE_FALL      MFP(0x0000,    0,0,    0,0,     2,1,   0,0)
> +#define MFP_LPM_EDGE_BOTH      MFP(0x0000,    0,0,    0,0,     3,1,   0,0)
> +#define MFP_LPM_EDGE_MASK      MFP(0x0000,    0,0,    0,0,     3,0,   0,0)
> +
> +#define MFP_DRIVE_VERY_SLOW    MFP(0x0000,    0,0,    0,1,     0,0,   0,0)
> +#define MFP_DRIVE_SLOW         MFP(0x0000,    0,0,    1,1,     0,0,   0,0)
> +#define MFP_DRIVE_MEDIUM       MFP(0x0000,    0,0,    2,1,     0,0,   0,0)
> +#define MFP_DRIVE_FAST         MFP(0x0000,    0,0,    3,1,     0,0,   0,0)
> +#define MFP_DRIVE_MASK         MFP(0x0000,    0,0,    3,0,     0,0,   0,0)
> +
> +#define MFP_PULL_NONE          MFP(0x0000,    0,1,    0,0,     0,0,   0,0)
> +#define MFP_PULL_LOW           MFP(0x0000,    1,1,    0,0,     0,0,   0,0)
> +#define MFP_PULL_HIGH          MFP(0x0000,    2,1,    0,0,     0,0,   0,0)
> +#define MFP_PULL_BOTH          MFP(0x0000,    3,1,    0,0,     0,0,   0,0)
> +#define MFP_PULL_FLOAT         MFP(0x0000,    4,1,    0,0,     0,0,   0,0)
> +#define MFP_PULL_MASK          MFP(0x0000,    7,0,    0,0,     0,0,   0,0)
> +
> +#define MFP_EOC                        0xffffffff      /* indicates end-of-conf */
> +
> +/* Functions */
> +void mfp_config(u32 *mfp_cfgs);
> +
> +#endif /* __MVMFP_H */
> --
> 1.5.3.4
>
Best regards,
Lei
Prafulla Wadaskar - Dec. 7, 2010, 5:06 p.m.
Most of the Marvell SoCs has Multi Function Pin (MFP) configuration registers
For ex. ARMADA100.

These registers are programmed to expose the specific functionality
associated with respective SoC Pins

This driver provides configuration APIs,
using them, configuration need to be done in board specific code

for ex- following code configures MFPs 107 and 108 for UART_TX/RX functionality

int board_early_init_f(void)
{
        u32 mfp_cfg[] = {
                /* Console on UART1 */
                MFP107_UART1_RXD,
                MFP108_UART1_TXD,
                MFP_EOC         /*End of configureation*/
        };
        /* configure MFP's */
        mfp_config(mfp_cfg);
        return 0;
}

Signed-off-by: Prafulla Wadaskar <prafulla@marvell.com>
---
Changelog v4:
1. Driver renamed as mvmfp
2. Re-architected mvmfp driver as per review feedback

 drivers/gpio/Makefile |    1 +
 drivers/gpio/mvmfp.c  |   90 ++++++++++++++++++++++++++++++++++++++++++++
 include/mvmfp.h       |  100 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpio/mvmfp.c
 create mode 100644 include/mvmfp.h
Prafulla Wadaskar - Dec. 7, 2010, 5:10 p.m.
> -----Original Message-----
> From: Lei Wen [mailto:adrian.wenl@gmail.com]
> Sent: Tuesday, December 07, 2010 8:53 PM
> To: Prafulla Wadaskar
> Cc: u-boot@lists.denx.de; Eric Miao; Manas Saksena; Lei Wen; Yu Tang;
> Ashish Karkare; Kiran Vedere; Prabhanjan Sarnaik
> Subject: Re: [U-Boot] [PATCH v4 2/7] gpio: Add Multi-Function-Pin
> configuration driver for Marvell SoCs
> 
> Hi Prafulla,
> 
> On Wed, Dec 8, 2010 at 1:06 AM, Prafulla Wadaskar <prafulla@marvell.com>
> wrote:
> > Most of the Marvell SoCs has Multi Function Pin (MFP) configuration
> registers
> > For ex. ARMADA100.
> >
> > These registers are programmed to expose the specific functionality
> > associated with respective SoC Pins
> >
> > This driver provides configuration APIs,
> > using them, configuration need to be done in board specific code
> >
> > for ex- following code configures MFPs 107 and 108 for UART_TX/RX
> functionality
> >
> > int board_early_init_f(void)
> > {
> >        u32 mfp_cfg[] = {
> >                /* Console on UART1 */
> >                MFP107_UART1_RXD,
> >                MFP108_UART1_TXD,
> >                MFP_EOC         /*End of configureation*/
> >        };
> >        /* configure MFP's */
> >        mfp_config(mfp_cfg);
> >        return 0;
> > }
> >
> > Signed-off-by: Prafulla Wadaskar <prafulla@marvell.com>
> > ---
> > Changelog v4:
> > 1. Driver renamed as mvmfp
> > 2. Re-architected mvmfp driver as per review feedback
> >
> >  drivers/gpio/Makefile |    1 +
> >  drivers/gpio/mvmfp.c  |   90
> ++++++++++++++++++++++++++++++++++++++++++++
> >  include/mvmfp.h       |  100
> +++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 191 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/gpio/mvmfp.c
> >  create mode 100644 include/mvmfp.h
> >
> > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> > index 398024c..a5fa2b5 100644
> > --- a/drivers/gpio/Makefile
> > +++ b/drivers/gpio/Makefile
> > @@ -27,6 +27,7 @@ LIB   := $(obj)libgpio.o
> >
> >  COBJS-$(CONFIG_AT91_GPIO)      += at91_gpio.o
> >  COBJS-$(CONFIG_KIRKWOOD_GPIO)  += kw_gpio.o
> > +COBJS-$(CONFIG_MARVELL_MFP)    += mvmfp.o
> >  COBJS-$(CONFIG_MXC_GPIO)       += mxc_gpio.o
> >  COBJS-$(CONFIG_PCA953X)                += pca953x.o
> >  COBJS-$(CONFIG_S5P)            += s5p_gpio.o
> > diff --git a/drivers/gpio/mvmfp.c b/drivers/gpio/mvmfp.c
> > new file mode 100644
> > index 0000000..3472278
> > --- /dev/null
> > +++ b/drivers/gpio/mvmfp.c
> > @@ -0,0 +1,90 @@
> > +/*
> > + * (C) Copyright 2010
> > + * Marvell Semiconductor <www.marvell.com>
> > + * Written-by: Prafulla Wadaskar <prafulla@marvell.com>,
> > + *
> > + * See file CREDITS for list of people who contributed to this
> > + * project.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> > + * MA 02110-1301 USA
> > + */
> > +
> > +#include <common.h>
> > +#include <asm/io.h>
> > +#include <mvmfp.h>
> > +#include <asm/arch/mfp.h>
> > +#ifdef CONFIG_ARMADA100
> > +#include <asm/arch/armada100.h>
> > +#define MFPR_BASE      ARMD1_MFPR_BASE
> > +#else
> > +#error Unsupported SoC...
> > +#endif
> 
> Why not directly name a CONFIG_MFPR_BASE, and define its value in the
> config file?

Otherway, We can eliminate #define MFPR_BASE here and define the same in asm/arch/armada100.h instead of ARMD1_MFPR_BASE

> If we do like this ifdef, we may need do add each arch here, seems
> some kind of redundant?

This is required here, see drivers/serial/serial.c

...snip...
> > +               /* Write a mfg register as per configuration */
> > +               if (cfg_val & MFP_AF_FLAG) {
> > +                       /* Abstract and program Afternate-Func Selection
> */
> > +                       val &= ~MFP_AF_MASK;
> Do we need to do this & here? For val is only 0 here...

This can be removed.

> Should not it be more concise like:
> writel(cfg_val, p_mfpr);

NACK, cfg_val have some more stuff like offset, flags, those are not required to write on mfp register.

Regards..
Prafulla . .
Albert ARIBAUD - Dec. 7, 2010, 5:39 p.m.
Le 07/12/2010 18:10, Prafulla Wadaskar a écrit :

>>> +                       val&= ~MFP_AF_MASK;
>> Do we need to do this&  here? For val is only 0 here...
>
> This can be removed.

OTOH, with the &, this line makes no assumption about val, and thus will 
work regardless of it. If the & is removed, and if later val is set to 
non-zero before reaching this instruction, it will cause a bug.

IOW, the & makes the statement more resilient.

Amicalement,
Chris Moore - Dec. 9, 2010, 6:11 a.m.
Hi,

Le 07/12/2010 18:39, Albert ARIBAUD a écrit :
> Le 07/12/2010 18:10, Prafulla Wadaskar a écrit :
>
>>>> +                       val&= ~MFP_AF_MASK;
>>> Do we need to do this&   here? For val is only 0 here...
>> This can be removed.
> OTOH, with the&, this line makes no assumption about val, and thus will
> work regardless of it. If the&  is removed, and if later val is set to
> non-zero before reaching this instruction, it will cause a bug.
>
> IOW, the&  makes the statement more resilient.
>

If val really is zero then the result will always be zero :(
Simply removing the & would give a different result.
It would be better to remove the whole bloody line ;-)

I haven't followed this thread but I suspect the original code was wrong.

Cheers,
Chris
Albert ARIBAUD - Dec. 9, 2010, 6:59 a.m.
Hi Chris,

Le 09/12/2010 07:11, Chris Moore a écrit :
> Hi,
>
> Le 07/12/2010 18:39, Albert ARIBAUD a écrit :
>> Le 07/12/2010 18:10, Prafulla Wadaskar a écrit :
>>
>>>>> + val&= ~MFP_AF_MASK;
>>>> Do we need to do this& here? For val is only 0 here...
>>> This can be removed.
>> OTOH, with the&, this line makes no assumption about val, and thus will
>> work regardless of it. If the& is removed, and if later val is set to
>> non-zero before reaching this instruction, it will cause a bug.
>>
>> IOW, the& makes the statement more resilient.
>>
>
> If val really is zero then the result will always be zero :(
> Simply removing the & would give a different result.
> It would be better to remove the whole bloody line ;-)
>
> I haven't followed this thread but I suspect the original code was wrong.

Good point as to the removal if the removal must be done :)

I still think that the original is functionally more correct *if we are 
not sure that val will always be zero.

I'll have a second look tonight.

> Cheers,
> Chris

Amicalement,
Prafulla Wadaskar - Dec. 9, 2010, 9:18 a.m.
> -----Original Message-----
> From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de]
> On Behalf Of Albert ARIBAUD
> Sent: Thursday, December 09, 2010 12:29 PM
> To: Chris Moore
> Cc: u-boot@lists.denx.de
> Subject: Re: [U-Boot] [PATCH v4 2/7] gpio: Add Multi-Function-Pin
> configuration driver for Marvell SoCs
> 
> Hi Chris,
> 
> Le 09/12/2010 07:11, Chris Moore a écrit :
> > Hi,
> >
> > Le 07/12/2010 18:39, Albert ARIBAUD a écrit :
> >> Le 07/12/2010 18:10, Prafulla Wadaskar a écrit :
> >>
> >>>>> + val&= ~MFP_AF_MASK;
> >>>> Do we need to do this& here? For val is only 0 here...
> >>> This can be removed.
> >> OTOH, with the&, this line makes no assumption about val, and thus will
> >> work regardless of it. If the& is removed, and if later val is set to
> >> non-zero before reaching this instruction, it will cause a bug.
> >>
> >> IOW, the& makes the statement more resilient.
> >>
> >
> > If val really is zero then the result will always be zero :(
> > Simply removing the & would give a different result.
> > It would be better to remove the whole bloody line ;-)
> >
> > I haven't followed this thread but I suspect the original code was
> wrong.
> 
> Good point as to the removal if the removal must be done :)
> 
> I still think that the original is functionally more correct *if we are
> not sure that val will always be zero.

The earlier code was using read-modify-write strategy for mfpr programming.
It is changed to create-write.
So removing 'and' operation makes more sense, I will post v4.1 for this since I do not want to post entire patch series.

Regards..
Prafulla . .

Patch

diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 398024c..a5fa2b5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -27,6 +27,7 @@  LIB 	:= $(obj)libgpio.o
 
 COBJS-$(CONFIG_AT91_GPIO)	+= at91_gpio.o
 COBJS-$(CONFIG_KIRKWOOD_GPIO)	+= kw_gpio.o
+COBJS-$(CONFIG_MARVELL_MFP)	+= mvmfp.o
 COBJS-$(CONFIG_MXC_GPIO)	+= mxc_gpio.o
 COBJS-$(CONFIG_PCA953X)		+= pca953x.o
 COBJS-$(CONFIG_S5P)		+= s5p_gpio.o
diff --git a/drivers/gpio/mvmfp.c b/drivers/gpio/mvmfp.c
new file mode 100644
index 0000000..3472278
--- /dev/null
+++ b/drivers/gpio/mvmfp.c
@@ -0,0 +1,90 @@ 
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>,
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mvmfp.h>
+#include <asm/arch/mfp.h>
+#ifdef CONFIG_ARMADA100
+#include <asm/arch/armada100.h>
+#define MFPR_BASE	ARMD1_MFPR_BASE
+#else
+#error Unsupported SoC...
+#endif
+
+/*
+ * mfp_config
+ *
+ * On most of Marvell SoCs (ex. ARMADA100) there is Multi-Funtion-Pin
+ * configuration registers to configure each GPIO/Function pin on the
+ * SoC.
+ *
+ * This function reads the array of values for
+ * MFPR_X registers and programms them into respective
+ * Multi-Function Pin registers.
+ * It supports - Alternate Function Selection programming.
+ *
+ * Whereas,
+ * The Configureation value is constructed using MFP()
+ * array consists of 32bit values as defined in MFP(xx,xx..) macro
+ */
+void mfp_config(u32 *mfp_cfgs)
+{
+	u32 *p_mfpr = NULL;
+	u32 cfg_val, val=0;
+
+	do {
+		cfg_val = *mfp_cfgs++;
+		/* exit if End of configuration table detected */
+		if (cfg_val == MFP_EOC)
+			break;
+
+		p_mfpr = (u32 *)(MFPR_BASE + MFP_REG_GET_OFFSET(cfg_val));
+
+		/* Write a mfg register as per configuration */
+		if (cfg_val & MFP_AF_FLAG) {
+			/* Abstract and program Afternate-Func Selection */
+			val &= ~MFP_AF_MASK;
+			val |= cfg_val & MFP_AF_MASK;
+		} if (cfg_val & MFP_EDGE_FLAG) {
+			/* Abstract and program Edge configuration */
+			val &= ~MFP_LPM_EDGE_MASK;
+			val |= cfg_val & MFP_LPM_EDGE_MASK;
+		} if (cfg_val & MFP_DRIVE_FLAG) {
+			/* Abstract and program Drive configuration */
+			val &= ~MFP_DRIVE_MASK;
+			val |= cfg_val & MFP_DRIVE_MASK;
+		} if (cfg_val & MFP_PULL_FLAG) {
+			/* Abstract and program Pullup/down configuration */
+			val &= ~MFP_PULL_MASK;
+			val |= cfg_val & MFP_PULL_MASK;
+		}
+		writel(val, p_mfpr);
+	} while (1);
+	/*
+	 * perform a read-back of any MFPR register to make sure the
+	 * previous writings are finished
+	 */
+	readl(p_mfpr);
+}
diff --git a/include/mvmfp.h b/include/mvmfp.h
new file mode 100644
index 0000000..0b36393
--- /dev/null
+++ b/include/mvmfp.h
@@ -0,0 +1,100 @@ 
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __MVMFP_H
+#define __MVMFP_H
+
+/*
+ * Header file for MultiFunctionPin (MFP) Configururation framework
+ *
+ * Processors Supported:
+ * 1. Marvell ARMADA100 Processors
+ *
+ * processor to be supported should be added here
+ */
+
+/*
+ * MFP configuration is represented by a 32-bit unsigned integer
+ */
+#define MFP(_off, _pull, _pF, _drv, _dF, _edge, _eF, _afn, _aF) ( \
+	/* bits 31..16 - MFP Register Offset */	(((_off) & 0xffff) << 16) | \
+	/* bits 15..13 - Run Mode Pull State */	(((_pull) & 0x7) << 13) | \
+	/* bit  12     - Unused */ \
+	/* bits 11..10 - Driver Strength */	(((_drv) & 0x3) << 10) | \
+	/* bit  09     - Pull State flag */	(((_pF) & 0x1) << 9) | \
+	/* bit  08     - Drv-strength flag */	(((_dF) & 0x1) << 8) | \
+	/* bit  07     - Edge-det flag */	(((_eF) & 0x1) << 7) | \
+	/* bits 06..04 - Edge Detection */	(((_edge) & 0x7) << 4) | \
+	/* bits 03..00 - Alt-fun flag */	(((_aF) & 0x1) << 3) | \
+	/* bits Alternate-fun select */		((_afn) & 0x7))
+
+/*
+ * to facilitate the definition, the following macros are provided
+ *
+ * 				    offset, pull,pF, drv,dF, edge,eF ,afn,aF
+ */
+#define MFP_OFFSET_MASK		MFP(0xffff,    0,0,    0,0,     0,0,   0,0)
+#define MFP_REG(x)		MFP(x,         0,0,    0,0,     0,0,   0,0)
+#define MFP_REG_GET_OFFSET(x)	((x & MFP_OFFSET_MASK) >> 16)
+
+#define MFP_AF_FLAG		MFP(0x0000,    0,0,    0,0,     0,0,   0,1)
+#define MFP_DRIVE_FLAG		MFP(0x0000,    0,0,    0,1,     0,0,   0,0)
+#define MFP_EDGE_FLAG		MFP(0x0000,    0,0,    0,0,     0,1,   0,0)
+#define MFP_PULL_FLAG		MFP(0x0000,    0,1,    0,0,     0,0,   0,0)
+
+#define MFP_AF0			MFP(0x0000,    0,0,    0,0,     0,0,   0,1)
+#define MFP_AF1			MFP(0x0000,    0,0,    0,0,     0,0,   1,1)
+#define MFP_AF2			MFP(0x0000,    0,0,    0,0,     0,0,   2,1)
+#define MFP_AF3			MFP(0x0000,    0,0,    0,0,     0,0,   3,1)
+#define MFP_AF4			MFP(0x0000,    0,0,    0,0,     0,0,   4,1)
+#define MFP_AF5			MFP(0x0000,    0,0,    0,0,     0,0,   5,1)
+#define MFP_AF6			MFP(0x0000,    0,0,    0,0,     0,0,   6,1)
+#define MFP_AF7			MFP(0x0000,    0,0,    0,0,     0,0,   7,1)
+#define MFP_AF_MASK		MFP(0x0000,    0,0,    0,0,     0,0,   7,0)
+
+#define MFP_LPM_EDGE_NONE	MFP(0x0000,    0,0,    0,0,     0,1,   0,0)
+#define MFP_LPM_EDGE_RISE	MFP(0x0000,    0,0,    0,0,     1,1,   0,0)
+#define MFP_LPM_EDGE_FALL	MFP(0x0000,    0,0,    0,0,     2,1,   0,0)
+#define MFP_LPM_EDGE_BOTH	MFP(0x0000,    0,0,    0,0,     3,1,   0,0)
+#define MFP_LPM_EDGE_MASK	MFP(0x0000,    0,0,    0,0,     3,0,   0,0)
+
+#define MFP_DRIVE_VERY_SLOW	MFP(0x0000,    0,0,    0,1,     0,0,   0,0)
+#define MFP_DRIVE_SLOW		MFP(0x0000,    0,0,    1,1,     0,0,   0,0)
+#define MFP_DRIVE_MEDIUM	MFP(0x0000,    0,0,    2,1,     0,0,   0,0)
+#define MFP_DRIVE_FAST		MFP(0x0000,    0,0,    3,1,     0,0,   0,0)
+#define MFP_DRIVE_MASK		MFP(0x0000,    0,0,    3,0,     0,0,   0,0)
+
+#define MFP_PULL_NONE		MFP(0x0000,    0,1,    0,0,     0,0,   0,0)
+#define MFP_PULL_LOW		MFP(0x0000,    1,1,    0,0,     0,0,   0,0)
+#define MFP_PULL_HIGH		MFP(0x0000,    2,1,    0,0,     0,0,   0,0)
+#define MFP_PULL_BOTH		MFP(0x0000,    3,1,    0,0,     0,0,   0,0)
+#define MFP_PULL_FLOAT		MFP(0x0000,    4,1,    0,0,     0,0,   0,0)
+#define MFP_PULL_MASK		MFP(0x0000,    7,0,    0,0,     0,0,   0,0)
+
+#define MFP_EOC			0xffffffff	/* indicates end-of-conf */
+
+/* Functions */
+void mfp_config(u32 *mfp_cfgs);
+
+#endif /* __MVMFP_H */