Skip to content

Commit 8f43640

Browse files
committed
Merge tag 'gpio-fixes-for-v6.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: - fix resource handling in gpio-tegra186 - fix wakeup source leaks in gpio-mpc8xxx and gpio-zynq - fix minor issues with some GPIO OF quirks - deprecate GPIOD_FLAGS_BIT_NONEXCLUSIVE and devm_gpiod_unhinge() symbols and add a TODO task to track replacing them with a better solution * tag 'gpio-fixes-for-v6.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpiolib: of: Move Atmel HSMCI quirk up out of the regulator comment gpiolib: of: Fix the choice for Ingenic NAND quirk gpio: zynq: Fix wakeup source leaks on device unbind gpio: mpc8xxx: Fix wakeup source leaks on device unbind gpio: TODO: track the removal of regulator-related workarounds MAINTAINERS: add more keywords for the GPIO subsystem entry gpio: deprecate devm_gpiod_unhinge() gpio: deprecate the GPIOD_FLAGS_BIT_NONEXCLUSIVE flag gpio: tegra186: fix resource handling in ACPI probe path
2 parents b4991c0 + b8c7a1a commit 8f43640

File tree

8 files changed

+65
-18
lines changed

8 files changed

+65
-18
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10151,6 +10151,8 @@ F: include/linux/gpio.h
1015110151
F: include/linux/gpio/
1015210152
F: include/linux/of_gpio.h
1015310153
K: (devm_)?gpio_(request|free|direction|get|set)
10154+
K: GPIOD_FLAGS_BIT_NONEXCLUSIVE
10155+
K: devm_gpiod_unhinge
1015410156

1015510157
GPIO UAPI
1015610158
M: Bartosz Golaszewski <brgl@bgdev.pl>

drivers/gpio/TODO

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,37 @@ their hardware offsets within the chip.
186186

187187
Encourage users to switch to using them and eventually remove the existing
188188
global export/unexport attribues.
189+
190+
-------------------------------------------------------------------------------
191+
192+
Remove GPIOD_FLAGS_BIT_NONEXCLUSIVE
193+
194+
GPIOs in the linux kernel are meant to be an exclusive resource. This means
195+
that the GPIO descriptors (the software representation of the hardware concept)
196+
are not reference counted and - in general - only one user at a time can
197+
request a GPIO line and control its settings. The consumer API is designed
198+
around full control of the line's state as evidenced by the fact that, for
199+
instance, gpiod_set_value() does indeed drive the line as requested, instead
200+
of bumping an enable counter of some sort.
201+
202+
A problematic use-case for GPIOs is when two consumers want to use the same
203+
descriptor independently. An example of such a user is the regulator subsystem
204+
which may instantiate several struct regulator_dev instances containing
205+
a struct device but using the same enable GPIO line.
206+
207+
A workaround was introduced in the form of the GPIOD_FLAGS_BIT_NONEXCLUSIVE
208+
flag but its implementation is problematic: it does not provide any
209+
synchronization of usage nor did it introduce any enable count meaning the
210+
non-exclusive users of the same descriptor will in fact "fight" for the
211+
control over it. This flag should be removed and replaced with a better
212+
solution, possibly based on the new power sequencing subsystem.
213+
214+
-------------------------------------------------------------------------------
215+
216+
Remove devm_gpiod_unhinge()
217+
218+
devm_gpiod_unhinge() is provided as a way to transfer the ownership of managed
219+
enable GPIOs to the regulator core. Rather than doing that however, we should
220+
make it possible for the regulator subsystem to deal with GPIO resources the
221+
lifetime of which it doesn't control as logically, a GPIO obtained by a caller
222+
should also be freed by it.

drivers/gpio/gpio-mpc8xxx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
410410
goto err;
411411
}
412412

413-
device_init_wakeup(dev, true);
413+
ret = devm_device_init_wakeup(dev);
414+
if (ret)
415+
return dev_err_probe(dev, ret, "Failed to init wakeup\n");
414416

415417
return 0;
416418
err:

drivers/gpio/gpio-tegra186.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
823823
struct gpio_irq_chip *irq;
824824
struct tegra_gpio *gpio;
825825
struct device_node *np;
826+
struct resource *res;
826827
char **names;
827828
int err;
828829

@@ -842,19 +843,19 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
842843
gpio->num_banks++;
843844

844845
/* get register apertures */
845-
gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
846-
if (IS_ERR(gpio->secure)) {
847-
gpio->secure = devm_platform_ioremap_resource(pdev, 0);
848-
if (IS_ERR(gpio->secure))
849-
return PTR_ERR(gpio->secure);
850-
}
851-
852-
gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
853-
if (IS_ERR(gpio->base)) {
854-
gpio->base = devm_platform_ioremap_resource(pdev, 1);
855-
if (IS_ERR(gpio->base))
856-
return PTR_ERR(gpio->base);
857-
}
846+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "security");
847+
if (!res)
848+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
849+
gpio->secure = devm_ioremap_resource(&pdev->dev, res);
850+
if (IS_ERR(gpio->secure))
851+
return PTR_ERR(gpio->secure);
852+
853+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
854+
if (!res)
855+
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
856+
gpio->base = devm_ioremap_resource(&pdev->dev, res);
857+
if (IS_ERR(gpio->base))
858+
return PTR_ERR(gpio->base);
858859

859860
err = platform_irq_count(pdev);
860861
if (err < 0)

drivers/gpio/gpio-zynq.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@ static void zynq_gpio_remove(struct platform_device *pdev)
10111011
ret = pm_runtime_get_sync(&pdev->dev);
10121012
if (ret < 0)
10131013
dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n");
1014+
device_init_wakeup(&pdev->dev, 0);
10141015
gpiochip_remove(&gpio->chip);
10151016
device_set_wakeup_capable(&pdev->dev, 0);
10161017
pm_runtime_disable(&pdev->dev);

drivers/gpio/gpiolib-devres.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,15 @@ EXPORT_SYMBOL_GPL(devm_gpiod_put);
317317
* @dev: GPIO consumer
318318
* @desc: GPIO descriptor to remove resource management from
319319
*
320+
* *DEPRECATED*
321+
* This function should not be used. It's been provided as a workaround for
322+
* resource ownership issues in the regulator framework and should be replaced
323+
* with a better solution.
324+
*
320325
* Remove resource management from a GPIO descriptor. This is needed when
321326
* you want to hand over lifecycle management of a descriptor to another
322327
* mechanism.
323328
*/
324-
325329
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
326330
{
327331
int ret;

drivers/gpio/gpiolib-of.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
193193
*/
194194
{ "himax,hx8357", "gpios-reset", false },
195195
{ "himax,hx8369", "gpios-reset", false },
196+
#endif
197+
#if IS_ENABLED(CONFIG_MTD_NAND_JZ4780)
196198
/*
197199
* The rb-gpios semantics was undocumented and qi,lb60 (along with
198200
* the ingenic driver) got it wrong. The active state encodes the
@@ -266,6 +268,9 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np,
266268
{ "fsl,imx8qm-fec", "phy-reset-gpios", "phy-reset-active-high" },
267269
{ "fsl,s32v234-fec", "phy-reset-gpios", "phy-reset-active-high" },
268270
#endif
271+
#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
272+
{ "atmel,hsmci", "cd-gpios", "cd-inverted" },
273+
#endif
269274
#if IS_ENABLED(CONFIG_PCI_IMX6)
270275
{ "fsl,imx6q-pcie", "reset-gpio", "reset-gpio-active-high" },
271276
{ "fsl,imx6sx-pcie", "reset-gpio", "reset-gpio-active-high" },
@@ -291,9 +296,6 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np,
291296
#if IS_ENABLED(CONFIG_REGULATOR_GPIO)
292297
{ "regulator-gpio", "enable-gpio", "enable-active-high" },
293298
{ "regulator-gpio", "enable-gpios", "enable-active-high" },
294-
#endif
295-
#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
296-
{ "atmel,hsmci", "cd-gpios", "cd-inverted" },
297299
#endif
298300
};
299301
unsigned int i;

include/linux/gpio/consumer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct gpio_descs {
3131
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
3232
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
3333
#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
34+
/* GPIOD_FLAGS_BIT_NONEXCLUSIVE is DEPRECATED, don't use in new code. */
3435
#define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4)
3536

3637
/**

0 commit comments

Comments
 (0)