summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2022-11-08 15:38:53 +0200
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>2022-11-09 14:10:27 +0100
commit27043a7d500c4a3debb899c28bbf492492f64e58 (patch)
tree01e53a1fe81b6229214e2ec49a87e8337901e2ac /drivers/gpio/gpiolib.c
parent8afe82550240640617abfb3d6ba2c7579261e7fa (diff)
downloadlinux-27043a7d500c4a3debb899c28bbf492492f64e58.tar.bz2
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 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c54
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,