Skip to content

Commit

Permalink
gpio: mmio: handle "ngpios" properly in bgpio_init()
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
  • Loading branch information
Asmaa Mnebhi authored and intel-lab-lkp committed Mar 3, 2023
1 parent 4827aae commit 3a5c965
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 33 deletions.
7 changes: 6 additions & 1 deletion drivers/gpio/gpio-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
#include <linux/of.h>
#include <linux/of_device.h>

#include "gpiolib.h"

static void bgpio_write8(void __iomem *reg, unsigned long data)
{
writeb(data, reg);
Expand Down Expand Up @@ -614,10 +616,13 @@ 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;

ret = bgpio_setup_io(gc, dat, set, clr, flags);
if (ret)
return ret;
Expand Down
58 changes: 26 additions & 32 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,28 @@ static void gpiochip_setup_devs(void)
}
}

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) {
chip_err(gc, "Failed to get ngpios property\n");
return -EINVAL;
}

gc->ngpio = ngpios;
}

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;
}

int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
Expand All @@ -656,7 +678,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct gpio_device *gdev;
unsigned long flags;
unsigned int i;
u32 ngpios = 0;
int base = 0;
int ret = 0;

Expand Down Expand Up @@ -700,36 +721,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
else
gdev->owner = THIS_MODULE;

/*
* Try the device properties if the driver didn't supply the number
* of GPIO lines.
*/
ngpios = gc->ngpio;
if (ngpios == 0) {
ret = device_property_read_u32(&gdev->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)
goto err_free_dev_name;

gc->ngpio = ngpios;
}

if (gc->ngpio == 0) {
chip_err(gc, "tried to insert a GPIO chip with zero lines\n");
ret = -EINVAL;
goto err_free_dev_name;
}

if (gc->ngpio > FASTPATH_NGPIO)
chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n",
gc->ngpio, FASTPATH_NGPIO);
ret = gpiochip_get_ngpios(gc, &gdev->dev);
if (ret)
return ret;

gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
if (!gdev->descs) {
Expand Down Expand Up @@ -899,7 +893,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
/* failures here can mean systems won't boot... */
if (ret != -EPROBE_DEFER) {
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
base, base + (int)ngpios - 1,
base, base + (int)gc->ngpio - 1,
gc->label ? : "generic", ret);
}
return ret;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpio/gpiolib.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
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
Expand Down

0 comments on commit 3a5c965

Please sign in to comment.