[08/10] mmc: pxa: Use the slot GPIO descriptor

Message ID 20181112141239.19646-9-linus.walleij@linaro.org
State New
Headers show
Series
  • Convert MMC slot GPIO to descriptors
Related show

Commit Message

Linus Walleij Nov. 12, 2018, 2:12 p.m.
Simplify things by making the PXA MCI driver just use
slot GPIO with descriptors instead of passing around the global
GPIO numbers that we want to get rid of.

This involves augmenting more or less every PXA boardfile,
associating each card detect or write protect line with the
right GPIO chip or GPIO expander.

As we are no longer checking for global GPIO numbers we avoid
having to fill them in at all in the platform data including
the kludge of setting the GPIO to -1 when we don't have either
signal. We just look for the slot GPIO descriptor for CD and
WP and if we find it we use it.

We take care of correctly specifying the edge sensitivity of
the GPIO lines (active low or active high) so we can later
on use this flag even though the MMC slot GPIO code uses the
*raw accessors and rely on the caps2 flags
MMC_CAP2_CD_ACTIVE_HIGH and MMC_CAP2_RO_ACTIVE_HIGH for polarity
inversion semantics as of now.

Cc: Daniel Mack <daniel@zonque.org>
Cc: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: Bartosz Golaszewski <brgl@bgdev.pl>
Cc: Andrea Adami <andrea.adami@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

---
 arch/arm/mach-pxa/balloon3.c              |  2 --
 arch/arm/mach-pxa/cm-x270.c               | 18 ++++++----
 arch/arm/mach-pxa/cm-x300.c               | 21 +++++++-----
 arch/arm/mach-pxa/colibri-evalboard.c     | 40 +++++++++++++++++-----
 arch/arm/mach-pxa/colibri-pxa270-income.c | 18 +++++++---
 arch/arm/mach-pxa/corgi.c                 | 16 +++++++--
 arch/arm/mach-pxa/csb726.c                | 18 ++++++++--
 arch/arm/mach-pxa/em-x270.c               | 33 +++++++-----------
 arch/arm/mach-pxa/gumstix.c               |  2 --
 arch/arm/mach-pxa/idp.c                   |  2 --
 arch/arm/mach-pxa/littleton.c             | 16 ++++++---
 arch/arm/mach-pxa/lubbock.c               |  2 --
 arch/arm/mach-pxa/magician.c              | 15 +++++++--
 arch/arm/mach-pxa/mainstone.c             |  2 --
 arch/arm/mach-pxa/mioa701.c               | 15 +++++++--
 arch/arm/mach-pxa/mxm8x10.c               | 16 +++++++--
 arch/arm/mach-pxa/palm27x.c               |  8 ++---
 arch/arm/mach-pxa/palm27x.h               | 12 ++++---
 arch/arm/mach-pxa/palmld.c                | 15 +++++++--
 arch/arm/mach-pxa/palmt5.c                | 15 +++++++--
 arch/arm/mach-pxa/palmtc.c                | 16 +++++++--
 arch/arm/mach-pxa/palmte2.c               | 15 +++++++--
 arch/arm/mach-pxa/palmtreo.c              | 29 +++++++++++++---
 arch/arm/mach-pxa/palmtx.c                | 15 +++++++--
 arch/arm/mach-pxa/palmz72.c               | 15 +++++++--
 arch/arm/mach-pxa/pcm990-baseboard.c      |  2 --
 arch/arm/mach-pxa/poodle.c                | 14 ++++++--
 arch/arm/mach-pxa/raumfeld.c              |  2 --
 arch/arm/mach-pxa/spitz.c                 | 15 +++++++--
 arch/arm/mach-pxa/stargate2.c             |  2 --
 arch/arm/mach-pxa/tosa.c                  | 15 +++++++--
 arch/arm/mach-pxa/trizeps4.c              |  2 --
 arch/arm/mach-pxa/vpac270.c               | 15 +++++++--
 arch/arm/mach-pxa/z2.c                    | 13 +++++--
 arch/arm/mach-pxa/zeus.c                  | 14 ++++++--
 arch/arm/mach-pxa/zylonite.c              | 41 ++++++++++++++++++-----
 drivers/mmc/host/pxamci.c                 | 37 +++++++++-----------
 include/linux/platform_data/mmc-pxamci.h  |  2 --
 38 files changed, 397 insertions(+), 153 deletions(-)

-- 
2.17.2

Comments

Daniel Mack Nov. 12, 2018, 11:48 p.m. | #1
On 12/11/2018 3:12 PM, Linus Walleij wrote:
> Simplify things by making the PXA MCI driver just use

> slot GPIO with descriptors instead of passing around the global

> GPIO numbers that we want to get rid of.

> 

> This involves augmenting more or less every PXA boardfile,

> associating each card detect or write protect line with the

> right GPIO chip or GPIO expander.

> 

> As we are no longer checking for global GPIO numbers we avoid

> having to fill them in at all in the platform data including

> the kludge of setting the GPIO to -1 when we don't have either

> signal. We just look for the slot GPIO descriptor for CD and

> WP and if we find it we use it.

> 

> We take care of correctly specifying the edge sensitivity of

> the GPIO lines (active low or active high) so we can later

> on use this flag even though the MMC slot GPIO code uses the

> *raw accessors and rely on the caps2 flags

> MMC_CAP2_CD_ACTIVE_HIGH and MMC_CAP2_RO_ACTIVE_HIGH for polarity

> inversion semantics as of now.

> 

> Cc: Daniel Mack <daniel@zonque.org>

> Cc: Robert Jarzmik <robert.jarzmik@free.fr>

> Cc: Bartosz Golaszewski <brgl@bgdev.pl>

> Cc: Andrea Adami <andrea.adami@gmail.com>

> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

> ---


...

>   arch/arm/mach-pxa/raumfeld.c              |  2 --


Thanks for doing this!

However, I'm planning to remove that file entirely very soon, and 
replace it with a dtb version. In order to avoid conflicts in the merge 
window - could you respin and leave the file untouched?


Thanks,
Daniel
Linus Walleij Nov. 13, 2018, 7:47 a.m. | #2
On Tue, Nov 13, 2018 at 12:48 AM Daniel Mack <daniel@zonque.org> wrote:

> On 12/11/2018 3:12 PM, Linus Walleij wrote:

> > Simplify things by making the PXA MCI driver just use

> > slot GPIO with descriptors instead of passing around the global

> > GPIO numbers that we want to get rid of.

> >

> > This involves augmenting more or less every PXA boardfile,

> > associating each card detect or write protect line with the

> > right GPIO chip or GPIO expander.

> >

> > As we are no longer checking for global GPIO numbers we avoid

> > having to fill them in at all in the platform data including

> > the kludge of setting the GPIO to -1 when we don't have either

> > signal. We just look for the slot GPIO descriptor for CD and

> > WP and if we find it we use it.

> >

> > We take care of correctly specifying the edge sensitivity of

> > the GPIO lines (active low or active high) so we can later

> > on use this flag even though the MMC slot GPIO code uses the

> > *raw accessors and rely on the caps2 flags

