aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-10-12 08:54:12 -0400
committerMark Brown <broonie@kernel.org>2018-10-12 12:55:02 -0400
commitb0ce7b29bfcd090ddba476f45a75ec0a797b048a (patch)
treeb689c014f8e3423d4db5a5355ec81c548eba3ae1
parentbef9391cbec547351c6a13e52f3a26bb2d271ec7 (diff)
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 <m.szyprowski@samsung.com> Cc: Jon Hunter <jonathanh@nvidia.com> Fixes: efdfeb079cc3 ("regulator: fixed: Convert to use GPIO descriptor only") Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/gpio/gpiolib.c19
-rw-r--r--drivers/regulator/fixed.c13
-rw-r--r--include/linux/gpio/consumer.h1
3 files changed, 31 insertions, 2 deletions
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,
3908 * the device name as label 3908 * the device name as label
3909 */ 3909 */
3910 status = gpiod_request(desc, con_id ? con_id : devname); 3910 status = gpiod_request(desc, con_id ? con_id : devname);
3911 if (status < 0) 3911 if (status < 0) {
3912 return ERR_PTR(status); 3912 if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
3913 /*
3914 * This happens when there are several consumers for
3915 * the same GPIO line: we just return here without
3916 * further initialization. It is a bit if a hack.
3917 * This is necessary to support fixed regulators.
3918 *
3919 * FIXME: Make this more sane and safe.
3920 */
3921 dev_info(dev, "nonexclusive access to GPIO for %s\n",
3922 con_id ? con_id : devname);
3923 return desc;
3924 } else {
3925 return ERR_PTR(status);
3926 }
3927 }
3913 3928
3914 status = gpiod_configure_flags(desc, con_id, lookupflags, flags); 3929 status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
3915 if (status < 0) { 3930 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)
170 gflags = GPIOD_OUT_LOW_OPEN_DRAIN; 170 gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
171 } 171 }
172 172
173 /*
174 * Some fixed regulators share the enable line between two
175 * regulators which makes it necessary to get a handle on the
176 * same descriptor for two different consumers. This will get
177 * the GPIO descriptor, but only the first call will initialize
178 * it so any flags such as inversion or open drain will only
179 * be set up by the first caller and assumed identical on the
180 * next caller.
181 *
182 * FIXME: find a better way to deal with this.
183 */
184 gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
185
173 cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags); 186 cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags);
174 if (IS_ERR(cfg.ena_gpiod)) 187 if (IS_ERR(cfg.ena_gpiod))
175 return PTR_ERR(cfg.ena_gpiod); 188 return PTR_ERR(cfg.ena_gpiod);
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 21ddbe440030..33695a1d8b35 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -30,6 +30,7 @@ struct gpio_descs {
30#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) 30#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
31#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) 31#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
32#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3) 32#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
33#define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4)
33 34
34/** 35/**
35 * Optional flags that can be passed to one of gpiod_* to configure direction 36 * Optional flags that can be passed to one of gpiod_* to configure direction