Pull gpio updates from Bartosz Golaszewski: "Relatively few updates for this release cycle. We have a single new driver and some minor changes in drivers, more work on limiting the usage of of_node in drivers and DT updates: - new driver: gpio-en7523 - dt-bindings: convertion of faraday,ftgpio010 to YAML, new compatible string in gpio-vf610 and a bugfix in an example - gpiolib core: several improvements and some code shrink - documentation: convert all public docs into kerneldoc format - set IRQ bus token in gpio-crystalcove (addresses a debugfs issue) - add a missing return value check for kstrdup() in gpio-merrifield - allow gpio-tps68470 to be built as module - more work on limiting usage of of_node in GPIO drivers - several sysfs interface improvements - use SDPX in gpio-ts4900" * tag 'gpio-updates-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: ts4900: Use SPDX header gpiolib: Use list_first_entry()/list_last_entry() gpiolib: sysfs: Simplify edge handling in the code gpiolib: sysfs: Move kstrtox() calls outside of the mutex lock gpiolib: sysfs: Move sysfs_emit() calls outside of the mutex lock gpiolib: make struct comments into real kernel docs dt-bindings: gpio: convert faraday,ftgpio01 to yaml dt-bindings: gpio: gpio-vf610: Add imx93 compatible string gpiolib: Simplify error path in gpiod_get_index() when requesting GPIO gpiolib: Use short form of ternary operator in gpiod_get_index() gpiolib: Introduce for_each_gpio_desc_with_flag() macro gpio: Add support for Airoha EN7523 GPIO controller dt-bindings: arm: airoha: Add binding for Airoha GPIO controller dt-bindings: gpio: fix gpio-hog example gpio: tps68470: Allow building as module gpio: tegra: Get rid of duplicate of_node assignment gpio: altera-a10sr: Switch to use fwnode instead of of_node gpio: merrifield: check the return value of devm_kstrdup() gpio: crystalcove: Set IRQ domain bus token to DOMAIN_BUS_WIRED
Unified · Split
| @@ -0,0 +1,66 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/gpio/airoha,en7523-gpio.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Airoha EN7523 GPIO controller | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - John Crispin <john@phrozen.org> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Airoha's GPIO controller on their ARM EN7523 SoCs consists of two banks of 32 | |
| 14 | + GPIOs. | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + $nodename: | |
| 18 | + pattern: "^gpio@[0-9a-f]+$" | |
| 19 | + | |
| 20 | + compatible: | |
| 21 | + items: | |
| 22 | + - const: airoha,en7523-gpio | |
| 23 | + | |
| 24 | + reg: | |
| 25 | + description: | | |
| 26 | + The first tuple points to the input register. | |
| 27 | + The second and third tuple point to the direction registers | |
| 28 | + The fourth tuple points to the output register | |
| 29 | + maxItems: 4 | |
| 30 | + | |
| 31 | + "#gpio-cells": | |
| 32 | + const: 2 | |
| 33 | + | |
| 34 | + gpio-controller: true | |
| 35 | + | |
| 36 | +required: | |
| 37 | + - compatible | |
| 38 | + - reg | |
| 39 | + - "#gpio-cells" | |
| 40 | + - gpio-controller | |
| 41 | + | |
| 42 | +additionalProperties: false | |
| 43 | + | |
| 44 | +examples: | |
| 45 | + - | | |
| 46 | + gpio0: gpio@1fbf0200 { | |
| 47 | + compatible = "airoha,en7523-gpio"; | |
| 48 | + reg = <0x1fbf0204 0x4>, | |
| 49 | + <0x1fbf0200 0x4>, | |
| 50 | + <0x1fbf0220 0x4>, | |
| 51 | + <0x1fbf0214 0x4>; | |
| 52 | + gpio-controller; | |
| 53 | + #gpio-cells = <2>; | |
| 54 | + }; | |
| 55 | + | |
| 56 | + gpio1: gpio@1fbf0270 { | |
| 57 | + compatible = "airoha,en7523-gpio"; | |
| 58 | + reg = <0x1fbf0270 0x4>, | |
| 59 | + <0x1fbf0260 0x4>, | |
| 60 | + <0x1fbf0264 0x4>, | |
| 61 | + <0x1fbf0278 0x4>; | |
| 62 | + gpio-controller; | |
| 63 | + #gpio-cells = <2>; | |
| 64 | + }; | |
| 65 | + | |
| 66 | +... | |
| @@ -1,27 +0,0 @@ | ||
| 1 | −Faraday Technology FTGPIO010 GPIO Controller | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | − | |
| 5 | −- compatible : Should be one of | |
| 6 | − "cortina,gemini-gpio", "faraday,ftgpio010" | |
| 7 | − "moxa,moxart-gpio", "faraday,ftgpio010" | |
| 8 | − "faraday,ftgpio010" | |
| 9 | −- reg : Should contain registers location and length | |
| 10 | −- interrupts : Should contain the interrupt line for the GPIO block | |
| 11 | −- gpio-controller : marks this as a GPIO controller | |
| 12 | −- #gpio-cells : Should be 2, see gpio/gpio.txt | |
| 13 | −- interrupt-controller : marks this as an interrupt controller | |
| 14 | −- #interrupt-cells : a standard two-cell interrupt flag, see | |
| 15 | − interrupt-controller/interrupts.txt | |
| 16 | − | |
| 17 | −Example: | |
| 18 | − | |
| 19 | −gpio@4d000000 { | |
| 20 | − compatible = "cortina,gemini-gpio", "faraday,ftgpio010"; | |
| 21 | − reg = <0x4d000000 0x100>; | |
| 22 | − interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; | |
| 23 | − gpio-controller; | |
| 24 | − #gpio-cells = <2>; | |
| 25 | − interrupt-controller; | |
| 26 | − #interrupt-cells = <2>; | |
| 27 | −}; | |
| @@ -0,0 +1,65 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/gpio/faraday,ftgpio010.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Faraday Technology FTGPIO010 GPIO Controller | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Linus Walleij <linus.walleij@linaro.org> | |
| 11 | + | |
| 12 | +properties: | |
| 13 | + compatible: | |
| 14 | + oneOf: | |
| 15 | + - items: | |
| 16 | + - const: cortina,gemini-gpio | |
| 17 | + - const: faraday,ftgpio010 | |
| 18 | + - items: | |
| 19 | + - const: moxa,moxart-gpio | |
| 20 | + - const: faraday,ftgpio010 | |
| 21 | + - const: faraday,ftgpio010 | |
| 22 | + | |
| 23 | + reg: | |
| 24 | + maxItems: 1 | |
| 25 | + | |
| 26 | + resets: | |
| 27 | + maxItems: 1 | |
| 28 | + | |
| 29 | + clocks: | |
| 30 | + maxItems: 1 | |
| 31 | + | |
| 32 | + interrupts: | |
| 33 | + maxItems: 1 | |
| 34 | + description: Should contain the interrupt line for the GPIO block | |
| 35 | + | |
| 36 | + gpio-controller: true | |
| 37 | + "#gpio-cells": | |
| 38 | + const: 2 | |
| 39 | + | |
| 40 | + interrupt-controller: true | |
| 41 | + "#interrupt-cells": | |
| 42 | + const: 2 | |
| 43 | + | |
| 44 | +required: | |
| 45 | + - compatible | |
| 46 | + - reg | |
| 47 | + - interrupts | |
| 48 | + - "#gpio-cells" | |
| 49 | + - interrupt-controller | |
| 50 | + - "#interrupt-cells" | |
| 51 | + | |
| 52 | +additionalProperties: false | |
| 53 | + | |
| 54 | +examples: | |
| 55 | + - | | |
| 56 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 57 | + gpio@4d000000 { | |
| 58 | + compatible = "cortina,gemini-gpio", "faraday,ftgpio010"; | |
| 59 | + reg = <0x4d000000 0x100>; | |
| 60 | + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; | |
| 61 | + gpio-controller; | |
| 62 | + #gpio-cells = <2>; | |
| 63 | + interrupt-controller; | |
| 64 | + #interrupt-cells = <2>; | |
| 65 | + }; | |
| @@ -25,7 +25,9 @@ properties: · 24 unmodified lines | ||
| 25 | 25 | - const: fsl,imx7ulp-gpio |
| 26 | 26 | - const: fsl,vf610-gpio |
| 27 | 27 | - items: |
| 28 | − - const: fsl,imx8ulp-gpio | |
| 28 | + - enum: | |
| 29 | + - fsl,imx93-gpio | |
| 30 | + - fsl,imx8ulp-gpio | |
| 29 | 31 | - const: fsl,imx7ulp-gpio |
| 30 | 32 | |
| 31 | 33 | reg: |
| @@ -213,7 +213,7 @@ Example of two SOC GPIO banks defined as gpio-controller nodes: · 212 unmodified lines | ||
| 213 | 213 | gpio-controller; |
| 214 | 214 | #gpio-cells = <2>; |
| 215 | 215 | |
| 216 | − line_b { | |
| 216 | + line_b-hog { | |
| 217 | 217 | gpio-hog; |
| 218 | 218 | gpios = <6 0>; |
| 219 | 219 | output-low; |
| @@ -247,6 +247,16 @@ config GPIO_EM · 246 unmodified lines | ||
| 247 | 247 | help |
| 248 | 248 | Say yes here to support GPIO on Renesas Emma Mobile SoCs. |
| 249 | 249 | |
| 250 | +config GPIO_EN7523 | |
| 251 | + tristate "Airoha GPIO support" | |
| 252 | + depends on ARCH_AIROHA | |
| 253 | + default ARCH_AIROHA | |
| 254 | + select GPIO_GENERIC | |
| 255 | + select GPIOLIB_IRQCHIP | |
| 256 | + help | |
| 257 | + Say Y or M here to support the GPIO controller block on the | |
| 258 | + Airoha EN7523 SoC. It supports two banks of 32 GPIOs. | |
| 259 | + | |
| 250 | 260 | config GPIO_EP93XX |
| 251 | 261 | def_bool y |
| 252 | 262 | depends on ARCH_EP93XX |
| @@ -1380,7 +1390,7 @@ config GPIO_TPS65912 · 1127 unmodified lines | ||
| 1380 | 1390 | This driver supports TPS65912 GPIO chip. |
| 1381 | 1391 | |
| 1382 | 1392 | config GPIO_TPS68470 |
| 1383 | − bool "TPS68470 GPIO" | |
| 1393 | + tristate "TPS68470 GPIO" | |
| 1384 | 1394 | depends on INTEL_SKL_INT3472 |
| 1385 | 1395 | help |
| 1386 | 1396 | Select this option to enable GPIO driver for the TPS68470 |
| @@ -1390,10 +1400,6 @@ config GPIO_TPS68470 · 3 unmodified lines | ||
| 1390 | 1400 | input or output as appropriate, the sensor related GPIOs |
| 1391 | 1401 | are "output only" GPIOs. |
| 1392 | 1402 | |
| 1393 | − This driver config is bool, as the GPIO functionality | |
| 1394 | − of the TPS68470 must be available before dependent | |
| 1395 | − drivers are loaded. | |
| 1396 | − | |
| 1397 | 1403 | config GPIO_TQMX86 |
| 1398 | 1404 | tristate "TQ-Systems QTMX86 GPIO" |
| 1399 | 1405 | depends on MFD_TQMX86 || COMPILE_TEST |
| @@ -55,6 +55,7 @@ obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o · 54 unmodified lines | ||
| 55 | 55 | obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o |
| 56 | 56 | obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o |
| 57 | 57 | obj-$(CONFIG_GPIO_EM) += gpio-em.o |
| 58 | +obj-$(CONFIG_GPIO_EN7523) += gpio-en7523.o | |
| 58 | 59 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
| 59 | 60 | obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o |
| 60 | 61 | obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/gpio/driver.h> |
| 11 | 11 | #include <linux/mfd/altera-a10sr.h> |
| 12 | 12 | #include <linux/module.h> |
| 13 | +#include <linux/property.h> | |
| 13 | 14 | |
| 14 | 15 | /** |
| 15 | 16 | * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure |
| @@ -88,7 +89,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) · 72 unmodified lines | ||
| 88 | 89 | |
| 89 | 90 | gpio->gp = altr_a10sr_gc; |
| 90 | 91 | gpio->gp.parent = pdev->dev.parent; |
| 91 | − gpio->gp.of_node = pdev->dev.of_node; | |
| 92 | + gpio->gp.fwnode = dev_fwnode(&pdev->dev); | |
| 92 | 93 | |
| 93 | 94 | return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); |
| 94 | 95 | } |
| @@ -370,7 +370,14 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) · 369 unmodified lines | ||
| 370 | 370 | return retval; |
| 371 | 371 | } |
| 372 | 372 | |
| 373 | − return devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg); | |
| 373 | + retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg); | |
| 374 | + if (retval) | |
| 375 | + return retval; | |
| 376 | + | |
| 377 | + /* Distuingish IRQ domain from others sharing (MFD) the same fwnode */ | |
| 378 | + irq_domain_update_bus_token(cg->chip.irq.domain, DOMAIN_BUS_WIRED); | |
| 379 | + | |
| 380 | + return 0; | |
| 374 | 381 | } |
| 375 | 382 | |
| 376 | 383 | static struct platform_driver crystalcove_gpio_driver = { |
| @@ -0,0 +1,137 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + | |
| 3 | +#include <linux/types.h> | |
| 4 | +#include <linux/io.h> | |
| 5 | +#include <linux/bits.h> | |
| 6 | +#include <linux/gpio/driver.h> | |
| 7 | +#include <linux/mod_devicetable.h> | |
| 8 | +#include <linux/module.h> | |
| 9 | +#include <linux/platform_device.h> | |
| 10 | +#include <linux/property.h> | |
| 11 | + | |
| 12 | +#define AIROHA_GPIO_MAX 32 | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * airoha_gpio_ctrl - Airoha GPIO driver data | |
| 16 | + * @gc: Associated gpio_chip instance. | |
| 17 | + * @data: The data register. | |
| 18 | + * @dir0: The direction register for the lower 16 pins. | |
| 19 | + * @dir1: The direction register for the higher 16 pins. | |
| 20 | + * @output: The output enable register. | |
| 21 | + */ | |
| 22 | +struct airoha_gpio_ctrl { | |
| 23 | + struct gpio_chip gc; | |
| 24 | + void __iomem *data; | |
| 25 | + void __iomem *dir[2]; | |
| 26 | + void __iomem *output; | |
| 27 | +}; | |
| 28 | + | |
| 29 | +static struct airoha_gpio_ctrl *gc_to_ctrl(struct gpio_chip *gc) | |
| 30 | +{ | |
| 31 | + return container_of(gc, struct airoha_gpio_ctrl, gc); | |
| 32 | +} | |
| 33 | + | |
| 34 | +static int airoha_dir_set(struct gpio_chip *gc, unsigned int gpio, | |
| 35 | + int val, int out) | |
| 36 | +{ | |
| 37 | + struct airoha_gpio_ctrl *ctrl = gc_to_ctrl(gc); | |
| 38 | + u32 dir = ioread32(ctrl->dir[gpio / 16]); | |
| 39 | + u32 output = ioread32(ctrl->output); | |
| 40 | + u32 mask = BIT((gpio % 16) * 2); | |
| 41 | + | |
| 42 | + if (out) { | |
| 43 | + dir |= mask; | |
| 44 | + output |= BIT(gpio); | |
| 45 | + } else { | |
| 46 | + dir &= ~mask; | |
| 47 | + output &= ~BIT(gpio); | |
| 48 | + } | |
| 49 | + | |
| 50 | + iowrite32(dir, ctrl->dir[gpio / 16]); | |
| 51 | + | |
| 52 | + if (out) | |
| 53 | + gc->set(gc, gpio, val); | |
| 54 | + | |
| 55 | + iowrite32(output, ctrl->output); | |
| 56 | + | |
| 57 | + return 0; | |
| 58 | +} | |
| 59 | + | |
| 60 | +static int airoha_dir_out(struct gpio_chip *gc, unsigned int gpio, | |
| 61 | + int val) | |
| 62 | +{ | |
| 63 | + return airoha_dir_set(gc, gpio, val, 1); | |
| 64 | +} | |
| 65 | + | |
| 66 | +static int airoha_dir_in(struct gpio_chip *gc, unsigned int gpio) | |
| 67 | +{ | |
| 68 | + return airoha_dir_set(gc, gpio, 0, 0); | |
| 69 | +} | |
| 70 | + | |
| 71 | +static int airoha_get_dir(struct gpio_chip *gc, unsigned int gpio) | |
| 72 | +{ | |
| 73 | + struct airoha_gpio_ctrl *ctrl = gc_to_ctrl(gc); | |
| 74 | + u32 dir = ioread32(ctrl->dir[gpio / 16]); | |
| 75 | + u32 mask = BIT((gpio % 16) * 2); | |
| 76 | + | |
| 77 | + return (dir & mask) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; | |
| 78 | +} | |
| 79 | + | |
| 80 | +static int airoha_gpio_probe(struct platform_device *pdev) | |
| 81 | +{ | |
| 82 | + struct device *dev = &pdev->dev; | |
| 83 | + struct airoha_gpio_ctrl *ctrl; | |
| 84 | + int err; | |
| 85 | + | |
| 86 | + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); | |
| 87 | + if (!ctrl) | |
| 88 | + return -ENOMEM; | |
| 89 | + | |
| 90 | + ctrl->data = devm_platform_ioremap_resource(pdev, 0); | |
| 91 | + if (IS_ERR(ctrl->data)) | |
| 92 | + return PTR_ERR(ctrl->data); | |
| 93 | + | |
| 94 | + ctrl->dir[0] = devm_platform_ioremap_resource(pdev, 1); | |
| 95 | + if (IS_ERR(ctrl->dir[0])) | |
| 96 | + return PTR_ERR(ctrl->dir[0]); | |
| 97 | + | |
| 98 | + ctrl->dir[1] = devm_platform_ioremap_resource(pdev, 2); | |
| 99 | + if (IS_ERR(ctrl->dir[1])) | |
| 100 | + return PTR_ERR(ctrl->dir[1]); | |
| 101 | + | |
| 102 | + ctrl->output = devm_platform_ioremap_resource(pdev, 3); | |
| 103 | + if (IS_ERR(ctrl->output)) | |
| 104 | + return PTR_ERR(ctrl->output); | |
| 105 | + | |
| 106 | + err = bgpio_init(&ctrl->gc, dev, 4, ctrl->data, NULL, | |
| 107 | + NULL, NULL, NULL, 0); | |
| 108 | + if (err) | |
| 109 | + return dev_err_probe(dev, err, "unable to init generic GPIO"); | |
| 110 | + | |
| 111 | + ctrl->gc.ngpio = AIROHA_GPIO_MAX; | |
| 112 | + ctrl->gc.owner = THIS_MODULE; | |
| 113 | + ctrl->gc.direction_output = airoha_dir_out; | |
| 114 | + ctrl->gc.direction_input = airoha_dir_in; | |
| 115 | + ctrl->gc.get_direction = airoha_get_dir; | |
| 116 | + | |
| 117 | + return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); | |
| 118 | +} | |
| 119 | + | |
| 120 | +static const struct of_device_id airoha_gpio_of_match[] = { | |
| 121 | + { .compatible = "airoha,en7523-gpio" }, | |
| 122 | + { } | |
| 123 | +}; | |
| 124 | +MODULE_DEVICE_TABLE(of, airoha_gpio_of_match); | |
| 125 | + | |
| 126 | +static struct platform_driver airoha_gpio_driver = { | |
| 127 | + .driver = { | |
| 128 | + .name = "airoha-gpio", | |
| 129 | + .of_match_table = airoha_gpio_of_match, | |
| 130 | + }, | |
| 131 | + .probe = airoha_gpio_probe, | |
| 132 | +}; | |
| 133 | +module_platform_driver(airoha_gpio_driver); | |
| 134 | + | |
| 135 | +MODULE_DESCRIPTION("Airoha GPIO support"); | |
| 136 | +MODULE_AUTHOR("John Crispin <john@phrozen.org>"); | |
| 137 | +MODULE_LICENSE("GPL v2"); | |
| @@ -409,6 +409,9 @@ static int mrfld_gpio_add_pin_ranges(struct gpio_chip *chip) · 408 unmodified lines | ||
| 409 | 409 | int retval; |
| 410 | 410 | |
| 411 | 411 | pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); |
| 412 | + if (!pinctrl_dev_name) | |
| 413 | + return -ENOMEM; | |
| 414 | + | |
| 412 | 415 | for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { |
| 413 | 416 | range = &mrfld_gpio_ranges[i]; |
| 414 | 417 | retval = gpiochip_add_pin_range(&priv->chip, pinctrl_dev_name, |
| @@ -691,7 +691,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) · 690 unmodified lines | ||
| 691 | 691 | tgi->gc.base = 0; |
| 692 | 692 | tgi->gc.ngpio = tgi->bank_count * 32; |
| 693 | 693 | tgi->gc.parent = &pdev->dev; |
| 694 | − tgi->gc.of_node = pdev->dev.of_node; | |
| 695 | 694 | |
| 696 | 695 | tgi->ic.name = "GPIO"; |
| 697 | 696 | tgi->ic.irq_ack = tegra_gpio_irq_ack; |
| @@ -154,5 +154,8 @@ static struct platform_driver tps68470_gpio_driver = { · 153 unmodified lines | ||
| 154 | 154 | }, |
| 155 | 155 | .probe = tps68470_gpio_probe, |
| 156 | 156 | }; |
| 157 | +module_platform_driver(tps68470_gpio_driver); | |
| 157 | 158 | |
| 158 | −builtin_platform_driver(tps68470_gpio_driver) | |
| 159 | +MODULE_ALIAS("platform:tps68470-gpio"); | |
| 160 | +MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC"); | |
| 161 | +MODULE_LICENSE("GPL v2"); | |
| @@ -1,17 +1,9 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 1 | 2 | /* |
| 2 | 3 | * Digital I/O driver for Technologic Systems I2C FPGA Core |
| 3 | 4 | * |
| 4 | 5 | * Copyright (C) 2015, 2018 Technologic Systems |
| 5 | 6 | * Copyright (C) 2016 Savoir-Faire Linux |
| 6 | − * | |
| 7 | − * This program is free software; you can redistribute it and/or | |
| 8 | − * modify it under the terms of the GNU General Public License version 2 as | |
| 9 | − * published by the Free Software Foundation. | |
| 10 | − * | |
| 11 | − * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
| 12 | − * kind, whether expressed or implied; without even the implied warranty | |
| 13 | − * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License version 2 for more details. | |
| 15 | 7 | */ |
| 16 | 8 | |
| 17 | 9 | #include <linux/gpio/driver.h> |
| @@ -711,14 +711,12 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) · 710 unmodified lines | ||
| 711 | 711 | static void of_gpiochip_remove_hog(struct gpio_chip *chip, |
| 712 | 712 | struct device_node *hog) |
| 713 | 713 | { |
| 714 | − struct gpio_desc *descs = chip->gpiodev->descs; | |
| 714 | + struct gpio_desc *desc; | |
| 715 | 715 | unsigned int i; |
| 716 | 716 | |
| 717 | − for (i = 0; i < chip->ngpio; i++) { | |
| 718 | − if (test_bit(FLAG_IS_HOGGED, &descs[i].flags) && | |
| 719 | − descs[i].hog == hog) | |
| 720 | − gpiochip_free_own_desc(&descs[i]); | |
| 721 | − } | |
| 717 | + for_each_gpio_desc_with_flag(i, chip, desc, FLAG_IS_HOGGED) | |
| 718 | + if (desc->hog == hog) | |
| 719 | + gpiochip_free_own_desc(desc); | |
| 722 | 720 | } |
| 723 | 721 | |
| 724 | 722 | static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "gpiolib.h" |
| 14 | 14 | #include "gpiolib-sysfs.h" |
| 15 | 15 | |
| 16 | +#define GPIO_IRQF_TRIGGER_NONE 0 | |
| 16 | 17 | #define GPIO_IRQF_TRIGGER_FALLING BIT(0) |
| 17 | 18 | #define GPIO_IRQF_TRIGGER_RISING BIT(1) |
| 18 | 19 | #define GPIO_IRQF_TRIGGER_BOTH (GPIO_IRQF_TRIGGER_FALLING | \ |
| @@ -61,17 +62,16 @@ static ssize_t direction_show(struct device *dev, · 42 unmodified lines | ||
| 61 | 62 | { |
| 62 | 63 | struct gpiod_data *data = dev_get_drvdata(dev); |
| 63 | 64 | struct gpio_desc *desc = data->desc; |
| 64 | − ssize_t status; | |
| 65 | + int value; | |
| 65 | 66 | |
| 66 | 67 | mutex_lock(&data->mutex); |
| 67 | 68 | |
| 68 | 69 | gpiod_get_direction(desc); |
| 69 | − status = sysfs_emit(buf, "%s\n", | |
| 70 | − test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); | |
| 70 | + value = !!test_bit(FLAG_IS_OUT, &desc->flags); | |
| 71 | 71 | |
| 72 | 72 | mutex_unlock(&data->mutex); |
| 73 | 73 | |
| 74 | − return status; | |
| 74 | + return sysfs_emit(buf, "%s\n", value ? "out" : "in"); | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | static ssize_t direction_store(struct device *dev, |
| @@ -108,12 +108,13 @@ static ssize_t value_show(struct device *dev, · 30 unmodified lines | ||
| 108 | 108 | mutex_lock(&data->mutex); |
| 109 | 109 | |
| 110 | 110 | status = gpiod_get_value_cansleep(desc); |
| 111 | − if (status >= 0) | |
| 112 | − status = sysfs_emit(buf, "%zd\n", status); | |
| 113 | 111 | |
| 114 | 112 | mutex_unlock(&data->mutex); |
| 115 | 113 | |
| 116 | − return status; | |
| 114 | + if (status < 0) | |
| 115 | + return status; | |
| 116 | + | |
| 117 | + return sysfs_emit(buf, "%zd\n", status); | |
| 117 | 118 | } |
| 118 | 119 | |
| 119 | 120 | static ssize_t value_store(struct device *dev, |
| @@ -121,24 +122,18 @@ static ssize_t value_store(struct device *dev, · 1 unmodified line | ||
| 121 | 122 | { |
| 122 | 123 | struct gpiod_data *data = dev_get_drvdata(dev); |
| 123 | 124 | struct gpio_desc *desc = data->desc; |
| 124 | − ssize_t status = 0; | |
| 125 | + ssize_t status; | |
| 126 | + long value; | |
| 127 | + | |
| 128 | + status = kstrtol(buf, 0, &value); | |
| 125 | 129 | |
| 126 | 130 | mutex_lock(&data->mutex); |
| 127 | 131 | |
| 128 | 132 | if (!test_bit(FLAG_IS_OUT, &desc->flags)) { |
| 129 | 133 | status = -EPERM; |
| 130 | − } else { | |
| 131 | − long value; | |
| 132 | − | |
| 133 | − if (size <= 2 && isdigit(buf[0]) && | |
| 134 | − (size == 1 || buf[1] == '\n')) | |
| 135 | − value = buf[0] - '0'; | |
| 136 | − else | |
| 137 | − status = kstrtol(buf, 0, &value); | |
| 138 | − if (status == 0) { | |
| 139 | − gpiod_set_value_cansleep(desc, value); | |
| 140 | − status = size; | |
| 141 | − } | |
| 134 | + } else if (status == 0) { | |
| 135 | + gpiod_set_value_cansleep(desc, value); | |
| 136 | + status = size; | |
| 142 | 137 | } |
| 143 | 138 | |
| 144 | 139 | mutex_unlock(&data->mutex); |
| @@ -224,54 +219,41 @@ static void gpio_sysfs_free_irq(struct device *dev) · 79 unmodified lines | ||
| 224 | 219 | sysfs_put(data->value_kn); |
| 225 | 220 | } |
| 226 | 221 | |
| 227 | −static const struct { | |
| 228 | − const char *name; | |
| 229 | − unsigned char flags; | |
| 230 | −} trigger_types[] = { | |
| 231 | − { "none", 0 }, | |
| 232 | − { "falling", GPIO_IRQF_TRIGGER_FALLING }, | |
| 233 | − { "rising", GPIO_IRQF_TRIGGER_RISING }, | |
| 234 | − { "both", GPIO_IRQF_TRIGGER_BOTH }, | |
| 222 | +static const char * const trigger_names[] = { | |
| 223 | + [GPIO_IRQF_TRIGGER_NONE] = "none", | |
| 224 | + [GPIO_IRQF_TRIGGER_FALLING] = "falling", | |
| 225 | + [GPIO_IRQF_TRIGGER_RISING] = "rising", | |
| 226 | + [GPIO_IRQF_TRIGGER_BOTH] = "both", | |
| 235 | 227 | }; |
| 236 | 228 | |
| 237 | 229 | static ssize_t edge_show(struct device *dev, |
| 238 | 230 | struct device_attribute *attr, char *buf) |
| 239 | 231 | { |
| 240 | 232 | struct gpiod_data *data = dev_get_drvdata(dev); |
| 241 | − ssize_t status = 0; | |
| 242 | − int i; | |
| 233 | + int flags; | |
| 243 | 234 | |
| 244 | 235 | mutex_lock(&data->mutex); |
| 245 | 236 | |
| 246 | − for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { | |
| 247 | − if (data->irq_flags == trigger_types[i].flags) | |
| 248 | − break; | |
| 249 | − } | |
| 250 | − if (i < ARRAY_SIZE(trigger_types)) | |
| 251 | − status = sysfs_emit(buf, "%s\n", trigger_types[i].name); | |
| 237 | + flags = data->irq_flags; | |
| 252 | 238 | |
| 253 | 239 | mutex_unlock(&data->mutex); |
| 254 | 240 | |
| 255 | − return status; | |
| 241 | + if (flags >= ARRAY_SIZE(trigger_names)) | |
| 242 | + return 0; | |
| 243 | + | |
| 244 | + return sysfs_emit(buf, "%s\n", trigger_names[flags]); | |
| 256 | 245 | } |
| 257 | 246 | |
| 258 | 247 | static ssize_t edge_store(struct device *dev, |
| 259 | 248 | struct device_attribute *attr, const char *buf, size_t size) |
| 260 | 249 | { |
| 261 | 250 | struct gpiod_data *data = dev_get_drvdata(dev); |
| 262 | − unsigned char flags; | |
| 263 | 251 | ssize_t status = size; |
| 264 | − int i; | |
| 265 | − | |
| 266 | − for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { | |
| 267 | − if (sysfs_streq(trigger_types[i].name, buf)) | |
| 268 | − break; | |
| 269 | − } | |
| 270 | − | |
| 271 | − if (i == ARRAY_SIZE(trigger_types)) | |
| 272 | − return -EINVAL; | |
| 252 | + int flags; | |
| 273 | 253 | |
| 274 | − flags = trigger_types[i].flags; | |
| 254 | + flags = sysfs_match_string(trigger_names, buf); | |
| 255 | + if (flags < 0) | |
| 256 | + return flags; | |
| 275 | 257 | |
| 276 | 258 | mutex_lock(&data->mutex); |
| 277 | 259 | |
| @@ -324,16 +306,15 @@ static ssize_t active_low_show(struct device *dev, · 46 unmodified lines | ||
| 324 | 306 | { |
| 325 | 307 | struct gpiod_data *data = dev_get_drvdata(dev); |
| 326 | 308 | struct gpio_desc *desc = data->desc; |
| 327 | − ssize_t status; | |
| 309 | + int value; | |
| 328 | 310 | |
| 329 | 311 | mutex_lock(&data->mutex); |
| 330 | 312 | |
| 331 | − status = sysfs_emit(buf, "%d\n", | |
| 332 | − !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); | |
| 313 | + value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags); | |
| 333 | 314 | |
| 334 | 315 | mutex_unlock(&data->mutex); |
| 335 | 316 | |
| 336 | − return status; | |
| 317 | + return sysfs_emit(buf, "%d\n", value); | |
| 337 | 318 | } |
| 338 | 319 | |
| 339 | 320 | static ssize_t active_low_store(struct device *dev, |
| @@ -343,11 +324,13 @@ static ssize_t active_low_store(struct device *dev, · 3 unmodified lines | ||
| 343 | 324 | ssize_t status; |
| 344 | 325 | long value; |
| 345 | 326 | |
| 327 | + status = kstrtol(buf, 0, &value); | |
| 328 | + if (status) | |
| 329 | + return status; | |
| 330 | + | |
| 346 | 331 | mutex_lock(&data->mutex); |
| 347 | 332 | |
| 348 | − status = kstrtol(buf, 0, &value); | |
| 349 | − if (status == 0) | |
| 350 | − status = gpio_sysfs_set_active_low(dev, value); | |
| 333 | + status = gpio_sysfs_set_active_low(dev, value); | |
| 351 | 334 | |
| 352 | 335 | mutex_unlock(&data->mutex); |
| 353 | 336 | |
| @@ -790,11 +773,8 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev) · 436 unmodified lines | ||
| 790 | 773 | mutex_unlock(&sysfs_lock); |
| 791 | 774 | |
| 792 | 775 | /* unregister gpiod class devices owned by sysfs */ |
| 793 | − for (i = 0; i < chip->ngpio; i++) { | |
| 794 | − desc = &gdev->descs[i]; | |
| 795 | − if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) | |
| 796 | − gpiod_free(desc); | |
| 797 | − } | |
| 776 | + for_each_gpio_desc_with_flag(i, chip, desc, FLAG_SYSFS) | |
| 777 | + gpiod_free(desc); | |
| 798 | 778 | } |
| 799 | 779 | |
| 800 | 780 | static int __init gpiolib_sysfs_init(void) |
| @@ -262,14 +262,14 @@ static int gpiodev_add_to_list(struct gpio_device *gdev) · 261 unmodified lines | ||
| 262 | 262 | return 0; |
| 263 | 263 | } |
| 264 | 264 | |
| 265 | − next = list_entry(gpio_devices.next, struct gpio_device, list); | |
| 265 | + next = list_first_entry(&gpio_devices, struct gpio_device, list); | |
| 266 | 266 | if (gdev->base + gdev->ngpio <= next->base) { |
| 267 | 267 | /* add before first entry */ |
| 268 | 268 | list_add(&gdev->list, &gpio_devices); |
| 269 | 269 | return 0; |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | − prev = list_entry(gpio_devices.prev, struct gpio_device, list); | |
| 272 | + prev = list_last_entry(&gpio_devices, struct gpio_device, list); | |
| 273 | 273 | if (prev->base + prev->ngpio <= gdev->base) { |
| 274 | 274 | /* add behind last entry */ |
| 275 | 275 | list_add_tail(&gdev->list, &gpio_devices); |
| @@ -3951,23 +3951,21 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, · 3675 unmodified lines | ||
| 3951 | 3951 | * If a connection label was passed use that, else attempt to use |
| 3952 | 3952 | * the device name as label |
| 3953 | 3953 | */ |
| 3954 | − ret = gpiod_request(desc, con_id ? con_id : devname); | |
| 3954 | + ret = gpiod_request(desc, con_id ?: devname); | |
| 3955 | 3955 | if (ret) { |
| 3956 | − if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { | |
| 3957 | − /* | |
| 3958 | − * This happens when there are several consumers for | |
| 3959 | − * the same GPIO line: we just return here without | |
| 3960 | − * further initialization. It is a bit if a hack. | |
| 3961 | − * This is necessary to support fixed regulators. | |
| 3962 | − * | |
| 3963 | − * FIXME: Make this more sane and safe. | |
| 3964 | − */ | |
| 3965 | − dev_info(dev, "nonexclusive access to GPIO for %s\n", | |
| 3966 | − con_id ? con_id : devname); | |
| 3967 | − return desc; | |
| 3968 | − } else { | |
| 3956 | + if (!(ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) | |
| 3969 | 3957 | return ERR_PTR(ret); |
| 3970 | − } | |
| 3958 | + | |
| 3959 | + /* | |
| 3960 | + * This happens when there are several consumers for | |
| 3961 | + * the same GPIO line: we just return here without | |
| 3962 | + * further initialization. It is a bit of a hack. | |
| 3963 | + * This is necessary to support fixed regulators. | |
| 3964 | + * | |
| 3965 | + * FIXME: Make this more sane and safe. | |
| 3966 | + */ | |
| 3967 | + dev_info(dev, "nonexclusive access to GPIO for %s\n", con_id ?: devname); | |
| 3968 | + return desc; | |
| 3971 | 3969 | } |
| 3972 | 3970 | |
| 3973 | 3971 | ret = gpiod_configure_flags(desc, con_id, lookupflags, flags); |
| @@ -4122,12 +4120,11 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, · 148 unmodified lines | ||
| 4122 | 4120 | */ |
| 4123 | 4121 | static void gpiochip_free_hogs(struct gpio_chip *gc) |
| 4124 | 4122 | { |
| 4123 | + struct gpio_desc *desc; | |
| 4125 | 4124 | int id; |
| 4126 | 4125 | |
| 4127 | − for (id = 0; id < gc->ngpio; id++) { | |
| 4128 | − if (test_bit(FLAG_IS_HOGGED, &gc->gpiodev->descs[id].flags)) | |
| 4129 | − gpiochip_free_own_desc(&gc->gpiodev->descs[id]); | |
| 4130 | − } | |
| 4126 | + for_each_gpio_desc_with_flag(id, gc, desc, FLAG_IS_HOGGED) | |
| 4127 | + gpiochip_free_own_desc(desc); | |
| 4131 | 4128 | } |
| 4132 | 4129 | |
| 4133 | 4130 | /** |
| @@ -4446,7 +4443,7 @@ static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos) · 312 unmodified lines | ||
| 4446 | 4443 | if (list_is_last(&gdev->list, &gpio_devices)) |
| 4447 | 4444 | ret = NULL; |
| 4448 | 4445 | else |
| 4449 | − ret = list_entry(gdev->list.next, struct gpio_device, list); | |
| 4446 | + ret = list_first_entry(&gdev->list, struct gpio_device, list); | |
| 4450 | 4447 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 4451 | 4448 | |
| 4452 | 4449 | s->private = "\n"; |
| @@ -37,6 +37,9 @@ · 36 unmodified lines | ||
| 37 | 37 | * or name of the IP component in a System on Chip. |
| 38 | 38 | * @data: per-instance data assigned by the driver |
| 39 | 39 | * @list: links gpio_device:s together for traversal |
| 40 | + * @notifier: used to notify subscribers about lines being requested, released | |
| 41 | + * or reconfigured | |
| 42 | + * @pin_ranges: range of pins served by the GPIO driver | |
| 40 | 43 | * |
| 41 | 44 | * This state container holds most of the runtime variable data |
| 42 | 45 | * for a GPIO device and can hold references and live on after the |
| @@ -72,6 +75,20 @@ struct gpio_device { · 29 unmodified lines | ||
| 72 | 75 | /* gpio suffixes used for ACPI and device tree lookup */ |
| 73 | 76 | static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; |
| 74 | 77 | |
| 78 | +/** | |
| 79 | + * struct gpio_array - Opaque descriptor for a structure of GPIO array attributes | |
| 80 | + * | |
| 81 | + * @desc: Array of pointers to the GPIO descriptors | |
| 82 | + * @size: Number of elements in desc | |
| 83 | + * @chip: Parent GPIO chip | |
| 84 | + * @get_mask: Get mask used in fastpath | |
| 85 | + * @set_mask: Set mask used in fastpath | |
| 86 | + * @invert_mask: Invert mask used in fastpath | |
| 87 | + * | |
| 88 | + * This structure is attached to struct gpiod_descs obtained from | |
| 89 | + * gpiod_get_array() and can be passed back to get/set array functions in order | |
| 90 | + * to activate fast processing path if applicable. | |
| 91 | + */ | |
| 75 | 92 | struct gpio_array { |
| 76 | 93 | struct gpio_desc **desc; |
| 77 | 94 | unsigned int size; |
| @@ -82,6 +99,13 @@ struct gpio_array { · 4 unmodified lines | ||
| 82 | 99 | }; |
| 83 | 100 | |
| 84 | 101 | struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum); |
| 102 | + | |
| 103 | +#define for_each_gpio_desc_with_flag(i, gc, desc, flag) \ | |
| 104 | + for (i = 0, desc = gpiochip_get_desc(gc, i); \ | |
| 105 | + i < gc->ngpio; \ | |
| 106 | + i++, desc = gpiochip_get_desc(gc, i)) \ | |
| 107 | + if (!test_bit(flag, &desc->flags)) {} else | |
| 108 | + | |
| 85 | 109 | int gpiod_get_array_value_complex(bool raw, bool can_sleep, |
| 86 | 110 | unsigned int array_size, |
| 87 | 111 | struct gpio_desc **desc_array, |
| @@ -96,6 +120,23 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, · 8 unmodified lines | ||
| 96 | 120 | extern spinlock_t gpio_lock; |
| 97 | 121 | extern struct list_head gpio_devices; |
| 98 | 122 | |
| 123 | + | |
| 124 | +/** | |
| 125 | + * struct gpio_desc - Opaque descriptor for a GPIO | |
| 126 | + * | |
| 127 | + * @gdev: Pointer to the parent GPIO device | |
| 128 | + * @flags: Binary descriptor flags | |
| 129 | + * @label: Name of the consumer | |
| 130 | + * @name: Line name | |
| 131 | + * @hog: Pointer to the device node that hogs this line (if any) | |
| 132 | + * @debounce_period_us: Debounce period in microseconds | |
| 133 | + * | |
| 134 | + * These are obtained using gpiod_get() and are preferable to the old | |
| 135 | + * integer-based handles. | |
| 136 | + * | |
| 137 | + * Contrary to integers, a pointer to a &struct gpio_desc is guaranteed to be | |
| 138 | + * valid until the GPIO is released. | |
| 139 | + */ | |
| 99 | 140 | struct gpio_desc { |
| 100 | 141 | struct gpio_device *gdev; |
| 101 | 142 | unsigned long flags; |
| @@ -8,27 +8,16 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/err.h> |
| 9 | 9 | |
| 10 | 10 | struct device; |
| 11 | − | |
| 12 | −/** | |
| 13 | − * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are | |
| 14 | − * preferable to the old integer-based handles. | |
| 15 | − * | |
| 16 | − * Contrary to integers, a pointer to a gpio_desc is guaranteed to be valid | |
| 17 | − * until the GPIO is released. | |
| 18 | − */ | |
| 19 | 11 | struct gpio_desc; |
| 20 | − | |
| 21 | −/** | |
| 22 | − * Opaque descriptor for a structure of GPIO array attributes. This structure | |
| 23 | − * is attached to struct gpiod_descs obtained from gpiod_get_array() and can be | |
| 24 | − * passed back to get/set array functions in order to activate fast processing | |
| 25 | − * path if applicable. | |
| 26 | − */ | |
| 27 | 12 | struct gpio_array; |
| 28 | 13 | |
| 29 | 14 | /** |
| 30 | − * Struct containing an array of descriptors that can be obtained using | |
| 31 | − * gpiod_get_array(). | |
| 15 | + * struct gpio_descs - Struct containing an array of descriptors that can be | |
| 16 | + * obtained using gpiod_get_array() | |
| 17 | + * | |
| 18 | + * @info: Pointer to the opaque gpio_array structure | |
| 19 | + * @ndescs: Number of held descriptors | |
| 20 | + * @desc: Array of pointers to GPIO descriptors | |
| 32 | 21 | */ |
| 33 | 22 | struct gpio_descs { |
| 34 | 23 | struct gpio_array *info; |
| @@ -43,8 +32,16 @@ struct gpio_descs { · 8 unmodified lines | ||
| 43 | 32 | #define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4) |
| 44 | 33 | |
| 45 | 34 | /** |
| 46 | − * Optional flags that can be passed to one of gpiod_* to configure direction | |
| 47 | − * and output value. These values cannot be OR'd. | |
| 35 | + * enum gpiod_flags - Optional flags that can be passed to one of gpiod_* to | |
| 36 | + * configure direction and output value. These values | |
| 37 | + * cannot be OR'd. | |
| 38 | + * | |
| 39 | + * @GPIOD_ASIS: Don't change anything | |
| 40 | + * @GPIOD_IN: Set lines to input mode | |
| 41 | + * @GPIOD_OUT_LOW: Set lines to output and drive them low | |
| 42 | + * @GPIOD_OUT_HIGH: Set lines to output and drive them high | |
| 43 | + * @GPIOD_OUT_LOW_OPEN_DRAIN: Set lines to open-drain output and drive them low | |
| 44 | + * @GPIOD_OUT_HIGH_OPEN_DRAIN: Set lines to open-drain output and drive them high | |
| 48 | 45 | */ |
| 49 | 46 | enum gpiod_flags { |
| 50 | 47 | GPIOD_ASIS = 0, |