Commit 9798f517 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Linus Walleij:
 "The is the bulk of GPIO changes for the v4.16 kernel cycle. It is
  pretty calm this time around I think. I even got time to get to things
  like starting to clean up header includes.

  Core changes:

   - Disallow open drain and open source flags to be set simultaneously.
     This doesn't make electrical sense, and would the hardware actually
     respond to this setting, the result would be short circuit.

   - ACPI GPIO has a new core infrastructure for handling quirks. The
     quirks are there to deal with broken ACPI tables centrally instead
     of pushing the work to individual drivers. In the world of BIOS
     writers, the ACPI tables are perfect. Until they find a mistake in
     it. When such a mistake is found, we can patch it with a quirk. It
     should never happen, the problem is that it happens. So we
     accomodate for it.

   - Several documentation updates.

   - Revert the patch setting up initial direction state from reading
     the device. This was causing bad things for drivers that can't read
     status on all its pins. It is only affecting debugfs information
     quality.

   - Label descriptors with the device name if no explicit label is
     passed in.

   - Pave the ground for transitioning SPI and regulators to use GPIO
     descriptors by implementing some quirks in the device tree GPIO
     parsing code.

  New drivers:

   - New driver for the Access PCIe IDIO 24 family.

  Other:

   - Major refactorings and improvements to the GPIO mockup driver used
     for test and verification.

   - Moved the AXP209 driver over to pin control since it gained a pin
     control back-end. These patches will appear (with the same hashes)
     in the pin control pull request as well.

   - Convert the onewire GPIO driver w1-gpio to use descriptors. This is
     merged here since the W1 maintainers send very few pull requests
     and he ACKed it.

   - Start to clean up driver headers using <linux/gpio.h> to just use
     <linux/gpio/driver.h> as appropriate"

* tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (103 commits)
  gpio: Timestamp events in hardirq handler
  gpio: Fix kernel stack leak to userspace
  gpio: Fix a documentation spelling mistake
  gpio: Documentation update
  gpiolib: remove redundant initialization of pointer desc
  gpio: of: Fix NPE from OF flags
  gpio: stmpe: Delete an unnecessary variable initialisation in stmpe_gpio_probe()
  gpio: stmpe: Move an assignment in stmpe_gpio_probe()
  gpio: stmpe: Improve a size determination in stmpe_gpio_probe()
  gpio: stmpe: Use seq_putc() in stmpe_dbg_show()
  gpio: No NULL owner
  gpio: stmpe: i2c transfer are forbiden in atomic context
  gpio: davinci: Include proper header
  gpio: da905x: Include proper header
  gpio: cs5535: Include proper header
  gpio: crystalcove: Include proper header
  gpio: bt8xx: Include proper header
  gpio: bcm-kona: Include proper header
  gpio: arizona: Include proper header
  gpio: amd8111: Include proper header
  ...