> > MMC_CAP2_CD_ACTIVE_HIGH and MMC_CAP2_RO_ACTIVE_HIGH for polarity

> > inversion semantics as of now.

> >

> > Cc: Daniel Mack <daniel@zonque.org>

> > Cc: Robert Jarzmik <robert.jarzmik@free.fr>

> > Cc: Bartosz Golaszewski <brgl@bgdev.pl>

> > Cc: Andrea Adami <andrea.adami@gmail.com>

> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

> > ---

>

> ...

>

> >   arch/arm/mach-pxa/raumfeld.c              |  2 --

>

> Thanks for doing this!

>

> However, I'm planning to remove that file entirely very soon, and

> replace it with a dtb version. In order to avoid conflicts in the merge

> window - could you respin and leave the file untouched?


That's not usually how we do things.

It's better if Ulf apply the patches to an immutable branch and we
pull that into ARM SoC so they have the changes and then you
can remove it on top of that.

Another possibility is to let linux-next (and Torvalds) deal with the
conflict when the file gets removed in one pull request and
altered in another. In fact that is usually what we do.

Yours,
Linus Walleij
Robert Jarzmik Nov. 13, 2018, 8:24 a.m. | #3
Linus Walleij <linus.walleij@linaro.org> writes:

> Simplify things by making the PXA MCI driver just use

> slot GPIO with descriptors instead of passing around the global

> GPIO numbers that we want to get rid of.


Hi Linus,

I'd like some improvement here and there. Let's tackle first the generic parts :
 - patch split
   I'd like the mach-pxa part to be in a separate patch. Looking at your patch,
   that probably means, if I'm right, a split in 4 patches :
     1) Add the GPIO_LOOKUP entries
     2) Add the pxamci part to use GPIO tables
     3) Remove the platform_data in mach-pxa
     4) Remove the dead code from pxamci
   That will enable easier "Fixes:" tags, and easier maintainance for me and
   Ulf, as the fixes will go either on a patch for his tree or mine, so neither
   of use will have to bother with other conflicts.

 - GPIO tables
   Don't use number, only defines.
   In some of the mach-pxa files, you use :
> +static struct gpiod_lookup_table cmx270_mci_gpio_table = {

> +	.dev_id = "pxa2xx-mci.0",

> +	.table = {

> +		/* Card detect on GPIO 83 */

> +		GPIO_LOOKUP("gpio-pxa", 83, "cd", GPIO_ACTIVE_LOW),

> +		{ },

> +	},

> +};

   I'd like instead :
> +static struct gpiod_lookup_table cmx270_mci_gpio_table = {

> +	.dev_id = "pxa2xx-mci.0",

> +	.table = {

> +		/* Card detect on GPIO 83 */

> +		GPIO_LOOKUP("gpio-pxa", GPIO83_MMC_IRQ, "cd", GPIO_ACTIVE_LOW),

> +		{ },

> +	},

> +};


 - the zylonite specific case
   This is the real showstopper here, which could block this conversion and
   deserves your full brain power :)
   I already had attempted this conversion in the past, and came to a limitation
   in the GPIO_LOOKUP model. The problem is that there are 2 gpio expanders (see
   zylonite_pxa300.c), struct zylonite_i2c_board_info[].
   Therefore, the GPIO_LOOKUP is not guaranteed AFAIK to check the correct
   expander to get the gpio ... That problem is a good one for the GPIO
   maintainer :)
> +static struct gpiod_lookup_table zylonite_mci_gpio_table = {

> +	.dev_id = "pxa2xx-mci.0",

> +	.table = {

> +		GPIO_LOOKUP("pca9539", 0, "cd", GPIO_ACTIVE_LOW),

> +		GPIO_LOOKUP("pca9539", 2, "wp", GPIO_ACTIVE_LOW),

> +		{ },

> +	},

> +};


 - the platform_data cleanup
> diff --git a/include/linux/platform_data/mmc-pxamci.h b/include/linux/platform_data/mmc-pxamci.h

> index 752f97c62ef2..db6c247d42d1 100644

> --- a/include/linux/platform_data/mmc-pxamci.h

> +++ b/include/linux/platform_data/mmc-pxamci.h

> @@ -15,8 +15,6 @@ struct pxamci_platform_data {

>  	int (*get_ro)(struct device *);

>  	int (*setpower)(struct device *, unsigned int);

>  	void (*exit)(struct device *, void *);

> -	int gpio_card_detect;			/* gpio detecting card insertion */

> -	int gpio_card_ro;			/* gpio detecting read only toggle */

>  	bool gpio_card_ro_invert;		/* gpio ro is inverted */

>  	int gpio_power;				/* gpio powering up MMC bus */

>  	bool gpio_power_invert;			/* gpio power is inverted */

   Given all the work you injected to remove the gpios, I wonder why
   gpio_card_ro_invert survived ...


In the mean time where these points are addressed, I'll go more deeply through
the details of this patch.

Cheers.

--
Robert
Daniel Mack Nov. 14, 2018, 7:41 p.m. | #4
Hi Linus,

On 13/11/2018 8:47 AM, Linus Walleij wrote:
>> On 12/11/2018 3:12 PM, Linus Walleij wrote:

>>> Simplify things by making the PXA MCI driver just use

>>> slot GPIO with descriptors instead of passing around the global

>>> GPIO numbers that we want to get rid of.

>>>

>>> This involves augmenting more or less every PXA boardfile,

>>> associating each card detect or write protect line with the

>>> right GPIO chip or GPIO expander.


...

>> However, I'm planning to remove that file entirely very soon, and

>> replace it with a dtb version. In order to avoid conflicts in the merge

>> window - could you respin and leave the file untouched?

> 

> That's not usually how we do things.


Fair enough, then let's just sort that out at merge time.

Robert's comments are more pressing anyway.


Thanks,
Daniel
Linus Walleij Nov. 15, 2018, 11:48 p.m. | #5
On Tue, Nov 13, 2018 at 9:24 AM Robert Jarzmik <robert.jarzmik@free.fr> wrote:

> I'd like some improvement here and there. Let's tackle first the generic parts :

>  - patch split

>    I'd like the mach-pxa part to be in a separate patch. Looking at your patch,

>    that probably means, if I'm right, a split in 4 patches :

>      1) Add the GPIO_LOOKUP entries

>      2) Add the pxamci part to use GPIO tables

>      3) Remove the platform_data in mach-pxa

>      4) Remove the dead code from pxamci

>    That will enable easier "Fixes:" tags, and easier maintainance for me and

>    Ulf, as the fixes will go either on a patch for his tree or mine, so neither

>    of use will have to bother with other conflicts.


OK usually when I do these manufacturings I take quite big
steps mainly because I do not see that the above will help
bisectability of anything breaks: all possible regressions
will be in patch (2) and all fixes will be to that patch as well
(unless purely syntactic issues).

But I'm happy to do it any way the PXA maintainers like it,
so sure!

>  - GPIO tables

>    Don't use number, only defines.


OK.

>  - the zylonite specific case

>    This is the real showstopper here, which could block this conversion and

>    deserves your full brain power :)

>    I already had attempted this conversion in the past, and came to a limitation

