diff mbox series

[01/19,v3] regulator: fixed: Convert to use GPIO descriptor only

Message ID 20180514080640.12515-2-linus.walleij@linaro.org
State Accepted
Commit 6059577cb28d8b15d2b7dad51eb90d885f1ed9ab
Headers show
Series Refactor fixed and GPIO regulators | expand

Commit Message

Linus Walleij May 14, 2018, 8:06 a.m. UTC
As we augmented the regulator core to accept a GPIO descriptor instead
of a GPIO number, we can augment the fixed GPIO regulator to look up
and pass that descriptor directly from device tree or board GPIO
descriptor look up tables.

Some boards just auto-enumerate their fixed regulator platform devices
and I have assumed they get names like "fixed-regulator.0" but it's
pretty hard to guess this. I need some testing from board maintainers to
be sure. Other boards are straight forward, using just plain
"fixed-regulator" (ID -1) or "fixed-regulator.1" hammering down the
device ID.

The OMAP didn't have proper label names on its GPIO chips so I have fixed
this with a separate patch to the GPIO tree, see
commit 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c
"gpio: omap: Give unique labels to each GPIO bank/chip"

It seems the da9055 and da9211 has never got around to actually passing
any enable gpio into its platform data (not the in-tree code anyway) so we
can just decide to simply pass a descriptor instead.

The fixed GPIO-controlled regulator in mach-pxa/ezx.c was confusingly named
"*_dummy_supply_device" while it is a very real device backed by a GPIO
line. There is nothing dummy about it at all, so I renamed it with the
infix *_regulator_* as part of this patch set.

For the patch hunk hitting arch/blackfin I would say I do not expect
testing, review or ACKs anymore so if it works, it works.

The hunk hitting the x86 BCM43xx driver is especially tricky as the number
comes out of SFI which is a mystery to me. I definately need someone to
look at this. (Hi Andy.)

Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> # Check the x86 BCM stuff
Cc: Alexander Shiyan <shc_work@mail.ru> # i.MX boards user
Cc: Haojian Zhuang <haojian.zhuang@gmail.com> # MMP2 maintainer
Cc: Aaro Koskinen <aaro.koskinen@iki.fi> # OMAP1 maintainer
Cc: Tony Lindgren <tony@atomide.com> # OMAP1,2,3 maintainer
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> # EM-X270 maintainer
Cc: Robert Jarzmik <robert.jarzmik@free.fr> # EZX maintainer
Cc: Philipp Zabel <philipp.zabel@gmail.com> # Magician maintainer
Cc: Daniel Mack <zonque@gmail.com> # Raumfeld maintainer
Cc: Marc Zyngier <marc.zyngier@arm.com> # Zeus maintainer
Cc: Geert Uytterhoeven <geert+renesas@glider.be> # SuperH pinctrl/GPIO maintainer
Cc: Russell King <rmk+kernel@armlinux.org.uk> # SA1100
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

---
ChangeLog v2->v3:
- Resending.
ChangeLog v1->v2:
- Rebase the patch on mainline with Blackfin gone and other changes.
- Fix up the new users that appeared in sa1100
- Drop some suplus comments in x86.
---
 arch/arm/mach-imx/mach-mx21ads.c              | 13 +++++++-
 arch/arm/mach-imx/mach-mx27ads.c              | 12 ++++++-
 arch/arm/mach-mmp/brownstone.c                | 12 ++++++-
 arch/arm/mach-omap1/board-ams-delta.c         | 14 +++++++-
 arch/arm/mach-omap2/pdata-quirks.c            | 16 ++++++++-
 arch/arm/mach-pxa/em-x270.c                   |  1 -
 arch/arm/mach-pxa/ezx.c                       | 33 ++++++++++++-------
 arch/arm/mach-pxa/magician.c                  |  2 +-
 arch/arm/mach-pxa/raumfeld.c                  | 12 +++++--
 arch/arm/mach-pxa/zeus.c                      | 23 +++++++++++--
 arch/arm/mach-s3c64xx/mach-crag6410.c         |  1 -
 arch/arm/mach-s3c64xx/mach-smdk6410.c         |  1 -
 arch/arm/mach-sa1100/assabet.c                | 21 ++++++++----
 arch/arm/mach-sa1100/generic.c                |  5 +--
 arch/arm/mach-sa1100/generic.h                |  3 +-
 arch/arm/mach-sa1100/shannon.c                |  4 +--
 arch/sh/boards/mach-ecovec24/setup.c          | 22 +++++++++++--
 .../intel-mid/device_libs/platform_bcm43xx.c  | 17 ++++++++--
 drivers/regulator/fixed-helper.c              |  1 -
 drivers/regulator/fixed.c                     | 33 +++++++++----------
 include/linux/regulator/fixed.h               |  3 --
 21 files changed, 187 insertions(+), 62 deletions(-)

-- 
2.17.0

Comments

Andy Shevchenko May 14, 2018, 11:03 a.m. UTC | #1
On Mon, 2018-05-14 at 10:06 +0200, Linus Walleij wrote:
> As we augmented the regulator core to accept a GPIO descriptor instead

> of a GPIO number, we can augment the fixed GPIO regulator to look up

> and pass that descriptor directly from device tree or board GPIO

> descriptor look up tables.

> 

> Some boards just auto-enumerate their fixed regulator platform devices

> and I have assumed they get names like "fixed-regulator.0" but it's

> pretty hard to guess this. I need some testing from board maintainers

> to

> be sure. Other boards are straight forward, using just plain

> "fixed-regulator" (ID -1) or "fixed-regulator.1" hammering down the

> device ID.

> 

> The OMAP didn't have proper label names on its GPIO chips so I have

> fixed

> this with a separate patch to the GPIO tree, see

> commit 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

> "gpio: omap: Give unique labels to each GPIO bank/chip"

> 

> It seems the da9055 and da9211 has never got around to actually

> passing

> any enable gpio into its platform data (not the in-tree code anyway)

> so we

> can just decide to simply pass a descriptor instead.

> 

> The fixed GPIO-controlled regulator in mach-pxa/ezx.c was confusingly

> named

> "*_dummy_supply_device" while it is a very real device backed by a

> GPIO

> line. There is nothing dummy about it at all, so I renamed it with the

> infix *_regulator_* as part of this patch set.

> 

> For the patch hunk hitting arch/blackfin I would say I do not expect

> testing, review or ACKs anymore so if it works, it works.

> 

> The hunk hitting the x86 BCM43xx driver is especially tricky as the

> number

> comes out of SFI which is a mystery to me. I definately need someone

> to

> look at this. (Hi Andy.)


Since there is no link to repo with a branch and I wasn't Cc'ed to cover
letter, asking here for a such. I would then pull it and test on real
hardware.

The code itself looks good, so:

Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>


for Intel MID bits.

> 

> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> # Check the

> x86 BCM stuff

> Cc: Alexander Shiyan <shc_work@mail.ru> # i.MX boards user

> Cc: Haojian Zhuang <haojian.zhuang@gmail.com> # MMP2 maintainer

> Cc: Aaro Koskinen <aaro.koskinen@iki.fi> # OMAP1 maintainer

> Cc: Tony Lindgren <tony@atomide.com> # OMAP1,2,3 maintainer

> Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> # EM-X270 maintainer

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

> Cc: Philipp Zabel <philipp.zabel@gmail.com> # Magician maintainer

> Cc: Daniel Mack <zonque@gmail.com> # Raumfeld maintainer

> Cc: Marc Zyngier <marc.zyngier@arm.com> # Zeus maintainer

> Cc: Geert Uytterhoeven <geert+renesas@glider.be> # SuperH pinctrl/GPIO

> maintainer

> Cc: Russell King <rmk+kernel@armlinux.org.uk> # SA1100

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

> ---

> ChangeLog v2->v3:

> - Resending.

> ChangeLog v1->v2:

> - Rebase the patch on mainline with Blackfin gone and other changes.

> - Fix up the new users that appeared in sa1100

> - Drop some suplus comments in x86.

> ---

>  arch/arm/mach-imx/mach-mx21ads.c              | 13 +++++++-

>  arch/arm/mach-imx/mach-mx27ads.c              | 12 ++++++-

>  arch/arm/mach-mmp/brownstone.c                | 12 ++++++-

>  arch/arm/mach-omap1/board-ams-delta.c         | 14 +++++++-

>  arch/arm/mach-omap2/pdata-quirks.c            | 16 ++++++++-

>  arch/arm/mach-pxa/em-x270.c                   |  1 -

>  arch/arm/mach-pxa/ezx.c                       | 33 ++++++++++++----

> ---

>  arch/arm/mach-pxa/magician.c                  |  2 +-

>  arch/arm/mach-pxa/raumfeld.c                  | 12 +++++--

>  arch/arm/mach-pxa/zeus.c                      | 23 +++++++++++--

>  arch/arm/mach-s3c64xx/mach-crag6410.c         |  1 -

>  arch/arm/mach-s3c64xx/mach-smdk6410.c         |  1 -

>  arch/arm/mach-sa1100/assabet.c                | 21 ++++++++----

>  arch/arm/mach-sa1100/generic.c                |  5 +--

>  arch/arm/mach-sa1100/generic.h                |  3 +-

>  arch/arm/mach-sa1100/shannon.c                |  4 +--

>  arch/sh/boards/mach-ecovec24/setup.c          | 22 +++++++++++--

>  .../intel-mid/device_libs/platform_bcm43xx.c  | 17 ++++++++--

>  drivers/regulator/fixed-helper.c              |  1 -

>  drivers/regulator/fixed.c                     | 33 +++++++++---------

> -

>  include/linux/regulator/fixed.h               |  3 --

>  21 files changed, 187 insertions(+), 62 deletions(-)

> 

> diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-

> imx/mach-mx21ads.c

> index 5e366824814f..5d3b6b4fe6db 100644

> --- a/arch/arm/mach-imx/mach-mx21ads.c

> +++ b/arch/arm/mach-imx/mach-mx21ads.c

> @@ -18,6 +18,7 @@

>  #include <linux/mtd/mtd.h>

>  #include <linux/mtd/physmap.h>

>  #include <linux/gpio/driver.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/gpio.h>

>  #include <linux/regulator/fixed.h>

>  #include <linux/regulator/machine.h>

> @@ -175,6 +176,7 @@ static struct resource mx21ads_mmgpio_resource =

>  	DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat");

>  

>  static struct bgpio_pdata mx21ads_mmgpio_pdata = {

> +	.label	= "mx21ads-mmgpio",

>  	.base	= MX21ADS_MMGPIO_BASE,

>  	.ngpio	= 16,

>  };

> @@ -203,7 +205,6 @@ static struct regulator_init_data

