From 99a91873f7fe56dcdb4dc68b5a0766b63465ccbb Mon Sep 17 00:00:00 2001 From: Asmaa Mnebhi Date: Thu, 30 Mar 2023 12:25:27 -0400 Subject: [PATCH 76/77] UBUNTU: SAUCE: gpio: mmio: handle "ngpios" properly in bgpio_init() X-NVConfidentiality: public BugLink: https://bugs.launchpad.net/bugs/2012743 bgpio_init() uses "sz" argument to populate ngpio, which is not accurate. Instead, read the "ngpios" property from the DT and if it doesn't exist, use the "sz" argument. With this change, drivers no longer need to overwrite the ngpio variable after calling bgpio_init(). This change has already been approved for upstreaming but has not been integrated into the linux-next branch yet (or any other branch as a matter of fact). There are 2 commits involved: gpio: mmio: handle "ngpios" properly in bgpio_init() - gpio: mmio: fix calculation of bgpio_bits There is no point in separating these 2 commits into 2 SAUCE patches since they target the same functionality and will be reverted soon anyways to cherry-pick the linux-next commits. Signed-off-by: Asmaa Mnebhi Acked-by: Tim Gardner Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/gpio/gpio-mmio.c | 9 ++++++++- drivers/gpio/gpiolib.c | 34 ++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib.h | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index c335a0309..ababc4091 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -60,6 +60,8 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` #include #include +#include "gpiolib.h" + static void bgpio_write8(void __iomem *reg, unsigned long data) { writeb(data, reg); @@ -614,10 +616,15 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, gc->parent = dev; gc->label = dev_name(dev); gc->base = -1; - gc->ngpio = gc->bgpio_bits; gc->request = bgpio_request; gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); + ret = gpiochip_get_ngpios(gc, dev); + if (ret) + gc->ngpio = gc->bgpio_bits; + else + gc->bgpio_bits = roundup_pow_of_two(round_up(gc->ngpio, 8)); + ret = bgpio_setup_io(gc, dat, set, clr, flags); if (ret) return ret; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3e01a3ac6..964f27f4d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -550,6 +550,40 @@ static void machine_gpiochip_add(struct gpio_chip *gc) mutex_unlock(&gpio_machine_hogs_mutex); } +int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev) +{ + u32 ngpios = gc->ngpio; + int ret; + + if (ngpios == 0) { + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (ret == -ENODATA) + /* + * -ENODATA means that there is no property found and + * we want to issue the error message to the user. + * Besides that, we want to return different error code + * to state that supplied value is not valid. + */ + ngpios = 0; + else if (ret) + return ret; + + gc->ngpio = ngpios; + } + + if (gc->ngpio == 0) { + chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); + return -EINVAL; + } + + if (gc->ngpio > FASTPATH_NGPIO) + chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", + gc->ngpio, FASTPATH_NGPIO); + + return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_get_ngpios); + static void gpiochip_setup_devs(void) { struct gpio_device *gdev; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index b674b5bb9..7c26a0060 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -136,6 +136,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, unsigned long lflags, enum gpiod_flags dflags); int gpiod_hog(struct gpio_desc *desc, const char *name, unsigned long lflags, enum gpiod_flags dflags); +int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev); /* * Return the GPIO number of the passed descriptor relative to its chip -- 2.14.1