| From dfdd0a7f23007b03125d56dd275f67b557b8bdf1 Mon Sep 17 00:00:00 2001 |
| From: Linus Walleij <linus.walleij@linaro.org> |
| Date: Sun, 10 Sep 2017 19:26:22 +0200 |
| Subject: [PATCH 0394/1795] 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> |
| (cherry picked from commit f926dfc112bc6cf41d7068ee5e3f261e13a5bec8) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/gpio/gpiolib.c | 13 +++++++++++++ |
| include/linux/gpio/consumer.h | 6 ++++++ |
| 2 files changed, 19 insertions(+) |
| |
| diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c |
| index 99d0b3510b54..e7660b708635 100644 |
| --- a/drivers/gpio/gpiolib.c |
| +++ b/drivers/gpio/gpiolib.c |
| @@ -3268,8 +3268,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, |
| |
| if (lflags & GPIO_ACTIVE_LOW) |
| set_bit(FLAG_ACTIVE_LOW, &desc->flags); |
| + |
| if (lflags & GPIO_OPEN_DRAIN) |
| set_bit(FLAG_OPEN_DRAIN, &desc->flags); |
| + else if (dflags & GPIOD_FLAGS_BIT_OPEN_DRAIN) { |
| + /* |
| + * This enforces open drain mode from the consumer side. |
| + * This is necessary for some busses like I2C, but the lookup |
| + * should *REALLY* have specified them as open drain in the |
| + * first place, so print a little warning here. |
| + */ |
| + set_bit(FLAG_OPEN_DRAIN, &desc->flags); |
| + gpiod_warn(desc, |
| + "enforced open drain please flag it properly in DT/ACPI DSDT/board file\n"); |
| + } |
| + |
| if (lflags & GPIO_OPEN_SOURCE) |
| set_bit(FLAG_OPEN_SOURCE, &desc->flags); |
| if (lflags & GPIO_SLEEP_MAY_LOOSE_VALUE) |
| diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h |
| index c4a350d83578..11fb79f3dd24 100644 |
| --- a/include/linux/gpio/consumer.h |
| +++ b/include/linux/gpio/consumer.h |
| @@ -29,6 +29,7 @@ struct gpio_descs { |
| #define GPIOD_FLAGS_BIT_DIR_SET BIT(0) |
| #define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) |
| #define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) |
| +#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3) |
| |
| /** |
| * Optional flags that can be passed to one of gpiod_* to configure direction |
| @@ -40,6 +41,11 @@ enum gpiod_flags { |
| GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT, |
| GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT | |
| GPIOD_FLAGS_BIT_DIR_VAL, |
| + GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET | |
| + GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_OPEN_DRAIN, |
| + GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET | |
| + GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_DIR_VAL | |
| + GPIOD_FLAGS_BIT_OPEN_DRAIN, |
| }; |
| |
| #ifdef CONFIG_GPIOLIB |
| -- |
| 2.19.0 |
| |