> mx21ads_lcd_regulator_init_data = {

>  static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = {

>  	.supply_name	= "LCD",

>  	.microvolts	= 3300000,

> -	.gpio		= MX21ADS_IO_LCDON,

>  	.enable_high	= 1,

>  	.init_data	= &mx21ads_lcd_regulator_init_data,

>  };

> @@ -216,6 +217,15 @@ static struct platform_device

> mx21ads_lcd_regulator = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table mx21ads_lcd_regulator_gpiod_table =

> {

> +	.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what

> we get */

> +	.table = {

> +		GPIO_LOOKUP("mx21ads-mmgpio", 9,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  /*

>   * Connected is a portrait Sharp-QVGA display

>   * of type: LQ035Q7DB02

> @@ -311,6 +321,7 @@ static void __init mx21ads_late_init(void)

>  {

>  	imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata);

>  

> +	gpiod_add_lookup_table(&mx21ads_lcd_regulator_gpiod_table);

>  	platform_add_devices(platform_devices,

> ARRAY_SIZE(platform_devices));

>  

>  	mx21ads_cs8900_resources[1].start =

> diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-

> imx/mach-mx27ads.c

> index a04bb094ded1..0fdb88db0cbd 100644

> --- a/arch/arm/mach-imx/mach-mx27ads.c

> +++ b/arch/arm/mach-imx/mach-mx27ads.c

> @@ -16,6 +16,7 @@

>  #include <linux/gpio/driver.h>

>  /* Needed for gpio_to_irq() */

>  #include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/platform_device.h>

>  #include <linux/mtd/mtd.h>

>  #include <linux/mtd/map.h>

> @@ -230,10 +231,17 @@ static struct regulator_init_data

> mx27ads_lcd_regulator_init_data = {

>  static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = {

>  	.supply_name	= "LCD",

>  	.microvolts	= 3300000,

> -	.gpio		= MX27ADS_LCD_GPIO,

>  	.init_data	= &mx27ads_lcd_regulator_init_data,

>  };

>  

> +static struct gpiod_lookup_table mx27ads_lcd_regulator_gpiod_table =

> {

> +	.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what

> we get */

> +	.table = {

> +		GPIO_LOOKUP("LCD", 0, "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static void __init mx27ads_regulator_init(void)

>  {

>  	struct gpio_chip *vchip;

> @@ -247,6 +255,8 @@ static void __init mx27ads_regulator_init(void)

>  	vchip->set		= vgpio_set;

>  	gpiochip_add_data(vchip, NULL);

>  

> +	gpiod_add_lookup_table(&mx27ads_lcd_regulator_gpiod_table);

> +

>  	platform_device_register_data(NULL, "reg-fixed-voltage",

>  				      PLATFORM_DEVID_AUTO,

>  				      &mx27ads_lcd_regulator_pdata,

> diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-

> mmp/brownstone.c

> index d1613b954926..563b5a278d65 100644

> --- a/arch/arm/mach-mmp/brownstone.c

> +++ b/arch/arm/mach-mmp/brownstone.c

> @@ -15,6 +15,7 @@

>  #include <linux/platform_device.h>

>  #include <linux/io.h>

>  #include <linux/gpio-pxa.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/regulator/machine.h>

>  #include <linux/regulator/max8649.h>

>  #include <linux/regulator/fixed.h>

> @@ -148,7 +149,6 @@ static struct regulator_init_data

> brownstone_v_5vp_data = {

>  static struct fixed_voltage_config brownstone_v_5vp = {

>  	.supply_name		= "v_5vp",

>  	.microvolts		= 5000000,

> -	.gpio			= GPIO_5V_ENABLE,

>  	.enable_high		= 1,

>  	.enabled_at_boot	= 1,

>  	.init_data		= &brownstone_v_5vp_data,

> @@ -162,6 +162,15 @@ static struct platform_device

> brownstone_v_5vp_device = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table brownstone_v_5vp_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.1", /* .id set to 1 above */

> +	.table = {

> +		GPIO_LOOKUP("gpio-pxa", GPIO_5V_ENABLE,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static struct max8925_platform_data brownstone_max8925_info = {

>  	.irq_base		= MMP_NR_IRQS,

>  };

> @@ -217,6 +226,7 @@ static void __init brownstone_init(void)

>  	mmp2_add_isram(&mmp2_isram_platdata);

>  

>  	/* enable 5v regulator */

> +	gpiod_add_lookup_table(&brownstone_v_5vp_gpiod_table);

>  	platform_device_register(&brownstone_v_5vp_device);

>  }

>  

> diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-

> omap1/board-ams-delta.c

> index 52e8e53ca154..759fa18f6ab4 100644

> --- a/arch/arm/mach-omap1/board-ams-delta.c

> +++ b/arch/arm/mach-omap1/board-ams-delta.c

> @@ -12,6 +12,7 @@

>   * published by the Free Software Foundation.

>   */

>  #include <linux/gpio/driver.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/gpio.h>

>  #include <linux/kernel.h>

>  #include <linux/init.h>

> @@ -203,6 +204,7 @@ static struct resource latch2_resources[] = {

>  };

>  

>  static struct bgpio_pdata latch2_pdata = {

> +	.label	= "ams-delta-latch2",

>  	.base	= AMS_DELTA_LATCH2_GPIO_BASE,

>  	.ngpio	= AMS_DELTA_LATCH2_NGPIO,

>  };

> @@ -272,7 +274,6 @@ static struct regulator_init_data

> modem_nreset_data = {

>  static struct fixed_voltage_config modem_nreset_config = {

>  	.supply_name		= "modem_nreset",

>  	.microvolts		= 3300000,

> -	.gpio			=

> AMS_DELTA_GPIO_PIN_MODEM_NRESET,

>  	.startup_delay		= 25000,

>  	.enable_high		= 1,

>  	.enabled_at_boot	= 1,

> @@ -287,6 +288,16 @@ static struct platform_device modem_nreset_device

> = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table modem_nreset_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage",

> +	.table = {

> +		/* The AMS_DELTA_GPIO_PIN_MODEM_NRESET is at offset

> 12 */

> +		GPIO_LOOKUP("ams-delta-latch2", 12,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  struct modem_private_data {

>  	struct regulator *regulator;

>  };

> @@ -570,6 +581,7 @@ static int __init late_init(void)

>  

>  	platform_add_devices(late_devices, ARRAY_SIZE(late_devices));

>  

> +	gpiod_add_lookup_table(&modem_nreset_gpiod_table);

>  	err = platform_device_register(&modem_nreset_device);

>  	if (err) {

>  		pr_err("Couldn't register the modem regulator

> device\n");

> diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-

> omap2/pdata-quirks.c

> index 6459816c2879..7d1447204fb8 100644

> --- a/arch/arm/mach-omap2/pdata-quirks.c

> +++ b/arch/arm/mach-omap2/pdata-quirks.c

> @@ -10,6 +10,7 @@

>  #include <linux/clk.h>

>  #include <linux/davinci_emac.h>

>  #include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/init.h>

>  #include <linux/kernel.h>

>  #include <linux/of_platform.h>

> @@ -330,7 +331,6 @@ static struct regulator_init_data pandora_vmmc3 =

> {

>  static struct fixed_voltage_config pandora_vwlan = {

>  	.supply_name		= "vwlan",

>  	.microvolts		= 1800000, /* 1.8V */

> -	.gpio			= PANDORA_WIFI_NRESET_GPIO,

>  	.startup_delay		= 50000, /* 50ms */

>  	.enable_high		= 1,

>  	.init_data		= &pandora_vmmc3,

> @@ -344,6 +344,19 @@ static struct platform_device

> pandora_vwlan_device = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table pandora_vwlan_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.1",

> +	.table = {

> +		/*

> +		 * As this is a low GPIO number it should be at the

> first

> +		 * GPIO bank.

> +		 */

> +		GPIO_LOOKUP("gpio-0-31", PANDORA_WIFI_NRESET_GPIO,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static void pandora_wl1251_init_card(struct mmc_card *card)

>  {

>  	/*

> @@ -405,6 +418,7 @@ static void __init pandora_wl1251_init(void)

>  static void __init omap3_pandora_legacy_init(void)

>  {

>  	platform_device_register(&pandora_backlight);

> +	gpiod_add_lookup_table(&pandora_vwlan_gpiod_table);

>  	platform_device_register(&pandora_vwlan_device);

>  	omap_hsmmc_init(pandora_mmc3);

>  	omap_hsmmc_late_init(pandora_mmc3);

> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c

> index 49022ad338e9..6d7d93981098 100644

> --- a/arch/arm/mach-pxa/em-x270.c

> +++ b/arch/arm/mach-pxa/em-x270.c

> @@ -987,7 +987,6 @@ static struct fixed_voltage_config

> camera_dummy_config = {

>  	.supply_name		= "camera_vdd",

>  	.input_supply		= "vcc cam",

>  	.microvolts		= 2800000,

> -	.gpio			= -1,

>  	.enable_high		= 0,

>  	.init_data		= &camera_dummy_initdata,

>  };

> diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c

> index 2c90b58f347d..2b4bd6d94855 100644

> --- a/arch/arm/mach-pxa/ezx.c

> +++ b/arch/arm/mach-pxa/ezx.c

> @@ -21,6 +21,7 @@

>  #include <linux/regulator/fixed.h>

>  #include <linux/input.h>

>  #include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/gpio_keys.h>

>  #include <linux/leds-lp3944.h>

>  #include <linux/platform_data/i2c-pxa.h>

> @@ -698,31 +699,39 @@ static struct pxa27x_keypad_platform_data

> e2_keypad_platform_data = {

>  

>  #if defined(CONFIG_MACH_EZX_A780) || defined(CONFIG_MACH_EZX_A910)

>  /* camera */

> -static struct regulator_consumer_supply camera_dummy_supplies[] = {

> +static struct regulator_consumer_supply camera_regulator_supplies[] =

> {

>  	REGULATOR_SUPPLY("vdd", "0-005d"),

>  };

>  

> -static struct regulator_init_data camera_dummy_initdata = {

> -	.consumer_supplies = camera_dummy_supplies,

> -	.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies),

> +static struct regulator_init_data camera_regulator_initdata = {

> +	.consumer_supplies = camera_regulator_supplies,

> +	.num_consumer_supplies =

> ARRAY_SIZE(camera_regulator_supplies),

>  	.constraints = {

>  		.valid_ops_mask = REGULATOR_CHANGE_STATUS,

>  	},

>  };

>  

> -static struct fixed_voltage_config camera_dummy_config = {

> +static struct fixed_voltage_config camera_regulator_config = {

>  	.supply_name		= "camera_vdd",

>  	.microvolts		= 2800000,

> -	.gpio			= GPIO50_nCAM_EN,

>  	.enable_high		= 0,

> -	.init_data		= &camera_dummy_initdata,

> +	.init_data		= &camera_regulator_initdata,

>  };

>  

> -static struct platform_device camera_supply_dummy_device = {

> +static struct platform_device camera_supply_regulator_device = {

>  	.name	= "reg-fixed-voltage",

>  	.id	= 1,

>  	.dev	= {

> -		.platform_data = &camera_dummy_config,

> +		.platform_data = &camera_regulator_config,

> +	},

> +};

> +

> +static struct gpiod_lookup_table camera_supply_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.1",

> +	.table = {

> +		GPIO_LOOKUP("gpio-pxa", GPIO50_nCAM_EN,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

>  	},

>  };

>  #endif

> @@ -800,7 +809,7 @@ static struct i2c_board_info a780_i2c_board_info[]

> = {

>  

>  static struct platform_device *a780_devices[] __initdata = {

>  	&a780_gpio_keys,

> -	&camera_supply_dummy_device,

> +	&camera_supply_regulator_device,

>  };

>  

>  static void __init a780_init(void)

> @@ -823,6 +832,7 @@ static void __init a780_init(void)

>  	if (a780_camera_init() == 0)

>  		pxa_set_camera_info(&a780_pxacamera_platform_data);

>  

> +	gpiod_add_lookup_table(&camera_supply_gpiod_table);

>  	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));

>  	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));

>  	platform_add_devices(ARRAY_AND_SIZE(a780_devices));

> @@ -892,6 +902,7 @@ static void __init e680_init(void)

>  

>  	pxa_set_keypad_info(&e680_keypad_platform_data);

>  

> +	gpiod_add_lookup_table(&camera_supply_gpiod_table);

>  	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));

>  	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));

>  	platform_add_devices(ARRAY_AND_SIZE(e680_devices));

> @@ -1098,7 +1109,7 @@ static struct i2c_board_info __initdata

> a910_i2c_board_info[] = {

>  

>  static struct platform_device *a910_devices[] __initdata = {

>  	&a910_gpio_keys,

> -	&camera_supply_dummy_device,

> +	&camera_supply_regulator_device,

>  };

>  

>  static void __init a910_init(void)

> diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-

> pxa/magician.c

> index c5325d1ae77b..14c0f80bc9e7 100644

> --- a/arch/arm/mach-pxa/magician.c

> +++ b/arch/arm/mach-pxa/magician.c

> @@ -18,6 +18,7 @@

>  #include <linux/platform_device.h>

>  #include <linux/delay.h>

>  #include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/gpio_keys.h>

>  #include <linux/input.h>

>  #include <linux/mfd/htc-pasic3.h>

> @@ -696,7 +697,6 @@ static struct regulator_init_data

> vads7846_regulator = {

>  static struct fixed_voltage_config vads7846 = {

>  	.supply_name	= "vads7846",

>  	.microvolts	= 3300000, /* probably */

> -	.gpio		= -EINVAL,

>  	.startup_delay	= 0,

>  	.init_data	= &vads7846_regulator,

>  };

> diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-

> pxa/raumfeld.c

> index 034345546f84..ee766e4ebddc 100644

> --- a/arch/arm/mach-pxa/raumfeld.c

> +++ b/arch/arm/mach-pxa/raumfeld.c

> @@ -886,7 +886,6 @@ static struct regulator_init_data

> audio_va_initdata = {

>  static struct fixed_voltage_config audio_va_config = {

>  	.supply_name		= "audio_va",

>  	.microvolts		= 5000000,

> -	.gpio			= GPIO_AUDIO_VA_ENABLE,

>  	.enable_high		= 1,

>  	.enabled_at_boot	= 0,

>  	.init_data		= &audio_va_initdata,

> @@ -900,6 +899,15 @@ static struct platform_device audio_va_device = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table audio_va_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.0",

> +	.table = {

> +		GPIO_LOOKUP("gpio-pxa", GPIO_AUDIO_VA_ENABLE,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  /* Dummy supplies for Codec's VD/VLC */

>  

>  static struct regulator_consumer_supply audio_dummy_supplies[] = {

> @@ -918,7 +926,6 @@ static struct regulator_init_data

> audio_dummy_initdata = {

>  static struct fixed_voltage_config audio_dummy_config = {

>  	.supply_name		= "audio_vd",

>  	.microvolts		= 3300000,

> -	.gpio			= -1,

>  	.init_data		= &audio_dummy_initdata,

>  };

>  

> @@ -1033,6 +1040,7 @@ static void __init raumfeld_audio_init(void)

>  	else

>  		gpio_direction_output(GPIO_MCLK_RESET, 1);

>  

> +	gpiod_add_lookup_table(&audio_va_gpiod_table);

>  	platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices))

> ;

>  }

>  

> diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c

> index e3851795d6d7..58e05afcece0 100644

> --- a/arch/arm/mach-pxa/zeus.c

> +++ b/arch/arm/mach-pxa/zeus.c

> @@ -17,6 +17,7 @@

>  #include <linux/irq.h>

>  #include <linux/pm.h>

>  #include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/serial_8250.h>

>  #include <linux/dm9000.h>

>  #include <linux/mmc/host.h>

> @@ -410,7 +411,6 @@ static struct regulator_init_data

> can_regulator_init_data = {

>  static struct fixed_voltage_config can_regulator_pdata = {

>  	.supply_name	= "CAN_SHDN",

>  	.microvolts	= 3300000,

> -	.gpio		= ZEUS_CAN_SHDN_GPIO,

>  	.init_data	= &can_regulator_init_data,

>  };

>  

> @@ -422,6 +422,15 @@ static struct platform_device

> can_regulator_device = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table can_regulator_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.0",

> +	.table = {

> +		GPIO_LOOKUP("gpio-pxa", ZEUS_CAN_SHDN_GPIO,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static struct mcp251x_platform_data zeus_mcp2515_pdata = {

>  	.oscillator_frequency	= 16*1000*1000,

>  };

> @@ -538,7 +547,6 @@ static struct regulator_init_data

> zeus_ohci_regulator_data = {

>  static struct fixed_voltage_config zeus_ohci_regulator_config = {

>  	.supply_name		= "vbus2",

>  	.microvolts		= 5000000, /* 5.0V */

> -	.gpio			= ZEUS_USB2_PWREN_GPIO,

>  	.enable_high		= 1,

>  	.startup_delay		= 0,

>  	.init_data		= &zeus_ohci_regulator_data,

> @@ -552,6 +560,15 @@ static struct platform_device

> zeus_ohci_regulator_device = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table zeus_ohci_regulator_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.0",

> +	.table = {

> +		GPIO_LOOKUP("gpio-pxa", ZEUS_USB2_PWREN_GPIO,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static struct pxaohci_platform_data zeus_ohci_platform_data = {

>  	.port_mode	= PMM_NPS_MODE,

>  	/* Clear Power Control Polarity Low and set Power Sense

> @@ -855,6 +872,8 @@ static void __init zeus_init(void)

>  

>  	pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));

>  

> +	gpiod_add_lookup_table(&can_regulator_gpiod_table);

> +	gpiod_add_lookup_table(&zeus_ohci_regulator_gpiod_table);

>  	platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));

>  

>  	zeus_register_ohci();

> diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-

> s3c64xx/mach-crag6410.c

> index f04650297487..379424d72ae7 100644

> --- a/arch/arm/mach-s3c64xx/mach-crag6410.c

> +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c

> @@ -352,7 +352,6 @@ static struct fixed_voltage_config wallvdd_pdata =

> {

>  	.supply_name = "WALLVDD",

>  	.microvolts = 5000000,

>  	.init_data = &wallvdd_data,

> -	.gpio = -EINVAL,

>  };

>  

>  static struct platform_device wallvdd_device = {

> diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-

> s3c64xx/mach-smdk6410.c

> index c46fa5dfd2e0..908e5aa831c8 100644

> --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c

> +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c

> @@ -222,7 +222,6 @@ static struct fixed_voltage_config

> smdk6410_b_pwr_5v_pdata = {

>  	.supply_name = "B_PWR_5V",

>  	.microvolts = 5000000,

>  	.init_data = &smdk6410_b_pwr_5v_data,

> -	.gpio = -EINVAL,

>  };

>  

>  static struct platform_device smdk6410_b_pwr_5v = {

> diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-

> sa1100/assabet.c

> index 575ec085cffa..dbb53c520165 100644

> --- a/arch/arm/mach-sa1100/assabet.c

> +++ b/arch/arm/mach-sa1100/assabet.c

> @@ -101,7 +101,7 @@ static int __init assabet_init_gpio(void __iomem

> *reg, u32 def_val)

>  

>  	assabet_bcr_gc = gc;

>  

> -	return gc->base;

> +	return 0;

>  }

>  

>  /*

> @@ -471,6 +471,14 @@ static struct fixed_voltage_config

> assabet_cf_vcc_pdata __initdata = {

>  	.enable_high = 1,

>  };

>  

> +static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {

> +	.dev_id = "reg-fixed-voltage.0",

> +	.table = {

> +		GPIO_LOOKUP("assabet", 0, "enable",

> GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static void __init assabet_init(void)

>  {

>  	/*

> @@ -517,9 +525,11 @@ static void __init assabet_init(void)

>  			neponset_resources,

> ARRAY_SIZE(neponset_resources));

>  #endif

>  	} else {

> +		gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);

>  		sa11x0_register_fixed_regulator(0,

> &assabet_cf_vcc_pdata,

> -					 assabet_cf_vcc_consumers,

> -					 ARRAY_SIZE(assabet_cf_vcc_co

> nsumers));

> +					assabet_cf_vcc_consumers,

> +					ARRAY_SIZE(assabet_cf_vcc_con

> sumers),

> +					true);

>  

>  	}

>  

> @@ -802,7 +812,6 @@ fs_initcall(assabet_leds_init);

>  

>  void __init assabet_init_irq(void)

>  {

> -	unsigned int assabet_gpio_base;

>  	u32 def_val;

>  

>  	sa1100_init_irq();

> @@ -817,9 +826,7 @@ void __init assabet_init_irq(void)

>  	 *

>  	 * This must precede any driver calls to BCR_set() or

> BCR_clear().

>  	 */

> -	assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR,

> def_val);

> -

> -	assabet_cf_vcc_pdata.gpio = assabet_gpio_base + 0;

> +	assabet_init_gpio((void *)&ASSABET_BCR, def_val);

>  }

>  

>  MACHINE_START(ASSABET, "Intel-Assabet")

> diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-

> sa1100/generic.c

> index 7167ddf84a0e..800321c6cbd8 100644

> --- a/arch/arm/mach-sa1100/generic.c

> +++ b/arch/arm/mach-sa1100/generic.c

> @@ -348,7 +348,8 @@ void __init sa11x0_init_late(void)

>  

>  int __init sa11x0_register_fixed_regulator(int n,

>  	struct fixed_voltage_config *cfg,

> -	struct regulator_consumer_supply *supplies, unsigned

> num_supplies)

> +	struct regulator_consumer_supply *supplies, unsigned

> num_supplies,

> +	bool uses_gpio)

>  {

>  	struct regulator_init_data *id;

>  

> @@ -356,7 +357,7 @@ int __init sa11x0_register_fixed_regulator(int n,

>  	if (!cfg->init_data)

>  		return -ENOMEM;

>  

> -	if (cfg->gpio < 0)

> +	if (!uses_gpio)

>  		id->constraints.always_on = 1;

>  	id->constraints.name = cfg->supply_name;

>  	id->constraints.min_uV = cfg->microvolts;

> diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-

> sa1100/generic.h

> index 5f3cb52fa6ab..158a4fd5ca24 100644

> --- a/arch/arm/mach-sa1100/generic.h

> +++ b/arch/arm/mach-sa1100/generic.h

> @@ -54,4 +54,5 @@ void sa11x0_register_pcmcia(int socket, struct

> gpiod_lookup_table *);

>  struct fixed_voltage_config;

>  struct regulator_consumer_supply;

>  int sa11x0_register_fixed_regulator(int n, struct

> fixed_voltage_config *cfg,

> -	struct regulator_consumer_supply *supplies, unsigned

> num_supplies);

> +	struct regulator_consumer_supply *supplies, unsigned

> num_supplies,

> +	bool uses_gpio);

> diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-

> sa1100/shannon.c

> index 22f7fe0b809f..5bc82e2671c6 100644

> --- a/arch/arm/mach-sa1100/shannon.c

> +++ b/arch/arm/mach-sa1100/shannon.c

> @@ -102,14 +102,14 @@ static struct fixed_voltage_config

> shannon_cf_vcc_pdata __initdata = {

>  	.supply_name = "cf-power",

>  	.microvolts = 3300000,

>  	.enabled_at_boot = 1,

> -	.gpio = -EINVAL,

>  };

>  

>  static void __init shannon_init(void)

>  {

>  	sa11x0_register_fixed_regulator(0, &shannon_cf_vcc_pdata,

>  					shannon_cf_vcc_consumers,

> -					ARRAY_SIZE(shannon_cf_vcc_con

> sumers));

> +					ARRAY_SIZE(shannon_cf_vcc_con

> sumers),

> +					false);

>  	sa11x0_register_pcmcia(0, &shannon_pcmcia0_gpio_table);

>  	sa11x0_register_pcmcia(1, &shannon_pcmcia1_gpio_table);

>  	sa11x0_ppc_configure_mcp();

> diff --git a/arch/sh/boards/mach-ecovec24/setup.c

> b/arch/sh/boards/mach-ecovec24/setup.c

> index adc61d14172c..c296b5c399b7 100644

> --- a/arch/sh/boards/mach-ecovec24/setup.c

> +++ b/arch/sh/boards/mach-ecovec24/setup.c

> @@ -633,7 +633,6 @@ static struct regulator_init_data

> cn12_power_init_data = {

>  static struct fixed_voltage_config cn12_power_info = {

>  	.supply_name = "CN12 SD/MMC Vdd",

>  	.microvolts = 3300000,

> -	.gpio = GPIO_PTB7,

>  	.enable_high = 1,

>  	.init_data = &cn12_power_init_data,

>  };

> @@ -646,6 +645,16 @@ static struct platform_device cn12_power = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table cn12_power_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.0",

> +	.table = {

> +		/* Offset 7 on port B */

> +		GPIO_LOOKUP("sh7724_pfc", GPIO_PTB7,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)

>  /* SDHI0 */

>  static struct regulator_consumer_supply sdhi0_power_consumers[] =

> @@ -665,7 +674,6 @@ static struct regulator_init_data

> sdhi0_power_init_data = {

>  static struct fixed_voltage_config sdhi0_power_info = {

>  	.supply_name = "CN11 SD/MMC Vdd",

>  	.microvolts = 3300000,

> -	.gpio = GPIO_PTB6,

>  	.enable_high = 1,

>  	.init_data = &sdhi0_power_init_data,

>  };

> @@ -678,6 +686,16 @@ static struct platform_device sdhi0_power = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table sdhi0_power_gpiod_table = {

> +	.dev_id = "reg-fixed-voltage.1",

> +	.table = {

> +		/* Offset 6 on port B */

> +		GPIO_LOOKUP("sh7724_pfc", GPIO_PTB6,

> +			    "enable", GPIO_ACTIVE_HIGH),

> +		{ },

> +	},

> +};

> +

>  static struct tmio_mmc_data sdhi0_info = {

>  	.chan_priv_tx	= (void *)SHDMA_SLAVE_SDHI0_TX,

>  	.chan_priv_rx	= (void *)SHDMA_SLAVE_SDHI0_RX,

> diff --git a/arch/x86/platform/intel-

> mid/device_libs/platform_bcm43xx.c b/arch/x86/platform/intel-

> mid/device_libs/platform_bcm43xx.c

> index 4392c15ed9e0..fc77d69e51d7 100644

> --- a/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c

> +++ b/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c

> @@ -10,7 +10,7 @@

>   * of the License.

>   */

>  

> -#include <linux/gpio.h>

> +#include <linux/gpio/machine.h>

>  #include <linux/platform_device.h>

>  #include <linux/regulator/machine.h>

>  #include <linux/regulator/fixed.h>

> @@ -43,7 +43,6 @@ static struct fixed_voltage_config bcm43xx_vmmc = {

>  	 * real voltage and signaling are still 1.8V.

>  	 */

>  	.microvolts		= 2000000,		/* 1.8V

> */

> -	.gpio			= -EINVAL,

>  	.startup_delay		= 250 * 1000,		/*

> 250ms */

>  	.enable_high		= 1,			/*

> active high */

>  	.enabled_at_boot	= 0,			/*

> disabled at boot */

> @@ -58,11 +57,23 @@ static struct platform_device

> bcm43xx_vmmc_regulator = {

>  	},

>  };

>  

> +static struct gpiod_lookup_table bcm43xx_vmmc_gpio_table = {

> +	.dev_id	= "reg-fixed-voltage.0",

> +	.table	= {

> +		GPIO_LOOKUP("0000:00:0c.0", -1, "enable",

> GPIO_ACTIVE_LOW),

> +		{}

> +	},

> +};

> +

>  static int __init bcm43xx_regulator_register(void)

>  {

> +	struct gpiod_lookup_table *table = &bcm43xx_vmmc_gpio_table;

> +	struct gpiod_lookup *lookup = table->table;

>  	int ret;

>  

> -	bcm43xx_vmmc.gpio =

> get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);

> +	lookup[0].chip_hwnum =

> get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);

> +	gpiod_add_lookup_table(table);

> +

>  	ret = platform_device_register(&bcm43xx_vmmc_regulator);

>  	if (ret) {

>  		pr_err("%s: vmmc regulator register failed\n",

> __func__);

> diff --git a/drivers/regulator/fixed-helper.c

> b/drivers/regulator/fixed-helper.c

> index 777fac6fb4cb..2c6098e6f4bc 100644

> --- a/drivers/regulator/fixed-helper.c

> +++ b/drivers/regulator/fixed-helper.c

> @@ -43,7 +43,6 @@ struct platform_device

> *regulator_register_always_on(int id, const char *name,

>  	}

>  

>  	data->cfg.microvolts = uv;

> -	data->cfg.gpio = -EINVAL;

>  	data->cfg.enabled_at_boot = 1;

>  	data->cfg.init_data = &data->init_data;

>  

> diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c

> index 988a7472c2ab..1142f195529b 100644

> --- a/drivers/regulator/fixed.c

> +++ b/drivers/regulator/fixed.c

> @@ -24,10 +24,9 @@

>  #include <linux/platform_device.h>

>  #include <linux/regulator/driver.h>

>  #include <linux/regulator/fixed.h>

> -#include <linux/gpio.h>

> +#include <linux/gpio/consumer.h>

>  #include <linux/slab.h>

>  #include <linux/of.h>

> -#include <linux/of_gpio.h>

>  #include <linux/regulator/of_regulator.h>

>  #include <linux/regulator/machine.h>

>  

> @@ -78,10 +77,6 @@ of_get_fixed_voltage_config(struct device *dev,

>  	if (init_data->constraints.boot_on)

>  		config->enabled_at_boot = true;

>  

> -	config->gpio = of_get_named_gpio(np, "gpio", 0);

> -	if ((config->gpio < 0) && (config->gpio != -ENOENT))

> -		return ERR_PTR(config->gpio);

> -

>  	of_property_read_u32(np, "startup-delay-us", &config-

> >startup_delay);

>  

>  	config->enable_high = of_property_read_bool(np, "enable-

> active-high");

> @@ -102,6 +97,7 @@ static int reg_fixed_voltage_probe(struct

> platform_device *pdev)

>  	struct fixed_voltage_config *config;

>  	struct fixed_voltage_data *drvdata;

>  	struct regulator_config cfg = { };

> +	enum gpiod_flags gflags;

>  	int ret;

>  

>  	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct

> fixed_voltage_data),

> @@ -150,25 +146,28 @@ static int reg_fixed_voltage_probe(struct

> platform_device *pdev)

>  

>  	drvdata->desc.fixed_uV = config->microvolts;

>  

> -	if (gpio_is_valid(config->gpio)) {

> -		cfg.ena_gpio = config->gpio;

> -		if (pdev->dev.of_node)

> -			cfg.ena_gpio_initialized = true;

> -	}

>  	cfg.ena_gpio_invert = !config->enable_high;

>  	if (config->enabled_at_boot) {

>  		if (config->enable_high)

> -			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;

> +			gflags = GPIOD_OUT_HIGH;

>  		else

> -			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;

> +			gflags = GPIOD_OUT_LOW;

>  	} else {

>  		if (config->enable_high)

> -			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;

> +			gflags = GPIOD_OUT_LOW;

>  		else

> -			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;

> +			gflags = GPIOD_OUT_HIGH;

>  	}

> -	if (config->gpio_is_open_drain)

> -		cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;

> +	if (config->gpio_is_open_drain) {

> +		if (gflags == GPIOD_OUT_HIGH)

> +			gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;

> +		else

> +			gflags = GPIOD_OUT_LOW_OPEN_DRAIN;

> +	}

> +

> +	cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL,

> gflags);

> +	if (IS_ERR(cfg.ena_gpiod))

> +		return PTR_ERR(cfg.ena_gpiod);

>  

>  	cfg.dev = &pdev->dev;

>  	cfg.init_data = config->init_data;

> diff --git a/include/linux/regulator/fixed.h

> b/include/linux/regulator/fixed.h

> index 48918be649d4..1a4340ed8e2b 100644

> --- a/include/linux/regulator/fixed.h

> +++ b/include/linux/regulator/fixed.h

> @@ -24,8 +24,6 @@ struct regulator_init_data;

>   * @supply_name:	Name of the regulator supply

>   * @input_supply:	Name of the input regulator supply

>   * @microvolts:		Output voltage of regulator

> - * @gpio:		GPIO to use for enable control

> - * 			set to -EINVAL if not used

>   * @startup_delay:	Start-up time in microseconds

>   * @gpio_is_open_drain: Gpio pin is open drain or normal type.

>   *			If it is open drain type then HIGH will be

> set

> @@ -49,7 +47,6 @@ struct fixed_voltage_config {

>  	const char *supply_name;

>  	const char *input_supply;

>  	int microvolts;

> -	int gpio;

>  	unsigned startup_delay;

>  	unsigned gpio_is_open_drain:1;

>  	unsigned enable_high:1;


-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy
Geert Uytterhoeven May 14, 2018, 11:49 a.m. UTC | #2
Hi Linus,

On Mon, May 14, 2018 at 10:06 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> As we augmented the regulator core to accept a GPIO descriptor instead

> of a GPIO number, we can augment the fixed GPIO regulator to look up

> and pass that descriptor directly from device tree or board GPIO

> descriptor look up tables.

>

> Some boards just auto-enumerate their fixed regulator platform devices

> and I have assumed they get names like "fixed-regulator.0" but it's

> pretty hard to guess this. I need some testing from board maintainers to

> be sure. Other boards are straight forward, using just plain

> "fixed-regulator" (ID -1) or "fixed-regulator.1" hammering down the

> device ID.

>

> The OMAP didn't have proper label names on its GPIO chips so I have fixed

> this with a separate patch to the GPIO tree, see

> commit 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

> "gpio: omap: Give unique labels to each GPIO bank/chip"

>

> It seems the da9055 and da9211 has never got around to actually passing

> any enable gpio into its platform data (not the in-tree code anyway) so we

> can just decide to simply pass a descriptor instead.

>

> The fixed GPIO-controlled regulator in mach-pxa/ezx.c was confusingly named

> "*_dummy_supply_device" while it is a very real device backed by a GPIO

> line. There is nothing dummy about it at all, so I renamed it with the

> infix *_regulator_* as part of this patch set.

>

> For the patch hunk hitting arch/blackfin I would say I do not expect

> testing, review or ACKs anymore so if it works, it works.

>

> The hunk hitting the x86 BCM43xx driver is especially tricky as the number

> comes out of SFI which is a mystery to me. I definately need someone to

> look at this. (Hi Andy.)


Thanks for your patch!

> Cc: Geert Uytterhoeven <geert+renesas@glider.be> # SuperH pinctrl/GPIO maintainer


IIRC, Jacopo (CC) has an Ecovec24.

> --- a/arch/sh/boards/mach-ecovec24/setup.c

> +++ b/arch/sh/boards/mach-ecovec24/setup.c

> @@ -633,7 +633,6 @@ static struct regulator_init_data cn12_power_init_data = {

>  static struct fixed_voltage_config cn12_power_info = {

>         .supply_name = "CN12 SD/MMC Vdd",

>         .microvolts = 3300000,

> -       .gpio = GPIO_PTB7,

>         .enable_high = 1,

>         .init_data = &cn12_power_init_data,

>  };

> @@ -646,6 +645,16 @@ static struct platform_device cn12_power = {

>         },

>  };

>

> +static struct gpiod_lookup_table cn12_power_gpiod_table = {

> +       .dev_id = "reg-fixed-voltage.0",

> +       .table = {

> +               /* Offset 7 on port B */

> +               GPIO_LOOKUP("sh7724_pfc", GPIO_PTB7,

> +                           "enable", GPIO_ACTIVE_HIGH),

> +               { },

> +       },

> +};

> +

>  #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)

>  /* SDHI0 */

>  static struct regulator_consumer_supply sdhi0_power_consumers[] =

> @@ -665,7 +674,6 @@ static struct regulator_init_data sdhi0_power_init_data = {

>  static struct fixed_voltage_config sdhi0_power_info = {

>         .supply_name = "CN11 SD/MMC Vdd",

>         .microvolts = 3300000,

> -       .gpio = GPIO_PTB6,

>         .enable_high = 1,

>         .init_data = &sdhi0_power_init_data,

>  };

> @@ -678,6 +686,16 @@ static struct platform_device sdhi0_power = {

>         },

>  };

>

> +static struct gpiod_lookup_table sdhi0_power_gpiod_table = {

> +       .dev_id = "reg-fixed-voltage.1",

> +       .table = {

> +               /* Offset 6 on port B */

> +               GPIO_LOOKUP("sh7724_pfc", GPIO_PTB6,

> +                           "enable", GPIO_ACTIVE_HIGH),

> +               { },

> +       },

> +};

> +

>  static struct tmio_mmc_data sdhi0_info = {

>         .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,

>         .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,


No calls to gpiod_add_lookup_table() to add to arch_setup()?

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Tony Lindgren May 17, 2018, 7:50 p.m. UTC | #3
* Linus Walleij <linus.walleij@linaro.org> [180514 08:08]:
> As we augmented the regulator core to accept a GPIO descriptor instead

> of a GPIO number, we can augment the fixed GPIO regulator to look up

> and pass that descriptor directly from device tree or board GPIO

> descriptor look up tables.

...
>  arch/arm/mach-omap1/board-ams-delta.c         | 14 +++++++-

>  arch/arm/mach-omap2/pdata-quirks.c            | 16 ++++++++-


Looks OK to me:

Acked-by: Tony Lindgren <tony@atomide.com>
Linus Walleij May 21, 2018, 11:27 a.m. UTC | #4
On Mon, May 14, 2018 at 1:03 PM, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> On Mon, 2018-05-14 at 10:06 +0200, Linus Walleij wrote:


>> The hunk hitting the x86 BCM43xx driver is especially tricky as the

>> number

>> comes out of SFI which is a mystery to me. I definately need someone

>> to

>> look at this. (Hi Andy.)

>

> Since there is no link to repo with a branch and I wasn't Cc'ed to cover

> letter, asking here for a such. I would then pull it and test on real

> hardware.


I'm sorry about this.
This branch:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/log/?h=gpio-descriptors-regulator

Has all the patches.

git pull git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
gpio-descriptors-regulator

will bring in the patches to a testing branch.

> The code itself looks good, so:

>

> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

>

> for Intel MID bits.


Thanks!

Yours,
Linus Walleij
Arnd Bergmann May 30, 2018, 9:27 p.m. UTC | #5
On Mon, May 14, 2018 at 10:06 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:


> @@ -892,6 +902,7 @@ static void __init e680_init(void)

>

>         pxa_set_keypad_info(&e680_keypad_platform_data);

>

> +       gpiod_add_lookup_table(&camera_supply_gpiod_table);

>         pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));

>         platform_add_devices(ARRAY_AND_SIZE(ezx_devices));

>         platform_add_devices(ARRAY_AND_SIZE(e680_devices));

> @@ -1098,7 +1109,7 @@ static struct i2c_board_info __initdata a910_i2c_board_info[] = {

>

>  static struct platform_device *a910_devices[] __initdata = {

>         &a910_gpio_keys,

> -       &camera_supply_dummy_device,

> +       &camera_supply_regulator_device,

>  };

>


This part is wrong and triggered a build warning: camera_supply_gpiod_table
should have been in a910_init(), not e680_init(). I sent a fixup with subject
"ARM: pxa, regulator: fix building ezx e680".

        Arnd
Thierry Reding June 1, 2018, 9:35 a.m. UTC | #6
On Mon, May 14, 2018 at 10:06:22AM +0200, Linus Walleij wrote:
> As we augmented the regulator core to accept a GPIO descriptor instead

> of a GPIO number, we can augment the fixed GPIO regulator to look up

> and pass that descriptor directly from device tree or board GPIO

> descriptor look up tables.

> 

> Some boards just auto-enumerate their fixed regulator platform devices

> and I have assumed they get names like "fixed-regulator.0" but it's

> pretty hard to guess this. I need some testing from board maintainers to

> be sure. Other boards are straight forward, using just plain

> "fixed-regulator" (ID -1) or "fixed-regulator.1" hammering down the

> device ID.

> 

> The OMAP didn't have proper label names on its GPIO chips so I have fixed

> this with a separate patch to the GPIO tree, see

> commit 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

> "gpio: omap: Give unique labels to each GPIO bank/chip"

> 

> It seems the da9055 and da9211 has never got around to actually passing

> any enable gpio into its platform data (not the in-tree code anyway) so we

> can just decide to simply pass a descriptor instead.

> 

> The fixed GPIO-controlled regulator in mach-pxa/ezx.c was confusingly named

> "*_dummy_supply_device" while it is a very real device backed by a GPIO

> line. There is nothing dummy about it at all, so I renamed it with the

> infix *_regulator_* as part of this patch set.

> 

> For the patch hunk hitting arch/blackfin I would say I do not expect

> testing, review or ACKs anymore so if it works, it works.

> 

> The hunk hitting the x86 BCM43xx driver is especially tricky as the number

> comes out of SFI which is a mystery to me. I definately need someone to

> look at this. (Hi Andy.)

> 

> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> # Check the x86 BCM stuff

> Cc: Alexander Shiyan <shc_work@mail.ru> # i.MX boards user

> Cc: Haojian Zhuang <haojian.zhuang@gmail.com> # MMP2 maintainer

> Cc: Aaro Koskinen <aaro.koskinen@iki.fi> # OMAP1 maintainer

> Cc: Tony Lindgren <tony@atomide.com> # OMAP1,2,3 maintainer

> Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> # EM-X270 maintainer

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

> Cc: Philipp Zabel <philipp.zabel@gmail.com> # Magician maintainer

> Cc: Daniel Mack <zonque@gmail.com> # Raumfeld maintainer

> Cc: Marc Zyngier <marc.zyngier@arm.com> # Zeus maintainer

> Cc: Geert Uytterhoeven <geert+renesas@glider.be> # SuperH pinctrl/GPIO maintainer

> Cc: Russell King <rmk+kernel@armlinux.org.uk> # SA1100

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

> ---

> ChangeLog v2->v3:

> - Resending.

> ChangeLog v1->v2:

> - Rebase the patch on mainline with Blackfin gone and other changes.

> - Fix up the new users that appeared in sa1100

> - Drop some suplus comments in x86.

> ---

>  arch/arm/mach-imx/mach-mx21ads.c              | 13 +++++++-

>  arch/arm/mach-imx/mach-mx27ads.c              | 12 ++++++-

>  arch/arm/mach-mmp/brownstone.c                | 12 ++++++-

>  arch/arm/mach-omap1/board-ams-delta.c         | 14 +++++++-

>  arch/arm/mach-omap2/pdata-quirks.c            | 16 ++++++++-

>  arch/arm/mach-pxa/em-x270.c                   |  1 -

>  arch/arm/mach-pxa/ezx.c                       | 33 ++++++++++++-------

>  arch/arm/mach-pxa/magician.c                  |  2 +-

>  arch/arm/mach-pxa/raumfeld.c                  | 12 +++++--

>  arch/arm/mach-pxa/zeus.c                      | 23 +++++++++++--

>  arch/arm/mach-s3c64xx/mach-crag6410.c         |  1 -

>  arch/arm/mach-s3c64xx/mach-smdk6410.c         |  1 -

>  arch/arm/mach-sa1100/assabet.c                | 21 ++++++++----

>  arch/arm/mach-sa1100/generic.c                |  5 +--

>  arch/arm/mach-sa1100/generic.h                |  3 +-

>  arch/arm/mach-sa1100/shannon.c                |  4 +--

>  arch/sh/boards/mach-ecovec24/setup.c          | 22 +++++++++++--

>  .../intel-mid/device_libs/platform_bcm43xx.c  | 17 ++++++++--

>  drivers/regulator/fixed-helper.c              |  1 -

>  drivers/regulator/fixed.c                     | 33 +++++++++----------

>  include/linux/regulator/fixed.h               |  3 --

>  21 files changed, 187 insertions(+), 62 deletions(-)


This causes an HDMI display regression on Jetson TK1. From what I can
tell, the problem is that we now get a double-inversion for low-active
GPIOs. For example, we have this in the Jetson TK1 device tree:

		vdd_hdmi_pll: regulator@11 {
			compatible = "regulator-fixed";
			reg = <11>;
			regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";
			regulator-min-microvolt = <1050000>;
			regulator-max-microvolt = <1050000>;
			gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;
			vin-supply = <&vdd_1v05_run>;
		};

We've got GPIO_ACTIVE_LOW for the regulator's enable GPIO and since we
don't have enable-active-high, the regulator core will treat the GPIO as
low active. The presence of the GPIO_ACTIVE_LOW flag will cause the GPIO
polarity to be inversed, transparently in gpiolib, and the lack of the
enable-active-high property causes the GPIO polarity to inversed as
well, so we effectively end up with a high-active enable GPIO for one
which should really be low-active.

This has always been a bit of an ambiguity since we've had two places
for expressing the polarity. But I think given the move to pervasively
using GPIO descriptors, it'd be reasonable to just ignore the
enable-active-high property, or perhaps warn if we stumble across a
low-active GPIO (via the flags in the specifier) if the regulator is
also marked enable-active-high.

> diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c

> index 988a7472c2ab..1142f195529b 100644

> --- a/drivers/regulator/fixed.c

> +++ b/drivers/regulator/fixed.c

> @@ -24,10 +24,9 @@

>  #include <linux/platform_device.h>

>  #include <linux/regulator/driver.h>

>  #include <linux/regulator/fixed.h>

> -#include <linux/gpio.h>

> +#include <linux/gpio/consumer.h>

>  #include <linux/slab.h>

>  #include <linux/of.h>

> -#include <linux/of_gpio.h>

>  #include <linux/regulator/of_regulator.h>

>  #include <linux/regulator/machine.h>

>  

> @@ -78,10 +77,6 @@ of_get_fixed_voltage_config(struct device *dev,

>  	if (init_data->constraints.boot_on)

>  		config->enabled_at_boot = true;

>  

> -	config->gpio = of_get_named_gpio(np, "gpio", 0);

> -	if ((config->gpio < 0) && (config->gpio != -ENOENT))

> -		return ERR_PTR(config->gpio);

> -

>  	of_property_read_u32(np, "startup-delay-us", &config->startup_delay);

>  

>  	config->enable_high = of_property_read_bool(np, "enable-active-high");

> @@ -102,6 +97,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)

>  	struct fixed_voltage_config *config;

>  	struct fixed_voltage_data *drvdata;

>  	struct regulator_config cfg = { };

> +	enum gpiod_flags gflags;

>  	int ret;

>  

>  	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),

> @@ -150,25 +146,28 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)

>  

>  	drvdata->desc.fixed_uV = config->microvolts;

>  

> -	if (gpio_is_valid(config->gpio)) {

> -		cfg.ena_gpio = config->gpio;

> -		if (pdev->dev.of_node)

> -			cfg.ena_gpio_initialized = true;

> -	}

>  	cfg.ena_gpio_invert = !config->enable_high;


Change this line to:

	cfg.ena_gpio_invert = false;

fixes the regression and is pretty much the implementation of my above
suggestion to ignore enable-active-high, though we may eventually want
to get rid of ena_gpio_invert altogether, provided that everyone has
moved over to GPIO descriptors.

Thierry
Thierry Reding June 1, 2018, 9:36 a.m. UTC | #7
On Fri, Jun 01, 2018 at 11:35:11AM +0200, Thierry Reding wrote:
> On Mon, May 14, 2018 at 10:06:22AM +0200, Linus Walleij wrote:

> > As we augmented the regulator core to accept a GPIO descriptor instead

> > of a GPIO number, we can augment the fixed GPIO regulator to look up

> > and pass that descriptor directly from device tree or board GPIO

> > descriptor look up tables.

> > 

> > Some boards just auto-enumerate their fixed regulator platform devices

> > and I have assumed they get names like "fixed-regulator.0" but it's

> > pretty hard to guess this. I need some testing from board maintainers to

> > be sure. Other boards are straight forward, using just plain

> > "fixed-regulator" (ID -1) or "fixed-regulator.1" hammering down the

> > device ID.

> > 

> > The OMAP didn't have proper label names on its GPIO chips so I have fixed

> > this with a separate patch to the GPIO tree, see

> > commit 088413bc0bd5f5fb66ca22a19d66a49d7154ba4c

> > "gpio: omap: Give unique labels to each GPIO bank/chip"

> > 

> > It seems the da9055 and da9211 has never got around to actually passing

> > any enable gpio into its platform data (not the in-tree code anyway) so we

> > can just decide to simply pass a descriptor instead.

> > 

> > The fixed GPIO-controlled regulator in mach-pxa/ezx.c was confusingly named

> > "*_dummy_supply_device" while it is a very real device backed by a GPIO

> > line. There is nothing dummy about it at all, so I renamed it with the

> > infix *_regulator_* as part of this patch set.

> > 

> > For the patch hunk hitting arch/blackfin I would say I do not expect

> > testing, review or ACKs anymore so if it works, it works.

> > 

> > The hunk hitting the x86 BCM43xx driver is especially tricky as the number

> > comes out of SFI which is a mystery to me. I definately need someone to

> > look at this. (Hi Andy.)

> > 

> > Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> # Check the x86 BCM stuff

> > Cc: Alexander Shiyan <shc_work@mail.ru> # i.MX boards user

> > Cc: Haojian Zhuang <haojian.zhuang@gmail.com> # MMP2 maintainer

> > Cc: Aaro Koskinen <aaro.koskinen@iki.fi> # OMAP1 maintainer

> > Cc: Tony Lindgren <tony@atomide.com> # OMAP1,2,3 maintainer

> > Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> # EM-X270 maintainer

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

> > Cc: Philipp Zabel <philipp.zabel@gmail.com> # Magician maintainer

> > Cc: Daniel Mack <zonque@gmail.com> # Raumfeld maintainer

> > Cc: Marc Zyngier <marc.zyngier@arm.com> # Zeus maintainer

> > Cc: Geert Uytterhoeven <geert+renesas@glider.be> # SuperH pinctrl/GPIO maintainer

> > Cc: Russell King <rmk+kernel@armlinux.org.uk> # SA1100

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

> > ---

> > ChangeLog v2->v3:

> > - Resending.

> > ChangeLog v1->v2:

> > - Rebase the patch on mainline with Blackfin gone and other changes.

> > - Fix up the new users that appeared in sa1100

> > - Drop some suplus comments in x86.

> > ---

> >  arch/arm/mach-imx/mach-mx21ads.c              | 13 +++++++-

> >  arch/arm/mach-imx/mach-mx27ads.c              | 12 ++++++-

> >  arch/arm/mach-mmp/brownstone.c                | 12 ++++++-

> >  arch/arm/mach-omap1/board-ams-delta.c         | 14 +++++++-

> >  arch/arm/mach-omap2/pdata-quirks.c            | 16 ++++++++-

> >  arch/arm/mach-pxa/em-x270.c                   |  1 -

> >  arch/arm/mach-pxa/ezx.c                       | 33 ++++++++++++-------

> >  arch/arm/mach-pxa/magician.c                  |  2 +-

> >  arch/arm/mach-pxa/raumfeld.c                  | 12 +++++--

> >  arch/arm/mach-pxa/zeus.c                      | 23 +++++++++++--

> >  arch/arm/mach-s3c64xx/mach-crag6410.c         |  1 -

> >  arch/arm/mach-s3c64xx/mach-smdk6410.c         |  1 -

> >  arch/arm/mach-sa1100/assabet.c                | 21 ++++++++----

> >  arch/arm/mach-sa1100/generic.c                |  5 +--

> >  arch/arm/mach-sa1100/generic.h                |  3 +-

> >  arch/arm/mach-sa1100/shannon.c                |  4 +--

> >  arch/sh/boards/mach-ecovec24/setup.c          | 22 +++++++++++--

> >  .../intel-mid/device_libs/platform_bcm43xx.c  | 17 ++++++++--

> >  drivers/regulator/fixed-helper.c              |  1 -

> >  drivers/regulator/fixed.c                     | 33 +++++++++----------

> >  include/linux/regulator/fixed.h               |  3 --

> >  21 files changed, 187 insertions(+), 62 deletions(-)

> 

> This causes an HDMI display regression on Jetson TK1. From what I can

> tell, the problem is that we now get a double-inversion for low-active

> GPIOs. For example, we have this in the Jetson TK1 device tree:

> 

> 		vdd_hdmi_pll: regulator@11 {

> 			compatible = "regulator-fixed";

> 			reg = <11>;

> 			regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";

> 			regulator-min-microvolt = <1050000>;

> 			regulator-max-microvolt = <1050000>;

> 			gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;

> 			vin-supply = <&vdd_1v05_run>;

> 		};

> 

> We've got GPIO_ACTIVE_LOW for the regulator's enable GPIO and since we

> don't have enable-active-high, the regulator core will treat the GPIO as

> low active. The presence of the GPIO_ACTIVE_LOW flag will cause the GPIO

> polarity to be inversed, transparently in gpiolib, and the lack of the

> enable-active-high property causes the GPIO polarity to inversed as

> well, so we effectively end up with a high-active enable GPIO for one

> which should really be low-active.

> 

> This has always been a bit of an ambiguity since we've had two places

> for expressing the polarity. But I think given the move to pervasively

> using GPIO descriptors, it'd be reasonable to just ignore the

> enable-active-high property, or perhaps warn if we stumble across a

> low-active GPIO (via the flags in the specifier) if the regulator is

> also marked enable-active-high.

> 

> > diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c

> > index 988a7472c2ab..1142f195529b 100644

> > --- a/drivers/regulator/fixed.c

> > +++ b/drivers/regulator/fixed.c

> > @@ -24,10 +24,9 @@

> >  #include <linux/platform_device.h>

> >  #include <linux/regulator/driver.h>

> >  #include <linux/regulator/fixed.h>

> > -#include <linux/gpio.h>

> > +#include <linux/gpio/consumer.h>

> >  #include <linux/slab.h>

> >  #include <linux/of.h>

> > -#include <linux/of_gpio.h>

> >  #include <linux/regulator/of_regulator.h>

> >  #include <linux/regulator/machine.h>

> >  

> > @@ -78,10 +77,6 @@ of_get_fixed_voltage_config(struct device *dev,

> >  	if (init_data->constraints.boot_on)

> >  		config->enabled_at_boot = true;

> >  

> > -	config->gpio = of_get_named_gpio(np, "gpio", 0);

> > -	if ((config->gpio < 0) && (config->gpio != -ENOENT))

> > -		return ERR_PTR(config->gpio);

> > -

> >  	of_property_read_u32(np, "startup-delay-us", &config->startup_delay);

> >  

> >  	config->enable_high = of_property_read_bool(np, "enable-active-high");

> > @@ -102,6 +97,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)

> >  	struct fixed_voltage_config *config;

> >  	struct fixed_voltage_data *drvdata;

> >  	struct regulator_config cfg = { };

> > +	enum gpiod_flags gflags;

> >  	int ret;

> >  

> >  	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),

> > @@ -150,25 +146,28 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)

> >  

> >  	drvdata->desc.fixed_uV = config->microvolts;

> >  

> > -	if (gpio_is_valid(config->gpio)) {

> > -		cfg.ena_gpio = config->gpio;

> > -		if (pdev->dev.of_node)

> > -			cfg.ena_gpio_initialized = true;

> > -	}

> >  	cfg.ena_gpio_invert = !config->enable_high;

> 

> Change this line to:

> 

> 	cfg.ena_gpio_invert = false;

> 

> fixes the regression and is pretty much the implementation of my above

> suggestion to ignore enable-active-high, though we may eventually want

> to get rid of ena_gpio_invert altogether, provided that everyone has

> moved over to GPIO descriptors.

> 

> Thierry


Forwarding this to linux-tegra for visibility.

Thierry
Mark Brown June 1, 2018, 10:21 a.m. UTC | #8
On Fri, Jun 01, 2018 at 11:35:11AM +0200, Thierry Reding wrote:

> >  	cfg.ena_gpio_invert = !config->enable_high;


> Change this line to:


> 	cfg.ena_gpio_invert = false;


> fixes the regression and is pretty much the implementation of my above

> suggestion to ignore enable-active-high, though we may eventually want

> to get rid of ena_gpio_invert altogether, provided that everyone has

> moved over to GPIO descriptors.


Please send a patch, I can't apply the above :(
Linus Walleij June 11, 2018, 1:11 p.m. UTC | #9
On Fri, Jun 1, 2018 at 11:35 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Mon, May 14, 2018 at 10:06:22AM +0200, Linus Walleij wrote:


>> As we augmented the regulator core to accept a GPIO descriptor instead

>> of a GPIO number, we can augment the fixed GPIO regulator to look up

>> and pass that descriptor directly from device tree or board GPIO

>> descriptor look up tables.

(...)
> This causes an HDMI display regression on Jetson TK1. From what I can

> tell, the problem is that we now get a double-inversion for low-active

> GPIOs. For example, we have this in the Jetson TK1 device tree:

>

>                 vdd_hdmi_pll: regulator@11 {

>                         compatible = "regulator-fixed";

>                         reg = <11>;

>                         regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";

>                         regulator-min-microvolt = <1050000>;

>                         regulator-max-microvolt = <1050000>;

>                         gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;

>                         vin-supply = <&vdd_1v05_run>;

>                 };

>

> We've got GPIO_ACTIVE_LOW for the regulator's enable GPIO and since we

> don't have enable-active-high, the regulator core will treat the GPIO as

> low active. The presence of the GPIO_ACTIVE_LOW flag will cause the GPIO

> polarity to be inversed, transparently in gpiolib, and the lack of the

> enable-active-high property causes the GPIO polarity to inversed as

> well, so we effectively end up with a high-active enable GPIO for one

> which should really be low-active.


I dug into this. It turns out there are some layers of mess....

The DT binding for "regulator-fixed" specifies that enable-active-high
should be set for polarity inversion. For historical reasons, I guess,
we screwed up. The example in the binding uses that.

I interpreted the binding such that also specifying GPIO_ACTIVE_LOW
was essentially illegal, so I patched gpiolib in commit
a603a2b8d86ee93ee2107da8ca75fd854fd4ff32
"gpio: of: Add special quirk to parse regulator flags"
so it looks like that:

+       if (IS_ENABLED(CONFIG_REGULATOR) &&
+           (of_device_is_compatible(np, "reg-fixed-voltage") ||
+            of_device_is_compatible(np, "regulator-gpio"))) {
+               /*
+                * The regulator GPIO handles are specified such that the
+                * presence or absence of "enable-active-high" solely controls
+                * the polarity of the GPIO line. Any phandle flags must
+                * be actively ignored.
+                */
+               if (*flags & OF_GPIO_ACTIVE_LOW) {
+                       pr_warn("%s GPIO handle specifies active low -
ignored\n",
+                               of_node_full_name(np));
+                       *flags &= ~OF_GPIO_ACTIVE_LOW;
+               }
+               if (!of_property_read_bool(np, "enable-active-high"))
+                       *flags |= OF_GPIO_ACTIVE_LOW;
+       }

This means no matter if you specify active low, the GPIO
will be treated as active low, as this is the default behaviour.
We will warn if things are overspecified as active low on the
flag as well.

The second clause (notice nagation!) specifies that
if enable-acive-high flag is NOT specified, we will be active
low.

Sadly this only handled the undocumented fixed
regulator binding "reg-fixed-voltage". So I need to fix it
for "regulator-fixed" as well, and then it "should work".

I will follow up with a patch.

Yours,
Linus Walleij
Mark Brown June 11, 2018, 3 p.m. UTC | #10
On Mon, Jun 11, 2018 at 03:11:14PM +0200, Linus Walleij wrote:

> The DT binding for "regulator-fixed" specifies that enable-active-high

> should be set for polarity inversion. For historical reasons, I guess,

> we screwed up. The example in the binding uses that.


No, it just says that if the enable is active high then we should
specify it using that boolean property.  It explicitly says that enables
might be active low:

| - enable-active-high: Polarity of GPIO is Active high
| If this property is missing, the default assumed is Active low.

This binding predates the GPIO binding having any gpiolib level polarity
inversion.

> Sadly this only handled the undocumented fixed

> regulator binding "reg-fixed-voltage". So I need to fix it

> for "regulator-fixed" as well, and then it "should work".


The normal fixed voltage regulator parses enable-active-high?
Linus Walleij June 12, 2018, 8:15 a.m. UTC | #11
On Mon, Jun 11, 2018 at 5:00 PM, Mark Brown <broonie@kernel.org> wrote:
> On Mon, Jun 11, 2018 at 03:11:14PM +0200, Linus Walleij wrote:

>

>> The DT binding for "regulator-fixed" specifies that enable-active-high

>> should be set for polarity inversion. For historical reasons, I guess,

>> we screwed up. The example in the binding uses that.

>

> No, it just says that if the enable is active high then we should

> specify it using that boolean property.  It explicitly says that enables

> might be active low

>

> | - enable-active-high: Polarity of GPIO is Active high

> | If this property is missing, the default assumed is Active low.


Yeah my code gets it right I think, my head doesn't always :/

The assumed default is active low and then we tag this
bool property on the regulator if we want it to be active high.

> This binding predates the GPIO binding having any gpiolib level polarity

> inversion.


Yeah, that's how it is.

The confusion stems from Tegra using kinda both.

I think I have it handled right in the gpiolib core by assuming
it is active low, and explicitlt ignoring any attempts to use
the GPIO flags to flag it as active low. It will be active low
anyway in the Tegra case (after my patch to the second
compatible string) albeit giving a warning in the
dmesg.

>> Sadly this only handled the undocumented fixed

>> regulator binding "reg-fixed-voltage". So I need to fix it

>> for "regulator-fixed" as well, and then it "should work".

>

> The normal fixed voltage regulator parses enable-active-high?


Yeah currently. However I moved the handling to the gpiolib
parsing code to centralize polarity inversion handling, in an
attempt so keep things under control. So in the patch series
this flag handling moves over to the gpiolib.

I was thinking to do the same with other subsystems, such as
MMC to get legacy GPIO flags under control and contained.

Yours,
Linus Walleij
Mark Brown June 12, 2018, 11 a.m. UTC | #12
On Tue, Jun 12, 2018 at 10:15:40AM +0200, Linus Walleij wrote:
> On Mon, Jun 11, 2018 at 5:00 PM, Mark Brown <broonie@kernel.org> wrote:

> > On Mon, Jun 11, 2018 at 03:11:14PM +0200, Linus Walleij wrote:


> >> Sadly this only handled the undocumented fixed

> >> regulator binding "reg-fixed-voltage". So I need to fix it

> >> for "regulator-fixed" as well, and then it "should work".


> > The normal fixed voltage regulator parses enable-active-high?


> Yeah currently. However I moved the handling to the gpiolib

> parsing code to centralize polarity inversion handling, in an

> attempt so keep things under control. So in the patch series

> this flag handling moves over to the gpiolib.


Ah, I see - you're talking about the series rather than the current
state of the code, I thought you were talking about the current state of
the code which was why I was confused.

> I was thinking to do the same with other subsystems, such as

> MMC to get legacy GPIO flags under control and contained.


Yes, it'd be good to try to make this clearer for users - having so many
ways of specifying the same thing makes everything hard to understand.
Andy Shevchenko July 6, 2018, 3:21 p.m. UTC | #13
On Mon, 2018-05-21 at 13:27 +0200, Linus Walleij wrote:
> On Mon, May 14, 2018 at 1:03 PM, Andy Shevchenko

> <andriy.shevchenko@linux.intel.com> wrote:

> > On Mon, 2018-05-14 at 10:06 +0200, Linus Walleij wrote:

> > > The hunk hitting the x86 BCM43xx driver is especially tricky as

> > > the

> > > number

> > > comes out of SFI which is a mystery to me. I definately need

> > > someone

> > > to

> > > look at this. (Hi Andy.)

> > 

> > Since there is no link to repo with a branch and I wasn't Cc'ed to

> > cover

> > letter, asking here for a such. I would then pull it and test on

> > real

> > hardware.

> 

> I'm sorry about this.

> This branch:

> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/

> log/?h=gpio-descriptors-regulator

> 

> Has all the patches.

> 

> git pull git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-

> gpio.git

> gpio-descriptors-regulator

> 

> will bring in the patches to a testing branch.


As of today I took only one patch from that folder, i.e. 
commit c032bce1c0b5 ("regulator: fixed: Convert to use GPIO descriptor
only") and applied on top of recent linux-next and tested on Intel
Edison. Wi-Fi has been detected and I got interface in 'ip link list'
output.

Thus,

Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>


(for Intel MID bits only)

Sorry it took a bit.

> 

> > The code itself looks good, so:

> > 

> > Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> > 

> > for Intel MID bits.

> 



-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy
diff mbox series

Patch

diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 5e366824814f..5d3b6b4fe6db 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -18,6 +18,7 @@ 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 #include <linux/gpio.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -175,6 +176,7 @@  static struct resource mx21ads_mmgpio_resource =
 	DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat");
 
 static struct bgpio_pdata mx21ads_mmgpio_pdata = {
+	.label	= "mx21ads-mmgpio",
 	.base	= MX21ADS_MMGPIO_BASE,
 	.ngpio	= 16,
 };
@@ -203,7 +205,6 @@  static struct regulator_init_data mx21ads_lcd_regulator_init_data = {
 static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = {
 	.supply_name	= "LCD",
 	.microvolts	= 3300000,
-	.gpio		= MX21ADS_IO_LCDON,
 	.enable_high	= 1,
 	.init_data	= &mx21ads_lcd_regulator_init_data,
 };
@@ -216,6 +217,15 @@  static struct platform_device mx21ads_lcd_regulator = {
 	},
 };
 
+static struct gpiod_lookup_table mx21ads_lcd_regulator_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what we get */
+	.table = {
+		GPIO_LOOKUP("mx21ads-mmgpio", 9,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 /*
  * Connected is a portrait Sharp-QVGA display
  * of type: LQ035Q7DB02
@@ -311,6 +321,7 @@  static void __init mx21ads_late_init(void)
 {
 	imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata);
 
+	gpiod_add_lookup_table(&mx21ads_lcd_regulator_gpiod_table);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 	mx21ads_cs8900_resources[1].start =
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index a04bb094ded1..0fdb88db0cbd 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -16,6 +16,7 @@ 
 #include <linux/gpio/driver.h>
 /* Needed for gpio_to_irq() */
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -230,10 +231,17 @@  static struct regulator_init_data mx27ads_lcd_regulator_init_data = {
 static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = {
 	.supply_name	= "LCD",
 	.microvolts	= 3300000,
-	.gpio		= MX27ADS_LCD_GPIO,
 	.init_data	= &mx27ads_lcd_regulator_init_data,
 };
 
+static struct gpiod_lookup_table mx27ads_lcd_regulator_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what we get */
+	.table = {
+		GPIO_LOOKUP("LCD", 0, "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static void __init mx27ads_regulator_init(void)
 {
 	struct gpio_chip *vchip;
@@ -247,6 +255,8 @@  static void __init mx27ads_regulator_init(void)
 	vchip->set		= vgpio_set;
 	gpiochip_add_data(vchip, NULL);
 
+	gpiod_add_lookup_table(&mx27ads_lcd_regulator_gpiod_table);
+
 	platform_device_register_data(NULL, "reg-fixed-voltage",
 				      PLATFORM_DEVID_AUTO,
 				      &mx27ads_lcd_regulator_pdata,
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index d1613b954926..563b5a278d65 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -15,6 +15,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio-pxa.h>
+#include <linux/gpio/machine.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
@@ -148,7 +149,6 @@  static struct regulator_init_data brownstone_v_5vp_data = {
 static struct fixed_voltage_config brownstone_v_5vp = {
 	.supply_name		= "v_5vp",
 	.microvolts		= 5000000,
-	.gpio			= GPIO_5V_ENABLE,
 	.enable_high		= 1,
 	.enabled_at_boot	= 1,
 	.init_data		= &brownstone_v_5vp_data,
@@ -162,6 +162,15 @@  static struct platform_device brownstone_v_5vp_device = {
 	},
 };
 
+static struct gpiod_lookup_table brownstone_v_5vp_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.1", /* .id set to 1 above */
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_5V_ENABLE,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static struct max8925_platform_data brownstone_max8925_info = {
 	.irq_base		= MMP_NR_IRQS,
 };
@@ -217,6 +226,7 @@  static void __init brownstone_init(void)
 	mmp2_add_isram(&mmp2_isram_platdata);
 
 	/* enable 5v regulator */
+	gpiod_add_lookup_table(&brownstone_v_5vp_gpiod_table);
 	platform_device_register(&brownstone_v_5vp_device);
 }
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 52e8e53ca154..759fa18f6ab4 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -12,6 +12,7 @@ 
  * published by the Free Software Foundation.
  */
 #include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -203,6 +204,7 @@  static struct resource latch2_resources[] = {
 };
 
 static struct bgpio_pdata latch2_pdata = {
+	.label	= "ams-delta-latch2",
 	.base	= AMS_DELTA_LATCH2_GPIO_BASE,
 	.ngpio	= AMS_DELTA_LATCH2_NGPIO,
 };
@@ -272,7 +274,6 @@  static struct regulator_init_data modem_nreset_data = {
 static struct fixed_voltage_config modem_nreset_config = {
 	.supply_name		= "modem_nreset",
 	.microvolts		= 3300000,
-	.gpio			= AMS_DELTA_GPIO_PIN_MODEM_NRESET,
 	.startup_delay		= 25000,
 	.enable_high		= 1,
 	.enabled_at_boot	= 1,
@@ -287,6 +288,16 @@  static struct platform_device modem_nreset_device = {
 	},
 };
 
+static struct gpiod_lookup_table modem_nreset_gpiod_table = {
+	.dev_id = "reg-fixed-voltage",
+	.table = {
+		/* The AMS_DELTA_GPIO_PIN_MODEM_NRESET is at offset 12 */
+		GPIO_LOOKUP("ams-delta-latch2", 12,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 struct modem_private_data {
 	struct regulator *regulator;
 };
@@ -570,6 +581,7 @@  static int __init late_init(void)
 
 	platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
 
+	gpiod_add_lookup_table(&modem_nreset_gpiod_table);
 	err = platform_device_register(&modem_nreset_device);
 	if (err) {
 		pr_err("Couldn't register the modem regulator device\n");
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 6459816c2879..7d1447204fb8 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -10,6 +10,7 @@ 
 #include <linux/clk.h>
 #include <linux/davinci_emac.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
@@ -330,7 +331,6 @@  static struct regulator_init_data pandora_vmmc3 = {
 static struct fixed_voltage_config pandora_vwlan = {
 	.supply_name		= "vwlan",
 	.microvolts		= 1800000, /* 1.8V */
-	.gpio			= PANDORA_WIFI_NRESET_GPIO,
 	.startup_delay		= 50000, /* 50ms */
 	.enable_high		= 1,
 	.init_data		= &pandora_vmmc3,
@@ -344,6 +344,19 @@  static struct platform_device pandora_vwlan_device = {
 	},
 };
 
+static struct gpiod_lookup_table pandora_vwlan_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.1",
+	.table = {
+		/*
+		 * As this is a low GPIO number it should be at the first
+		 * GPIO bank.
+		 */
+		GPIO_LOOKUP("gpio-0-31", PANDORA_WIFI_NRESET_GPIO,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static void pandora_wl1251_init_card(struct mmc_card *card)
 {
 	/*
@@ -405,6 +418,7 @@  static void __init pandora_wl1251_init(void)
 static void __init omap3_pandora_legacy_init(void)
 {
 	platform_device_register(&pandora_backlight);
+	gpiod_add_lookup_table(&pandora_vwlan_gpiod_table);
 	platform_device_register(&pandora_vwlan_device);
 	omap_hsmmc_init(pandora_mmc3);
 	omap_hsmmc_late_init(pandora_mmc3);
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 49022ad338e9..6d7d93981098 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -987,7 +987,6 @@  static struct fixed_voltage_config camera_dummy_config = {
 	.supply_name		= "camera_vdd",
 	.input_supply		= "vcc cam",
 	.microvolts		= 2800000,
-	.gpio			= -1,
 	.enable_high		= 0,
 	.init_data		= &camera_dummy_initdata,
 };
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 2c90b58f347d..2b4bd6d94855 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -21,6 +21,7 @@ 
 #include <linux/regulator/fixed.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds-lp3944.h>
 #include <linux/platform_data/i2c-pxa.h>
@@ -698,31 +699,39 @@  static struct pxa27x_keypad_platform_data e2_keypad_platform_data = {
 
 #if defined(CONFIG_MACH_EZX_A780) || defined(CONFIG_MACH_EZX_A910)
 /* camera */
-static struct regulator_consumer_supply camera_dummy_supplies[] = {
+static struct regulator_consumer_supply camera_regulator_supplies[] = {
 	REGULATOR_SUPPLY("vdd", "0-005d"),
 };
 
-static struct regulator_init_data camera_dummy_initdata = {
-	.consumer_supplies = camera_dummy_supplies,
-	.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies),
+static struct regulator_init_data camera_regulator_initdata = {
+	.consumer_supplies = camera_regulator_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(camera_regulator_supplies),
 	.constraints = {
 		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 	},
 };
 
-static struct fixed_voltage_config camera_dummy_config = {
+static struct fixed_voltage_config camera_regulator_config = {
 	.supply_name		= "camera_vdd",
 	.microvolts		= 2800000,
-	.gpio			= GPIO50_nCAM_EN,
 	.enable_high		= 0,
-	.init_data		= &camera_dummy_initdata,
+	.init_data		= &camera_regulator_initdata,
 };
 
-static struct platform_device camera_supply_dummy_device = {
+static struct platform_device camera_supply_regulator_device = {
 	.name	= "reg-fixed-voltage",
 	.id	= 1,
 	.dev	= {
-		.platform_data = &camera_dummy_config,
+		.platform_data = &camera_regulator_config,
+	},
+};
+
+static struct gpiod_lookup_table camera_supply_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.1",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO50_nCAM_EN,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
 	},
 };
 #endif
@@ -800,7 +809,7 @@  static struct i2c_board_info a780_i2c_board_info[] = {
 
 static struct platform_device *a780_devices[] __initdata = {
 	&a780_gpio_keys,
-	&camera_supply_dummy_device,
+	&camera_supply_regulator_device,
 };
 
 static void __init a780_init(void)
@@ -823,6 +832,7 @@  static void __init a780_init(void)
 	if (a780_camera_init() == 0)
 		pxa_set_camera_info(&a780_pxacamera_platform_data);
 
+	gpiod_add_lookup_table(&camera_supply_gpiod_table);
 	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(a780_devices));
@@ -892,6 +902,7 @@  static void __init e680_init(void)
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
+	gpiod_add_lookup_table(&camera_supply_gpiod_table);
 	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(e680_devices));
@@ -1098,7 +1109,7 @@  static struct i2c_board_info __initdata a910_i2c_board_info[] = {
 
 static struct platform_device *a910_devices[] __initdata = {
 	&a910_gpio_keys,
-	&camera_supply_dummy_device,
+	&camera_supply_regulator_device,
 };
 
 static void __init a910_init(void)
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index c5325d1ae77b..14c0f80bc9e7 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -18,6 +18,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/mfd/htc-pasic3.h>
@@ -696,7 +697,6 @@  static struct regulator_init_data vads7846_regulator = {
 static struct fixed_voltage_config vads7846 = {
 	.supply_name	= "vads7846",
 	.microvolts	= 3300000, /* probably */
-	.gpio		= -EINVAL,
 	.startup_delay	= 0,
 	.init_data	= &vads7846_regulator,
 };
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 034345546f84..ee766e4ebddc 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -886,7 +886,6 @@  static struct regulator_init_data audio_va_initdata = {
 static struct fixed_voltage_config audio_va_config = {
 	.supply_name		= "audio_va",
 	.microvolts		= 5000000,
-	.gpio			= GPIO_AUDIO_VA_ENABLE,
 	.enable_high		= 1,
 	.enabled_at_boot	= 0,
 	.init_data		= &audio_va_initdata,
@@ -900,6 +899,15 @@  static struct platform_device audio_va_device = {
 	},
 };
 
+static struct gpiod_lookup_table audio_va_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", GPIO_AUDIO_VA_ENABLE,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 /* Dummy supplies for Codec's VD/VLC */
 
 static struct regulator_consumer_supply audio_dummy_supplies[] = {
@@ -918,7 +926,6 @@  static struct regulator_init_data audio_dummy_initdata = {
 static struct fixed_voltage_config audio_dummy_config = {
 	.supply_name		= "audio_vd",
 	.microvolts		= 3300000,
-	.gpio			= -1,
 	.init_data		= &audio_dummy_initdata,
 };
 
@@ -1033,6 +1040,7 @@  static void __init raumfeld_audio_init(void)
 	else
 		gpio_direction_output(GPIO_MCLK_RESET, 1);
 
+	gpiod_add_lookup_table(&audio_va_gpiod_table);
 	platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices));
 }
 
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index e3851795d6d7..58e05afcece0 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -17,6 +17,7 @@ 
 #include <linux/irq.h>
 #include <linux/pm.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/serial_8250.h>
 #include <linux/dm9000.h>
 #include <linux/mmc/host.h>
@@ -410,7 +411,6 @@  static struct regulator_init_data can_regulator_init_data = {
 static struct fixed_voltage_config can_regulator_pdata = {
 	.supply_name	= "CAN_SHDN",
 	.microvolts	= 3300000,
-	.gpio		= ZEUS_CAN_SHDN_GPIO,
 	.init_data	= &can_regulator_init_data,
 };
 
@@ -422,6 +422,15 @@  static struct platform_device can_regulator_device = {
 	},
 };
 
+static struct gpiod_lookup_table can_regulator_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", ZEUS_CAN_SHDN_GPIO,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static struct mcp251x_platform_data zeus_mcp2515_pdata = {
 	.oscillator_frequency	= 16*1000*1000,
 };
@@ -538,7 +547,6 @@  static struct regulator_init_data zeus_ohci_regulator_data = {
 static struct fixed_voltage_config zeus_ohci_regulator_config = {
 	.supply_name		= "vbus2",
 	.microvolts		= 5000000, /* 5.0V */
-	.gpio			= ZEUS_USB2_PWREN_GPIO,
 	.enable_high		= 1,
 	.startup_delay		= 0,
 	.init_data		= &zeus_ohci_regulator_data,
@@ -552,6 +560,15 @@  static struct platform_device zeus_ohci_regulator_device = {
 	},
 };
 
+static struct gpiod_lookup_table zeus_ohci_regulator_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0",
+	.table = {
+		GPIO_LOOKUP("gpio-pxa", ZEUS_USB2_PWREN_GPIO,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static struct pxaohci_platform_data zeus_ohci_platform_data = {
 	.port_mode	= PMM_NPS_MODE,
 	/* Clear Power Control Polarity Low and set Power Sense
@@ -855,6 +872,8 @@  static void __init zeus_init(void)
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));
 
+	gpiod_add_lookup_table(&can_regulator_gpiod_table);
+	gpiod_add_lookup_table(&zeus_ohci_regulator_gpiod_table);
 	platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));
 
 	zeus_register_ohci();
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index f04650297487..379424d72ae7 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -352,7 +352,6 @@  static struct fixed_voltage_config wallvdd_pdata = {
 	.supply_name = "WALLVDD",
 	.microvolts = 5000000,
 	.init_data = &wallvdd_data,
-	.gpio = -EINVAL,
 };
 
 static struct platform_device wallvdd_device = {
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index c46fa5dfd2e0..908e5aa831c8 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -222,7 +222,6 @@  static struct fixed_voltage_config smdk6410_b_pwr_5v_pdata = {
 	.supply_name = "B_PWR_5V",
 	.microvolts = 5000000,
 	.init_data = &smdk6410_b_pwr_5v_data,
-	.gpio = -EINVAL,
 };
 
 static struct platform_device smdk6410_b_pwr_5v = {
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 575ec085cffa..dbb53c520165 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -101,7 +101,7 @@  static int __init assabet_init_gpio(void __iomem *reg, u32 def_val)
 
 	assabet_bcr_gc = gc;
 
-	return gc->base;
+	return 0;
 }
 
 /*
@@ -471,6 +471,14 @@  static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = {
 	.enable_high = 1,
 };
 
+static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
+	.dev_id = "reg-fixed-voltage.0",
+	.table = {
+		GPIO_LOOKUP("assabet", 0, "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static void __init assabet_init(void)
 {
 	/*
@@ -517,9 +525,11 @@  static void __init assabet_init(void)
 			neponset_resources, ARRAY_SIZE(neponset_resources));
 #endif
 	} else {
+		gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
 		sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
-					 assabet_cf_vcc_consumers,
-					 ARRAY_SIZE(assabet_cf_vcc_consumers));
+					assabet_cf_vcc_consumers,
+					ARRAY_SIZE(assabet_cf_vcc_consumers),
+					true);
 
 	}
 
@@ -802,7 +812,6 @@  fs_initcall(assabet_leds_init);
 
 void __init assabet_init_irq(void)
 {
-	unsigned int assabet_gpio_base;
 	u32 def_val;
 
 	sa1100_init_irq();
@@ -817,9 +826,7 @@  void __init assabet_init_irq(void)
 	 *
 	 * This must precede any driver calls to BCR_set() or BCR_clear().
 	 */
-	assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val);
-
-	assabet_cf_vcc_pdata.gpio = assabet_gpio_base + 0;
+	assabet_init_gpio((void *)&ASSABET_BCR, def_val);
 }
 
 MACHINE_START(ASSABET, "Intel-Assabet")
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 7167ddf84a0e..800321c6cbd8 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -348,7 +348,8 @@  void __init sa11x0_init_late(void)
 
 int __init sa11x0_register_fixed_regulator(int n,
 	struct fixed_voltage_config *cfg,
-	struct regulator_consumer_supply *supplies, unsigned num_supplies)
+	struct regulator_consumer_supply *supplies, unsigned num_supplies,
+	bool uses_gpio)
 {
 	struct regulator_init_data *id;
 
@@ -356,7 +357,7 @@  int __init sa11x0_register_fixed_regulator(int n,
 	if (!cfg->init_data)
 		return -ENOMEM;
 
-	if (cfg->gpio < 0)
+	if (!uses_gpio)
 		id->constraints.always_on = 1;
 	id->constraints.name = cfg->supply_name;
 	id->constraints.min_uV = cfg->microvolts;
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 5f3cb52fa6ab..158a4fd5ca24 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -54,4 +54,5 @@  void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *);
 struct fixed_voltage_config;
 struct regulator_consumer_supply;
 int sa11x0_register_fixed_regulator(int n, struct fixed_voltage_config *cfg,
-	struct regulator_consumer_supply *supplies, unsigned num_supplies);
+	struct regulator_consumer_supply *supplies, unsigned num_supplies,
+	bool uses_gpio);
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 22f7fe0b809f..5bc82e2671c6 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -102,14 +102,14 @@  static struct fixed_voltage_config shannon_cf_vcc_pdata __initdata = {
 	.supply_name = "cf-power",
 	.microvolts = 3300000,
 	.enabled_at_boot = 1,
-	.gpio = -EINVAL,
 };
 
 static void __init shannon_init(void)
 {
 	sa11x0_register_fixed_regulator(0, &shannon_cf_vcc_pdata,
 					shannon_cf_vcc_consumers,
-					ARRAY_SIZE(shannon_cf_vcc_consumers));
+					ARRAY_SIZE(shannon_cf_vcc_consumers),
+					false);
 	sa11x0_register_pcmcia(0, &shannon_pcmcia0_gpio_table);
 	sa11x0_register_pcmcia(1, &shannon_pcmcia1_gpio_table);
 	sa11x0_ppc_configure_mcp();
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index adc61d14172c..c296b5c399b7 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -633,7 +633,6 @@  static struct regulator_init_data cn12_power_init_data = {
 static struct fixed_voltage_config cn12_power_info = {
 	.supply_name = "CN12 SD/MMC Vdd",
 	.microvolts = 3300000,
-	.gpio = GPIO_PTB7,
 	.enable_high = 1,
 	.init_data = &cn12_power_init_data,
 };
@@ -646,6 +645,16 @@  static struct platform_device cn12_power = {
 	},
 };
 
+static struct gpiod_lookup_table cn12_power_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.0",
+	.table = {
+		/* Offset 7 on port B */
+		GPIO_LOOKUP("sh7724_pfc", GPIO_PTB7,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
 /* SDHI0 */
 static struct regulator_consumer_supply sdhi0_power_consumers[] =
@@ -665,7 +674,6 @@  static struct regulator_init_data sdhi0_power_init_data = {
 static struct fixed_voltage_config sdhi0_power_info = {
 	.supply_name = "CN11 SD/MMC Vdd",
 	.microvolts = 3300000,
-	.gpio = GPIO_PTB6,
 	.enable_high = 1,
 	.init_data = &sdhi0_power_init_data,
 };
@@ -678,6 +686,16 @@  static struct platform_device sdhi0_power = {
 	},
 };
 
+static struct gpiod_lookup_table sdhi0_power_gpiod_table = {
+	.dev_id = "reg-fixed-voltage.1",
+	.table = {
+		/* Offset 6 on port B */
+		GPIO_LOOKUP("sh7724_pfc", GPIO_PTB6,
+			    "enable", GPIO_ACTIVE_HIGH),
+		{ },
+	},
+};
+
 static struct tmio_mmc_data sdhi0_info = {
 	.chan_priv_tx	= (void *)SHDMA_SLAVE_SDHI0_TX,
 	.chan_priv_rx	= (void *)SHDMA_SLAVE_SDHI0_RX,
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c b/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c
index 4392c15ed9e0..fc77d69e51d7 100644
--- a/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c
+++ b/arch/x86/platform/intel-mid/device_libs/platform_bcm43xx.c
@@ -10,7 +10,7 @@ 
  * of the License.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -43,7 +43,6 @@  static struct fixed_voltage_config bcm43xx_vmmc = {
 	 * real voltage and signaling are still 1.8V.
 	 */
 	.microvolts		= 2000000,		/* 1.8V */
-	.gpio			= -EINVAL,
 	.startup_delay		= 250 * 1000,		/* 250ms */
 	.enable_high		= 1,			/* active high */
 	.enabled_at_boot	= 0,			/* disabled at boot */
@@ -58,11 +57,23 @@  static struct platform_device bcm43xx_vmmc_regulator = {
 	},
 };
 
+static struct gpiod_lookup_table bcm43xx_vmmc_gpio_table = {
+	.dev_id	= "reg-fixed-voltage.0",
+	.table	= {
+		GPIO_LOOKUP("0000:00:0c.0", -1, "enable", GPIO_ACTIVE_LOW),
+		{}
+	},
+};
+
 static int __init bcm43xx_regulator_register(void)
 {
+	struct gpiod_lookup_table *table = &bcm43xx_vmmc_gpio_table;
+	struct gpiod_lookup *lookup = table->table;
 	int ret;
 
-	bcm43xx_vmmc.gpio = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);
+	lookup[0].chip_hwnum = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);
+	gpiod_add_lookup_table(table);
+
 	ret = platform_device_register(&bcm43xx_vmmc_regulator);
 	if (ret) {
 		pr_err("%s: vmmc regulator register failed\n", __func__);
diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
index 777fac6fb4cb..2c6098e6f4bc 100644
--- a/drivers/regulator/fixed-helper.c
+++ b/drivers/regulator/fixed-helper.c
@@ -43,7 +43,6 @@  struct platform_device *regulator_register_always_on(int id, const char *name,
 	}
 
 	data->cfg.microvolts = uv;
-	data->cfg.gpio = -EINVAL;
 	data->cfg.enabled_at_boot = 1;
 	data->cfg.init_data = &data->init_data;
 
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 988a7472c2ab..1142f195529b 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -24,10 +24,9 @@ 
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/slab.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/machine.h>
 
@@ -78,10 +77,6 @@  of_get_fixed_voltage_config(struct device *dev,
 	if (init_data->constraints.boot_on)
 		config->enabled_at_boot = true;
 
-	config->gpio = of_get_named_gpio(np, "gpio", 0);
-	if ((config->gpio < 0) && (config->gpio != -ENOENT))
-		return ERR_PTR(config->gpio);
-
 	of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
 
 	config->enable_high = of_property_read_bool(np, "enable-active-high");
@@ -102,6 +97,7 @@  static int reg_fixed_voltage_probe(struct platform_device *pdev)
 	struct fixed_voltage_config *config;
 	struct fixed_voltage_data *drvdata;
 	struct regulator_config cfg = { };
+	enum gpiod_flags gflags;
 	int ret;
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
@@ -150,25 +146,28 @@  static int reg_fixed_voltage_probe(struct platform_device *pdev)
 
 	drvdata->desc.fixed_uV = config->microvolts;
 
-	if (gpio_is_valid(config->gpio)) {
-		cfg.ena_gpio = config->gpio;
-		if (pdev->dev.of_node)
-			cfg.ena_gpio_initialized = true;
-	}
 	cfg.ena_gpio_invert = !config->enable_high;
 	if (config->enabled_at_boot) {
 		if (config->enable_high)
-			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+			gflags = GPIOD_OUT_HIGH;
 		else
-			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+			gflags = GPIOD_OUT_LOW;
 	} else {
 		if (config->enable_high)
-			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+			gflags = GPIOD_OUT_LOW;
 		else
-			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+			gflags = GPIOD_OUT_HIGH;
 	}
-	if (config->gpio_is_open_drain)
-		cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
+	if (config->gpio_is_open_drain) {
+		if (gflags == GPIOD_OUT_HIGH)
+			gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
+		else
+			gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
+	}
+
+	cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags);
+	if (IS_ERR(cfg.ena_gpiod))
+		return PTR_ERR(cfg.ena_gpiod);
 
 	cfg.dev = &pdev->dev;
 	cfg.init_data = config->init_data;
diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
index 48918be649d4..1a4340ed8e2b 100644
--- a/include/linux/regulator/fixed.h
+++ b/include/linux/regulator/fixed.h
@@ -24,8 +24,6 @@  struct regulator_init_data;
  * @supply_name:	Name of the regulator supply
  * @input_supply:	Name of the input regulator supply
  * @microvolts:		Output voltage of regulator
- * @gpio:		GPIO to use for enable control
- * 			set to -EINVAL if not used
  * @startup_delay:	Start-up time in microseconds
  * @gpio_is_open_drain: Gpio pin is open drain or normal type.
  *			If it is open drain type then HIGH will be set
@@ -49,7 +47,6 @@  struct fixed_voltage_config {
 	const char *supply_name;
 	const char *input_supply;
 	int microvolts;
-	int gpio;
 	unsigned startup_delay;
 	unsigned gpio_is_open_drain:1;
 	unsigned enable_high:1;