parents 50081e43 d58f2bf2
AXP209 GPIO controller AXP209 GPIO & pinctrl controller
This driver follows the usual GPIO bindings found in This driver follows the usual GPIO bindings found in
Documentation/devicetree/bindings/gpio/gpio.txt Documentation/devicetree/bindings/gpio/gpio.txt
This driver follows the usual pinctrl bindings found in
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
This driver employs the per-pin muxing pattern.
Required properties: Required properties:
- compatible: Should be "x-powers,axp209-gpio" - compatible: Should be one of:
- "x-powers,axp209-gpio"
- "x-powers,axp813-gpio"
- #gpio-cells: Should be two. The first cell is the pin number and the - #gpio-cells: Should be two. The first cell is the pin number and the
second is the GPIO flags. second is the GPIO flags.
- gpio-controller: Marks the device node as a GPIO controller. - gpio-controller: Marks the device node as a GPIO controller.
...@@ -28,3 +35,41 @@ axp209: pmic@34 { ...@@ -28,3 +35,41 @@ axp209: pmic@34 {
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
}; };
The GPIOs can be muxed to other functions and therefore, must be a subnode of
axp_gpio.
Example:
&axp_gpio {
gpio0_adc: gpio0-adc {
pins = "GPIO0";
function = "adc";
};
};
&example_node {
pinctrl-names = "default";
pinctrl-0 = <&gpio0_adc>;
};
GPIOs and their functions
-------------------------
Each GPIO is independent from the other (i.e. GPIO0 in gpio_in function does
not force GPIO1 and GPIO2 to be in gpio_in function as well).
axp209
------
GPIO | Functions
------------------------
GPIO0 | gpio_in, gpio_out, ldo, adc
GPIO1 | gpio_in, gpio_out, ldo, adc
GPIO2 | gpio_in, gpio_out
axp813
------
GPIO | Functions
------------------------
GPIO0 | gpio_in, gpio_out, ldo, adc
GPIO1 | gpio_in, gpio_out, ldo
...@@ -5,7 +5,7 @@ Required Properties: ...@@ -5,7 +5,7 @@ Required Properties:
- compatible: should contain one or more of the following: - compatible: should contain one or more of the following:
- "renesas,gpio-r8a7743": for R8A7743 (RZ/G1M) compatible GPIO controller. - "renesas,gpio-r8a7743": for R8A7743 (RZ/G1M) compatible GPIO controller.
- "renesas,gpio-r8a7745": for R8A7745 (RZ/G1E) compatible GPIO controller. - "renesas,gpio-r8a7745": for R8A7745 (RZ/G1E) compatible GPIO controller.
- "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. - "renesas,gpio-r8a7778": for R8A7778 (R-Car M1) compatible GPIO controller.
- "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller.
- "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller.
- "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller. - "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller.
......
...@@ -2,6 +2,7 @@ GPIO Mappings ...@@ -2,6 +2,7 @@ GPIO Mappings
============= =============
This document explains how GPIOs can be assigned to given devices and functions. This document explains how GPIOs can be assigned to given devices and functions.
Note that it only applies to the new descriptor-based interface. For a Note that it only applies to the new descriptor-based interface. For a
description of the deprecated integer-based GPIO interface please refer to description of the deprecated integer-based GPIO interface please refer to
gpio-legacy.txt (actually, there is no real mapping possible with the old gpio-legacy.txt (actually, there is no real mapping possible with the old
...@@ -49,7 +50,7 @@ This property will make GPIOs 15, 16 and 17 available to the driver under the ...@@ -49,7 +50,7 @@ This property will make GPIOs 15, 16 and 17 available to the driver under the
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH); power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);
The led GPIOs will be active-high, while the power GPIO will be active-low (i.e. The led GPIOs will be active high, while the power GPIO will be active low (i.e.
gpiod_is_active_low(power) will be true). gpiod_is_active_low(power) will be true).
The second parameter of the gpiod_get() functions, the con_id string, has to be The second parameter of the gpiod_get() functions, the con_id string, has to be
...@@ -122,9 +123,14 @@ where ...@@ -122,9 +123,14 @@ where
can be NULL, in which case it will match any function. can be NULL, in which case it will match any function.
- idx is the index of the GPIO within the function. - idx is the index of the GPIO within the function.
- flags is defined to specify the following properties: - flags is defined to specify the following properties:
* GPIOF_ACTIVE_LOW - to configure the GPIO as active-low * GPIO_ACTIVE_HIGH - GPIO line is active high
* GPIOF_OPEN_DRAIN - GPIO pin is open drain type. * GPIO_ACTIVE_LOW - GPIO line is active low
* GPIOF_OPEN_SOURCE - GPIO pin is open source type. * GPIO_OPEN_DRAIN - GPIO line is set up as open drain
* GPIO_OPEN_SOURCE - GPIO line is set up as open source
* GPIO_PERSISTENT - GPIO line is persistent during
suspend/resume and maintains its value
* GPIO_TRANSITORY - GPIO line is transitory and may loose its
electrical state during suspend/resume
In the future, these flags might be extended to support more properties. In the future, these flags might be extended to support more properties.
......
...@@ -66,6 +66,15 @@ for the GPIO. Values can be: ...@@ -66,6 +66,15 @@ for the GPIO. Values can be:
* GPIOD_IN to initialize the GPIO as input. * GPIOD_IN to initialize the GPIO as input.
* GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0. * GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0.
* GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1. * GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1.
* GPIOD_OUT_LOW_OPEN_DRAIN same as GPIOD_OUT_LOW but also enforce the line
to be electrically used with open drain.
* GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line
to be electrically used with open drain.
The two last flags are used for use cases where open drain is mandatory, such
as I2C: if the line is not already configured as open drain in the mappings
(see board.txt), then open drain will be enforced anyway and a warning will be
printed that the board configuration needs to be updated to match the use case.
Both functions return either a valid GPIO descriptor, or an error code checkable Both functions return either a valid GPIO descriptor, or an error code checkable
with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned
...@@ -184,7 +193,7 @@ A driver can also query the current direction of a GPIO: ...@@ -184,7 +193,7 @@ A driver can also query the current direction of a GPIO:
int gpiod_get_direction(const struct gpio_desc *desc) int gpiod_get_direction(const struct gpio_desc *desc)
This function will return either GPIOF_DIR_IN or GPIOF_DIR_OUT. This function returns 0 for output, 1 for input, or an error code in case of error.
Be aware that there is no default direction for GPIOs. Therefore, **using a GPIO Be aware that there is no default direction for GPIOs. Therefore, **using a GPIO
without setting its direction first is illegal and will result in undefined without setting its direction first is illegal and will result in undefined
...@@ -240,59 +249,71 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the ...@@ -240,59 +249,71 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the
spinlock-safe calls. spinlock-safe calls.
Active-low State and Raw GPIO Values The active low and open drain semantics
------------------------------------ ---------------------------------------
Device drivers like to manage the logical state of a GPIO, i.e. the value their As a consumer should not have to care about the physical line level, all of the
device will actually receive, no matter what lies between it and the GPIO line.
In some cases, it might make sense to control the actual GPIO line value. The
following set of calls ignore the active-low property of a GPIO and work on the
raw line value:
int gpiod_get_raw_value(const struct gpio_desc *desc)
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
The active-low state of a GPIO can also be queried using the following call:
int gpiod_is_active_low(const struct gpio_desc *desc)
Note that these functions should only be used with great moderation ; a driver
should not have to care about the physical line level.
The active-low property
-----------------------
As a driver should not have to care about the physical line level, all of the
gpiod_set_value_xxx() or gpiod_set_array_value_xxx() functions operate with gpiod_set_value_xxx() or gpiod_set_array_value_xxx() functions operate with
the *logical* value. With this they take the active-low property into account. the *logical* value. With this they take the active low property into account.
This means that they check whether the GPIO is configured to be active-low, This means that they check whether the GPIO is configured to be active low,
and if so, they manipulate the passed value before the physical line level is and if so, they manipulate the passed value before the physical line level is
driven. driven.
The same is applicable for open drain or open source output lines: those do not
actively drive their output high (open drain) or low (open source), they just
switch their output to a high impedance value. The consumer should not need to
care. (For details read about open drain in driver.txt.)
With this, all the gpiod_set_(array)_value_xxx() functions interpret the With this, all the gpiod_set_(array)_value_xxx() functions interpret the
parameter "value" as "active" ("1") or "inactive" ("0"). The physical line parameter "value" as "asserted" ("1") or "de-asserted" ("0"). The physical line
level will be driven accordingly. level will be driven accordingly.
As an example, if the active-low property for a dedicated GPIO is set, and the As an example, if the active low property for a dedicated GPIO is set, and the
gpiod_set_(array)_value_xxx() passes "active" ("1"), the physical line level gpiod_set_(array)_value_xxx() passes "asserted" ("1"), the physical line level
will be driven low. will be driven low.
To summarize: To summarize:
Function (example) active-low property physical line Function (example) line property physical line
gpiod_set_raw_value(desc, 0); don't care low gpiod_set_raw_value(desc, 0); don't care low
gpiod_set_raw_value(desc, 1); don't care high gpiod_set_raw_value(desc, 1); don't care high
gpiod_set_value(desc, 0); default (active-high) low gpiod_set_value(desc, 0); default (active high) low
gpiod_set_value(desc, 1); default (active-high) high gpiod_set_value(desc, 1); default (active high) high
gpiod_set_value(desc, 0); active-low high gpiod_set_value(desc, 0); active low high
gpiod_set_value(desc, 1); active-low low gpiod_set_value(desc, 1); active low low
gpiod_set_value(desc, 0); default (active high) low
Please note again that the set_raw/get_raw functions should be avoided as much gpiod_set_value(desc, 1); default (active high) high
as possible, especially by drivers which should not care about the actual gpiod_set_value(desc, 0); open drain low
physical line level and worry about the logical value instead. gpiod_set_value(desc, 1); open drain high impedance
gpiod_set_value(desc, 0); open source high impedance
gpiod_set_value(desc, 1); open source high
It is possible to override these semantics using the *set_raw/'get_raw functions
but it should be avoided as much as possible, especially by system-agnostic drivers
which should not need to care about the actual physical line level and worry about
the logical value instead.
Accessing raw GPIO values
-------------------------
Consumers exist that need to manage the logical state of a GPIO line, i.e. the value
their device will actually receive, no matter what lies between it and the GPIO
line.
The following set of calls ignore the active-low or open drain property of a GPIO and
work on the raw line value:
int gpiod_get_raw_value(const struct gpio_desc *desc)
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
The active low state of a GPIO can also be queried using the following call:
int gpiod_is_active_low(const struct gpio_desc *desc)
Note that these functions should only be used with great moderation; a driver
should not have to care about the physical line level or open drain semantics.
Access multiple GPIOs with a single function call Access multiple GPIOs with a single function call
......
...@@ -88,6 +88,10 @@ ending up in the pin control back-end "behind" the GPIO controller, usually ...@@ -88,6 +88,10 @@ ending up in the pin control back-end "behind" the GPIO controller, usually
closer to the actual pins. This way the pin controller can manage the below closer to the actual pins. This way the pin controller can manage the below
listed GPIO configurations. listed GPIO configurations.
If a pin controller back-end is used, the GPIO controller or hardware
description needs to provide "GPIO ranges" mapping the GPIO line offsets to pin
numbers on the pin controller so they can properly cross-reference each other.
GPIOs with debounce support GPIOs with debounce support
--------------------------- ---------------------------
......
GPIO Sysfs Interface for Userspace GPIO Sysfs Interface for Userspace
================================== ==================================
THIS ABI IS DEPRECATED, THE ABI DOCUMENTATION HAS BEEN MOVED TO
Documentation/ABI/obsolete/sysfs-gpio AND NEW USERSPACE CONSUMERS
ARE SUPPOSED TO USE THE CHARACTER DEVICE ABI. THIS OLD SYSFS ABI WILL
NOT BE DEVELOPED (NO NEW FEATURES), IT WILL JUST BE MAINTAINED.
Refer to the examples in tools/gpio/* for an introduction to the new
character device ABI. Also see the userspace header in
include/uapi/linux/gpio.h
The deprecated sysfs ABI
------------------------
Platforms which use the "gpiolib" implementors framework may choose to Platforms which use the "gpiolib" implementors framework may choose to
configure a sysfs user interface to GPIOs. This is different from the configure a sysfs user interface to GPIOs. This is different from the
debugfs interface, since it provides control over GPIO direction and debugfs interface, since it provides control over GPIO direction and
......
...@@ -8,17 +8,27 @@ Description ...@@ -8,17 +8,27 @@ Description
----------- -----------
GPIO 1-wire bus master driver. The driver uses the GPIO API to control the GPIO 1-wire bus master driver. The driver uses the GPIO API to control the
wire and the GPIO pin can be specified using platform data. wire and the GPIO pin can be specified using GPIO machine descriptor tables.
It is also possible to define the master using device tree, see
Documentation/devicetree/bindings/w1/w1-gpio.txt
Example (mach-at91) Example (mach-at91)
------------------- -------------------
#include <linux/gpio/machine.h>
#include <linux/w1-gpio.h> #include <linux/w1-gpio.h>
static struct gpiod_lookup_table foo_w1_gpiod_table = {
.dev_id = "w1-gpio",
.table = {
GPIO_LOOKUP_IDX("at91-gpio", AT91_PIN_PB20, NULL, 0,
GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN),
},
};
static struct w1_gpio_platform_data foo_w1_gpio_pdata = { static struct w1_gpio_platform_data foo_w1_gpio_pdata = {
.pin = AT91_PIN_PB20, .ext_pullup_enable_pin = -EINVAL,
.is_open_drain = 1,
}; };
static struct platform_device foo_w1_device = { static struct platform_device foo_w1_device = {
...@@ -30,4 +40,5 @@ static struct platform_device foo_w1_device = { ...@@ -30,4 +40,5 @@ static struct platform_device foo_w1_device = {
... ...
at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1); at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1);
at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1); at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1);
gpiod_add_lookup_table(&foo_w1_gpiod_table);
platform_device_register(&foo_w1_device); platform_device_register(&foo_w1_device);
...@@ -278,6 +278,12 @@ L: linux-gpio@vger.kernel.org ...@@ -278,6 +278,12 @@ L: linux-gpio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/gpio/gpio-pci-idio-16.c F: drivers/gpio/gpio-pci-idio-16.c
ACCES PCIe-IDIO-24 GPIO DRIVER
M: William Breathitt Gray <vilhelm.gray@gmail.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-pcie-idio-24.c
ACENIC DRIVER ACENIC DRIVER
M: Jes Sorensen <jes@trained-monkey.org> M: Jes Sorensen <jes@trained-monkey.org>
L: linux-acenic@sunsite.dk L: linux-acenic@sunsite.dk
...@@ -5979,6 +5985,7 @@ F: drivers/media/rc/gpio-ir-tx.c ...@@ -5979,6 +5985,7 @@ F: drivers/media/rc/gpio-ir-tx.c
GPIO MOCKUP DRIVER GPIO MOCKUP DRIVER
M: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> M: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
R: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-gpio@vger.kernel.org L: linux-gpio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/gpio/gpio-mockup.c F: drivers/gpio/gpio-mockup.c
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/w1-gpio.h> #include <linux/w1-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/mtd/plat-ram.h> #include <linux/mtd/plat-ram.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -162,9 +163,16 @@ static struct platform_device vulcan_max6369 = { ...@@ -162,9 +163,16 @@ static struct platform_device vulcan_max6369 = {
.num_resources = 1, .num_resources = 1,
}; };
static struct gpiod_lookup_table vulcan_w1_gpiod_table = {
.dev_id = "w1-gpio",
.table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", 14, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = { static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
.pin = 14, /* Intentionally left blank */
.ext_pullup_enable_pin = -EINVAL,
}; };
static struct platform_device vulcan_w1_gpio = { static struct platform_device vulcan_w1_gpio = {
...@@ -233,6 +241,7 @@ static void __init vulcan_init(void) ...@@ -233,6 +241,7 @@ static void __init vulcan_init(void)
IXP4XX_EXP_BUS_WR_EN | IXP4XX_EXP_BUS_WR_EN |
IXP4XX_EXP_BUS_BYTE_EN; IXP4XX_EXP_BUS_BYTE_EN;
gpiod_add_lookup_table(&vulcan_w1_gpiod_table);
platform_add_devices(vulcan_devices, ARRAY_SIZE(vulcan_devices)); platform_add_devices(vulcan_devices, ARRAY_SIZE(vulcan_devices));
} }
......
...@@ -506,11 +506,16 @@ static void w1_enable_external_pullup(int enable) ...@@ -506,11 +506,16 @@ static void w1_enable_external_pullup(int enable)
msleep(100); msleep(100);
} }
static struct gpiod_lookup_table raumfeld_w1_gpiod_table = {
.dev_id = "w1-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio-pxa", GPIO_ONE_WIRE, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct w1_gpio_platform_data w1_gpio_platform_data = { static struct w1_gpio_platform_data w1_gpio_platform_data = {
.pin = GPIO_ONE_WIRE,
.is_open_drain = 0,
.enable_external_pullup = w1_enable_external_pullup, .enable_external_pullup = w1_enable_external_pullup,
.ext_pullup_enable_pin = -EINVAL,
}; };
static struct platform_device raumfeld_w1_gpio_device = { static struct platform_device raumfeld_w1_gpio_device = {
...@@ -530,6 +535,7 @@ static void __init raumfeld_w1_init(void) ...@@ -530,6 +535,7 @@ static void __init raumfeld_w1_init(void)
else else
gpio_direction_output(GPIO_W1_PULLUP_ENABLE, 0); gpio_direction_output(GPIO_W1_PULLUP_ENABLE, 0);
gpiod_add_lookup_table(&raumfeld_w1_gpiod_table);
platform_device_register(&raumfeld_w1_gpio_device); platform_device_register(&raumfeld_w1_gpio_device);
} }
......
...@@ -122,12 +122,6 @@ config GPIO_ATH79 ...@@ -122,12 +122,6 @@ config GPIO_ATH79
Select this option to enable GPIO driver for Select this option to enable GPIO driver for
Atheros AR71XX/AR724X/AR913X SoC devices. Atheros AR71XX/AR724X/AR913X SoC devices.
config GPIO_AXP209
tristate "X-Powers AXP209 PMIC GPIO Support"
depends on MFD_AXP20X
help
Say yes to enable GPIO support for the AXP209 PMIC
config GPIO_BCM_KONA config GPIO_BCM_KONA
bool "Broadcom Kona GPIO" bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
...@@ -704,6 +698,22 @@ config GPIO_TS5500 ...@@ -704,6 +698,22 @@ config GPIO_TS5500
blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
LCD port. LCD port.
config GPIO_WINBOND
tristate "Winbond Super I/O GPIO support"
depends on ISA_BUS_API
help
This option enables support for GPIOs found on Winbond Super I/O
chips.
Currently, only W83627UHG (also known as Nuvoton NCT6627UD) is
supported.
You will need to provide a module parameter "gpios", or a
boot-time parameter "gpio_winbond.gpios" with a bitmask of GPIO
ports to enable (bit 0 is GPIO1, bit 1 is GPIO2, etc.).
To compile this driver as a module, choose M here: the module will
be called gpio-winbond.
config GPIO_WS16C48 config GPIO_WS16C48
tristate "WinSystems WS16C48 GPIO support" tristate "WinSystems WS16C48 GPIO support"
depends on ISA_BUS_API depends on ISA_BUS_API
...@@ -1234,6 +1244,16 @@ config GPIO_PCI_IDIO_16 ...@@ -1234,6 +1244,16 @@ config GPIO_PCI_IDIO_16
low). Input filter control is not supported by this driver, and the low). Input filter control is not supported by this driver, and the
input filters are deactivated by this driver. input filters are deactivated by this driver.
config GPIO_PCIE_IDIO_24
tristate "ACCES PCIe-IDIO-24 GPIO support"
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES PCIe-IDIO-24 family (PCIe-IDIO-24,
PCIe-IDI-24, PCIe-IDO-24, PCIe-IDIO-12). An interrupt is generated
when any of the inputs change state (low to high or high to low).
Input filter control is not supported by this driver, and the input
filters are deactivated by this driver.
config GPIO_RDC321X config GPIO_RDC321X
tristate "RDC R-321x GPIO support" tristate "RDC R-321x GPIO support"
select MFD_CORE select MFD_CORE
......
...@@ -32,7 +32,6 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o ...@@ -32,7 +32,6 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
...@@ -96,6 +95,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o ...@@ -96,6 +95,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o
obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
...@@ -140,6 +140,7 @@ obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o ...@@ -140,6 +140,7 @@ obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o
obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
......
...@@ -124,6 +124,48 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, ...@@ -124,6 +124,48 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
} }
EXPORT_SYMBOL(devm_gpiod_get_index); EXPORT_SYMBOL(devm_gpiod_get_index);
/**
* devm_gpiod_get_from_of_node() - obtain a GPIO from an OF node
* @dev: device for lifecycle management
* @node: handle of the OF node
* @propname: name of the DT property representing the GPIO
* @index: index of the GPIO to obtain for the consumer
* @dflags: GPIO initialization flags
* @label: label to attach to the requested GPIO
*
* Returns:
* On successful request the GPIO pin is configured in accordance with
* provided @dflags.
*
* In case of error an ERR_PTR() is returned.
*/
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
{
struct gpio_desc **dr;
struct gpio_desc *desc;
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
desc = gpiod_get_from_of_node(node, propname, index, dflags, label);
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
}
*dr = desc;
devres_add(dev, dr);
return desc;
}
EXPORT_SYMBOL(devm_gpiod_get_from_of_node);
/** /**
* devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
* device's child node * device's child node
......
...@@ -9,12 +9,11 @@ ...@@ -9,12 +9,11 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/gpio/consumer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/of_gpio.h> #include <linux/gpio/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/adp5520.h> #include <linux/mfd/adp5520.h>
#include <linux/gpio/driver.h>
#include <linux/gpio.h>
struct adp5520_gpio { struct adp5520_gpio {
struct device *master; struct device *master;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h> #include <linux/gpio/driver.h>
#include <linux/of_gpio.h> /* For of_mm_gpio_chip */
#include <linux/platform_device.h> #include <linux/platform_device.h>
#define ALTERA_GPIO_MAX_NGPIO 32 #define ALTERA_GPIO_MAX_NGPIO 32
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
......
...@@ -60,6 +60,7 @@ struct aspeed_gpio_bank { ...@@ -60,6 +60,7 @@ struct aspeed_gpio_bank {
uint16_t val_regs; uint16_t val_regs;
uint16_t irq_regs; uint16_t irq_regs;
uint16_t debounce_regs; uint16_t debounce_regs;
uint16_t tolerance_regs;
const char names[4][3]; const char names[4][3];
}; };
...@@ -70,48 +71,56 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = { ...@@ -70,48 +71,56 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
.val_regs = 0x0000, .val_regs = 0x0000,
.irq_regs = 0x0008, .irq_regs = 0x0008,
.debounce_regs = 0x0040, .debounce_regs = 0x0040,
.tolerance_regs = 0x001c,
.names = { "A", "B", "C", "D" }, .names = { "A", "B", "C", "D" },
}, },
{ {
.val_regs = 0x0020, .val_regs = 0x0020,
.irq_regs = 0x0028, .irq_regs = 0x0028,
.debounce_regs = 0x0048, .debounce_regs = 0x0048,
.tolerance_regs = 0x003c,
.names = { "E", "F", "G", "H" }, .names = { "E", "F", "G", "H" },
}, },
{ {
.val_regs = 0x0070, .val_regs = 0x0070,
.irq_regs = 0x0098, .irq_regs = 0x0098,
.debounce_regs = 0x00b0, .debounce_regs = 0x00b0,
.tolerance_regs = 0x00ac,
.names = { "I", "J", "K", "L" }, .names = { "I", "J", "K", "L" },
}, },
{ {
.val_regs = 0x0078, .val_regs = 0x0078,
.irq_regs = 0x00e8, .irq_regs = 0x00e8,
.debounce_regs = 0x0100, .debounce_regs = 0x0100,
.tolerance_regs = 0x00fc,
.names = { "M", "N", "O", "P" }, .names = { "M", "N", "O", "P" },
}, },
{ {
.val_regs = 0x0080, .val_regs = 0x0080,
.irq_regs = 0x0118, .irq_regs = 0x0118,
.debounce_regs = 0x0130, .debounce_regs = 0x0130,
.tolerance_regs = 0x012c,
.names = { "Q", "R", "S", "T" }, .names = { "Q", "R", "S", "T" },
}, },
{ {
.val_regs = 0x0088, .val_regs = 0x0088,
.irq_regs = 0x0148, .irq_regs = 0x0148,
.debounce_regs = 0x0160, .debounce_regs = 0x0160,
.tolerance_regs = 0x015c,
.names = { "U", "V", "W", "X" }, .names = { "U", "V", "W", "X" },
}, },
{ {
.val_regs = 0x01E0, .val_regs = 0x01E0,
.irq_regs = 0x0178, .irq_regs = 0x0178,
.debounce_regs = 0x0190, .debounce_regs = 0x0190,
.tolerance_regs = 0x018c,
.names = { "Y", "Z", "AA", "AB" }, .names = { "Y", "Z", "AA", "AB" },
}, },
{ {
.val_regs = 0x01E8, .val_regs = 0x01e8,
.irq_regs = 0x01A8, .irq_regs = 0x01a8,
.debounce_regs = 0x01c0, .debounce_regs = 0x01c0,
.tolerance_regs = 0x01bc,
.names = { "AC", "", "", "" }, .names = { "AC", "", "", "" },
}, },
}; };
...@@ -140,7 +149,7 @@ static const struct aspeed_gpio_bank *to_bank(unsigned int offset) ...@@ -140,7 +149,7 @@ static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
{ {
unsigned int bank = GPIO_BANK(offset); unsigned int bank = GPIO_BANK(offset);
WARN_ON(bank > ARRAY_SIZE(aspeed_gpio_banks)); WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks));
return &aspeed_gpio_banks[bank]; return &aspeed_gpio_banks[bank];
} }
...@@ -534,6 +543,30 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio, ...@@ -534,6 +543,30 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
return 0; return 0;
} }
static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
unsigned int offset, bool enable)
{
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
const struct aspeed_gpio_bank *bank;
unsigned long flags;
u32 val;
bank = to_bank(offset);
spin_lock_irqsave(&gpio->lock, flags);
val = readl(gpio->base + bank->tolerance_regs);
if (enable)
val |= GPIO_BIT(offset);
else
val &= ~GPIO_BIT(offset);
writel(val, gpio->base + bank->tolerance_regs);
spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset) static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
{ {
if (!have_gpio(gpiochip_get_data(chip), offset)) if (!have_gpio(gpiochip_get_data(chip), offset))
...@@ -771,6 +804,8 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, ...@@ -771,6 +804,8 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
param == PIN_CONFIG_DRIVE_OPEN_SOURCE) param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
/* Return -ENOTSUPP to trigger emulation, as per datasheet */ /* Return -ENOTSUPP to trigger emulation, as per datasheet */
return -ENOTSUPP; return -ENOTSUPP;
else if (param == PIN_CONFIG_PERSIST_STATE)
return aspeed_gpio_reset_tolerance(chip, offset, arg);
return -ENOTSUPP; return -ENOTSUPP;
} }
......
...@@ -324,3 +324,6 @@ static struct platform_driver ath79_gpio_driver = { ...@@ -324,3 +324,6 @@ static struct platform_driver ath79_gpio_driver = {
}; };
module_platform_driver(ath79_gpio_driver); module_platform_driver(ath79_gpio_driver);
MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support");
MODULE_LICENSE("GPL v2");
/*
* AXP20x GPIO driver
*
* Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/axp20x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#define AXP20X_GPIO_FUNCTIONS 0x7
#define AXP20X_GPIO_FUNCTION_OUT_LOW 0
#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
#define AXP20X_GPIO_FUNCTION_INPUT 2
struct axp20x_gpio {
struct gpio_chip chip;
struct regmap *regmap;
};
static int axp20x_gpio_get_reg(unsigned offset)
{
switch (offset) {
case 0:
return AXP20X_GPIO0_CTRL;
case 1:
return AXP20X_GPIO1_CTRL;
case 2:
return AXP20X_GPIO2_CTRL;
}
return -EINVAL;
}
static int axp20x_gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
int reg;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
return regmap_update_bits(gpio->regmap, reg,
AXP20X_GPIO_FUNCTIONS,
AXP20X_GPIO_FUNCTION_INPUT);
}
static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
int ret;
ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
if (ret)
return ret;
return !!(val & BIT(offset + 4));
}
static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
int reg, ret;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
ret = regmap_read(gpio->regmap, reg, &val);
if (ret)
return ret;
/*
* This shouldn't really happen if the pin is in use already,
* or if it's not in use yet, it doesn't matter since we're
* going to change the value soon anyway. Default to output.
*/
if ((val & AXP20X_GPIO_FUNCTIONS) > 2)
return 0;
/*
* The GPIO directions are the three lowest values.
* 2 is input, 0 and 1 are output
*/
return val & 2;
}
static int axp20x_gpio_output(struct gpio_chip *chip, unsigned offset,
int value)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
int reg;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
return regmap_update_bits(gpio->regmap, reg,
AXP20X_GPIO_FUNCTIONS,
value ? AXP20X_GPIO_FUNCTION_OUT_HIGH
: AXP20X_GPIO_FUNCTION_OUT_LOW);
}
static void axp20x_gpio_set(struct gpio_chip *chip, unsigned offset,
int value)
{
axp20x_gpio_output(chip, offset, value);
}
static int axp20x_gpio_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct axp20x_gpio *gpio;
int ret;
if (!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
if (!axp20x) {
dev_err(&pdev->dev, "Parent drvdata not set\n");
return -EINVAL;
}
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
gpio->chip.base = -1;
gpio->chip.can_sleep = true;
gpio->chip.parent = &pdev->dev;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.owner = THIS_MODULE;
gpio->chip.get = axp20x_gpio_get;
gpio->chip.get_direction = axp20x_gpio_get_direction;
gpio->chip.set = axp20x_gpio_set;
gpio->chip.direction_input = axp20x_gpio_input;
gpio->chip.direction_output = axp20x_gpio_output;
gpio->chip.ngpio = 3;
gpio->regmap = axp20x->regmap;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPIO chip\n");
return ret;
}
dev_info(&pdev->dev, "AXP209 GPIO driver loaded\n");
return 0;
}
static const struct of_device_id axp20x_gpio_match[] = {
{ .compatible = "x-powers,axp209-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, axp20x_gpio_match);
static struct platform_driver axp20x_gpio_driver = {
.probe = axp20x_gpio_probe,
.driver = {
.name = "axp20x-gpio",
.of_match_table = axp20x_gpio_match,
},
};
module_platform_driver(axp20x_gpio_driver);
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
MODULE_DESCRIPTION("AXP20x PMIC GPIO driver");
MODULE_LICENSE("GPL");
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -127,7 +127,7 @@ static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio) ...@@ -127,7 +127,7 @@ static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
u32 val; u32 val;
val = readl(reg_base + GPIO_CONTROL(gpio)) & GPIO_GPCTR0_IOTR_MASK; val = readl(reg_base + GPIO_CONTROL(gpio)) & GPIO_GPCTR0_IOTR_MASK;
return val ? GPIOF_DIR_IN : GPIOF_DIR_OUT; return !!val;
} }
static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
...@@ -144,7 +144,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) ...@@ -144,7 +144,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
raw_spin_lock_irqsave(&kona_gpio->lock, flags); raw_spin_lock_irqsave(&kona_gpio->lock, flags);
/* this function only applies to output pin */ /* this function only applies to output pin */
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN) if (bcm_kona_gpio_get_dir(chip, gpio) == 1)
goto out; goto out;
reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id); reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
...@@ -170,7 +170,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) ...@@ -170,7 +170,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
reg_base = kona_gpio->reg_base; reg_base = kona_gpio->reg_base;
raw_spin_lock_irqsave(&kona_gpio->lock, flags); raw_spin_lock_irqsave(&kona_gpio->lock, flags);
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN) if (bcm_kona_gpio_get_dir(chip, gpio) == 1)
reg_offset = GPIO_IN_STATUS(bank_id); reg_offset = GPIO_IN_STATUS(bank_id);
else else
reg_offset = GPIO_OUT_STATUS(bank_id); reg_offset = GPIO_OUT_STATUS(bank_id);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/bitops.h>
enum gio_reg_index { enum gio_reg_index {
GIO_REG_ODEN = 0, GIO_REG_ODEN = 0,
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
/* Steal the hardware definitions from the bttv driver. */ /* Steal the hardware definitions from the bttv driver. */
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/regmap.h> #include <linux/regmap.h>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/cs5535.h> #include <linux/cs5535.h>
#include <asm/msr.h> #include <asm/msr.h>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/mfd/da9055/core.h> #include <linux/mfd/da9055/core.h>
#include <linux/mfd/da9055/reg.h> #include <linux/mfd/da9055/reg.h>
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
*/ */
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/clk.h> #include <linux/clk.h>
......
...@@ -176,8 +176,8 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) ...@@ -176,8 +176,8 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
return PTR_ERR(g->base); return PTR_ERR(g->base);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (!irq) if (irq <= 0)
return -EINVAL; return irq ? irq : -EINVAL;
ret = bgpio_init(&g->gc, dev, 4, ret = bgpio_init(&g->gc, dev, 4,
g->base + GPIO_DATA_IN, g->base + GPIO_DATA_IN,
......
...@@ -58,3 +58,7 @@ static int __init iop3xx_gpio_init(void) ...@@ -58,3 +58,7 @@ static int __init iop3xx_gpio_init(void)
return platform_driver_register(&iop3xx_gpio_driver); return platform_driver_register(&iop3xx_gpio_driver);
} }
arch_initcall(iop3xx_gpio_init); arch_initcall(iop3xx_gpio_init);
MODULE_DESCRIPTION("GPIO handling for Intel IOP3xx processors");
MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
MODULE_LICENSE("GPL");
...@@ -414,6 +414,6 @@ static void __exit it87_gpio_exit(void) ...@@ -414,6 +414,6 @@ static void __exit it87_gpio_exit(void)
module_init(it87_gpio_init); module_init(it87_gpio_init);
module_exit(it87_gpio_exit); module_exit(it87_gpio_exit);
MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>"); MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips"); MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -709,7 +709,6 @@ static int max732x_probe(struct i2c_client *client, ...@@ -709,7 +709,6 @@ static int max732x_probe(struct i2c_client *client,
return 0; return 0;
out_failed: out_failed:
if (chip->client_dummy)
i2c_unregister_device(chip->client_dummy); i2c_unregister_device(chip->client_dummy);
return ret; return ret;
} }
...@@ -734,7 +733,6 @@ static int max732x_remove(struct i2c_client *client) ...@@ -734,7 +733,6 @@ static int max732x_remove(struct i2c_client *client)
gpiochip_remove(&chip->gpio_chip); gpiochip_remove(&chip->gpio_chip);
/* unregister any dummy i2c_client */ /* unregister any dummy i2c_client */
if (chip->client_dummy)
i2c_unregister_device(chip->client_dummy); i2c_unregister_device(chip->client_dummy);
return 0; return 0;
......
This diff is collapsed.
...@@ -1058,7 +1058,9 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) ...@@ -1058,7 +1058,9 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
{ {
struct gpio_irq_chip *irq;
static int gpio; static int gpio;
const char *label;
int irq_base = 0; int irq_base = 0;
int ret; int ret;
...@@ -1080,21 +1082,15 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) ...@@ -1080,21 +1082,15 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
bank->chip.parent = &omap_mpuio_device.dev; bank->chip.parent = &omap_mpuio_device.dev;
bank->chip.base = OMAP_MPUIO(0); bank->chip.base = OMAP_MPUIO(0);
} else { } else {
bank->chip.label = "gpio"; label = devm_kasprintf(bank->chip.parent, GFP_KERNEL, "gpio-%d-%d",
gpio, gpio + bank->width - 1);
if (!label)
return -ENOMEM;
bank->chip.label = label;
bank->chip.base = gpio; bank->chip.base = gpio;
} }
bank->chip.ngpio = bank->width; bank->chip.ngpio = bank->width;
ret = gpiochip_add_data(&bank->chip, bank);
if (ret) {
dev_err(bank->chip.parent,
"Could not register gpio chip %d\n", ret);
return ret;
}
if (!bank->is_mpuio)
gpio += bank->width;
#ifdef CONFIG_ARCH_OMAP1 #ifdef CONFIG_ARCH_OMAP1
/* /*
* REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
...@@ -1115,25 +1111,30 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) ...@@ -1115,25 +1111,30 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
irqc->irq_set_wake = NULL; irqc->irq_set_wake = NULL;
} }
ret = gpiochip_irqchip_add(&bank->chip, irqc, irq = &bank->chip.irq;
irq_base, handle_bad_irq, irq->chip = irqc;
IRQ_TYPE_NONE); irq->handler = handle_bad_irq;
irq->default_type = IRQ_TYPE_NONE;
irq->num_parents = 1;
irq->parents = &bank->irq;
irq->first = irq_base;
ret = gpiochip_add_data(&bank->chip, bank);
if (ret) { if (ret) {
dev_err(bank->chip.parent, dev_err(bank->chip.parent,
"Couldn't add irqchip to gpiochip %d\n", ret); "Could not register gpio chip %d\n", ret);
gpiochip_remove(&bank->chip); return ret;
return -ENODEV;
} }
gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL);
ret = devm_request_irq(bank->chip.parent, bank->irq, ret = devm_request_irq(bank->chip.parent, bank->irq,
omap_gpio_irq_handler, omap_gpio_irq_handler,
0, dev_name(bank->chip.parent), bank); 0, dev_name(bank->chip.parent), bank);
if (ret) if (ret)
gpiochip_remove(&bank->chip); gpiochip_remove(&bank->chip);
if (!bank->is_mpuio)
gpio += bank->width;
return ret; return ret;
} }
......
This diff is collapsed.
...@@ -190,6 +190,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) ...@@ -190,6 +190,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
}; };
int i, j; int i, j;
/*
* STMPE1600: to be able to get IRQ from pins,
* a read must be done on GPMR register, or a write in
* GPSR or GPCR registers
*/
if (stmpe->partnum == STMPE1600) {
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
}
for (i = 0; i < CACHE_NR_REGS; i++) { for (i = 0; i < CACHE_NR_REGS; i++) {
/* STMPE801 and STMPE1600 don't have RE and FE registers */ /* STMPE801 and STMPE1600 don't have RE and FE registers */
if ((stmpe->partnum == STMPE801 || if ((stmpe->partnum == STMPE801 ||
...@@ -227,21 +237,11 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d) ...@@ -227,21 +237,11 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
struct stmpe *stmpe = stmpe_gpio->stmpe;
int offset = d->hwirq; int offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = BIT(offset % 8); int mask = BIT(offset % 8);
stmpe_gpio->regs[REG_IE][regoffset] |= mask; stmpe_gpio->regs[REG_IE][regoffset] |= mask;
/*
* STMPE1600 workaround: to be able to get IRQ from pins,
* a read must be done on GPMR register, or a write in
* GPSR or GPCR registers
*/
if (stmpe->partnum == STMPE1600)
stmpe_reg_read(stmpe,
stmpe->regs[STMPE_IDX_GPMR_LSB + regoffset]);
} }
static void stmpe_dbg_show_one(struct seq_file *s, static void stmpe_dbg_show_one(struct seq_file *s,
...@@ -273,15 +273,21 @@ static void stmpe_dbg_show_one(struct seq_file *s, ...@@ -273,15 +273,21 @@ static void stmpe_dbg_show_one(struct seq_file *s,
u8 fall_reg; u8 fall_reg;
u8 irqen_reg; u8 irqen_reg;
char *edge_det_values[] = {"edge-inactive", static const char * const edge_det_values[] = {
"edge-inactive",
"edge-asserted", "edge-asserted",
"not-supported"}; "not-supported"
char *rise_values[] = {"no-rising-edge-detection", };
static const char * const rise_values[] = {
"no-rising-edge-detection",
"rising-edge-detection", "rising-edge-detection",
"not-supported"}; "not-supported"
char *fall_values[] = {"no-falling-edge-detection", };
static const char * const fall_values[] = {
"no-falling-edge-detection",
"falling-edge-detection", "falling-edge-detection",
"not-supported"}; "not-supported"
};
#define NOT_SUPPORTED_IDX 2 #define NOT_SUPPORTED_IDX 2
u8 edge_det = NOT_SUPPORTED_IDX; u8 edge_det = NOT_SUPPORTED_IDX;
u8 rise = NOT_SUPPORTED_IDX; u8 rise = NOT_SUPPORTED_IDX;
...@@ -344,7 +350,7 @@ static void stmpe_dbg_show(struct seq_file *s, struct gpio_chip *gc) ...@@ -344,7 +350,7 @@ static void stmpe_dbg_show(struct seq_file *s, struct gpio_chip *gc)
for (i = 0; i < gc->ngpio; i++, gpio++) { for (i = 0; i < gc->ngpio; i++, gpio++) {
stmpe_dbg_show_one(s, gc, i, gpio); stmpe_dbg_show_one(s, gc, i, gpio);
seq_printf(s, "\n"); seq_putc(s, '\n');
} }
} }
...@@ -426,12 +432,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -426,12 +432,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct stmpe_gpio *stmpe_gpio; struct stmpe_gpio *stmpe_gpio;
int ret; int ret, irq;
int irq = 0;
irq = platform_get_irq(pdev, 0); stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL);
stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
if (!stmpe_gpio) if (!stmpe_gpio)
return -ENOMEM; return -ENOMEM;
...@@ -453,6 +456,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -453,6 +456,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
if (stmpe_gpio->norequest_mask) if (stmpe_gpio->norequest_mask)
stmpe_gpio->chip.irq.need_valid_mask = true; stmpe_gpio->chip.irq.need_valid_mask = true;
irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
dev_info(&pdev->dev, dev_info(&pdev->dev,
"device configured in no-irq mode: " "device configured in no-irq mode: "
......
...@@ -553,8 +553,10 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, ...@@ -553,8 +553,10 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
0, 0, of_node_to_fwnode(dev->of_node), 0, 0, of_node_to_fwnode(dev->of_node),
&thunderx_gpio_irqd_ops, txgpio); &thunderx_gpio_irqd_ops, txgpio);
if (!txgpio->irqd) if (!txgpio->irqd) {
err = -ENOMEM;
goto out; goto out;
}
/* Push on irq_data and the domain for each line. */ /* Push on irq_data and the domain for each line. */
for (i = 0; i < ngpio; i++) { for (i = 0; i < ngpio; i++) {
......
This diff is collapsed.
...@@ -414,7 +414,8 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios); ...@@ -414,7 +414,8 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
static bool acpi_get_driver_gpio_data(struct acpi_device *adev, static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
const char *name, int index, const char *name, int index,
struct acpi_reference_args *args) struct acpi_reference_args *args,
unsigned int *quirks)
{ {
const struct acpi_gpio_mapping *gm; const struct acpi_gpio_mapping *gm;
...@@ -430,6 +431,8 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev, ...@@ -430,6 +431,8 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
args->args[1] = par->line_index; args->args[1] = par->line_index;
args->args[2] = par->active_low; args->args[2] = par->active_low;
args->nargs = 3; args->nargs = 3;
*quirks = gm->quirks;
return true; return true;
} }
...@@ -461,8 +464,8 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) ...@@ -461,8 +464,8 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
} }
} }
int static int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
{ {
int ret = 0; int ret = 0;
...@@ -489,12 +492,31 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) ...@@ -489,12 +492,31 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
return ret; return ret;
} }
int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
{
struct device *dev = &info->adev->dev;
enum gpiod_flags old = *flags;
int ret;
ret = __acpi_gpio_update_gpiod_flags(&old, info->flags);
if (info->quirks & ACPI_GPIO_QUIRK_NO_IO_RESTRICTION) {
if (ret)
dev_warn(dev, FW_BUG "GPIO not in correct mode, fixing\n");
} else {
if (ret)
dev_dbg(dev, "Override GPIO initialization flags\n");
*flags = old;
}
return ret;
}
struct acpi_gpio_lookup { struct acpi_gpio_lookup {
struct acpi_gpio_info info; struct acpi_gpio_info info;
int index; int index;
int pin_index; int pin_index;
bool active_low; bool active_low;
struct acpi_device *adev;
struct gpio_desc *desc; struct gpio_desc *desc;
int n; int n;
}; };
...@@ -531,8 +553,8 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) ...@@ -531,8 +553,8 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
lookup->info.triggering = agpio->triggering; lookup->info.triggering = agpio->triggering;
} else { } else {
lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio); lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio);
lookup->info.polarity = lookup->active_low;
} }
} }
return 1; return 1;
...@@ -541,12 +563,13 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) ...@@ -541,12 +563,13 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
struct acpi_gpio_info *info) struct acpi_gpio_info *info)
{ {
struct acpi_device *adev = lookup->info.adev;
struct list_head res_list; struct list_head res_list;
int ret; int ret;
INIT_LIST_HEAD(&res_list); INIT_LIST_HEAD(&res_list);
ret = acpi_dev_get_resources(lookup->adev, &res_list, ret = acpi_dev_get_resources(adev, &res_list,
acpi_populate_gpio_lookup, acpi_populate_gpio_lookup,
lookup); lookup);
if (ret < 0) if (ret < 0)
...@@ -557,11 +580,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, ...@@ -557,11 +580,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
if (!lookup->desc) if (!lookup->desc)
return -ENOENT; return -ENOENT;
if (info) { if (info)
*info = lookup->info; *info = lookup->info;
if (lookup->active_low)
info->polarity = lookup->active_low;
}
return 0; return 0;
} }
...@@ -570,6 +590,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, ...@@ -570,6 +590,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
struct acpi_gpio_lookup *lookup) struct acpi_gpio_lookup *lookup)
{ {
struct acpi_reference_args args; struct acpi_reference_args args;
unsigned int quirks = 0;
int ret; int ret;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -581,14 +602,14 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, ...@@ -581,14 +602,14 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
if (!adev) if (!adev)
return ret; return ret;
if (!acpi_get_driver_gpio_data(adev, propname, index, &args)) if (!acpi_get_driver_gpio_data(adev, propname, index, &args,
&quirks))
return ret; return ret;
} }
/* /*
* The property was found and resolved, so need to lookup the GPIO based * The property was found and resolved, so need to lookup the GPIO based
* on returned args. * on returned args.
*/ */
lookup->adev = args.adev;
if (args.nargs != 3) if (args.nargs != 3)
return -EPROTO; return -EPROTO;
...@@ -596,6 +617,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, ...@@ -596,6 +617,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
lookup->pin_index = args.args[1]; lookup->pin_index = args.args[1];
lookup->active_low = !!args.args[2]; lookup->active_low = !!args.args[2];
lookup->info.adev = args.adev;
lookup->info.quirks = quirks;
return 0; return 0;
} }
...@@ -643,11 +666,11 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, ...@@ -643,11 +666,11 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ERR_PTR(ret); return ERR_PTR(ret);
dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n", dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n",
dev_name(&lookup.adev->dev), lookup.index, dev_name(&lookup.info.adev->dev), lookup.index,
lookup.pin_index, lookup.active_low); lookup.pin_index, lookup.active_low);
} else { } else {
dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
lookup.adev = adev; lookup.info.adev = adev;
} }
ret = acpi_gpio_resource_lookup(&lookup, info); ret = acpi_gpio_resource_lookup(&lookup, info);
...@@ -664,7 +687,6 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, ...@@ -664,7 +687,6 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
struct acpi_gpio_info info; struct acpi_gpio_info info;
struct gpio_desc *desc; struct gpio_desc *desc;
char propname[32]; char propname[32];
int err;
int i; int i;
/* Try first from _DSD */ /* Try first from _DSD */
...@@ -703,10 +725,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, ...@@ -703,10 +725,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
if (info.polarity == GPIO_ACTIVE_LOW) if (info.polarity == GPIO_ACTIVE_LOW)
*lookupflags |= GPIO_ACTIVE_LOW; *lookupflags |= GPIO_ACTIVE_LOW;
err = acpi_gpio_update_gpiod_flags(dflags, info.flags); acpi_gpio_update_gpiod_flags(dflags, &info);
if (err)
dev_dbg(dev, "Override GPIO initialization flags\n");
return desc; return desc;
} }
......
...@@ -56,6 +56,42 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, ...@@ -56,6 +56,42 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
return gpiochip_get_desc(chip, ret); return gpiochip_get_desc(chip, ret);
} }
static void of_gpio_flags_quirks(struct device_node *np,
enum of_gpio_flags *flags)
{
/*
* Some GPIO fixed regulator quirks.
* Note that active low is the default.
*/
if (IS_ENABLED(CONFIG_REGULATOR) &&
(of_device_is_compatible(np, "reg-fixed-voltage") ||
of_device_is_compatible(np, "regulator-gpio"))) {
/*
* The regulator GPIO handles are specified such that the
* presence or absence of "enable-active-high" solely controls
* the polarity of the GPIO line. Any phandle flags must
* be actively ignored.
*/
if (*flags & OF_GPIO_ACTIVE_LOW) {
pr_warn("%s GPIO handle specifies active low - ignored\n",
of_node_full_name(np));
*flags &= ~OF_GPIO_ACTIVE_LOW;
}
if (!of_property_read_bool(np, "enable-active-high"))
*flags |= OF_GPIO_ACTIVE_LOW;
}
/*
* Legacy open drain handling for fixed voltage regulators.
*/
if (IS_ENABLED(CONFIG_REGULATOR) &&
of_device_is_compatible(np, "reg-fixed-voltage") &&
of_property_read_bool(np, "gpio-open-drain")) {
*flags |= (OF_GPIO_SINGLE_ENDED | OF_GPIO_OPEN_DRAIN);
pr_info("%s uses legacy open drain flag - update the DTS if you can\n",
of_node_full_name(np));
}
}
/** /**
* of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API
* @np: device node to get GPIO from * @np: device node to get GPIO from
...@@ -93,6 +129,9 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, ...@@ -93,6 +129,9 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
if (IS_ERR(desc)) if (IS_ERR(desc))
goto out; goto out;
if (flags)
of_gpio_flags_quirks(np, flags);
pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n", pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n",
__func__, propname, np, index, __func__, propname, np, index,
PTR_ERR_OR_ZERO(desc)); PTR_ERR_OR_ZERO(desc));
...@@ -117,6 +156,71 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, ...@@ -117,6 +156,71 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
} }
EXPORT_SYMBOL(of_get_named_gpio_flags); EXPORT_SYMBOL(of_get_named_gpio_flags);
/*
* The SPI GPIO bindings happened before we managed to establish that GPIO
* properties should be named "foo-gpios" so we have this special kludge for
* them.
*/
static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id,
enum of_gpio_flags *of_flags)
{
char prop_name[32]; /* 32 is max size of property name */
struct device_node *np = dev->of_node;
struct gpio_desc *desc;
/*
* Hopefully the compiler stubs the rest of the function if this
* is false.
*/
if (!IS_ENABLED(CONFIG_SPI_MASTER))
return ERR_PTR(-ENOENT);
/* Allow this specifically for "spi-gpio" devices */
if (!of_device_is_compatible(np, "spi-gpio") || !con_id)
return ERR_PTR(-ENOENT);
/* Will be "gpio-sck", "gpio-mosi" or "gpio-miso" */
snprintf(prop_name, sizeof(prop_name), "%s-%s", "gpio", con_id);
desc = of_get_named_gpiod_flags(np, prop_name, 0, of_flags);
return desc;
}
/*
* Some regulator bindings happened before we managed to establish that GPIO
* properties should be named "foo-gpios" so we have this special kludge for
* them.
*/
static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *con_id,
enum of_gpio_flags *of_flags)
{
/* These are the connection IDs we accept as legacy GPIO phandles */
const char *whitelist[] = {
"wlf,ldoena", /* Arizona */
"wlf,ldo1ena", /* WM8994 */
"wlf,ldo2ena", /* WM8994 */
};
struct device_node *np = dev->of_node;
struct gpio_desc *desc;
int i;
if (!IS_ENABLED(CONFIG_REGULATOR))
return ERR_PTR(-ENOENT);
if (!con_id)
return ERR_PTR(-ENOENT);
for (i = 0; i < ARRAY_SIZE(whitelist); i++)
if (!strcmp(con_id, whitelist[i]))
break;
if (i == ARRAY_SIZE(whitelist))
return ERR_PTR(-ENOENT);
desc = of_get_named_gpiod_flags(np, con_id, 0, of_flags);
return desc;
}
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpio_lookup_flags *flags) enum gpio_lookup_flags *flags)
...@@ -126,6 +230,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -126,6 +230,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
struct gpio_desc *desc; struct gpio_desc *desc;
unsigned int i; unsigned int i;
/* Try GPIO property "foo-gpios" and "foo-gpio" */
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id) if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id, snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
...@@ -140,6 +245,14 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -140,6 +245,14 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
break; break;
} }
/* Special handling for SPI GPIOs if used */
if (IS_ERR(desc))
desc = of_find_spi_gpio(dev, con_id, &of_flags);
/* Special handling for regulator GPIOs if used */
if (IS_ERR(desc))
desc = of_find_regulator_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc)) if (IS_ERR(desc))
return desc; return desc;
...@@ -153,8 +266,8 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -153,8 +266,8 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
*flags |= GPIO_OPEN_SOURCE; *flags |= GPIO_OPEN_SOURCE;
} }
if (of_flags & OF_GPIO_SLEEP_MAY_LOSE_VALUE) if (of_flags & OF_GPIO_TRANSITORY)
*flags |= GPIO_SLEEP_MAY_LOSE_VALUE; *flags |= GPIO_TRANSITORY;
return desc; return desc;
} }
...@@ -214,6 +327,8 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, ...@@ -214,6 +327,8 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
if (xlate_flags & OF_GPIO_ACTIVE_LOW) if (xlate_flags & OF_GPIO_ACTIVE_LOW)
*lflags |= GPIO_ACTIVE_LOW; *lflags |= GPIO_ACTIVE_LOW;
if (xlate_flags & OF_GPIO_TRANSITORY)
*lflags |= GPIO_TRANSITORY;
if (of_property_read_bool(np, "input")) if (of_property_read_bool(np, "input"))
*dflags |= GPIOD_IN; *dflags |= GPIOD_IN;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ctype.h>
#include "gpiolib.h" #include "gpiolib.h"
...@@ -106,8 +107,14 @@ static ssize_t value_show(struct device *dev, ...@@ -106,8 +107,14 @@ static ssize_t value_show(struct device *dev,
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc)); status = gpiod_get_value_cansleep(desc);
if (status < 0)
goto err;
buf[0] = '0' + status;
buf[1] = '\n';
status = 2;
err:
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
return status; return status;
...@@ -118,7 +125,7 @@ static ssize_t value_store(struct device *dev, ...@@ -118,7 +125,7 @@ static ssize_t value_store(struct device *dev,
{ {
struct gpiod_data *data = dev_get_drvdata(dev); struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc; struct gpio_desc *desc = data->desc;
ssize_t status; ssize_t status = 0;
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
...@@ -127,6 +134,10 @@ static ssize_t value_store(struct device *dev, ...@@ -127,6 +134,10 @@ static ssize_t value_store(struct device *dev,
} else { } else {
long value; long value;
if (size <= 2 && isdigit(buf[0]) &&
(size == 1 || buf[1] == '\n'))
value = buf[0] - '0';
else
status = kstrtol(buf, 0, &value); status = kstrtol(buf, 0, &value);
if (status == 0) { if (status == 0) {
gpiod_set_value_cansleep(desc, value); gpiod_set_value_cansleep(desc, value);
...@@ -138,7 +149,7 @@ static ssize_t value_store(struct device *dev, ...@@ -138,7 +149,7 @@ static ssize_t value_store(struct device *dev,
return status; return status;
} }
static DEVICE_ATTR_RW(value); static DEVICE_ATTR_PREALLOC(value, S_IWUSR | S_IRUGO, value_show, value_store);
static irqreturn_t gpio_sysfs_irq(int irq, void *priv) static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
{ {
...@@ -474,11 +485,15 @@ static ssize_t export_store(struct class *class, ...@@ -474,11 +485,15 @@ static ssize_t export_store(struct class *class,
status = -ENODEV; status = -ENODEV;
goto done; goto done;
} }
status = gpiod_set_transitory(desc, false);
if (!status) {
status = gpiod_export(desc, true); status = gpiod_export(desc, true);
if (status < 0) if (status < 0)
gpiod_free(desc); gpiod_free(desc);
else else
set_bit(FLAG_SYSFS, &desc->flags); set_bit(FLAG_SYSFS, &desc->flags);
}
done: done:
if (status) if (status)
......
This diff is collapsed.
...@@ -58,7 +58,7 @@ struct gpio_device { ...@@ -58,7 +58,7 @@ struct gpio_device {
struct gpio_desc *descs; struct gpio_desc *descs;
int base; int base;
u16 ngpio; u16 ngpio;
char *label; const char *label;
void *data; void *data;
struct list_head list; struct list_head list;
...@@ -75,16 +75,20 @@ struct gpio_device { ...@@ -75,16 +75,20 @@ struct gpio_device {
/** /**
* struct acpi_gpio_info - ACPI GPIO specific information * struct acpi_gpio_info - ACPI GPIO specific information
* @adev: reference to ACPI device which consumes GPIO resource
* @flags: GPIO initialization flags * @flags: GPIO initialization flags
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @polarity: interrupt polarity as provided by ACPI * @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI * @triggering: triggering type as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/ */
struct acpi_gpio_info { struct acpi_gpio_info {
struct acpi_device *adev;
enum gpiod_flags flags; enum gpiod_flags flags;
bool gpioint; bool gpioint;
int polarity; int polarity;
int triggering; int triggering;
unsigned int quirks;
}; };
/* gpio suffixes used for ACPI and device tree lookup */ /* gpio suffixes used for ACPI and device tree lookup */
...@@ -124,7 +128,7 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); ...@@ -124,7 +128,7 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
enum gpiod_flags update); struct acpi_gpio_info *info);
struct gpio_desc *acpi_find_gpio(struct device *dev, struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id, const char *con_id,
...@@ -149,7 +153,7 @@ static inline void ...@@ -149,7 +153,7 @@ static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline int static inline int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update) acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
{ {
return 0; return 0;
} }
...@@ -189,6 +193,12 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep, ...@@ -189,6 +193,12 @@ void gpiod_set_array_value_complex(bool raw, bool can_sleep,
struct gpio_desc **desc_array, struct gpio_desc **desc_array,
int *value_array); int *value_array);
/* This is just passed between gpiolib and devres */
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label);
extern struct spinlock gpio_lock; extern struct spinlock gpio_lock;
extern struct list_head gpio_devices; extern struct list_head gpio_devices;
...@@ -205,7 +215,7 @@ struct gpio_desc { ...@@ -205,7 +215,7 @@ struct gpio_desc {
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ #define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */ #define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */ #define FLAG_IS_HOGGED 11 /* GPIO is hogged */
#define FLAG_SLEEP_MAY_LOSE_VALUE 12 /* GPIO may lose value in sleep */ #define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */
/* Connection label */ /* Connection label */
const char *label; const char *label;
......
...@@ -63,6 +63,16 @@ config PINCTRL_AS3722 ...@@ -63,6 +63,16 @@ config PINCTRL_AS3722
open drain configuration for the GPIO pins of AS3722 devices. It also open drain configuration for the GPIO pins of AS3722 devices. It also
supports the GPIO functionality through gpiolib. supports the GPIO functionality through gpiolib.
config PINCTRL_AXP209
tristate "X-Powers AXP209 PMIC pinctrl and GPIO Support"
depends on MFD_AXP20X
help
AXP PMICs provides multiple GPIOs that can be muxed for different
functions. This driver bundles a pinctrl driver to select the function
muxing and a GPIO driver to handle the GPIO when the GPIO function is
selected.
Say yes to enable pinctrl and GPIO support for the AXP209 PMIC
config PINCTRL_BF54x config PINCTRL_BF54x
def_bool y if BF54x def_bool y if BF54x
select PINCTRL_ADI2 select PINCTRL_ADI2
......
...@@ -11,6 +11,7 @@ obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o ...@@ -11,6 +11,7 @@ obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o
obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
......
This diff is collapsed.
...@@ -13,9 +13,8 @@ ...@@ -13,9 +13,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/w1-gpio.h> #include <linux/w1-gpio.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -30,11 +29,17 @@ static u8 w1_gpio_set_pullup(void *data, int delay) ...@@ -30,11 +29,17 @@ static u8 w1_gpio_set_pullup(void *data, int delay)
pdata->pullup_duration = delay; pdata->pullup_duration = delay;
} else { } else {
if (pdata->pullup_duration) { if (pdata->pullup_duration) {
gpio_direction_output(pdata->pin, 1); /*
* This will OVERRIDE open drain emulation and force-pull
* the line high for some time.
*/
gpiod_set_raw_value(pdata->gpiod, 1);
msleep(pdata->pullup_duration); msleep(pdata->pullup_duration);
/*
gpio_direction_input(pdata->pin); * This will simply set the line as input since we are doing
* open drain emulation in the GPIO library.
*/
gpiod_set_value(pdata->gpiod, 1);
} }
pdata->pullup_duration = 0; pdata->pullup_duration = 0;
} }
...@@ -42,28 +47,18 @@ static u8 w1_gpio_set_pullup(void *data, int delay) ...@@ -42,28 +47,18 @@ static u8 w1_gpio_set_pullup(void *data, int delay)
return 0; return 0;
} }
static void w1_gpio_write_bit_dir(void *data, u8 bit) static void w1_gpio_write_bit(void *data, u8 bit)
{ {
struct w1_gpio_platform_data *pdata = data; struct w1_gpio_platform_data *pdata = data;
if (bit) gpiod_set_value(pdata->gpiod, bit);
gpio_direction_input(pdata->pin);
else
gpio_direction_output(pdata->pin, 0);
}
static void w1_gpio_write_bit_val(void *data, u8 bit)
{
struct w1_gpio_platform_data *pdata = data;
gpio_set_value(pdata->pin, bit);
} }
static u8 w1_gpio_read_bit(void *data) static u8 w1_gpio_read_bit(void *data)
{ {
struct w1_gpio_platform_data *pdata = data; struct w1_gpio_platform_data *pdata = data;
return gpio_get_value(pdata->pin) ? 1 : 0; return gpiod_get_value(pdata->gpiod) ? 1 : 0;
} }
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
...@@ -74,107 +69,85 @@ static const struct of_device_id w1_gpio_dt_ids[] = { ...@@ -74,107 +69,85 @@ static const struct of_device_id w1_gpio_dt_ids[] = {
MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
#endif #endif
static int w1_gpio_probe_dt(struct platform_device *pdev) static int w1_gpio_probe(struct platform_device *pdev)
{ {
struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); struct w1_bus_master *master;
struct device_node *np = pdev->dev.of_node; struct w1_gpio_platform_data *pdata;
int gpio; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
/* Enforce open drain mode by default */
enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
int err;
if (of_have_populated_dt()) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
/*
* This parameter means that something else than the gpiolib has
* already set the line into open drain mode, so we should just
* driver it high/low like we are in full control of the line and
* open drain will happen transparently.
*/
if (of_get_property(np, "linux,open-drain", NULL)) if (of_get_property(np, "linux,open-drain", NULL))
pdata->is_open_drain = 1; gflags = GPIOD_OUT_LOW;
gpio = of_get_gpio(np, 0);
if (gpio < 0) {
if (gpio != -EPROBE_DEFER)
dev_err(&pdev->dev,
"Failed to parse gpio property for data pin (%d)\n",
gpio);
return gpio;
}
pdata->pin = gpio;
gpio = of_get_gpio(np, 1);
if (gpio == -EPROBE_DEFER)
return gpio;
/* ignore other errors as the pullup gpio is optional */
pdata->ext_pullup_enable_pin = gpio;
pdev->dev.platform_data = pdata; pdev->dev.platform_data = pdata;
return 0;
}
static int w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata;
int err;
if (of_have_populated_dt()) {
err = w1_gpio_probe_dt(pdev);
if (err < 0)
return err;
} }
pdata = dev_get_platdata(dev);
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) { if (!pdata) {
dev_err(&pdev->dev, "No configuration data\n"); dev_err(dev, "No configuration data\n");
return -ENXIO; return -ENXIO;
} }
master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master), master = devm_kzalloc(dev, sizeof(struct w1_bus_master),
GFP_KERNEL); GFP_KERNEL);
if (!master) { if (!master) {
dev_err(&pdev->dev, "Out of memory\n"); dev_err(dev, "Out of memory\n");
return -ENOMEM; return -ENOMEM;
} }
err = devm_gpio_request(&pdev->dev, pdata->pin, "w1"); pdata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags);
if (err) { if (IS_ERR(pdata->gpiod)) {
dev_err(&pdev->dev, "gpio_request (pin) failed\n"); dev_err(dev, "gpio_request (pin) failed\n");
return err; return PTR_ERR(pdata->gpiod);
} }
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) { pdata->pullup_gpiod =
err = devm_gpio_request_one(&pdev->dev, devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_LOW);
pdata->ext_pullup_enable_pin, GPIOF_INIT_LOW, if (IS_ERR(pdata->pullup_gpiod)) {
"w1 pullup"); dev_err(dev, "gpio_request_one "
if (err < 0) {
dev_err(&pdev->dev, "gpio_request_one "
"(ext_pullup_enable_pin) failed\n"); "(ext_pullup_enable_pin) failed\n");
return err; return PTR_ERR(pdata->pullup_gpiod);
}
} }
master->data = pdata; master->data = pdata;
master->read_bit = w1_gpio_read_bit; master->read_bit = w1_gpio_read_bit;
gpiod_direction_output(pdata->gpiod, 1);
if (pdata->is_open_drain) { master->write_bit = w1_gpio_write_bit;
gpio_direction_output(pdata->pin, 1);
master->write_bit = w1_gpio_write_bit_val; /*
} else { * If we are using open drain emulation from the GPIO library,
gpio_direction_input(pdata->pin); * we need to use this pullup function that hammers the line
master->write_bit = w1_gpio_write_bit_dir; * high using a raw accessor to provide pull-up for the w1
* line.
*/
if (gflags == GPIOD_OUT_LOW_OPEN_DRAIN)
master->set_pullup = w1_gpio_set_pullup; master->set_pullup = w1_gpio_set_pullup;
}
err = w1_add_master_device(master); err = w1_add_master_device(master);
if (err) { if (err) {
dev_err(&pdev->dev, "w1_add_master device failed\n"); dev_err(dev, "w1_add_master device failed\n");
return err; return err;
} }
if (pdata->enable_external_pullup) if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1); pdata->enable_external_pullup(1);
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) if (pdata->pullup_gpiod)
gpio_set_value(pdata->ext_pullup_enable_pin, 1); gpiod_set_value(pdata->pullup_gpiod, 1);
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
...@@ -189,8 +162,8 @@ static int w1_gpio_remove(struct platform_device *pdev) ...@@ -189,8 +162,8 @@ static int w1_gpio_remove(struct platform_device *pdev)
if (pdata->enable_external_pullup) if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0); pdata->enable_external_pullup(0);
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) if (pdata->pullup_gpiod)
gpio_set_value(pdata->ext_pullup_enable_pin, 0); gpiod_set_value(pdata->pullup_gpiod, 0);
w1_remove_master_device(master); w1_remove_master_device(master);
......
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) #define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) #define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE)
/* Bit 3 express GPIO suspend/resume persistence */ /* Bit 3 express GPIO suspend/resume and reset persistence */
#define GPIO_SLEEP_MAINTAIN_VALUE 0 #define GPIO_PERSISTENT 0
#define GPIO_SLEEP_MAY_LOSE_VALUE 8 #define GPIO_TRANSITORY 8
#endif #endif
...@@ -991,6 +991,11 @@ struct acpi_gpio_mapping { ...@@ -991,6 +991,11 @@ struct acpi_gpio_mapping {
const char *name; const char *name;
const struct acpi_gpio_params *data; const struct acpi_gpio_params *data;
unsigned int size; unsigned int size;
/* Ignore IoRestriction field */
#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0)
unsigned int quirks;
}; };
#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) #if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
......
...@@ -575,6 +575,9 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, ...@@ -575,6 +575,9 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
#define DEVICE_ATTR(_name, _mode, _show, _store) \ #define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DEVICE_ATTR_PREALLOC(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = \
__ATTR_PREALLOC(_name, _mode, _show, _store)
#define DEVICE_ATTR_RW(_name) \ #define DEVICE_ATTR_RW(_name) \
struct device_attribute dev_attr_##_name = __ATTR_RW(_name) struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
#define DEVICE_ATTR_RO(_name) \ #define DEVICE_ATTR_RO(_name) \
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/*
* <linux/gpio.h>
*
* This is the LEGACY GPIO bulk include file, including legacy APIs. It is
* used for GPIO drivers still referencing the global GPIO numberspace,
* and should not be included in new code.
*
* If you're implementing a GPIO driver, only include <linux/gpio/driver.h>
* If you're implementing a GPIO consumer, only include <linux/gpio/consumer.h>
*/
#ifndef __LINUX_GPIO_H #ifndef __LINUX_GPIO_H
#define __LINUX_GPIO_H #define __LINUX_GPIO_H
......
...@@ -139,6 +139,7 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size, ...@@ -139,6 +139,7 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
int *value_array); int *value_array);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
int gpiod_is_active_low(const struct gpio_desc *desc); int gpiod_is_active_low(const struct gpio_desc *desc);
int gpiod_cansleep(const struct gpio_desc *desc); int gpiod_cansleep(const struct gpio_desc *desc);
...@@ -150,8 +151,14 @@ struct gpio_desc *gpio_to_desc(unsigned gpio); ...@@ -150,8 +151,14 @@ struct gpio_desc *gpio_to_desc(unsigned gpio);
int desc_to_gpio(const struct gpio_desc *desc); int desc_to_gpio(const struct gpio_desc *desc);
/* Child properties interface */ /* Child properties interface */
struct device_node;
struct fwnode_handle; struct fwnode_handle;
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label);
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
...@@ -431,6 +438,13 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) ...@@ -431,6 +438,13 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
return -ENOSYS; return -ENOSYS;
} }
static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
{
/* GPIO can never have been requested */
WARN_ON(1);
return -ENOSYS;
}
static inline int gpiod_is_active_low(const struct gpio_desc *desc) static inline int gpiod_is_active_low(const struct gpio_desc *desc)
{ {
/* GPIO can never have been requested */ /* GPIO can never have been requested */
...@@ -464,8 +478,19 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) ...@@ -464,8 +478,19 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
} }
/* Child properties interface */ /* Child properties interface */
struct device_node;
struct fwnode_handle; struct fwnode_handle;
static inline
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
{
return ERR_PTR(-ENOSYS);
}
static inline static inline
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index, const char *propname, int index,
......
...@@ -436,6 +436,9 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, ...@@ -436,6 +436,9 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
struct lock_class_key *lock_key, struct lock_class_key *lock_key,
struct lock_class_key *request_key); struct lock_class_key *request_key);
bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
unsigned int offset);
#ifdef CONFIG_LOCKDEP #ifdef CONFIG_LOCKDEP
/* /*
......
...@@ -10,8 +10,8 @@ enum gpio_lookup_flags { ...@@ -10,8 +10,8 @@ enum gpio_lookup_flags {
GPIO_ACTIVE_LOW = (1 << 0), GPIO_ACTIVE_LOW = (1 << 0),
GPIO_OPEN_DRAIN = (1 << 1), GPIO_OPEN_DRAIN = (1 << 1),
GPIO_OPEN_SOURCE = (1 << 2), GPIO_OPEN_SOURCE = (1 << 2),
GPIO_SLEEP_MAINTAIN_VALUE = (0 << 3), GPIO_PERSISTENT = (0 << 3),
GPIO_SLEEP_MAY_LOSE_VALUE = (1 << 3), GPIO_TRANSITORY = (1 << 3),
}; };
/** /**
......
...@@ -31,7 +31,7 @@ enum of_gpio_flags { ...@@ -31,7 +31,7 @@ enum of_gpio_flags {
OF_GPIO_ACTIVE_LOW = 0x1, OF_GPIO_ACTIVE_LOW = 0x1,
OF_GPIO_SINGLE_ENDED = 0x2, OF_GPIO_SINGLE_ENDED = 0x2,
OF_GPIO_OPEN_DRAIN = 0x4, OF_GPIO_OPEN_DRAIN = 0x4,
OF_GPIO_SLEEP_MAY_LOSE_VALUE = 0x8, OF_GPIO_TRANSITORY = 0x8,
}; };
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
......
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
* or latch delay (on outputs) this parameter (in a custom format) * or latch delay (on outputs) this parameter (in a custom format)
* specifies the clock skew or latch delay. It typically controls how * specifies the clock skew or latch delay. It typically controls how
* many double inverters are put in front of the line. * many double inverters are put in front of the line.
* @PIN_CONFIG_PERSIST_STATE: retain pin state across sleep or controller reset
* @PIN_CONFIG_END: this is the last enumerator for pin configurations, if * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
* you need to pass in custom configurations to the pin controller, use * you need to pass in custom configurations to the pin controller, use
* PIN_CONFIG_END+1 as the base offset. * PIN_CONFIG_END+1 as the base offset.
...@@ -122,6 +123,7 @@ enum pin_config_param { ...@@ -122,6 +123,7 @@ enum pin_config_param {
PIN_CONFIG_SLEEP_HARDWARE_STATE, PIN_CONFIG_SLEEP_HARDWARE_STATE,
PIN_CONFIG_SLEW_RATE, PIN_CONFIG_SLEW_RATE,
PIN_CONFIG_SKEW_DELAY, PIN_CONFIG_SKEW_DELAY,
PIN_CONFIG_PERSIST_STATE,
PIN_CONFIG_END = 0x7F, PIN_CONFIG_END = 0x7F,
PIN_CONFIG_MAX = 0xFF, PIN_CONFIG_MAX = 0xFF,
}; };
......
...@@ -10,16 +10,15 @@ ...@@ -10,16 +10,15 @@
#ifndef _LINUX_W1_GPIO_H #ifndef _LINUX_W1_GPIO_H
#define _LINUX_W1_GPIO_H #define _LINUX_W1_GPIO_H
struct gpio_desc;
/** /**
* struct w1_gpio_platform_data - Platform-dependent data for w1-gpio * struct w1_gpio_platform_data - Platform-dependent data for w1-gpio
* @pin: GPIO pin to use
* @is_open_drain: GPIO pin is configured as open drain
*/ */
struct w1_gpio_platform_data { struct w1_gpio_platform_data {
unsigned int pin; struct gpio_desc *gpiod;
unsigned int is_open_drain:1; struct gpio_desc *pullup_gpiod;
void (*enable_external_pullup)(int enable); void (*enable_external_pullup)(int enable);
unsigned int ext_pullup_enable_pin;
unsigned int pullup_duration; unsigned int pullup_duration;
}; };
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
...@@ -23,12 +24,13 @@ ...@@ -23,12 +24,13 @@
#include <getopt.h> #include <getopt.h>
#include <inttypes.h> #include <inttypes.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/gpio.h> #include <linux/gpio.h>
int monitor_device(const char *device_name, int monitor_device(const char *device_name,
unsigned int line, unsigned int line,
u_int32_t handleflags, uint32_t handleflags,
u_int32_t eventflags, uint32_t eventflags,
unsigned int loops) unsigned int loops)
{ {
struct gpioevent_request req; struct gpioevent_request req;
...@@ -145,8 +147,8 @@ int main(int argc, char **argv) ...@@ -145,8 +147,8 @@ int main(int argc, char **argv)
const char *device_name = NULL; const char *device_name = NULL;
unsigned int line = -1; unsigned int line = -1;
unsigned int loops = 0; unsigned int loops = 0;
u_int32_t handleflags = GPIOHANDLE_REQUEST_INPUT; uint32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
u_int32_t eventflags = 0; uint32_t eventflags = 0;
int c; int c;
while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) { while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment