GPIOs can be requested with GPIOD_ASIS and with this the GPIO should be kept in its current state. This doesn't work currently as GPIOD_ASIS is defined as 0 and the flags are then interpreted as GPIOF_INIT_LOW (also 0).
To fix this set GPIOD_ASIS to a bit value which makes it a flag which can be explicitly tested for. Note this is different than in Linux. Linux defines GPIOD_ASIS to 0 just like barebox did, but in Linux the other GPIOD_* flags have an explicit "change this setting" flag which we don't have in barebox. Introducing these flags in barebox would mean we have to add the "change this setting" flags in various other places, like for example gpiod_request_one(). Motivation for this patch is the only current user of GPIOD_ASIS, the fixed regulator driver. Without this patch regulators will already be enabled in the fixed regulator drivers probe function. Signed-off-by: Sascha Hauer <[email protected]> --- drivers/gpio/gpiolib.c | 15 +++++++++------ include/gpio.h | 2 ++ include/linux/gpio/consumer.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index ec4d8e889bb1e7671f844c5c158188b7b9a23888..e1493ffb6640bc417996f81c45197c32441a8d69 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -622,6 +622,7 @@ static int gpiodesc_request_one(struct gpio_desc *desc, unsigned long lflags, const bool logical = (dflags & GPIOF_LOGICAL) == GPIOF_LOGICAL; const bool init_active = (dflags & GPIOF_INIT_ACTIVE) == GPIOF_INIT_ACTIVE; const bool init_high = (dflags & GPIOF_INIT_HIGH) == GPIOF_INIT_HIGH; + const bool set = (dflags & GPIOF_ASIS) == GPIOF_ASIS; err = gpiodesc_request(desc, label); if (err) @@ -631,12 +632,14 @@ static int gpiodesc_request_one(struct gpio_desc *desc, unsigned long lflags, if (active_low) desc->flags |= OF_GPIO_ACTIVE_LOW; - if (dir_in) - err = gpiod_direction_input(desc); - else if (logical) - err = gpiod_direction_output(desc, init_active); - else - err = gpiod_direction_output_raw(desc, init_high); + if (!set) { + if (dir_in) + err = gpiod_direction_input(desc); + else if (logical) + err = gpiod_direction_output(desc, init_active); + else + err = gpiod_direction_output_raw(desc, init_high); + } if (err) gpiodesc_free(desc); diff --git a/include/gpio.h b/include/gpio.h index 92fd27b2b996eed8777e9321b4f34e245ceca480..2264d0c495a4439f0f8b23e023e28f7472c90889 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -114,6 +114,8 @@ static inline int gpio_is_valid(int gpio) #define GPIOF_OUT_INIT_ACTIVE (GPIOF_DIR_OUT | GPIOF_INIT_ACTIVE) #define GPIOF_OUT_INIT_INACTIVE (GPIOF_DIR_OUT | GPIOF_INIT_INACTIVE) +#define GPIOF_ASIS BIT(4) + /** * struct gpio - a structure describing a GPIO with configuration * @gpio: the GPIO number diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index c461f3f3108bd9e31777df2a37ffb469fafb36bd..a425145351b0da1476e9327dfebb2e13801488f3 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -13,7 +13,7 @@ * and output value. These values cannot be OR'd. */ enum gpiod_flags { - GPIOD_ASIS = 0, + GPIOD_ASIS = GPIOF_ASIS, GPIOD_IN = GPIOF_IN, /* * To change this later to a different logic level (i.e. taking -- 2.47.3
