diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index a7d69f3835c1..91ff789c4fa6 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -578,7 +579,7 @@ static int __init gpio_mockup_register_chip(int idx) static int __init gpio_mockup_init(void) { - int i, num_chips, err; + int i, num_chips, err, base, ngpio; if ((gpio_mockup_num_ranges % 2) || (gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES)) @@ -592,8 +593,19 @@ static int __init gpio_mockup_init(void) * always be greater than 0. */ for (i = 0; i < num_chips; i++) { - if (gpio_mockup_range_ngpio(i) < 0) + base = gpio_mockup_range_base(i); + ngpio = gpio_mockup_range_ngpio(i); + + if (ngpio <= 0) return -EINVAL; + + if (base < 0) { + if (ngpio > U16_MAX) + return -EINVAL; + } else { + if (ngpio <= base || ngpio - base > U16_MAX) + return -EINVAL; + } } gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL); diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 22c36b79e249..c030d1f00abc 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -996,7 +996,7 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) BUG(); } - if (IS_REACHABLE(CONFIG_PWM)) + if (IS_REACHABLE(CONFIG_PWM) && mvchip->mvpwm) mvebu_pwm_suspend(mvchip); return 0; @@ -1048,7 +1048,7 @@ static int mvebu_gpio_resume(struct platform_device *pdev) BUG(); } - if (IS_REACHABLE(CONFIG_PWM)) + if (IS_REACHABLE(CONFIG_PWM) && mvchip->mvpwm) mvebu_pwm_resume(mvchip); return 0; diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index bc97d5d5d329..9478a58f1caa 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -802,8 +802,10 @@ static void rockchip_gpio_remove(struct platform_device *pdev) struct rockchip_pin_bank *bank = platform_get_drvdata(pdev); irq_set_chained_handler_and_data(bank->irq, NULL, NULL); - if (bank->domain) + if (bank->domain) { + irq_domain_remove_generic_chips(bank->domain); irq_domain_remove(bank->domain); + } gpiochip_remove(&bank->gpio_chip); } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 571e366624d2..fafca91128b2 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1014,6 +1014,7 @@ static void zynq_gpio_remove(struct platform_device *pdev) gpiochip_remove(&gpio->chip); device_set_wakeup_capable(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); } static struct platform_driver zynq_gpio_driver = { diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 2c923d17541f..813dbcb91f6f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -1066,11 +1066,6 @@ int of_gpiochip_add(struct gpio_chip *chip) of_node_get(np); - for_each_available_child_of_node_scoped(np, child) { - if (of_property_read_bool(child, "gpio-hog")) - of_node_set_flag(child, OF_POPULATED); - } - return ret; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1e6dce430dca..c1f9c0d367d5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1031,9 +1031,17 @@ static int gpiochip_hog_lines(struct gpio_chip *gc) if (!fwnode_property_present(fwnode, "gpio-hog")) continue; + /* The hog may have been handled by another gpio_chip on the same fwnode */ + if (is_of_node(fwnode) && + of_node_check_flag(to_of_node(fwnode), OF_POPULATED)) + continue; + ret = gpiochip_add_hog(gc, fwnode); if (ret) return ret; + + if (is_of_node(fwnode)) + of_node_set_flag(to_of_node(fwnode), OF_POPULATED); } return 0; @@ -1291,7 +1299,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ret = gpiochip_hog_lines(gc); if (ret) - goto err_remove_of_chip; + goto err_free_hogs; ret = gpiochip_irqchip_init_valid_mask(gc); if (ret)