diff options
author | Haojian Zhuang <haojian.zhuang@linaro.org> | 2013-02-17 06:42:50 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-03-06 23:27:30 -0500 |
commit | 51e13c2475913d45a3ec546dee647538a9341d6a (patch) | |
tree | 4dc33099bddd1860ac04c6007611329b5789e2b4 | |
parent | f1f70479e999217ecbf619d71837fc5d77c680fb (diff) |
pinctrl: check pinctrl ready for gpio range
pinctrl_get_device_gpio_range() only checks whether a certain GPIO pin
is in gpio range. But maybe some GPIO pins don't have back-end pinctrl
interface, it means that these pins are always configured as GPIO
function. For example, gpio159 isn't related to back-end pinctrl device
in Hi3620 while other GPIO pins are related to back-end pinctrl device.
Append pinctrl_ready_for_gpio_range() that is used to check whether
pinctrl device with GPIO range is ready. This function will be called
after pinctrl_get_device_gpio_range() fails.
If pinctrl device with GPIO range is found, it means that pinctrl device
is already launched and a certain GPIO pin just don't have back-end pinctrl
interface. Then pinctrl_request_gpio() shouldn't return -EPROBE_DEFER in
this case.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/core.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index e2d214c5c58f..f8a632dc877b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pinctrl/consumer.h> | 27 | #include <linux/pinctrl/consumer.h> |
28 | #include <linux/pinctrl/pinctrl.h> | 28 | #include <linux/pinctrl/pinctrl.h> |
29 | #include <linux/pinctrl/machine.h> | 29 | #include <linux/pinctrl/machine.h> |
30 | #include <asm-generic/gpio.h> | ||
30 | #include "core.h" | 31 | #include "core.h" |
31 | #include "devicetree.h" | 32 | #include "devicetree.h" |
32 | #include "pinmux.h" | 33 | #include "pinmux.h" |
@@ -277,6 +278,39 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio) | |||
277 | } | 278 | } |
278 | 279 | ||
279 | /** | 280 | /** |
281 | * pinctrl_ready_for_gpio_range() - check if other GPIO pins of | ||
282 | * the same GPIO chip are in range | ||
283 | * @gpio: gpio pin to check taken from the global GPIO pin space | ||
284 | * | ||
285 | * This function is complement of pinctrl_match_gpio_range(). If the return | ||
286 | * value of pinctrl_match_gpio_range() is NULL, this function could be used | ||
287 | * to check whether pinctrl device is ready or not. Maybe some GPIO pins | ||
288 | * of the same GPIO chip don't have back-end pinctrl interface. | ||
289 | * If the return value is true, it means that pinctrl device is ready & the | ||
290 | * certain GPIO pin doesn't have back-end pinctrl device. If the return value | ||
291 | * is false, it means that pinctrl device may not be ready. | ||
292 | */ | ||
293 | static bool pinctrl_ready_for_gpio_range(unsigned gpio) | ||
294 | { | ||
295 | struct pinctrl_dev *pctldev; | ||
296 | struct pinctrl_gpio_range *range = NULL; | ||
297 | struct gpio_chip *chip = gpio_to_chip(gpio); | ||
298 | |||
299 | /* Loop over the pin controllers */ | ||
300 | list_for_each_entry(pctldev, &pinctrldev_list, node) { | ||
301 | /* Loop over the ranges */ | ||
302 | list_for_each_entry(range, &pctldev->gpio_ranges, node) { | ||
303 | /* Check if any gpio range overlapped with gpio chip */ | ||
304 | if (range->base + range->npins - 1 < chip->base || | ||
305 | range->base > chip->base + chip->ngpio - 1) | ||
306 | continue; | ||
307 | return true; | ||
308 | } | ||
309 | } | ||
310 | return false; | ||
311 | } | ||
312 | |||
313 | /** | ||
280 | * pinctrl_get_device_gpio_range() - find device for GPIO range | 314 | * pinctrl_get_device_gpio_range() - find device for GPIO range |
281 | * @gpio: the pin to locate the pin controller for | 315 | * @gpio: the pin to locate the pin controller for |
282 | * @outdev: the pin control device if found | 316 | * @outdev: the pin control device if found |
@@ -443,6 +477,8 @@ int pinctrl_request_gpio(unsigned gpio) | |||
443 | 477 | ||
444 | ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); | 478 | ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); |
445 | if (ret) { | 479 | if (ret) { |
480 | if (pinctrl_ready_for_gpio_range(gpio)) | ||
481 | ret = 0; | ||
446 | mutex_unlock(&pinctrl_mutex); | 482 | mutex_unlock(&pinctrl_mutex); |
447 | return ret; | 483 | return ret; |
448 | } | 484 | } |