>    in the GPIO_LOOKUP model. The problem is that there are 2 gpio expanders (see

>    zylonite_pxa300.c), struct zylonite_i2c_board_info[].

>    Therefore, the GPIO_LOOKUP is not088413bc0bd5f5fb66ca22a19d66a49d7154ba4c guaranteed AFAIK to check the correct

>    expander to get the gpio ... That problem is a good one for the GPIO

>    maintainer :)


This is no big deal usually, see e.g. commit
088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

The GPIOs are looked up to the gpio_chip .label field,
this is not an ABI or anything so all we need to do is make
sure that this label is unique for each GPIO expander.
pca9539 probes drivers/gpio/gpio-pca953x.c
and as you can see label is set from the i2c client
name. This is bad practice, let's just patch it to use
the dev_name on the I2C struct device* instead.

That makes things very easy since I2C board data has
a way of naming I2C devices using .dev_name.
If you set .dev_name to "expander-a" on the first
instance, and "expander-b" on the second instance,
the gpiochip labels will be "i2c-expander-a" and
"i2c-expander-b" as you can see in drivers/i2c/i2c-core-base.c

I'll send a patch.

Yours,
Linus Walleij
Robert Jarzmik Nov. 17, 2018, 8:09 p.m. | #6
Linus Walleij <linus.walleij@linaro.org> writes:

> On Tue, Nov 13, 2018 at 9:24 AM Robert Jarzmik <robert.jarzmik@free.fr> wrote:

>

>> I'd like some improvement here and there. Let's tackle first the generic parts :

>>  - patch split

>>    I'd like the mach-pxa part to be in a separate patch. Looking at your patch,

>>    that probably means, if I'm right, a split in 4 patches :

>>      1) Add the GPIO_LOOKUP entries

>>      2) Add the pxamci part to use GPIO tables

>>      3) Remove the platform_data in mach-pxa

>>      4) Remove the dead code from pxamci

>>    That will enable easier "Fixes:" tags, and easier maintainance for me and

>>    Ulf, as the fixes will go either on a patch for his tree or mine, so neither

>>    of use will have to bother with other conflicts.

>

> OK usually when I do these manufacturings I take quite big

> steps mainly because I do not see that the above will help

> bisectability of anything breaks: all possible regressions

> will be in patch (2) and all fixes will be to that patch as well

> (unless purely syntactic issues).

>

> But I'm happy to do it any way the PXA maintainers like it,

> so sure!

Thanks Linux, I appreciate that.

>>  - the zylonite specific case

>>    This is the real showstopper here, which could block this conversion and

>>    deserves your full brain power :)

> This is no big deal usually, see e.g. commit

> 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

> I'll send a patch.

Excellent, rock'n roll.

Cheers.

-- 
Robert

Patch

diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index c52c081eb6d9..612109c515da 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -290,8 +290,6 @@  static unsigned long balloon3_mmc_pin_config[] __initdata = {
 
 static struct pxamci_platform_data balloon3_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 	.detect_delay_ms	= 200,
 };
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index be4a66166d61..8c530fcd87d9 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -12,6 +12,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/delay.h>
 
 #include <linux/platform_data/rtc-v3020.h>
@@ -30,11 +31,6 @@ 
 /* physical address if local-bus attached devices */
 #define RTC_PHYS_BASE		(PXA_CS1_PHYS + (5 << 22))
 
-/* GPIO IRQ usage */
-#define GPIO83_MMC_IRQ		(83)
-
-#define CMX270_MMC_IRQ		PXA_GPIO_TO_IRQ(GPIO83_MMC_IRQ)
-
 /* MMC power enable */
 #define GPIO105_MMC_POWER	(105)
 
@@ -288,14 +284,22 @@  static inline void cmx270_init_ohci(void) {}
 #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
 static struct pxamci_platform_data cmx270_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO83_MMC_IRQ,
-	.gpio_card_ro		= -1,
 	.gpio_power		= GPIO105_MMC_POWER,
 	.gpio_power_invert	= 1,
 };
 
