Commit 6a497e9d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.9 series:

  Subsystem improvements:

   - do away with the last users of the obsolete Kconfig options
     ARCH_REQUIRE_GPIOLIB and ARCH_WANT_OPTIONAL_GPIOLIB (the latter
     always sounded like an item on a wishlist to Santa Claus to me). We
     can now select GPIOLIB and be done with it, for all archs. After
     some struggle it even work on UM. Not that it has GPIO, but if it
     wants to, it can select the library.

   - continued efforts to make drivers properly either tristate or bool.

   - introduce a warning for drivers assigning default triggers to their
     irqchip lines when probed from device tree, so we find and fix
     these ambigous drivers. It is agreed that in the OF config path,
     the device tree defines trigger characteristics.

   - the same warning, mutatis mutandis, for ACPI-probed GPIO irqchips.

   - we introduce the ability to mark certain IRQ lines as "unusable" as
     they can be taken by BIOS/firmware, unrouted in silicon and
     generally nasty if you use them, and such things. This is put to
     good use in the STMPE driver and also in the Cherryview pin control
     driver.

   - a new "mockup" virtual GPIO device that can be used for testing.
     The plan is to add unit tests under tools/* for exercising this
     device and verify that the kernel code paths are working as they
     should.

   - make memory-mapped I/O-drivers depend on HAS_IOMEM. This was
     implicit all the time, but when people started building UM with
     allyesconfig or allmodconfig it exploded in their face.

   - move some stray bits of device tree and ACPI HW description
     callbacks down into their respective implementation silo. These
     were causing issues when compiling on !HAS_IOMEM as well, so now
     eventually UM compiles the GPIOLIB library if it wants to.

  New drivers:

   - new driver for the Aspeed GPIO front-end companion to the pin
     controller merged through the pin control tree.

   - new driver for the LP873x PMIC GPIO portions.

   - new driver for Technologic Systems' I2C FPGA GPIO such as TS4900,
     TS-7970, TS-7990 and TS-4100.

   - new driver for the Broadcom BCM63xx series including BCM6338 and
     BCM6345.

   - new driver for the Intel WhiskeyCove PMIC GPIO.

   - new driver for the Allwinner AXP209 PMIC GPIO portions.

   - new driver for Diamond Systems 48 line GPIO-MM, another of these
     port-mapped I/O expansion cards.

   - support the STMicroelectronics STMPE1600 variant in the STMPE
     driver.

  Driver improvements:

   - the STMPE driver now supports rising/falling edge detection
     properly for IRQs.

   - the PCA954x will now fetch and enable its VCC regulator properly.

   - major rework of the PCA953x driver with the goal of eventually
     switching it over to use regmap and thus modernize it even more.

   - switch the IOP driver to use the generic MMIO GPIO library.

   - move the ages old HTC EGPIO (extended GPIO) GPIO expander driver
     over to this subsystem from MFD, achieveing some separation of
     concerns"

* tag 'gpio-v4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (81 commits)
  gpio: add missing static inline
  gpio: OF: localize some gpiochip init functions
  gpio: acpi: separation of concerns
  gpio: OF: separation of concerns
  gpio: make memory-mapped drivers depend on HAS_IOMEM
  gpio: stmpe: use BIT() macro
  gpio: stmpe: forbid unused lines to be mapped as IRQs
  mfd/gpio: Move HTC GPIO driver to GPIO subsystem
  gpio: MAINTAINERS: Add an entry for GPIO mockup driver
  gpio/mockup: add virtual gpio device
  gpio: Added zynq specific check for special pins on bank zero
  gpio: axp209: Implement get_direction
  gpio: aspeed: remove redundant return value check
  gpio: loongson1: remove redundant return value check
  ARM: omap2: fix missing include
  gpio: tc3589x: fix up complaints on unsigned
  gpio: tc3589x: add .get_direction() and small cleanup
  gpio: f7188x: use gpiochip_get_data instead of container_of
  gpio: tps65218: use devm_gpiochip_add_data() for gpio registration
  gpio: aspeed: fix return value check in aspeed_gpio_probe()
  ...
parents d268dbe7 e0852940
Bindings for the Broadcom's brcm,bcm6345-gpio memory-mapped GPIO controllers.
These bindings can be used on any BCM63xx SoC. However, BCM6338 and BCM6345
are the only ones which don't need a pinctrl driver.
BCM6338 have 8-bit data and dirout registers, where GPIO state can be read
and/or written, and the direction changed from input to output.
BCM6345 have 16-bit data and dirout registers, where GPIO state can be read
and/or written, and the direction changed from input to output.
Required properties:
- compatible: should be "brcm,bcm6345-gpio"
- reg-names: must contain
"dat" - data register
"dirout" - direction (output) register
- reg: address + size pairs describing the GPIO register sets;
order must correspond with the order of entries in reg-names
- #gpio-cells: must be set to 2. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- gpio-controller: Marks the device node as a gpio controller.
Optional properties:
- native-endian: use native endian memory.
Examples:
- BCM6338:
gpio: gpio-controller@fffe0407 {
compatible = "brcm,bcm6345-gpio";
reg-names = "dirout", "dat";
reg = <0xfffe0407 1>, <0xfffe040f 1>;
#gpio-cells = <2>;
gpio-controller;
};
- BCM6345:
gpio: gpio-controller@fffe0406 {
compatible = "brcm,bcm6345-gpio";
reg-names = "dirout", "dat";
reg = <0xfffe0406 2>, <0xfffe040a 2>;
native-endian;
#gpio-cells = <2>;
gpio-controller;
};
Aspeed GPIO controller Device Tree Bindings
-------------------------------------------
Required properties:
- compatible : Either "aspeed,ast2400-gpio" or "aspeed,ast2500-gpio"
- #gpio-cells : Should be two
- First cell is the GPIO line number
- Second cell is used to specify optional
parameters (unused)
- reg : Address and length of the register set for the device
- gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt specifier (see interrupt bindings for
details)
- interrupt-controller : Mark the GPIO controller as an interrupt-controller
Optional properties:
- interrupt-parent : The parent interrupt controller, optional if inherited
The gpio and interrupt properties are further described in their respective
bindings documentation:
- Documentation/devicetree/bindings/gpio/gpio.txt
- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example:
gpio@1e780000 {
#gpio-cells = <2>;
compatible = "aspeed,ast2400-gpio";
gpio-controller;
interrupts = <20>;
reg = <0x1e780000 0x1000>;
interrupt-controller;
};
AXP209 GPIO controller
This driver follows the usual GPIO bindings found in
Documentation/devicetree/bindings/gpio/gpio.txt
Required properties:
- compatible: Should be "x-powers,axp209-gpio"
- #gpio-cells: Should be two. The first cell is the pin number and the
second is the GPIO flags.
- gpio-controller: Marks the device node as a GPIO controller.
This node must be a subnode of the axp20x PMIC, documented in
Documentation/devicetree/bindings/mfd/axp20x.txt
Example:
axp209: pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
axp_gpio: gpio {
compatible = "x-powers,axp209-gpio";
gpio-controller;
#gpio-cells = <2>;
};
};
TPIC2810 GPIO controller bindings
Required properties:
- compatible : Should be "ti,tpic2810".
- reg : The I2C address of the device
- gpio-controller : Marks the device node as a GPIO controller.
- #gpio-cells : Should be two. For consumer use see gpio.txt.
Example:
gpio@60 {
compatible = "ti,tpic2810";
reg = <0x60>;
gpio-controller;
#gpio-cells = <2>;
};
* TPS65086 GPO Controller bindings
Required properties:
- compatible : Should be "ti,tps65086-gpio".
- gpio-controller : Marks the device node as a GPIO Controller.
- #gpio-cells : Should be two. The first cell is the pin number
and the second cell is used to specify flags.
See ../gpio/gpio.txt for possible values.
Example:
gpio4: gpio {
compatible = "ti,tps65086-gpio";
gpio-controller;
#gpio-cells = <2>;
};
* Technologic Systems I2C-FPGA's GPIO controller bindings
This bindings describes the GPIO controller for Technologic's FPGA core.
TS-4900's FPGA encodes the GPIO state on 3 bits, whereas the TS-7970's FPGA
uses 2 bits: it doesn't use a dedicated input bit.
Required properties:
- compatible: Should be one of the following
"technologic,ts4900-gpio"
"technologic,ts7970-gpio"
- reg: Physical base address of the controller and length
of memory mapped region.
- #gpio-cells: Should be two. The first cell is the pin number.
- gpio-controller: Marks the device node as a gpio controller.
Optional property:
- ngpios: Number of GPIOs this controller is instantiated with,
the default is 32. See gpio.txt for more details.
Example:
&i2c2 {
gpio8: gpio@28 {
compatible = "technologic,ts4900-gpio";
reg = <0x28>;
#gpio-cells = <2>;
gpio-controller;
ngpios = <32>;
};
};
......@@ -44,26 +44,3 @@ Example for a PXA3xx platform:
interrupt-controller;
#interrupt-cells = <0x2>;
};
* Marvell Orion GPIO Controller
Required properties:
- compatible : Should be "marvell,orion-gpio"
- reg : Address and length of the register set for controller.
- gpio-controller : So we know this is a gpio controller.
- ngpio : How many gpios this controller has.
- interrupts : Up to 4 Interrupts for the controller.
Optional properties:
- mask-offset : For SMP Orions, offset for Nth CPU
Example:
gpio0: gpio@10100 {
compatible = "marvell,orion-gpio";
#gpio-cells = <2>;
gpio-controller;
reg = <0x10100 0x40>;
ngpio = <32>;
interrupts = <35>, <36>, <37>, <38>;
};
......@@ -11,6 +11,7 @@ Required Properties:
- "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller.
- "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller.
- "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller.
- "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller.
- "renesas,gpio-rcar": for generic R-Car GPIO controller.
- reg: Base address and length of each memory resource used by the GPIO
......
......@@ -4,7 +4,7 @@ STMPE is an MFD device which may expose the following inbuilt devices: gpio,
keypad, touchscreen, adc, pwm, rotator.
Required properties:
- compatible : "st,stmpe[610|801|811|1601|2401|2403]"
- compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]"
- reg : I2C/SPI address of the device
Optional properties:
......
......@@ -8,9 +8,9 @@ gpio-legacy.txt (actually, there is no real mapping possible with the old
interface; you just fetch an integer from somewhere and request the
corresponding GPIO.
Platforms that make use of GPIOs must select ARCH_REQUIRE_GPIOLIB (if GPIO usage
is mandatory) or ARCH_WANT_OPTIONAL_GPIOLIB (if GPIO support can be omitted) in
their Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
All platforms can enable the GPIO library, but if the platform strictly
requires GPIO functionality to be present, it needs to select GPIOLIB from its
Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
describe its hardware layout. Currently, mappings can be defined through device
tree, ACPI, and platform data.
......
......@@ -72,8 +72,8 @@ in this document, but drivers acting as clients to the GPIO interface must
not care how it's implemented.)
That said, if the convention is supported on their platform, drivers should
use it when possible. Platforms must select ARCH_REQUIRE_GPIOLIB or
ARCH_WANT_OPTIONAL_GPIOLIB in their Kconfig. Drivers that can't work without
use it when possible. Platforms must select GPIOLIB if GPIO functionality
is strictly required. Drivers that can't work without
standard GPIO calls should have Kconfig entries which depend on GPIOLIB. The
GPIO calls are available, either as "real code" or as optimized-away stubs,
when drivers use the include file:
......@@ -553,22 +553,14 @@ either NULL or the label associated with that GPIO when it was requested.
Platform Support
----------------
To support this framework, a platform's Kconfig will "select" either
ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
To force-enable this framework, a platform's Kconfig will "select" GPIOLIB,
else it is up to the user to configure support for GPIO.
It may also provide a custom value for ARCH_NR_GPIOS, so that it better
reflects the number of GPIOs in actual use on that platform, without
wasting static table space. (It should count both built-in/SoC GPIOs and
also ones on GPIO expanders.
ARCH_REQUIRE_GPIOLIB means that the gpiolib code will always get compiled
into the kernel on that architecture.
ARCH_WANT_OPTIONAL_GPIOLIB means the gpiolib code defaults to off and the user
can enable it and build it into the kernel optionally.
If neither of these options are selected, the platform does not support
GPIOs through GPIO-lib and the code cannot be enabled by the user.
......
......@@ -1374,6 +1374,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
Default: 1024
gpio-mockup.gpio_mockup_ranges
[HW] Sets the ranges of gpiochip of for this device.
Format: <start1>,<end1>,<start2>,<end2>...
hardlockup_all_cpu_backtrace=
[KNL] Should the hard-lockup detector generate
backtraces on all cpus.
......
......@@ -3794,6 +3794,12 @@ F: include/linux/regulator/da9211.h
F: include/sound/da[79]*.h
F: sound/soc/codecs/da[79]*.[ch]
DIAMOND SYSTEMS GPIO-MM GPIO DRIVER
M: William Breathitt Gray <vilhelm.gray@gmail.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-gpio-mm.c
DIGI NEO AND CLASSIC PCI PRODUCTS
M: Lidza Louina <lidza.louina@gmail.com>
M: Mark Hounschell <markh@compro.net>
......@@ -5274,6 +5280,13 @@ L: linux-input@vger.kernel.org
S: Maintained
F: drivers/input/touchscreen/goodix.c
GPIO MOCKUP DRIVER
M: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-mockup.c
F: tools/testing/selftests/gpio/
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>
......
......@@ -29,6 +29,7 @@
#include <linux/power/isp1704_charger.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/mtd-onenand-omap2.h>
#include <linux/module.h>
#include <plat/dmtimer.h>
......
......@@ -24,10 +24,10 @@
#include <linux/input.h>
#include <linux/input/navpoint.h>
#include <linux/lcd.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mfd/asic3.h>
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/platform_data/gpio-htc-egpio.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/regulator/driver.h>
......
......@@ -20,10 +20,10 @@
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mfd/htc-pasic3.h>
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/platform_data/gpio-htc-egpio.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/regulator/driver.h>
......
......@@ -14,9 +14,9 @@
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_data/gpio-htc-egpio.h>
#include <linux/platform_data/sa11x0-serial.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
......
......@@ -17,7 +17,6 @@ config ARM64
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_NUMA_BALANCING
select ARCH_WANT_OPTIONAL_GPIOLIB
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select ARCH_WANT_FRAME_POINTERS
select ARCH_HAS_UBSAN_SANITIZE_ALL
......
......@@ -15,8 +15,8 @@ config ARCH_ALPINE
config ARCH_BCM2835
bool "Broadcom BCM2835 family"
select ARCH_REQUIRE_GPIOLIB
select CLKSRC_OF
select GPIOLIB
select PINCTRL
select PINCTRL_BCM2835
select ARM_AMBA
......@@ -29,15 +29,15 @@ config ARCH_BCM2835
config ARCH_BCM_IPROC
bool "Broadcom iProc SoC Family"
select COMMON_CLK_IPROC
select GPIOLIB
select PINCTRL
select ARCH_REQUIRE_GPIOLIB
help
This enables support for Broadcom iProc based SoCs
config ARCH_BERLIN
bool "Marvell Berlin SoC Family"
select ARCH_REQUIRE_GPIOLIB
select DW_APB_ICTL
select GPIOLIB
select PINCTRL
help
This enables support for Marvell Berlin SoC Family
......@@ -110,7 +110,7 @@ config ARCH_QCOM
config ARCH_ROCKCHIP
bool "Rockchip Platforms"
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select GPIOLIB
select PINCTRL
select PINCTRL_ROCKCHIP
select ROCKCHIP_TIMER
......@@ -156,11 +156,11 @@ config ARCH_STRATIX10
config ARCH_TEGRA
bool "NVIDIA Tegra SoC Family"
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select CLKSRC_OF
select GENERIC_CLOCKEVENTS
select GPIOLIB
select PINCTRL
select RESET_CONTROLLER
help
......@@ -184,8 +184,8 @@ config ARCH_UNIPHIER
config ARCH_VEXPRESS
bool "ARMv8 software model (Versatile Express)"
select ARCH_REQUIRE_GPIOLIB
select COMMON_CLK_VERSATILE
select GPIOLIB
select PM
select PM_GENERIC_DOMAINS
select POWER_RESET_VEXPRESS
......
......@@ -26,7 +26,7 @@ config BLACKFIN
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
select ARCH_HAVE_CUSTOM_GPIO_H
select ARCH_REQUIRE_GPIOLIB
select GPIOLIB
select HAVE_UID16
select HAVE_UNDERSCORE_SYMBOL_PREFIX
select VIRT_TO_BUS
......
......@@ -10,27 +10,6 @@ config ARCH_HAVE_CUSTOM_GPIO_H
overriding the default implementations. New uses of this are
strongly discouraged.
config ARCH_WANT_OPTIONAL_GPIOLIB
bool
help
Select this config option from the architecture Kconfig, if
it is possible to use gpiolib on the architecture, but let the
user decide whether to actually build it or not.
Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does
not depend on GPIOs being available, but rather let the user
decide whether he needs it or not.
config ARCH_REQUIRE_GPIOLIB
bool
select GPIOLIB
help
Platforms select gpiolib if they use this infrastructure
for all their GPIOs, usually starting with ones integrated
into SOC processors.
Selecting this from the architecture code will cause the gpiolib
code to always get built in.
menuconfig GPIOLIB
bool "GPIO Support"
select ANON_INODES
......@@ -87,6 +66,7 @@ config GPIO_SYSFS
exported to userspace; this can be useful when debugging.
config GPIO_GENERIC
depends on HAS_IOMEM # Only for IOMEM drivers
tristate
# put drivers in the right section, in alphabetical order
......@@ -96,6 +76,7 @@ config GPIO_MAX730X
tristate
menu "Memory mapped GPIO drivers"
depends on HAS_IOMEM
config GPIO_74XX_MMIO
tristate "GPIO driver for 74xx-ICs with MMIO access"
......@@ -128,6 +109,13 @@ config GPIO_AMDPT
driver for GPIO functionality on Promontory IOHub
Require ACPI ASL code to enumerate as a platform device.
config GPIO_ASPEED
tristate "Aspeed GPIO support"
depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO
select GPIOLIB_IRQCHIP
help
Say Y here to support Aspeed AST2400 and AST2500 GPIO controllers.
config GPIO_ATH79
tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
default y if ATH79
......@@ -138,6 +126,12 @@ config GPIO_ATH79
Select this option to enable GPIO driver for
Atheros AR71XX/AR724X/AR913X SoC devices.
config GPIO_AXP209
tristate "X-Powers AXP209 PMIC GPIO Support"
depends on MFD_AXP20X
help
Say yes to enable GPIO support for the AXP209 PMIC
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
......@@ -237,7 +231,8 @@ config GPIO_ICH
config GPIO_IOP
tristate "Intel IOP GPIO"
depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
select GPIO_GENERIC
help
Say yes here to support the GPIO functionality of a number of Intel
IOP32X or IOP33X.
......@@ -287,6 +282,18 @@ config GPIO_MM_LANTIQ
(EBU) found on Lantiq SoCs. The gpios are output only as they are
created by attaching a 16bit latch to the bus.
config GPIO_MOCKUP
tristate "GPIO Testing Driver"
depends on GPIOLIB
select GPIO_SYSFS
help
This enables GPIO Testing driver, which provides a way to test GPIO
subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS
must be selected for this test.
User could use it through the script in
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it.
config GPIO_MOXART
bool "MOXART GPIO support"
depends on ARCH_MOXART || COMPILE_TEST
......@@ -574,6 +581,19 @@ config GPIO_F7188X
To compile this driver as a module, choose M here: the module will
be called f7188x-gpio.
config GPIO_GPIO_MM
tristate "Diamond Systems GPIO-MM GPIO support"
depends on ISA_BUS_API
help
Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
The Diamond Systems GPIO-MM device features 48 lines of digital I/O
via the emulation of dual 82C55A PPI chips. This driver provides GPIO
support for these 48 channels of digital I/O.
The base port addresses for the devices may be configured via the base
array module parameter.
config GPIO_IT87
tristate "IT87xx GPIO support"
help
......@@ -780,6 +800,13 @@ config GPIO_TPIC2810
To compile this driver as a module, choose M here: the module will
be called gpio-tpic2810.
config GPIO_TS4900
tristate "Technologic Systems FPGA I2C GPIO"
select REGMAP_I2C
help
Say yes here to enabled the GPIO driver for Technologic's FPGA core.
Series supported include TS-4100, TS-4900, TS-7970 and TS-7990.
endmenu
menu "MFD GPIO expanders"
......@@ -849,6 +876,14 @@ config GPIO_DLN2
This driver can also be built as a module. If so, the module
will be called gpio-dln2.
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GPIOLIB && ARM
help
This driver supports the CPLD egpio chip present on
several HTC phones. It provides basic support for input
pins, output pins, and irqs.
config GPIO_JANZ_TTL
tristate "Janz VMOD-TTL Digital IO Module"
depends on MFD_JANZ_CMODIO
......@@ -875,6 +910,16 @@ config GPIO_LP3943
LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
Open drain outputs are required for this usage.
config GPIO_LP873X
tristate "TI LP873X GPO"
depends on MFD_TI_LP873X
help
This driver supports the GPO on TI Lp873x PMICs. 2 GPOs are present
on LP873X PMICs.
This driver can also be built as a module. If so, the module will be
called gpio-lp873x.
config GPIO_MAX77620
tristate "GPIO support for PMIC MAX77620 and MAX20024"
depends on MFD_MAX77620
......@@ -985,6 +1030,19 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
config GPIO_WHISKEY_COVE
tristate "GPIO support for Whiskey Cove PMIC"
depends on INTEL_SOC_PMIC
select GPIOLIB_IRQCHIP
help
Support for GPIO pins on Whiskey Cove PMIC.
Say Yes if you have a Intel SoC based tablet with Whiskey Cove PMIC
inside.
This driver can also be built as a module. If so, the module will be
called gpio-wcove.
config GPIO_WM831X
tristate "WM831x GPIOs"
depends on MFD_WM831X
......
......@@ -28,6 +28,8 @@ obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
......@@ -44,7 +46,9 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
......@@ -56,6 +60,7 @@ obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
......@@ -70,6 +75,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
......@@ -110,6 +116,7 @@ obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o
obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
......@@ -120,6 +127,7 @@ obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
......
......@@ -17,6 +17,7 @@
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
......
......@@ -79,7 +79,7 @@ static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
ARIZONA_GPN_LVL, value);
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "arizona",
.owner = THIS_MODULE,
.direction_input = arizona_gpio_direction_in,
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
#include <linux/platform_data/gpio-ath79.h>
#include <linux/of_device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/irq.h>
#define AR71XX_GPIO_REG_OE 0x00
......
/*
* AXP20x GPIO driver
*
* Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/axp20x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#define AXP20X_GPIO_FUNCTIONS 0x7
#define AXP20X_GPIO_FUNCTION_OUT_LOW 0
#define AXP20X_GPIO_FUNCTION_OUT_HIGH 1
#define AXP20X_GPIO_FUNCTION_INPUT 2
struct axp20x_gpio {
struct gpio_chip chip;
struct regmap *regmap;
};
static int axp20x_gpio_get_reg(unsigned offset)
{
switch (offset) {
case 0:
return AXP20X_GPIO0_CTRL;
case 1:
return AXP20X_GPIO1_CTRL;
case 2:
return AXP20X_GPIO2_CTRL;
}
return -EINVAL;
}
static int axp20x_gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
int reg;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
return regmap_update_bits(gpio->regmap, reg,
AXP20X_GPIO_FUNCTIONS,
AXP20X_GPIO_FUNCTION_INPUT);
}
static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
int reg, ret;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
ret = regmap_read(gpio->regmap, reg, &val);
if (ret)
return ret;
return !!(val & BIT(offset + 4));
}
static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
unsigned int val;
int reg, ret;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
ret = regmap_read(gpio->regmap, reg, &val);
if (ret)
return ret;
/*
* This shouldn't really happen if the pin is in use already,
* or if it's not in use yet, it doesn't matter since we're
* going to change the value soon anyway. Default to output.
*/
if ((val & AXP20X_GPIO_FUNCTIONS) > 2)
return 0;
/*
* The GPIO directions are the three lowest values.
* 2 is input, 0 and 1 are output
*/
return val & 2;
}
static int axp20x_gpio_output(struct gpio_chip *chip, unsigned offset,
int value)
{
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
int reg;
reg = axp20x_gpio_get_reg(offset);
if (reg < 0)
return reg;
return regmap_update_bits(gpio->regmap, reg,
AXP20X_GPIO_FUNCTIONS,
value ? AXP20X_GPIO_FUNCTION_OUT_HIGH
: AXP20X_GPIO_FUNCTION_OUT_LOW);
}
static void axp20x_gpio_set(struct gpio_chip *chip, unsigned offset,
int value)
{
axp20x_gpio_output(chip, offset, value);
}
static int axp20x_gpio_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct axp20x_gpio *gpio;
int ret;
if (!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
if (!axp20x) {
dev_err(&pdev->dev, "Parent drvdata not set\n");
return -EINVAL;
}
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
gpio->chip.base = -1;
gpio->chip.can_sleep = true;
gpio->chip.parent = &pdev->dev;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.owner = THIS_MODULE;
gpio->chip.get = axp20x_gpio_get;
gpio->chip.get_direction = axp20x_gpio_get_direction;
gpio->chip.set = axp20x_gpio_set;
gpio->chip.direction_input = axp20x_gpio_input;
gpio->chip.direction_output = axp20x_gpio_output;
gpio->chip.ngpio = 3;
gpio->regmap = axp20x->regmap;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPIO chip\n");
return ret;
}
dev_info(&pdev->dev, "AXP209 GPIO driver loaded\n");
return 0;
}
static const struct of_device_id axp20x_gpio_match[] = {
{ .compatible = "x-powers,axp209-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, axp20x_gpio_match);
static struct platform_driver axp20x_gpio_driver = {
.probe = axp20x_gpio_probe,
.driver = {
.name = "axp20x-gpio",
.of_match_table = axp20x_gpio_match,
},
};
module_platform_driver(axp20x_gpio_driver);
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
MODULE_DESCRIPTION("AXP20x PMIC GPIO driver");
MODULE_LICENSE("GPL");
......@@ -308,7 +308,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
return 0;
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "bcm-kona-gpio",
.owner = THIS_MODULE,
.request = bcm_kona_gpio_request,
......
......@@ -184,7 +184,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
return irq;
}
static struct gpio_chip reference_gp = {
static const struct gpio_chip reference_gp = {
.label = "da9052-gpio",
.owner = THIS_MODULE,
.get = da9052_gpio_get,
......
......@@ -121,7 +121,7 @@ static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
DA9055_IRQ_GPI0 + offset);
}
static struct gpio_chip reference_gp = {
static const struct gpio_chip reference_gp = {
.label = "da9055-gpio",
.owner = THIS_MODULE,
.get = da9055_gpio_get,
......
......@@ -214,8 +214,7 @@ static struct f7188x_gpio_bank f81866_gpio_bank[] = {
static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
int err;
struct f7188x_gpio_bank *bank =
container_of(chip, struct f7188x_gpio_bank, chip);
struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
struct f7188x_sio *sio = bank->data->sio;
u8 dir;
......
/*
* GPIO driver for the Diamond Systems GPIO-MM
* Copyright (C) 2016 William Breathitt Gray
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* This driver supports the following Diamond Systems devices: GPIO-MM and
* GPIO-MM-12.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#define GPIOMM_EXTENT 8
#define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
static unsigned int base[MAX_NUM_GPIOMM];
static unsigned int num_gpiomm;
module_param_array(base, uint, &num_gpiomm, 0);
MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
/**
* struct gpiomm_gpio - GPIO device private data structure
* @chip: instance of the gpio_chip
* @io_state: bit I/O state (whether bit is set to input or output)
* @out_state: output bits state
* @control: Control registers state
* @lock: synchronization lock to prevent I/O race conditions
* @base: base port address of the GPIO device
*/
struct gpiomm_gpio {
struct gpio_chip chip;
unsigned char io_state[6];
unsigned char out_state[6];
unsigned char control[2];
spinlock_t lock;
unsigned int base;
};
static int gpiomm_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
return !!(gpiommgpio->io_state[port] & mask);
}
static int gpiomm_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
const unsigned int io_port = offset / 8;
const unsigned int control_port = io_port / 3;
const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4;
unsigned long flags;
unsigned int control;
spin_lock_irqsave(&gpiommgpio->lock, flags);
/* Check if configuring Port C */
if (io_port == 2 || io_port == 5) {
/* Port C can be configured by nibble */
if (offset % 8 > 3) {
gpiommgpio->io_state[io_port] |= 0xF0;
gpiommgpio->control[control_port] |= BIT(3);
} else {
gpiommgpio->io_state[io_port] |= 0x0F;
gpiommgpio->control[control_port] |= BIT(0);
}
} else {
gpiommgpio->io_state[io_port] |= 0xFF;
if (io_port == 0 || io_port == 3)
gpiommgpio->control[control_port] |= BIT(4);
else
gpiommgpio->control[control_port] |= BIT(1);
}
control = BIT(7) | gpiommgpio->control[control_port];
outb(control, control_addr);
spin_unlock_irqrestore(&gpiommgpio->lock, flags);
return 0;
}
static int gpiomm_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
const unsigned int io_port = offset / 8;
const unsigned int control_port = io_port / 3;
const unsigned int mask = BIT(offset % 8);
const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4;
const unsigned int out_port = (io_port > 2) ? io_port + 1 : io_port;
unsigned long flags;
unsigned int control;
spin_lock_irqsave(&gpiommgpio->lock, flags);
/* Check if configuring Port C */
if (io_port == 2 || io_port == 5) {
/* Port C can be configured by nibble */
if (offset % 8 > 3) {
gpiommgpio->io_state[io_port] &= 0x0F;
gpiommgpio->control[control_port] &= ~BIT(3);
} else {
gpiommgpio->io_state[io_port] &= 0xF0;
gpiommgpio->control[control_port] &= ~BIT(0);
}
} else {
gpiommgpio->io_state[io_port] &= 0x00;
if (io_port == 0 || io_port == 3)
gpiommgpio->control[control_port] &= ~BIT(4);
else
gpiommgpio->control[control_port] &= ~BIT(1);
}
if (value)
gpiommgpio->out_state[io_port] |= mask;
else
gpiommgpio->out_state[io_port] &= ~mask;
control = BIT(7) | gpiommgpio->control[control_port];
outb(control, control_addr);
outb(gpiommgpio->out_state[io_port], gpiommgpio->base + out_port);
spin_unlock_irqrestore(&gpiommgpio->lock, flags);
return 0;
}
static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
const unsigned int in_port = (port > 2) ? port + 1 : port;
unsigned long flags;
unsigned int port_state;
spin_lock_irqsave(&gpiommgpio->lock, flags);
/* ensure that GPIO is set for input */
if (!(gpiommgpio->io_state[port] & mask)) {
spin_unlock_irqrestore(&gpiommgpio->lock, flags);
return -EINVAL;
}
port_state = inb(gpiommgpio->base + in_port);
spin_unlock_irqrestore(&gpiommgpio->lock, flags);
return !!(port_state & mask);
}
static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
const unsigned int out_port = (port > 2) ? port + 1 : port;
unsigned long flags;
spin_lock_irqsave(&gpiommgpio->lock, flags);
if (value)
gpiommgpio->out_state[port] |= mask;
else
gpiommgpio->out_state[port] &= ~mask;
outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port);
spin_unlock_irqrestore(&gpiommgpio->lock, flags);
}
static int gpiomm_probe(struct device *dev, unsigned int id)
{
struct gpiomm_gpio *gpiommgpio;
const char *const name = dev_name(dev);
int err;
gpiommgpio = devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL);
if (!gpiommgpio)
return -ENOMEM;
if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
base[id], base[id] + GPIOMM_EXTENT);
return -EBUSY;
}
gpiommgpio->chip.label = name;
gpiommgpio->chip.parent = dev;
gpiommgpio->chip.owner = THIS_MODULE;
gpiommgpio->chip.base = -1;
gpiommgpio->chip.ngpio = 48;
gpiommgpio->chip.get_direction = gpiomm_gpio_get_direction;
gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input;
gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output;
gpiommgpio->chip.get = gpiomm_gpio_get;
gpiommgpio->chip.set = gpiomm_gpio_set;
gpiommgpio->base = base[id];
spin_lock_init(&gpiommgpio->lock);
dev_set_drvdata(dev, gpiommgpio);
err = gpiochip_add_data(&gpiommgpio->chip, gpiommgpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
}
/* initialize all GPIO as output */
outb(0x80, base[id] + 3);
outb(0x00, base[id]);
outb(0x00, base[id] + 1);
outb(0x00, base[id] + 2);
outb(0x80, base[id] + 7);
outb(0x00, base[id] + 4);
outb(0x00, base[id] + 5);
outb(0x00, base[id] + 6);
return 0;
}
static int gpiomm_remove(struct device *dev, unsigned int id)
{
struct gpiomm_gpio *const gpiommgpio = dev_get_drvdata(dev);
gpiochip_remove(&gpiommgpio->chip);
return 0;
}
static struct isa_driver gpiomm_driver = {
.probe = gpiomm_probe,
.driver = {
.name = "gpio-mm"
},
.remove = gpiomm_remove
};
module_isa_driver(gpiomm_driver, num_gpiomm);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver");
MODULE_LICENSE("GPL v2");
......@@ -14,10 +14,10 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/platform_data/gpio-htc-egpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mfd/htc-egpio.h>
struct egpio_chip {
int reg_start;
......
......@@ -10,111 +10,40 @@
* your option) any later version.
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <linux/io.h>
#define IOP3XX_N_GPIOS 8
#define GPIO_IN 0
#define GPIO_OUT 1
#define GPIO_LOW 0
#define GPIO_HIGH 1
/* Memory base offset */
static void __iomem *base;
#define IOP3XX_GPIO_REG(reg) (base + (reg))
#define IOP3XX_GPOE IOP3XX_GPIO_REG(0x0000)
#define IOP3XX_GPID IOP3XX_GPIO_REG(0x0004)
#define IOP3XX_GPOD IOP3XX_GPIO_REG(0x0008)
static void gpio_line_config(int line, int direction)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = readl(IOP3XX_GPOE);
if (direction == GPIO_IN) {
val |= BIT(line);
} else if (direction == GPIO_OUT) {
val &= ~BIT(line);
}
writel(val, IOP3XX_GPOE);
local_irq_restore(flags);
}
static int gpio_line_get(int line)
{
return !!(readl(IOP3XX_GPID) & BIT(line));
}
static void gpio_line_set(int line, int value)
{
unsigned long flags;
u32 val;
local_irq_save(flags);
val = readl(IOP3XX_GPOD);
if (value == GPIO_LOW) {
val &= ~BIT(line);
} else if (value == GPIO_HIGH) {
val |= BIT(line);
}
writel(val, IOP3XX_GPOD);
local_irq_restore(flags);
}
static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
gpio_line_config(gpio, GPIO_IN);
return 0;
}
static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
{
gpio_line_set(gpio, level);
gpio_line_config(gpio, GPIO_OUT);
return 0;
}
static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
return gpio_line_get(gpio);
}
static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
{
gpio_line_set(gpio, value);
}
static struct gpio_chip iop3xx_chip = {
.label = "iop3xx",
.direction_input = iop3xx_gpio_direction_input,
.get = iop3xx_gpio_get_value,
.direction_output = iop3xx_gpio_direction_output,
.set = iop3xx_gpio_set_value,
.base = 0,
.ngpio = IOP3XX_N_GPIOS,
};
#define IOP3XX_GPOE 0x0000
#define IOP3XX_GPID 0x0004
#define IOP3XX_GPOD 0x0008
static int iop3xx_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
struct gpio_chip *gc;
void __iomem *base;
int err;
gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
if (!gc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
return devm_gpiochip_add_data(&pdev->dev, &iop3xx_chip, NULL);
err = bgpio_init(gc, &pdev->dev, 1, base + IOP3XX_GPID,
base + IOP3XX_GPOD, NULL, NULL, base + IOP3XX_GPOE, 0);
if (err)
return err;
gc->base = 0;
gc->owner = THIS_MODULE;
return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
}
static struct platform_driver iop3xx_gpio_driver = {
......
......@@ -273,7 +273,7 @@ static int it87_gpio_direction_out(struct gpio_chip *chip,
return rc;
}
static struct gpio_chip it87_template_chip = {
static const struct gpio_chip it87_template_chip = {
.label = KBUILD_MODNAME,
.owner = THIS_MODULE,
.request = it87_gpio_request,
......
......@@ -8,6 +8,7 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
......@@ -55,11 +56,6 @@ static int ls1x_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to get I/O memory\n");
return -EINVAL;
}
gpio_reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(gpio_reg_base))
return PTR_ERR(gpio_reg_base);
......
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
* Keerthy <j-keerthy@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether expressed or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License version 2 for more details.
*
* Based on the TPS65218 driver
*/
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/lp873x.h>
#define BITS_PER_GPO 0x4
#define LP873X_GPO_CTRL_OD 0x2
struct lp873x_gpio {
struct gpio_chip chip;
struct lp873x *lp873;
};
static int lp873x_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
/* This device is output only */
return 0;
}
static int lp873x_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
/* This device is output only */
return -EINVAL;
}
static int lp873x_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct lp873x_gpio *gpio = gpiochip_get_data(chip);
/* Set the initial value */
return regmap_update_bits(gpio->lp873->regmap, LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO),
value ? BIT(offset * BITS_PER_GPO) : 0);
}
static int lp873x_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct lp873x_gpio *gpio = gpiochip_get_data(chip);
int ret, val;
ret = regmap_read(gpio->lp873->regmap, LP873X_REG_GPO_CTRL, &val);
if (ret < 0)
return ret;
return val & BIT(offset * BITS_PER_GPO);
}
static void lp873x_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct lp873x_gpio *gpio = gpiochip_get_data(chip);
regmap_update_bits(gpio->lp873->regmap, LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO),
value ? BIT(offset * BITS_PER_GPO) : 0);
}
static int lp873x_gpio_request(struct gpio_chip *gc, unsigned int offset)
{
struct lp873x_gpio *gpio = gpiochip_get_data(gc);
int ret;
switch (offset) {
case 0:
/* No MUX Set up Needed for GPO */
break;
case 1:
/* Setup the CLKIN_PIN_SEL MUX to GPO2 */
ret = regmap_update_bits(gpio->lp873->regmap, LP873X_REG_CONFIG,
LP873X_CONFIG_CLKIN_PIN_SEL, 0);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
return 0;
}
static int lp873x_gpio_set_single_ended(struct gpio_chip *gc,
unsigned int offset,
enum single_ended_mode mode)
{
struct lp873x_gpio *gpio = gpiochip_get_data(gc);
switch (mode) {
case LINE_MODE_OPEN_DRAIN:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD),
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD));
case LINE_MODE_PUSH_PULL:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD), 0);
default:
return -ENOTSUPP;
}
}
static const struct gpio_chip template_chip = {
.label = "lp873x-gpio",
.owner = THIS_MODULE,
.request = lp873x_gpio_request,
.get_direction = lp873x_gpio_get_direction,
.direction_input = lp873x_gpio_direction_input,
.direction_output = lp873x_gpio_direction_output,
.get = lp873x_gpio_get,
.set = lp873x_gpio_set,
.set_single_ended = lp873x_gpio_set_single_ended,
.base = -1,
.ngpio = 2,
.can_sleep = true,
};
static int lp873x_gpio_probe(struct platform_device *pdev)
{
struct lp873x_gpio *gpio;
int ret;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
platform_set_drvdata(pdev, gpio);
gpio->lp873 = dev_get_drvdata(pdev->dev.parent);
gpio->chip = template_chip;
gpio->chip.parent = gpio->lp873->dev;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
return ret;
}
return 0;
}
static const struct platform_device_id lp873x_gpio_id_table[] = {
{ "lp873x-gpio", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, lp873x_gpio_id_table);
static struct platform_driver lp873x_gpio_driver = {
.driver = {
.name = "lp873x-gpio",
},
.probe = lp873x_gpio_probe,
.id_table = lp873x_gpio_id_table,
};
module_platform_driver(lp873x_gpio_driver);
MODULE_AUTHOR("Keerthy <j-keerthy@ti.com>");
MODULE_DESCRIPTION("LP873X GPIO driver");
MODULE_LICENSE("GPL v2");
......@@ -78,7 +78,7 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip,
return lpc18xx_gpio_direction(chip, offset, true);
}
static struct gpio_chip lpc18xx_chip = {
static const struct gpio_chip lpc18xx_chip = {
.label = "lpc18xx/43xx-gpio",
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
......
......@@ -25,7 +25,6 @@
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/platform_data/gpio-lpc32xx.h>
#include <mach/hardware.h>
#include <mach/platform.h>
......@@ -68,6 +67,20 @@
#define GPI3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
#define GPO3_PIN_IN_SEL(x, y) (((x) >> (y)) & 1)
#define LPC32XX_GPIO_P0_MAX 8
#define LPC32XX_GPIO_P1_MAX 24
#define LPC32XX_GPIO_P2_MAX 13
#define LPC32XX_GPIO_P3_MAX 6
#define LPC32XX_GPI_P3_MAX 29
#define LPC32XX_GPO_P3_MAX 24
#define LPC32XX_GPIO_P0_GRP 0
#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
struct gpio_regs {
void __iomem *inp_state;
void __iomem *outp_state;
......
......@@ -573,6 +573,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
#ifdef CONFIG_OF
static const struct of_device_id bgpio_of_match[] = {
{ .compatible = "brcm,bcm6345-gpio" },
{ .compatible = "wd,mbl-gpio" },
{ }
};
......@@ -593,6 +594,9 @@ static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
pdata->base = -1;
if (of_device_is_big_endian(pdev->dev.of_node))
*flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
if (of_property_read_bool(pdev->dev.of_node, "no-output"))
*flags |= BGPIOF_NO_OUTPUT;
......
/*
* GPIO Testing Device Driver
*
* Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com>
* Copyright (C) 2015-2016 Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#define GPIO_NAME "gpio-mockup"
#define MAX_GC 10
enum direction {
OUT,
IN
};
/*
* struct gpio_pin_status - structure describing a GPIO status
* @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out
* @value: Configures status of the gpio as 0(low) or 1(high)
*/
struct gpio_pin_status {
enum direction dir;
bool value;
};
struct mockup_gpio_controller {
struct gpio_chip gc;
struct gpio_pin_status *stats;
};
static int gpio_mockup_ranges[MAX_GC << 1];
static int gpio_mockup_params_nr;
module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400);
const char pins_name_start = 'A';
static int mockup_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
struct mockup_gpio_controller *cntr = gpiochip_get_data(gc);
return cntr->stats[offset].value;
}
static void mockup_gpio_set(struct gpio_chip *gc, unsigned int offset,
int value)
{
struct mockup_gpio_controller *cntr = gpiochip_get_data(gc);
cntr->stats[offset].value = !!value;
}
static int mockup_gpio_dirout(struct gpio_chip *gc, unsigned int offset,
int value)
{
struct mockup_gpio_controller *cntr = gpiochip_get_data(gc);
mockup_gpio_set(gc, offset, value);
cntr->stats[offset].dir = OUT;
return 0;
}
static int mockup_gpio_dirin(struct gpio_chip *gc, unsigned int offset)
{
struct mockup_gpio_controller *cntr = gpiochip_get_data(gc);
cntr->stats[offset].dir = IN;
return 0;
}
static int mockup_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
struct mockup_gpio_controller *cntr = gpiochip_get_data(gc);
return cntr->stats[offset].dir;
}
static int mockup_gpio_add(struct device *dev,
struct mockup_gpio_controller *cntr,
const char *name, int base, int ngpio)
{
int ret;
cntr->gc.base = base;
cntr->gc.ngpio = ngpio;
cntr->gc.label = name;
cntr->gc.owner = THIS_MODULE;
cntr->gc.parent = dev;
cntr->gc.get = mockup_gpio_get;
cntr->gc.set = mockup_gpio_set;
cntr->gc.direction_output = mockup_gpio_dirout;
cntr->gc.direction_input = mockup_gpio_dirin;
cntr->gc.get_direction = mockup_gpio_get_direction;
cntr->stats = devm_kzalloc(dev, sizeof(*cntr->stats) * cntr->gc.ngpio,
GFP_KERNEL);
if (!cntr->stats) {
ret = -ENOMEM;
goto err;
}
ret = devm_gpiochip_add_data(dev, &cntr->gc, cntr);
if (ret)
goto err;
dev_info(dev, "gpio<%d..%d> add successful!", base, base + ngpio);
return 0;
err:
dev_err(dev, "gpio<%d..%d> add failed!", base, base + ngpio);
return ret;
}
static int mockup_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mockup_gpio_controller *cntr;
int ret;
int i;
int base;
int ngpio;
char chip_name[sizeof(GPIO_NAME) + 3];
if (gpio_mockup_params_nr < 2)
return -EINVAL;
cntr = devm_kzalloc(dev, sizeof(*cntr) * (gpio_mockup_params_nr >> 1),
GFP_KERNEL);
if (!cntr)
return -ENOMEM;
platform_set_drvdata(pdev, cntr);
for (i = 0; i < gpio_mockup_params_nr >> 1; i++) {
base = gpio_mockup_ranges[i * 2];
if (base == -1)
ngpio = gpio_mockup_ranges[i * 2 + 1];
else
ngpio = gpio_mockup_ranges[i * 2 + 1] - base;
if (ngpio >= 0) {
sprintf(chip_name, "%s-%c", GPIO_NAME,
pins_name_start + i);
ret = mockup_gpio_add(dev, &cntr[i],
chip_name, base, ngpio);
} else {
ret = -1;
}
if (ret) {
if (base < 0)
dev_err(dev, "gpio<%d..%d> add failed\n",
base, ngpio);
else
dev_err(dev, "gpio<%d..%d> add failed\n",
base, base + ngpio);
return ret;
}
}
return 0;
}
static struct platform_driver mockup_gpio_driver = {
.driver = {
.name = GPIO_NAME,
},
.probe = mockup_gpio_probe,
};
static struct platform_device *pdev;
static int __init mock_device_init(void)
{
int err;
pdev = platform_device_alloc(GPIO_NAME, -1);
if (!pdev)
return -ENOMEM;
err = platform_device_add(pdev);
if (err) {
platform_device_put(pdev);
return err;
}
err = platform_driver_register(&mockup_gpio_driver);
if (err) {
platform_device_unregister(pdev);
return err;
}
return 0;
}
static void __exit mock_device_exit(void)
{
platform_driver_unregister(&mockup_gpio_driver);
platform_device_unregister(pdev);
}
module_init(mock_device_init);
module_exit(mock_device_exit);
MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
MODULE_AUTHOR("Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>");
MODULE_DESCRIPTION("GPIO Testing driver");
MODULE_LICENSE("GPL v2");
......@@ -20,7 +20,6 @@
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
......@@ -328,9 +327,4 @@ static int __init platform_msic_gpio_init(void)
{
return platform_driver_register(&platform_msic_gpio_driver);
}
subsys_initcall(platform_msic_gpio_init);
MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
MODULE_DESCRIPTION("Intel Medfield MSIC GPIO driver");
MODULE_LICENSE("GPL v2");
......@@ -2,7 +2,8 @@
* MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* Based on code from Freescale,
* Based on code from Freescale Semiconductor,
* Authors: Daniel Mack, Juergen Beisert.
* Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
......@@ -33,7 +34,6 @@
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/bug.h>
enum mxc_gpio_hwtype {
......@@ -516,9 +516,3 @@ static int __init gpio_mxc_init(void)
return platform_driver_register(&mxc_gpio_driver);
}
subsys_initcall(gpio_mxc_init);
MODULE_AUTHOR("Freescale Semiconductor, "
"Daniel Mack <danielncaiaq.de>, "
"Juergen Beisert <kernel@pengutronix.de>");
MODULE_DESCRIPTION("Freescale MXC GPIO");
MODULE_LICENSE("GPL");
......@@ -152,7 +152,6 @@ static const struct of_device_id of_palmas_gpio_match[] = {
{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
{ },
};
MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
static int palmas_gpio_probe(struct platform_device *pdev)
{
......
This diff is collapsed.
......@@ -90,7 +90,7 @@ static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset)
return (gpio->buffer[offset / 8] >> (offset % 8)) & 0x1;
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "pisosr-gpio",
.owner = THIS_MODULE,
.get_direction = pisosr_gpio_get_direction,
......
......@@ -347,6 +347,10 @@ static const struct of_device_id gpio_rcar_of_table[] = {
.compatible = "renesas,gpio-r8a7795",
/* Gen3 GPIO is identical to Gen2. */
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7796",
/* Gen3 GPIO is identical to Gen2. */
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-rcar",
.data = &gpio_rcar_info_gen1,
......
......@@ -138,7 +138,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
return 0;
}
static struct gpio_chip sch_gpio_chip = {
static const struct gpio_chip sch_gpio_chip = {
.label = "sch_gpio",
.owner = THIS_MODULE,
.direction_input = sch_gpio_direction_in,
......
......@@ -12,7 +12,7 @@
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/types.h>
......@@ -183,7 +183,6 @@ static const struct of_device_id spics_gpio_of_match[] = {
{ .compatible = "st,spear-spics-gpio" },
{}
};
MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
static struct platform_driver spics_gpio_driver = {
.probe = spics_gpio_probe,
......@@ -198,7 +197,3 @@ static int __init spics_gpio_init(void)
return platform_driver_register(&spics_gpio_driver);
}
subsys_initcall(spics_gpio_init);
MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>");
MODULE_DESCRIPTION("STMicroelectronics SPEAr SPI Chip Select Abstraction");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -236,7 +236,6 @@ static const struct i2c_device_id sx150x_id[] = {
{"sx1502q", 3},
{}
};
MODULE_DEVICE_TABLE(i2c, sx150x_id);
static const struct of_device_id sx150x_of_match[] = {
{ .compatible = "semtech,sx1508q" },
......@@ -245,7 +244,6 @@ static const struct of_device_id sx150x_of_match[] = {
{ .compatible = "semtech,sx1502q" },
{},
};
MODULE_DEVICE_TABLE(of, sx150x_of_match);
static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
{
......
......@@ -34,7 +34,7 @@ struct tc3589x_gpio {
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
};
static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
......@@ -49,24 +49,24 @@ static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(ret & mask);
}
static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned int offset, int val)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
unsigned pos = offset % 8;
unsigned int pos = offset % 8;
u8 data[] = {val ? BIT(pos) : 0, BIT(pos)};
tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
}
static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int val)
unsigned int offset, int val)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
u8 reg = TC3589x_GPIODIR0 + offset / 8;
unsigned pos = offset % 8;
unsigned int pos = offset % 8;
tc3589x_gpio_set(chip, offset, val);
......@@ -74,18 +74,34 @@ static int tc3589x_gpio_direction_output(struct gpio_chip *chip,
}
static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
unsigned int offset)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
u8 reg = TC3589x_GPIODIR0 + offset / 8;
unsigned pos = offset % 8;
unsigned int pos = offset % 8;
return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0);
}
static int tc3589x_gpio_single_ended(struct gpio_chip *chip,
unsigned offset,
static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
u8 reg = TC3589x_GPIODIR0 + offset / 8;
unsigned int pos = offset % 8;
int ret;
ret = tc3589x_reg_read(tc3589x, reg);
if (ret < 0)
return ret;
return !!(ret & BIT(pos));
}
static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
......@@ -97,7 +113,7 @@ static int tc3589x_gpio_single_ended(struct gpio_chip *chip,
*/
u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2;
u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2;
unsigned pos = offset % 8;
unsigned int pos = offset % 8;
int ret;
switch(mode) {
......@@ -124,14 +140,15 @@ static int tc3589x_gpio_single_ended(struct gpio_chip *chip,
return -ENOTSUPP;
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "tc3589x",
.owner = THIS_MODULE,
.direction_input = tc3589x_gpio_direction_input,
.get = tc3589x_gpio_get,
.direction_output = tc3589x_gpio_direction_output,
.set = tc3589x_gpio_set,
.set_single_ended = tc3589x_gpio_single_ended,
.direction_output = tc3589x_gpio_direction_output,
.direction_input = tc3589x_gpio_direction_input,
.get_direction = tc3589x_gpio_get_direction,
.set_single_ended = tc3589x_gpio_set_single_ended,
.can_sleep = true,
};
......
......@@ -87,7 +87,7 @@ static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask,
tpic2810_set_mask_bits(chip, *mask, *bits);
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "tpic2810",
.owner = THIS_MODULE,
.get_direction = tpic2810_get_direction,
......
......@@ -72,7 +72,7 @@ static void tps65086_gpio_set(struct gpio_chip *chip, unsigned offset,
BIT(4 + offset), value ? BIT(4 + offset) : 0);
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "tps65086-gpio",
.owner = THIS_MODULE,
.get_direction = tps65086_gpio_get_direction,
......
......@@ -172,7 +172,7 @@ static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
return -ENOTSUPP;
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "gpio-tps65218",
.owner = THIS_MODULE,
.request = tps65218_gpio_request,
......@@ -204,7 +204,8 @@ static int tps65218_gpio_probe(struct platform_device *pdev)
tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node;
#endif
ret = gpiochip_add_data(&tps65218_gpio->gpio_chip, tps65218_gpio);
ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip,
tps65218_gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
return ret;
......@@ -215,15 +216,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev)
return ret;
}
static int tps65218_gpio_remove(struct platform_device *pdev)
{
struct tps65218_gpio *tps65218_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&tps65218_gpio->gpio_chip);
return 0;
}
static const struct of_device_id tps65218_dt_match[] = {
{ .compatible = "ti,tps65218-gpio" },
{ }
......@@ -242,7 +234,6 @@ static struct platform_driver tps65218_gpio_driver = {
.of_match_table = of_match_ptr(tps65218_dt_match)
},
.probe = tps65218_gpio_probe,
.remove = tps65218_gpio_remove,
.id_table = tps65218_gpio_id_table,
};
......
......@@ -90,7 +90,7 @@ static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset,
GPIO_SET_MASK, value ? GPIO_SET_MASK : 0);
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "tps65912-gpio",
.owner = THIS_MODULE,
.get_direction = tps65912_gpio_get_direction,
......
......@@ -9,6 +9,7 @@
*/
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
......
/*
* Digital I/O driver for Technologic Systems I2C FPGA Core
*
* Copyright (C) 2015 Technologic Systems
* Copyright (C) 2016 Savoir-Faire Linux
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether expressed or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License version 2 for more details.
*/
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/regmap.h>
#define DEFAULT_PIN_NUMBER 32
/*
* Register bits used by the GPIO device
* Some boards, such as TS-7970 do not have a separate input bit
*/
#define TS4900_GPIO_OE 0x01
#define TS4900_GPIO_OUT 0x02
#define TS4900_GPIO_IN 0x04
#define TS7970_GPIO_IN 0x02
struct ts4900_gpio_priv {
struct regmap *regmap;
struct gpio_chip gpio_chip;
unsigned int input_bit;
};
static int ts4900_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
unsigned int reg;
regmap_read(priv->regmap, offset, &reg);
return !(reg & TS4900_GPIO_OE);
}
static int ts4900_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
/*
* This will clear the output enable bit, the other bits are
* dontcare when this is cleared
*/
return regmap_write(priv->regmap, offset, 0);
}
static int ts4900_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
int ret;
if (value)
ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
TS4900_GPIO_OUT);
else
ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE);
return ret;
}
static int ts4900_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
unsigned int reg;
regmap_read(priv->regmap, offset, &reg);
return !!(reg & priv->input_bit);
}
static void ts4900_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
if (value)
regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT,
TS4900_GPIO_OUT);
else
regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 0);
}
static const struct regmap_config ts4900_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
};
static const struct gpio_chip template_chip = {
.label = "ts4900-gpio",
.owner = THIS_MODULE,
.get_direction = ts4900_gpio_get_direction,
.direction_input = ts4900_gpio_direction_input,
.direction_output = ts4900_gpio_direction_output,
.get = ts4900_gpio_get,
.set = ts4900_gpio_set,
.base = -1,
.can_sleep = true,
};
static const struct of_device_id ts4900_gpio_of_match_table[] = {
{
.compatible = "technologic,ts4900-gpio",
.data = (void *)TS4900_GPIO_IN,
}, {
.compatible = "technologic,ts7970-gpio",
.data = (void *)TS7970_GPIO_IN,
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table);
static int ts4900_gpio_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct of_device_id *match;
struct ts4900_gpio_priv *priv;
u32 ngpio;
int ret;
match = of_match_device(ts4900_gpio_of_match_table, &client->dev);
if (!match)
return -EINVAL;
if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio))
ngpio = DEFAULT_PIN_NUMBER;
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->gpio_chip = template_chip;
priv->gpio_chip.label = "ts4900-gpio";
priv->gpio_chip.ngpio = ngpio;
priv->gpio_chip.parent = &client->dev;
priv->input_bit = (uintptr_t)match->data;
priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config);
if (IS_ERR(priv->regmap)) {
ret = PTR_ERR(priv->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
ret = devm_gpiochip_add_data(&client->dev, &priv->gpio_chip, priv);
if (ret < 0) {
dev_err(&client->dev, "Unable to register gpiochip\n");
return ret;
}
i2c_set_clientdata(client, priv);
return 0;
}
static const struct i2c_device_id ts4900_gpio_id_table[] = {
{ "ts4900-gpio", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, ts4900_gpio_id_table);
static struct i2c_driver ts4900_gpio_driver = {
.driver = {
.name = "ts4900-gpio",
.of_match_table = ts4900_gpio_of_match_table,
},
.probe = ts4900_gpio_probe,
.id_table = ts4900_gpio_id_table,
};
module_i2c_driver(ts4900_gpio_driver);
MODULE_AUTHOR("Technologic Systems");
MODULE_DESCRIPTION("GPIO interface for Technologic Systems I2C-FPGA core");
MODULE_LICENSE("GPL");
......@@ -381,7 +381,7 @@ static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
: -EINVAL;
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "twl4030",
.owner = THIS_MODULE,
.request = twl_request,
......
/*
* vf610 GPIO support through PORT and GPIO module
* Freescale vf610 GPIO support through PORT and GPIO
*
* Copyright (c) 2014 Toradex AG.
*
......@@ -23,7 +23,6 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
......@@ -289,7 +288,3 @@ static int __init gpio_vf610_init(void)
return platform_driver_register(&vf610_gpio_driver);
}
device_initcall(gpio_vf610_init);
MODULE_AUTHOR("Stefan Agner <stefan@agner.ch>");
MODULE_DESCRIPTION("Freescale VF610 GPIO");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
......@@ -247,7 +247,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define wm831x_gpio_dbg_show NULL
#endif
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "wm831x",
.owner = THIS_MODULE,
.direction_input = wm831x_gpio_direction_in,
......
......@@ -93,7 +93,7 @@ static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
}
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "wm8350",
.owner = THIS_MODULE,
.direction_input = wm8350_gpio_direction_in,
......
......@@ -249,7 +249,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#define wm8994_gpio_dbg_show NULL
#endif
static struct gpio_chip template_chip = {
static const struct gpio_chip template_chip = {
.label = "wm8994",
.owner = THIS_MODULE,
.request = wm8994_gpio_request,
......
......@@ -96,6 +96,9 @@
/* GPIO upper 16 bit mask */
#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
/* For GPIO quirks */
#define ZYNQ_GPIO_QUIRK_FOO BIT(0)
/**
* struct zynq_gpio - gpio device private data structure
* @chip: instance of the gpio_chip
......@@ -122,6 +125,7 @@ struct zynq_gpio {
*/
struct zynq_platform_data {
const char *label;
u32 quirks;
u16 ngpio;
int max_bank;
int bank_min[ZYNQMP_GPIO_MAX_BANK];
......@@ -238,13 +242,19 @@ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
u32 reg;
bool is_zynq_gpio;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = gpiochip_get_data(chip);
is_zynq_gpio = gpio->p_data->quirks & ZYNQ_GPIO_QUIRK_FOO;
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
/* bank 0 pins 7 and 8 are special and cannot be used as inputs */
if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
/*
* On zynq bank 0 pins 7 and 8 are special and cannot be used
* as inputs.
*/
if (is_zynq_gpio && bank_num == 0 &&
(bank_pin_num == 7 || bank_pin_num == 8))
return -EINVAL;
/* clear the bit in direction mode reg to set the pin as input */
......@@ -627,6 +637,7 @@ static const struct zynq_platform_data zynqmp_gpio_def = {
static const struct zynq_platform_data zynq_gpio_def = {
.label = "zynq_gpio",
.quirks = ZYNQ_GPIO_QUIRK_FOO,
.ngpio = ZYNQ_GPIO_NR_GPIOS,
.max_bank = ZYNQ_GPIO_MAX_BANK,
.bank_min[0] = ZYNQ_GPIO_BANK0_PIN_MIN(),
......
......@@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/export.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
......@@ -395,7 +396,7 @@ struct acpi_gpio_lookup {
int n;
};
static int acpi_find_gpio(struct acpi_resource *ares, void *data)
static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
{
struct acpi_gpio_lookup *lookup = data;
......@@ -440,7 +441,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
INIT_LIST_HEAD(&res_list);
ret = acpi_dev_get_resources(lookup->adev, &res_list, acpi_find_gpio,
ret = acpi_dev_get_resources(lookup->adev, &res_list,
acpi_populate_gpio_lookup,
lookup);
if (ret < 0)
return ret;
......@@ -513,7 +515,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
* Note: if the GPIO resource has multiple entries in the pin list, this
* function only returns the first.
*/
struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
const char *propname, int index,
struct acpi_gpio_info *info)
{
......@@ -546,6 +548,55 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ret ? ERR_PTR(ret) : lookup.desc;
}
struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags flags,
enum gpio_lookup_flags *lookupflags)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_gpio_info info;
struct gpio_desc *desc;
char propname[32];
int i;
/* Try first from _DSD */
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id && strcmp(con_id, "gpios")) {
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
} else {
snprintf(propname, sizeof(propname), "%s",
gpio_suffixes[i]);
}
desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
break;
}
/* Then from plain _CRS GPIOs */
if (IS_ERR(desc)) {
if (!acpi_can_fallback_to_crs(adev, con_id))
return ERR_PTR(-ENOENT);
desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
if (IS_ERR(desc))
return desc;
if ((flags == GPIOD_OUT_LOW || flags == GPIOD_OUT_HIGH) &&
info.gpioint) {
dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
return ERR_PTR(-ENOENT);
}
}
if (info.polarity == GPIO_ACTIVE_LOW)
*lookupflags |= GPIO_ACTIVE_LOW;
return desc;
}
/**
* acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources
* @fwnode: pointer to an ACPI firmware node to get the GPIO information from
......
......@@ -113,6 +113,45 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags)
{
char prop_name[32]; /* 32 is max size of property name */
enum of_gpio_flags of_flags;
struct gpio_desc *desc;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
gpio_suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
gpio_suffixes[i]);
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
break;
}
if (IS_ERR(desc))
return desc;
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW;
if (of_flags & OF_GPIO_SINGLE_ENDED) {
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_OPEN_DRAIN;
else
*flags |= GPIO_OPEN_SOURCE;
}
return desc;
}
/**
* of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API
* @np: device node to get GPIO from
......
......@@ -670,10 +670,10 @@ int gpiod_export_link(struct device *dev, const char *name,
EXPORT_SYMBOL_GPL(gpiod_export_link);
/**
* gpiod_unexport - reverse effect of gpio_export()
* gpiod_unexport - reverse effect of gpiod_export()
* @gpio: gpio to make unavailable
*
* This is implicit on gpio_free().
* This is implicit on gpiod_free().
*/
void gpiod_unexport(struct gpio_desc *desc)
{
......
......@@ -1370,19 +1370,15 @@ struct gpio_chip *gpiochip_find(void *data,
void *data))
{
struct gpio_device *gdev;
struct gpio_chip *chip;
struct gpio_chip *chip = NULL;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list)
if (gdev->chip && match(gdev->chip, data))
break;
/* No match? */
if (&gdev->list == &gpio_devices)
chip = NULL;
else
if (gdev->chip && match(gdev->chip, data)) {
chip = gdev->chip;
break;
}
spin_unlock_irqrestore(&gpio_lock, flags);
......@@ -1667,6 +1663,20 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
if (gpiochip->of_node)
of_node = gpiochip->of_node;
#endif
/*
* Specifying a default trigger is a terrible idea if DT or ACPI is
* used to configure the interrupts, as you may end-up with
* conflicting triggers. Tell the user, and reset to NONE.
*/
if (WARN(of_node && type != IRQ_TYPE_NONE,
"%s: Ignoring %d default trigger\n", of_node->full_name, type))
type = IRQ_TYPE_NONE;
if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {
acpi_handle_warn(ACPI_HANDLE(gpiochip->parent),
"Ignoring %d default trigger\n", type);
type = IRQ_TYPE_NONE;
}
gpiochip->irqchip = irqchip;
gpiochip->irq_handler = handler;
gpiochip->irq_default_type = type;
......@@ -2873,94 +2883,6 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
mutex_unlock(&gpio_lookup_lock);
}
static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags)
{
char prop_name[32]; /* 32 is max size of property name */
enum of_gpio_flags of_flags;
struct gpio_desc *desc;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s", con_id,
gpio_suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
gpio_suffixes[i]);
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
break;
}
if (IS_ERR(desc))
return desc;
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW;
if (of_flags & OF_GPIO_SINGLE_ENDED) {
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_OPEN_DRAIN;
else
*flags |= GPIO_OPEN_SOURCE;
}
return desc;
}
static struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags flags,
enum gpio_lookup_flags *lookupflags)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_gpio_info info;
struct gpio_desc *desc;
char propname[32];
int i;
/* Try first from _DSD */
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id && strcmp(con_id, "gpios")) {
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
} else {
snprintf(propname, sizeof(propname), "%s",
gpio_suffixes[i]);
}
desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
break;
}
/* Then from plain _CRS GPIOs */
if (IS_ERR(desc)) {
if (!acpi_can_fallback_to_crs(adev, con_id))
return ERR_PTR(-ENOENT);
desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
if (IS_ERR(desc))
return desc;
if ((flags == GPIOD_OUT_LOW || flags == GPIOD_OUT_HIGH) &&
info.gpioint) {
dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
return ERR_PTR(-ENOENT);
}
}
if (info.polarity == GPIO_ACTIVE_LOW)
*lookupflags |= GPIO_ACTIVE_LOW;
return desc;
}
static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
......
......@@ -20,6 +20,7 @@
enum of_gpio_flags;
enum gpiod_flags;
enum gpio_lookup_flags;
struct acpi_device;
/**
......@@ -86,6 +87,32 @@ struct acpi_gpio_info {
/* gpio suffixes used for ACPI and device tree lookup */
static const char * const gpio_suffixes[] = { "gpios", "gpio" };
#ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags);
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
#else
static inline struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpio_lookup_flags *flags)
{
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags)
{
return ERR_PTR(-ENOENT);
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
......@@ -93,9 +120,11 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
const char *propname, int index,
struct acpi_gpio_info *info);
struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags flags,
enum gpio_lookup_flags *lookupflags);
struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
struct acpi_gpio_info *info);
......@@ -114,10 +143,11 @@ static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline struct gpio_desc *
acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
int index, struct acpi_gpio_info *info)
acpi_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, enum gpiod_flags flags,
enum gpio_lookup_flags *lookupflags)
{
return ERR_PTR(-ENOSYS);
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *
acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
......@@ -137,9 +167,6 @@ static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
}
#endif
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
void gpiod_set_array_value_complex(bool raw, bool can_sleep,
unsigned int array_size,
......
......@@ -340,14 +340,6 @@ config MFD_HI655X_PMIC
help
Select this option to enable Hisilicon hi655x series pmic driver.
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GPIOLIB && ARM
help
This driver supports the CPLD egpio chip present on
several HTC phones. It provides basic support for input
pins, output pins, and irqs.
config HTC_PASIC3
tristate "HTC PASIC3 LED/DS1WM chip support"
select MFD_CORE
......@@ -1224,6 +1216,20 @@ config MFD_TPS65217
This driver can also be built as a module. If so, the module
will be called tps65217.
config MFD_TI_LP873X
tristate "TI LP873X Power Management IC"
depends on I2C
select MFD_CORE
select REGMAP_I2C
help
If you say yes here then you get support for the LP873X series of
Power Management Integrated Circuits (PMIC).
These include voltage regulators, thermal protection, configurable
General Purpose Outputs (GPO) that are used in portable devices.
This driver can also be built as a module. If so, the module
will be called lp873x.
config MFD_TPS65218
tristate "TI TPS65218 Power Management chips"
depends on I2C
......
......@@ -18,10 +18,11 @@ rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o
obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
......
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
*
* Author: Keerthy <j-keerthy@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/lp873x.h>
static const struct regmap_config lp873x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LP873X_REG_MAX,
};
static const struct mfd_cell lp873x_cells[] = {
{ .name = "lp873x-regulator", },
{ .name = "lp873x-gpio", },
};
static int lp873x_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct lp873x *lp873;
int ret;
unsigned int otpid;
lp873 = devm_kzalloc(&client->dev, sizeof(*lp873), GFP_KERNEL);
if (!lp873)
return -ENOMEM;
lp873->dev = &client->dev;
lp873->regmap = devm_regmap_init_i2c(client, &lp873x_regmap_config);
if (IS_ERR(lp873->regmap)) {
ret = PTR_ERR(lp873->regmap);
dev_err(lp873->dev,
"Failed to initialize register map: %d\n", ret);
return ret;
}
mutex_init(&lp873->lock);
ret = regmap_read(lp873->regmap, LP873X_REG_OTP_REV, &otpid);
if (ret) {
dev_err(lp873->dev, "Failed to read OTP ID\n");
return ret;
}
lp873->rev = otpid & LP873X_OTP_REV_OTP_ID;
i2c_set_clientdata(client, lp873);
ret = mfd_add_devices(lp873->dev, PLATFORM_DEVID_AUTO, lp873x_cells,
ARRAY_SIZE(lp873x_cells), NULL, 0, NULL);
return ret;
}
static const struct of_device_id of_lp873x_match_table[] = {
{ .compatible = "ti,lp8733", },
{ .compatible = "ti,lp8732", },
{}
};
MODULE_DEVICE_TABLE(of, of_lp873x_match_table);
static const struct i2c_device_id lp873x_id_table[] = {
{ "lp873x", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, lp873x_id_table);
static struct i2c_driver lp873x_driver = {
.driver = {
.name = "lp873x",
.of_match_table = of_lp873x_match_table,
},
.probe = lp873x_probe,
.id_table = lp873x_id_table,
};
module_i2c_driver(lp873x_driver);
MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
MODULE_DESCRIPTION("LP873X chip family Multi-Function Device driver");
MODULE_LICENSE("GPL v2");
......@@ -57,6 +57,7 @@ static const struct of_device_id stmpe_of_match[] = {
{ .compatible = "st,stmpe610", .data = (void *)STMPE610, },
{ .compatible = "st,stmpe801", .data = (void *)STMPE801, },
{ .compatible = "st,stmpe811", .data = (void *)STMPE811, },
{ .compatible = "st,stmpe1600", .data = (void *)STMPE1600, },
{ .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
{ .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
{ .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
......@@ -101,6 +102,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = {
{ "stmpe610", STMPE610 },
{ "stmpe801", STMPE801 },
{ "stmpe811", STMPE811 },
{ "stmpe1600", STMPE1600 },
{ "stmpe1601", STMPE1601 },
{ "stmpe1801", STMPE1801 },
{ "stmpe2401", STMPE2401 },
......
This diff is collapsed.
This diff is collapsed.
......@@ -29,7 +29,6 @@
#include <linux/slab.h>
#include "../core.h"
#include "../../gpio/gpiolib.h"
#include "pinctrl-sunxi.h"
static struct irq_chip sunxi_pinctrl_edge_irq_chip;
......
......@@ -323,7 +323,7 @@ config REGULATOR_LP872X
config REGULATOR_LP873X
tristate "TI LP873X Power regulators"
depends on MFD_LP873X && OF
depends on MFD_TI_LP873X && OF
help
This driver supports LP873X voltage regulator chips. LP873X
provides two step-down converters and two general-purpose LDO
......
......@@ -3,7 +3,6 @@
#include <linux/device.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
......@@ -16,6 +15,7 @@ struct of_phandle_args;
struct device_node;
struct seq_file;
struct gpio_device;
struct module;
#ifdef CONFIG_GPIOLIB
......
This diff is collapsed.
This diff is collapsed.
......@@ -61,8 +61,6 @@ static inline int of_mm_gpiochip_add(struct device_node *np,
}
extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
extern int of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec,
u32 *flags);
......@@ -86,9 +84,6 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
return -ENOSYS;
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */
/**
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment