diff options
| author | 2022-11-08 15:38:53 +0200 | |
|---|---|---|
| committer | 2022-11-09 14:10:27 +0100 | |
| commit | 27043a7d500c4a3debb899c28bbf492492f64e58 (patch) | |
| tree | 01e53a1fe81b6229214e2ec49a87e8337901e2ac /drivers/gpio/gpiolib.c | |
| parent | gpiolib: of: Prepare of_gpiochip_add() / of_gpiochip_remove() for fwnode (diff) | |
| download | linux-rng-27043a7d500c4a3debb899c28bbf492492f64e58.tar.xz linux-rng-27043a7d500c4a3debb899c28bbf492492f64e58.zip | |
gpiolib: of: Integrate of_gpiochip_init_valid_mask() into gpiochip_init_valid_mask()
In preparation to complete fwnode switch, integrate
of_gpiochip_init_valid_mask() into gpiochip_init_valid_mask().
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Diffstat (limited to '')
| -rw-r--r-- | drivers/gpio/gpiolib.c | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8faedca6b14..11fb7ec883e9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -445,9 +445,21 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc) return p; } +static unsigned int gpiochip_count_reserved_ranges(struct gpio_chip *gc) +{ + int size; + + /* Format is "start, count, ..." */ + size = fwnode_property_count_u32(gc->fwnode, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + return size; + + return 0; +} + static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { - if (!(of_gpio_need_valid_mask(gc) || gc->init_valid_mask)) + if (!(gpiochip_count_reserved_ranges(gc) || gc->init_valid_mask)) return 0; gc->valid_mask = gpiochip_allocate_mask(gc); @@ -457,8 +469,48 @@ static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) return 0; } +static int gpiochip_apply_reserved_ranges(struct gpio_chip *gc) +{ + unsigned int size; + u32 *ranges; + int ret; + + size = gpiochip_count_reserved_ranges(gc); + if (size == 0) + return 0; + + ranges = kmalloc_array(size, sizeof(*ranges), GFP_KERNEL); + if (!ranges) + return -ENOMEM; + + ret = fwnode_property_read_u32_array(gc->fwnode, "gpio-reserved-ranges", ranges, size); + if (ret) { + kfree(ranges); + return ret; + } + + while (size) { + u32 count = ranges[--size]; + u32 start = ranges[--size]; + + if (start >= gc->ngpio || start + count > gc->ngpio) + continue; + + bitmap_clear(gc->valid_mask, start, count); + } + + kfree(ranges); + return 0; +} + static int gpiochip_init_valid_mask(struct gpio_chip *gc) { + int ret; + + ret = gpiochip_apply_reserved_ranges(gc); + if (ret) + return ret; + if (gc->init_valid_mask) return gc->init_valid_mask(gc, gc->valid_mask, |
