diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/TODO | 34 | ||||
-rw-r--r-- | drivers/gpio/gpio-brcmstb.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-davinci.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-em.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-grgpio.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-idt3243x.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-lpc18xx.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 17 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpio-pxa.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpio-rockchip.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-sa1100.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-sodaville.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-tb10x.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra186.c | 27 | ||||
-rw-r--r-- | drivers/gpio/gpio-twl4030.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-virtuser.c | 12 | ||||
-rw-r--r-- | drivers/gpio/gpio-zynq.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-devres.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 8 |
24 files changed, 114 insertions, 57 deletions
diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index c1f4c63a7605..4a8b349f2483 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -193,3 +193,37 @@ their hardware offsets within the chip. Encourage users to switch to using them and eventually remove the existing global export/unexport attribues. + +------------------------------------------------------------------------------- + +Remove GPIOD_FLAGS_BIT_NONEXCLUSIVE + +GPIOs in the linux kernel are meant to be an exclusive resource. This means +that the GPIO descriptors (the software representation of the hardware concept) +are not reference counted and - in general - only one user at a time can +request a GPIO line and control its settings. The consumer API is designed +around full control of the line's state as evidenced by the fact that, for +instance, gpiod_set_value() does indeed drive the line as requested, instead +of bumping an enable counter of some sort. + +A problematic use-case for GPIOs is when two consumers want to use the same +descriptor independently. An example of such a user is the regulator subsystem +which may instantiate several struct regulator_dev instances containing +a struct device but using the same enable GPIO line. + +A workaround was introduced in the form of the GPIOD_FLAGS_BIT_NONEXCLUSIVE +flag but its implementation is problematic: it does not provide any +synchronization of usage nor did it introduce any enable count meaning the +non-exclusive users of the same descriptor will in fact "fight" for the +control over it. This flag should be removed and replaced with a better +solution, possibly based on the new power sequencing subsystem. + +------------------------------------------------------------------------------- + +Remove devm_gpiod_unhinge() + +devm_gpiod_unhinge() is provided as a way to transfer the ownership of managed +enable GPIOs to the regulator core. Rather than doing that however, we should +make it possible for the regulator subsystem to deal with GPIO resources the +lifetime of which it doesn't control as logically, a GPIO obtained by a caller +should also be freed by it. diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index ca3472977431..e7671bcd5c07 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -437,7 +437,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, int err; priv->irq_domain = - irq_domain_add_linear(np, priv->num_gpios, + irq_domain_create_linear(of_fwnode_handle(np), priv->num_gpios, &brcmstb_gpio_irq_domain_ops, priv); if (!priv->irq_domain) { diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index bd1821ecb2ea..80a82492171e 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -478,9 +478,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) return irq; } - irq_domain = irq_domain_add_legacy(dev->of_node, ngpio, irq, 0, - &davinci_gpio_irq_ops, - chips); + irq_domain = irq_domain_create_legacy(of_fwnode_handle(dev->of_node), ngpio, irq, 0, + &davinci_gpio_irq_ops, chips); if (!irq_domain) { dev_err(dev, "Couldn't register an IRQ domain\n"); return -ENODEV; diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 857c28895131..a5e6e446f39c 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -325,8 +325,9 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0, - &em_gio_irq_domain_ops, p); + p->irq_domain = irq_domain_create_simple(of_fwnode_handle(dev->of_node), + ngpios, 0, + &em_gio_irq_domain_ops, p); if (!p->irq_domain) { dev_err(dev, "cannot initialize irq domain\n"); return -ENXIO; diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 68cca7751c0e..d38a2d9854ca 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -402,7 +402,7 @@ static int grgpio_probe(struct platform_device *ofdev) return -EINVAL; } - priv->domain = irq_domain_add_linear(np, gc->ngpio, + priv->domain = irq_domain_create_linear(of_fwnode_handle(np), gc->ngpio, &grgpio_irq_domain_ops, priv); if (!priv->domain) { diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c index 00f547d26254..535f25514455 100644 --- a/drivers/gpio/gpio-idt3243x.c +++ b/drivers/gpio/gpio-idt3243x.c @@ -37,7 +37,7 @@ static void idt_gpio_dispatch(struct irq_desc *desc) pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); pending &= ~ctrl->mask_cache; for_each_set_bit(bit, &pending, gc->ngpio) { - virq = irq_linear_revmap(gc->irq.domain, bit); + virq = irq_find_mapping(gc->irq.domain, bit); if (virq) generic_handle_irq(virq); } diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index fffc13da673e..b0a8da5c058d 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -248,11 +248,9 @@ static int lpc18xx_gpio_pin_ic_probe(struct lpc18xx_gpio_chip *gc) raw_spin_lock_init(&ic->lock); - ic->domain = irq_domain_add_hierarchy(parent_domain, 0, - NR_LPC18XX_GPIO_PIN_IC_IRQS, - dev->of_node, - &lpc18xx_gpio_pin_ic_domain_ops, - ic); + ic->domain = irq_domain_create_hierarchy(parent_domain, 0, NR_LPC18XX_GPIO_PIN_IC_IRQS, + of_fwnode_handle(dev->of_node), + &lpc18xx_gpio_pin_ic_domain_ops, ic); if (!ic->domain) { pr_err("unable to add irq domain\n"); ret = -ENODEV; diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 805ac9607b56..121efdd71e45 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -418,7 +418,9 @@ static int mpc8xxx_probe(struct platform_device *pdev) goto err; } - device_init_wakeup(dev, true); + ret = devm_device_init_wakeup(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to init wakeup\n"); return 0; err: diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 3604abcb6fec..57633a7b4270 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -408,9 +408,8 @@ static void mvebu_gpio_irq_ack(struct irq_data *d) struct mvebu_gpio_chip *mvchip = gc->private; u32 mask = d->mask; - irq_gc_lock(gc); + guard(raw_spinlock)(&gc->lock); mvebu_gpio_write_edge_cause(mvchip, ~mask); - irq_gc_unlock(gc); } static void mvebu_gpio_edge_irq_mask(struct irq_data *d) @@ -420,10 +419,9 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d) struct irq_chip_type *ct = irq_data_get_chip_type(d); u32 mask = d->mask; - irq_gc_lock(gc); + guard(raw_spinlock)(&gc->lock); ct->mask_cache_priv &= ~mask; mvebu_gpio_write_edge_mask(mvchip, ct->mask_cache_priv); - irq_gc_unlock(gc); } static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) @@ -433,11 +431,10 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) struct irq_chip_type *ct = irq_data_get_chip_type(d); u32 mask = d->mask; - irq_gc_lock(gc); + guard(raw_spinlock)(&gc->lock); mvebu_gpio_write_edge_cause(mvchip, ~mask); ct->mask_cache_priv |= mask; mvebu_gpio_write_edge_mask(mvchip, ct->mask_cache_priv); - irq_gc_unlock(gc); } static void mvebu_gpio_level_irq_mask(struct irq_data *d) @@ -447,10 +444,9 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d) struct irq_chip_type *ct = irq_data_get_chip_type(d); u32 mask = d->mask; - irq_gc_lock(gc); + guard(raw_spinlock)(&gc->lock); ct->mask_cache_priv &= ~mask; mvebu_gpio_write_level_mask(mvchip, ct->mask_cache_priv); - irq_gc_unlock(gc); } static void mvebu_gpio_level_irq_unmask(struct irq_data *d) @@ -460,10 +456,9 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) struct irq_chip_type *ct = irq_data_get_chip_type(d); u32 mask = d->mask; - irq_gc_lock(gc); + guard(raw_spinlock)(&gc->lock); ct->mask_cache_priv |= mask; mvebu_gpio_write_level_mask(mvchip, ct->mask_cache_priv); - irq_gc_unlock(gc); } /***************************************************************************** @@ -1242,7 +1237,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) return 0; mvchip->domain = - irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL); + irq_domain_create_linear(of_fwnode_handle(np), ngpios, &irq_generic_chip_ops, NULL); if (!mvchip->domain) { dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", mvchip->chip.label); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 38504c9486b0..fae1a30f8ae6 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -509,7 +509,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) goto out_bgio; } - port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, + port->domain = irq_domain_create_legacy(of_fwnode_handle(np), 32, irq_base, 0, &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 024ad077e98d..b418fbccb26c 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -303,8 +303,8 @@ static int mxs_gpio_probe(struct platform_device *pdev) goto out_iounmap; } - port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, - &irq_domain_simple_ops, NULL); + port->domain = irq_domain_create_legacy(of_fwnode_handle(np), 32, irq_base, 0, + &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; goto out_iounmap; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index ab2c0fd428fb..b852e4997629 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1226,6 +1226,8 @@ static int pca953x_restore_context(struct pca953x_chip *chip) guard(mutex)(&chip->i2c_lock); + if (chip->client->irq > 0) + enable_irq(chip->client->irq); regcache_cache_only(chip->regmap, false); regcache_mark_dirty(chip->regmap); ret = pca953x_regcache_sync(chip); @@ -1238,6 +1240,10 @@ static int pca953x_restore_context(struct pca953x_chip *chip) static void pca953x_save_context(struct pca953x_chip *chip) { guard(mutex)(&chip->i2c_lock); + + /* Disable IRQ to prevent early triggering while regmap "cache only" is on */ + if (chip->client->irq > 0) + disable_irq(chip->client->irq); regcache_cache_only(chip->regmap, true); } diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 530ddeaba2f1..aead35ea090e 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -642,9 +642,9 @@ static int pxa_gpio_probe(struct platform_device *pdev) if (!pxa_last_gpio) return -EINVAL; - pchip->irqdomain = irq_domain_add_legacy(pdev->dev.of_node, - pxa_last_gpio + 1, irq_base, - 0, &pxa_irq_domain_ops, pchip); + pchip->irqdomain = irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), + pxa_last_gpio + 1, irq_base, 0, + &pxa_irq_domain_ops, pchip); if (!pchip->irqdomain) return -ENOMEM; diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 01a3b3dac58b..c63352f2f1ec 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -521,7 +521,7 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) struct irq_chip_generic *gc; int ret; - bank->domain = irq_domain_add_linear(bank->of_node, 32, + bank->domain = irq_domain_create_linear(of_fwnode_handle(bank->of_node), 32, &irq_generic_chip_ops, NULL); if (!bank->domain) { dev_warn(bank->dev, "could not init irq domain for bank %s\n", diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 242dad763ac4..3f3ee36bc3cb 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -319,7 +319,7 @@ void __init sa1100_init_gpio(void) gpiochip_add_data(&sa1100_gpio_chip.chip, NULL); - sa1100_gpio_irqdomain = irq_domain_add_simple(NULL, + sa1100_gpio_irqdomain = irq_domain_create_simple(NULL, 28, IRQ_GPIO0, &sa1100_gpio_irqdomain_ops, sgc); diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index c2a2c76c1652..6a3c4c625138 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -169,7 +169,7 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); - sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, + sd->id = irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), SDV_NUM_PUB_GPIOS, sd->irq_base, 0, &irq_domain_sdv_ops, sd); if (!sd->id) return -ENODEV; diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index b6335cde455f..8cf676fd0a0b 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -183,7 +183,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) if (ret != 0) return ret; - tb10x_gpio->domain = irq_domain_add_linear(np, + tb10x_gpio->domain = irq_domain_create_linear(of_fwnode_handle(np), tb10x_gpio->gc.ngpio, &irq_generic_chip_ops, NULL); if (!tb10x_gpio->domain) { diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 6895b65c86af..d27bfac6c9f5 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -823,6 +823,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) struct gpio_irq_chip *irq; struct tegra_gpio *gpio; struct device_node *np; + struct resource *res; char **names; int err; @@ -842,19 +843,19 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->num_banks++; /* get register apertures */ - gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security"); - if (IS_ERR(gpio->secure)) { - gpio->secure = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(gpio->secure)) - return PTR_ERR(gpio->secure); - } - - gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio"); - if (IS_ERR(gpio->base)) { - gpio->base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(gpio->base)) - return PTR_ERR(gpio->base); - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "security"); + if (!res) + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + gpio->secure = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->secure)) + return PTR_ERR(gpio->secure); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio"); + if (!res) + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + gpio->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); err = platform_irq_count(pdev); if (err < 0) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index bcd692229c7c..0d17985a5fdc 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -502,7 +502,6 @@ static void gpio_twl4030_power_off_action(void *data) static int gpio_twl4030_probe(struct platform_device *pdev) { struct twl4030_gpio_platform_data *pdata; - struct device_node *node = pdev->dev.of_node; struct gpio_twl4030_priv *priv; int ret, irq_base; @@ -524,8 +523,8 @@ static int gpio_twl4030_probe(struct platform_device *pdev) return irq_base; } - irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0, - &irq_domain_simple_ops, NULL); + irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), TWL4030_GPIO_MAX, irq_base, 0, + &irq_domain_simple_ops, NULL); ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); if (ret < 0) diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c index 13407fd4f0eb..eab6726953b4 100644 --- a/drivers/gpio/gpio-virtuser.c +++ b/drivers/gpio/gpio-virtuser.c @@ -401,10 +401,15 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file, char buf[32], *trimmed; int ret, dir, val = 0; - ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count); + if (count >= sizeof(buf)) + return -EINVAL; + + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); if (ret < 0) return ret; + buf[ret] = '\0'; + trimmed = strim(buf); if (strcmp(trimmed, "input") == 0) { @@ -623,12 +628,15 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file, char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; int ret; + if (count >= sizeof(buf)) + return -EINVAL; + ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos, user_buf, count); if (ret < 0) return ret; - buf[strlen(buf) - 1] = '\0'; + buf[ret] = '\0'; ret = gpiod_set_consumer_name(data->ad.desc, buf); if (ret) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index be81fa2b17ab..3dae63f3ea21 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1011,6 +1011,7 @@ static void zynq_gpio_remove(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); + device_init_wakeup(&pdev->dev, 0); gpiochip_remove(&gpio->chip); device_set_wakeup_capable(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 840d0ad7c5ba..4d5f83b17624 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -279,6 +279,11 @@ EXPORT_SYMBOL_GPL(devm_gpiod_put); * @dev: GPIO consumer * @desc: GPIO descriptor to remove resource management from * + * *DEPRECATED* + * This function should not be used. It's been provided as a workaround for + * resource ownership issues in the regulator framework and should be replaced + * with a better solution. + * * Remove resource management from a GPIO descriptor. This is needed when * you want to hand over lifecycle management of a descriptor to another * mechanism. diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 3651c4178b81..73ba73b31cb1 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -193,6 +193,8 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np, */ { "himax,hx8357", "gpios-reset", false }, { "himax,hx8369", "gpios-reset", false }, +#endif +#if IS_ENABLED(CONFIG_MTD_NAND_JZ4780) /* * The rb-gpios semantics was undocumented and qi,lb60 (along with * the ingenic driver) got it wrong. The active state encodes the @@ -275,6 +277,9 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, { "fsl,imx8qm-fec", "phy-reset-gpios", "phy-reset-active-high" }, { "fsl,s32v234-fec", "phy-reset-gpios", "phy-reset-active-high" }, #endif +#if IS_ENABLED(CONFIG_MMC_ATMELMCI) + { "atmel,hsmci", "cd-gpios", "cd-inverted" }, +#endif #if IS_ENABLED(CONFIG_PCI_IMX6) { "fsl,imx6q-pcie", "reset-gpio", "reset-gpio-active-high" }, { "fsl,imx6sx-pcie", "reset-gpio", "reset-gpio-active-high" }, @@ -301,9 +306,6 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, { "regulator-gpio", "enable-gpio", "enable-active-high" }, { "regulator-gpio", "enable-gpios", "enable-active-high" }, #endif -#if IS_ENABLED(CONFIG_MMC_ATMELMCI) - { "atmel,hsmci", "cd-gpios", "cd-inverted" }, -#endif }; unsigned int i; bool active_high; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index a64647c9db75..fdafa0df1b43 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -784,6 +784,12 @@ EXPORT_SYMBOL_GPL(gpiochip_query_valid_mask); bool gpiochip_line_is_valid(const struct gpio_chip *gc, unsigned int offset) { + /* + * hog pins are requested before registering GPIO chip + */ + if (!gc->gpiodev) + return true; + /* No mask means all valid */ if (likely(!gc->gpiodev->valid_mask)) return true; @@ -2899,7 +2905,7 @@ static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value) * output-only, but if there is then not even a .set() operation it * is pretty tricky to drive the output line. */ - if (!guard.gc->set && !guard.gc->direction_output) { + if (!guard.gc->set && !guard.gc->set_rv && !guard.gc->direction_output) { gpiod_warn(desc, "%s: missing set() and direction_output() operations\n", __func__); |