diff options
66 files changed, 2207 insertions, 230 deletions
diff --git a/Documentation/devicetree/bindings/gpio/cirrus,clps711x-mctrl-gpio.txt b/Documentation/devicetree/bindings/gpio/cirrus,clps711x-mctrl-gpio.txt index 94ae9f82dcf8..fd42e7280f72 100644 --- a/Documentation/devicetree/bindings/gpio/cirrus,clps711x-mctrl-gpio.txt +++ b/Documentation/devicetree/bindings/gpio/cirrus,clps711x-mctrl-gpio.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | * ARM Cirrus Logic CLPS711X SYSFLG1 MCTRL GPIOs | 1 | * ARM Cirrus Logic CLPS711X SYSFLG1 MCTRL GPIOs |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should contain "cirrus,clps711x-mctrl-gpio". | 4 | - compatible: Should contain "cirrus,ep7209-mctrl-gpio". |
| 5 | - gpio-controller: Marks the device node as a gpio controller. | 5 | - gpio-controller: Marks the device node as a gpio controller. |
| 6 | - #gpio-cells: Should be two. The first cell is the pin number and | 6 | - #gpio-cells: Should be two. The first cell is the pin number and |
| 7 | the second cell is used to specify the gpio polarity: | 7 | the second cell is used to specify the gpio polarity: |
| @@ -11,7 +11,7 @@ Required properties: | |||
| 11 | Example: | 11 | Example: |
| 12 | sysgpio: sysgpio { | 12 | sysgpio: sysgpio { |
| 13 | compatible = "cirrus,ep7312-mctrl-gpio", | 13 | compatible = "cirrus,ep7312-mctrl-gpio", |
| 14 | "cirrus,clps711x-mctrl-gpio"; | 14 | "cirrus,ep7209-mctrl-gpio"; |
| 15 | gpio-controller; | 15 | gpio-controller; |
| 16 | #gpio-cells = <2>; | 16 | #gpio-cells = <2>; |
| 17 | }; | 17 | }; |
diff --git a/Documentation/devicetree/bindings/gpio/gpio-clps711x.txt b/Documentation/devicetree/bindings/gpio/gpio-clps711x.txt index e0d0446a6b78..0a304ad29d81 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-clps711x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-clps711x.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | Cirrus Logic CLPS711X GPIO controller | 1 | Cirrus Logic CLPS711X GPIO controller |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should be "cirrus,clps711x-gpio" | 4 | - compatible: Should be "cirrus,ep7209-gpio" |
| 5 | - reg: Physical base GPIO controller registers location and length. | 5 | - reg: Physical base GPIO controller registers location and length. |
| 6 | There should be two registers, first is DATA register, the second | 6 | There should be two registers, first is DATA register, the second |
| 7 | is DIRECTION. | 7 | is DIRECTION. |
| @@ -21,7 +21,7 @@ aliases { | |||
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | porta: gpio@80000000 { | 23 | porta: gpio@80000000 { |
| 24 | compatible = "cirrus,clps711x-gpio"; | 24 | compatible = "cirrus,ep7312-gpio","cirrus,ep7209-gpio"; |
| 25 | reg = <0x80000000 0x1>, <0x80000040 0x1>; | 25 | reg = <0x80000000 0x1>, <0x80000040 0x1>; |
| 26 | gpio-controller; | 26 | gpio-controller; |
| 27 | #gpio-cells = <2>; | 27 | #gpio-cells = <2>; |
diff --git a/Documentation/devicetree/bindings/gpio/gpio-max77620.txt b/Documentation/devicetree/bindings/gpio/gpio-max77620.txt new file mode 100644 index 000000000000..410e716fd3d2 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-max77620.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | GPIO driver for MAX77620 Power management IC from Maxim Semiconductor. | ||
| 2 | |||
| 3 | Device has 8 GPIO pins which can be configured as GPIO as well as the | ||
| 4 | special IO functions. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | ------------------- | ||
| 8 | - gpio-controller : Marks the device node as a gpio controller. | ||
| 9 | - #gpio-cells : Should be two. The first cell is the pin number and | ||
| 10 | the second cell is used to specify the gpio polarity: | ||
| 11 | 0 = active high | ||
| 12 | 1 = active low | ||
| 13 | For more details, please refer generic GPIO DT binding document | ||
| 14 | <devicetree/bindings/gpio/gpio.txt>. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | -------- | ||
| 18 | #include <dt-bindings/mfd/max77620.h> | ||
| 19 | ... | ||
| 20 | max77620@3c { | ||
| 21 | compatible = "maxim,max77620"; | ||
| 22 | |||
| 23 | gpio-controller; | ||
| 24 | #gpio-cells = <2>; | ||
| 25 | }; | ||
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index 6b4a98f74be3..08dd15f89ba9 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | |||
| @@ -21,6 +21,7 @@ Required properties: | |||
| 21 | maxim,max7313 | 21 | maxim,max7313 |
| 22 | maxim,max7315 | 22 | maxim,max7315 |
| 23 | ti,pca6107 | 23 | ti,pca6107 |
| 24 | ti,pca9536 | ||
| 24 | ti,tca6408 | 25 | ti,tca6408 |
| 25 | ti,tca6416 | 26 | ti,tca6416 |
| 26 | ti,tca6424 | 27 | ti,tca6424 |
diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt index f60e2f477e93..8da26b35b5c3 100644 --- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt | |||
| @@ -7,6 +7,7 @@ Required Properties: | |||
| 7 | - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. | 7 | - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. |
| 8 | - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. | 8 | - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. |
| 9 | - "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller. | 9 | - "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller. |
| 10 | - "renesas,gpio-r8a7792": for R8A7792 (R-Car V2H) compatible GPIO controller. | ||
| 10 | - "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller. | 11 | - "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller. |
| 11 | - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller. | 12 | - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller. |
| 12 | - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller. | 13 | - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller. |
diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/gpio/drivers-on-gpio.txt index 14bf95a13bae..306513251713 100644 --- a/Documentation/gpio/drivers-on-gpio.txt +++ b/Documentation/gpio/drivers-on-gpio.txt | |||
| @@ -37,15 +37,16 @@ hardware descriptions such as device tree or ACPI: | |||
| 37 | external connector status, such as a headset line for an audio driver or an | 37 | external connector status, such as a headset line for an audio driver or an |
| 38 | HDMI connector. It will provide a better userspace sysfs interface than GPIO. | 38 | HDMI connector. It will provide a better userspace sysfs interface than GPIO. |
| 39 | 39 | ||
| 40 | - restart-gpio: drivers/power/gpio-restart.c is used to restart/reboot the | 40 | - restart-gpio: drivers/power/reset/gpio-restart.c is used to restart/reboot |
| 41 | system by pulling a GPIO line and will register a restart handler so | 41 | the system by pulling a GPIO line and will register a restart handler so |
| 42 | userspace can issue the right system call to restart the system. | 42 | userspace can issue the right system call to restart the system. |
| 43 | 43 | ||
| 44 | - poweroff-gpio: drivers/power/gpio-poweroff.c is used to power the system down | 44 | - poweroff-gpio: drivers/power/reset/gpio-poweroff.c is used to power the |
| 45 | by pulling a GPIO line and will register a pm_power_off() callback so that | 45 | system down by pulling a GPIO line and will register a pm_power_off() |
| 46 | userspace can issue the right system call to power down the system. | 46 | callback so that userspace can issue the right system call to power down the |
| 47 | system. | ||
| 47 | 48 | ||
| 48 | - gpio-gate-clock: drivers/clk/clk-gpio-gate.c is used to control a gated clock | 49 | - gpio-gate-clock: drivers/clk/clk-gpio.c is used to control a gated clock |
| 49 | (off/on) that uses a GPIO, and integrated with the clock subsystem. | 50 | (off/on) that uses a GPIO, and integrated with the clock subsystem. |
| 50 | 51 | ||
| 51 | - i2c-gpio: drivers/i2c/busses/i2c-gpio.c is used to drive an I2C bus | 52 | - i2c-gpio: drivers/i2c/busses/i2c-gpio.c is used to drive an I2C bus |
diff --git a/MAINTAINERS b/MAINTAINERS index 0a3827b722b0..f4698b1cf847 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -6060,6 +6060,12 @@ L: linux-rdma@vger.kernel.org | |||
| 6060 | S: Supported | 6060 | S: Supported |
| 6061 | F: drivers/infiniband/hw/i40iw/ | 6061 | F: drivers/infiniband/hw/i40iw/ |
| 6062 | 6062 | ||
| 6063 | INTEL MERRIFIELD GPIO DRIVER | ||
| 6064 | M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
| 6065 | L: linux-gpio@vger.kernel.org | ||
| 6066 | S: Maintained | ||
| 6067 | F: drivers/gpio/gpio-merrifield.c | ||
| 6068 | |||
| 6063 | INTEL-MID GPIO DRIVER | 6069 | INTEL-MID GPIO DRIVER |
| 6064 | M: David Cohen <david.a.cohen@linux.intel.com> | 6070 | M: David Cohen <david.a.cohen@linux.intel.com> |
| 6065 | L: linux-gpio@vger.kernel.org | 6071 | L: linux-gpio@vger.kernel.org |
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 57298e7b4867..1941e4baaee6 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig | |||
| @@ -8,8 +8,7 @@ config HEXAGON | |||
| 8 | # select HAVE_REGS_AND_STACK_ACCESS_API | 8 | # select HAVE_REGS_AND_STACK_ACCESS_API |
| 9 | # select HAVE_HW_BREAKPOINT if PERF_EVENTS | 9 | # select HAVE_HW_BREAKPOINT if PERF_EVENTS |
| 10 | # select ARCH_HAS_CPU_IDLE_WAIT | 10 | # select ARCH_HAS_CPU_IDLE_WAIT |
| 11 | # select ARCH_WANT_OPTIONAL_GPIOLIB | 11 | # select GPIOLIB |
| 12 | # select ARCH_REQUIRE_GPIOLIB | ||
| 13 | # select HAVE_CLK | 12 | # select HAVE_CLK |
| 14 | # select GENERIC_PENDING_IRQ if SMP | 13 | # select GENERIC_PENDING_IRQ if SMP |
| 15 | select GENERIC_ATOMIC64 | 14 | select GENERIC_ATOMIC64 |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index e109ee95e919..6a15083cc366 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
| @@ -39,7 +39,6 @@ config IA64 | |||
| 39 | select GENERIC_PENDING_IRQ if SMP | 39 | select GENERIC_PENDING_IRQ if SMP |
| 40 | select GENERIC_IRQ_SHOW | 40 | select GENERIC_IRQ_SHOW |
| 41 | select GENERIC_IRQ_LEGACY | 41 | select GENERIC_IRQ_LEGACY |
| 42 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 43 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 42 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 44 | select GENERIC_IOMAP | 43 | select GENERIC_IOMAP |
| 45 | select GENERIC_SMP_IDLE_THREAD | 44 | select GENERIC_SMP_IDLE_THREAD |
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 636e0720fb20..86f65721e629 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
| @@ -3,7 +3,6 @@ config MICROBLAZE | |||
| 3 | select ARCH_HAS_GCOV_PROFILE_ALL | 3 | select ARCH_HAS_GCOV_PROFILE_ALL |
| 4 | select ARCH_MIGHT_HAVE_PC_PARPORT | 4 | select ARCH_MIGHT_HAVE_PC_PARPORT |
| 5 | select ARCH_WANT_IPC_PARSE_VERSION | 5 | select ARCH_WANT_IPC_PARSE_VERSION |
| 6 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 7 | select BUILDTIME_EXTABLE_SORT | 6 | select BUILDTIME_EXTABLE_SORT |
| 8 | select CLKSRC_OF | 7 | select CLKSRC_OF |
| 9 | select CLONE_BACKWARDS3 | 8 | select CLONE_BACKWARDS3 |
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 142cb057c41b..489e7f909286 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
| @@ -10,7 +10,7 @@ config OPENRISC | |||
| 10 | select IRQ_DOMAIN | 10 | select IRQ_DOMAIN |
| 11 | select HANDLE_DOMAIN_IRQ | 11 | select HANDLE_DOMAIN_IRQ |
| 12 | select HAVE_MEMBLOCK | 12 | select HAVE_MEMBLOCK |
| 13 | select ARCH_REQUIRE_GPIOLIB | 13 | select GPIOLIB |
| 14 | select HAVE_ARCH_TRACEHOOK | 14 | select HAVE_ARCH_TRACEHOOK |
| 15 | select GENERIC_IRQ_CHIP | 15 | select GENERIC_IRQ_CHIP |
| 16 | select GENERIC_IRQ_PROBE | 16 | select GENERIC_IRQ_PROBE |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 0a9d439bcda6..d111044f41a2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -98,7 +98,6 @@ config PPC | |||
| 98 | select HAVE_FUNCTION_TRACER | 98 | select HAVE_FUNCTION_TRACER |
| 99 | select HAVE_FUNCTION_GRAPH_TRACER | 99 | select HAVE_FUNCTION_GRAPH_TRACER |
| 100 | select SYSCTL_EXCEPTION_TRACE | 100 | select SYSCTL_EXCEPTION_TRACE |
| 101 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 102 | select VIRT_TO_BUS if !PPC64 | 101 | select VIRT_TO_BUS if !PPC64 |
| 103 | select HAVE_IDE | 102 | select HAVE_IDE |
| 104 | select HAVE_IOREMAP_PROT | 103 | select HAVE_IOREMAP_PROT |
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 6e287f1294fa..e3257f24a8a1 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
| @@ -137,7 +137,7 @@ config STB03xxx | |||
| 137 | config PPC4xx_GPIO | 137 | config PPC4xx_GPIO |
| 138 | bool "PPC4xx GPIO support" | 138 | bool "PPC4xx GPIO support" |
| 139 | depends on 40x | 139 | depends on 40x |
| 140 | select ARCH_REQUIRE_GPIOLIB | 140 | select GPIOLIB |
| 141 | help | 141 | help |
| 142 | Enable gpiolib support for ppc40x based boards | 142 | Enable gpiolib support for ppc40x based boards |
| 143 | 143 | ||
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 5538e57c36c1..48fc18041ff6 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
| @@ -273,7 +273,7 @@ config PPC44x_SIMPLE | |||
| 273 | config PPC4xx_GPIO | 273 | config PPC4xx_GPIO |
| 274 | bool "PPC4xx GPIO support" | 274 | bool "PPC4xx GPIO support" |
| 275 | depends on 44x | 275 | depends on 44x |
| 276 | select ARCH_REQUIRE_GPIOLIB | 276 | select GPIOLIB |
| 277 | help | 277 | help |
| 278 | Enable gpiolib support for ppc440 based boards | 278 | Enable gpiolib support for ppc440 based boards |
| 279 | 279 | ||
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig index f09016f6b3a6..bf7ae5cbd07a 100644 --- a/arch/powerpc/platforms/512x/Kconfig +++ b/arch/powerpc/platforms/512x/Kconfig | |||
| @@ -6,7 +6,6 @@ config PPC_MPC512x | |||
| 6 | select IPIC | 6 | select IPIC |
| 7 | select PPC_PCI_CHOICE | 7 | select PPC_PCI_CHOICE |
| 8 | select FSL_PCI if PCI | 8 | select FSL_PCI if PCI |
| 9 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 10 | select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD | 9 | select USB_EHCI_BIG_ENDIAN_MMIO if USB_EHCI_HCD |
| 11 | select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD | 10 | select USB_EHCI_BIG_ENDIAN_DESC if USB_EHCI_HCD |
| 12 | 11 | ||
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 2bdc8c862c46..4ef7f1cd05b7 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
| @@ -116,7 +116,6 @@ endif | |||
| 116 | # used for usb & gpio | 116 | # used for usb & gpio |
| 117 | config PPC_MPC831x | 117 | config PPC_MPC831x |
| 118 | bool | 118 | bool |
| 119 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 120 | 119 | ||
| 121 | # used for math-emu | 120 | # used for math-emu |
| 122 | config PPC_MPC832x | 121 | config PPC_MPC832x |
| @@ -125,9 +124,7 @@ config PPC_MPC832x | |||
| 125 | # used for usb & gpio | 124 | # used for usb & gpio |
| 126 | config PPC_MPC834x | 125 | config PPC_MPC834x |
| 127 | bool | 126 | bool |
| 128 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 129 | 127 | ||
| 130 | # used for usb & gpio | 128 | # used for usb & gpio |
| 131 | config PPC_MPC837x | 129 | config PPC_MPC837x |
| 132 | bool | 130 | bool |
| 133 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index e626461a63bd..df25a3ed489d 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
| @@ -225,7 +225,7 @@ config GE_IMP3A | |||
| 225 | select DEFAULT_UIMAGE | 225 | select DEFAULT_UIMAGE |
| 226 | select SWIOTLB | 226 | select SWIOTLB |
| 227 | select MMIO_NVRAM | 227 | select MMIO_NVRAM |
| 228 | select ARCH_REQUIRE_GPIOLIB | 228 | select GPIOLIB |
| 229 | select GE_FPGA | 229 | select GE_FPGA |
| 230 | help | 230 | help |
| 231 | This option enables support for the GE Intelligent Platforms IMP3A | 231 | This option enables support for the GE Intelligent Platforms IMP3A |
| @@ -272,7 +272,7 @@ config CORENET_GENERIC | |||
| 272 | select PPC_E500MC | 272 | select PPC_E500MC |
| 273 | select PHYS_64BIT | 273 | select PHYS_64BIT |
| 274 | select SWIOTLB | 274 | select SWIOTLB |
| 275 | select ARCH_REQUIRE_GPIOLIB | 275 | select GPIOLIB |
| 276 | select GPIO_MPC8XXX | 276 | select GPIO_MPC8XXX |
| 277 | select HAS_RAPIDIO | 277 | select HAS_RAPIDIO |
| 278 | select PPC_EPAPR_HV_PIC | 278 | select PPC_EPAPR_HV_PIC |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 1afd1e4a2dd2..3988f16e46c1 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
| @@ -4,7 +4,6 @@ menuconfig PPC_86xx | |||
| 4 | depends on 6xx | 4 | depends on 6xx |
| 5 | select FSL_SOC | 5 | select FSL_SOC |
| 6 | select ALTIVEC | 6 | select ALTIVEC |
| 7 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 8 | help | 7 | help |
| 9 | The Freescale E600 SoCs have 74xx cores. | 8 | The Freescale E600 SoCs have 74xx cores. |
| 10 | 9 | ||
| @@ -37,7 +36,7 @@ config GEF_PPC9A | |||
| 37 | bool "GE PPC9A" | 36 | bool "GE PPC9A" |
| 38 | select DEFAULT_UIMAGE | 37 | select DEFAULT_UIMAGE |
| 39 | select MMIO_NVRAM | 38 | select MMIO_NVRAM |
| 40 | select ARCH_REQUIRE_GPIOLIB | 39 | select GPIOLIB |
| 41 | select GE_FPGA | 40 | select GE_FPGA |
| 42 | help | 41 | help |
| 43 | This option enables support for the GE PPC9A. | 42 | This option enables support for the GE PPC9A. |
| @@ -46,7 +45,7 @@ config GEF_SBC310 | |||
| 46 | bool "GE SBC310" | 45 | bool "GE SBC310" |
| 47 | select DEFAULT_UIMAGE | 46 | select DEFAULT_UIMAGE |
| 48 | select MMIO_NVRAM | 47 | select MMIO_NVRAM |
| 49 | select ARCH_REQUIRE_GPIOLIB | 48 | select GPIOLIB |
| 50 | select GE_FPGA | 49 | select GE_FPGA |
| 51 | help | 50 | help |
| 52 | This option enables support for the GE SBC310. | 51 | This option enables support for the GE SBC310. |
| @@ -55,7 +54,7 @@ config GEF_SBC610 | |||
| 55 | bool "GE SBC610" | 54 | bool "GE SBC610" |
| 56 | select DEFAULT_UIMAGE | 55 | select DEFAULT_UIMAGE |
| 57 | select MMIO_NVRAM | 56 | select MMIO_NVRAM |
| 58 | select ARCH_REQUIRE_GPIOLIB | 57 | select GPIOLIB |
| 59 | select GE_FPGA | 58 | select GE_FPGA |
| 60 | select HAS_RAPIDIO | 59 | select HAS_RAPIDIO |
| 61 | help | 60 | help |
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 157250426b56..564d99bb2a26 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig | |||
| @@ -109,7 +109,7 @@ config 8xx_COPYBACK | |||
| 109 | 109 | ||
| 110 | config 8xx_GPIO | 110 | config 8xx_GPIO |
| 111 | bool "GPIO API Support" | 111 | bool "GPIO API Support" |
| 112 | select ARCH_REQUIRE_GPIOLIB | 112 | select GPIOLIB |
| 113 | help | 113 | help |
| 114 | Saying Y here will cause the ports on an MPC8xx processor to be used | 114 | Saying Y here will cause the ports on an MPC8xx processor to be used |
| 115 | with the GPIO API. If you say N here, the kernel needs less memory. | 115 | with the GPIO API. If you say N here, the kernel needs less memory. |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 46a3533d3acb..3663f71fd913 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -275,7 +275,7 @@ config TAU_AVERAGE | |||
| 275 | config QE_GPIO | 275 | config QE_GPIO |
| 276 | bool "QE GPIO support" | 276 | bool "QE GPIO support" |
| 277 | depends on QUICC_ENGINE | 277 | depends on QUICC_ENGINE |
| 278 | select ARCH_REQUIRE_GPIOLIB | 278 | select GPIOLIB |
| 279 | help | 279 | help |
| 280 | Say Y here if you're going to use hardware that connects to the | 280 | Say Y here if you're going to use hardware that connects to the |
| 281 | QE GPIOs. | 281 | QE GPIOs. |
| @@ -285,7 +285,7 @@ config CPM2 | |||
| 285 | depends on (FSL_SOC_BOOKE && PPC32) || 8260 | 285 | depends on (FSL_SOC_BOOKE && PPC32) || 8260 |
| 286 | select CPM | 286 | select CPM |
| 287 | select PPC_PCI_CHOICE | 287 | select PPC_PCI_CHOICE |
| 288 | select ARCH_REQUIRE_GPIOLIB | 288 | select GPIOLIB |
| 289 | help | 289 | help |
| 290 | The CPM2 (Communications Processor Module) is a coprocessor on | 290 | The CPM2 (Communications Processor Module) is a coprocessor on |
| 291 | embedded CPUs made by Freescale. Selecting this option means that | 291 | embedded CPUs made by Freescale. Selecting this option means that |
| @@ -324,7 +324,7 @@ config OF_RTC | |||
| 324 | config SIMPLE_GPIO | 324 | config SIMPLE_GPIO |
| 325 | bool "Support for simple, memory-mapped GPIO controllers" | 325 | bool "Support for simple, memory-mapped GPIO controllers" |
| 326 | depends on PPC | 326 | depends on PPC |
| 327 | select ARCH_REQUIRE_GPIOLIB | 327 | select GPIOLIB |
| 328 | help | 328 | help |
| 329 | Say Y here to support simple, memory-mapped GPIO controllers. | 329 | Say Y here to support simple, memory-mapped GPIO controllers. |
| 330 | These are usually BCSRs used to control board's switches, LEDs, | 330 | These are usually BCSRs used to control board's switches, LEDs, |
| @@ -334,7 +334,7 @@ config SIMPLE_GPIO | |||
| 334 | config MCU_MPC8349EMITX | 334 | config MCU_MPC8349EMITX |
| 335 | bool "MPC8349E-mITX MCU driver" | 335 | bool "MPC8349E-mITX MCU driver" |
| 336 | depends on I2C=y && PPC_83xx | 336 | depends on I2C=y && PPC_83xx |
| 337 | select ARCH_REQUIRE_GPIOLIB | 337 | select GPIOLIB |
| 338 | help | 338 | help |
| 339 | Say Y here to enable soft power-off functionality on the Freescale | 339 | Say Y here to enable soft power-off functionality on the Freescale |
| 340 | boards with the MPC8349E-mITX-compatible MCU chips. This driver will | 340 | boards with the MPC8349E-mITX-compatible MCU chips. This driver will |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index e803a836cb7c..0d5f3a9bb315 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
| @@ -264,7 +264,6 @@ config CPU_SUBTYPE_SH7203 | |||
| 264 | select CPU_HAS_FPU | 264 | select CPU_HAS_FPU |
| 265 | select SYS_SUPPORTS_SH_CMT | 265 | select SYS_SUPPORTS_SH_CMT |
| 266 | select SYS_SUPPORTS_SH_MTU2 | 266 | select SYS_SUPPORTS_SH_MTU2 |
| 267 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 268 | select PINCTRL | 267 | select PINCTRL |
| 269 | 268 | ||
| 270 | config CPU_SUBTYPE_SH7206 | 269 | config CPU_SUBTYPE_SH7206 |
| @@ -353,7 +352,6 @@ config CPU_SUBTYPE_SH7720 | |||
| 353 | select CPU_SH3 | 352 | select CPU_SH3 |
| 354 | select CPU_HAS_DSP | 353 | select CPU_HAS_DSP |
| 355 | select SYS_SUPPORTS_SH_CMT | 354 | select SYS_SUPPORTS_SH_CMT |
| 356 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 357 | select USB_OHCI_SH if USB_OHCI_HCD | 355 | select USB_OHCI_SH if USB_OHCI_HCD |
| 358 | select PINCTRL | 356 | select PINCTRL |
| 359 | help | 357 | help |
| @@ -419,7 +417,6 @@ config CPU_SUBTYPE_SH7723 | |||
| 419 | select ARCH_SHMOBILE | 417 | select ARCH_SHMOBILE |
| 420 | select ARCH_SPARSEMEM_ENABLE | 418 | select ARCH_SPARSEMEM_ENABLE |
| 421 | select SYS_SUPPORTS_SH_CMT | 419 | select SYS_SUPPORTS_SH_CMT |
| 422 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 423 | select PINCTRL | 420 | select PINCTRL |
| 424 | help | 421 | help |
| 425 | Select SH7723 if you have an SH-MobileR2 CPU. | 422 | Select SH7723 if you have an SH-MobileR2 CPU. |
| @@ -431,7 +428,6 @@ config CPU_SUBTYPE_SH7724 | |||
| 431 | select ARCH_SHMOBILE | 428 | select ARCH_SHMOBILE |
| 432 | select ARCH_SPARSEMEM_ENABLE | 429 | select ARCH_SPARSEMEM_ENABLE |
| 433 | select SYS_SUPPORTS_SH_CMT | 430 | select SYS_SUPPORTS_SH_CMT |
| 434 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 435 | select PINCTRL | 431 | select PINCTRL |
| 436 | help | 432 | help |
| 437 | Select SH7724 if you have an SH-MobileR2R CPU. | 433 | Select SH7724 if you have an SH-MobileR2R CPU. |
| @@ -440,7 +436,6 @@ config CPU_SUBTYPE_SH7734 | |||
| 440 | bool "Support SH7734 processor" | 436 | bool "Support SH7734 processor" |
| 441 | select CPU_SH4A | 437 | select CPU_SH4A |
| 442 | select CPU_SHX2 | 438 | select CPU_SHX2 |
| 443 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 444 | select PINCTRL | 439 | select PINCTRL |
| 445 | help | 440 | help |
| 446 | Select SH7734 if you have a SH4A SH7734 CPU. | 441 | Select SH7734 if you have a SH4A SH7734 CPU. |
| @@ -449,7 +444,6 @@ config CPU_SUBTYPE_SH7757 | |||
| 449 | bool "Support SH7757 processor" | 444 | bool "Support SH7757 processor" |
| 450 | select CPU_SH4A | 445 | select CPU_SH4A |
| 451 | select CPU_SHX2 | 446 | select CPU_SHX2 |
| 452 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 453 | select PINCTRL | 447 | select PINCTRL |
| 454 | help | 448 | help |
| 455 | Select SH7757 if you have a SH4A SH7757 CPU. | 449 | Select SH7757 if you have a SH4A SH7757 CPU. |
| @@ -475,7 +469,6 @@ config CPU_SUBTYPE_SH7785 | |||
| 475 | select CPU_SHX2 | 469 | select CPU_SHX2 |
| 476 | select ARCH_SPARSEMEM_ENABLE | 470 | select ARCH_SPARSEMEM_ENABLE |
| 477 | select SYS_SUPPORTS_NUMA | 471 | select SYS_SUPPORTS_NUMA |
| 478 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 479 | select PINCTRL | 472 | select PINCTRL |
| 480 | 473 | ||
| 481 | config CPU_SUBTYPE_SH7786 | 474 | config CPU_SUBTYPE_SH7786 |
| @@ -484,7 +477,6 @@ config CPU_SUBTYPE_SH7786 | |||
| 484 | select CPU_SHX3 | 477 | select CPU_SHX3 |
| 485 | select CPU_HAS_PTEAEX | 478 | select CPU_HAS_PTEAEX |
| 486 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP | 479 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP |
| 487 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 488 | select USB_OHCI_SH if USB_OHCI_HCD | 480 | select USB_OHCI_SH if USB_OHCI_HCD |
| 489 | select USB_EHCI_SH if USB_EHCI_HCD | 481 | select USB_EHCI_SH if USB_EHCI_HCD |
| 490 | select PINCTRL | 482 | select PINCTRL |
| @@ -494,7 +486,7 @@ config CPU_SUBTYPE_SHX3 | |||
| 494 | select CPU_SH4A | 486 | select CPU_SH4A |
| 495 | select CPU_SHX3 | 487 | select CPU_SHX3 |
| 496 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP | 488 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP |
| 497 | select ARCH_REQUIRE_GPIOLIB | 489 | select GPIOLIB |
| 498 | select PINCTRL | 490 | select PINCTRL |
| 499 | 491 | ||
| 500 | # SH4AL-DSP Processor Support | 492 | # SH4AL-DSP Processor Support |
| @@ -513,7 +505,6 @@ config CPU_SUBTYPE_SH7722 | |||
| 513 | select ARCH_SPARSEMEM_ENABLE | 505 | select ARCH_SPARSEMEM_ENABLE |
| 514 | select SYS_SUPPORTS_NUMA | 506 | select SYS_SUPPORTS_NUMA |
| 515 | select SYS_SUPPORTS_SH_CMT | 507 | select SYS_SUPPORTS_SH_CMT |
| 516 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 517 | select PINCTRL | 508 | select PINCTRL |
| 518 | 509 | ||
| 519 | config CPU_SUBTYPE_SH7366 | 510 | config CPU_SUBTYPE_SH7366 |
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 5e52d5362292..e0db04664e2e 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig | |||
| @@ -70,7 +70,7 @@ config SH_7724_SOLUTION_ENGINE | |||
| 70 | bool "SolutionEngine7724" | 70 | bool "SolutionEngine7724" |
| 71 | select SOLUTION_ENGINE | 71 | select SOLUTION_ENGINE |
| 72 | depends on CPU_SUBTYPE_SH7724 | 72 | depends on CPU_SUBTYPE_SH7724 |
| 73 | select ARCH_REQUIRE_GPIOLIB | 73 | select GPIOLIB |
| 74 | select SND_SOC_AK4642 if SND_SIMPLE_CARD | 74 | select SND_SOC_AK4642 if SND_SIMPLE_CARD |
| 75 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 75 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 76 | help | 76 | help |
| @@ -174,7 +174,6 @@ config SH_SDK7786 | |||
| 174 | depends on CPU_SUBTYPE_SH7786 | 174 | depends on CPU_SUBTYPE_SH7786 |
| 175 | select SYS_SUPPORTS_PCI | 175 | select SYS_SUPPORTS_PCI |
| 176 | select NO_IOPORT_MAP if !PCI | 176 | select NO_IOPORT_MAP if !PCI |
| 177 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 178 | select HAVE_SRAM_POOL | 177 | select HAVE_SRAM_POOL |
| 179 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 178 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 180 | help | 179 | help |
| @@ -190,7 +189,7 @@ config SH_HIGHLANDER | |||
| 190 | config SH_SH7757LCR | 189 | config SH_SH7757LCR |
| 191 | bool "SH7757LCR" | 190 | bool "SH7757LCR" |
| 192 | depends on CPU_SUBTYPE_SH7757 | 191 | depends on CPU_SUBTYPE_SH7757 |
| 193 | select ARCH_REQUIRE_GPIOLIB | 192 | select GPIOLIB |
| 194 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 193 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 195 | 194 | ||
| 196 | config SH_SH7785LCR | 195 | config SH_SH7785LCR |
| @@ -217,14 +216,14 @@ config SH_SH7785LCR_PT | |||
| 217 | config SH_URQUELL | 216 | config SH_URQUELL |
| 218 | bool "Urquell" | 217 | bool "Urquell" |
| 219 | depends on CPU_SUBTYPE_SH7786 | 218 | depends on CPU_SUBTYPE_SH7786 |
| 220 | select ARCH_REQUIRE_GPIOLIB | 219 | select GPIOLIB |
| 221 | select SYS_SUPPORTS_PCI | 220 | select SYS_SUPPORTS_PCI |
| 222 | select NO_IOPORT_MAP if !PCI | 221 | select NO_IOPORT_MAP if !PCI |
| 223 | 222 | ||
| 224 | config SH_MIGOR | 223 | config SH_MIGOR |
| 225 | bool "Migo-R" | 224 | bool "Migo-R" |
| 226 | depends on CPU_SUBTYPE_SH7722 | 225 | depends on CPU_SUBTYPE_SH7722 |
| 227 | select ARCH_REQUIRE_GPIOLIB | 226 | select GPIOLIB |
| 228 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 227 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 229 | help | 228 | help |
| 230 | Select Migo-R if configuring for the SH7722 Migo-R platform | 229 | Select Migo-R if configuring for the SH7722 Migo-R platform |
| @@ -233,7 +232,7 @@ config SH_MIGOR | |||
| 233 | config SH_AP325RXA | 232 | config SH_AP325RXA |
| 234 | bool "AP-325RXA" | 233 | bool "AP-325RXA" |
| 235 | depends on CPU_SUBTYPE_SH7723 | 234 | depends on CPU_SUBTYPE_SH7723 |
| 236 | select ARCH_REQUIRE_GPIOLIB | 235 | select GPIOLIB |
| 237 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 236 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 238 | help | 237 | help |
| 239 | Renesas "AP-325RXA" support. | 238 | Renesas "AP-325RXA" support. |
| @@ -242,7 +241,7 @@ config SH_AP325RXA | |||
| 242 | config SH_KFR2R09 | 241 | config SH_KFR2R09 |
| 243 | bool "KFR2R09" | 242 | bool "KFR2R09" |
| 244 | depends on CPU_SUBTYPE_SH7724 | 243 | depends on CPU_SUBTYPE_SH7724 |
| 245 | select ARCH_REQUIRE_GPIOLIB | 244 | select GPIOLIB |
| 246 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 245 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 247 | help | 246 | help |
| 248 | "Kit For R2R for 2009" support. | 247 | "Kit For R2R for 2009" support. |
| @@ -250,7 +249,7 @@ config SH_KFR2R09 | |||
| 250 | config SH_ECOVEC | 249 | config SH_ECOVEC |
| 251 | bool "EcoVec" | 250 | bool "EcoVec" |
| 252 | depends on CPU_SUBTYPE_SH7724 | 251 | depends on CPU_SUBTYPE_SH7724 |
| 253 | select ARCH_REQUIRE_GPIOLIB | 252 | select GPIOLIB |
| 254 | select SND_SOC_DA7210 if SND_SIMPLE_CARD | 253 | select SND_SOC_DA7210 if SND_SIMPLE_CARD |
| 255 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 254 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 256 | help | 255 | help |
| @@ -327,7 +326,7 @@ config SH_X3PROTO | |||
| 327 | config SH_MAGIC_PANEL_R2 | 326 | config SH_MAGIC_PANEL_R2 |
| 328 | bool "Magic Panel R2" | 327 | bool "Magic Panel R2" |
| 329 | depends on CPU_SUBTYPE_SH7720 | 328 | depends on CPU_SUBTYPE_SH7720 |
| 330 | select ARCH_REQUIRE_GPIOLIB | 329 | select GPIOLIB |
| 331 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 330 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
| 332 | help | 331 | help |
| 333 | Select Magic Panel R2 if configuring for Magic Panel R2. | 332 | Select Magic Panel R2 if configuring for Magic Panel R2. |
diff --git a/arch/sh/boards/mach-highlander/Kconfig b/arch/sh/boards/mach-highlander/Kconfig index def49cc0a7b9..42f5589b4bf3 100644 --- a/arch/sh/boards/mach-highlander/Kconfig +++ b/arch/sh/boards/mach-highlander/Kconfig | |||
| @@ -18,7 +18,7 @@ config SH_R7780MP | |||
| 18 | config SH_R7785RP | 18 | config SH_R7785RP |
| 19 | bool "R7785RP board support" | 19 | bool "R7785RP board support" |
| 20 | depends on CPU_SUBTYPE_SH7785 | 20 | depends on CPU_SUBTYPE_SH7785 |
| 21 | select ARCH_REQUIRE_GPIOLIB | 21 | select GPIOLIB |
| 22 | 22 | ||
| 23 | endchoice | 23 | endchoice |
| 24 | 24 | ||
diff --git a/arch/sh/boards/mach-rsk/Kconfig b/arch/sh/boards/mach-rsk/Kconfig index 458a11ffd022..0b9b2c4952c1 100644 --- a/arch/sh/boards/mach-rsk/Kconfig +++ b/arch/sh/boards/mach-rsk/Kconfig | |||
| @@ -10,17 +10,17 @@ config SH_RSK7201 | |||
| 10 | 10 | ||
| 11 | config SH_RSK7203 | 11 | config SH_RSK7203 |
| 12 | bool "RSK7203" | 12 | bool "RSK7203" |
| 13 | select ARCH_REQUIRE_GPIOLIB | 13 | select GPIOLIB |
| 14 | depends on CPU_SUBTYPE_SH7203 | 14 | depends on CPU_SUBTYPE_SH7203 |
| 15 | 15 | ||
| 16 | config SH_RSK7264 | 16 | config SH_RSK7264 |
| 17 | bool "RSK2+SH7264" | 17 | bool "RSK2+SH7264" |
| 18 | select ARCH_REQUIRE_GPIOLIB | 18 | select GPIOLIB |
| 19 | depends on CPU_SUBTYPE_SH7264 | 19 | depends on CPU_SUBTYPE_SH7264 |
| 20 | 20 | ||
| 21 | config SH_RSK7269 | 21 | config SH_RSK7269 |
| 22 | bool "RSK2+SH7269" | 22 | bool "RSK2+SH7269" |
| 23 | select ARCH_REQUIRE_GPIOLIB | 23 | select GPIOLIB |
| 24 | depends on CPU_SUBTYPE_SH7269 | 24 | depends on CPU_SUBTYPE_SH7269 |
| 25 | 25 | ||
| 26 | endchoice | 26 | endchoice |
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index e5602ee9c610..0769066929c6 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig | |||
| @@ -80,7 +80,7 @@ config ARCH_PUV3 | |||
| 80 | select CPU_UCV2 | 80 | select CPU_UCV2 |
| 81 | select GENERIC_CLOCKEVENTS | 81 | select GENERIC_CLOCKEVENTS |
| 82 | select HAVE_CLK | 82 | select HAVE_CLK |
| 83 | select ARCH_REQUIRE_GPIOLIB | 83 | select GPIOLIB |
| 84 | 84 | ||
| 85 | # CONFIGs for ARCH_PUV3 | 85 | # CONFIGs for ARCH_PUV3 |
| 86 | 86 | ||
diff --git a/drivers/Makefile b/drivers/Makefile index a7187b999c5e..f93771346218 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -12,7 +12,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy/ | |||
| 12 | 12 | ||
| 13 | # GPIO must come after pinctrl as gpios may need to mux pins etc | 13 | # GPIO must come after pinctrl as gpios may need to mux pins etc |
| 14 | obj-$(CONFIG_PINCTRL) += pinctrl/ | 14 | obj-$(CONFIG_PINCTRL) += pinctrl/ |
| 15 | obj-y += gpio/ | 15 | obj-$(CONFIG_GPIOLIB) += gpio/ |
| 16 | obj-y += pwm/ | 16 | obj-y += pwm/ |
| 17 | obj-$(CONFIG_PCI) += pci/ | 17 | obj-$(CONFIG_PCI) += pci/ |
| 18 | obj-$(CONFIG_PARISC) += parisc/ | 18 | obj-$(CONFIG_PARISC) += parisc/ |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d7860614f87f..98dd47a30fc7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -250,7 +250,7 @@ config GPIO_LOONGSON | |||
| 250 | driver for GPIO functionality on Loongson-2F/3A/3B processors. | 250 | driver for GPIO functionality on Loongson-2F/3A/3B processors. |
| 251 | 251 | ||
| 252 | config GPIO_LPC18XX | 252 | config GPIO_LPC18XX |
| 253 | bool "NXP LPC18XX/43XX GPIO support" | 253 | tristate "NXP LPC18XX/43XX GPIO support" |
| 254 | default y if ARCH_LPC18XX | 254 | default y if ARCH_LPC18XX |
| 255 | depends on OF_GPIO && (ARCH_LPC18XX || COMPILE_TEST) | 255 | depends on OF_GPIO && (ARCH_LPC18XX || COMPILE_TEST) |
| 256 | help | 256 | help |
| @@ -874,6 +874,15 @@ config GPIO_LP3943 | |||
| 874 | LP3943 can be used as a GPIO expander which provides up to 16 GPIOs. | 874 | LP3943 can be used as a GPIO expander which provides up to 16 GPIOs. |
| 875 | Open drain outputs are required for this usage. | 875 | Open drain outputs are required for this usage. |
| 876 | 876 | ||
| 877 | config GPIO_MAX77620 | ||
| 878 | tristate "GPIO support for PMIC MAX77620 and MAX20024" | ||
| 879 | depends on MFD_MAX77620 | ||
| 880 | help | ||
| 881 | GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor. | ||
| 882 | MAX77620 PMIC has 8 pins that can be configured as GPIOs. The | ||
| 883 | driver also provides interrupt support for each of the gpios. | ||
| 884 | Say yes here to enable the max77620 to be used as gpio controller. | ||
| 885 | |||
| 877 | config GPIO_MSIC | 886 | config GPIO_MSIC |
| 878 | bool "Intel MSIC mixed signal gpio support" | 887 | bool "Intel MSIC mixed signal gpio support" |
| 879 | depends on MFD_INTEL_MSIC | 888 | depends on MFD_INTEL_MSIC |
| @@ -1029,11 +1038,18 @@ config GPIO_BT8XX | |||
| 1029 | If unsure, say N. | 1038 | If unsure, say N. |
| 1030 | 1039 | ||
| 1031 | config GPIO_INTEL_MID | 1040 | config GPIO_INTEL_MID |
| 1032 | bool "Intel Mid GPIO support" | 1041 | bool "Intel MID GPIO support" |
| 1033 | depends on X86 | 1042 | depends on X86_INTEL_MID |
| 1043 | select GPIOLIB_IRQCHIP | ||
| 1044 | help | ||
| 1045 | Say Y here to support Intel MID GPIO. | ||
| 1046 | |||
| 1047 | config GPIO_MERRIFIELD | ||
| 1048 | tristate "Intel Merrifield GPIO support" | ||
| 1049 | depends on X86_INTEL_MID | ||
| 1034 | select GPIOLIB_IRQCHIP | 1050 | select GPIOLIB_IRQCHIP |
| 1035 | help | 1051 | help |
| 1036 | Say Y here to support Intel Mid GPIO. | 1052 | Say Y here to support Intel Merrifield GPIO. |
| 1037 | 1053 | ||
| 1038 | config GPIO_ML_IOH | 1054 | config GPIO_ML_IOH |
| 1039 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" | 1055 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 991598ea3fba..2a035ed8f168 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -61,8 +61,10 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o | |||
| 61 | obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o | 61 | obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o |
| 62 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o | 62 | obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o |
| 63 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o | 63 | obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o |
| 64 | obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o | ||
| 64 | obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o | 65 | obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o |
| 65 | obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o | 66 | obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o |
| 67 | obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o | ||
| 66 | obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o | 68 | obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o |
| 67 | obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o | 69 | obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o |
| 68 | obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o | 70 | obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o |
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 80f9ddf13343..a6607faf2fdf 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c | |||
| @@ -35,13 +35,8 @@ struct gen_74x164_chip { | |||
| 35 | 35 | ||
| 36 | static int __gen_74x164_write_config(struct gen_74x164_chip *chip) | 36 | static int __gen_74x164_write_config(struct gen_74x164_chip *chip) |
| 37 | { | 37 | { |
| 38 | struct spi_transfer xfer = { | 38 | return spi_write(to_spi_device(chip->gpio_chip.parent), chip->buffer, |
| 39 | .tx_buf = chip->buffer, | 39 | chip->registers); |
| 40 | .len = chip->registers, | ||
| 41 | }; | ||
| 42 | |||
| 43 | return spi_sync_transfer(to_spi_device(chip->gpio_chip.parent), | ||
| 44 | &xfer, 1); | ||
| 45 | } | 40 | } |
| 46 | 41 | ||
| 47 | static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) | 42 | static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) |
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 5a690256af9b..52fd63f02134 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c | |||
| @@ -20,8 +20,12 @@ static int clps711x_gpio_probe(struct platform_device *pdev) | |||
| 20 | void __iomem *dat, *dir; | 20 | void __iomem *dat, *dir; |
| 21 | struct gpio_chip *gc; | 21 | struct gpio_chip *gc; |
| 22 | struct resource *res; | 22 | struct resource *res; |
| 23 | int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id; | 23 | int err, id; |
| 24 | 24 | ||
| 25 | if (!np) | ||
| 26 | return -ENODEV; | ||
| 27 | |||
| 28 | id = of_alias_get_id(np, "gpio"); | ||
| 25 | if ((id < 0) || (id > 4)) | 29 | if ((id < 0) || (id > 4)) |
| 26 | return -ENODEV; | 30 | return -ENODEV; |
| 27 | 31 | ||
| @@ -63,7 +67,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev) | |||
| 63 | break; | 67 | break; |
| 64 | } | 68 | } |
| 65 | 69 | ||
| 66 | gc->base = id * 8; | 70 | gc->base = -1; |
| 67 | gc->owner = THIS_MODULE; | 71 | gc->owner = THIS_MODULE; |
| 68 | platform_set_drvdata(pdev, gc); | 72 | platform_set_drvdata(pdev, gc); |
| 69 | 73 | ||
| @@ -71,7 +75,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev) | |||
| 71 | } | 75 | } |
| 72 | 76 | ||
| 73 | static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = { | 77 | static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = { |
| 74 | { .compatible = "cirrus,clps711x-gpio" }, | 78 | { .compatible = "cirrus,ep7209-gpio" }, |
| 75 | { } | 79 | { } |
| 76 | }; | 80 | }; |
| 77 | MODULE_DEVICE_TABLE(of, clps711x_gpio_ids); | 81 | MODULE_DEVICE_TABLE(of, clps711x_gpio_ids); |
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 34779bb375de..6193f62c0df4 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c | |||
| @@ -486,6 +486,7 @@ dwapb_gpio_get_pdata(struct device *dev) | |||
| 486 | pp->idx >= DWAPB_MAX_PORTS) { | 486 | pp->idx >= DWAPB_MAX_PORTS) { |
| 487 | dev_err(dev, | 487 | dev_err(dev, |
| 488 | "missing/invalid port index for port%d\n", i); | 488 | "missing/invalid port index for port%d\n", i); |
| 489 | fwnode_handle_put(fwnode); | ||
| 489 | return ERR_PTR(-EINVAL); | 490 | return ERR_PTR(-EINVAL); |
| 490 | } | 491 | } |
| 491 | 492 | ||
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 05aa538c3767..600be8418707 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c | |||
| @@ -125,6 +125,7 @@ static inline void superio_exit(int base) | |||
| 125 | * GPIO chip. | 125 | * GPIO chip. |
| 126 | */ | 126 | */ |
| 127 | 127 | ||
| 128 | static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset); | ||
| 128 | static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset); | 129 | static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset); |
| 129 | static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset); | 130 | static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset); |
| 130 | static int f7188x_gpio_direction_out(struct gpio_chip *chip, | 131 | static int f7188x_gpio_direction_out(struct gpio_chip *chip, |
| @@ -139,6 +140,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *gc, | |||
| 139 | .chip = { \ | 140 | .chip = { \ |
| 140 | .label = DRVNAME, \ | 141 | .label = DRVNAME, \ |
| 141 | .owner = THIS_MODULE, \ | 142 | .owner = THIS_MODULE, \ |
| 143 | .get_direction = f7188x_gpio_get_direction, \ | ||
| 142 | .direction_input = f7188x_gpio_direction_in, \ | 144 | .direction_input = f7188x_gpio_direction_in, \ |
| 143 | .get = f7188x_gpio_get, \ | 145 | .get = f7188x_gpio_get, \ |
| 144 | .direction_output = f7188x_gpio_direction_out, \ | 146 | .direction_output = f7188x_gpio_direction_out, \ |
| @@ -209,6 +211,26 @@ static struct f7188x_gpio_bank f81866_gpio_bank[] = { | |||
| 209 | F7188X_GPIO_BANK(80, 8, 0x88), | 211 | F7188X_GPIO_BANK(80, 8, 0x88), |
| 210 | }; | 212 | }; |
| 211 | 213 | ||
| 214 | static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) | ||
| 215 | { | ||
| 216 | int err; | ||
| 217 | struct f7188x_gpio_bank *bank = | ||
| 218 | container_of(chip, struct f7188x_gpio_bank, chip); | ||
| 219 | struct f7188x_sio *sio = bank->data->sio; | ||
| 220 | u8 dir; | ||
| 221 | |||
| 222 | err = superio_enter(sio->addr); | ||
| 223 | if (err) | ||
| 224 | return err; | ||
| 225 | superio_select(sio->addr, SIO_LD_GPIO); | ||
| 226 | |||
| 227 | dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); | ||
| 228 | |||
| 229 | superio_exit(sio->addr); | ||
| 230 | |||
| 231 | return !(dir & 1 << offset); | ||
| 232 | } | ||
| 233 | |||
| 212 | static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | 234 | static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) |
| 213 | { | 235 | { |
| 214 | int err; | 236 | int err; |
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index cdaba13cb8e8..164de64b11fc 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Intel MID GPIO driver | 2 | * Intel MID GPIO driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2014 Intel Corporation. | 4 | * Copyright (c) 2008-2014,2016 Intel Corporation. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
| @@ -17,21 +17,20 @@ | |||
| 17 | * Moorestown platform Langwell chip. | 17 | * Moorestown platform Langwell chip. |
| 18 | * Medfield platform Penwell chip. | 18 | * Medfield platform Penwell chip. |
| 19 | * Clovertrail platform Cloverview chip. | 19 | * Clovertrail platform Cloverview chip. |
| 20 | * Merrifield platform Tangier chip. | ||
| 21 | */ | 20 | */ |
| 22 | 21 | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/pci.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 28 | #include <linux/stddef.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/interrupt.h> | ||
| 31 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 32 | #include <linux/gpio/driver.h> | 26 | #include <linux/gpio/driver.h> |
| 33 | #include <linux/slab.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/pci.h> | ||
| 30 | #include <linux/platform_device.h> | ||
| 34 | #include <linux/pm_runtime.h> | 31 | #include <linux/pm_runtime.h> |
| 32 | #include <linux/slab.h> | ||
| 33 | #include <linux/stddef.h> | ||
| 35 | 34 | ||
| 36 | #define INTEL_MID_IRQ_TYPE_EDGE (1 << 0) | 35 | #define INTEL_MID_IRQ_TYPE_EDGE (1 << 0) |
| 37 | #define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1) | 36 | #define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1) |
| @@ -64,10 +63,6 @@ enum GPIO_REG { | |||
| 64 | /* intel_mid gpio driver data */ | 63 | /* intel_mid gpio driver data */ |
| 65 | struct intel_mid_gpio_ddata { | 64 | struct intel_mid_gpio_ddata { |
| 66 | u16 ngpio; /* number of gpio pins */ | 65 | u16 ngpio; /* number of gpio pins */ |
| 67 | u32 gplr_offset; /* offset of first GPLR register from base */ | ||
| 68 | u32 flis_base; /* base address of FLIS registers */ | ||
| 69 | u32 flis_len; /* length of FLIS registers */ | ||
| 70 | u32 (*get_flis_offset)(int gpio); | ||
| 71 | u32 chip_irq_type; /* chip interrupt type */ | 66 | u32 chip_irq_type; /* chip interrupt type */ |
| 72 | }; | 67 | }; |
| 73 | 68 | ||
| @@ -252,15 +247,6 @@ static const struct intel_mid_gpio_ddata gpio_cloverview_core = { | |||
| 252 | .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, | 247 | .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, |
| 253 | }; | 248 | }; |
| 254 | 249 | ||
| 255 | static const struct intel_mid_gpio_ddata gpio_tangier = { | ||
| 256 | .ngpio = 192, | ||
| 257 | .gplr_offset = 4, | ||
| 258 | .flis_base = 0xff0c0000, | ||
| 259 | .flis_len = 0x8000, | ||
| 260 | .get_flis_offset = NULL, | ||
| 261 | .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static const struct pci_device_id intel_gpio_ids[] = { | 250 | static const struct pci_device_id intel_gpio_ids[] = { |
| 265 | { | 251 | { |
| 266 | /* Lincroft */ | 252 | /* Lincroft */ |
| @@ -287,11 +273,6 @@ static const struct pci_device_id intel_gpio_ids[] = { | |||
| 287 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), | 273 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), |
| 288 | .driver_data = (kernel_ulong_t)&gpio_cloverview_core, | 274 | .driver_data = (kernel_ulong_t)&gpio_cloverview_core, |
| 289 | }, | 275 | }, |
| 290 | { | ||
| 291 | /* Tangier */ | ||
| 292 | PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199), | ||
| 293 | .driver_data = (kernel_ulong_t)&gpio_tangier, | ||
| 294 | }, | ||
| 295 | { 0 } | 276 | { 0 } |
| 296 | }; | 277 | }; |
| 297 | MODULE_DEVICE_TABLE(pci, intel_gpio_ids); | 278 | MODULE_DEVICE_TABLE(pci, intel_gpio_ids); |
| @@ -401,7 +382,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, | |||
| 401 | spin_lock_init(&priv->lock); | 382 | spin_lock_init(&priv->lock); |
| 402 | 383 | ||
| 403 | pci_set_drvdata(pdev, priv); | 384 | pci_set_drvdata(pdev, priv); |
| 404 | retval = gpiochip_add_data(&priv->chip, priv); | 385 | retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); |
| 405 | if (retval) { | 386 | if (retval) { |
| 406 | dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); | 387 | dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); |
| 407 | return retval; | 388 | return retval; |
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 9df015e85ad9..fbd393b46ce0 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c | |||
| @@ -383,7 +383,6 @@ static int lp_gpio_probe(struct platform_device *pdev) | |||
| 383 | handle_simple_irq, IRQ_TYPE_NONE); | 383 | handle_simple_irq, IRQ_TYPE_NONE); |
| 384 | if (ret) { | 384 | if (ret) { |
| 385 | dev_err(dev, "failed to add irqchip\n"); | 385 | dev_err(dev, "failed to add irqchip\n"); |
| 386 | gpiochip_remove(gc); | ||
| 387 | return ret; | 386 | return ret; |
| 388 | } | 387 | } |
| 389 | 388 | ||
diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c new file mode 100644 index 000000000000..b46b436cb97f --- /dev/null +++ b/drivers/gpio/gpio-max77620.c | |||
| @@ -0,0 +1,315 @@ | |||
| 1 | /* | ||
| 2 | * MAXIM MAX77620 GPIO driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/gpio/driver.h> | ||
| 12 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/mfd/max77620.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/regmap.h> | ||
| 17 | |||
| 18 | #define GPIO_REG_ADDR(offset) (MAX77620_REG_GPIO0 + offset) | ||
| 19 | |||
| 20 | struct max77620_gpio { | ||
| 21 | struct gpio_chip gpio_chip; | ||
| 22 | struct regmap *rmap; | ||
| 23 | struct device *dev; | ||
| 24 | int gpio_irq; | ||
| 25 | int irq_base; | ||
| 26 | int gpio_base; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static const struct regmap_irq max77620_gpio_irqs[] = { | ||
| 30 | [0] = { | ||
| 31 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0, | ||
| 32 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 33 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 34 | .reg_offset = 0, | ||
| 35 | .type_reg_offset = 0, | ||
| 36 | }, | ||
| 37 | [1] = { | ||
| 38 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1, | ||
| 39 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 40 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 41 | .reg_offset = 0, | ||
| 42 | .type_reg_offset = 1, | ||
| 43 | }, | ||
| 44 | [2] = { | ||
| 45 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2, | ||
| 46 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 47 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 48 | .reg_offset = 0, | ||
| 49 | .type_reg_offset = 2, | ||
| 50 | }, | ||
| 51 | [3] = { | ||
| 52 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3, | ||
| 53 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 54 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 55 | .reg_offset = 0, | ||
| 56 | .type_reg_offset = 3, | ||
| 57 | }, | ||
| 58 | [4] = { | ||
| 59 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4, | ||
| 60 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 61 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 62 | .reg_offset = 0, | ||
| 63 | .type_reg_offset = 4, | ||
| 64 | }, | ||
| 65 | [5] = { | ||
| 66 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5, | ||
| 67 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 68 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 69 | .reg_offset = 0, | ||
| 70 | .type_reg_offset = 5, | ||
| 71 | }, | ||
| 72 | [6] = { | ||
| 73 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6, | ||
| 74 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 75 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 76 | .reg_offset = 0, | ||
| 77 | .type_reg_offset = 6, | ||
| 78 | }, | ||
| 79 | [7] = { | ||
| 80 | .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7, | ||
| 81 | .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING, | ||
| 82 | .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING, | ||
| 83 | .reg_offset = 0, | ||
| 84 | .type_reg_offset = 7, | ||
| 85 | }, | ||
| 86 | }; | ||
| 87 | |||
| 88 | static struct regmap_irq_chip max77620_gpio_irq_chip = { | ||
| 89 | .name = "max77620-gpio", | ||
| 90 | .irqs = max77620_gpio_irqs, | ||
| 91 | .num_irqs = ARRAY_SIZE(max77620_gpio_irqs), | ||
| 92 | .num_regs = 1, | ||
| 93 | .num_type_reg = 8, | ||
| 94 | .irq_reg_stride = 1, | ||
| 95 | .type_reg_stride = 1, | ||
| 96 | .status_base = MAX77620_REG_IRQ_LVL2_GPIO, | ||
| 97 | .type_base = MAX77620_REG_GPIO0, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) | ||
| 101 | { | ||
| 102 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 103 | int ret; | ||
| 104 | |||
| 105 | ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 106 | MAX77620_CNFG_GPIO_DIR_MASK, | ||
| 107 | MAX77620_CNFG_GPIO_DIR_INPUT); | ||
| 108 | if (ret < 0) | ||
| 109 | dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret); | ||
| 110 | |||
| 111 | return ret; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int max77620_gpio_get(struct gpio_chip *gc, unsigned int offset) | ||
| 115 | { | ||
| 116 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 117 | unsigned int val; | ||
| 118 | int ret; | ||
| 119 | |||
| 120 | ret = regmap_read(mgpio->rmap, GPIO_REG_ADDR(offset), &val); | ||
| 121 | if (ret < 0) { | ||
| 122 | dev_err(mgpio->dev, "CNFG_GPIOx read failed: %d\n", ret); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (val & MAX77620_CNFG_GPIO_DIR_MASK) | ||
| 127 | return !!(val & MAX77620_CNFG_GPIO_INPUT_VAL_MASK); | ||
| 128 | else | ||
| 129 | return !!(val & MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset, | ||
| 133 | int value) | ||
| 134 | { | ||
| 135 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 136 | u8 val; | ||
| 137 | int ret; | ||
| 138 | |||
| 139 | val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH : | ||
| 140 | MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW; | ||
| 141 | |||
| 142 | ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 143 | MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val); | ||
| 144 | if (ret < 0) { | ||
| 145 | dev_err(mgpio->dev, "CNFG_GPIOx val update failed: %d\n", ret); | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 149 | ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 150 | MAX77620_CNFG_GPIO_DIR_MASK, | ||
| 151 | MAX77620_CNFG_GPIO_DIR_OUTPUT); | ||
| 152 | if (ret < 0) | ||
| 153 | dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret); | ||
| 154 | |||
| 155 | return ret; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int max77620_gpio_set_debounce(struct gpio_chip *gc, | ||
| 159 | unsigned int offset, | ||
| 160 | unsigned int debounce) | ||
| 161 | { | ||
| 162 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 163 | u8 val; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | switch (debounce) { | ||
| 167 | case 0: | ||
| 168 | val = MAX77620_CNFG_GPIO_DBNC_None; | ||
| 169 | break; | ||
| 170 | case 1 ... 8: | ||
| 171 | val = MAX77620_CNFG_GPIO_DBNC_8ms; | ||
| 172 | break; | ||
| 173 | case 9 ... 16: | ||
| 174 | val = MAX77620_CNFG_GPIO_DBNC_16ms; | ||
| 175 | break; | ||
| 176 | case 17 ... 32: | ||
| 177 | val = MAX77620_CNFG_GPIO_DBNC_32ms; | ||
| 178 | break; | ||
| 179 | default: | ||
| 180 | dev_err(mgpio->dev, "Illegal value %u\n", debounce); | ||
| 181 | return -EINVAL; | ||
| 182 | } | ||
| 183 | |||
| 184 | ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 185 | MAX77620_CNFG_GPIO_DBNC_MASK, val); | ||
| 186 | if (ret < 0) | ||
| 187 | dev_err(mgpio->dev, "CNFG_GPIOx_DBNC update failed: %d\n", ret); | ||
| 188 | |||
| 189 | return ret; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset, | ||
| 193 | int value) | ||
| 194 | { | ||
| 195 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 196 | u8 val; | ||
| 197 | int ret; | ||
| 198 | |||
| 199 | val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH : | ||
| 200 | MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW; | ||
| 201 | |||
| 202 | ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 203 | MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val); | ||
| 204 | if (ret < 0) | ||
| 205 | dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret); | ||
| 206 | } | ||
| 207 | |||
| 208 | static int max77620_gpio_set_single_ended(struct gpio_chip *gc, | ||
| 209 | unsigned int offset, | ||
| 210 | enum single_ended_mode mode) | ||
| 211 | { | ||
| 212 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 213 | |||
| 214 | switch (mode) { | ||
| 215 | case LINE_MODE_OPEN_DRAIN: | ||
| 216 | return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 217 | MAX77620_CNFG_GPIO_DRV_MASK, | ||
| 218 | MAX77620_CNFG_GPIO_DRV_OPENDRAIN); | ||
| 219 | case LINE_MODE_PUSH_PULL: | ||
| 220 | return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), | ||
| 221 | MAX77620_CNFG_GPIO_DRV_MASK, | ||
| 222 | MAX77620_CNFG_GPIO_DRV_PUSHPULL); | ||
| 223 | default: | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | |||
| 227 | return -ENOTSUPP; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int max77620_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) | ||
| 231 | { | ||
| 232 | struct max77620_gpio *mgpio = gpiochip_get_data(gc); | ||
| 233 | struct max77620_chip *chip = dev_get_drvdata(mgpio->dev->parent); | ||
| 234 | |||
| 235 | return regmap_irq_get_virq(chip->gpio_irq_data, offset); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int max77620_gpio_probe(struct platform_device *pdev) | ||
| 239 | { | ||
| 240 | struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 241 | struct max77620_gpio *mgpio; | ||
| 242 | int gpio_irq; | ||
| 243 | int ret; | ||
| 244 | |||
| 245 | gpio_irq = platform_get_irq(pdev, 0); | ||
| 246 | if (gpio_irq <= 0) { | ||
| 247 | dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq); | ||
| 248 | return -ENODEV; | ||
| 249 | } | ||
| 250 | |||
| 251 | mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL); | ||
| 252 | if (!mgpio) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | mgpio->rmap = chip->rmap; | ||
| 256 | mgpio->dev = &pdev->dev; | ||
| 257 | mgpio->gpio_irq = gpio_irq; | ||
| 258 | |||
| 259 | mgpio->gpio_chip.label = pdev->name; | ||
| 260 | mgpio->gpio_chip.parent = &pdev->dev; | ||
| 261 | mgpio->gpio_chip.direction_input = max77620_gpio_dir_input; | ||
| 262 | mgpio->gpio_chip.get = max77620_gpio_get; | ||
| 263 | mgpio->gpio_chip.direction_output = max77620_gpio_dir_output; | ||
| 264 | mgpio->gpio_chip.set_debounce = max77620_gpio_set_debounce; | ||
| 265 | mgpio->gpio_chip.set = max77620_gpio_set; | ||
| 266 | mgpio->gpio_chip.set_single_ended = max77620_gpio_set_single_ended; | ||
| 267 | mgpio->gpio_chip.to_irq = max77620_gpio_to_irq; | ||
| 268 | mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR; | ||
| 269 | mgpio->gpio_chip.can_sleep = 1; | ||
| 270 | mgpio->gpio_chip.base = -1; | ||
| 271 | mgpio->irq_base = -1; | ||
| 272 | #ifdef CONFIG_OF_GPIO | ||
| 273 | mgpio->gpio_chip.of_node = pdev->dev.parent->of_node; | ||
| 274 | #endif | ||
| 275 | |||
| 276 | platform_set_drvdata(pdev, mgpio); | ||
| 277 | |||
| 278 | ret = devm_gpiochip_add_data(&pdev->dev, &mgpio->gpio_chip, mgpio); | ||
| 279 | if (ret < 0) { | ||
| 280 | dev_err(&pdev->dev, "gpio_init: Failed to add max77620_gpio\n"); | ||
| 281 | return ret; | ||
| 282 | } | ||
| 283 | |||
| 284 | mgpio->gpio_base = mgpio->gpio_chip.base; | ||
| 285 | ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq, | ||
| 286 | IRQF_ONESHOT, mgpio->irq_base, | ||
| 287 | &max77620_gpio_irq_chip, | ||
| 288 | &chip->gpio_irq_data); | ||
| 289 | if (ret < 0) { | ||
| 290 | dev_err(&pdev->dev, "Failed to add gpio irq_chip %d\n", ret); | ||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static const struct platform_device_id max77620_gpio_devtype[] = { | ||
| 298 | { .name = "max77620-gpio", }, | ||
| 299 | {}, | ||
| 300 | }; | ||
| 301 | MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype); | ||
| 302 | |||
| 303 | static struct platform_driver max77620_gpio_driver = { | ||
| 304 | .driver.name = "max77620-gpio", | ||
| 305 | .probe = max77620_gpio_probe, | ||
| 306 | .id_table = max77620_gpio_devtype, | ||
| 307 | }; | ||
| 308 | |||
| 309 | module_platform_driver(max77620_gpio_driver); | ||
| 310 | |||
| 311 | MODULE_DESCRIPTION("GPIO interface for MAX77620 and MAX20024 PMIC"); | ||
| 312 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
| 313 | MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>"); | ||
| 314 | MODULE_ALIAS("platform:max77620-gpio"); | ||
| 315 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index cc103aff45e4..a1210e330571 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c | |||
| @@ -187,7 +187,6 @@ MODULE_DEVICE_TABLE(mcb, men_z127_ids); | |||
| 187 | static struct mcb_driver men_z127_driver = { | 187 | static struct mcb_driver men_z127_driver = { |
| 188 | .driver = { | 188 | .driver = { |
| 189 | .name = "z127-gpio", | 189 | .name = "z127-gpio", |
| 190 | .owner = THIS_MODULE, | ||
| 191 | }, | 190 | }, |
| 192 | .probe = men_z127_probe, | 191 | .probe = men_z127_probe, |
| 193 | .remove = men_z127_remove, | 192 | .remove = men_z127_remove, |
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c new file mode 100644 index 000000000000..45b51278b8ee --- /dev/null +++ b/drivers/gpio/gpio-merrifield.c | |||
| @@ -0,0 +1,444 @@ | |||
| 1 | /* | ||
| 2 | * Intel Merrifield SoC GPIO driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016 Intel Corporation. | ||
| 5 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/bitops.h> | ||
| 13 | #include <linux/gpio/driver.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/pci.h> | ||
| 19 | #include <linux/pinctrl/consumer.h> | ||
| 20 | |||
| 21 | #define GCCR 0x000 /* controller configuration */ | ||
| 22 | #define GPLR 0x004 /* pin level r/o */ | ||
| 23 | #define GPDR 0x01c /* pin direction */ | ||
| 24 | #define GPSR 0x034 /* pin set w/o */ | ||
| 25 | #define GPCR 0x04c /* pin clear w/o */ | ||
| 26 | #define GRER 0x064 /* rising edge detect */ | ||
| 27 | #define GFER 0x07c /* falling edge detect */ | ||
| 28 | #define GFBR 0x094 /* glitch filter bypass */ | ||
| 29 | #define GIMR 0x0ac /* interrupt mask */ | ||
| 30 | #define GISR 0x0c4 /* interrupt source */ | ||
| 31 | #define GITR 0x300 /* input type */ | ||
| 32 | #define GLPR 0x318 /* level input polarity */ | ||
| 33 | #define GWMR 0x400 /* wake mask */ | ||
| 34 | #define GWSR 0x418 /* wake source */ | ||
| 35 | #define GSIR 0xc00 /* secure input */ | ||
| 36 | |||
| 37 | /* Intel Merrifield has 192 GPIO pins */ | ||
| 38 | #define MRFLD_NGPIO 192 | ||
| 39 | |||
| 40 | struct mrfld_gpio_pinrange { | ||
| 41 | unsigned int gpio_base; | ||
| 42 | unsigned int pin_base; | ||
| 43 | unsigned int npins; | ||
| 44 | }; | ||
| 45 | |||
| 46 | #define GPIO_PINRANGE(gstart, gend, pstart) \ | ||
| 47 | { \ | ||
| 48 | .gpio_base = (gstart), \ | ||
| 49 | .pin_base = (pstart), \ | ||
| 50 | .npins = (gend) - (gstart) + 1, \ | ||
| 51 | } | ||
| 52 | |||
| 53 | struct mrfld_gpio { | ||
| 54 | struct gpio_chip chip; | ||
| 55 | void __iomem *reg_base; | ||
| 56 | raw_spinlock_t lock; | ||
| 57 | struct device *dev; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static const struct mrfld_gpio_pinrange mrfld_gpio_ranges[] = { | ||
| 61 | GPIO_PINRANGE(0, 11, 146), | ||
| 62 | GPIO_PINRANGE(12, 13, 144), | ||
| 63 | GPIO_PINRANGE(14, 15, 35), | ||
| 64 | GPIO_PINRANGE(16, 16, 164), | ||
| 65 | GPIO_PINRANGE(17, 18, 105), | ||
| 66 | GPIO_PINRANGE(19, 22, 101), | ||
| 67 | GPIO_PINRANGE(23, 30, 107), | ||
| 68 | GPIO_PINRANGE(32, 43, 67), | ||
| 69 | GPIO_PINRANGE(44, 63, 195), | ||
| 70 | GPIO_PINRANGE(64, 67, 140), | ||
| 71 | GPIO_PINRANGE(68, 69, 165), | ||
| 72 | GPIO_PINRANGE(70, 71, 65), | ||
| 73 | GPIO_PINRANGE(72, 76, 228), | ||
| 74 | GPIO_PINRANGE(77, 86, 37), | ||
| 75 | GPIO_PINRANGE(87, 87, 48), | ||
| 76 | GPIO_PINRANGE(88, 88, 47), | ||
| 77 | GPIO_PINRANGE(89, 96, 49), | ||
| 78 | GPIO_PINRANGE(97, 97, 34), | ||
| 79 | GPIO_PINRANGE(102, 119, 83), | ||
| 80 | GPIO_PINRANGE(120, 123, 79), | ||
| 81 | GPIO_PINRANGE(124, 135, 115), | ||
| 82 | GPIO_PINRANGE(137, 142, 158), | ||
| 83 | GPIO_PINRANGE(154, 163, 24), | ||
| 84 | GPIO_PINRANGE(164, 176, 215), | ||
| 85 | GPIO_PINRANGE(177, 189, 127), | ||
| 86 | GPIO_PINRANGE(190, 191, 178), | ||
| 87 | }; | ||
| 88 | |||
| 89 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned int offset, | ||
| 90 | unsigned int reg_type_offset) | ||
| 91 | { | ||
| 92 | struct mrfld_gpio *priv = gpiochip_get_data(chip); | ||
| 93 | u8 reg = offset / 32; | ||
| 94 | |||
| 95 | return priv->reg_base + reg_type_offset + reg * 4; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int mrfld_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
| 99 | { | ||
| 100 | void __iomem *gplr = gpio_reg(chip, offset, GPLR); | ||
| 101 | |||
| 102 | return !!(readl(gplr) & BIT(offset % 32)); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void mrfld_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
| 106 | int value) | ||
| 107 | { | ||
| 108 | struct mrfld_gpio *priv = gpiochip_get_data(chip); | ||
| 109 | void __iomem *gpsr, *gpcr; | ||
| 110 | unsigned long flags; | ||
| 111 | |||
| 112 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 113 | |||
| 114 | if (value) { | ||
| 115 | gpsr = gpio_reg(chip, offset, GPSR); | ||
| 116 | writel(BIT(offset % 32), gpsr); | ||
| 117 | } else { | ||
| 118 | gpcr = gpio_reg(chip, offset, GPCR); | ||
| 119 | writel(BIT(offset % 32), gpcr); | ||
| 120 | } | ||
| 121 | |||
| 122 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 123 | } | ||
| 124 | |||
| 125 | static int mrfld_gpio_direction_input(struct gpio_chip *chip, | ||
| 126 | unsigned int offset) | ||
| 127 | { | ||
| 128 | struct mrfld_gpio *priv = gpiochip_get_data(chip); | ||
| 129 | void __iomem *gpdr = gpio_reg(chip, offset, GPDR); | ||
| 130 | unsigned long flags; | ||
| 131 | u32 value; | ||
| 132 | |||
| 133 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 134 | |||
| 135 | value = readl(gpdr); | ||
| 136 | value &= ~BIT(offset % 32); | ||
| 137 | writel(value, gpdr); | ||
| 138 | |||
| 139 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int mrfld_gpio_direction_output(struct gpio_chip *chip, | ||
| 145 | unsigned int offset, int value) | ||
| 146 | { | ||
| 147 | struct mrfld_gpio *priv = gpiochip_get_data(chip); | ||
| 148 | void __iomem *gpdr = gpio_reg(chip, offset, GPDR); | ||
| 149 | unsigned long flags; | ||
| 150 | |||
| 151 | mrfld_gpio_set(chip, offset, value); | ||
| 152 | |||
| 153 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 154 | |||
| 155 | value = readl(gpdr); | ||
| 156 | value |= BIT(offset % 32); | ||
| 157 | writel(value, gpdr); | ||
| 158 | |||
| 159 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void mrfld_irq_ack(struct irq_data *d) | ||
| 165 | { | ||
| 166 | struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); | ||
| 167 | u32 gpio = irqd_to_hwirq(d); | ||
| 168 | void __iomem *gisr = gpio_reg(&priv->chip, gpio, GISR); | ||
| 169 | unsigned long flags; | ||
| 170 | |||
| 171 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 172 | |||
| 173 | writel(BIT(gpio % 32), gisr); | ||
| 174 | |||
| 175 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void mrfld_irq_unmask_mask(struct irq_data *d, bool unmask) | ||
| 179 | { | ||
| 180 | struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); | ||
| 181 | u32 gpio = irqd_to_hwirq(d); | ||
| 182 | void __iomem *gimr = gpio_reg(&priv->chip, gpio, GIMR); | ||
| 183 | unsigned long flags; | ||
| 184 | u32 value; | ||
| 185 | |||
| 186 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 187 | |||
| 188 | if (unmask) | ||
| 189 | value = readl(gimr) | BIT(gpio % 32); | ||
| 190 | else | ||
| 191 | value = readl(gimr) & ~BIT(gpio % 32); | ||
| 192 | writel(value, gimr); | ||
| 193 | |||
| 194 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 195 | } | ||
| 196 | |||
| 197 | static void mrfld_irq_mask(struct irq_data *d) | ||
| 198 | { | ||
| 199 | mrfld_irq_unmask_mask(d, false); | ||
| 200 | } | ||
| 201 | |||
| 202 | static void mrfld_irq_unmask(struct irq_data *d) | ||
| 203 | { | ||
| 204 | mrfld_irq_unmask_mask(d, true); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int mrfld_irq_set_type(struct irq_data *d, unsigned int type) | ||
| 208 | { | ||
| 209 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 210 | struct mrfld_gpio *priv = gpiochip_get_data(gc); | ||
| 211 | u32 gpio = irqd_to_hwirq(d); | ||
| 212 | void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER); | ||
| 213 | void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER); | ||
| 214 | void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR); | ||
| 215 | void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR); | ||
| 216 | unsigned long flags; | ||
| 217 | u32 value; | ||
| 218 | |||
| 219 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 220 | |||
| 221 | if (type & IRQ_TYPE_EDGE_RISING) | ||
| 222 | value = readl(grer) | BIT(gpio % 32); | ||
| 223 | else | ||
| 224 | value = readl(grer) & ~BIT(gpio % 32); | ||
| 225 | writel(value, grer); | ||
| 226 | |||
| 227 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
| 228 | value = readl(gfer) | BIT(gpio % 32); | ||
| 229 | else | ||
| 230 | value = readl(gfer) & ~BIT(gpio % 32); | ||
| 231 | writel(value, gfer); | ||
| 232 | |||
| 233 | /* | ||
| 234 | * To prevent glitches from triggering an unintended level interrupt, | ||
| 235 | * configure GLPR register first and then configure GITR. | ||
| 236 | */ | ||
| 237 | if (type & IRQ_TYPE_LEVEL_LOW) | ||
| 238 | value = readl(glpr) | BIT(gpio % 32); | ||
| 239 | else | ||
| 240 | value = readl(glpr) & ~BIT(gpio % 32); | ||
| 241 | writel(value, glpr); | ||
| 242 | |||
| 243 | if (type & IRQ_TYPE_LEVEL_MASK) { | ||
| 244 | value = readl(gitr) | BIT(gpio % 32); | ||
| 245 | writel(value, gitr); | ||
| 246 | |||
| 247 | irq_set_handler_locked(d, handle_level_irq); | ||
| 248 | } else if (type & IRQ_TYPE_EDGE_BOTH) { | ||
| 249 | value = readl(gitr) & ~BIT(gpio % 32); | ||
| 250 | writel(value, gitr); | ||
| 251 | |||
| 252 | irq_set_handler_locked(d, handle_edge_irq); | ||
| 253 | } | ||
| 254 | |||
| 255 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 256 | |||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on) | ||
| 261 | { | ||
| 262 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
| 263 | struct mrfld_gpio *priv = gpiochip_get_data(gc); | ||
| 264 | u32 gpio = irqd_to_hwirq(d); | ||
| 265 | void __iomem *gwmr = gpio_reg(&priv->chip, gpio, GWMR); | ||
| 266 | void __iomem *gwsr = gpio_reg(&priv->chip, gpio, GWSR); | ||
| 267 | unsigned long flags; | ||
| 268 | u32 value; | ||
| 269 | |||
| 270 | raw_spin_lock_irqsave(&priv->lock, flags); | ||
| 271 | |||
| 272 | /* Clear the existing wake status */ | ||
| 273 | writel(BIT(gpio % 32), gwsr); | ||
| 274 | |||
| 275 | if (on) | ||
| 276 | value = readl(gwmr) | BIT(gpio % 32); | ||
| 277 | else | ||
| 278 | value = readl(gwmr) & ~BIT(gpio % 32); | ||
| 279 | writel(value, gwmr); | ||
| 280 | |||
| 281 | raw_spin_unlock_irqrestore(&priv->lock, flags); | ||
| 282 | |||
| 283 | dev_dbg(priv->dev, "%sable wake for gpio %u\n", on ? "en" : "dis", gpio); | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | static struct irq_chip mrfld_irqchip = { | ||
| 288 | .name = "gpio-merrifield", | ||
| 289 | .irq_ack = mrfld_irq_ack, | ||
| 290 | .irq_mask = mrfld_irq_mask, | ||
| 291 | .irq_unmask = mrfld_irq_unmask, | ||
| 292 | .irq_set_type = mrfld_irq_set_type, | ||
| 293 | .irq_set_wake = mrfld_irq_set_wake, | ||
| 294 | }; | ||
| 295 | |||
| 296 | static void mrfld_irq_handler(struct irq_desc *desc) | ||
| 297 | { | ||
| 298 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | ||
| 299 | struct mrfld_gpio *priv = gpiochip_get_data(gc); | ||
| 300 | struct irq_chip *irqchip = irq_desc_get_chip(desc); | ||
| 301 | unsigned long base, gpio; | ||
| 302 | |||
| 303 | chained_irq_enter(irqchip, desc); | ||
| 304 | |||
| 305 | /* Check GPIO controller to check which pin triggered the interrupt */ | ||
| 306 | for (base = 0; base < priv->chip.ngpio; base += 32) { | ||
| 307 | void __iomem *gisr = gpio_reg(&priv->chip, base, GISR); | ||
| 308 | void __iomem *gimr = gpio_reg(&priv->chip, base, GIMR); | ||
| 309 | unsigned long pending, enabled; | ||
| 310 | |||
| 311 | pending = readl(gisr); | ||
| 312 | enabled = readl(gimr); | ||
| 313 | |||
| 314 | /* Only interrupts that are enabled */ | ||
| 315 | pending &= enabled; | ||
| 316 | |||
| 317 | for_each_set_bit(gpio, &pending, 32) { | ||
| 318 | unsigned int irq; | ||
| 319 | |||
| 320 | irq = irq_find_mapping(gc->irqdomain, base + gpio); | ||
| 321 | generic_handle_irq(irq); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | chained_irq_exit(irqchip, desc); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void mrfld_irq_init_hw(struct mrfld_gpio *priv) | ||
| 329 | { | ||
| 330 | void __iomem *reg; | ||
| 331 | unsigned int base; | ||
| 332 | |||
| 333 | for (base = 0; base < priv->chip.ngpio; base += 32) { | ||
| 334 | /* Clear the rising-edge detect register */ | ||
| 335 | reg = gpio_reg(&priv->chip, base, GRER); | ||
| 336 | writel(0, reg); | ||
| 337 | /* Clear the falling-edge detect register */ | ||
| 338 | reg = gpio_reg(&priv->chip, base, GFER); | ||
| 339 | writel(0, reg); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 344 | { | ||
| 345 | const struct mrfld_gpio_pinrange *range; | ||
| 346 | struct mrfld_gpio *priv; | ||
| 347 | u32 gpio_base, irq_base; | ||
| 348 | void __iomem *base; | ||
| 349 | unsigned int i; | ||
| 350 | int retval; | ||
| 351 | |||
| 352 | retval = pcim_enable_device(pdev); | ||
| 353 | if (retval) | ||
| 354 | return retval; | ||
| 355 | |||
| 356 | retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev)); | ||
| 357 | if (retval) { | ||
| 358 | dev_err(&pdev->dev, "I/O memory mapping error\n"); | ||
| 359 | return retval; | ||
| 360 | } | ||
| 361 | |||
| 362 | base = pcim_iomap_table(pdev)[1]; | ||
| 363 | |||
| 364 | irq_base = readl(base); | ||
| 365 | gpio_base = readl(sizeof(u32) + base); | ||
| 366 | |||
| 367 | /* Release the IO mapping, since we already get the info from BAR1 */ | ||
| 368 | pcim_iounmap_regions(pdev, BIT(1)); | ||
| 369 | |||
| 370 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
| 371 | if (!priv) { | ||
| 372 | dev_err(&pdev->dev, "can't allocate chip data\n"); | ||
| 373 | return -ENOMEM; | ||
| 374 | } | ||
| 375 | |||
| 376 | priv->dev = &pdev->dev; | ||
| 377 | priv->reg_base = pcim_iomap_table(pdev)[0]; | ||
| 378 | |||
| 379 | priv->chip.label = dev_name(&pdev->dev); | ||
| 380 | priv->chip.parent = &pdev->dev; | ||
| 381 | priv->chip.request = gpiochip_generic_request; | ||
| 382 | priv->chip.free = gpiochip_generic_free; | ||
| 383 | priv->chip.direction_input = mrfld_gpio_direction_input; | ||
| 384 | priv->chip.direction_output = mrfld_gpio_direction_output; | ||
| 385 | priv->chip.get = mrfld_gpio_get; | ||
| 386 | priv->chip.set = mrfld_gpio_set; | ||
| 387 | priv->chip.base = gpio_base; | ||
| 388 | priv->chip.ngpio = MRFLD_NGPIO; | ||
| 389 | priv->chip.can_sleep = false; | ||
| 390 | |||
| 391 | raw_spin_lock_init(&priv->lock); | ||
| 392 | |||
| 393 | pci_set_drvdata(pdev, priv); | ||
| 394 | retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); | ||
| 395 | if (retval) { | ||
| 396 | dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); | ||
| 397 | return retval; | ||
| 398 | } | ||
| 399 | |||
| 400 | for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { | ||
| 401 | range = &mrfld_gpio_ranges[i]; | ||
| 402 | retval = gpiochip_add_pin_range(&priv->chip, | ||
| 403 | "pinctrl-merrifield", | ||
| 404 | range->gpio_base, | ||
| 405 | range->pin_base, | ||
| 406 | range->npins); | ||
| 407 | if (retval) { | ||
| 408 | dev_err(&pdev->dev, "failed to add GPIO pin range\n"); | ||
| 409 | return retval; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, | ||
| 414 | handle_simple_irq, IRQ_TYPE_NONE); | ||
| 415 | if (retval) { | ||
| 416 | dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); | ||
| 417 | return retval; | ||
| 418 | } | ||
| 419 | |||
| 420 | mrfld_irq_init_hw(priv); | ||
| 421 | |||
| 422 | gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq, | ||
| 423 | mrfld_irq_handler); | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static const struct pci_device_id mrfld_gpio_ids[] = { | ||
| 429 | { PCI_VDEVICE(INTEL, 0x1199) }, | ||
| 430 | { } | ||
| 431 | }; | ||
| 432 | MODULE_DEVICE_TABLE(pci, mrfld_gpio_ids); | ||
| 433 | |||
| 434 | static struct pci_driver mrfld_gpio_driver = { | ||
| 435 | .name = "gpio-merrifield", | ||
| 436 | .id_table = mrfld_gpio_ids, | ||
| 437 | .probe = mrfld_gpio_probe, | ||
| 438 | }; | ||
| 439 | |||
| 440 | module_pci_driver(mrfld_gpio_driver); | ||
| 441 | |||
| 442 | MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); | ||
| 443 | MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver"); | ||
| 444 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 6c1cb3b8c02c..6ec144baeb11 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c | |||
| @@ -61,6 +61,8 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` | |||
| 61 | #include <linux/bitops.h> | 61 | #include <linux/bitops.h> |
| 62 | #include <linux/platform_device.h> | 62 | #include <linux/platform_device.h> |
| 63 | #include <linux/mod_devicetable.h> | 63 | #include <linux/mod_devicetable.h> |
| 64 | #include <linux/of.h> | ||
| 65 | #include <linux/of_device.h> | ||
| 64 | 66 | ||
| 65 | static void bgpio_write8(void __iomem *reg, unsigned long data) | 67 | static void bgpio_write8(void __iomem *reg, unsigned long data) |
| 66 | { | 68 | { |
| @@ -569,6 +571,41 @@ static void __iomem *bgpio_map(struct platform_device *pdev, | |||
| 569 | return devm_ioremap_resource(&pdev->dev, r); | 571 | return devm_ioremap_resource(&pdev->dev, r); |
| 570 | } | 572 | } |
| 571 | 573 | ||
| 574 | #ifdef CONFIG_OF | ||
| 575 | static const struct of_device_id bgpio_of_match[] = { | ||
| 576 | { .compatible = "wd,mbl-gpio" }, | ||
| 577 | { } | ||
| 578 | }; | ||
| 579 | MODULE_DEVICE_TABLE(of, bgpio_of_match); | ||
| 580 | |||
| 581 | static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev, | ||
| 582 | unsigned long *flags) | ||
| 583 | { | ||
| 584 | struct bgpio_pdata *pdata; | ||
| 585 | |||
| 586 | if (!of_match_device(bgpio_of_match, &pdev->dev)) | ||
| 587 | return NULL; | ||
| 588 | |||
| 589 | pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata), | ||
| 590 | GFP_KERNEL); | ||
| 591 | if (!pdata) | ||
| 592 | return ERR_PTR(-ENOMEM); | ||
| 593 | |||
| 594 | pdata->base = -1; | ||
| 595 | |||
| 596 | if (of_property_read_bool(pdev->dev.of_node, "no-output")) | ||
| 597 | *flags |= BGPIOF_NO_OUTPUT; | ||
| 598 | |||
| 599 | return pdata; | ||
| 600 | } | ||
| 601 | #else | ||
| 602 | static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev, | ||
| 603 | unsigned long *flags) | ||
| 604 | { | ||
| 605 | return NULL; | ||
| 606 | } | ||
| 607 | #endif /* CONFIG_OF */ | ||
| 608 | |||
| 572 | static int bgpio_pdev_probe(struct platform_device *pdev) | 609 | static int bgpio_pdev_probe(struct platform_device *pdev) |
| 573 | { | 610 | { |
| 574 | struct device *dev = &pdev->dev; | 611 | struct device *dev = &pdev->dev; |
| @@ -579,10 +616,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev) | |||
| 579 | void __iomem *dirout; | 616 | void __iomem *dirout; |
| 580 | void __iomem *dirin; | 617 | void __iomem *dirin; |
| 581 | unsigned long sz; | 618 | unsigned long sz; |
| 582 | unsigned long flags = pdev->id_entry->driver_data; | 619 | unsigned long flags = 0; |
| 583 | int err; | 620 | int err; |
| 584 | struct gpio_chip *gc; | 621 | struct gpio_chip *gc; |
| 585 | struct bgpio_pdata *pdata = dev_get_platdata(dev); | 622 | struct bgpio_pdata *pdata; |
| 623 | |||
| 624 | pdata = bgpio_parse_dt(pdev, &flags); | ||
| 625 | if (IS_ERR(pdata)) | ||
| 626 | return PTR_ERR(pdata); | ||
| 627 | |||
| 628 | if (!pdata) { | ||
| 629 | pdata = dev_get_platdata(dev); | ||
| 630 | flags = pdev->id_entry->driver_data; | ||
| 631 | } | ||
| 586 | 632 | ||
| 587 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | 633 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); |
| 588 | if (!r) | 634 | if (!r) |
| @@ -646,6 +692,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table); | |||
| 646 | static struct platform_driver bgpio_driver = { | 692 | static struct platform_driver bgpio_driver = { |
| 647 | .driver = { | 693 | .driver = { |
| 648 | .name = "basic-mmio-gpio", | 694 | .name = "basic-mmio-gpio", |
| 695 | .of_match_table = of_match_ptr(bgpio_of_match), | ||
| 649 | }, | 696 | }, |
| 650 | .id_table = bgpio_id_table, | 697 | .id_table = bgpio_id_table, |
| 651 | .probe = bgpio_pdev_probe, | 698 | .probe = bgpio_pdev_probe, |
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index e248707ca39e..839474430229 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c | |||
| @@ -208,7 +208,6 @@ static int palmas_gpio_probe(struct platform_device *pdev) | |||
| 208 | 208 | ||
| 209 | static struct platform_driver palmas_gpio_driver = { | 209 | static struct platform_driver palmas_gpio_driver = { |
| 210 | .driver.name = "palmas-gpio", | 210 | .driver.name = "palmas-gpio", |
| 211 | .driver.owner = THIS_MODULE, | ||
| 212 | .driver.of_match_table = of_palmas_gpio_match, | 211 | .driver.of_match_table = of_palmas_gpio_match, |
| 213 | .probe = palmas_gpio_probe, | 212 | .probe = palmas_gpio_probe, |
| 214 | }; | 213 | }; |
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 5e3be32ebb8d..02f2a5621bb0 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | #define PCA_GPIO_MASK 0x00FF | 45 | #define PCA_GPIO_MASK 0x00FF |
| 46 | #define PCA_INT 0x0100 | 46 | #define PCA_INT 0x0100 |
| 47 | #define PCA_PCAL 0x0200 | 47 | #define PCA_PCAL 0x0200 |
| 48 | #define PCA953X_TYPE 0x1000 | 48 | #define PCA953X_TYPE 0x1000 |
| 49 | #define PCA957X_TYPE 0x2000 | 49 | #define PCA957X_TYPE 0x2000 |
| 50 | #define PCA_TYPE_MASK 0xF000 | 50 | #define PCA_TYPE_MASK 0xF000 |
| @@ -67,6 +67,8 @@ static const struct i2c_device_id pca953x_id[] = { | |||
| 67 | { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, | 67 | { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, |
| 68 | { "pca9698", 40 | PCA953X_TYPE, }, | 68 | { "pca9698", 40 | PCA953X_TYPE, }, |
| 69 | 69 | ||
| 70 | { "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, | ||
| 71 | |||
| 70 | { "max7310", 8 | PCA953X_TYPE, }, | 72 | { "max7310", 8 | PCA953X_TYPE, }, |
| 71 | { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, | 73 | { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, |
| 72 | { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, | 74 | { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, |
| @@ -90,7 +92,7 @@ MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); | |||
| 90 | #define MAX_BANK 5 | 92 | #define MAX_BANK 5 |
| 91 | #define BANK_SZ 8 | 93 | #define BANK_SZ 8 |
| 92 | 94 | ||
| 93 | #define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) | 95 | #define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ) |
| 94 | 96 | ||
| 95 | struct pca953x_chip { | 97 | struct pca953x_chip { |
| 96 | unsigned gpio_start; | 98 | unsigned gpio_start; |
| @@ -135,7 +137,7 @@ static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, | |||
| 135 | static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, | 137 | static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, |
| 136 | int off) | 138 | int off) |
| 137 | { | 139 | { |
| 138 | int ret = 0; | 140 | int ret; |
| 139 | int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); | 141 | int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); |
| 140 | int offset = off / BANK_SZ; | 142 | int offset = off / BANK_SZ; |
| 141 | 143 | ||
| @@ -163,10 +165,13 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) | |||
| 163 | NBANK(chip), val); | 165 | NBANK(chip), val); |
| 164 | } else { | 166 | } else { |
| 165 | switch (chip->chip_type) { | 167 | switch (chip->chip_type) { |
| 166 | case PCA953X_TYPE: | 168 | case PCA953X_TYPE: { |
| 167 | ret = i2c_smbus_write_word_data(chip->client, | 169 | __le16 word = cpu_to_le16(get_unaligned((u16 *)val)); |
| 168 | reg << 1, cpu_to_le16(get_unaligned((u16 *)val))); | 170 | |
| 171 | ret = i2c_smbus_write_word_data(chip->client, reg << 1, | ||
| 172 | (__force u16)word); | ||
| 169 | break; | 173 | break; |
| 174 | } | ||
| 170 | case PCA957X_TYPE: | 175 | case PCA957X_TYPE: |
| 171 | ret = i2c_smbus_write_byte_data(chip->client, reg << 1, | 176 | ret = i2c_smbus_write_byte_data(chip->client, reg << 1, |
| 172 | val[0]); | 177 | val[0]); |
| @@ -235,7 +240,6 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) | |||
| 235 | goto exit; | 240 | goto exit; |
| 236 | 241 | ||
| 237 | chip->reg_direction[off / BANK_SZ] = reg_val; | 242 | chip->reg_direction[off / BANK_SZ] = reg_val; |
| 238 | ret = 0; | ||
| 239 | exit: | 243 | exit: |
| 240 | mutex_unlock(&chip->i2c_lock); | 244 | mutex_unlock(&chip->i2c_lock); |
| 241 | return ret; | 245 | return ret; |
| @@ -286,7 +290,6 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, | |||
| 286 | goto exit; | 290 | goto exit; |
| 287 | 291 | ||
| 288 | chip->reg_direction[off / BANK_SZ] = reg_val; | 292 | chip->reg_direction[off / BANK_SZ] = reg_val; |
| 289 | ret = 0; | ||
| 290 | exit: | 293 | exit: |
| 291 | mutex_unlock(&chip->i2c_lock); | 294 | mutex_unlock(&chip->i2c_lock); |
| 292 | return ret; | 295 | return ret; |
| @@ -351,7 +354,6 @@ exit: | |||
| 351 | mutex_unlock(&chip->i2c_lock); | 354 | mutex_unlock(&chip->i2c_lock); |
| 352 | } | 355 | } |
| 353 | 356 | ||
| 354 | |||
| 355 | static void pca953x_gpio_set_multiple(struct gpio_chip *gc, | 357 | static void pca953x_gpio_set_multiple(struct gpio_chip *gc, |
| 356 | unsigned long *mask, unsigned long *bits) | 358 | unsigned long *mask, unsigned long *bits) |
| 357 | { | 359 | { |
| @@ -820,7 +822,7 @@ static int pca953x_remove(struct i2c_client *client) | |||
| 820 | { | 822 | { |
| 821 | struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); | 823 | struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); |
| 822 | struct pca953x_chip *chip = i2c_get_clientdata(client); | 824 | struct pca953x_chip *chip = i2c_get_clientdata(client); |
| 823 | int ret = 0; | 825 | int ret; |
| 824 | 826 | ||
| 825 | if (pdata && pdata->teardown) { | 827 | if (pdata && pdata->teardown) { |
| 826 | ret = pdata->teardown(client, chip->gpio_chip.base, | 828 | ret = pdata->teardown(client, chip->gpio_chip.base, |
| @@ -861,6 +863,7 @@ static const struct of_device_id pca953x_dt_ids[] = { | |||
| 861 | { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, | 863 | { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, |
| 862 | 864 | ||
| 863 | { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, | 865 | { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, |
| 866 | { .compatible = "ti,pca9536", .data = OF_953X( 4, 0), }, | ||
| 864 | { .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, | 867 | { .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, |
| 865 | { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, | 868 | { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, |
| 866 | { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, | 869 | { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, |
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 169c09aa33c8..d168410e2338 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c | |||
| @@ -440,6 +440,14 @@ static int pcf857x_remove(struct i2c_client *client) | |||
| 440 | return status; | 440 | return status; |
| 441 | } | 441 | } |
| 442 | 442 | ||
| 443 | static void pcf857x_shutdown(struct i2c_client *client) | ||
| 444 | { | ||
| 445 | struct pcf857x *gpio = i2c_get_clientdata(client); | ||
| 446 | |||
| 447 | /* Drive all the I/O lines high */ | ||
| 448 | gpio->write(gpio->client, BIT(gpio->chip.ngpio) - 1); | ||
| 449 | } | ||
| 450 | |||
| 443 | static struct i2c_driver pcf857x_driver = { | 451 | static struct i2c_driver pcf857x_driver = { |
| 444 | .driver = { | 452 | .driver = { |
| 445 | .name = "pcf857x", | 453 | .name = "pcf857x", |
| @@ -447,6 +455,7 @@ static struct i2c_driver pcf857x_driver = { | |||
| 447 | }, | 455 | }, |
| 448 | .probe = pcf857x_probe, | 456 | .probe = pcf857x_probe, |
| 449 | .remove = pcf857x_remove, | 457 | .remove = pcf857x_remove, |
| 458 | .shutdown = pcf857x_shutdown, | ||
| 450 | .id_table = pcf857x_id, | 459 | .id_table = pcf857x_id, |
| 451 | }; | 460 | }; |
| 452 | 461 | ||
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 681c93fb9e70..b96e0b466f74 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c | |||
| @@ -335,6 +335,9 @@ static const struct of_device_id gpio_rcar_of_table[] = { | |||
| 335 | .compatible = "renesas,gpio-r8a7791", | 335 | .compatible = "renesas,gpio-r8a7791", |
| 336 | .data = &gpio_rcar_info_gen2, | 336 | .data = &gpio_rcar_info_gen2, |
| 337 | }, { | 337 | }, { |
| 338 | .compatible = "renesas,gpio-r8a7792", | ||
| 339 | .data = &gpio_rcar_info_gen2, | ||
| 340 | }, { | ||
| 338 | .compatible = "renesas,gpio-r8a7793", | 341 | .compatible = "renesas,gpio-r8a7793", |
| 339 | .data = &gpio_rcar_info_gen2, | 342 | .data = &gpio_rcar_info_gen2, |
| 340 | }, { | 343 | }, { |
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index ec945b90f54d..cbf0f9e6465b 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c | |||
| @@ -200,7 +200,6 @@ static int rdc321x_gpio_probe(struct platform_device *pdev) | |||
| 200 | 200 | ||
| 201 | static struct platform_driver rdc321x_gpio_driver = { | 201 | static struct platform_driver rdc321x_gpio_driver = { |
| 202 | .driver.name = "rdc321x-gpio", | 202 | .driver.name = "rdc321x-gpio", |
| 203 | .driver.owner = THIS_MODULE, | ||
| 204 | .probe = rdc321x_gpio_probe, | 203 | .probe = rdc321x_gpio_probe, |
| 205 | }; | 204 | }; |
| 206 | 205 | ||
diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index a03b38ee2e02..b96990c262a1 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c | |||
| @@ -296,7 +296,6 @@ static int sch311x_gpio_remove(struct platform_device *pdev) | |||
| 296 | 296 | ||
| 297 | static struct platform_driver sch311x_gpio_driver = { | 297 | static struct platform_driver sch311x_gpio_driver = { |
| 298 | .driver.name = DRV_NAME, | 298 | .driver.name = DRV_NAME, |
| 299 | .driver.owner = THIS_MODULE, | ||
| 300 | .probe = sch311x_gpio_probe, | 299 | .probe = sch311x_gpio_probe, |
| 301 | .remove = sch311x_gpio_remove, | 300 | .remove = sch311x_gpio_remove, |
| 302 | }; | 301 | }; |
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 6f7af28b8966..f675132de10e 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
| @@ -68,6 +68,22 @@ static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | |||
| 68 | stmpe_reg_write(stmpe, reg, mask); | 68 | stmpe_reg_write(stmpe, reg, mask); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static int stmpe_gpio_get_direction(struct gpio_chip *chip, | ||
| 72 | unsigned offset) | ||
| 73 | { | ||
| 74 | struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(chip); | ||
| 75 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
| 76 | u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
| 77 | u8 mask = 1 << (offset % 8); | ||
| 78 | int ret; | ||
| 79 | |||
| 80 | ret = stmpe_reg_read(stmpe, reg); | ||
| 81 | if (ret < 0) | ||
| 82 | return ret; | ||
| 83 | |||
| 84 | return !(ret & mask); | ||
| 85 | } | ||
| 86 | |||
| 71 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, | 87 | static int stmpe_gpio_direction_output(struct gpio_chip *chip, |
| 72 | unsigned offset, int val) | 88 | unsigned offset, int val) |
| 73 | { | 89 | { |
| @@ -106,6 +122,7 @@ static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset) | |||
| 106 | static struct gpio_chip template_chip = { | 122 | static struct gpio_chip template_chip = { |
| 107 | .label = "stmpe", | 123 | .label = "stmpe", |
| 108 | .owner = THIS_MODULE, | 124 | .owner = THIS_MODULE, |
| 125 | .get_direction = stmpe_gpio_get_direction, | ||
| 109 | .direction_input = stmpe_gpio_direction_input, | 126 | .direction_input = stmpe_gpio_direction_input, |
| 110 | .get = stmpe_gpio_get, | 127 | .get = stmpe_gpio_get, |
| 111 | .direction_output = stmpe_gpio_direction_output, | 128 | .direction_output = stmpe_gpio_direction_output, |
| @@ -416,7 +433,6 @@ static struct platform_driver stmpe_gpio_driver = { | |||
| 416 | .driver = { | 433 | .driver = { |
| 417 | .suppress_bind_attrs = true, | 434 | .suppress_bind_attrs = true, |
| 418 | .name = "stmpe-gpio", | 435 | .name = "stmpe-gpio", |
| 419 | .owner = THIS_MODULE, | ||
| 420 | }, | 436 | }, |
| 421 | .probe = stmpe_gpio_probe, | 437 | .probe = stmpe_gpio_probe, |
| 422 | }; | 438 | }; |
diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 24b6d643ecdb..537cec7583fc 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c | |||
| @@ -129,7 +129,7 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) | |||
| 129 | 129 | ||
| 130 | static const struct syscon_gpio_data clps711x_mctrl_gpio = { | 130 | static const struct syscon_gpio_data clps711x_mctrl_gpio = { |
| 131 | /* ARM CLPS711X SYSFLG1 Bits 8-10 */ | 131 | /* ARM CLPS711X SYSFLG1 Bits 8-10 */ |
| 132 | .compatible = "cirrus,clps711x-syscon1", | 132 | .compatible = "cirrus,ep7209-syscon1", |
| 133 | .flags = GPIO_SYSCON_FEAT_IN, | 133 | .flags = GPIO_SYSCON_FEAT_IN, |
| 134 | .bit_count = 3, | 134 | .bit_count = 3, |
| 135 | .dat_bit_offset = 0x40 * 8 + 8, | 135 | .dat_bit_offset = 0x40 * 8 + 8, |
| @@ -168,7 +168,7 @@ static const struct syscon_gpio_data keystone_dsp_gpio = { | |||
| 168 | 168 | ||
| 169 | static const struct of_device_id syscon_gpio_ids[] = { | 169 | static const struct of_device_id syscon_gpio_ids[] = { |
| 170 | { | 170 | { |
| 171 | .compatible = "cirrus,clps711x-mctrl-gpio", | 171 | .compatible = "cirrus,ep7209-mctrl-gpio", |
| 172 | .data = &clps711x_mctrl_gpio, | 172 | .data = &clps711x_mctrl_gpio, |
| 173 | }, | 173 | }, |
| 174 | { | 174 | { |
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 2e35ed3abbcf..8b3659352e49 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c | |||
| @@ -343,7 +343,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) | |||
| 343 | 343 | ||
| 344 | static struct platform_driver tc3589x_gpio_driver = { | 344 | static struct platform_driver tc3589x_gpio_driver = { |
| 345 | .driver.name = "tc3589x-gpio", | 345 | .driver.name = "tc3589x-gpio", |
| 346 | .driver.owner = THIS_MODULE, | ||
| 347 | .probe = tc3589x_gpio_probe, | 346 | .probe = tc3589x_gpio_probe, |
| 348 | }; | 347 | }; |
| 349 | 348 | ||
diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 0eaeac8de9de..1c09a19ae10c 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c | |||
| @@ -230,6 +230,12 @@ static const struct of_device_id tps65218_dt_match[] = { | |||
| 230 | }; | 230 | }; |
| 231 | MODULE_DEVICE_TABLE(of, tps65218_dt_match); | 231 | MODULE_DEVICE_TABLE(of, tps65218_dt_match); |
| 232 | 232 | ||
| 233 | static const struct platform_device_id tps65218_gpio_id_table[] = { | ||
| 234 | { "tps65218-gpio", }, | ||
| 235 | { /* sentinel */ } | ||
| 236 | }; | ||
| 237 | MODULE_DEVICE_TABLE(platform, tps65218_gpio_id_table); | ||
| 238 | |||
| 233 | static struct platform_driver tps65218_gpio_driver = { | 239 | static struct platform_driver tps65218_gpio_driver = { |
| 234 | .driver = { | 240 | .driver = { |
| 235 | .name = "tps65218-gpio", | 241 | .name = "tps65218-gpio", |
| @@ -237,6 +243,7 @@ static struct platform_driver tps65218_gpio_driver = { | |||
| 237 | }, | 243 | }, |
| 238 | .probe = tps65218_gpio_probe, | 244 | .probe = tps65218_gpio_probe, |
| 239 | .remove = tps65218_gpio_remove, | 245 | .remove = tps65218_gpio_remove, |
| 246 | .id_table = tps65218_gpio_id_table, | ||
| 240 | }; | 247 | }; |
| 241 | 248 | ||
| 242 | module_platform_driver(tps65218_gpio_driver); | 249 | module_platform_driver(tps65218_gpio_driver); |
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 6b15e68a314f..042b9a20781a 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c | |||
| @@ -131,7 +131,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) | |||
| 131 | 131 | ||
| 132 | static struct platform_driver tps6586x_gpio_driver = { | 132 | static struct platform_driver tps6586x_gpio_driver = { |
| 133 | .driver.name = "tps6586x-gpio", | 133 | .driver.name = "tps6586x-gpio", |
| 134 | .driver.owner = THIS_MODULE, | ||
| 135 | .probe = tps6586x_gpio_probe, | 134 | .probe = tps6586x_gpio_probe, |
| 136 | }; | 135 | }; |
| 137 | 136 | ||
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 0ae6a5a54ea8..e63d7dabf78b 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c | |||
| @@ -184,7 +184,6 @@ skip_init: | |||
| 184 | 184 | ||
| 185 | static struct platform_driver tps65910_gpio_driver = { | 185 | static struct platform_driver tps65910_gpio_driver = { |
| 186 | .driver.name = "tps65910-gpio", | 186 | .driver.name = "tps65910-gpio", |
| 187 | .driver.owner = THIS_MODULE, | ||
| 188 | .probe = tps65910_gpio_probe, | 187 | .probe = tps65910_gpio_probe, |
| 189 | }; | 188 | }; |
| 190 | 189 | ||
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index dec47aafd5cd..e6d1328dddfa 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c | |||
| @@ -440,7 +440,6 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) | |||
| 440 | 440 | ||
| 441 | static struct platform_driver vprbrd_gpio_driver = { | 441 | static struct platform_driver vprbrd_gpio_driver = { |
| 442 | .driver.name = "viperboard-gpio", | 442 | .driver.name = "viperboard-gpio", |
| 443 | .driver.owner = THIS_MODULE, | ||
| 444 | .probe = vprbrd_gpio_probe, | 443 | .probe = vprbrd_gpio_probe, |
| 445 | }; | 444 | }; |
| 446 | 445 | ||
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 41ec7834059a..21f97bcd0062 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c | |||
| @@ -296,7 +296,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev) | |||
| 296 | 296 | ||
| 297 | static struct platform_driver wm831x_gpio_driver = { | 297 | static struct platform_driver wm831x_gpio_driver = { |
| 298 | .driver.name = "wm831x-gpio", | 298 | .driver.name = "wm831x-gpio", |
| 299 | .driver.owner = THIS_MODULE, | ||
| 300 | .probe = wm831x_gpio_probe, | 299 | .probe = wm831x_gpio_probe, |
| 301 | }; | 300 | }; |
| 302 | 301 | ||
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index 07d45a3b205a..e9765707d5c1 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c | |||
| @@ -139,7 +139,6 @@ static int wm8350_gpio_probe(struct platform_device *pdev) | |||
| 139 | 139 | ||
| 140 | static struct platform_driver wm8350_gpio_driver = { | 140 | static struct platform_driver wm8350_gpio_driver = { |
| 141 | .driver.name = "wm8350-gpio", | 141 | .driver.name = "wm8350-gpio", |
| 142 | .driver.owner = THIS_MODULE, | ||
| 143 | .probe = wm8350_gpio_probe, | 142 | .probe = wm8350_gpio_probe, |
| 144 | }; | 143 | }; |
| 145 | 144 | ||
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 744af388c949..2457aac8592e 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c | |||
| @@ -299,7 +299,6 @@ static int wm8994_gpio_probe(struct platform_device *pdev) | |||
| 299 | 299 | ||
| 300 | static struct platform_driver wm8994_gpio_driver = { | 300 | static struct platform_driver wm8994_gpio_driver = { |
| 301 | .driver.name = "wm8994-gpio", | 301 | .driver.name = "wm8994-gpio", |
| 302 | .driver.owner = THIS_MODULE, | ||
| 303 | .probe = wm8994_gpio_probe, | 302 | .probe = wm8994_gpio_probe, |
| 304 | }; | 303 | }; |
| 305 | 304 | ||
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index d0fbb7f99523..14b2a62338ea 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c | |||
| @@ -133,6 +133,53 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | |||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /** | 135 | /** |
| 136 | * xgpio_set_multiple - Write the specified signals of the GPIO device. | ||
| 137 | * @gc: Pointer to gpio_chip device structure. | ||
| 138 | * @mask: Mask of the GPIOS to modify. | ||
| 139 | * @bits: Value to be wrote on each GPIO | ||
| 140 | * | ||
| 141 | * This function writes the specified values into the specified signals of the | ||
| 142 | * GPIO devices. | ||
| 143 | */ | ||
| 144 | static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, | ||
| 145 | unsigned long *bits) | ||
| 146 | { | ||
| 147 | unsigned long flags; | ||
| 148 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 149 | struct xgpio_instance *chip = gpiochip_get_data(gc); | ||
| 150 | int index = xgpio_index(chip, 0); | ||
| 151 | int offset, i; | ||
| 152 | |||
| 153 | spin_lock_irqsave(&chip->gpio_lock[index], flags); | ||
| 154 | |||
| 155 | /* Write to GPIO signals */ | ||
| 156 | for (i = 0; i < gc->ngpio; i++) { | ||
| 157 | if (*mask == 0) | ||
| 158 | break; | ||
| 159 | if (index != xgpio_index(chip, i)) { | ||
| 160 | xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + | ||
| 161 | xgpio_regoffset(chip, i), | ||
| 162 | chip->gpio_state[index]); | ||
| 163 | spin_unlock_irqrestore(&chip->gpio_lock[index], flags); | ||
| 164 | index = xgpio_index(chip, i); | ||
| 165 | spin_lock_irqsave(&chip->gpio_lock[index], flags); | ||
| 166 | } | ||
| 167 | if (__test_and_clear_bit(i, mask)) { | ||
| 168 | offset = xgpio_offset(chip, i); | ||
| 169 | if (test_bit(i, bits)) | ||
| 170 | chip->gpio_state[index] |= BIT(offset); | ||
| 171 | else | ||
| 172 | chip->gpio_state[index] &= ~BIT(offset); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + | ||
| 177 | xgpio_regoffset(chip, i), chip->gpio_state[index]); | ||
| 178 | |||
| 179 | spin_unlock_irqrestore(&chip->gpio_lock[index], flags); | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 136 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. | 183 | * xgpio_dir_in - Set the direction of the specified GPIO signal as input. |
| 137 | * @gc: Pointer to gpio_chip device structure. | 184 | * @gc: Pointer to gpio_chip device structure. |
| 138 | * @gpio: GPIO signal number. | 185 | * @gpio: GPIO signal number. |
| @@ -306,6 +353,7 @@ static int xgpio_probe(struct platform_device *pdev) | |||
| 306 | chip->mmchip.gc.direction_output = xgpio_dir_out; | 353 | chip->mmchip.gc.direction_output = xgpio_dir_out; |
| 307 | chip->mmchip.gc.get = xgpio_get; | 354 | chip->mmchip.gc.get = xgpio_get; |
| 308 | chip->mmchip.gc.set = xgpio_set; | 355 | chip->mmchip.gc.set = xgpio_set; |
| 356 | chip->mmchip.gc.set_multiple = xgpio_set_multiple; | ||
| 309 | 357 | ||
| 310 | chip->mmchip.save_regs = xgpio_save_regs; | 358 | chip->mmchip.save_regs = xgpio_save_regs; |
| 311 | 359 | ||
diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 1a33a19d95b9..4620d050e5a8 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/irqchip/chained_irq.h> | 21 | #include <linux/irqchip/chained_irq.h> |
| 22 | #include <linux/acpi.h> | ||
| 22 | 23 | ||
| 23 | /* | 24 | /* |
| 24 | * XLP GPIO has multiple 32 bit registers for each feature where each register | 25 | * XLP GPIO has multiple 32 bit registers for each feature where each register |
| @@ -299,7 +300,6 @@ static int xlp_gpio_probe(struct platform_device *pdev) | |||
| 299 | struct gpio_chip *gc; | 300 | struct gpio_chip *gc; |
| 300 | struct resource *iores; | 301 | struct resource *iores; |
| 301 | struct xlp_gpio_priv *priv; | 302 | struct xlp_gpio_priv *priv; |
| 302 | const struct of_device_id *of_id; | ||
| 303 | void __iomem *gpio_base; | 303 | void __iomem *gpio_base; |
| 304 | int irq_base, irq, err; | 304 | int irq_base, irq, err; |
| 305 | int ngpio; | 305 | int ngpio; |
| @@ -321,13 +321,26 @@ static int xlp_gpio_probe(struct platform_device *pdev) | |||
| 321 | if (irq < 0) | 321 | if (irq < 0) |
| 322 | return irq; | 322 | return irq; |
| 323 | 323 | ||
| 324 | of_id = of_match_device(xlp_gpio_of_ids, &pdev->dev); | 324 | if (pdev->dev.of_node) { |
| 325 | if (!of_id) { | 325 | const struct of_device_id *of_id; |
| 326 | dev_err(&pdev->dev, "Failed to get soc type!\n"); | ||
| 327 | return -ENODEV; | ||
| 328 | } | ||
| 329 | 326 | ||
| 330 | soc_type = (uintptr_t) of_id->data; | 327 | of_id = of_match_device(xlp_gpio_of_ids, &pdev->dev); |
| 328 | if (!of_id) { | ||
| 329 | dev_err(&pdev->dev, "Unable to match OF ID\n"); | ||
| 330 | return -ENODEV; | ||
| 331 | } | ||
| 332 | soc_type = (uintptr_t) of_id->data; | ||
| 333 | } else { | ||
| 334 | const struct acpi_device_id *acpi_id; | ||
| 335 | |||
| 336 | acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table, | ||
| 337 | &pdev->dev); | ||
| 338 | if (!acpi_id || !acpi_id->driver_data) { | ||
| 339 | dev_err(&pdev->dev, "Unable to match ACPI ID\n"); | ||
| 340 | return -ENODEV; | ||
| 341 | } | ||
| 342 | soc_type = (uintptr_t) acpi_id->driver_data; | ||
| 343 | } | ||
| 331 | 344 | ||
| 332 | switch (soc_type) { | 345 | switch (soc_type) { |
| 333 | case XLP_GPIO_VARIANT_XLP832: | 346 | case XLP_GPIO_VARIANT_XLP832: |
| @@ -388,14 +401,16 @@ static int xlp_gpio_probe(struct platform_device *pdev) | |||
| 388 | gc->get = xlp_gpio_get; | 401 | gc->get = xlp_gpio_get; |
| 389 | 402 | ||
| 390 | spin_lock_init(&priv->lock); | 403 | spin_lock_init(&priv->lock); |
| 391 | /* XLP has fixed IRQ range for GPIO interrupts */ | 404 | |
| 392 | if (soc_type == GPIO_VARIANT_VULCAN) | 405 | /* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */ |
| 393 | irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0); | 406 | if (soc_type != GPIO_VARIANT_VULCAN) { |
| 394 | else | ||
| 395 | irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); | 407 | irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); |
| 396 | if (irq_base < 0) { | 408 | if (irq_base < 0) { |
| 397 | dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); | 409 | dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); |
| 398 | return irq_base; | 410 | return irq_base; |
| 411 | } | ||
| 412 | } else { | ||
| 413 | irq_base = 0; | ||
| 399 | } | 414 | } |
| 400 | 415 | ||
| 401 | err = gpiochip_add_data(gc, priv); | 416 | err = gpiochip_add_data(gc, priv); |
| @@ -423,10 +438,19 @@ out_free_desc: | |||
| 423 | return err; | 438 | return err; |
| 424 | } | 439 | } |
| 425 | 440 | ||
| 441 | #ifdef CONFIG_ACPI | ||
| 442 | static const struct acpi_device_id xlp_gpio_acpi_match[] = { | ||
| 443 | { "BRCM9006", GPIO_VARIANT_VULCAN }, | ||
| 444 | {}, | ||
| 445 | }; | ||
| 446 | MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match); | ||
| 447 | #endif | ||
| 448 | |||
| 426 | static struct platform_driver xlp_gpio_driver = { | 449 | static struct platform_driver xlp_gpio_driver = { |
| 427 | .driver = { | 450 | .driver = { |
| 428 | .name = "xlp-gpio", | 451 | .name = "xlp-gpio", |
| 429 | .of_match_table = xlp_gpio_of_ids, | 452 | .of_match_table = xlp_gpio_of_ids, |
| 453 | .acpi_match_table = ACPI_PTR(xlp_gpio_acpi_match), | ||
| 430 | }, | 454 | }, |
| 431 | .probe = xlp_gpio_probe, | 455 | .probe = xlp_gpio_probe, |
| 432 | }; | 456 | }; |
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 2dc52585e3f2..af514618d7fb 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
| @@ -836,6 +836,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip) | |||
| 836 | } | 836 | } |
| 837 | 837 | ||
| 838 | acpi_gpiochip_request_regions(acpi_gpio); | 838 | acpi_gpiochip_request_regions(acpi_gpio); |
| 839 | acpi_walk_dep_device_list(handle); | ||
| 839 | } | 840 | } |
| 840 | 841 | ||
| 841 | void acpi_gpiochip_remove(struct gpio_chip *chip) | 842 | void acpi_gpiochip_remove(struct gpio_chip *chip) |
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 4aabddb38b59..75e7b3919ea7 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
| @@ -27,38 +27,30 @@ | |||
| 27 | 27 | ||
| 28 | #include "gpiolib.h" | 28 | #include "gpiolib.h" |
| 29 | 29 | ||
| 30 | /* Private data structure for of_gpiochip_find_and_xlate */ | 30 | static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) |
| 31 | struct gg_data { | 31 | { |
| 32 | enum of_gpio_flags *flags; | 32 | return chip->gpiodev->dev.of_node == data; |
| 33 | struct of_phandle_args gpiospec; | 33 | } |
| 34 | 34 | ||
| 35 | struct gpio_desc *out_gpio; | 35 | static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) |
| 36 | }; | 36 | { |
| 37 | return gpiochip_find(np, of_gpiochip_match_node); | ||
| 38 | } | ||
| 37 | 39 | ||
| 38 | /* Private function for resolving node pointer to gpio_chip */ | 40 | static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, |
| 39 | static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) | 41 | struct of_phandle_args *gpiospec, |
| 42 | enum of_gpio_flags *flags) | ||
| 40 | { | 43 | { |
| 41 | struct gg_data *gg_data = data; | ||
| 42 | int ret; | 44 | int ret; |
| 43 | 45 | ||
| 44 | if ((gc->of_node != gg_data->gpiospec.np) || | 46 | if (chip->of_gpio_n_cells != gpiospec->args_count) |
| 45 | (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) || | 47 | return ERR_PTR(-EINVAL); |
| 46 | (!gc->of_xlate)) | 48 | |
| 47 | return false; | 49 | ret = chip->of_xlate(chip, gpiospec, flags); |
| 48 | 50 | if (ret < 0) | |
| 49 | ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags); | 51 | return ERR_PTR(ret); |
| 50 | if (ret < 0) { | 52 | |
| 51 | /* We've found a gpio chip, but the translation failed. | 53 | return gpiochip_get_desc(chip, ret); |
| 52 | * Store translation error in out_gpio. | ||
| 53 | * Return false to keep looking, as more than one gpio chip | ||
| 54 | * could be registered per of-node. | ||
| 55 | */ | ||
| 56 | gg_data->out_gpio = ERR_PTR(ret); | ||
| 57 | return false; | ||
| 58 | } | ||
| 59 | |||
| 60 | gg_data->out_gpio = gpiochip_get_desc(gc, ret); | ||
| 61 | return true; | ||
| 62 | } | 54 | } |
| 63 | 55 | ||
| 64 | /** | 56 | /** |
| @@ -75,34 +67,37 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) | |||
| 75 | struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, | 67 | struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, |
| 76 | const char *propname, int index, enum of_gpio_flags *flags) | 68 | const char *propname, int index, enum of_gpio_flags *flags) |
| 77 | { | 69 | { |
| 78 | /* Return -EPROBE_DEFER to support probe() functions to be called | 70 | struct of_phandle_args gpiospec; |
| 79 | * later when the GPIO actually becomes available | 71 | struct gpio_chip *chip; |
| 80 | */ | 72 | struct gpio_desc *desc; |
| 81 | struct gg_data gg_data = { | ||
| 82 | .flags = flags, | ||
| 83 | .out_gpio = ERR_PTR(-EPROBE_DEFER) | ||
| 84 | }; | ||
| 85 | int ret; | 73 | int ret; |
| 86 | 74 | ||
| 87 | /* .of_xlate might decide to not fill in the flags, so clear it. */ | ||
| 88 | if (flags) | ||
| 89 | *flags = 0; | ||
| 90 | |||
| 91 | ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, | 75 | ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index, |
| 92 | &gg_data.gpiospec); | 76 | &gpiospec); |
| 93 | if (ret) { | 77 | if (ret) { |
| 94 | pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n", | 78 | pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n", |
| 95 | __func__, propname, np->full_name, index); | 79 | __func__, propname, np->full_name, index); |
| 96 | return ERR_PTR(ret); | 80 | return ERR_PTR(ret); |
| 97 | } | 81 | } |
| 98 | 82 | ||
| 99 | gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); | 83 | chip = of_find_gpiochip_by_node(gpiospec.np); |
| 84 | if (!chip) { | ||
| 85 | desc = ERR_PTR(-EPROBE_DEFER); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 89 | desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags); | ||
| 90 | if (IS_ERR(desc)) | ||
| 91 | goto out; | ||
| 100 | 92 | ||
| 101 | of_node_put(gg_data.gpiospec.np); | ||
| 102 | pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n", | 93 | pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n", |
| 103 | __func__, propname, np->full_name, index, | 94 | __func__, propname, np->full_name, index, |
| 104 | PTR_ERR_OR_ZERO(gg_data.out_gpio)); | 95 | PTR_ERR_OR_ZERO(desc)); |
| 105 | return gg_data.out_gpio; | 96 | |
| 97 | out: | ||
| 98 | of_node_put(gpiospec.np); | ||
| 99 | |||
| 100 | return desc; | ||
| 106 | } | 101 | } |
| 107 | 102 | ||
| 108 | int of_get_named_gpio_flags(struct device_node *np, const char *list_name, | 103 | int of_get_named_gpio_flags(struct device_node *np, const char *list_name, |
| @@ -122,6 +117,7 @@ EXPORT_SYMBOL(of_get_named_gpio_flags); | |||
| 122 | /** | 117 | /** |
| 123 | * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API | 118 | * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API |
| 124 | * @np: device node to get GPIO from | 119 | * @np: device node to get GPIO from |
| 120 | * @chip: GPIO chip whose hog is parsed | ||
| 125 | * @name: GPIO line name | 121 | * @name: GPIO line name |
| 126 | * @lflags: gpio_lookup_flags - returned from of_find_gpio() or | 122 | * @lflags: gpio_lookup_flags - returned from of_find_gpio() or |
| 127 | * of_parse_own_gpio() | 123 | * of_parse_own_gpio() |
| @@ -131,19 +127,19 @@ EXPORT_SYMBOL(of_get_named_gpio_flags); | |||
| 131 | * value on the error condition. | 127 | * value on the error condition. |
| 132 | */ | 128 | */ |
| 133 | static struct gpio_desc *of_parse_own_gpio(struct device_node *np, | 129 | static struct gpio_desc *of_parse_own_gpio(struct device_node *np, |
| 130 | struct gpio_chip *chip, | ||
| 134 | const char **name, | 131 | const char **name, |
| 135 | enum gpio_lookup_flags *lflags, | 132 | enum gpio_lookup_flags *lflags, |
| 136 | enum gpiod_flags *dflags) | 133 | enum gpiod_flags *dflags) |
| 137 | { | 134 | { |
| 138 | struct device_node *chip_np; | 135 | struct device_node *chip_np; |
| 139 | enum of_gpio_flags xlate_flags; | 136 | enum of_gpio_flags xlate_flags; |
| 140 | struct gg_data gg_data = { | 137 | struct of_phandle_args gpiospec; |
| 141 | .flags = &xlate_flags, | 138 | struct gpio_desc *desc; |
| 142 | }; | ||
| 143 | u32 tmp; | 139 | u32 tmp; |
| 144 | int i, ret; | 140 | int ret; |
| 145 | 141 | ||
| 146 | chip_np = np->parent; | 142 | chip_np = chip->of_node; |
| 147 | if (!chip_np) | 143 | if (!chip_np) |
| 148 | return ERR_PTR(-EINVAL); | 144 | return ERR_PTR(-EINVAL); |
| 149 | 145 | ||
| @@ -155,25 +151,16 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, | |||
| 155 | if (ret) | 151 | if (ret) |
| 156 | return ERR_PTR(ret); | 152 | return ERR_PTR(ret); |
| 157 | 153 | ||
| 158 | if (tmp > MAX_PHANDLE_ARGS) | 154 | gpiospec.np = chip_np; |
| 159 | return ERR_PTR(-EINVAL); | 155 | gpiospec.args_count = tmp; |
| 160 | 156 | ||
| 161 | gg_data.gpiospec.args_count = tmp; | 157 | ret = of_property_read_u32_array(np, "gpios", gpiospec.args, tmp); |
| 162 | gg_data.gpiospec.np = chip_np; | 158 | if (ret) |
| 163 | for (i = 0; i < tmp; i++) { | 159 | return ERR_PTR(ret); |
| 164 | ret = of_property_read_u32_index(np, "gpios", i, | ||
| 165 | &gg_data.gpiospec.args[i]); | ||
| 166 | if (ret) | ||
| 167 | return ERR_PTR(ret); | ||
| 168 | } | ||
| 169 | 160 | ||
| 170 | gpiochip_find(&gg_data, of_gpiochip_find_and_xlate); | 161 | desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags); |
| 171 | if (!gg_data.out_gpio) { | 162 | if (IS_ERR(desc)) |
| 172 | if (np->parent == np) | 163 | return desc; |
| 173 | return ERR_PTR(-ENXIO); | ||
| 174 | else | ||
| 175 | return ERR_PTR(-EINVAL); | ||
| 176 | } | ||
| 177 | 164 | ||
| 178 | if (xlate_flags & OF_GPIO_ACTIVE_LOW) | 165 | if (xlate_flags & OF_GPIO_ACTIVE_LOW) |
| 179 | *lflags |= GPIO_ACTIVE_LOW; | 166 | *lflags |= GPIO_ACTIVE_LOW; |
| @@ -186,14 +173,14 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, | |||
| 186 | *dflags |= GPIOD_OUT_HIGH; | 173 | *dflags |= GPIOD_OUT_HIGH; |
| 187 | else { | 174 | else { |
| 188 | pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n", | 175 | pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n", |
| 189 | desc_to_gpio(gg_data.out_gpio), np->name); | 176 | desc_to_gpio(desc), np->name); |
| 190 | return ERR_PTR(-EINVAL); | 177 | return ERR_PTR(-EINVAL); |
| 191 | } | 178 | } |
| 192 | 179 | ||
| 193 | if (name && of_property_read_string(np, "line-name", name)) | 180 | if (name && of_property_read_string(np, "line-name", name)) |
| 194 | *name = np->name; | 181 | *name = np->name; |
| 195 | 182 | ||
| 196 | return gg_data.out_gpio; | 183 | return desc; |
| 197 | } | 184 | } |
| 198 | 185 | ||
| 199 | /** | 186 | /** |
| @@ -262,7 +249,7 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) | |||
| 262 | if (!of_property_read_bool(np, "gpio-hog")) | 249 | if (!of_property_read_bool(np, "gpio-hog")) |
| 263 | continue; | 250 | continue; |
| 264 | 251 | ||
| 265 | desc = of_parse_own_gpio(np, &name, &lflags, &dflags); | 252 | desc = of_parse_own_gpio(np, chip, &name, &lflags, &dflags); |
| 266 | if (IS_ERR(desc)) | 253 | if (IS_ERR(desc)) |
| 267 | continue; | 254 | continue; |
| 268 | 255 | ||
| @@ -410,6 +397,7 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
| 410 | break; | 397 | break; |
| 411 | 398 | ||
| 412 | pctldev = of_pinctrl_get(pinspec.np); | 399 | pctldev = of_pinctrl_get(pinspec.np); |
| 400 | of_node_put(pinspec.np); | ||
| 413 | if (!pctldev) | 401 | if (!pctldev) |
| 414 | return -EPROBE_DEFER; | 402 | return -EPROBE_DEFER; |
| 415 | 403 | ||
| @@ -487,6 +475,9 @@ int of_gpiochip_add(struct gpio_chip *chip) | |||
| 487 | chip->of_xlate = of_gpio_simple_xlate; | 475 | chip->of_xlate = of_gpio_simple_xlate; |
| 488 | } | 476 | } |
| 489 | 477 | ||
| 478 | if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) | ||
| 479 | return -EINVAL; | ||
| 480 | |||
| 490 | status = of_gpiochip_add_pin_range(chip); | 481 | status = of_gpiochip_add_pin_range(chip); |
| 491 | if (status) | 482 | if (status) |
| 492 | return status; | 483 | return status; |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index be74bd370f1f..53ff25ac66d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -16,11 +16,14 @@ | |||
| 16 | #include <linux/gpio/driver.h> | 16 | #include <linux/gpio/driver.h> |
| 17 | #include <linux/gpio/machine.h> | 17 | #include <linux/gpio/machine.h> |
| 18 | #include <linux/pinctrl/consumer.h> | 18 | #include <linux/pinctrl/consumer.h> |
| 19 | #include <linux/idr.h> | ||
| 20 | #include <linux/cdev.h> | 19 | #include <linux/cdev.h> |
| 21 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
| 22 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
| 23 | #include <linux/compat.h> | 22 | #include <linux/compat.h> |
| 23 | #include <linux/anon_inodes.h> | ||
| 24 | #include <linux/kfifo.h> | ||
| 25 | #include <linux/poll.h> | ||
| 26 | #include <linux/timekeeping.h> | ||
| 24 | #include <uapi/linux/gpio.h> | 27 | #include <uapi/linux/gpio.h> |
| 25 | 28 | ||
| 26 | #include "gpiolib.h" | 29 | #include "gpiolib.h" |
| @@ -310,6 +313,497 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) | |||
| 310 | return 0; | 313 | return 0; |
| 311 | } | 314 | } |
| 312 | 315 | ||
| 316 | /* | ||
| 317 | * GPIO line handle management | ||
| 318 | */ | ||
| 319 | |||
| 320 | /** | ||
| 321 | * struct linehandle_state - contains the state of a userspace handle | ||
| 322 | * @gdev: the GPIO device the handle pertains to | ||
| 323 | * @label: consumer label used to tag descriptors | ||
| 324 | * @descs: the GPIO descriptors held by this handle | ||
| 325 | * @numdescs: the number of descriptors held in the descs array | ||
| 326 | */ | ||
| 327 | struct linehandle_state { | ||
| 328 | struct gpio_device *gdev; | ||
| 329 | const char *label; | ||
| 330 | struct gpio_desc *descs[GPIOHANDLES_MAX]; | ||
| 331 | u32 numdescs; | ||
| 332 | }; | ||
| 333 | |||
| 334 | static long linehandle_ioctl(struct file *filep, unsigned int cmd, | ||
| 335 | unsigned long arg) | ||
| 336 | { | ||
| 337 | struct linehandle_state *lh = filep->private_data; | ||
| 338 | void __user *ip = (void __user *)arg; | ||
| 339 | struct gpiohandle_data ghd; | ||
| 340 | int i; | ||
| 341 | |||
| 342 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | ||
| 343 | int val; | ||
| 344 | |||
| 345 | /* TODO: check if descriptors are really input */ | ||
| 346 | for (i = 0; i < lh->numdescs; i++) { | ||
| 347 | val = gpiod_get_value_cansleep(lh->descs[i]); | ||
| 348 | if (val < 0) | ||
| 349 | return val; | ||
| 350 | ghd.values[i] = val; | ||
| 351 | } | ||
| 352 | |||
| 353 | if (copy_to_user(ip, &ghd, sizeof(ghd))) | ||
| 354 | return -EFAULT; | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) { | ||
| 358 | int vals[GPIOHANDLES_MAX]; | ||
| 359 | |||
| 360 | /* TODO: check if descriptors are really output */ | ||
| 361 | if (copy_from_user(&ghd, ip, sizeof(ghd))) | ||
| 362 | return -EFAULT; | ||
| 363 | |||
| 364 | /* Clamp all values to [0,1] */ | ||
| 365 | for (i = 0; i < lh->numdescs; i++) | ||
| 366 | vals[i] = !!ghd.values[i]; | ||
| 367 | |||
| 368 | /* Reuse the array setting function */ | ||
| 369 | gpiod_set_array_value_complex(false, | ||
| 370 | true, | ||
| 371 | lh->numdescs, | ||
| 372 | lh->descs, | ||
| 373 | vals); | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | return -EINVAL; | ||
| 377 | } | ||
| 378 | |||
| 379 | #ifdef CONFIG_COMPAT | ||
| 380 | static long linehandle_ioctl_compat(struct file *filep, unsigned int cmd, | ||
| 381 | unsigned long arg) | ||
| 382 | { | ||
| 383 | return linehandle_ioctl(filep, cmd, (unsigned long)compat_ptr(arg)); | ||
| 384 | } | ||
| 385 | #endif | ||
| 386 | |||
| 387 | static int linehandle_release(struct inode *inode, struct file *filep) | ||
| 388 | { | ||
| 389 | struct linehandle_state *lh = filep->private_data; | ||
| 390 | struct gpio_device *gdev = lh->gdev; | ||
| 391 | int i; | ||
| 392 | |||
| 393 | for (i = 0; i < lh->numdescs; i++) | ||
| 394 | gpiod_free(lh->descs[i]); | ||
| 395 | kfree(lh->label); | ||
| 396 | kfree(lh); | ||
| 397 | put_device(&gdev->dev); | ||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | static const struct file_operations linehandle_fileops = { | ||
| 402 | .release = linehandle_release, | ||
| 403 | .owner = THIS_MODULE, | ||
| 404 | .llseek = noop_llseek, | ||
| 405 | .unlocked_ioctl = linehandle_ioctl, | ||
| 406 | #ifdef CONFIG_COMPAT | ||
| 407 | .compat_ioctl = linehandle_ioctl_compat, | ||
| 408 | #endif | ||
| 409 | }; | ||
| 410 | |||
| 411 | static int linehandle_create(struct gpio_device *gdev, void __user *ip) | ||
| 412 | { | ||
| 413 | struct gpiohandle_request handlereq; | ||
| 414 | struct linehandle_state *lh; | ||
| 415 | int fd, i, ret; | ||
| 416 | |||
| 417 | if (copy_from_user(&handlereq, ip, sizeof(handlereq))) | ||
| 418 | return -EFAULT; | ||
| 419 | if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX)) | ||
| 420 | return -EINVAL; | ||
| 421 | |||
| 422 | lh = kzalloc(sizeof(*lh), GFP_KERNEL); | ||
| 423 | if (!lh) | ||
| 424 | return -ENOMEM; | ||
| 425 | lh->gdev = gdev; | ||
| 426 | get_device(&gdev->dev); | ||
| 427 | |||
| 428 | /* Make sure this is terminated */ | ||
| 429 | handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0'; | ||
| 430 | if (strlen(handlereq.consumer_label)) { | ||
| 431 | lh->label = kstrdup(handlereq.consumer_label, | ||
| 432 | GFP_KERNEL); | ||
| 433 | if (!lh->label) { | ||
| 434 | ret = -ENOMEM; | ||
| 435 | goto out_free_lh; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | /* Request each GPIO */ | ||
| 440 | for (i = 0; i < handlereq.lines; i++) { | ||
| 441 | u32 offset = handlereq.lineoffsets[i]; | ||
| 442 | u32 lflags = handlereq.flags; | ||
| 443 | struct gpio_desc *desc; | ||
| 444 | |||
| 445 | desc = &gdev->descs[offset]; | ||
| 446 | ret = gpiod_request(desc, lh->label); | ||
| 447 | if (ret) | ||
| 448 | goto out_free_descs; | ||
| 449 | lh->descs[i] = desc; | ||
| 450 | |||
| 451 | if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | ||
| 452 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
| 453 | if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) | ||
| 454 | set_bit(FLAG_OPEN_DRAIN, &desc->flags); | ||
| 455 | if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE) | ||
| 456 | set_bit(FLAG_OPEN_SOURCE, &desc->flags); | ||
| 457 | |||
| 458 | /* | ||
| 459 | * Lines have to be requested explicitly for input | ||
| 460 | * or output, else the line will be treated "as is". | ||
| 461 | */ | ||
| 462 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { | ||
| 463 | int val = !!handlereq.default_values[i]; | ||
| 464 | |||
| 465 | ret = gpiod_direction_output(desc, val); | ||
| 466 | if (ret) | ||
| 467 | goto out_free_descs; | ||
| 468 | } else if (lflags & GPIOHANDLE_REQUEST_INPUT) { | ||
| 469 | ret = gpiod_direction_input(desc); | ||
| 470 | if (ret) | ||
| 471 | goto out_free_descs; | ||
| 472 | } | ||
| 473 | dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", | ||
| 474 | offset); | ||
| 475 | } | ||
| 476 | /* Let i point at the last handle */ | ||
| 477 | i--; | ||
| 478 | lh->numdescs = handlereq.lines; | ||
| 479 | |||
| 480 | fd = anon_inode_getfd("gpio-linehandle", | ||
| 481 | &linehandle_fileops, | ||
| 482 | lh, | ||
| 483 | O_RDONLY | O_CLOEXEC); | ||
| 484 | if (fd < 0) { | ||
| 485 | ret = fd; | ||
| 486 | goto out_free_descs; | ||
| 487 | } | ||
| 488 | |||
| 489 | handlereq.fd = fd; | ||
| 490 | if (copy_to_user(ip, &handlereq, sizeof(handlereq))) { | ||
| 491 | ret = -EFAULT; | ||
| 492 | goto out_free_descs; | ||
| 493 | } | ||
| 494 | |||
| 495 | dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", | ||
| 496 | lh->numdescs); | ||
| 497 | |||
| 498 | return 0; | ||
| 499 | |||
| 500 | out_free_descs: | ||
| 501 | for (; i >= 0; i--) | ||
| 502 | gpiod_free(lh->descs[i]); | ||
| 503 | kfree(lh->label); | ||
| 504 | out_free_lh: | ||
| 505 | kfree(lh); | ||
| 506 | put_device(&gdev->dev); | ||
| 507 | return ret; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* | ||
| 511 | * GPIO line event management | ||
| 512 | */ | ||
| 513 | |||
| 514 | /** | ||
| 515 | * struct lineevent_state - contains the state of a userspace event | ||
| 516 | * @gdev: the GPIO device the event pertains to | ||
| 517 | * @label: consumer label used to tag descriptors | ||
| 518 | * @desc: the GPIO descriptor held by this event | ||
| 519 | * @eflags: the event flags this line was requested with | ||
| 520 | * @irq: the interrupt that trigger in response to events on this GPIO | ||
| 521 | * @wait: wait queue that handles blocking reads of events | ||
| 522 | * @events: KFIFO for the GPIO events | ||
| 523 | * @read_lock: mutex lock to protect reads from colliding with adding | ||
| 524 | * new events to the FIFO | ||
| 525 | */ | ||
| 526 | struct lineevent_state { | ||
| 527 | struct gpio_device *gdev; | ||
| 528 | const char *label; | ||
| 529 | struct gpio_desc *desc; | ||
| 530 | u32 eflags; | ||
| 531 | int irq; | ||
| 532 | wait_queue_head_t wait; | ||
| 533 | DECLARE_KFIFO(events, struct gpioevent_data, 16); | ||
| 534 | struct mutex read_lock; | ||
| 535 | }; | ||
| 536 | |||
| 537 | static unsigned int lineevent_poll(struct file *filep, | ||
| 538 | struct poll_table_struct *wait) | ||
| 539 | { | ||
| 540 | struct lineevent_state *le = filep->private_data; | ||
| 541 | unsigned int events = 0; | ||
| 542 | |||
| 543 | poll_wait(filep, &le->wait, wait); | ||
| 544 | |||
| 545 | if (!kfifo_is_empty(&le->events)) | ||
| 546 | events = POLLIN | POLLRDNORM; | ||
| 547 | |||
| 548 | return events; | ||
| 549 | } | ||
| 550 | |||
| 551 | |||
| 552 | static ssize_t lineevent_read(struct file *filep, | ||
| 553 | char __user *buf, | ||
| 554 | size_t count, | ||
| 555 | loff_t *f_ps) | ||
| 556 | { | ||
| 557 | struct lineevent_state *le = filep->private_data; | ||
| 558 | unsigned int copied; | ||
| 559 | int ret; | ||
| 560 | |||
| 561 | if (count < sizeof(struct gpioevent_data)) | ||
| 562 | return -EINVAL; | ||
| 563 | |||
| 564 | do { | ||
| 565 | if (kfifo_is_empty(&le->events)) { | ||
| 566 | if (filep->f_flags & O_NONBLOCK) | ||
| 567 | return -EAGAIN; | ||
| 568 | |||
| 569 | ret = wait_event_interruptible(le->wait, | ||
| 570 | !kfifo_is_empty(&le->events)); | ||
| 571 | if (ret) | ||
| 572 | return ret; | ||
| 573 | } | ||
| 574 | |||
| 575 | if (mutex_lock_interruptible(&le->read_lock)) | ||
| 576 | return -ERESTARTSYS; | ||
| 577 | ret = kfifo_to_user(&le->events, buf, count, &copied); | ||
| 578 | mutex_unlock(&le->read_lock); | ||
| 579 | |||
| 580 | if (ret) | ||
| 581 | return ret; | ||
| 582 | |||
| 583 | /* | ||
| 584 | * If we couldn't read anything from the fifo (a different | ||
| 585 | * thread might have been faster) we either return -EAGAIN if | ||
| 586 | * the file descriptor is non-blocking, otherwise we go back to | ||
| 587 | * sleep and wait for more data to arrive. | ||
| 588 | */ | ||
| 589 | if (copied == 0 && (filep->f_flags & O_NONBLOCK)) | ||
| 590 | return -EAGAIN; | ||
| 591 | |||
| 592 | } while (copied == 0); | ||
| 593 | |||
| 594 | return copied; | ||
| 595 | } | ||
| 596 | |||
| 597 | static int lineevent_release(struct inode *inode, struct file *filep) | ||
| 598 | { | ||
| 599 | struct lineevent_state *le = filep->private_data; | ||
| 600 | struct gpio_device *gdev = le->gdev; | ||
| 601 | |||
| 602 | free_irq(le->irq, le); | ||
| 603 | gpiod_free(le->desc); | ||
| 604 | kfree(le->label); | ||
| 605 | kfree(le); | ||
| 606 | put_device(&gdev->dev); | ||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | static long lineevent_ioctl(struct file *filep, unsigned int cmd, | ||
| 611 | unsigned long arg) | ||
| 612 | { | ||
| 613 | struct lineevent_state *le = filep->private_data; | ||
| 614 | void __user *ip = (void __user *)arg; | ||
| 615 | struct gpiohandle_data ghd; | ||
| 616 | |||
| 617 | /* | ||
| 618 | * We can get the value for an event line but not set it, | ||
| 619 | * because it is input by definition. | ||
| 620 | */ | ||
| 621 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | ||
| 622 | int val; | ||
| 623 | |||
| 624 | val = gpiod_get_value_cansleep(le->desc); | ||
| 625 | if (val < 0) | ||
| 626 | return val; | ||
| 627 | ghd.values[0] = val; | ||
| 628 | |||
| 629 | if (copy_to_user(ip, &ghd, sizeof(ghd))) | ||
| 630 | return -EFAULT; | ||
| 631 | |||
| 632 | return 0; | ||
| 633 | } | ||
| 634 | return -EINVAL; | ||
| 635 | } | ||
| 636 | |||
| 637 | #ifdef CONFIG_COMPAT | ||
| 638 | static long lineevent_ioctl_compat(struct file *filep, unsigned int cmd, | ||
| 639 | unsigned long arg) | ||
| 640 | { | ||
| 641 | return lineevent_ioctl(filep, cmd, (unsigned long)compat_ptr(arg)); | ||
| 642 | } | ||
| 643 | #endif | ||
| 644 | |||
| 645 | static const struct file_operations lineevent_fileops = { | ||
| 646 | .release = lineevent_release, | ||
| 647 | .read = lineevent_read, | ||
| 648 | .poll = lineevent_poll, | ||
| 649 | .owner = THIS_MODULE, | ||
| 650 | .llseek = noop_llseek, | ||
| 651 | .unlocked_ioctl = lineevent_ioctl, | ||
| 652 | #ifdef CONFIG_COMPAT | ||
| 653 | .compat_ioctl = lineevent_ioctl_compat, | ||
| 654 | #endif | ||
| 655 | }; | ||
| 656 | |||
| 657 | static irqreturn_t lineevent_irq_thread(int irq, void *p) | ||
| 658 | { | ||
| 659 | struct lineevent_state *le = p; | ||
| 660 | struct gpioevent_data ge; | ||
| 661 | int ret; | ||
| 662 | |||
| 663 | ge.timestamp = ktime_get_real_ns(); | ||
| 664 | |||
| 665 | if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) { | ||
| 666 | int level = gpiod_get_value_cansleep(le->desc); | ||
| 667 | |||
| 668 | if (level) | ||
| 669 | /* Emit low-to-high event */ | ||
| 670 | ge.id = GPIOEVENT_EVENT_RISING_EDGE; | ||
| 671 | else | ||
| 672 | /* Emit high-to-low event */ | ||
| 673 | ge.id = GPIOEVENT_EVENT_FALLING_EDGE; | ||
| 674 | } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) { | ||
| 675 | /* Emit low-to-high event */ | ||
| 676 | ge.id = GPIOEVENT_EVENT_RISING_EDGE; | ||
| 677 | } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { | ||
| 678 | /* Emit high-to-low event */ | ||
| 679 | ge.id = GPIOEVENT_EVENT_FALLING_EDGE; | ||
| 680 | } else { | ||
| 681 | return IRQ_NONE; | ||
| 682 | } | ||
| 683 | |||
| 684 | ret = kfifo_put(&le->events, ge); | ||
| 685 | if (ret != 0) | ||
| 686 | wake_up_poll(&le->wait, POLLIN); | ||
| 687 | |||
| 688 | return IRQ_HANDLED; | ||
| 689 | } | ||
| 690 | |||
| 691 | static int lineevent_create(struct gpio_device *gdev, void __user *ip) | ||
| 692 | { | ||
| 693 | struct gpioevent_request eventreq; | ||
| 694 | struct lineevent_state *le; | ||
| 695 | struct gpio_desc *desc; | ||
| 696 | u32 offset; | ||
| 697 | u32 lflags; | ||
| 698 | u32 eflags; | ||
| 699 | int fd; | ||
| 700 | int ret; | ||
| 701 | int irqflags = 0; | ||
| 702 | |||
| 703 | if (copy_from_user(&eventreq, ip, sizeof(eventreq))) | ||
| 704 | return -EFAULT; | ||
| 705 | |||
| 706 | le = kzalloc(sizeof(*le), GFP_KERNEL); | ||
| 707 | if (!le) | ||
| 708 | return -ENOMEM; | ||
| 709 | le->gdev = gdev; | ||
| 710 | get_device(&gdev->dev); | ||
| 711 | |||
| 712 | /* Make sure this is terminated */ | ||
| 713 | eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0'; | ||
| 714 | if (strlen(eventreq.consumer_label)) { | ||
| 715 | le->label = kstrdup(eventreq.consumer_label, | ||
| 716 | GFP_KERNEL); | ||
| 717 | if (!le->label) { | ||
| 718 | ret = -ENOMEM; | ||
| 719 | goto out_free_le; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | offset = eventreq.lineoffset; | ||
| 724 | lflags = eventreq.handleflags; | ||
| 725 | eflags = eventreq.eventflags; | ||
| 726 | |||
| 727 | /* This is just wrong: we don't look for events on output lines */ | ||
| 728 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { | ||
| 729 | ret = -EINVAL; | ||
| 730 | goto out_free_label; | ||
| 731 | } | ||
| 732 | |||
| 733 | desc = &gdev->descs[offset]; | ||
| 734 | ret = gpiod_request(desc, le->label); | ||
| 735 | if (ret) | ||
| 736 | goto out_free_desc; | ||
| 737 | le->desc = desc; | ||
| 738 | le->eflags = eflags; | ||
| 739 | |||
| 740 | if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | ||
| 741 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | ||
| 742 | if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) | ||
| 743 | set_bit(FLAG_OPEN_DRAIN, &desc->flags); | ||
| 744 | if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE) | ||
| 745 | set_bit(FLAG_OPEN_SOURCE, &desc->flags); | ||
| 746 | |||
| 747 | ret = gpiod_direction_input(desc); | ||
| 748 | if (ret) | ||
| 749 | goto out_free_desc; | ||
| 750 | |||
| 751 | le->irq = gpiod_to_irq(desc); | ||
| 752 | if (le->irq <= 0) { | ||
| 753 | ret = -ENODEV; | ||
| 754 | goto out_free_desc; | ||
| 755 | } | ||
| 756 | |||
| 757 | if (eflags & GPIOEVENT_REQUEST_RISING_EDGE) | ||
| 758 | irqflags |= IRQF_TRIGGER_RISING; | ||
| 759 | if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE) | ||
| 760 | irqflags |= IRQF_TRIGGER_FALLING; | ||
| 761 | irqflags |= IRQF_ONESHOT; | ||
| 762 | irqflags |= IRQF_SHARED; | ||
| 763 | |||
| 764 | INIT_KFIFO(le->events); | ||
| 765 | init_waitqueue_head(&le->wait); | ||
| 766 | mutex_init(&le->read_lock); | ||
| 767 | |||
| 768 | /* Request a thread to read the events */ | ||
| 769 | ret = request_threaded_irq(le->irq, | ||
| 770 | NULL, | ||
| 771 | lineevent_irq_thread, | ||
| 772 | irqflags, | ||
| 773 | le->label, | ||
| 774 | le); | ||
| 775 | if (ret) | ||
| 776 | goto out_free_desc; | ||
| 777 | |||
| 778 | fd = anon_inode_getfd("gpio-event", | ||
| 779 | &lineevent_fileops, | ||
| 780 | le, | ||
| 781 | O_RDONLY | O_CLOEXEC); | ||
| 782 | if (fd < 0) { | ||
| 783 | ret = fd; | ||
| 784 | goto out_free_irq; | ||
| 785 | } | ||
| 786 | |||
| 787 | eventreq.fd = fd; | ||
| 788 | if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { | ||
| 789 | ret = -EFAULT; | ||
| 790 | goto out_free_irq; | ||
| 791 | } | ||
| 792 | |||
| 793 | return 0; | ||
| 794 | |||
| 795 | out_free_irq: | ||
| 796 | free_irq(le->irq, le); | ||
| 797 | out_free_desc: | ||
| 798 | gpiod_free(le->desc); | ||
| 799 | out_free_label: | ||
| 800 | kfree(le->label); | ||
| 801 | out_free_le: | ||
| 802 | kfree(le); | ||
| 803 | put_device(&gdev->dev); | ||
| 804 | return ret; | ||
| 805 | } | ||
| 806 | |||
| 313 | /** | 807 | /** |
| 314 | * gpio_ioctl() - ioctl handler for the GPIO chardev | 808 | * gpio_ioctl() - ioctl handler for the GPIO chardev |
| 315 | */ | 809 | */ |
| @@ -385,6 +879,10 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 385 | if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) | 879 | if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) |
| 386 | return -EFAULT; | 880 | return -EFAULT; |
| 387 | return 0; | 881 | return 0; |
| 882 | } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { | ||
| 883 | return linehandle_create(gdev, ip); | ||
| 884 | } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { | ||
| 885 | return lineevent_create(gdev, ip); | ||
| 388 | } | 886 | } |
| 389 | return -EINVAL; | 887 | return -EINVAL; |
| 390 | } | 888 | } |
| @@ -548,13 +1046,14 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) | |||
| 548 | if (chip->parent) { | 1046 | if (chip->parent) { |
| 549 | gdev->dev.parent = chip->parent; | 1047 | gdev->dev.parent = chip->parent; |
| 550 | gdev->dev.of_node = chip->parent->of_node; | 1048 | gdev->dev.of_node = chip->parent->of_node; |
| 551 | } else { | 1049 | } |
| 1050 | |||
| 552 | #ifdef CONFIG_OF_GPIO | 1051 | #ifdef CONFIG_OF_GPIO |
| 553 | /* If the gpiochip has an assigned OF node this takes precedence */ | 1052 | /* If the gpiochip has an assigned OF node this takes precedence */ |
| 554 | if (chip->of_node) | 1053 | if (chip->of_node) |
| 555 | gdev->dev.of_node = chip->of_node; | 1054 | gdev->dev.of_node = chip->of_node; |
| 556 | #endif | 1055 | #endif |
| 557 | } | 1056 | |
| 558 | gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); | 1057 | gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); |
| 559 | if (gdev->id < 0) { | 1058 | if (gdev->id < 0) { |
| 560 | status = gdev->id; | 1059 | status = gdev->id; |
| @@ -2333,7 +2832,7 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, | |||
| 2333 | 2832 | ||
| 2334 | desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx, | 2833 | desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx, |
| 2335 | &of_flags); | 2834 | &of_flags); |
| 2336 | if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) | 2835 | if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT)) |
| 2337 | break; | 2836 | break; |
| 2338 | } | 2837 | } |
| 2339 | 2838 | ||
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index a13f2b6f6fc0..b9375544dff0 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c | |||
| @@ -1724,9 +1724,9 @@ static int pinmux_xway_probe(struct platform_device *pdev) | |||
| 1724 | } | 1724 | } |
| 1725 | xway_pctrl_desc.pins = xway_info.pads; | 1725 | xway_pctrl_desc.pins = xway_info.pads; |
| 1726 | 1726 | ||
| 1727 | /* load the gpio chip */ | 1727 | /* register the gpio chip */ |
| 1728 | xway_chip.parent = &pdev->dev; | 1728 | xway_chip.parent = &pdev->dev; |
| 1729 | ret = gpiochip_add(&xway_chip); | 1729 | ret = devm_gpiochip_add_data(&pdev->dev, &xway_chip, NULL); |
| 1730 | if (ret) { | 1730 | if (ret) { |
| 1731 | dev_err(&pdev->dev, "Failed to register gpio chip\n"); | 1731 | dev_err(&pdev->dev, "Failed to register gpio chip\n"); |
| 1732 | return ret; | 1732 | return ret; |
| @@ -1749,7 +1749,6 @@ static int pinmux_xway_probe(struct platform_device *pdev) | |||
| 1749 | /* register with the generic lantiq layer */ | 1749 | /* register with the generic lantiq layer */ |
| 1750 | ret = ltq_pinctrl_register(pdev, &xway_info); | 1750 | ret = ltq_pinctrl_register(pdev, &xway_info); |
| 1751 | if (ret) { | 1751 | if (ret) { |
| 1752 | gpiochip_remove(&xway_chip); | ||
| 1753 | dev_err(&pdev->dev, "Failed to register pinctrl driver\n"); | 1752 | dev_err(&pdev->dev, "Failed to register pinctrl driver\n"); |
| 1754 | return ret; | 1753 | return ret; |
| 1755 | } | 1754 | } |
diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h index d0a3cac72250..333d3544c964 100644 --- a/include/uapi/linux/gpio.h +++ b/include/uapi/linux/gpio.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * <linux/gpio.h> - userspace ABI for the GPIO character devices | 2 | * <linux/gpio.h> - userspace ABI for the GPIO character devices |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2015 Linus Walleij | 4 | * Copyright (C) 2016 Linus Walleij |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License version 2 as published by | 7 | * under the terms of the GNU General Public License version 2 as published by |
| @@ -26,8 +26,8 @@ struct gpiochip_info { | |||
| 26 | __u32 lines; | 26 | __u32 lines; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | /* Line is in use by the kernel */ | 29 | /* Informational flags */ |
| 30 | #define GPIOLINE_FLAG_KERNEL (1UL << 0) | 30 | #define GPIOLINE_FLAG_KERNEL (1UL << 0) /* Line used by the kernel */ |
| 31 | #define GPIOLINE_FLAG_IS_OUT (1UL << 1) | 31 | #define GPIOLINE_FLAG_IS_OUT (1UL << 1) |
| 32 | #define GPIOLINE_FLAG_ACTIVE_LOW (1UL << 2) | 32 | #define GPIOLINE_FLAG_ACTIVE_LOW (1UL << 2) |
| 33 | #define GPIOLINE_FLAG_OPEN_DRAIN (1UL << 3) | 33 | #define GPIOLINE_FLAG_OPEN_DRAIN (1UL << 3) |
| @@ -52,7 +52,106 @@ struct gpioline_info { | |||
| 52 | char consumer[32]; | 52 | char consumer[32]; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* Maximum number of requested handles */ | ||
| 56 | #define GPIOHANDLES_MAX 64 | ||
| 57 | |||
| 58 | /* Linerequest flags */ | ||
| 59 | #define GPIOHANDLE_REQUEST_INPUT (1UL << 0) | ||
| 60 | #define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) | ||
| 61 | #define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2) | ||
| 62 | #define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3) | ||
| 63 | #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4) | ||
| 64 | |||
| 65 | /** | ||
| 66 | * struct gpiohandle_request - Information about a GPIO handle request | ||
| 67 | * @lineoffsets: an array desired lines, specified by offset index for the | ||
| 68 | * associated GPIO device | ||
| 69 | * @flags: desired flags for the desired GPIO lines, such as | ||
| 70 | * GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed | ||
| 71 | * together. Note that even if multiple lines are requested, the same flags | ||
| 72 | * must be applicable to all of them, if you want lines with individual | ||
| 73 | * flags set, request them one by one. It is possible to select | ||
| 74 | * a batch of input or output lines, but they must all have the same | ||
| 75 | * characteristics, i.e. all inputs or all outputs, all active low etc | ||
| 76 | * @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set for a requested | ||
| 77 | * line, this specifies the default output value, should be 0 (low) or | ||
| 78 | * 1 (high), anything else than 0 or 1 will be interpreted as 1 (high) | ||
| 79 | * @consumer_label: a desired consumer label for the selected GPIO line(s) | ||
| 80 | * such as "my-bitbanged-relay" | ||
| 81 | * @lines: number of lines requested in this request, i.e. the number of | ||
| 82 | * valid fields in the above arrays, set to 1 to request a single line | ||
| 83 | * @fd: if successful this field will contain a valid anonymous file handle | ||
| 84 | * after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value | ||
| 85 | * means error | ||
| 86 | */ | ||
| 87 | struct gpiohandle_request { | ||
| 88 | __u32 lineoffsets[GPIOHANDLES_MAX]; | ||
| 89 | __u32 flags; | ||
| 90 | __u8 default_values[GPIOHANDLES_MAX]; | ||
| 91 | char consumer_label[32]; | ||
| 92 | __u32 lines; | ||
| 93 | int fd; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /** | ||
| 97 | * struct gpiohandle_data - Information of values on a GPIO handle | ||
| 98 | * @values: when getting the state of lines this contains the current | ||
| 99 | * state of a line, when setting the state of lines these should contain | ||
| 100 | * the desired target state | ||
| 101 | */ | ||
| 102 | struct gpiohandle_data { | ||
| 103 | __u8 values[GPIOHANDLES_MAX]; | ||
| 104 | }; | ||
| 105 | |||
| 106 | #define GPIOHANDLE_GET_LINE_VALUES_IOCTL _IOWR(0xB4, 0x08, struct gpiohandle_data) | ||
| 107 | #define GPIOHANDLE_SET_LINE_VALUES_IOCTL _IOWR(0xB4, 0x09, struct gpiohandle_data) | ||
| 108 | |||
| 109 | /* Eventrequest flags */ | ||
| 110 | #define GPIOEVENT_REQUEST_RISING_EDGE (1UL << 0) | ||
| 111 | #define GPIOEVENT_REQUEST_FALLING_EDGE (1UL << 1) | ||
| 112 | #define GPIOEVENT_REQUEST_BOTH_EDGES ((1UL << 0) | (1UL << 1)) | ||
| 113 | |||
| 114 | /** | ||
| 115 | * struct gpioevent_request - Information about a GPIO event request | ||
| 116 | * @lineoffset: the desired line to subscribe to events from, specified by | ||
| 117 | * offset index for the associated GPIO device | ||
| 118 | * @handleflags: desired handle flags for the desired GPIO line, such as | ||
| 119 | * GPIOHANDLE_REQUEST_ACTIVE_LOW or GPIOHANDLE_REQUEST_OPEN_DRAIN | ||
| 120 | * @eventflags: desired flags for the desired GPIO event line, such as | ||
| 121 | * GPIOEVENT_REQUEST_RISING_EDGE or GPIOEVENT_REQUEST_FALLING_EDGE | ||
| 122 | * @consumer_label: a desired consumer label for the selected GPIO line(s) | ||
| 123 | * such as "my-listener" | ||
| 124 | * @fd: if successful this field will contain a valid anonymous file handle | ||
| 125 | * after a GPIO_GET_LINEEVENT_IOCTL operation, zero or negative value | ||
| 126 | * means error | ||
| 127 | */ | ||
| 128 | struct gpioevent_request { | ||
| 129 | __u32 lineoffset; | ||
| 130 | __u32 handleflags; | ||
| 131 | __u32 eventflags; | ||
| 132 | char consumer_label[32]; | ||
| 133 | int fd; | ||
| 134 | }; | ||
| 135 | |||
| 136 | /** | ||
| 137 | * GPIO event types | ||
| 138 | */ | ||
| 139 | #define GPIOEVENT_EVENT_RISING_EDGE 0x01 | ||
| 140 | #define GPIOEVENT_EVENT_FALLING_EDGE 0x02 | ||
| 141 | |||
| 142 | /** | ||
| 143 | * struct gpioevent_data - The actual event being pushed to userspace | ||
| 144 | * @timestamp: best estimate of time of event occurrence, in nanoseconds | ||
| 145 | * @id: event identifier | ||
| 146 | */ | ||
| 147 | struct gpioevent_data { | ||
| 148 | __u64 timestamp; | ||
| 149 | __u32 id; | ||
| 150 | }; | ||
| 151 | |||
| 55 | #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) | 152 | #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) |
| 56 | #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) | 153 | #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) |
| 154 | #define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) | ||
| 155 | #define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request) | ||
| 57 | 156 | ||
| 58 | #endif /* _UAPI_GPIO_H_ */ | 157 | #endif /* _UAPI_GPIO_H_ */ |
diff --git a/tools/Makefile b/tools/Makefile index f10b64d8c674..daa8fb3e4363 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
| @@ -85,7 +85,7 @@ tmon: FORCE | |||
| 85 | freefall: FORCE | 85 | freefall: FORCE |
| 86 | $(call descend,laptop/$@) | 86 | $(call descend,laptop/$@) |
| 87 | 87 | ||
| 88 | all: acpi cgroup cpupower hv firewire lguest \ | 88 | all: acpi cgroup cpupower gpio hv firewire lguest \ |
| 89 | perf selftests turbostat usb \ | 89 | perf selftests turbostat usb \ |
| 90 | virtio vm net x86_energy_perf_policy \ | 90 | virtio vm net x86_energy_perf_policy \ |
| 91 | tmon freefall objtool | 91 | tmon freefall objtool |
| @@ -96,7 +96,7 @@ acpi_install: | |||
| 96 | cpupower_install: | 96 | cpupower_install: |
| 97 | $(call descend,power/$(@:_install=),install) | 97 | $(call descend,power/$(@:_install=),install) |
| 98 | 98 | ||
| 99 | cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: | 99 | cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: |
| 100 | $(call descend,$(@:_install=),install) | 100 | $(call descend,$(@:_install=),install) |
| 101 | 101 | ||
| 102 | selftests_install: | 102 | selftests_install: |
| @@ -114,7 +114,8 @@ freefall_install: | |||
| 114 | kvm_stat_install: | 114 | kvm_stat_install: |
| 115 | $(call descend,kvm/$(@:_install=),install) | 115 | $(call descend,kvm/$(@:_install=),install) |
| 116 | 116 | ||
| 117 | install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ | 117 | install: acpi_install cgroup_install cpupower_install gpio_install \ |
| 118 | hv_install firewire_install lguest_install \ | ||
| 118 | perf_install selftests_install turbostat_install usb_install \ | 119 | perf_install selftests_install turbostat_install usb_install \ |
| 119 | virtio_install vm_install net_install x86_energy_perf_policy_install \ | 120 | virtio_install vm_install net_install x86_energy_perf_policy_install \ |
| 120 | tmon_install freefall_install objtool_install kvm_stat_install | 121 | tmon_install freefall_install objtool_install kvm_stat_install |
diff --git a/tools/gpio/Build b/tools/gpio/Build new file mode 100644 index 000000000000..620c1937d957 --- /dev/null +++ b/tools/gpio/Build | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | lsgpio-y += lsgpio.o gpio-utils.o | ||
| 2 | gpio-hammer-y += gpio-hammer.o gpio-utils.o | ||
| 3 | gpio-event-mon-y += gpio-event-mon.o gpio-utils.o | ||
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index c155d6bc47a7..250a891e6ef0 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile | |||
| @@ -1,12 +1,75 @@ | |||
| 1 | include ../scripts/Makefile.include | ||
| 2 | |||
| 3 | bindir ?= /usr/bin | ||
| 4 | |||
| 5 | ifeq ($(srctree),) | ||
| 6 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | ||
| 7 | srctree := $(patsubst %/,%,$(dir $(srctree))) | ||
| 8 | endif | ||
| 9 | |||
| 10 | # Do not use make's built-in rules | ||
| 11 | # (this improves performance and avoids hard-to-debug behaviour); | ||
| 12 | MAKEFLAGS += -r | ||
| 13 | |||
| 1 | CC = $(CROSS_COMPILE)gcc | 14 | CC = $(CROSS_COMPILE)gcc |
| 2 | CFLAGS += -O2 -Wall -g -D_GNU_SOURCE | 15 | LD = $(CROSS_COMPILE)ld |
| 16 | CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include | ||
| 17 | |||
| 18 | ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon | ||
| 19 | ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) | ||
| 20 | |||
| 21 | all: $(ALL_PROGRAMS) | ||
| 3 | 22 | ||
| 4 | all: lsgpio | 23 | export srctree OUTPUT CC LD CFLAGS |
| 24 | include $(srctree)/tools/build/Makefile.include | ||
| 5 | 25 | ||
| 6 | lsgpio: lsgpio.o gpio-utils.o | 26 | # |
| 27 | # We need the following to be outside of kernel tree | ||
| 28 | # | ||
| 29 | $(OUTPUT)include/linux/gpio.h: ../../include/uapi/linux/gpio.h | ||
| 30 | mkdir -p $(OUTPUT)include/linux 2>&1 || true | ||
| 31 | ln -sf $(CURDIR)/../../include/uapi/linux/gpio.h $@ | ||
| 7 | 32 | ||
| 8 | %.o: %.c gpio-utils.h | 33 | prepare: $(OUTPUT)include/linux/gpio.h |
| 34 | |||
| 35 | # | ||
| 36 | # lsgpio | ||
| 37 | # | ||
| 38 | LSGPIO_IN := $(OUTPUT)lsgpio-in.o | ||
| 39 | $(LSGPIO_IN): prepare FORCE | ||
| 40 | $(Q)$(MAKE) $(build)=lsgpio | ||
| 41 | $(OUTPUT)lsgpio: $(LSGPIO_IN) | ||
| 42 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
| 43 | |||
| 44 | # | ||
| 45 | # gpio-hammer | ||
| 46 | # | ||
| 47 | GPIO_HAMMER_IN := $(OUTPUT)gpio-hammer-in.o | ||
| 48 | $(GPIO_HAMMER_IN): prepare FORCE | ||
| 49 | $(Q)$(MAKE) $(build)=gpio-hammer | ||
| 50 | $(OUTPUT)gpio-hammer: $(GPIO_HAMMER_IN) | ||
| 51 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
| 52 | |||
| 53 | # | ||
| 54 | # gpio-event-mon | ||
| 55 | # | ||
| 56 | GPIO_EVENT_MON_IN := $(OUTPUT)gpio-event-mon-in.o | ||
| 57 | $(GPIO_EVENT_MON_IN): prepare FORCE | ||
| 58 | $(Q)$(MAKE) $(build)=gpio-event-mon | ||
| 59 | $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN) | ||
| 60 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
| 9 | 61 | ||
| 10 | .PHONY: clean | ||
| 11 | clean: | 62 | clean: |
| 12 | rm -f *.o lsgpio | 63 | rm -f $(ALL_PROGRAMS) |
| 64 | rm -f $(OUTPUT)include/linux/gpio.h | ||
| 65 | find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete | ||
| 66 | |||
| 67 | install: $(ALL_PROGRAMS) | ||
| 68 | install -d -m 755 $(DESTDIR)$(bindir); \ | ||
| 69 | for program in $(ALL_PROGRAMS); do \ | ||
| 70 | install $$program $(DESTDIR)$(bindir); \ | ||
| 71 | done | ||
| 72 | |||
| 73 | FORCE: | ||
| 74 | |||
| 75 | .PHONY: all install clean FORCE prepare | ||
diff --git a/tools/gpio/gpio-event-mon.c b/tools/gpio/gpio-event-mon.c new file mode 100644 index 000000000000..448ed96b3b4f --- /dev/null +++ b/tools/gpio/gpio-event-mon.c | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | /* | ||
| 2 | * gpio-hammer - example swiss army knife to shake GPIO lines on a system | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016 Linus Walleij | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License version 2 as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Usage: | ||
| 11 | * gpio-event-mon -n <device-name> -o <offset> | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <unistd.h> | ||
| 15 | #include <stdlib.h> | ||
| 16 | #include <stdbool.h> | ||
| 17 | #include <stdio.h> | ||
| 18 | #include <dirent.h> | ||
| 19 | #include <errno.h> | ||
| 20 | #include <string.h> | ||
| 21 | #include <poll.h> | ||
| 22 | #include <fcntl.h> | ||
| 23 | #include <getopt.h> | ||
| 24 | #include <inttypes.h> | ||
| 25 | #include <sys/ioctl.h> | ||
| 26 | #include <linux/gpio.h> | ||
| 27 | |||
| 28 | int monitor_device(const char *device_name, | ||
| 29 | unsigned int line, | ||
| 30 | u_int32_t handleflags, | ||
| 31 | u_int32_t eventflags, | ||
| 32 | unsigned int loops) | ||
| 33 | { | ||
| 34 | struct gpioevent_request req; | ||
| 35 | struct gpiohandle_data data; | ||
| 36 | char *chrdev_name; | ||
| 37 | int fd; | ||
| 38 | int ret; | ||
| 39 | int i = 0; | ||
| 40 | |||
| 41 | ret = asprintf(&chrdev_name, "/dev/%s", device_name); | ||
| 42 | if (ret < 0) | ||
| 43 | return -ENOMEM; | ||
| 44 | |||
| 45 | fd = open(chrdev_name, 0); | ||
| 46 | if (fd == -1) { | ||
| 47 | ret = -errno; | ||
| 48 | fprintf(stderr, "Failed to open %s\n", chrdev_name); | ||
| 49 | goto exit_close_error; | ||
| 50 | } | ||
| 51 | |||
| 52 | req.lineoffset = line; | ||
| 53 | req.handleflags = handleflags; | ||
| 54 | req.eventflags = eventflags; | ||
| 55 | strcpy(req.consumer_label, "gpio-event-mon"); | ||
| 56 | |||
| 57 | ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req); | ||
| 58 | if (ret == -1) { | ||
| 59 | ret = -errno; | ||
| 60 | fprintf(stderr, "Failed to issue GET EVENT " | ||
| 61 | "IOCTL (%d)\n", | ||
| 62 | ret); | ||
| 63 | goto exit_close_error; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* Read initial states */ | ||
| 67 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
| 68 | if (ret == -1) { | ||
| 69 | ret = -errno; | ||
| 70 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
| 71 | "VALUES IOCTL (%d)\n", | ||
| 72 | ret); | ||
| 73 | goto exit_close_error; | ||
| 74 | } | ||
| 75 | |||
| 76 | fprintf(stdout, "Monitoring line %d on %s\n", line, device_name); | ||
| 77 | fprintf(stdout, "Initial line value: %d\n", data.values[0]); | ||
| 78 | |||
| 79 | while (1) { | ||
| 80 | struct gpioevent_data event; | ||
| 81 | |||
| 82 | ret = read(req.fd, &event, sizeof(event)); | ||
| 83 | if (ret == -1) { | ||
| 84 | if (errno == -EAGAIN) { | ||
| 85 | fprintf(stderr, "nothing available\n"); | ||
| 86 | continue; | ||
| 87 | } else { | ||
| 88 | ret = -errno; | ||
| 89 | fprintf(stderr, "Failed to read event (%d)\n", | ||
| 90 | ret); | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | if (ret != sizeof(event)) { | ||
| 96 | fprintf(stderr, "Reading event failed\n"); | ||
| 97 | ret = -EIO; | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | fprintf(stdout, "GPIO EVENT %" PRIu64 ": ", event.timestamp); | ||
| 101 | switch (event.id) { | ||
| 102 | case GPIOEVENT_EVENT_RISING_EDGE: | ||
| 103 | fprintf(stdout, "rising edge"); | ||
| 104 | break; | ||
| 105 | case GPIOEVENT_EVENT_FALLING_EDGE: | ||
| 106 | fprintf(stdout, "falling edge"); | ||
| 107 | break; | ||
| 108 | default: | ||
| 109 | fprintf(stdout, "unknown event"); | ||
| 110 | } | ||
| 111 | fprintf(stdout, "\n"); | ||
| 112 | |||
| 113 | i++; | ||
| 114 | if (i == loops) | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | |||
| 118 | exit_close_error: | ||
| 119 | if (close(fd) == -1) | ||
| 120 | perror("Failed to close GPIO character device file"); | ||
| 121 | free(chrdev_name); | ||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | void print_usage(void) | ||
| 126 | { | ||
| 127 | fprintf(stderr, "Usage: gpio-event-mon [options]...\n" | ||
| 128 | "Listen to events on GPIO lines, 0->1 1->0\n" | ||
| 129 | " -n <name> Listen on GPIOs on a named device (must be stated)\n" | ||
| 130 | " -o <n> Offset to monitor\n" | ||
| 131 | " -d Set line as open drain\n" | ||
| 132 | " -s Set line as open source\n" | ||
| 133 | " -r Listen for rising edges\n" | ||
| 134 | " -f Listen for falling edges\n" | ||
| 135 | " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" | ||
| 136 | " -? This helptext\n" | ||
| 137 | "\n" | ||
| 138 | "Example:\n" | ||
| 139 | "gpio-event-mon -n gpiochip0 -o 4 -r -f\n" | ||
| 140 | ); | ||
| 141 | } | ||
| 142 | |||
| 143 | int main(int argc, char **argv) | ||
| 144 | { | ||
| 145 | const char *device_name = NULL; | ||
| 146 | unsigned int line = -1; | ||
| 147 | unsigned int loops = 0; | ||
| 148 | u_int32_t handleflags = GPIOHANDLE_REQUEST_INPUT; | ||
| 149 | u_int32_t eventflags = 0; | ||
| 150 | int c; | ||
| 151 | |||
| 152 | while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) { | ||
| 153 | switch (c) { | ||
| 154 | case 'c': | ||
| 155 | loops = strtoul(optarg, NULL, 10); | ||
| 156 | break; | ||
| 157 | case 'n': | ||
| 158 | device_name = optarg; | ||
| 159 | break; | ||
| 160 | case 'o': | ||
| 161 | line = strtoul(optarg, NULL, 10); | ||
| 162 | break; | ||
| 163 | case 'd': | ||
| 164 | handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN; | ||
| 165 | break; | ||
| 166 | case 's': | ||
| 167 | handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE; | ||
| 168 | break; | ||
| 169 | case 'r': | ||
| 170 | eventflags |= GPIOEVENT_REQUEST_RISING_EDGE; | ||
| 171 | break; | ||
| 172 | case 'f': | ||
| 173 | eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE; | ||
| 174 | break; | ||
| 175 | case '?': | ||
| 176 | print_usage(); | ||
| 177 | return -1; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | if (!device_name || line == -1) { | ||
| 182 | print_usage(); | ||
| 183 | return -1; | ||
| 184 | } | ||
| 185 | if (!eventflags) { | ||
| 186 | printf("No flags specified, listening on both rising and " | ||
| 187 | "falling edges\n"); | ||
| 188 | eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; | ||
| 189 | } | ||
| 190 | return monitor_device(device_name, line, handleflags, | ||
| 191 | eventflags, loops); | ||
| 192 | } | ||
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c new file mode 100644 index 000000000000..37b3f141053d --- /dev/null +++ b/tools/gpio/gpio-hammer.c | |||
| @@ -0,0 +1,189 @@ | |||
| 1 | /* | ||
| 2 | * gpio-hammer - example swiss army knife to shake GPIO lines on a system | ||
| 3 | * | ||
| 4 | * Copyright (C) 2016 Linus Walleij | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License version 2 as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Usage: | ||
| 11 | * gpio-hammer -n <device-name> -o <offset1> -o <offset2> | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <unistd.h> | ||
| 15 | #include <stdlib.h> | ||
| 16 | #include <stdbool.h> | ||
| 17 | #include <stdio.h> | ||
| 18 | #include <dirent.h> | ||
| 19 | #include <errno.h> | ||
| 20 | #include <string.h> | ||
| 21 | #include <poll.h> | ||
| 22 | #include <fcntl.h> | ||
| 23 | #include <getopt.h> | ||
| 24 | #include <sys/ioctl.h> | ||
| 25 | #include <linux/gpio.h> | ||
| 26 | |||
| 27 | int hammer_device(const char *device_name, unsigned int *lines, int nlines, | ||
| 28 | unsigned int loops) | ||
| 29 | { | ||
| 30 | struct gpiohandle_request req; | ||
| 31 | struct gpiohandle_data data; | ||
| 32 | char *chrdev_name; | ||
| 33 | char swirr[] = "-\\|/"; | ||
| 34 | int fd; | ||
| 35 | int ret; | ||
| 36 | int i, j; | ||
| 37 | unsigned int iteration = 0; | ||
| 38 | |||
| 39 | ret = asprintf(&chrdev_name, "/dev/%s", device_name); | ||
| 40 | if (ret < 0) | ||
| 41 | return -ENOMEM; | ||
| 42 | |||
| 43 | fd = open(chrdev_name, 0); | ||
| 44 | if (fd == -1) { | ||
| 45 | ret = -errno; | ||
| 46 | fprintf(stderr, "Failed to open %s\n", chrdev_name); | ||
| 47 | goto exit_close_error; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* Request lines as output */ | ||
| 51 | for (i = 0; i < nlines; i++) | ||
| 52 | req.lineoffsets[i] = lines[i]; | ||
| 53 | req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */ | ||
| 54 | strcpy(req.consumer_label, "gpio-hammer"); | ||
| 55 | req.lines = nlines; | ||
| 56 | ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); | ||
| 57 | if (ret == -1) { | ||
| 58 | ret = -errno; | ||
| 59 | fprintf(stderr, "Failed to issue GET LINEHANDLE " | ||
| 60 | "IOCTL (%d)\n", | ||
| 61 | ret); | ||
| 62 | goto exit_close_error; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Read initial states */ | ||
| 66 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
| 67 | if (ret == -1) { | ||
| 68 | ret = -errno; | ||
| 69 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
| 70 | "VALUES IOCTL (%d)\n", | ||
| 71 | ret); | ||
| 72 | goto exit_close_error; | ||
| 73 | } | ||
| 74 | fprintf(stdout, "Hammer lines ["); | ||
| 75 | for (i = 0; i < nlines; i++) { | ||
| 76 | fprintf(stdout, "%d", lines[i]); | ||
| 77 | if (i != (nlines - 1)) | ||
| 78 | fprintf(stdout, ", "); | ||
| 79 | } | ||
| 80 | fprintf(stdout, "] on %s, initial states: [", device_name); | ||
| 81 | for (i = 0; i < nlines; i++) { | ||
| 82 | fprintf(stdout, "%d", data.values[i]); | ||
| 83 | if (i != (nlines - 1)) | ||
| 84 | fprintf(stdout, ", "); | ||
| 85 | } | ||
| 86 | fprintf(stdout, "]\n"); | ||
| 87 | |||
| 88 | /* Hammertime! */ | ||
| 89 | j = 0; | ||
| 90 | while (1) { | ||
| 91 | /* Invert all lines so we blink */ | ||
| 92 | for (i = 0; i < nlines; i++) | ||
| 93 | data.values[i] = !data.values[i]; | ||
| 94 | |||
| 95 | ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); | ||
| 96 | if (ret == -1) { | ||
| 97 | ret = -errno; | ||
| 98 | fprintf(stderr, "Failed to issue GPIOHANDLE SET LINE " | ||
| 99 | "VALUES IOCTL (%d)\n", | ||
| 100 | ret); | ||
| 101 | goto exit_close_error; | ||
| 102 | } | ||
| 103 | /* Re-read values to get status */ | ||
| 104 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
| 105 | if (ret == -1) { | ||
| 106 | ret = -errno; | ||
| 107 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
| 108 | "VALUES IOCTL (%d)\n", | ||
| 109 | ret); | ||
| 110 | goto exit_close_error; | ||
| 111 | } | ||
| 112 | |||
| 113 | fprintf(stdout, "[%c] ", swirr[j]); | ||
| 114 | j++; | ||
| 115 | if (j == sizeof(swirr)-1) | ||
| 116 | j = 0; | ||
| 117 | |||
| 118 | fprintf(stdout, "["); | ||
| 119 | for (i = 0; i < nlines; i++) { | ||
| 120 | fprintf(stdout, "%d: %d", lines[i], data.values[i]); | ||
| 121 | if (i != (nlines - 1)) | ||
| 122 | fprintf(stdout, ", "); | ||
| 123 | } | ||
| 124 | fprintf(stdout, "]\r"); | ||
| 125 | fflush(stdout); | ||
| 126 | sleep(1); | ||
| 127 | iteration++; | ||
| 128 | if (loops && iteration == loops) | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | fprintf(stdout, "\n"); | ||
| 132 | ret = 0; | ||
| 133 | |||
| 134 | exit_close_error: | ||
| 135 | if (close(fd) == -1) | ||
| 136 | perror("Failed to close GPIO character device file"); | ||
| 137 | free(chrdev_name); | ||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | |||
| 141 | void print_usage(void) | ||
| 142 | { | ||
| 143 | fprintf(stderr, "Usage: gpio-hammer [options]...\n" | ||
| 144 | "Hammer GPIO lines, 0->1->0->1...\n" | ||
| 145 | " -n <name> Hammer GPIOs on a named device (must be stated)\n" | ||
| 146 | " -o <n> Offset[s] to hammer, at least one, several can be stated\n" | ||
| 147 | " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" | ||
| 148 | " -? This helptext\n" | ||
| 149 | "\n" | ||
| 150 | "Example:\n" | ||
| 151 | "gpio-hammer -n gpiochip0 -o 4\n" | ||
| 152 | ); | ||
| 153 | } | ||
| 154 | |||
| 155 | int main(int argc, char **argv) | ||
| 156 | { | ||
| 157 | const char *device_name = NULL; | ||
| 158 | unsigned int lines[GPIOHANDLES_MAX]; | ||
| 159 | unsigned int loops = 0; | ||
| 160 | int nlines; | ||
| 161 | int c; | ||
| 162 | int i; | ||
| 163 | |||
| 164 | i = 0; | ||
| 165 | while ((c = getopt(argc, argv, "c:n:o:?")) != -1) { | ||
| 166 | switch (c) { | ||
| 167 | case 'c': | ||
| 168 | loops = strtoul(optarg, NULL, 10); | ||
| 169 | break; | ||
| 170 | case 'n': | ||
| 171 | device_name = optarg; | ||
| 172 | break; | ||
| 173 | case 'o': | ||
| 174 | lines[i] = strtoul(optarg, NULL, 10); | ||
| 175 | i++; | ||
| 176 | break; | ||
| 177 | case '?': | ||
| 178 | print_usage(); | ||
| 179 | return -1; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | nlines = i; | ||
| 183 | |||
| 184 | if (!device_name || !nlines) { | ||
| 185 | print_usage(); | ||
| 186 | return -1; | ||
| 187 | } | ||
| 188 | return hammer_device(device_name, lines, nlines, loops); | ||
| 189 | } | ||
