aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-10-12 17:20:20 -0400
committerLinus Walleij <linus.walleij@linaro.org>2015-10-16 16:46:46 -0400
commit923b93e451db876d1479d3e4458fce14fec31d1c (patch)
tree4f8252982415c3f29a36e739f453b7c030eda878 /drivers/gpio
parent98c85d583a5dee70d75faed3eb79851dd0a2e2fe (diff)
gpiolib: Split GPIO flags parsing and GPIO configuration
When requesting a GPIO through the legacy or the gpiod_* API the gpiochip request operation is first called and then the GPIO flags are parsed and the GPIO is configured. This prevents the gpiochip from rejecting the request if the flags are not supported by the device. To fix this split the parse-and-configure operation in two and parse flags before requesting the GPIO. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib-legacy.c8
-rw-r--r--drivers/gpio/gpiolib.c52
2 files changed, 40 insertions, 20 deletions
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 8b830996fe02..3a5c7011ad3b 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -28,10 +28,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
28 if (!desc && gpio_is_valid(gpio)) 28 if (!desc && gpio_is_valid(gpio))
29 return -EPROBE_DEFER; 29 return -EPROBE_DEFER;
30 30
31 err = gpiod_request(desc, label);
32 if (err)
33 return err;
34
35 if (flags & GPIOF_OPEN_DRAIN) 31 if (flags & GPIOF_OPEN_DRAIN)
36 set_bit(FLAG_OPEN_DRAIN, &desc->flags); 32 set_bit(FLAG_OPEN_DRAIN, &desc->flags);
37 33
@@ -41,6 +37,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
41 if (flags & GPIOF_ACTIVE_LOW) 37 if (flags & GPIOF_ACTIVE_LOW)
42 set_bit(FLAG_ACTIVE_LOW, &desc->flags); 38 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
43 39
40 err = gpiod_request(desc, label);
41 if (err)
42 return err;
43
44 if (flags & GPIOF_DIR_IN) 44 if (flags & GPIOF_DIR_IN)
45 err = gpiod_direction_input(desc); 45 err = gpiod_direction_input(desc);
46 else 46 else
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8eba02db5608..1615cc904702 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -927,6 +927,14 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
927 spin_lock_irqsave(&gpio_lock, flags); 927 spin_lock_irqsave(&gpio_lock, flags);
928 } 928 }
929done: 929done:
930 if (status < 0) {
931 /* Clear flags that might have been set by the caller before
932 * requesting the GPIO.
933 */
934 clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
935 clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
936 clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
937 }
930 spin_unlock_irqrestore(&gpio_lock, flags); 938 spin_unlock_irqrestore(&gpio_lock, flags);
931 return status; 939 return status;
932} 940}
@@ -2041,13 +2049,28 @@ struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
2041} 2049}
2042EXPORT_SYMBOL_GPL(gpiod_get_optional); 2050EXPORT_SYMBOL_GPL(gpiod_get_optional);
2043 2051
2052/**
2053 * gpiod_parse_flags - helper function to parse GPIO lookup flags
2054 * @desc: gpio to be setup
2055 * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
2056 * of_get_gpio_hog()
2057 *
2058 * Set the GPIO descriptor flags based on the given GPIO lookup flags.
2059 */
2060static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
2061{
2062 if (lflags & GPIO_ACTIVE_LOW)
2063 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
2064 if (lflags & GPIO_OPEN_DRAIN)
2065 set_bit(FLAG_OPEN_DRAIN, &desc->flags);
2066 if (lflags & GPIO_OPEN_SOURCE)
2067 set_bit(FLAG_OPEN_SOURCE, &desc->flags);
2068}
2044 2069
2045/** 2070/**
2046 * gpiod_configure_flags - helper function to configure a given GPIO 2071 * gpiod_configure_flags - helper function to configure a given GPIO
2047 * @desc: gpio whose value will be assigned 2072 * @desc: gpio whose value will be assigned
2048 * @con_id: function within the GPIO consumer 2073 * @con_id: function within the GPIO consumer
2049 * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
2050 * of_get_gpio_hog()
2051 * @dflags: gpiod_flags - optional GPIO initialization flags 2074 * @dflags: gpiod_flags - optional GPIO initialization flags
2052 * 2075 *
2053 * Return 0 on success, -ENOENT if no GPIO has been assigned to the 2076 * Return 0 on success, -ENOENT if no GPIO has been assigned to the
@@ -2055,17 +2078,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
2055 * occurred while trying to acquire the GPIO. 2078 * occurred while trying to acquire the GPIO.
2056 */ 2079 */
2057static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, 2080static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
2058 unsigned long lflags, enum gpiod_flags dflags) 2081 enum gpiod_flags dflags)
2059{ 2082{
2060 int status; 2083 int status;
2061 2084
2062 if (lflags & GPIO_ACTIVE_LOW)
2063 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
2064 if (lflags & GPIO_OPEN_DRAIN)
2065 set_bit(FLAG_OPEN_DRAIN, &desc->flags);
2066 if (lflags & GPIO_OPEN_SOURCE)
2067 set_bit(FLAG_OPEN_SOURCE, &desc->flags);
2068
2069 /* No particular flag request, return here... */ 2085 /* No particular flag request, return here... */
2070 if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { 2086 if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
2071 pr_debug("no flags found for %s\n", con_id); 2087 pr_debug("no flags found for %s\n", con_id);
@@ -2132,11 +2148,13 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
2132 return desc; 2148 return desc;
2133 } 2149 }
2134 2150
2151 gpiod_parse_flags(desc, lookupflags);
2152
2135 status = gpiod_request(desc, con_id); 2153 status = gpiod_request(desc, con_id);
2136 if (status < 0) 2154 if (status < 0)
2137 return ERR_PTR(status); 2155 return ERR_PTR(status);
2138 2156
2139 status = gpiod_configure_flags(desc, con_id, lookupflags, flags); 2157 status = gpiod_configure_flags(desc, con_id, flags);
2140 if (status < 0) { 2158 if (status < 0) {
2141 dev_dbg(dev, "setup of GPIO %s failed\n", con_id); 2159 dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
2142 gpiod_put(desc); 2160 gpiod_put(desc);
@@ -2190,14 +2208,14 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
2190 if (IS_ERR(desc)) 2208 if (IS_ERR(desc))
2191 return desc; 2209 return desc;
2192 2210
2193 ret = gpiod_request(desc, NULL);
2194 if (ret)
2195 return ERR_PTR(ret);
2196
2197 /* Only value flag can be set from both DT and ACPI is active_low */ 2211 /* Only value flag can be set from both DT and ACPI is active_low */
2198 if (active_low) 2212 if (active_low)
2199 set_bit(FLAG_ACTIVE_LOW, &desc->flags); 2213 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
2200 2214
2215 ret = gpiod_request(desc, NULL);
2216 if (ret)
2217 return ERR_PTR(ret);
2218
2201 return desc; 2219 return desc;
2202} 2220}
2203EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); 2221EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@ -2250,6 +2268,8 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
2250 chip = gpiod_to_chip(desc); 2268 chip = gpiod_to_chip(desc);
2251 hwnum = gpio_chip_hwgpio(desc); 2269 hwnum = gpio_chip_hwgpio(desc);
2252 2270
2271 gpiod_parse_flags(desc, lflags);
2272
2253 local_desc = gpiochip_request_own_desc(chip, hwnum, name); 2273 local_desc = gpiochip_request_own_desc(chip, hwnum, name);
2254 if (IS_ERR(local_desc)) { 2274 if (IS_ERR(local_desc)) {
2255 pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n", 2275 pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
@@ -2257,7 +2277,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
2257 return PTR_ERR(local_desc); 2277 return PTR_ERR(local_desc);
2258 } 2278 }
2259 2279
2260 status = gpiod_configure_flags(desc, name, lflags, dflags); 2280 status = gpiod_configure_flags(desc, name, dflags);
2261 if (status < 0) { 2281 if (status < 0) {
2262 pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n", 2282 pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
2263 name, chip->label, hwnum); 2283 name, chip->label, hwnum);