From b0ce7b29bfcd090ddba476f45a75ec0a797b048a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 12 Oct 2018 14:54:12 +0200 Subject: regulator/gpio: Allow nonexclusive GPIO access This allows nonexclusive (simultaneous) access to a single GPIO line for the fixed regulator enable line. This happens when several regulators use the same GPIO for enabling and disabling a regulator, and all need a handle on their GPIO descriptor. This solution with a special flag is not entirely elegant and should ideally be replaced by something more careful as this makes it possible for several consumers to enable/disable the same GPIO line to the left and right without any consistency. The current use inside the regulator core should however be fine as it takes special care to handle this. For the state of the GPIO backend, this is still the lesser evil compared to going back to global GPIO numbers. Cc: Marek Szyprowski Cc: Jon Hunter Fixes: efdfeb079cc3 ("regulator: fixed: Convert to use GPIO descriptor only") Reported-by: Marek Szyprowski Tested-by: Jon Hunter Tested-by: Marek Szyprowski Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/gpio/gpiolib.c | 19 +++++++++++++++++-- drivers/regulator/fixed.c | 13 +++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8f8a1999393..8228306aba46 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3908,8 +3908,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * the device name as label */ status = gpiod_request(desc, con_id ? con_id : devname); - if (status < 0) - return ERR_PTR(status); + if (status < 0) { + if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { + /* + * This happens when there are several consumers for + * the same GPIO line: we just return here without + * further initialization. It is a bit if a hack. + * This is necessary to support fixed regulators. + * + * FIXME: Make this more sane and safe. + */ + dev_info(dev, "nonexclusive access to GPIO for %s\n", + con_id ? con_id : devname); + return desc; + } else { + return ERR_PTR(status); + } + } status = gpiod_configure_flags(desc, con_id, lookupflags, flags); if (status < 0) { diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 7d639ad953b6..ccc29038f19a 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -170,6 +170,19 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) gflags = GPIOD_OUT_LOW_OPEN_DRAIN; } + /* + * Some fixed regulators share the enable line between two + * regulators which makes it necessary to get a handle on the + * same descriptor for two different consumers. This will get + * the GPIO descriptor, but only the first call will initialize + * it so any flags such as inversion or open drain will only + * be set up by the first caller and assumed identical on the + * next caller. + * + * FIXME: find a better way to deal with this. + */ + gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE; + cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags); if (IS_ERR(cfg.ena_gpiod)) return PTR_ERR(cfg.ena_gpiod); -- cgit v1.2.3