aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2017-09-10 13:26:22 -0400
committerLinus Walleij <linus.walleij@linaro.org>2017-10-30 03:42:31 -0400
commitf926dfc112bc6cf41d7068ee5e3f261e13a5bec8 (patch)
tree07ed8f8beb6804d1623c0686d33335584ba04217
parentb2e63555592f81331c8da3afaa607d8cf83e8138 (diff)
gpio: Make it possible for consumers to enforce open drain
Some busses, like I2C, strictly need to have the line handled as open drain, i.e. not actively driven high. For this reason the i2c-gpio.c bit-banged I2C driver is reimplementing open drain handling outside of gpiolib. This is not very optimal. Instead make it possible for a consumer to explcitly express that the line must be handled as open drain instead of allowing local hacks papering over this issue. The descriptor tables, whether DT, ACPI or board files, should of course have flagged these lines as open drain. E.g.: enum gpio_lookup_flags GPIO_OPEN_DRAIN for a board file, or gpios = <&foo 42 GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN>; in a device tree using <dt-bindings/gpio/gpio.h> But more often than not, these descriptors are wrong. So we need to make it possible for consumers to enforce this open drain behaviour. We now have two new enumerated GPIO descriptor config flags: GPIOD_OUT_LOW_OPEN_DRAIN and GPIOD_OUT_HIGH_OPEN_DRAIN that will set up the lined enforced as open drain as output low or high, using open drain (if the driver supports it) or using open drain emulation (setting the line as input to drive it high) from the gpiolib core. Cc: linux-gpio@vger.kernel.org Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpiolib.c13
-rw-r--r--include/linux/gpio/consumer.h6
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index eb80dac4e26a..c952ef1b2f46 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3264,8 +3264,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
3264 3264
3265 if (lflags & GPIO_ACTIVE_LOW) 3265 if (lflags & GPIO_ACTIVE_LOW)
3266 set_bit(FLAG_ACTIVE_LOW, &desc->flags); 3266 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
3267
3267 if (lflags & GPIO_OPEN_DRAIN) 3268 if (lflags & GPIO_OPEN_DRAIN)
3268 set_bit(FLAG_OPEN_DRAIN, &desc->flags); 3269 set_bit(FLAG_OPEN_DRAIN, &desc->flags);
3270 else if (dflags & GPIOD_FLAGS_BIT_OPEN_DRAIN) {
3271 /*
3272 * This enforces open drain mode from the consumer side.
3273 * This is necessary for some busses like I2C, but the lookup
3274 * should *REALLY* have specified them as open drain in the
3275 * first place, so print a little warning here.
3276 */
3277 set_bit(FLAG_OPEN_DRAIN, &desc->flags);
3278 gpiod_warn(desc,
3279 "enforced open drain please flag it properly in DT/ACPI DSDT/board file\n");
3280 }
3281
3269 if (lflags & GPIO_OPEN_SOURCE) 3282 if (lflags & GPIO_OPEN_SOURCE)
3270 set_bit(FLAG_OPEN_SOURCE, &desc->flags); 3283 set_bit(FLAG_OPEN_SOURCE, &desc->flags);
3271 if (lflags & GPIO_SLEEP_MAY_LOOSE_VALUE) 3284 if (lflags & GPIO_SLEEP_MAY_LOOSE_VALUE)
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 8f702fcbe485..5f72a49d1aa3 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -28,6 +28,7 @@ struct gpio_descs {
28#define GPIOD_FLAGS_BIT_DIR_SET BIT(0) 28#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
29#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) 29#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
30#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) 30#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
31#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
31 32
32/** 33/**
33 * Optional flags that can be passed to one of gpiod_* to configure direction 34 * Optional flags that can be passed to one of gpiod_* to configure direction
@@ -39,6 +40,11 @@ enum gpiod_flags {
39 GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT, 40 GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
40 GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT | 41 GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
41 GPIOD_FLAGS_BIT_DIR_VAL, 42 GPIOD_FLAGS_BIT_DIR_VAL,
43 GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
44 GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_OPEN_DRAIN,
45 GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
46 GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_DIR_VAL |
47 GPIOD_FLAGS_BIT_OPEN_DRAIN,
42}; 48};
43 49
44#ifdef CONFIG_GPIOLIB 50#ifdef CONFIG_GPIOLIB