+static struct gpiod_lookup_table cmx270_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 83 */
+		GPIO_LOOKUP("gpio-pxa", 83, "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init cmx270_init_mmc(void)
 {
+	gpiod_add_lookup_table(&cmx270_mci_gpio_table);
 	pxa_set_mci_info(&cmx270_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index c5c0ab8ac9f9..93a2d5b58f84 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -64,11 +64,6 @@ 
 
 #define CM_X300_ETH_PHYS	0x08000010
 
-#define GPIO82_MMC_IRQ		(82)
-#define GPIO85_MMC_WP		(85)
-
-#define	CM_X300_MMC_IRQ		PXA_GPIO_TO_IRQ(GPIO82_MMC_IRQ)
-
 #define GPIO95_RTC_CS		(95)
 #define GPIO96_RTC_WR		(96)
 #define GPIO97_RTC_RD		(97)
@@ -459,11 +454,20 @@  static inline void cm_x300_init_nand(void) {}
 static struct pxamci_platform_data cm_x300_mci_platform_data = {
 	.detect_delay_ms	= 200,
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO82_MMC_IRQ,
-	.gpio_card_ro		= GPIO85_MMC_WP,
 	.gpio_power		= -1,
 };
 
+static struct gpiod_lookup_table cm_x300_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 82 */
+		GPIO_LOOKUP("gpio-pxa", 82, "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 85 */
+		GPIO_LOOKUP("gpio-pxa", 85, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 /* The second MMC slot of CM-X300 is hardwired to Libertas card and has
    no detection/ro pins */
 static int cm_x300_mci2_init(struct device *dev,
@@ -482,13 +486,12 @@  static struct pxamci_platform_data cm_x300_mci2_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
 	.init 			= cm_x300_mci2_init,
 	.exit			= cm_x300_mci2_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
 static void __init cm_x300_init_mmc(void)
 {
+	gpiod_add_lookup_table(&cm_x300_mci_gpio_table);
 	pxa_set_mci_info(&cm_x300_mci_platform_data);
 	pxa3xx_set_mci2_info(&cm_x300_mci2_platform_data);
 }
diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
index 10e2278b7a28..2ccdef5de138 100644
--- a/arch/arm/mach-pxa/colibri-evalboard.c
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -14,7 +14,7 @@ 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/mach/arch.h>
@@ -37,22 +37,44 @@ 
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data colibri_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_power		= -1,
-	.gpio_card_ro		= -1,
 	.detect_delay_ms	= 200,
 };
 
+static struct gpiod_lookup_table colibri_pxa270_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO0_COLIBRI_PXA270_SD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
+static struct gpiod_lookup_table colibri_pxa300_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO13_COLIBRI_PXA300_SD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
+static struct gpiod_lookup_table colibri_pxa320_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO28_COLIBRI_PXA320_SD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init colibri_mmc_init(void)
 {
 	if (machine_is_colibri())	/* PXA270 Colibri */
-		colibri_mci_platform_data.gpio_card_detect =
-			GPIO0_COLIBRI_PXA270_SD_DETECT;
+		gpiod_add_lookup_table(&colibri_pxa270_mci_gpio_table);
 	if (machine_is_colibri300())	/* PXA300 Colibri */
-		colibri_mci_platform_data.gpio_card_detect =
-			GPIO13_COLIBRI_PXA300_SD_DETECT;
+		gpiod_add_lookup_table(&colibri_pxa300_mci_gpio_table);
 	else				/* PXA320 Colibri */
-		colibri_mci_platform_data.gpio_card_detect =
-			GPIO28_COLIBRI_PXA320_SD_DETECT;
+		gpiod_add_lookup_table(&colibri_pxa320_mci_gpio_table);
 
 	pxa_set_mci_info(&colibri_mci_platform_data);
 }
diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 3ccf2a95569b..3554e6befbb8 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -14,7 +14,7 @@ 
 
 #include <linux/bitops.h>
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/leds.h>
@@ -39,8 +39,6 @@ 
 #include "generic.h"
 
 #define GPIO114_INCOME_ETH_IRQ  (114)
-#define GPIO0_INCOME_SD_DETECT  (0)
-#define GPIO0_INCOME_SD_RO      (1)
 #define GPIO54_INCOME_LED_A     (54)
 #define GPIO55_INCOME_LED_B     (55)
 #define GPIO113_INCOME_TS_IRQ   (113)
@@ -52,13 +50,23 @@ 
 static struct pxamci_platform_data income_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
 	.gpio_power		= -1,
-	.gpio_card_detect	= GPIO0_INCOME_SD_DETECT,
-	.gpio_card_ro		= GPIO0_INCOME_SD_RO,
 	.detect_delay_ms	= 200,
 };
 
+static struct gpiod_lookup_table income_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 0 */
+		GPIO_LOOKUP("gpio-pxa", 0, "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 1 */
+		GPIO_LOOKUP("gpio-pxa", 1, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init income_mmc_init(void)
 {
+	gpiod_add_lookup_table(&income_mci_gpio_table);
 	pxa_set_mci_info(&income_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 9a5a35e90769..d57a3738a200 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -24,6 +24,7 @@ 
 #include <linux/mtd/physmap.h>
 #include <linux/pm.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/backlight.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-pxa.h>
@@ -493,11 +494,21 @@  static struct platform_device corgi_audio_device = {
 static struct pxamci_platform_data corgi_mci_platform_data = {
 	.detect_delay_ms	= 250,
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect	= CORGI_GPIO_nSD_DETECT,
-	.gpio_card_ro		= CORGI_GPIO_nSD_WP,
 	.gpio_power		= CORGI_GPIO_SD_PWR,
 };
 
+static struct gpiod_lookup_table corgi_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 9 */
+		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_nSD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 7 */
+		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_nSD_WP,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
 
 /*
  * Irda
@@ -731,6 +742,7 @@  static void __init corgi_init(void)
 	corgi_init_spi();
 
  	pxa_set_udc_info(&udc_info);
+	gpiod_add_lookup_table(&corgi_mci_gpio_table);
 	pxa_set_mci_info(&corgi_mci_platform_data);
 	pxa_set_ficp_info(&corgi_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 271aedae7542..f00e0c12f63e 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -11,7 +11,7 @@ 
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
@@ -129,11 +129,22 @@  static struct pxamci_platform_data csb726_mci = {
 	.detect_delay_ms	= 500,
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
 	/* FIXME setpower */
-	.gpio_card_detect	= CSB726_GPIO_MMC_DETECT,
-	.gpio_card_ro		= CSB726_GPIO_MMC_RO,
 	.gpio_power		= -1,
 };
 
+static struct gpiod_lookup_table csb726_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 100 */
+		GPIO_LOOKUP("gpio-pxa", CSB726_GPIO_MMC_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 101 */
+		GPIO_LOOKUP("gpio-pxa", CSB726_GPIO_MMC_RO,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static struct pxaohci_platform_data csb726_ohci_platform_data = {
 	.port_mode	= PMM_NPS_MODE,
 	.flags		= ENABLE_PORT1 | NO_OC_PROTECTION,
@@ -264,6 +275,7 @@  static void __init csb726_init(void)
 	pxa_set_stuart_info(NULL);
 	pxa_set_i2c_info(NULL);
 	pxa27x_set_i2c_power_info(NULL);
+	gpiod_add_lookup_table(&csb726_mci_gpio_table);
 	pxa_set_mci_info(&csb726_mci);
 	pxa_set_ohci_info(&csb726_ohci_platform_data);
 	pxa_set_ac97_info(NULL);
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 67e37df637f5..e41d94e3c2c3 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -20,6 +20,7 @@ 
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/mfd/da903x.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -546,6 +547,15 @@  static inline void em_x270_init_ohci(void) {}
 #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
 static struct regulator *em_x270_sdio_ldo;
 
+static struct gpiod_lookup_table em_x270_mci_wp_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Write protect on GPIO 95 */
+		GPIO_LOOKUP("gpio-pxa", GPIO95_MMC_WP, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static int em_x270_mci_init(struct device *dev,
 			    irq_handler_t em_x270_detect_int,
 			    void *data)
@@ -567,15 +577,7 @@  static int em_x270_mci_init(struct device *dev,
 		goto err_irq;
 	}
 
-	if (machine_is_em_x270()) {
-		err = gpio_request(GPIO95_MMC_WP, "MMC WP");
-		if (err) {
-			dev_err(dev, "can't request MMC write protect: %d\n",
-				err);
-			goto err_gpio_wp;
-		}
-		gpio_direction_input(GPIO95_MMC_WP);
-	} else {
+	if (!machine_is_em_x270()) {
 		err = gpio_request(GPIO38_SD_PWEN, "sdio power");
 		if (err) {
 			dev_err(dev, "can't request MMC power control : %d\n",
@@ -615,17 +617,10 @@  static void em_x270_mci_exit(struct device *dev, void *data)
 	free_irq(gpio_to_irq(mmc_cd), data);
 	regulator_put(em_x270_sdio_ldo);
 
-	if (machine_is_em_x270())
-		gpio_free(GPIO95_MMC_WP);
-	else
+	if (!machine_is_em_x270())
 		gpio_free(GPIO38_SD_PWEN);
 }
 
-static int em_x270_mci_get_ro(struct device *dev)
-{
-	return gpio_get_value(GPIO95_MMC_WP);
-}
-
 static struct pxamci_platform_data em_x270_mci_platform_data = {
 	.detect_delay_ms	= 250,
 	.ocr_mask		= MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23|
@@ -635,15 +630,13 @@  static struct pxamci_platform_data em_x270_mci_platform_data = {
 	.init 			= em_x270_mci_init,
 	.setpower 		= em_x270_mci_setpower,
 	.exit			= em_x270_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
 static void __init em_x270_init_mmc(void)
 {
 	if (machine_is_em_x270())
-		em_x270_mci_platform_data.get_ro = em_x270_mci_get_ro;
+		gpiod_add_lookup_table(&em_x270_mci_wp_gpio_table);
 
 	pxa_set_mci_info(&em_x270_mci_platform_data);
 }
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index 9c5b2fb054f9..fef80dc401de 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -90,8 +90,6 @@  static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_MMC_PXA
 static struct pxamci_platform_data gumstix_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect 	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 88e0068f92a8..a03b23c2fee9 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -160,8 +160,6 @@  static struct pxafb_mach_info sharp_lm8v31 = {
 
 static struct pxamci_platform_data idp_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 9e132b3e48c6..704a0effba3d 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -20,7 +20,7 @@ 
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/smc91x.h>
@@ -51,8 +51,6 @@ 
 
 #include "generic.h"
 
-#define GPIO_MMC1_CARD_DETECT	mfp_to_gpio(MFP_PIN_GPIO15)
-
 /* Littleton MFP configurations */
 static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
 	/* LCD */
@@ -278,13 +276,21 @@  static inline void littleton_init_keypad(void) {}
 static struct pxamci_platform_data littleton_mci_platform_data = {
 	.detect_delay_ms	= 200,
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO_MMC1_CARD_DETECT,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
+static struct gpiod_lookup_table littleton_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on MFP (gpio-pxa) GPIO 15 */
+		GPIO_LOOKUP("gpio-pxa", 15, "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init littleton_init_mmc(void)
 {
+	gpiod_add_lookup_table(&littleton_mci_gpio_table);
 	pxa_set_mci_info(&littleton_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index fe2ef9b78602..469cbc6b747f 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -440,8 +440,6 @@  static struct pxamci_platform_data lubbock_mci_platform_data = {
 	.init 			= lubbock_mci_init,
 	.get_ro			= lubbock_mci_get_ro,
 	.exit 			= lubbock_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 14c0f80bc9e7..3e515394b20a 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -775,12 +775,22 @@  static struct pxamci_platform_data magician_mci_info = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
 	.init			= magician_mci_init,
 	.exit			= magician_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= EGPIO_MAGICIAN_nSD_READONLY,
 	.gpio_card_ro_invert	= 1,
 	.gpio_power		= EGPIO_MAGICIAN_SD_POWER,
 };
 
+static struct gpiod_lookup_table magician_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/*
+		 * Write protect on EGPIO register 5 index 4, this is
+		 * on the second HTC EGPIO chip which starts at regiser
+		 * 4, so we need offset 8+4=12 on that particular chip.
+		 */
+		GPIO_LOOKUP("htc-egpio-1", 12, "wp", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
 
 /*
  * USB OHCI
@@ -979,6 +989,7 @@  static void __init magician_init(void)
 	i2c_register_board_info(1,
 		ARRAY_AND_SIZE(magician_pwr_i2c_board_info));
 
+	gpiod_add_lookup_table(&magician_mci_gpio_table);
 	pxa_set_mci_info(&magician_mci_info);
 	pxa_set_ohci_info(&magician_ohci_info);
 	pxa_set_udc_info(&magician_udc_info);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index afd62a94fdbf..31142b17d845 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -361,8 +361,6 @@  static struct pxamci_platform_data mainstone_mci_platform_data = {
 	.init 			= mainstone_mci_init,
 	.setpower 		= mainstone_mci_setpower,
 	.exit			= mainstone_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 04dc78d0809f..d2941c256233 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -31,6 +31,7 @@ 
 #include <linux/rtc.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/pda_power.h>
@@ -397,11 +398,20 @@  struct gpio_vbus_mach_info gpio_vbus_data = {
 static struct pxamci_platform_data mioa701_mci_info = {
 	.detect_delay_ms	= 250,
 	.ocr_mask 		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO15_SDIO_INSERT,
-	.gpio_card_ro		= GPIO78_SDIO_RO,
 	.gpio_power		= GPIO91_SDIO_EN,
 };
 
+static struct gpiod_lookup_table mioa701_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 15 */
+		GPIO_LOOKUP("gpio-pxa", 15, "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 78 */
+		GPIO_LOOKUP("gpio-pxa", 78, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 /* FlashRAM */
 static struct resource docg3_resource = {
 	.start = PXA_CS0_PHYS,
@@ -743,6 +753,7 @@  static void __init mioa701_machine_init(void)
 		pr_err("MioA701: Failed to request GPIOs: %d", rc);
 	bootstrap_init();
 	pxa_set_fb_info(NULL, &mioa701_pxafb_info);
+	gpiod_add_lookup_table(&mioa701_mci_gpio_table);
 	pxa_set_mci_info(&mioa701_mci_info);
 	pxa_set_keypad_info(&mioa701_keypad_info);
 	pxa_set_udc_info(&mioa701_udc_info);
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 616b22397d73..d1562e35644c 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -21,7 +21,7 @@ 
 
 #include <linux/serial_8250.h>
 #include <linux/dm9000.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_data/i2c-pxa.h>
 
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
@@ -326,13 +326,23 @@  static mfp_cfg_t mfp_cfg[] __initdata = {
 static struct pxamci_platform_data mxm_8x10_mci_platform_data = {
 	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
 	.detect_delay_ms = 10,
-	.gpio_card_detect = MXM_8X10_SD_nCD,
-	.gpio_card_ro = MXM_8X10_SD_WP,
 	.gpio_power = -1
 };
 
+static struct gpiod_lookup_table mxm_8x10_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		/* Card detect on GPIO 72 */
+		GPIO_LOOKUP("gpio-pxa", 72, "cd", GPIO_ACTIVE_LOW),
+		/* Write protect on GPIO 84 */
+		GPIO_LOOKUP("gpio-pxa", 84, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 void __init mxm_8x10_mmc_init(void)
 {
+	gpiod_add_lookup_table(&mxm_8x10_mci_gpio_table);
 	pxa_set_mci_info(&mxm_8x10_mci_platform_data);
 }
 #endif
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index 1efe9bcf07fa..62b37fecfdcb 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -49,14 +49,14 @@  static struct pxamci_platform_data palm27x_mci_platform_data = {
 	.detect_delay_ms	= 200,
 };
 
-void __init palm27x_mmc_init(int detect, int ro, int power,
-					int power_inverted)
+void __init palm27x_mmc_init(struct gpiod_lookup_table *gtable, int power,
+			     int power_inverted)
 {
-	palm27x_mci_platform_data.gpio_card_detect	= detect;
-	palm27x_mci_platform_data.gpio_card_ro		= ro;
 	palm27x_mci_platform_data.gpio_power		= power;
 	palm27x_mci_platform_data.gpio_power_invert	= power_inverted;
 
+	if (gtable)
+		gpiod_add_lookup_table(gtable);
 	pxa_set_mci_info(&palm27x_mci_platform_data);
 }
 #endif
diff --git a/arch/arm/mach-pxa/palm27x.h b/arch/arm/mach-pxa/palm27x.h
index d4eac3d6ffb5..05e3f04c11e2 100644
--- a/arch/arm/mach-pxa/palm27x.h
+++ b/arch/arm/mach-pxa/palm27x.h
@@ -12,12 +12,16 @@ 
 #ifndef	__INCLUDE_MACH_PALM27X__
 #define	__INCLUDE_MACH_PALM27X__
 
+#include <linux/gpio/machine.h>
+
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
-extern void __init palm27x_mmc_init(int detect, int ro, int power,
-					int power_inverted);
+extern void __init palm27x_mmc_init(struct gpiod_lookup_table *gtable,
+				    int power,
+				    int power_inverted);
 #else
-static inline void palm27x_mmc_init(int detect, int ro, int power,
-					int power_inverted)
+static inline void palm27x_mmc_init(struct gpiod_lookup_table *gtable,
+				    int power,
+				    int power_inverted)
 {}
 #endif
 
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 980f2847f5b5..63d81c1a3103 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -320,6 +320,17 @@  static void __init palmld_map_io(void)
 	iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc));
 }
 
+static struct gpiod_lookup_table palmld_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMLD_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMLD_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init palmld_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config));
@@ -327,8 +338,8 @@  static void __init palmld_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	palm27x_mmc_init(GPIO_NR_PALMLD_SD_DETECT_N, GPIO_NR_PALMLD_SD_READONLY,
-			GPIO_NR_PALMLD_SD_POWER, 0);
+	palm27x_mmc_init(&palmld_mci_gpio_table,
+			 GPIO_NR_PALMLD_SD_POWER, 0);
 	palm27x_pm_init(PALMLD_STR_BASE);
 	palm27x_lcd_init(-1, &palm_320x480_lcd_mode);
 	palm27x_irda_init(GPIO_NR_PALMLD_IR_DISABLE);
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 876144aa3564..81a37116081b 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -182,6 +182,17 @@  static void __init palmt5_reserve(void)
 	memblock_reserve(0xa0200000, 0x1000);
 }
 
+static struct gpiod_lookup_table palmt5_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMT5_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMT5_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init palmt5_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config));
@@ -189,8 +200,8 @@  static void __init palmt5_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	palm27x_mmc_init(GPIO_NR_PALMT5_SD_DETECT_N, GPIO_NR_PALMT5_SD_READONLY,
-			GPIO_NR_PALMT5_SD_POWER, 0);
+	palm27x_mmc_init(&palmt5_mci_gpio_table,
+			 GPIO_NR_PALMT5_SD_POWER, 0);
 	palm27x_pm_init(PALMT5_STR_BASE);
 	palm27x_lcd_init(-1, &palm_320x480_lcd_mode);
 	palm27x_udc_init(GPIO_NR_PALMT5_USB_DETECT_N,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index 18946594a7c8..7b4c686de8c2 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -20,7 +20,7 @@ 
 #include <linux/input.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/ucb1400.h>
 #include <linux/power_supply.h>
@@ -121,13 +121,23 @@  static unsigned long palmtc_pin_config[] __initdata = {
 static struct pxamci_platform_data palmtc_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
 	.gpio_power		= GPIO_NR_PALMTC_SD_POWER,
-	.gpio_card_ro		= GPIO_NR_PALMTC_SD_READONLY,
-	.gpio_card_detect	= GPIO_NR_PALMTC_SD_DETECT_N,
 	.detect_delay_ms	= 200,
 };
 
+static struct gpiod_lookup_table palmtc_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTC_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTC_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init palmtc_mmc_init(void)
 {
+	gpiod_add_lookup_table(&palmtc_mci_gpio_table);
 	pxa_set_mci_info(&palmtc_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 36b46141a28b..77cb2d98cbdd 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -19,6 +19,7 @@ 
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/gpio_keys.h>
+#include <linux/gpio/machine.h>
 #include <linux/input.h>
 #include <linux/pda_power.h>
 #include <linux/pwm.h>
@@ -101,11 +102,20 @@  static unsigned long palmte2_pin_config[] __initdata = {
  ******************************************************************************/
 static struct pxamci_platform_data palmte2_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO_NR_PALMTE2_SD_DETECT_N,
-	.gpio_card_ro		= GPIO_NR_PALMTE2_SD_READONLY,
 	.gpio_power		= GPIO_NR_PALMTE2_SD_POWER,
 };
 
+static struct gpiod_lookup_table palmte2_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTE2_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTE2_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 /******************************************************************************
  * GPIO keys
@@ -354,6 +364,7 @@  static void __init palmte2_init(void)
 	pxa_set_stuart_info(NULL);
 
 	pxa_set_fb_info(NULL, &palmte2_lcd_screen);
+	gpiod_add_lookup_table(&palmte2_mci_gpio_table);
 	pxa_set_mci_info(&palmte2_mci_platform_data);
 	palmte2_udc_init();
 	pxa_set_ac97_info(&palmte2_ac97_pdata);
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index b66b0b11d717..ea44f699240f 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -480,23 +480,44 @@  void __init treo680_gpio_init(void)
 	gpio_free(GPIO_NR_TREO680_LCD_EN_N);
 }
 
+static struct gpiod_lookup_table treo680_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_TREO_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_TREO680_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init treo680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
 	palmphone_common_init();
 	treo680_gpio_init();
-	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
-			GPIO_NR_TREO680_SD_POWER, 0);
+	palm27x_mmc_init(&treo680_mci_gpio_table,
+			 GPIO_NR_TREO680_SD_POWER, 0);
 }
 #endif
 
 #ifdef CONFIG_MACH_CENTRO
+
+static struct gpiod_lookup_table centro685_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_TREO_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init centro_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(centro685_pin_config));
 	palmphone_common_init();
-	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, -1,
-			GPIO_NR_CENTRO_SD_POWER, 1);
+	palm27x_mmc_init(&centro685_mci_gpio_table,
+			 GPIO_NR_CENTRO_SD_POWER, 1);
 }
 #endif
 
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 1d06a8e91d8f..9df7cd84ba7b 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -337,6 +337,17 @@  static void __init palmtx_map_io(void)
 	iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
 }
 
+static struct gpiod_lookup_table palmtx_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTX_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMTX_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init palmtx_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
@@ -344,8 +355,8 @@  static void __init palmtx_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	palm27x_mmc_init(GPIO_NR_PALMTX_SD_DETECT_N, GPIO_NR_PALMTX_SD_READONLY,
-			GPIO_NR_PALMTX_SD_POWER, 0);
+	palm27x_mmc_init(&palmtx_mci_gpio_table,
+			 GPIO_NR_PALMTX_SD_POWER, 0);
 	palm27x_pm_init(PALMTX_STR_BASE);
 	palm27x_lcd_init(-1, &palm_320x480_lcd_mode);
 	palm27x_udc_init(GPIO_NR_PALMTX_USB_DETECT_N,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 4d475f6f4a77..febf5aadbde6 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -386,6 +386,17 @@  static void __init palmz72_camera_init(void)
 static inline void palmz72_camera_init(void) {}
 #endif
 
+static struct gpiod_lookup_table palmz72_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMZ72_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO_NR_PALMZ72_SD_RO,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -396,8 +407,8 @@  static void __init palmz72_init(void)
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	palm27x_mmc_init(GPIO_NR_PALMZ72_SD_DETECT_N, GPIO_NR_PALMZ72_SD_RO,
-			GPIO_NR_PALMZ72_SD_POWER_N, 1);
+	palm27x_mmc_init(&palmz72_mci_gpio_table,
+			 GPIO_NR_PALMZ72_SD_POWER_N, 1);
 	palm27x_lcd_init(-1, &palm_320x320_lcd_mode);
 	palm27x_udc_init(GPIO_NR_PALMZ72_USB_DETECT_N,
 			GPIO_NR_PALMZ72_USB_PULLUP, 0);
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 973568d4b9ec..f76d7665420e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -370,8 +370,6 @@  static struct pxamci_platform_data pcm990_mci_platform_data = {
 	.init 			= pcm990_mci_init,
 	.setpower 		= pcm990_mci_setpower,
 	.exit			= pcm990_mci_exit,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 1adde1251e2b..9b8663ac532f 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -23,6 +23,7 @@ 
 #include <linux/delay.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-pxa.h>
 #include <linux/regulator/machine.h>
@@ -288,11 +289,19 @@  static struct pxamci_platform_data poodle_mci_platform_data = {
 	.init 			= poodle_mci_init,
 	.setpower 		= poodle_mci_setpower,
 	.exit			= poodle_mci_exit,
-	.gpio_card_detect	= POODLE_GPIO_nSD_DETECT,
-	.gpio_card_ro		= POODLE_GPIO_nSD_WP,
 	.gpio_power		= -1,
 };
 
+static struct gpiod_lookup_table poodle_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", POODLE_GPIO_nSD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", POODLE_GPIO_nSD_WP,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
 
 /*
  * Irda
@@ -439,6 +448,7 @@  static void __init poodle_init(void)
 
 	pxa_set_fb_info(&poodle_locomo_device.dev, &poodle_fb_info);
 	pxa_set_udc_info(&udc_info);
+	gpiod_add_lookup_table(&poodle_mci_gpio_table);
 	pxa_set_mci_info(&poodle_mci_platform_data);
 	pxa_set_ficp_info(&poodle_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index bd3c23ad6ce6..19b988d6dc44 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -749,8 +749,6 @@  static struct pxamci_platform_data raumfeld_mci_platform_data = {
 	.init			= raumfeld_mci_init,
 	.exit			= raumfeld_mci_exit,
 	.detect_delay_ms	= 200,
-	.gpio_card_detect	= -1,
-	.gpio_card_ro		= -1,
 	.gpio_power		= -1,
 };
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 5d50025492b7..7a9fe1749d7a 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -18,6 +18,7 @@ 
 #include <linux/delay.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/leds.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-pxa.h>
@@ -615,13 +616,23 @@  static struct pxamci_platform_data spitz_mci_platform_data = {
 	.detect_delay_ms	= 250,
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
 	.setpower		= spitz_mci_setpower,
-	.gpio_card_detect	= SPITZ_GPIO_nSD_DETECT,
-	.gpio_card_ro		= SPITZ_GPIO_nSD_WP,
 	.gpio_power		= -1,
 };
 
+static struct gpiod_lookup_table spitz_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", SPITZ_GPIO_nSD_WP,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init spitz_mmc_init(void)
 {
+	gpiod_add_lookup_table(&spitz_mci_gpio_table);
 	pxa_set_mci_info(&spitz_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index bbea5fa9a140..0bdb414daedd 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -436,8 +436,6 @@  static int imote2_mci_get_ro(struct device *dev)
 static struct pxamci_platform_data imote2_mci_platform_data = {
 	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* default anyway */
 	.get_ro = imote2_mci_get_ro,
-	.gpio_card_detect = -1,
-	.gpio_card_ro	= -1,
 	.gpio_power = -1,
 };
 
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index cb5cd8e78c94..934338b574da 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -31,6 +31,7 @@ 
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/power/gpio-charger.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
@@ -291,11 +292,20 @@  static struct pxamci_platform_data tosa_mci_platform_data = {
 	.ocr_mask       	= MMC_VDD_32_33|MMC_VDD_33_34,
 	.init           	= tosa_mci_init,
 	.exit           	= tosa_mci_exit,
-	.gpio_card_detect	= TOSA_GPIO_nSD_DETECT,
-	.gpio_card_ro		= TOSA_GPIO_SD_WP,
 	.gpio_power		= TOSA_GPIO_PWR_ON,
 };
 
+static struct gpiod_lookup_table tosa_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_nSD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_SD_WP,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 /*
  * Irda
  */
@@ -908,6 +918,7 @@  static void __init tosa_init(void)
 	/* enable batt_fault */
 	PMCR = 0x01;
 
+	gpiod_add_lookup_table(&tosa_mci_gpio_table);
 	pxa_set_mci_info(&tosa_mci_platform_data);
 	pxa_set_ficp_info(&tosa_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 55b8c501b6fc..849f8b0e6651 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -355,8 +355,6 @@  static struct pxamci_platform_data trizeps4_mci_platform_data = {
 	.exit		= trizeps4_mci_exit,
 	.get_ro		= NULL,	/* write-protection not supported */
 	.setpower 	= NULL,	/* power-switching not supported */
-	.gpio_card_detect = -1,
-	.gpio_card_ro	= -1,
 	.gpio_power	= -1,
 };
 
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index f65dfb6e20e2..186c75161df8 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -17,6 +17,7 @@ 
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -241,13 +242,23 @@  static void __init vpac270_onenand_init(void) {}
 static struct pxamci_platform_data vpac270_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
 	.gpio_power		= -1,
-	.gpio_card_detect	= GPIO53_VPAC270_SD_DETECT_N,
-	.gpio_card_ro		= GPIO52_VPAC270_SD_READONLY,
 	.detect_delay_ms	= 200,
 };
 
+static struct gpiod_lookup_table vpac270_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO53_VPAC270_SD_DETECT_N,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", GPIO52_VPAC270_SD_READONLY,
+			    "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init vpac270_mmc_init(void)
 {
+	gpiod_add_lookup_table(&vpac270_mci_gpio_table);
 	pxa_set_mci_info(&vpac270_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 6fffcfc4621e..d2a63c16404e 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -27,6 +27,7 @@ 
 #include <linux/power_supply.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 #include <linux/regulator/machine.h>
@@ -290,14 +291,22 @@  static inline void z2_lcd_init(void) {}
 #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
 static struct pxamci_platform_data z2_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
-	.gpio_card_detect	= GPIO96_ZIPITZ2_SD_DETECT,
 	.gpio_power		= -1,
-	.gpio_card_ro		= -1,
 	.detect_delay_ms	= 200,
 };
 
+static struct gpiod_lookup_table z2_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO96_ZIPITZ2_SD_DETECT,
+			    "cd", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init z2_mmc_init(void)
 {
+	gpiod_add_lookup_table(&z2_mci_gpio_table);
 	pxa_set_mci_info(&z2_mci_platform_data);
 }
 #else
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index d53ea12fc766..8c71e47e33c4 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -663,12 +663,21 @@  static struct pxafb_mach_info zeus_fb_info = {
 static struct pxamci_platform_data zeus_mci_platform_data = {
 	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
 	.detect_delay_ms	= 250,
-	.gpio_card_detect       = ZEUS_MMC_CD_GPIO,
-	.gpio_card_ro           = ZEUS_MMC_WP_GPIO,
 	.gpio_card_ro_invert	= 1,
 	.gpio_power             = -1
 };
 
+static struct gpiod_lookup_table zeus_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", ZEUS_MMC_CD_GPIO,
+			    "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("gpio-pxa", ZEUS_MMC_WP_GPIO,
+			    "wp", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 /*
  * USB Device Controller
  */
@@ -883,6 +892,7 @@  static void __init zeus_init(void)
 	else
 		pxa_set_fb_info(NULL, &zeus_fb_info);
 
+	gpiod_add_lookup_table(&zeus_mci_gpio_table);
 	pxa_set_mci_info(&zeus_mci_platform_data);
 	pxa_set_udc_info(&zeus_udc_info);
 	pxa_set_ac97_info(&zeus_ac97_info);
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 52e70a5c1281..5617f17a91d0 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -19,7 +19,7 @@ 
 #include <linux/leds.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/smc91x.h>
@@ -227,33 +227,58 @@  static inline void zylonite_init_lcd(void) {}
 static struct pxamci_platform_data zylonite_mci_platform_data = {
 	.detect_delay_ms= 200,
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect = EXT_GPIO(0),
-	.gpio_card_ro	= EXT_GPIO(2),
 	.gpio_power	= -1,
 };
 
+static struct gpiod_lookup_table zylonite_mci_gpio_table = {
+	.dev_id = "pxa2xx-mci.0",
+	.table = {
+		GPIO_LOOKUP("pca9539", 0, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("pca9539", 2, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static struct pxamci_platform_data zylonite_mci2_platform_data = {
 	.detect_delay_ms= 200,
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect = EXT_GPIO(1),
-	.gpio_card_ro	= EXT_GPIO(3),
 	.gpio_power	= -1,
 };
 
+static struct gpiod_lookup_table zylonite_mci2_gpio_table = {
+	.dev_id = "pxa2xx-mci.1",
+	.table = {
+		GPIO_LOOKUP("pca9539", 1, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("pca9539", 3, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static struct pxamci_platform_data zylonite_mci3_platform_data = {
 	.detect_delay_ms= 200,
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
-	.gpio_card_detect = EXT_GPIO(30),
-	.gpio_card_ro	= EXT_GPIO(31),
 	.gpio_power	= -1,
 };
 
+static struct gpiod_lookup_table zylonite_mci3_gpio_table = {
+	.dev_id = "pxa2xx-mci.2",
+	.table = {
+		GPIO_LOOKUP("pca9539", 30, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("pca9539", 31, "wp", GPIO_ACTIVE_LOW),
+		{ },
+	},
+};
+
 static void __init zylonite_init_mmc(void)
 {
+	gpiod_add_lookup_table(&zylonite_mci_gpio_table);
 	pxa_set_mci_info(&zylonite_mci_platform_data);
+	gpiod_add_lookup_table(&zylonite_mci2_gpio_table);
 	pxa3xx_set_mci2_info(&zylonite_mci2_platform_data);
-	if (cpu_is_pxa310())
+	if (cpu_is_pxa310()) {
+		gpiod_add_lookup_table(&zylonite_mci3_gpio_table);
 		pxa3xx_set_mci3_info(&zylonite_mci3_platform_data);
+	}
 }
 #else
 static inline void zylonite_init_mmc(void) {}
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index f7ffbf1676b1..a8b6c14f2687 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -33,7 +33,6 @@ 
 #include <linux/gpio.h>
 #include <linux/gfp.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/of_device.h>
 
 #include <asm/sizes.h>
@@ -63,6 +62,7 @@  struct pxamci_host {
 	unsigned int		imask;
 	unsigned int		power_mode;
 	unsigned long		detect_delay_ms;
+	bool			use_ro_gpio;
 	struct pxamci_platform_data *pdata;
 
 	struct mmc_request	*mrq;
@@ -432,7 +432,7 @@  static int pxamci_get_ro(struct mmc_host *mmc)
 {
 	struct pxamci_host *host = mmc_priv(mmc);
 
-	if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro))
+	if (host->use_ro_gpio)
 		return mmc_gpio_get_ro(mmc);
 	if (host->pdata && host->pdata->get_ro)
 		return !!host->pdata->get_ro(mmc_dev(mmc));
@@ -730,8 +730,6 @@  static int pxamci_probe(struct platform_device *pdev)
 	}
 
 	if (host->pdata) {
-		int gpio_cd = host->pdata->gpio_card_detect;
-		int gpio_ro = host->pdata->gpio_card_ro;
 		int gpio_power = host->pdata->gpio_power;
 
 		host->detect_delay_ms = host->pdata->detect_delay_ms;
@@ -749,33 +747,30 @@  static int pxamci_probe(struct platform_device *pdev)
 					      host->pdata->gpio_power_invert);
 		}
 
-		if (gpio_is_valid(gpio_ro)) {
-			ret = mmc_gpio_request_ro(mmc, gpio_ro);
-			if (ret) {
-				dev_err(dev,
-					"Failed requesting gpio_ro %d\n",
-					gpio_ro);
-				goto out;
-			} else {
-				mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
-					0 : MMC_CAP2_RO_ACTIVE_HIGH;
-			}
+		/* FIXME: should we pass detection delay to debounce? */
+		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
+		if (ret && ret != -ENOENT) {
+			dev_err(dev, "Failed requesting gpio_cd\n");
+			goto out;
 		}
 
-		if (gpio_is_valid(gpio_cd))
-			ret = mmc_gpio_request_cd(mmc, gpio_cd, 0);
-		if (ret) {
-			dev_err(dev, "Failed requesting gpio_cd %d\n",
-				gpio_cd);
+		ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+		if (ret && ret != -ENOENT) {
+			dev_err(dev, "Failed requesting gpio_ro\n");
 			goto out;
 		}
+		if (!ret) {
+			host->use_ro_gpio = true;
+			mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
+				0 : MMC_CAP2_RO_ACTIVE_HIGH;
+		}
 
 		if (host->pdata->init)
 			host->pdata->init(dev, pxamci_detect_irq, mmc);
 
 		if (gpio_is_valid(gpio_power) && host->pdata->setpower)
 			dev_warn(dev, "gpio_power and setpower() both defined\n");
-		if (gpio_is_valid(gpio_ro) && host->pdata->get_ro)
+		if (host->use_ro_gpio && host->pdata->get_ro)
 			dev_warn(dev, "gpio_ro and get_ro() both defined\n");
 	}
 
diff --git a/include/linux/platform_data/mmc-pxamci.h b/include/linux/platform_data/mmc-pxamci.h
index 752f97c62ef2..db6c247d42d1 100644
--- a/include/linux/platform_data/mmc-pxamci.h
+++ b/include/linux/platform_data/mmc-pxamci.h
@@ -15,8 +15,6 @@  struct pxamci_platform_data {
 	int (*get_ro)(struct device *);
 	int (*setpower)(struct device *, unsigned int);
 	void (*exit)(struct device *, void *);
-	int gpio_card_detect;			/* gpio detecting card insertion */
-	int gpio_card_ro;			/* gpio detecting read only toggle */
 	bool gpio_card_ro_invert;		/* gpio ro is inverted */
 	int gpio_power;				/* gpio powering up MMC bus */
 	bool gpio_power_invert;			/* gpio power is inverted */