Commit 1b2951dd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.17-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.17 kernel cycle:

  New drivers:

   - Nintendo Wii GameCube GPIO, known as "Hollywood"

   - Raspberry Pi mailbox service GPIO expander

   - Spreadtrum main SC9860 SoC and IEC GPIO controllers.

  Improvements:

   - Implemented .get_multiple() callback for most of the
     high-performance industrial GPIO cards for the ISA bus.

   - ISA GPIO drivers now select the ISA_BUS_API instead of depending on
     it. This is merged with the same pattern for all the ISA drivers
     and some other Kconfig cleanups related to this.

  Cleanup:

   - Delete the TZ1090 GPIO drivers following the deletion of this SoC
     from the ARM tree.

   - Move the documentation over to driver-api to conform with the rest
     of the kernel documentation build.

   - Continue to make the GPIO drivers include only
     <linux/gpio/driver.h> and not the too broad <linux/gpio.h> that we
     want to get rid of.

   - Managed to remove VLA allocation from two drivers pending more
     fixes in this area for the next merge window.

   - Misc janitorial fixes"

* tag 'gpio-v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (77 commits)
  gpio: Add Spreadtrum PMIC EIC driver support
  gpio: Add Spreadtrum EIC driver support
  dt-bindings: gpio: Add Spreadtrum EIC controller documentation
  gpio: ath79: Fix potential NULL dereference in ath79_gpio_probe()
  pinctrl: qcom: Don't allow protected pins to be requested
  gpiolib: Support 'gpio-reserved-ranges' property
  gpiolib: Change bitmap allocation to kmalloc_array
  gpiolib: Extract mask allocation into subroutine
  dt-bindings: gpio: Add a gpio-reserved-ranges property
  gpio: mockup: fix a potential crash when creating debugfs entries
  gpio: pca953x: add compatibility for pcal6524 and pcal9555a
  gpio: dwapb: Add support for a bus clock
  gpio: Remove VLA from xra1403 driver
  gpio: Remove VLA from MAX3191X driver
  gpio: ws16c48: Implement get_multiple callback
  gpio: gpio-mm: Implement get_multiple callback
  gpio: 104-idi-48: Implement get_multiple callback
  gpio: 104-dio-48e: Implement get_multiple callback
  gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks
  gpio: pci-idio-16: Implement get_multiple callback
  ...
parents 06dd3dfe 348f3cde
Spreadtrum EIC controller bindings
The EIC is the abbreviation of external interrupt controller, which can
be used only in input mode. The Spreadtrum platform has 2 EIC controllers,
one is in digital chip, and another one is in PMIC. The digital chip EIC
controller contains 4 sub-modules: EIC-debounce, EIC-latch, EIC-async and
EIC-sync. But the PMIC EIC controller contains only one EIC-debounce sub-
module.
The EIC-debounce sub-module provides up to 8 source input signal
connections. A debounce mechanism is used to capture the input signals'
stable status (millisecond resolution) and a single-trigger mechanism
is introduced into this sub-module to enhance the input event detection
reliability. In addition, this sub-module's clock can be shut off
automatically to reduce power dissipation. Moreover the debounce range
is from 1ms to 4s with a step size of 1ms. The input signal will be
ignored if it is asserted for less than 1 ms.
The EIC-latch sub-module is used to latch some special power down signals
and generate interrupts, since the EIC-latch does not depend on the APB
clock to capture signals.
The EIC-async sub-module uses a 32kHz clock to capture the short signals
(microsecond resolution) to generate interrupts by level or edge trigger.
The EIC-sync is similar with GPIO's input function, which is a synchronized
signal input register. It can generate interrupts by level or edge trigger
when detecting input signals.
Required properties:
- compatible: Should be one of the following:
"sprd,sc9860-eic-debounce",
"sprd,sc9860-eic-latch",
"sprd,sc9860-eic-async",
"sprd,sc9860-eic-sync",
"sprd,sc27xx-eic".
- reg: Define the base and range of the I/O address space containing
the GPIO controller registers.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be <2>. The first cell is the gpio number and
the second cell is used to specify optional parameters.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Should be <2>. Specifies the number of cells needed
to encode interrupt source.
- interrupts: Should be the port interrupt shared by all the gpios.
Example:
eic_debounce: gpio@40210000 {
compatible = "sprd,sc9860-eic-debounce";
reg = <0 0x40210000 0 0x80>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
};
eic_latch: gpio@40210080 {
compatible = "sprd,sc9860-eic-latch";
reg = <0 0x40210080 0 0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
};
eic_async: gpio@402100a0 {
compatible = "sprd,sc9860-eic-async";
reg = <0 0x402100a0 0 0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
};
eic_sync: gpio@402100c0 {
compatible = "sprd,sc9860-eic-sync";
reg = <0 0x402100c0 0 0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
};
pmic_eic: gpio@300 {
compatible = "sprd,sc27xx-eic";
reg = <0x300>;
interrupt-parent = <&sc2731_pmic>;
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
...@@ -16,6 +16,8 @@ Required properties: ...@@ -16,6 +16,8 @@ Required properties:
nxp,pca9574 nxp,pca9574
nxp,pca9575 nxp,pca9575
nxp,pca9698 nxp,pca9698
nxp,pcal6524
nxp,pcal9555a
maxim,max7310 maxim,max7310
maxim,max7312 maxim,max7312
maxim,max7313 maxim,max7313
......
Spreadtrum GPIO controller bindings
The controller's registers are organized as sets of sixteen 16-bit
registers with each set controlling a bank of up to 16 pins. A single
interrupt is shared for all of the banks handled by the controller.
Required properties:
- compatible: Should be "sprd,sc9860-gpio".
- reg: Define the base and range of the I/O address space containing
the GPIO controller registers.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be <2>. The first cell is the gpio number and
the second cell is used to specify optional parameters.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Should be <2>. Specifies the number of cells needed
to encode interrupt source.
- interrupts: Should be the port interrupt shared by all the gpios.
Example:
ap_gpio: gpio@40280000 {
compatible = "sprd,sc9860-gpio";
reg = <0 0x40280000 0 0x1000>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
};
ImgTec TZ1090 PDC GPIO Controller
Required properties:
- compatible: Compatible property value should be "img,tz1090-pdc-gpio".
- reg: Physical base address of the controller and length of memory mapped
region. This starts at and cover the SOC_GPIO_CONTROL registers.
- gpio-controller: Specifies that the node is a gpio controller.
- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
nodes should have the following values.
<[phandle of the gpio controller node]
[PDC gpio number]
[gpio flags]>
Values for gpio specifier:
- GPIO number: a value in the range 0 to 6.
- GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
Only the following flags are supported:
GPIO_ACTIVE_HIGH
GPIO_ACTIVE_LOW
Optional properties:
- gpio-ranges: Mapping to pin controller pins (as described in
Documentation/devicetree/bindings/gpio/gpio.txt)
- interrupts: Individual syswake interrupts (other GPIOs cannot interrupt)
Example:
pdc_gpios: gpio-controller@2006500 {
gpio-controller;
#gpio-cells = <2>;
compatible = "img,tz1090-pdc-gpio";
reg = <0x02006500 0x100>;
interrupt-parent = <&pdc>;
interrupts = <8 IRQ_TYPE_NONE>, /* Syswake 0 */
<9 IRQ_TYPE_NONE>, /* Syswake 1 */
<10 IRQ_TYPE_NONE>; /* Syswake 2 */
gpio-ranges = <&pdc_pinctrl 0 0 7>;
};
ImgTec TZ1090 GPIO Controller
Required properties:
- compatible: Compatible property value should be "img,tz1090-gpio".
- reg: Physical base address of the controller and length of memory mapped
region.
- #address-cells: Should be 1 (for bank subnodes)
- #size-cells: Should be 0 (for bank subnodes)
- Each bank of GPIOs should have a subnode to represent it.
Bank subnode required properties:
- reg: Index of bank in the range 0 to 2.
- gpio-controller: Specifies that the node is a gpio controller.
- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client
nodes should have the following values.
<[phandle of the gpio controller node]
[gpio number within the gpio bank]
[gpio flags]>
Values for gpio specifier:
- GPIO number: a value in the range 0 to 29.
- GPIO flags: bit field of flags, as defined in <dt-bindings/gpio/gpio.h>.
Only the following flags are supported:
GPIO_ACTIVE_HIGH
GPIO_ACTIVE_LOW
Bank subnode optional properties:
- gpio-ranges: Mapping to pin controller pins (as described in
Documentation/devicetree/bindings/gpio/gpio.txt)
- interrupts: Interrupt for the entire bank
- interrupt-controller: Specifies that the node is an interrupt controller
- #interrupt-cells: Should be 2. The syntax of the interrupt specifier used by
client nodes should have the following values.
<[phandle of the interurupt controller]
[gpio number within the gpio bank]
[irq flags]>
Values for irq specifier:
- GPIO number: a value in the range 0 to 29
- IRQ flags: value to describe edge and level triggering, as defined in
<dt-bindings/interrupt-controller/irq.h>. Only the following flags are
supported:
IRQ_TYPE_EDGE_RISING
IRQ_TYPE_EDGE_FALLING
IRQ_TYPE_EDGE_BOTH
IRQ_TYPE_LEVEL_HIGH
IRQ_TYPE_LEVEL_LOW
Example:
gpios: gpio-controller@2005800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "img,tz1090-gpio";
reg = <0x02005800 0x90>;
/* bank 0 with an interrupt */
gpios0: bank@0 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
reg = <0>;
interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
gpio-ranges = <&pinctrl 0 0 30>;
interrupt-controller;
};
/* bank 2 without interrupt */
gpios2: bank@2 {
#gpio-cells = <2>;
reg = <2>;
gpio-controller;
gpio-ranges = <&pinctrl 0 60 30>;
};
};
...@@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using ...@@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using
first 18 GPIOs, at local offset 0 .. 17, are in use. first 18 GPIOs, at local offset 0 .. 17, are in use.
If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an
additional bitmask is needed to specify which GPIOs are actually in use, additional set of tuples is needed to specify which GPIOs are unusable, with
and which are dummies. The bindings for this case has not yet been the gpio-reserved-ranges binding. This property indicates the start and size
specified, but should be specified if/when such hardware appears. of the GPIOs that can't be used.
Optionally, a GPIO controller may have a "gpio-line-names" property. This is Optionally, a GPIO controller may have a "gpio-line-names" property. This is
an array of strings defining the names of the GPIO lines going out of the an array of strings defining the names of the GPIO lines going out of the
...@@ -178,6 +178,7 @@ gpio-controller@00000000 { ...@@ -178,6 +178,7 @@ gpio-controller@00000000 {
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <18>; ngpios = <18>;
gpio-reserved-ranges = <0 4>, <12 2>;
gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R", gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
"LED G", "LED B", "Col A", "Col B", "Col C", "Col D", "LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
"Row A", "Row B", "Row C", "Row D", "NMI button", "Row A", "Row B", "Row C", "Row D", "NMI button",
......
Nintendo Wii (Hollywood) GPIO controller
Required properties:
- compatible: "nintendo,hollywood-gpio
- reg: Physical base address and length of the controller's registers.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be <2>. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted).
Optional properties:
- ngpios: see Documentation/devicetree/bindings/gpio/gpio.txt
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Should be two.
- interrupts: Interrupt specifier for the controller's Broadway (PowerPC)
interrupt.
- interrupt-parent: phandle of the parent interrupt controller.
Example:
GPIO: gpio@d8000c0 {
#gpio-cells = <2>;
compatible = "nintendo,hollywood-gpio";
reg = <0x0d8000c0 0x40>;
gpio-controller;
ngpios = <24>;
}
Raspberry Pi GPIO expander
The Raspberry Pi 3 GPIO expander is controlled by the VC4 firmware. The
firmware exposes a mailbox interface that allows the ARM core to control the
GPIO lines on the expander.
The Raspberry Pi GPIO expander node must be a child node of the Raspberry Pi
firmware node.
Required properties:
- compatible : Should be "raspberrypi,firmware-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 the gpio polarity:
0 = active high
1 = active low
Example:
firmware: firmware-rpi {
compatible = "raspberrypi,bcm2835-firmware";
mboxes = <&mailbox>;
expgpio: gpio {
compatible = "raspberrypi,firmware-gpio";
gpio-controller;
#gpio-cells = <2>;
};
};
...@@ -152,14 +152,7 @@ Nintendo Wii device tree ...@@ -152,14 +152,7 @@ Nintendo Wii device tree
1.l) The General Purpose I/O (GPIO) controller node 1.l) The General Purpose I/O (GPIO) controller node
Represents the dual access 32 GPIO controller interface. see Documentation/devicetree/bindings/gpio/nintendo,hollywood-gpio.txt
Required properties:
- #gpio-cells : <2>
- compatible : should be "nintendo,hollywood-gpio"
- reg : should contain the IPC registers location and length
- gpio-controller
1.m) The control node 1.m) The control node
......
=============
GPIO Mappings GPIO Mappings
============= =============
...@@ -23,7 +24,7 @@ device tree bindings for your controller. ...@@ -23,7 +24,7 @@ device tree bindings for your controller.
GPIOs mappings are defined in the consumer device's node, in a property named GPIOs mappings are defined in the consumer device's node, in a property named
<function>-gpios, where <function> is the function the driver will request <function>-gpios, where <function> is the function the driver will request
through gpiod_get(). For example: through gpiod_get(). For example::
foo_device { foo_device {
compatible = "acme,foo"; compatible = "acme,foo";
...@@ -40,7 +41,7 @@ it but are only supported for compatibility reasons and should not be used for ...@@ -40,7 +41,7 @@ it but are only supported for compatibility reasons and should not be used for
newer bindings since it has been deprecated. newer bindings since it has been deprecated.
This property will make GPIOs 15, 16 and 17 available to the driver under the This property will make GPIOs 15, 16 and 17 available to the driver under the
"led" function, and GPIO 1 as the "power" GPIO: "led" function, and GPIO 1 as the "power" GPIO::
struct gpio_desc *red, *green, *blue, *power; struct gpio_desc *red, *green, *blue, *power;
...@@ -60,13 +61,13 @@ looked up by the gpiod functions internally) used in the device tree. With above ...@@ -60,13 +61,13 @@ looked up by the gpiod functions internally) used in the device tree. With above
Internally, the GPIO subsystem prefixes the GPIO suffix ("gpios" or "gpio") Internally, the GPIO subsystem prefixes the GPIO suffix ("gpios" or "gpio")
with the string passed in con_id to get the resulting string with the string passed in con_id to get the resulting string
(snprintf(... "%s-%s", con_id, gpio_suffixes[]). (``snprintf(... "%s-%s", con_id, gpio_suffixes[]``).
ACPI ACPI
---- ----
ACPI also supports function names for GPIOs in a similar fashion to DT. ACPI also supports function names for GPIOs in a similar fashion to DT.
The above DT example can be converted to an equivalent ACPI description The above DT example can be converted to an equivalent ACPI description
with the help of _DSD (Device Specific Data), introduced in ACPI 5.1: with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
Device (FOO) { Device (FOO) {
Name (_CRS, ResourceTemplate () { Name (_CRS, ResourceTemplate () {
...@@ -105,12 +106,12 @@ Documentation/acpi/gpio-properties.txt. ...@@ -105,12 +106,12 @@ Documentation/acpi/gpio-properties.txt.
Platform Data Platform Data
------------- -------------
Finally, GPIOs can be bound to devices and functions using platform data. Board Finally, GPIOs can be bound to devices and functions using platform data. Board
files that desire to do so need to include the following header: files that desire to do so need to include the following header::
#include <linux/gpio/machine.h> #include <linux/gpio/machine.h>
GPIOs are mapped by the means of tables of lookups, containing instances of the GPIOs are mapped by the means of tables of lookups, containing instances of the
gpiod_lookup structure. Two macros are defined to help declaring such mappings: gpiod_lookup structure. Two macros are defined to help declaring such mappings::
GPIO_LOOKUP(chip_label, chip_hwnum, con_id, flags) GPIO_LOOKUP(chip_label, chip_hwnum, con_id, flags)
GPIO_LOOKUP_IDX(chip_label, chip_hwnum, con_id, idx, flags) GPIO_LOOKUP_IDX(chip_label, chip_hwnum, con_id, idx, flags)
...@@ -141,22 +142,24 @@ end. The 'dev_id' field of the table is the identifier of the device that will ...@@ -141,22 +142,24 @@ end. The 'dev_id' field of the table is the identifier of the device that will
make use of these GPIOs. It can be NULL, in which case it will be matched for make use of these GPIOs. It can be NULL, in which case it will be matched for
calls to gpiod_get() with a NULL device. calls to gpiod_get() with a NULL device.
struct gpiod_lookup_table gpios_table = { .. code-block:: c
.dev_id = "foo.0",
.table = { struct gpiod_lookup_table gpios_table = {
GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH), .dev_id = "foo.0",
GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH), .table = {
GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH), GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW), GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH),
{ }, GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH),
}, GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW),
}; { },
},
};
And the table can be added by the board code as follows: And the table can be added by the board code as follows::
gpiod_add_lookup_table(&gpios_table); gpiod_add_lookup_table(&gpios_table);
The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: The driver controlling "foo.0" will then be able to obtain its GPIOs as follows::
struct gpio_desc *red, *green, *blue, *power; struct gpio_desc *red, *green, *blue, *power;
......
================================
GPIO Descriptor Driver Interface GPIO Descriptor Driver Interface
================================ ================================
...@@ -53,9 +54,9 @@ common to each controller of that type: ...@@ -53,9 +54,9 @@ common to each controller of that type:
The code implementing a gpio_chip should support multiple instances of the The code implementing a gpio_chip should support multiple instances of the
controller, possibly using the driver model. That code will configure each controller, possibly using the driver model. That code will configure each
gpio_chip and issue gpiochip_add[_data]() or devm_gpiochip_add_data(). gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``.
Removing a GPIO controller should be rare; use [devm_]gpiochip_remove() when Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()``
it is unavoidable. when it is unavoidable.
Often a gpio_chip is part of an instance-specific structure with states not Often a gpio_chip is part of an instance-specific structure with states not
exposed by the GPIO interfaces, such as addressing, power management, and more. exposed by the GPIO interfaces, such as addressing, power management, and more.
...@@ -115,7 +116,7 @@ GPIOs with open drain/source support ...@@ -115,7 +116,7 @@ GPIOs with open drain/source support
Open drain (CMOS) or open collector (TTL) means the line is not actively driven Open drain (CMOS) or open collector (TTL) means the line is not actively driven
high: instead you provide the drain/collector as output, so when the transistor high: instead you provide the drain/collector as output, so when the transistor
is not open, it will present a high-impedance (tristate) to the external rail. is not open, it will present a high-impedance (tristate) to the external rail::
CMOS CONFIGURATION TTL CONFIGURATION CMOS CONFIGURATION TTL CONFIGURATION
...@@ -148,19 +149,19 @@ level-shift to the higher VDD. ...@@ -148,19 +149,19 @@ level-shift to the higher VDD.
Integrated electronics often have an output driver stage in the form of a CMOS Integrated electronics often have an output driver stage in the form of a CMOS
"totem-pole" with one N-MOS and one P-MOS transistor where one of them drives "totem-pole" with one N-MOS and one P-MOS transistor where one of them drives
the line high and one of them drives the line low. This is called a push-pull the line high and one of them drives the line low. This is called a push-pull
output. The "totem-pole" looks like so: output. The "totem-pole" looks like so::
VDD VDD
| |
OD ||--+ OD ||--+
+--/ ---o|| P-MOS-FET +--/ ---o|| P-MOS-FET
| ||--+ | ||--+
IN --+ +----- out IN --+ +----- out
| ||--+ | ||--+
+--/ ----|| N-MOS-FET +--/ ----|| N-MOS-FET
OS ||--+ OS ||--+
| |
GND GND
The desired output signal (e.g. coming directly from some GPIO output register) The desired output signal (e.g. coming directly from some GPIO output register)
arrives at IN. The switches named "OD" and "OS" are normally closed, creating arrives at IN. The switches named "OD" and "OS" are normally closed, creating
...@@ -219,8 +220,9 @@ systems simultaneously: gpio and irq. ...@@ -219,8 +220,9 @@ systems simultaneously: gpio and irq.
RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any
sleepable APIs (like PM runtime) as part of its irq_chip implementation. sleepable APIs (like PM runtime) as part of its irq_chip implementation.
- spinlock_t should be replaced with raw_spinlock_t [1].
- If sleepable APIs have to be used, these can be done from the .irq_bus_lock() * spinlock_t should be replaced with raw_spinlock_t [1].
* If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
on an irqchip. Create the callbacks if needed [2]. on an irqchip. Create the callbacks if needed [2].
...@@ -232,12 +234,12 @@ GPIO irqchips usually fall in one of two categories: ...@@ -232,12 +234,12 @@ GPIO irqchips usually fall in one of two categories:
system interrupt controller. This means that the GPIO irqchip handler will system interrupt controller. This means that the GPIO irqchip handler will
be called immediately from the parent irqchip, while holding the IRQs be called immediately from the parent irqchip, while holding the IRQs
disabled. The GPIO irqchip will then end up calling something like this disabled. The GPIO irqchip will then end up calling something like this
sequence in its interrupt handler: sequence in its interrupt handler::
static irqreturn_t foo_gpio_irq(int irq, void *data) static irqreturn_t foo_gpio_irq(int irq, void *data)
chained_irq_enter(...); chained_irq_enter(...);
generic_handle_irq(...); generic_handle_irq(...);
chained_irq_exit(...); chained_irq_exit(...);
Chained GPIO irqchips typically can NOT set the .can_sleep flag on Chained GPIO irqchips typically can NOT set the .can_sleep flag on
struct gpio_chip, as everything happens directly in the callbacks: no struct gpio_chip, as everything happens directly in the callbacks: no
...@@ -252,7 +254,7 @@ GPIO irqchips usually fall in one of two categories: ...@@ -252,7 +254,7 @@ GPIO irqchips usually fall in one of two categories:
(for example, see [3]). (for example, see [3]).
Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled, Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled,
so the IRQ core will complain if it is called from an IRQ handler which is so the IRQ core will complain if it is called from an IRQ handler which is
forced to a thread. The "fake?" raw lock can be used to W/A this problem: forced to a thread. The "fake?" raw lock can be used to W/A this problem::
raw_spinlock_t wa_lock; raw_spinlock_t wa_lock;
static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
...@@ -265,11 +267,11 @@ GPIO irqchips usually fall in one of two categories: ...@@ -265,11 +267,11 @@ GPIO irqchips usually fall in one of two categories:
but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is
performed by generic IRQ handler which is configured using request_irq(). performed by generic IRQ handler which is configured using request_irq().
The GPIO irqchip will then end up calling something like this sequence in The GPIO irqchip will then end up calling something like this sequence in
its interrupt handler: its interrupt handler::
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
for each detected GPIO IRQ for each detected GPIO IRQ
generic_handle_irq(...); generic_handle_irq(...);
RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ
core will complain that generic_handle_irq() is called with IRQ enabled and core will complain that generic_handle_irq() is called with IRQ enabled and
...@@ -282,11 +284,11 @@ GPIO irqchips usually fall in one of two categories: ...@@ -282,11 +284,11 @@ GPIO irqchips usually fall in one of two categories:
in a quick IRQ handler with IRQs disabled. Instead they need to spawn a in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
thread and then mask the parent IRQ line until the interrupt is handled thread and then mask the parent IRQ line until the interrupt is handled
by the driver. The hallmark of this driver is to call something like by the driver. The hallmark of this driver is to call something like
this in its interrupt handler: this in its interrupt handler::
static irqreturn_t foo_gpio_irq(int irq, void *data) static irqreturn_t foo_gpio_irq(int irq, void *data)
... ...
handle_nested_irq(irq); handle_nested_irq(irq);
The hallmark of threaded GPIO irqchips is that they set the .can_sleep The hallmark of threaded GPIO irqchips is that they set the .can_sleep
flag on struct gpio_chip to true, indicating that this chip may sleep flag on struct gpio_chip to true, indicating that this chip may sleep
...@@ -359,12 +361,12 @@ below exists. ...@@ -359,12 +361,12 @@ below exists.
Locking IRQ usage Locking IRQ usage
----------------- -----------------
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
to mark the GPIO as being used as an IRQ: to mark the GPIO as being used as an IRQ::
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
is released: is released::
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
...@@ -408,7 +410,7 @@ Sometimes it is useful to allow a GPIO chip driver to request its own GPIO ...@@ -408,7 +410,7 @@ Sometimes it is useful to allow a GPIO chip driver to request its own GPIO
descriptors through the gpiolib API. Using gpio_request() for this purpose descriptors through the gpiolib API. Using gpio_request() for this purpose
does not help since it pins the module to the kernel forever (it calls does not help since it pins the module to the kernel forever (it calls
try_module_get()). A GPIO driver can use the following functions instead try_module_get()). A GPIO driver can use the following functions instead
to request and free descriptors without being pinned to the kernel forever. to request and free descriptors without being pinned to the kernel forever::
struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc, struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc,
const char *label) const char *label)
...@@ -422,6 +424,6 @@ These functions must be used with care since they do not affect module use ...@@ -422,6 +424,6 @@ These functions must be used with care since they do not affect module use
count. Do not use the functions to request gpio descriptors not owned by the count. Do not use the functions to request gpio descriptors not owned by the
calling driver. calling driver.
[1] http://www.spinics.net/lists/linux-omap/msg120425.html * [1] http://www.spinics.net/lists/linux-omap/msg120425.html
[2] https://lkml.org/lkml/2015/9/25/494 * [2] https://lkml.org/lkml/2015/9/25/494
[3] https://lkml.org/lkml/2015/9/25/495 * [3] https://lkml.org/lkml/2015/9/25/495
============================
Subsystem drivers using GPIO Subsystem drivers using GPIO
============================ ============================
......
...@@ -2,6 +2,18 @@ ...@@ -2,6 +2,18 @@
General Purpose Input/Output (GPIO) General Purpose Input/Output (GPIO)
=================================== ===================================
Contents:
.. toctree::
:maxdepth: 2
intro
driver
consumer
board
drivers-on-gpio
legacy
Core Core
==== ====
...@@ -11,15 +23,6 @@ Core ...@@ -11,15 +23,6 @@ Core
.. kernel-doc:: drivers/gpio/gpiolib.c .. kernel-doc:: drivers/gpio/gpiolib.c
:export: :export:
Legacy API
==========
The functions listed in this section are deprecated. The GPIO descriptor based
API described above should be used in new code.
.. kernel-doc:: drivers/gpio/gpiolib-legacy.c
:export:
ACPI support ACPI support
============ ============
......
============
Introduction
============
GPIO Interfaces GPIO Interfaces
=============== ===============
...@@ -9,9 +14,9 @@ Due to the history of GPIO interfaces in the kernel, there are two different ...@@ -9,9 +14,9 @@ Due to the history of GPIO interfaces in the kernel, there are two different
ways to obtain and use GPIOs: ways to obtain and use GPIOs:
- The descriptor-based interface is the preferred way to manipulate GPIOs, - The descriptor-based interface is the preferred way to manipulate GPIOs,
and is described by all the files in this directory excepted gpio-legacy.txt. and is described by all the files in this directory excepted gpio-legacy.txt.
- The legacy integer-based interface which is considered deprecated (but still - The legacy integer-based interface which is considered deprecated (but still
usable for compatibility reasons) is documented in gpio-legacy.txt. usable for compatibility reasons) is documented in gpio-legacy.txt.
The remainder of this document applies to the new descriptor-based interface. The remainder of this document applies to the new descriptor-based interface.
gpio-legacy.txt contains the same information applied to the legacy gpio-legacy.txt contains the same information applied to the legacy
......
GPIO Interfaces ======================
Legacy GPIO Interfaces
======================
This provides an overview of GPIO access conventions on Linux. This provides an overview of GPIO access conventions on Linux.
...@@ -129,7 +131,7 @@ The first thing a system should do with a GPIO is allocate it, using ...@@ -129,7 +131,7 @@ The first thing a system should do with a GPIO is allocate it, using
the gpio_request() call; see later. the gpio_request() call; see later.
One of the next things to do with a GPIO, often in board setup code when One of the next things to do with a GPIO, often in board setup code when
setting up a platform_device using the GPIO, is mark its direction: setting up a platform_device using the GPIO, is mark its direction::
/* set as input or output, returning 0 or negative errno */ /* set as input or output, returning 0 or negative errno */
int gpio_direction_input(unsigned gpio); int gpio_direction_input(unsigned gpio);
...@@ -164,7 +166,7 @@ Those don't need to sleep, and can safely be done from inside hard ...@@ -164,7 +166,7 @@ Those don't need to sleep, and can safely be done from inside hard
(nonthreaded) IRQ handlers and similar contexts. (nonthreaded) IRQ handlers and similar contexts.
Use the following calls to access such GPIOs, Use the following calls to access such GPIOs,
for which gpio_cansleep() will always return false (see below): for which gpio_cansleep() will always return false (see below)::
/* GPIO INPUT: return zero or nonzero */ /* GPIO INPUT: return zero or nonzero */
int gpio_get_value(unsigned gpio); int gpio_get_value(unsigned gpio);
...@@ -201,11 +203,11 @@ This requires sleeping, which can't be done from inside IRQ handlers. ...@@ -201,11 +203,11 @@ This requires sleeping, which can't be done from inside IRQ handlers.
Platforms that support this type of GPIO distinguish them from other GPIOs Platforms that support this type of GPIO distinguish them from other GPIOs
by returning nonzero from this call (which requires a valid GPIO number, by returning nonzero from this call (which requires a valid GPIO number,
which should have been previously allocated with gpio_request): which should have been previously allocated with gpio_request)::
int gpio_cansleep(unsigned gpio); int gpio_cansleep(unsigned gpio);
To access such GPIOs, a different set of accessors is defined: To access such GPIOs, a different set of accessors is defined::
/* GPIO INPUT: return zero or nonzero, might sleep */ /* GPIO INPUT: return zero or nonzero, might sleep */
int gpio_get_value_cansleep(unsigned gpio); int gpio_get_value_cansleep(unsigned gpio);
...@@ -222,27 +224,27 @@ Other than the fact that these accessors might sleep, and will work ...@@ -222,27 +224,27 @@ Other than the fact that these accessors might sleep, and will work
on GPIOs that can't be accessed from hardIRQ handlers, these calls act on GPIOs that can't be accessed from hardIRQ handlers, these calls act
the same as the spinlock-safe calls. the same as the spinlock-safe calls.
** IN ADDITION ** calls to setup and configure such GPIOs must be made **IN ADDITION** calls to setup and configure such GPIOs must be made
from contexts which may sleep, since they may need to access the GPIO from contexts which may sleep, since they may need to access the GPIO
controller chip too: (These setup calls are usually made from board controller chip too (These setup calls are usually made from board
setup or driver probe/teardown code, so this is an easy constraint.) setup or driver probe/teardown code, so this is an easy constraint.)::
gpio_direction_input() gpio_direction_input()
gpio_direction_output() gpio_direction_output()
gpio_request() gpio_request()
## gpio_request_one() ## gpio_request_one()
## gpio_request_array() ## gpio_request_array()
## gpio_free_array() ## gpio_free_array()
gpio_free() gpio_free()
gpio_set_debounce() gpio_set_debounce()
Claiming and Releasing GPIOs Claiming and Releasing GPIOs
---------------------------- ----------------------------
To help catch system configuration errors, two calls are defined. To help catch system configuration errors, two calls are defined::
/* request GPIO, returning 0 or negative errno. /* request GPIO, returning 0 or negative errno.
* non-null labels may be useful for diagnostics. * non-null labels may be useful for diagnostics.
...@@ -296,7 +298,7 @@ Also note that it's your responsibility to have stopped using a GPIO ...@@ -296,7 +298,7 @@ Also note that it's your responsibility to have stopped using a GPIO
before you free it. before you free it.
Considering in most cases GPIOs are actually configured right after they Considering in most cases GPIOs are actually configured right after they
are claimed, three additional calls are defined: are claimed, three additional calls are defined::
/* request a single GPIO, with initial configuration specified by /* request a single GPIO, with initial configuration specified by
* 'flags', identical to gpio_request() wrt other arguments and * 'flags', identical to gpio_request() wrt other arguments and
...@@ -347,7 +349,7 @@ to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode. ...@@ -347,7 +349,7 @@ to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
In the future, these flags can be extended to support more properties. In the future, these flags can be extended to support more properties.
Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
introduced to encapsulate all three fields as: introduced to encapsulate all three fields as::
struct gpio { struct gpio {
unsigned gpio; unsigned gpio;
...@@ -355,7 +357,7 @@ introduced to encapsulate all three fields as: ...@@ -355,7 +357,7 @@ introduced to encapsulate all three fields as:
const char *label; const char *label;
}; };
A typical example of usage: A typical example of usage::
static struct gpio leds_gpios[] = { static struct gpio leds_gpios[] = {
{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */ { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
...@@ -380,7 +382,7 @@ GPIOs mapped to IRQs ...@@ -380,7 +382,7 @@ GPIOs mapped to IRQs
-------------------- --------------------
GPIO numbers are unsigned integers; so are IRQ numbers. These make up GPIO numbers are unsigned integers; so are IRQ numbers. These make up
two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can
map between them using calls like: map between them using calls like::
/* map GPIO numbers to IRQ numbers */ /* map GPIO numbers to IRQ numbers */
int gpio_to_irq(unsigned gpio); int gpio_to_irq(unsigned gpio);
...@@ -446,12 +448,12 @@ A GPIO controller on a SOC might be tightly coupled with the pinctrl ...@@ -446,12 +448,12 @@ A GPIO controller on a SOC might be tightly coupled with the pinctrl
subsystem, in the sense that the pins can be used by other functions subsystem, in the sense that the pins can be used by other functions
together with an optional gpio feature. We have already covered the together with an optional gpio feature. We have already covered the
case where e.g. a GPIO controller need to reserve a pin or set the case where e.g. a GPIO controller need to reserve a pin or set the
direction of a pin by calling any of: direction of a pin by calling any of::
pinctrl_gpio_request() pinctrl_gpio_request()
pinctrl_gpio_free() pinctrl_gpio_free()
pinctrl_gpio_direction_input() pinctrl_gpio_direction_input()
pinctrl_gpio_direction_output() pinctrl_gpio_direction_output()
But how does the pin control subsystem cross-correlate the GPIO But how does the pin control subsystem cross-correlate the GPIO
numbers (which are a global business) to a certain pin on a certain numbers (which are a global business) to a certain pin on a certain
...@@ -565,7 +567,7 @@ If neither of these options are selected, the platform does not support ...@@ -565,7 +567,7 @@ 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. GPIOs through GPIO-lib and the code cannot be enabled by the user.
Trivial implementations of those functions can directly use framework Trivial implementations of those functions can directly use framework
code, which always dispatches through the gpio_chip: code, which always dispatches through the gpio_chip::
#define gpio_get_value __gpio_get_value #define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value #define gpio_set_value __gpio_set_value
...@@ -731,7 +733,7 @@ the correct GPIO number to use for a given signal. ...@@ -731,7 +733,7 @@ the correct GPIO number to use for a given signal.
Exporting from Kernel code Exporting from Kernel code
-------------------------- --------------------------
Kernel code can explicitly manage exports of GPIOs which have already been Kernel code can explicitly manage exports of GPIOs which have already been
requested using gpio_request(): requested using gpio_request()::
/* export the GPIO to userspace */ /* export the GPIO to userspace */
int gpio_export(unsigned gpio, bool direction_may_change); int gpio_export(unsigned gpio, bool direction_may_change);
...@@ -756,3 +758,13 @@ After the GPIO has been exported, gpio_export_link() allows creating ...@@ -756,3 +758,13 @@ After the GPIO has been exported, gpio_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with use this to provide the interface under their own device in sysfs with
a descriptive name. a descriptive name.
API Reference
=============
The functions listed in this section are deprecated. The GPIO descriptor based
API should be used in new code.
.. kernel-doc:: drivers/gpio/gpiolib-legacy.c
:export:
...@@ -44,7 +44,7 @@ available subsections can be seen below. ...@@ -44,7 +44,7 @@ available subsections can be seen below.
uio-howto uio-howto
firmware/index firmware/index
pinctl pinctl
gpio gpio/index
misc_devices misc_devices
dmaengine/index dmaengine/index
slimbus slimbus
......
00-INDEX 00-INDEX
- This file - This file
gpio.txt
- Introduction to GPIOs and their kernel interfaces
consumer.txt
- How to obtain and use GPIOs in a driver
driver.txt
- How to write a GPIO driver
drivers-on-gpio.txt:
- Drivers in other subsystems that can use GPIO to provide more
complex functionality.
board.txt
- How to assign GPIOs to a consumer device and a function
sysfs.txt sysfs.txt
- Information about the GPIO sysfs interface - Information about the GPIO sysfs interface
gpio-legacy.txt
- Historical documentation of the deprecated GPIO integer interface
...@@ -32,9 +32,8 @@ standard kernels won't know about. And for some tasks, simple userspace ...@@ -32,9 +32,8 @@ standard kernels won't know about. And for some tasks, simple userspace
GPIO drivers could be all that the system really needs. GPIO drivers could be all that the system really needs.
DO NOT ABUSE SYSFS TO CONTROL HARDWARE THAT HAS PROPER KERNEL DRIVERS. DO NOT ABUSE SYSFS TO CONTROL HARDWARE THAT HAS PROPER KERNEL DRIVERS.
PLEASE READ THE DOCUMENT NAMED "drivers-on-gpio.txt" IN THIS DOCUMENTATION PLEASE READ THE DOCUMENT AT Documentation/driver-api/gpio/drivers-on-gpio.rst
DIRECTORY TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT. TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT. REALLY.
REALLY.
Paths in Sysfs Paths in Sysfs
-------------- --------------
......
...@@ -5984,7 +5984,7 @@ S: Maintained ...@@ -5984,7 +5984,7 @@ S: Maintained
F: drivers/media/rc/gpio-ir-tx.c F: drivers/media/rc/gpio-ir-tx.c
GPIO MOCKUP DRIVER GPIO MOCKUP DRIVER
M: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> M: Bamvor Jian Zhang <bamv2005@gmail.com>
R: Bartosz Golaszewski <brgl@bgdev.pl> R: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-gpio@vger.kernel.org L: linux-gpio@vger.kernel.org
S: Maintained S: Maintained
...@@ -5997,6 +5997,7 @@ L: linux-gpio@vger.kernel.org ...@@ -5997,6 +5997,7 @@ L: linux-gpio@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/gpio/ F: Documentation/devicetree/bindings/gpio/
F: Documentation/driver-api/gpio/
F: Documentation/gpio/ F: Documentation/gpio/
F: Documentation/ABI/testing/gpio-cdev F: Documentation/ABI/testing/gpio-cdev
F: Documentation/ABI/obsolete/sysfs-gpio F: Documentation/ABI/obsolete/sysfs-gpio
......
...@@ -2665,11 +2665,13 @@ config PCI_CNB20LE_QUIRK ...@@ -2665,11 +2665,13 @@ config PCI_CNB20LE_QUIRK
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
config ISA_BUS config ISA_BUS
bool "ISA-style bus support on modern systems" if EXPERT bool "ISA bus support on modern systems" if EXPERT
select ISA_BUS_API
help help
Enables ISA-style drivers on modern systems. This is necessary to Expose ISA bus device drivers and options available for selection and
support PC/104 devices on X86_64 platforms. configuration. Enable this option if your target machine has an ISA
bus. ISA is an older system, displaced by PCI and newer bus
architectures -- if your target machine is modern, it probably does
not have an ISA bus.
If unsure, say N. If unsure, say N.
......
...@@ -122,6 +122,17 @@ config GPIO_ATH79 ...@@ -122,6 +122,17 @@ config GPIO_ATH79
Select this option to enable GPIO driver for Select this option to enable GPIO driver for
Atheros AR71XX/AR724X/AR913X SoC devices. Atheros AR71XX/AR724X/AR913X SoC devices.
config GPIO_RASPBERRYPI_EXP
tristate "Raspberry Pi 3 GPIO Expander"
default RASPBERRYPI_FIRMWARE
depends on OF_GPIO
# Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only
# happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE.
depends on (ARCH_BCM2835 && RASPBERRYPI_FIRMWARE) || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
help
Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
the firmware mailbox to communicate with VideoCore on BCM283x chips.
config GPIO_BCM_KONA config GPIO_BCM_KONA
bool "Broadcom Kona GPIO" bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
...@@ -159,6 +170,14 @@ config GPIO_DWAPB ...@@ -159,6 +170,14 @@ config GPIO_DWAPB
Say Y or M here to build support for the Synopsys DesignWare APB Say Y or M here to build support for the Synopsys DesignWare APB
GPIO block. GPIO block.
config GPIO_EIC_SPRD
tristate "Spreadtrum EIC support"
depends on ARCH_SPRD || COMPILE_TEST
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
Say yes here to support Spreadtrum EIC device.
config GPIO_EM config GPIO_EM
tristate "Emma Mobile GPIO" tristate "Emma Mobile GPIO"
depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO
...@@ -214,6 +233,15 @@ config GPIO_GRGPIO ...@@ -214,6 +233,15 @@ config GPIO_GRGPIO
Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB
VHDL IP core library. VHDL IP core library.
config GPIO_HLWD
tristate "Nintendo Wii (Hollywood) GPIO"
depends on OF_GPIO
select GPIO_GENERIC
help
Select this to support the GPIO controller of the Nintendo Wii.
If unsure, say N.
config GPIO_ICH config GPIO_ICH
tristate "Intel ICH GPIO" tristate "Intel ICH GPIO"
depends on PCI && X86 depends on PCI && X86
...@@ -363,6 +391,14 @@ config GPIO_PL061 ...@@ -363,6 +391,14 @@ config GPIO_PL061
help help
Say yes here to support the PrimeCell PL061 GPIO device Say yes here to support the PrimeCell PL061 GPIO device
config GPIO_PMIC_EIC_SPRD
tristate "Spreadtrum PMIC EIC support"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
Say yes here to support Spreadtrum PMIC EIC device.
config GPIO_PXA config GPIO_PXA
bool "PXA GPIO support" bool "PXA GPIO support"
depends on ARCH_PXA || ARCH_MMP depends on ARCH_PXA || ARCH_MMP
...@@ -389,6 +425,14 @@ config GPIO_SPEAR_SPICS ...@@ -389,6 +425,14 @@ config GPIO_SPEAR_SPICS
help help
Say yes here to support ST SPEAr SPI Chip Select as GPIO device Say yes here to support ST SPEAr SPI Chip Select as GPIO device
config GPIO_SPRD
tristate "Spreadtrum GPIO support"
depends on ARCH_SPRD || COMPILE_TEST
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
Say yes here to support Spreadtrum GPIO device.
config GPIO_STA2X11 config GPIO_STA2X11
bool "STA2x11/ConneXt GPIO support" bool "STA2x11/ConneXt GPIO support"
depends on MFD_STA2X11 depends on MFD_STA2X11
...@@ -453,21 +497,6 @@ config GPIO_THUNDERX ...@@ -453,21 +497,6 @@ config GPIO_THUNDERX
Say yes here to support the on-chip GPIO lines on the ThunderX Say yes here to support the on-chip GPIO lines on the ThunderX
and OCTEON-TX families of SoCs. and OCTEON-TX families of SoCs.
config GPIO_TZ1090
bool "Toumaz Xenif TZ1090 GPIO support"
depends on SOC_TZ1090
select GENERIC_IRQ_CHIP
default y
help
Say yes here to support Toumaz Xenif TZ1090 GPIOs.
config GPIO_TZ1090_PDC
bool "Toumaz Xenif TZ1090 PDC GPIO support"
depends on SOC_TZ1090
default y
help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
config GPIO_UNIPHIER config GPIO_UNIPHIER
tristate "UniPhier GPIO support" tristate "UniPhier GPIO support"
depends on ARCH_UNIPHIER || COMPILE_TEST depends on ARCH_UNIPHIER || COMPILE_TEST
...@@ -581,7 +610,8 @@ menu "Port-mapped I/O GPIO drivers" ...@@ -581,7 +610,8 @@ menu "Port-mapped I/O GPIO drivers"
config GPIO_104_DIO_48E config GPIO_104_DIO_48E
tristate "ACCES 104-DIO-48E GPIO support" tristate "ACCES 104-DIO-48E GPIO support"
depends on PC104 && ISA_BUS_API depends on PC104
select ISA_BUS_API
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
...@@ -591,7 +621,8 @@ config GPIO_104_DIO_48E ...@@ -591,7 +621,8 @@ config GPIO_104_DIO_48E
config GPIO_104_IDIO_16 config GPIO_104_IDIO_16
tristate "ACCES 104-IDIO-16 GPIO support" tristate "ACCES 104-IDIO-16 GPIO support"
depends on PC104 && ISA_BUS_API depends on PC104
select ISA_BUS_API
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
...@@ -602,7 +633,8 @@ config GPIO_104_IDIO_16 ...@@ -602,7 +633,8 @@ config GPIO_104_IDIO_16
config GPIO_104_IDI_48 config GPIO_104_IDI_48
tristate "ACCES 104-IDI-48 GPIO support" tristate "ACCES 104-IDI-48 GPIO support"
depends on PC104 && ISA_BUS_API depends on PC104
select ISA_BUS_API
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
...@@ -622,7 +654,8 @@ config GPIO_F7188X ...@@ -622,7 +654,8 @@ config GPIO_F7188X
config GPIO_GPIO_MM config GPIO_GPIO_MM
tristate "Diamond Systems GPIO-MM GPIO support" tristate "Diamond Systems GPIO-MM GPIO support"
depends on PC104 && ISA_BUS_API depends on PC104
select ISA_BUS_API
help help
Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12. Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
...@@ -691,7 +724,7 @@ config GPIO_TS5500 ...@@ -691,7 +724,7 @@ config GPIO_TS5500
config GPIO_WINBOND config GPIO_WINBOND
tristate "Winbond Super I/O GPIO support" tristate "Winbond Super I/O GPIO support"
depends on ISA_BUS_API select ISA_BUS_API
help help
This option enables support for GPIOs found on Winbond Super I/O This option enables support for GPIOs found on Winbond Super I/O
chips. chips.
...@@ -707,7 +740,7 @@ config GPIO_WINBOND ...@@ -707,7 +740,7 @@ config GPIO_WINBOND
config GPIO_WS16C48 config GPIO_WS16C48
tristate "WinSystems WS16C48 GPIO support" tristate "WinSystems WS16C48 GPIO support"
depends on ISA_BUS_API select ISA_BUS_API
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
Enables GPIO support for the WinSystems WS16C48. The base port Enables GPIO support for the WinSystems WS16C48. The base port
......
...@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o ...@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
...@@ -44,6 +45,7 @@ obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o ...@@ -44,6 +45,7 @@ obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
...@@ -52,6 +54,7 @@ obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o ...@@ -52,6 +54,7 @@ obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_INGENIC) += gpio-ingenic.o obj-$(CONFIG_GPIO_INGENIC) += gpio-ingenic.o
...@@ -97,6 +100,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o ...@@ -97,6 +100,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o
obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
...@@ -107,6 +111,7 @@ obj-$(CONFIG_GPIO_SCH) += gpio-sch.o ...@@ -107,6 +111,7 @@ obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
...@@ -130,8 +135,6 @@ obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o ...@@ -130,8 +135,6 @@ obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* This driver supports the following ACCES devices: 104-DIO-48E and * This driver supports the following ACCES devices: 104-DIO-48E and
* 104-DIO-24E. * 104-DIO-24E.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -182,6 +183,51 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -182,6 +183,51 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(port_state & mask); return !!(port_state & mask);
} }
static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
size_t i;
const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port */
port_state = inb(dio48egpio->base + ports[i]);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
...@@ -384,6 +430,7 @@ static int dio48e_probe(struct device *dev, unsigned int id) ...@@ -384,6 +430,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
dio48egpio->chip.direction_input = dio48e_gpio_direction_input; dio48egpio->chip.direction_input = dio48e_gpio_direction_input;
dio48egpio->chip.direction_output = dio48e_gpio_direction_output; dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
dio48egpio->chip.get = dio48e_gpio_get; dio48egpio->chip.get = dio48e_gpio_get;
dio48egpio->chip.get_multiple = dio48e_gpio_get_multiple;
dio48egpio->chip.set = dio48e_gpio_set; dio48egpio->chip.set = dio48e_gpio_set;
dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple; dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
dio48egpio->base = base[id]; dio48egpio->base = base[id];
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* This driver supports the following ACCES devices: 104-IDI-48A, * This driver supports the following ACCES devices: 104-IDI-48A,
* 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC. * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -88,6 +89,51 @@ static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -88,6 +89,51 @@ static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset)
return 0; return 0;
} }
static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
size_t i;
const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port */
port_state = inb(idi48gpio->base + ports[i]);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void idi_48_irq_ack(struct irq_data *data) static void idi_48_irq_ack(struct irq_data *data)
{ {
} }
...@@ -256,6 +302,7 @@ static int idi_48_probe(struct device *dev, unsigned int id) ...@@ -256,6 +302,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
idi48gpio->chip.get_direction = idi_48_gpio_get_direction; idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
idi48gpio->chip.direction_input = idi_48_gpio_direction_input; idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
idi48gpio->chip.get = idi_48_gpio_get; idi48gpio->chip.get = idi_48_gpio_get;
idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
idi48gpio->base = base[id]; idi48gpio->base = base[id];
raw_spin_lock_init(&idi48gpio->lock); raw_spin_lock_init(&idi48gpio->lock);
......
...@@ -90,6 +90,20 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -90,6 +90,20 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(inb(idio16gpio->base + 5) & (mask>>8)); return !!(inb(idio16gpio->base + 5) & (mask>>8));
} }
static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
*bits = 0;
if (*mask & GENMASK(23, 16))
*bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
if (*mask & GENMASK(31, 24))
*bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
return 0;
}
static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
...@@ -244,6 +258,7 @@ static int idio_16_probe(struct device *dev, unsigned int id) ...@@ -244,6 +258,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
idio16gpio->chip.direction_input = idio_16_gpio_direction_input; idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
idio16gpio->chip.direction_output = idio_16_gpio_direction_output; idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get; idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
idio16gpio->base = base[id]; idio16gpio->base = base[id];
......
...@@ -258,6 +258,8 @@ static int ath79_gpio_probe(struct platform_device *pdev) ...@@ -258,6 +258,8 @@ static int ath79_gpio_probe(struct platform_device *pdev)
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
ctrl->base = devm_ioremap_nocache( ctrl->base = devm_ioremap_nocache(
&pdev->dev, res->start, resource_size(res)); &pdev->dev, res->start, resource_size(res));
if (!ctrl->base) if (!ctrl->base)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/platform_data/gpio-davinci.h> #include <linux/platform_data/gpio-davinci.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
...@@ -225,6 +226,11 @@ static int davinci_gpio_probe(struct platform_device *pdev) ...@@ -225,6 +226,11 @@ static int davinci_gpio_probe(struct platform_device *pdev)
chips->chip.of_gpio_n_cells = 2; chips->chip.of_gpio_n_cells = 2;
chips->chip.parent = dev; chips->chip.parent = dev;
chips->chip.of_node = dev->of_node; chips->chip.of_node = dev->of_node;
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
chips->chip.request = gpiochip_generic_request;
chips->chip.free = gpiochip_generic_free;
}
#endif #endif
spin_lock_init(&chips->lock); spin_lock_init(&chips->lock);
bank_base += ngpio; bank_base += ngpio;
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/dln2.h> #include <linux/mfd/dln2.h>
...@@ -204,9 +203,9 @@ static int dln2_gpio_get_direction(struct gpio_chip *chip, unsigned offset) ...@@ -204,9 +203,9 @@ static int dln2_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
struct dln2_gpio *dln2 = gpiochip_get_data(chip); struct dln2_gpio *dln2 = gpiochip_get_data(chip);
if (test_bit(offset, dln2->output_enabled)) if (test_bit(offset, dln2->output_enabled))
return GPIOF_DIR_OUT; return 0;
return GPIOF_DIR_IN; return 1;
} }
static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset) static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset)
...@@ -218,7 +217,7 @@ static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset) ...@@ -218,7 +217,7 @@ static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset)
if (dir < 0) if (dir < 0)
return dir; return dir;
if (dir == GPIOF_DIR_IN) if (dir == 1)
return dln2_gpio_pin_get_in_val(dln2, offset); return dln2_gpio_pin_get_in_val(dln2, offset);
return dln2_gpio_pin_get_out_val(dln2, offset); return dln2_gpio_pin_get_out_val(dln2, offset);
......
...@@ -8,10 +8,9 @@ ...@@ -8,10 +8,9 @@
* All enquiries to support@picochip.com * All enquiries to support@picochip.com
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/driver.h> #include <linux/clk.h>
/* FIXME: for gpio_get_value(), replace this with direct register read */
#include <linux/gpio.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -53,9 +52,9 @@ ...@@ -53,9 +52,9 @@
#define GPIO_EXT_PORTD 0x5c #define GPIO_EXT_PORTD 0x5c
#define DWAPB_MAX_PORTS 4 #define DWAPB_MAX_PORTS 4
#define GPIO_EXT_PORT_SIZE (GPIO_EXT_PORTB - GPIO_EXT_PORTA) #define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */
#define GPIO_SWPORT_DR_SIZE (GPIO_SWPORTB_DR - GPIO_SWPORTA_DR) #define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
#define GPIO_SWPORT_DDR_SIZE (GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR) #define GPIO_SWPORT_DDR_STRIDE 0x0c /* register stride 3*32 bits */
#define GPIO_REG_OFFSET_V2 1 #define GPIO_REG_OFFSET_V2 1
...@@ -100,6 +99,7 @@ struct dwapb_gpio { ...@@ -100,6 +99,7 @@ struct dwapb_gpio {
struct irq_domain *domain; struct irq_domain *domain;
unsigned int flags; unsigned int flags;
struct reset_control *rst; struct reset_control *rst;
struct clk *clk;
}; };
static inline u32 gpio_reg_v2_convert(unsigned int offset) static inline u32 gpio_reg_v2_convert(unsigned int offset)
...@@ -153,16 +153,40 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -153,16 +153,40 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return irq_find_mapping(gpio->domain, offset); return irq_find_mapping(gpio->domain, offset);
} }
static struct dwapb_gpio_port *dwapb_offs_to_port(struct dwapb_gpio *gpio, unsigned int offs)
{
struct dwapb_gpio_port *port;
int i;
for (i = 0; i < gpio->nr_ports; i++) {
port = &gpio->ports[i];
if (port->idx == offs / 32)
return port;
}
return NULL;
}
static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
{ {
u32 v = dwapb_read(gpio, GPIO_INT_POLARITY); struct dwapb_gpio_port *port = dwapb_offs_to_port(gpio, offs);
struct gpio_chip *gc;
u32 pol;
int val;
if (!port)
return;
gc = &port->gc;
if (gpio_get_value(gpio->ports[0].gc.base + offs)) pol = dwapb_read(gpio, GPIO_INT_POLARITY);
v &= ~BIT(offs); /* Just read the current value right out of the data register */
val = gc->get(gc, offs % 32);
if (val)
pol &= ~BIT(offs);
else else
v |= BIT(offs); pol |= BIT(offs);
dwapb_write(gpio, GPIO_INT_POLARITY, v); dwapb_write(gpio, GPIO_INT_POLARITY, pol);
} }
static u32 dwapb_do_irq(struct dwapb_gpio *gpio) static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
...@@ -476,11 +500,12 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, ...@@ -476,11 +500,12 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
return -ENOMEM; return -ENOMEM;
#endif #endif
dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_SIZE); dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_STRIDE);
set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_SIZE); set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_STRIDE);
dirout = gpio->regs + GPIO_SWPORTA_DDR + dirout = gpio->regs + GPIO_SWPORTA_DDR +
(pp->idx * GPIO_SWPORT_DDR_SIZE); (pp->idx * GPIO_SWPORT_DDR_STRIDE);
/* This registers 32 GPIO lines per port */
err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout, err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout,
NULL, 0); NULL, 0);
if (err) { if (err) {
...@@ -647,6 +672,16 @@ static int dwapb_gpio_probe(struct platform_device *pdev) ...@@ -647,6 +672,16 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->regs)) if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs); return PTR_ERR(gpio->regs);
/* Optional bus clock */
gpio->clk = devm_clk_get(&pdev->dev, "bus");
if (!IS_ERR(gpio->clk)) {
err = clk_prepare_enable(gpio->clk);
if (err) {
dev_info(&pdev->dev, "Cannot enable clock\n");
return err;
}
}
gpio->flags = 0; gpio->flags = 0;
if (dev->of_node) { if (dev->of_node) {
const struct of_device_id *of_devid; const struct of_device_id *of_devid;
...@@ -689,6 +724,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev) ...@@ -689,6 +724,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev)
dwapb_gpio_unregister(gpio); dwapb_gpio_unregister(gpio);
dwapb_irq_teardown(gpio); dwapb_irq_teardown(gpio);
reset_control_assert(gpio->rst); reset_control_assert(gpio->rst);
clk_disable_unprepare(gpio->clk);
return 0; return 0;
} }
...@@ -710,13 +746,13 @@ static int dwapb_gpio_suspend(struct device *dev) ...@@ -710,13 +746,13 @@ static int dwapb_gpio_suspend(struct device *dev)
BUG_ON(!ctx); BUG_ON(!ctx);
offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE;
ctx->dir = dwapb_read(gpio, offset); ctx->dir = dwapb_read(gpio, offset);
offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE;
ctx->data = dwapb_read(gpio, offset); ctx->data = dwapb_read(gpio, offset);
offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE;
ctx->ext = dwapb_read(gpio, offset); ctx->ext = dwapb_read(gpio, offset);
/* Only port A can provide interrupts */ /* Only port A can provide interrupts */
...@@ -734,6 +770,8 @@ static int dwapb_gpio_suspend(struct device *dev) ...@@ -734,6 +770,8 @@ static int dwapb_gpio_suspend(struct device *dev)
} }
spin_unlock_irqrestore(&gc->bgpio_lock, flags); spin_unlock_irqrestore(&gc->bgpio_lock, flags);
clk_disable_unprepare(gpio->clk);
return 0; return 0;
} }
...@@ -745,6 +783,9 @@ static int dwapb_gpio_resume(struct device *dev) ...@@ -745,6 +783,9 @@ static int dwapb_gpio_resume(struct device *dev)
unsigned long flags; unsigned long flags;
int i; int i;
if (!IS_ERR(gpio->clk))
clk_prepare_enable(gpio->clk);
spin_lock_irqsave(&gc->bgpio_lock, flags); spin_lock_irqsave(&gc->bgpio_lock, flags);
for (i = 0; i < gpio->nr_ports; i++) { for (i = 0; i < gpio->nr_ports; i++) {
unsigned int offset; unsigned int offset;
...@@ -753,13 +794,13 @@ static int dwapb_gpio_resume(struct device *dev) ...@@ -753,13 +794,13 @@ static int dwapb_gpio_resume(struct device *dev)
BUG_ON(!ctx); BUG_ON(!ctx);
offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE;
dwapb_write(gpio, offset, ctx->data); dwapb_write(gpio, offset, ctx->data);
offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE;
dwapb_write(gpio, offset, ctx->dir); dwapb_write(gpio, offset, ctx->dir);
offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE;
dwapb_write(gpio, offset, ctx->ext); dwapb_write(gpio, offset, ctx->ext);
/* Only port A can provide interrupts */ /* Only port A can provide interrupts */
......
This diff is collapsed.
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
......
...@@ -14,19 +14,20 @@ ...@@ -14,19 +14,20 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/bitops.h> #include <linux/bitops.h>
/* GPIO registers definition */ /* GPIO registers definition */
#define GPIO_DATA_OUT 0x00 #define GPIO_DATA_OUT 0x00
#define GPIO_DATA_IN 0x04 #define GPIO_DATA_IN 0x04
#define GPIO_DIR 0x08 #define GPIO_DIR 0x08
#define GPIO_BYPASS_IN 0x0C
#define GPIO_DATA_SET 0x10 #define GPIO_DATA_SET 0x10
#define GPIO_DATA_CLR 0x14 #define GPIO_DATA_CLR 0x14
#define GPIO_PULL_EN 0x18 #define GPIO_PULL_EN 0x18
#define GPIO_PULL_TYPE 0x1C #define GPIO_PULL_TYPE 0x1C
#define GPIO_INT_EN 0x20 #define GPIO_INT_EN 0x20
#define GPIO_INT_STAT 0x24 #define GPIO_INT_STAT_RAW 0x24
#define GPIO_INT_STAT_MASKED 0x28
#define GPIO_INT_MASK 0x2C #define GPIO_INT_MASK 0x2C
#define GPIO_INT_CLR 0x30 #define GPIO_INT_CLR 0x30
#define GPIO_INT_TYPE 0x34 #define GPIO_INT_TYPE 0x34
...@@ -147,7 +148,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc) ...@@ -147,7 +148,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
chained_irq_enter(irqchip, desc); chained_irq_enter(irqchip, desc);
stat = readl(g->base + GPIO_INT_STAT); stat = readl(g->base + GPIO_INT_STAT_RAW);
if (stat) if (stat)
for_each_set_bit(offset, &stat, gc->ngpio) for_each_set_bit(offset, &stat, gc->ngpio)
generic_handle_irq(irq_find_mapping(gc->irq.domain, generic_handle_irq(irq_find_mapping(gc->irq.domain,
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* This driver supports the following Diamond Systems devices: GPIO-MM and * This driver supports the following Diamond Systems devices: GPIO-MM and
* GPIO-MM-12. * GPIO-MM-12.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -171,6 +172,51 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset) ...@@ -171,6 +172,51 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(port_state & mask); return !!(port_state & mask);
} }
static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
size_t i;
const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port */
port_state = inb(gpiommgpio->base + ports[i]);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset, static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value) int value)
{ {
...@@ -268,6 +314,7 @@ static int gpiomm_probe(struct device *dev, unsigned int id) ...@@ -268,6 +314,7 @@ static int gpiomm_probe(struct device *dev, unsigned int id)
gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input; gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input;
gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output; gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output;
gpiommgpio->chip.get = gpiomm_gpio_get; gpiommgpio->chip.get = gpiomm_gpio_get;
gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple;
gpiommgpio->chip.set = gpiomm_gpio_set; gpiommgpio->chip.set = gpiomm_gpio_set;
gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple; gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple;
gpiommgpio->base = base[id]; gpiommgpio->base = base[id];
......
...@@ -26,9 +26,8 @@ ...@@ -26,9 +26,8 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
......
// SPDX-License-Identifier: GPL-2.0+
// Copyright (C) 2008-2009 The GameCube Linux Team
// Copyright (C) 2008,2009 Albert Herranz
// Copyright (C) 2017-2018 Jonathan Neuschäfer
//
// Nintendo Wii (Hollywood) GPIO driver
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
/*
* Register names and offsets courtesy of WiiBrew:
* https://wiibrew.org/wiki/Hardware/Hollywood_GPIOs
*
* Note that for most registers, there are two versions:
* - HW_GPIOB_* Is always accessible by the Broadway PowerPC core, but does
* always give access to all GPIO lines
* - HW_GPIO_* Is only accessible by the Broadway PowerPC code if the memory
* firewall (AHBPROT) in the Hollywood chipset has been configured to allow
* such access.
*
* The ownership of each GPIO line can be configured in the HW_GPIO_OWNER
* register: A one bit configures the line for access via the HW_GPIOB_*
* registers, a zero bit indicates access via HW_GPIO_*. This driver uses
* HW_GPIOB_*.
*/
#define HW_GPIOB_OUT 0x00
#define HW_GPIOB_DIR 0x04
#define HW_GPIOB_IN 0x08
#define HW_GPIOB_INTLVL 0x0c
#define HW_GPIOB_INTFLAG 0x10
#define HW_GPIOB_INTMASK 0x14
#define HW_GPIOB_INMIR 0x18
#define HW_GPIO_ENABLE 0x1c
#define HW_GPIO_OUT 0x20
#define HW_GPIO_DIR 0x24
#define HW_GPIO_IN 0x28
#define HW_GPIO_INTLVL 0x2c
#define HW_GPIO_INTFLAG 0x30
#define HW_GPIO_INTMASK 0x34
#define HW_GPIO_INMIR 0x38
#define HW_GPIO_OWNER 0x3c
struct hlwd_gpio {
struct gpio_chip gpioc;
void __iomem *regs;
};
static int hlwd_gpio_probe(struct platform_device *pdev)
{
struct hlwd_gpio *hlwd;
struct resource *regs_resource;
u32 ngpios;
int res;
hlwd = devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL);
if (!hlwd)
return -ENOMEM;
regs_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hlwd->regs = devm_ioremap_resource(&pdev->dev, regs_resource);
if (IS_ERR(hlwd->regs))
return PTR_ERR(hlwd->regs);
/*
* Claim all GPIOs using the OWNER register. This will not work on
* systems where the AHBPROT memory firewall hasn't been configured to
* permit PPC access to HW_GPIO_*.
*
* Note that this has to happen before bgpio_init reads the
* HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the wrong
* values.
*/
iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER);
res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4,
hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT,
NULL, hlwd->regs + HW_GPIOB_DIR, NULL,
BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (res < 0) {
dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res);
return res;
}
res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios);
if (res)
ngpios = 32;
hlwd->gpioc.ngpio = ngpios;
return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
}
static const struct of_device_id hlwd_gpio_match[] = {
{ .compatible = "nintendo,hollywood-gpio", },
{},
};
MODULE_DEVICE_TABLE(of, hlwd_gpio_match);
static struct platform_driver hlwd_gpio_driver = {
.driver = {
.name = "gpio-hlwd",
.of_match_table = hlwd_gpio_match,
},
.probe = hlwd_gpio_probe,
};
module_platform_driver(hlwd_gpio_driver);
MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
MODULE_DESCRIPTION("Nintendo Wii GPIO driver");
MODULE_LICENSE("GPL");
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio/driver.h>
struct egpio_chip { struct egpio_chip {
int reg_start; int reg_start;
......
...@@ -23,9 +23,10 @@ ...@@ -23,9 +23,10 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/lpc_ich.h> #include <linux/mfd/lpc_ich.h>
#include <linux/bitops.h>
#define DRV_NAME "gpio_ich" #define DRV_NAME "gpio_ich"
...@@ -131,9 +132,9 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify) ...@@ -131,9 +132,9 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
ichx_priv.gpio_base); ichx_priv.gpio_base);
if (val) if (val)
data |= 1 << bit; data |= BIT(bit);
else else
data &= ~(1 << bit); data &= ~BIT(bit);
ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
ichx_priv.gpio_base); ichx_priv.gpio_base);
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
...@@ -166,17 +167,17 @@ static int ichx_read_bit(int reg, unsigned nr) ...@@ -166,17 +167,17 @@ static int ichx_read_bit(int reg, unsigned nr)
spin_unlock_irqrestore(&ichx_priv.lock, flags); spin_unlock_irqrestore(&ichx_priv.lock, flags);
return data & (1 << bit) ? 1 : 0; return !!(data & BIT(bit));
} }
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
{ {
return !!(ichx_priv.use_gpio & (1 << (nr / 32))); return !!(ichx_priv.use_gpio & BIT(nr / 32));
} }
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
{ {
return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; return ichx_read_bit(GPIO_IO_SEL, nr);
} }
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
...@@ -232,12 +233,12 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) ...@@ -232,12 +233,12 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
spin_lock_irqsave(&ichx_priv.lock, flags); spin_lock_irqsave(&ichx_priv.lock, flags);
/* GPI 0 - 15 are latched, write 1 to clear*/ /* GPI 0 - 15 are latched, write 1 to clear*/
ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); ICHX_WRITE(BIT(16 + nr), 0, ichx_priv.pm_base);
data = ICHX_READ(0, ichx_priv.pm_base); data = ICHX_READ(0, ichx_priv.pm_base);
spin_unlock_irqrestore(&ichx_priv.lock, flags); spin_unlock_irqrestore(&ichx_priv.lock, flags);
return (data >> 16) & (1 << nr) ? 1 : 0; return !!((data >> 16) & BIT(nr));
} else { } else {
return ichx_gpio_get(chip, nr); return ichx_gpio_get(chip, nr);
} }
...@@ -254,7 +255,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) ...@@ -254,7 +255,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
* the chipset's USE value can be trusted for this specific bit. * the chipset's USE value can be trusted for this specific bit.
* If it can't be trusted, assume that the pin can be used as a GPIO. * If it can't be trusted, assume that the pin can be used as a GPIO.
*/ */
if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) if (ichx_priv.desc->use_sel_ignore[nr / 32] & BIT(nr & 0x1f))
return 0; return 0;
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
...@@ -394,7 +395,7 @@ static int ichx_gpio_request_regions(struct device *dev, ...@@ -394,7 +395,7 @@ static int ichx_gpio_request_regions(struct device *dev,
return -ENODEV; return -ENODEV;
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
if (!(use_gpio & (1 << i))) if (!(use_gpio & BIT(i)))
continue; continue;
if (!devm_request_region(dev, if (!devm_request_region(dev,
res_base->start + ichx_priv.desc->regs[0][i], res_base->start + ichx_priv.desc->regs[0][i],
......
...@@ -361,10 +361,8 @@ static int intel_gpio_probe(struct pci_dev *pdev, ...@@ -361,10 +361,8 @@ static int intel_gpio_probe(struct pci_dev *pdev,
pcim_iounmap_regions(pdev, 1 << 1); pcim_iounmap_regions(pdev, 1 << 1);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv)
dev_err(&pdev->dev, "can't allocate chip data\n");
return -ENOMEM; return -ENOMEM;
}
priv->reg_base = pcim_iomap_table(pdev)[0]; priv->reg_base = pcim_iomap_table(pdev)[0];
priv->chip.label = dev_name(&pdev->dev); priv->chip.label = dev_name(&pdev->dev);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
/* Chip Id numbers */ /* Chip Id numbers */
#define NO_DEV_ID 0xffff #define NO_DEV_ID 0xffff
......
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/mfd/janz.h> #include <linux/mfd/janz.h>
...@@ -33,9 +34,9 @@ ...@@ -33,9 +34,9 @@
#define MASTER_INT_CTL 0x00 #define MASTER_INT_CTL 0x00
#define MASTER_CONF_CTL 0x01 #define MASTER_CONF_CTL 0x01
#define CONF_PAE (1 << 2) #define CONF_PAE BIT(2)
#define CONF_PBE (1 << 7) #define CONF_PBE BIT(7)
#define CONF_PCE (1 << 4) #define CONF_PCE BIT(4)
struct ttl_control_regs { struct ttl_control_regs {
__be16 portc; __be16 portc;
...@@ -74,7 +75,7 @@ static int ttl_get_value(struct gpio_chip *gpio, unsigned offset) ...@@ -74,7 +75,7 @@ static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
} }
spin_lock(&mod->lock); spin_lock(&mod->lock);
ret = *shadow & (1 << offset); ret = *shadow & BIT(offset);
spin_unlock(&mod->lock); spin_unlock(&mod->lock);
return !!ret; return !!ret;
} }
...@@ -100,9 +101,9 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value) ...@@ -100,9 +101,9 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
spin_lock(&mod->lock); spin_lock(&mod->lock);
if (value) if (value)
*shadow |= (1 << offset); *shadow |= BIT(offset);
else else
*shadow &= ~(1 << offset); *shadow &= ~BIT(offset);
iowrite16be(*shadow, port); iowrite16be(*shadow, port);
spin_unlock(&mod->lock); spin_unlock(&mod->lock);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/mfd/kempld.h> #include <linux/mfd/kempld.h>
#define KEMPLD_GPIO_MAX_NUM 16 #define KEMPLD_GPIO_MAX_NUM 16
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/gpio.h> #include <linux/gpio/driver.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -315,12 +315,17 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs, ...@@ -315,12 +315,17 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
struct gpio_desc **desc, struct gpio_desc **desc,
int value) int value)
{ {
int i, values[ndescs]; int i, *values;
values = kmalloc_array(ndescs, sizeof(*values), GFP_KERNEL);
if (!values)
return;
for (i = 0; i < ndescs; i++) for (i = 0; i < ndescs; i++)
values[i] = value; values[i] = value;
gpiod_set_array_value_cansleep(ndescs, desc, values); gpiod_set_array_value_cansleep(ndescs, desc, values);
kfree(values);
} }
static struct gpio_descs *devm_gpiod_get_array_optional_count( static struct gpio_descs *devm_gpiod_get_array_optional_count(
......
...@@ -416,10 +416,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -416,10 +416,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
pcim_iounmap_regions(pdev, BIT(1)); pcim_iounmap_regions(pdev, BIT(1));
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv)
dev_err(&pdev->dev, "can't allocate chip data\n");
return -ENOMEM; return -ENOMEM;
}
priv->dev = &pdev->dev; priv->dev = &pdev->dev;
priv->reg_base = pcim_iomap_table(pdev)[0]; priv->reg_base = pcim_iomap_table(pdev)[0];
......
...@@ -445,7 +445,6 @@ static int ioh_gpio_probe(struct pci_dev *pdev, ...@@ -445,7 +445,6 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
if (chip_save == NULL) { if (chip_save == NULL) {
dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
ret = -ENOMEM; ret = -ENOMEM;
goto err_kzalloc; goto err_kzalloc;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* GPIO Testing Device Driver * GPIO Testing Device Driver
* *
* Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com> * Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com>
* Copyright (C) 2015-2016 Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> * Copyright (C) 2015-2016 Bamvor Jian Zhang <bamv2005@gmail.com>
* Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl> * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
...@@ -314,7 +314,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) ...@@ -314,7 +314,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
if (rv) if (rv)
return rv; return rv;
if (gpio_mockup_dbg_dir) if (!IS_ERR_OR_NULL(gpio_mockup_dbg_dir))
gpio_mockup_debugfs_setup(dev, chip); gpio_mockup_debugfs_setup(dev, chip);
return 0; return 0;
...@@ -411,7 +411,7 @@ module_init(gpio_mockup_init); ...@@ -411,7 +411,7 @@ module_init(gpio_mockup_init);
module_exit(gpio_mockup_exit); module_exit(gpio_mockup_exit);
MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>"); MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
MODULE_AUTHOR("Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>"); MODULE_AUTHOR("Bamvor Jian Zhang <bamv2005@gmail.com>");
MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>"); MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>");
MODULE_DESCRIPTION("GPIO Testing driver"); MODULE_DESCRIPTION("GPIO Testing driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -1157,11 +1157,9 @@ static int omap_gpio_probe(struct platform_device *pdev) ...@@ -1157,11 +1157,9 @@ static int omap_gpio_probe(struct platform_device *pdev)
if (!pdata) if (!pdata)
return -EINVAL; return -EINVAL;
bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL); bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
if (!bank) { if (!bank)
dev_err(dev, "Memory alloc failed\n");
return -ENOMEM; return -ENOMEM;
}
irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL);
if (!irqc) if (!irqc)
......
...@@ -70,6 +70,7 @@ static const struct i2c_device_id pca953x_id[] = { ...@@ -70,6 +70,7 @@ static const struct i2c_device_id pca953x_id[] = {
{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
{ "pca9698", 40 | PCA953X_TYPE, }, { "pca9698", 40 | PCA953X_TYPE, },
{ "pcal6524", 24 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
{ "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, { "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
{ "max7310", 8 | PCA953X_TYPE, }, { "max7310", 8 | PCA953X_TYPE, },
...@@ -935,6 +936,9 @@ static const struct of_device_id pca953x_dt_ids[] = { ...@@ -935,6 +936,9 @@ static const struct of_device_id pca953x_dt_ids[] = {
{ .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), },
{ .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), },
{ .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_INT), },
{ .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_INT), },
{ .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), },
{ .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
{ .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), },
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -103,6 +104,54 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) ...@@ -103,6 +104,54 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24)); return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
} }
static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
size_t i;
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
u8 __iomem ports[] = {
idio16gpio->reg->out0_7, idio16gpio->reg->out8_15,
idio16gpio->reg->in0_7, idio16gpio->reg->in8_15,
};
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port */
port_state = ioread8(ports + i);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value) int value)
{ {
...@@ -299,6 +348,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -299,6 +348,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idio16gpio->chip.direction_input = idio_16_gpio_direction_input; idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
idio16gpio->chip.direction_output = idio_16_gpio_direction_output; idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get; idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* This driver supports the following ACCES devices: PCIe-IDIO-24, * This driver supports the following ACCES devices: PCIe-IDIO-24,
* PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12. * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -193,6 +194,61 @@ static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset) ...@@ -193,6 +194,61 @@ static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask); return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
} }
static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
size_t i;
const unsigned int gpio_reg_size = 8;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
u8 __iomem ports[] = {
idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
idio24gpio->reg->out16_23, idio24gpio->reg->in0_7,
idio24gpio->reg->in8_15, idio24gpio->reg->in16_23,
};
const unsigned long out_mode_mask = BIT(1);
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port (port 6 is TTL GPIO) */
if (i < 6)
port_state = ioread8(ports + i);
else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
else
port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value) int value)
{ {
...@@ -234,6 +290,65 @@ static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, ...@@ -234,6 +290,65 @@ static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
} }
static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
size_t i;
unsigned long bits_offset;
unsigned long gpio_mask;
const unsigned int gpio_reg_size = 8;
const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
unsigned long flags;
unsigned int out_state;
u8 __iomem ports[] = {
idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
idio24gpio->reg->out16_23
};
const unsigned long out_mode_mask = BIT(1);
const unsigned int ttl_offset = 48;
const size_t ttl_i = BIT_WORD(ttl_offset);
const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
/* set bits are processed a gpio port register at a time */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* check if any set bits for current port */
gpio_mask = (*mask >> bits_offset) & port_mask;
if (!gpio_mask) {
/* no set bits for this port so move on to next port */
continue;
}
raw_spin_lock_irqsave(&idio24gpio->lock, flags);
/* process output lines */
out_state = ioread8(ports + i) & ~gpio_mask;
out_state |= (*bits >> bits_offset) & gpio_mask;
iowrite8(out_state, ports + i);
raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
}
/* check if setting TTL lines and if they are in output mode */
if (!ttl_mask || !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
return;
/* handle TTL output */
raw_spin_lock_irqsave(&idio24gpio->lock, flags);
/* process output lines */
out_state = ioread8(&idio24gpio->reg->ttl_out0_7) & ~ttl_mask;
out_state |= ttl_bits;
iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
}
static void idio_24_irq_ack(struct irq_data *data) static void idio_24_irq_ack(struct irq_data *data)
{ {
} }
...@@ -397,7 +512,9 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -397,7 +512,9 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idio24gpio->chip.direction_input = idio_24_gpio_direction_input; idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
idio24gpio->chip.direction_output = idio_24_gpio_direction_output; idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
idio24gpio->chip.get = idio_24_gpio_get; idio24gpio->chip.get = idio_24_gpio_get;
idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
idio24gpio->chip.set = idio_24_gpio_set; idio24gpio->chip.set = idio_24_gpio_set;
idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
raw_spin_lock_init(&idio24gpio->lock); raw_spin_lock_init(&idio24gpio->lock);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Spreadtrum Communications Inc.
* Copyright (C) 2018 Linaro Ltd.
*/
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
/* EIC registers definition */
#define SPRD_PMIC_EIC_DATA 0x0
#define SPRD_PMIC_EIC_DMSK 0x4
#define SPRD_PMIC_EIC_IEV 0x14
#define SPRD_PMIC_EIC_IE 0x18
#define SPRD_PMIC_EIC_RIS 0x1c
#define SPRD_PMIC_EIC_MIS 0x20
#define SPRD_PMIC_EIC_IC 0x24
#define SPRD_PMIC_EIC_TRIG 0x28
#define SPRD_PMIC_EIC_CTRL0 0x40
/*
* The PMIC EIC controller only has one bank, and each bank now can contain
* 16 EICs.
*/
#define SPRD_PMIC_EIC_PER_BANK_NR 16
#define SPRD_PMIC_EIC_NR SPRD_PMIC_EIC_PER_BANK_NR
#define SPRD_PMIC_EIC_DATA_MASK GENMASK(15, 0)
#define SPRD_PMIC_EIC_BIT(x) ((x) & (SPRD_PMIC_EIC_PER_BANK_NR - 1))
#define SPRD_PMIC_EIC_DBNC_MASK GENMASK(11, 0)
/*
* These registers are modified under the irq bus lock and cached to avoid
* unnecessary writes in bus_sync_unlock.
*/
enum {
REG_IEV,
REG_IE,
REG_TRIG,
CACHE_NR_REGS
};
/**
* struct sprd_pmic_eic - PMIC EIC controller
* @chip: the gpio_chip structure.
* @intc: the irq_chip structure.
* @regmap: the regmap from the parent device.
* @offset: the EIC controller's offset address of the PMIC.
* @reg: the array to cache the EIC registers.
* @buslock: for bus lock/sync and unlock.
* @irq: the interrupt number of the PMIC EIC conteroller.
*/
struct sprd_pmic_eic {
struct gpio_chip chip;
struct irq_chip intc;
struct regmap *map;
u32 offset;
u8 reg[CACHE_NR_REGS];
struct mutex buslock;
int irq;
};
static void sprd_pmic_eic_update(struct gpio_chip *chip, unsigned int offset,
u16 reg, unsigned int val)
{
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 shift = SPRD_PMIC_EIC_BIT(offset);
regmap_update_bits(pmic_eic->map, pmic_eic->offset + reg,
BIT(shift), val << shift);
}
static int sprd_pmic_eic_read(struct gpio_chip *chip, unsigned int offset,
u16 reg)
{
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 value;
int ret;
ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value);
if (ret)
return ret;
return !!(value & BIT(SPRD_PMIC_EIC_BIT(offset)));
}
static int sprd_pmic_eic_request(struct gpio_chip *chip, unsigned int offset)
{
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 1);
return 0;
}
static void sprd_pmic_eic_free(struct gpio_chip *chip, unsigned int offset)
{
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 0);
}
static int sprd_pmic_eic_get(struct gpio_chip *chip, unsigned int offset)
{
return sprd_pmic_eic_read(chip, offset, SPRD_PMIC_EIC_DATA);
}
static int sprd_pmic_eic_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
/* EICs are always input, nothing need to do here. */
return 0;
}
static void sprd_pmic_eic_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
/* EICs are always input, nothing need to do here. */
}
static int sprd_pmic_eic_set_debounce(struct gpio_chip *chip,
unsigned int offset,
unsigned int debounce)
{
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 reg, value;
int ret;
reg = SPRD_PMIC_EIC_CTRL0 + SPRD_PMIC_EIC_BIT(offset) * 0x4;
ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value);
if (ret)
return ret;
value &= ~SPRD_PMIC_EIC_DBNC_MASK;
value |= (debounce / 1000) & SPRD_PMIC_EIC_DBNC_MASK;
return regmap_write(pmic_eic->map, pmic_eic->offset + reg, value);
}
static int sprd_pmic_eic_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
unsigned long param = pinconf_to_config_param(config);
u32 arg = pinconf_to_config_argument(config);
if (param == PIN_CONFIG_INPUT_DEBOUNCE)
return sprd_pmic_eic_set_debounce(chip, offset, arg);
return -ENOTSUPP;
}
static void sprd_pmic_eic_irq_mask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
pmic_eic->reg[REG_IE] = 0;
pmic_eic->reg[REG_TRIG] = 0;
}
static void sprd_pmic_eic_irq_unmask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
pmic_eic->reg[REG_IE] = 1;
pmic_eic->reg[REG_TRIG] = 1;
}
static int sprd_pmic_eic_irq_set_type(struct irq_data *data,
unsigned int flow_type)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
switch (flow_type) {
case IRQ_TYPE_LEVEL_HIGH:
pmic_eic->reg[REG_IEV] = 1;
break;
case IRQ_TYPE_LEVEL_LOW:
pmic_eic->reg[REG_IEV] = 0;
break;
default:
return -ENOTSUPP;
}
return 0;
}
static void sprd_pmic_eic_bus_lock(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
mutex_lock(&pmic_eic->buslock);
}
static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 offset = irqd_to_hwirq(data);
/* Set irq type */
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV,
pmic_eic->reg[REG_IEV]);
/* Set irq unmask */
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE,
pmic_eic->reg[REG_IE]);
/* Generate trigger start pulse for debounce EIC */
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG,
pmic_eic->reg[REG_TRIG]);
mutex_unlock(&pmic_eic->buslock);
}
static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data)
{
struct sprd_pmic_eic *pmic_eic = data;
struct gpio_chip *chip = &pmic_eic->chip;
unsigned long status;
u32 n, girq, val;
int ret;
ret = regmap_read(pmic_eic->map, pmic_eic->offset + SPRD_PMIC_EIC_MIS,
&val);
if (ret)
return IRQ_RETVAL(ret);
status = val & SPRD_PMIC_EIC_DATA_MASK;
for_each_set_bit(n, &status, chip->ngpio) {
/* Clear the interrupt */
sprd_pmic_eic_update(chip, n, SPRD_PMIC_EIC_IC, 1);
girq = irq_find_mapping(chip->irq.domain, n);
handle_nested_irq(girq);
}
return IRQ_HANDLED;
}
static int sprd_pmic_eic_probe(struct platform_device *pdev)
{
struct gpio_irq_chip *irq;
struct sprd_pmic_eic *pmic_eic;
int ret;
pmic_eic = devm_kzalloc(&pdev->dev, sizeof(*pmic_eic), GFP_KERNEL);
if (!pmic_eic)
return -ENOMEM;
mutex_init(&pmic_eic->buslock);
pmic_eic->irq = platform_get_irq(pdev, 0);
if (pmic_eic->irq < 0) {
dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n");
return pmic_eic->irq;
}
pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL);
if (!pmic_eic->map)
return -ENODEV;
ret = of_property_read_u32(pdev->dev.of_node, "reg", &pmic_eic->offset);
if (ret) {
dev_err(&pdev->dev, "Failed to get PMIC EIC base address.\n");
return ret;
}
ret = devm_request_threaded_irq(&pdev->dev, pmic_eic->irq, NULL,
sprd_pmic_eic_irq_handler,
IRQF_TRIGGER_LOW |
IRQF_ONESHOT | IRQF_NO_SUSPEND,
dev_name(&pdev->dev), pmic_eic);
if (ret) {
dev_err(&pdev->dev, "Failed to request PMIC EIC IRQ.\n");
return ret;
}
pmic_eic->chip.label = dev_name(&pdev->dev);
pmic_eic->chip.ngpio = SPRD_PMIC_EIC_NR;
pmic_eic->chip.base = -1;
pmic_eic->chip.parent = &pdev->dev;
pmic_eic->chip.of_node = pdev->dev.of_node;
pmic_eic->chip.direction_input = sprd_pmic_eic_direction_input;
pmic_eic->chip.request = sprd_pmic_eic_request;
pmic_eic->chip.free = sprd_pmic_eic_free;
pmic_eic->chip.set_config = sprd_pmic_eic_set_config;
pmic_eic->chip.set = sprd_pmic_eic_set;
pmic_eic->chip.get = sprd_pmic_eic_get;
pmic_eic->intc.name = dev_name(&pdev->dev);
pmic_eic->intc.irq_mask = sprd_pmic_eic_irq_mask;
pmic_eic->intc.irq_unmask = sprd_pmic_eic_irq_unmask;
pmic_eic->intc.irq_set_type = sprd_pmic_eic_irq_set_type;
pmic_eic->intc.irq_bus_lock = sprd_pmic_eic_bus_lock;
pmic_eic->intc.irq_bus_sync_unlock = sprd_pmic_eic_bus_sync_unlock;
pmic_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE;
irq = &pmic_eic->chip.irq;
irq->chip = &pmic_eic->intc;
irq->threaded = true;
ret = devm_gpiochip_add_data(&pdev->dev, &pmic_eic->chip, pmic_eic);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret);
return ret;
}
platform_set_drvdata(pdev, pmic_eic);
return 0;
}
static const struct of_device_id sprd_pmic_eic_of_match[] = {
{ .compatible = "sprd,sc27xx-eic", },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, sprd_pmic_eic_of_match);
static struct platform_driver sprd_pmic_eic_driver = {
.probe = sprd_pmic_eic_probe,
.driver = {
.name = "sprd-pmic-eic",
.of_match_table = sprd_pmic_eic_of_match,
},
};
module_platform_driver(sprd_pmic_eic_driver);
MODULE_DESCRIPTION("Spreadtrum PMIC EIC driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0+
/*
* Raspberry Pi 3 expander GPIO driver
*
* Uses the firmware mailbox service to communicate with the
* GPIO expander on the VPU.
*
* Copyright (C) 2017 Raspberry Pi Trading Ltd.
*/
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#define MODULE_NAME "raspberrypi-exp-gpio"
#define NUM_GPIO 8
#define RPI_EXP_GPIO_BASE 128
#define RPI_EXP_GPIO_DIR_IN 0
#define RPI_EXP_GPIO_DIR_OUT 1
struct rpi_exp_gpio {
struct gpio_chip gc;
struct rpi_firmware *fw;
};
/* VC4 firmware mailbox interface data structures */
struct gpio_set_config {
u32 gpio;
u32 direction;
u32 polarity;
u32 term_en;
u32 term_pull_up;
u32 state;
};
struct gpio_get_config {
u32 gpio;
u32 direction;
u32 polarity;
u32 term_en;
u32 term_pull_up;
};
struct gpio_get_set_state {
u32 gpio;
u32 state;
};
static int rpi_exp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off)
{
struct rpi_exp_gpio *gpio;
struct gpio_get_config get;
int ret;
gpio = gpiochip_get_data(gc);
get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
&get, sizeof(get));
if (ret || get.gpio != 0) {
dev_err(gc->parent, "Failed to get GPIO %u config (%d %x)\n",
off, ret, get.gpio);
return ret ? ret : -EIO;
}
return get.polarity;
}
static int rpi_exp_gpio_dir_in(struct gpio_chip *gc, unsigned int off)
{
struct rpi_exp_gpio *gpio;
struct gpio_set_config set_in;
int ret;
gpio = gpiochip_get_data(gc);
set_in.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
set_in.direction = RPI_EXP_GPIO_DIR_IN;
set_in.term_en = 0; /* termination disabled */
set_in.term_pull_up = 0; /* n/a as termination disabled */
set_in.state = 0; /* n/a as configured as an input */
ret = rpi_exp_gpio_get_polarity(gc, off);
if (ret < 0)
return ret;
set_in.polarity = ret; /* Retain existing setting */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
&set_in, sizeof(set_in));
if (ret || set_in.gpio != 0) {
dev_err(gc->parent, "Failed to set GPIO %u to input (%d %x)\n",
off, ret, set_in.gpio);
return ret ? ret : -EIO;
}
return 0;
}
static int rpi_exp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val)
{
struct rpi_exp_gpio *gpio;
struct gpio_set_config set_out;
int ret;
gpio = gpiochip_get_data(gc);
set_out.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
set_out.direction = RPI_EXP_GPIO_DIR_OUT;
set_out.term_en = 0; /* n/a as an output */
set_out.term_pull_up = 0; /* n/a as termination disabled */
set_out.state = val; /* Output state */
ret = rpi_exp_gpio_get_polarity(gc, off);
if (ret < 0)
return ret;
set_out.polarity = ret; /* Retain existing setting */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
&set_out, sizeof(set_out));
if (ret || set_out.gpio != 0) {
dev_err(gc->parent, "Failed to set GPIO %u to output (%d %x)\n",
off, ret, set_out.gpio);
return ret ? ret : -EIO;
}
return 0;
}
static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
{
struct rpi_exp_gpio *gpio;
struct gpio_get_config get;
int ret;
gpio = gpiochip_get_data(gc);
get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
&get, sizeof(get));
if (ret || get.gpio != 0) {
dev_err(gc->parent,
"Failed to get GPIO %u config (%d %x)\n", off, ret,
get.gpio);
return ret ? ret : -EIO;
}
return !get.direction;
}
static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off)
{
struct rpi_exp_gpio *gpio;
struct gpio_get_set_state get;
int ret;
gpio = gpiochip_get_data(gc);
get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
get.state = 0; /* storage for returned value */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE,
&get, sizeof(get));
if (ret || get.gpio != 0) {
dev_err(gc->parent,
"Failed to get GPIO %u state (%d %x)\n", off, ret,
get.gpio);
return ret ? ret : -EIO;
}
return !!get.state;
}
static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
{
struct rpi_exp_gpio *gpio;
struct gpio_get_set_state set;
int ret;
gpio = gpiochip_get_data(gc);
set.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
set.state = val; /* Output state */
ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE,
&set, sizeof(set));
if (ret || set.gpio != 0)
dev_err(gc->parent,
"Failed to set GPIO %u state (%d %x)\n", off, ret,
set.gpio);
}
static int rpi_exp_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *fw_node;
struct rpi_firmware *fw;
struct rpi_exp_gpio *rpi_gpio;
fw_node = of_get_parent(np);
if (!fw_node) {
dev_err(dev, "Missing firmware node\n");
return -ENOENT;
}
fw = rpi_firmware_get(fw_node);
if (!fw)
return -EPROBE_DEFER;
rpi_gpio = devm_kzalloc(dev, sizeof(*rpi_gpio), GFP_KERNEL);
if (!rpi_gpio)
return -ENOMEM;
rpi_gpio->fw = fw;
rpi_gpio->gc.parent = dev;
rpi_gpio->gc.label = MODULE_NAME;
rpi_gpio->gc.owner = THIS_MODULE;
rpi_gpio->gc.of_node = np;
rpi_gpio->gc.base = -1;
rpi_gpio->gc.ngpio = NUM_GPIO;
rpi_gpio->gc.direction_input = rpi_exp_gpio_dir_in;
rpi_gpio->gc.direction_output = rpi_exp_gpio_dir_out;
rpi_gpio->gc.get_direction = rpi_exp_gpio_get_direction;
rpi_gpio->gc.get = rpi_exp_gpio_get;
rpi_gpio->gc.set = rpi_exp_gpio_set;
rpi_gpio->gc.can_sleep = true;
return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio);
}
static const struct of_device_id rpi_exp_gpio_ids[] = {
{ .compatible = "raspberrypi,firmware-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, rpi_exp_gpio_ids);
static struct platform_driver rpi_exp_gpio_driver = {
.driver = {
.name = MODULE_NAME,
.of_match_table = of_match_ptr(rpi_exp_gpio_ids),
},
.probe = rpi_exp_gpio_probe,
};
module_platform_driver(rpi_exp_gpio_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.org>");
MODULE_DESCRIPTION("Raspberry Pi 3 expander GPIO driver");
MODULE_ALIAS("platform:rpi-exp-gpio");
...@@ -30,6 +30,16 @@ ...@@ -30,6 +30,16 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h> #include <linux/slab.h>
struct gpio_rcar_bank_info {
u32 iointsel;
u32 inoutsel;
u32 outdt;
u32 posneg;
u32 edglevel;
u32 bothedge;
u32 intmsk;
};
struct gpio_rcar_priv { struct gpio_rcar_priv {
void __iomem *base; void __iomem *base;
spinlock_t lock; spinlock_t lock;
...@@ -39,6 +49,7 @@ struct gpio_rcar_priv { ...@@ -39,6 +49,7 @@ struct gpio_rcar_priv {
unsigned int irq_parent; unsigned int irq_parent;
atomic_t wakeup_path; atomic_t wakeup_path;
bool has_both_edge_trigger; bool has_both_edge_trigger;
struct gpio_rcar_bank_info bank_info;
}; };
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
...@@ -512,17 +523,62 @@ static int gpio_rcar_remove(struct platform_device *pdev) ...@@ -512,17 +523,62 @@ static int gpio_rcar_remove(struct platform_device *pdev)
return 0; return 0;
} }
static int __maybe_unused gpio_rcar_suspend(struct device *dev) #ifdef CONFIG_PM_SLEEP
static int gpio_rcar_suspend(struct device *dev)
{ {
struct gpio_rcar_priv *p = dev_get_drvdata(dev); struct gpio_rcar_priv *p = dev_get_drvdata(dev);
p->bank_info.iointsel = gpio_rcar_read(p, IOINTSEL);
p->bank_info.inoutsel = gpio_rcar_read(p, INOUTSEL);
p->bank_info.outdt = gpio_rcar_read(p, OUTDT);
p->bank_info.intmsk = gpio_rcar_read(p, INTMSK);
p->bank_info.posneg = gpio_rcar_read(p, POSNEG);
p->bank_info.edglevel = gpio_rcar_read(p, EDGLEVEL);
if (p->has_both_edge_trigger)
p->bank_info.bothedge = gpio_rcar_read(p, BOTHEDGE);
if (atomic_read(&p->wakeup_path)) if (atomic_read(&p->wakeup_path))
device_set_wakeup_path(dev); device_set_wakeup_path(dev);
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, NULL); static int gpio_rcar_resume(struct device *dev)
{
struct gpio_rcar_priv *p = dev_get_drvdata(dev);
unsigned int offset;
u32 mask;
for (offset = 0; offset < p->gpio_chip.ngpio; offset++) {
mask = BIT(offset);
/* I/O pin */
if (!(p->bank_info.iointsel & mask)) {
if (p->bank_info.inoutsel & mask)
gpio_rcar_direction_output(
&p->gpio_chip, offset,
!!(p->bank_info.outdt & mask));
else
gpio_rcar_direction_input(&p->gpio_chip,
offset);
} else {
/* Interrupt pin */
gpio_rcar_config_interrupt_input_mode(
p,
offset,
!(p->bank_info.posneg & mask),
!(p->bank_info.edglevel & mask),
!!(p->bank_info.bothedge & mask));
if (p->bank_info.intmsk & mask)
gpio_rcar_write(p, MSKCLR, mask);
}
}
return 0;
}
#endif /* CONFIG_PM_SLEEP*/
static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, gpio_rcar_resume);
static struct platform_driver gpio_rcar_device_driver = { static struct platform_driver gpio_rcar_device_driver = {
.probe = gpio_rcar_probe, .probe = gpio_rcar_probe,
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Spreadtrum Communications Inc.
* Copyright (C) 2018 Linaro Ltd.
*/
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
/* GPIO registers definition */
#define SPRD_GPIO_DATA 0x0
#define SPRD_GPIO_DMSK 0x4
#define SPRD_GPIO_DIR 0x8
#define SPRD_GPIO_IS 0xc
#define SPRD_GPIO_IBE 0x10
#define SPRD_GPIO_IEV 0x14
#define SPRD_GPIO_IE 0x18
#define SPRD_GPIO_RIS 0x1c
#define SPRD_GPIO_MIS 0x20
#define SPRD_GPIO_IC 0x24
#define SPRD_GPIO_INEN 0x28
/* We have 16 banks GPIOs and each bank contain 16 GPIOs */
#define SPRD_GPIO_BANK_NR 16
#define SPRD_GPIO_NR 256
#define SPRD_GPIO_BANK_SIZE 0x80
#define SPRD_GPIO_BANK_MASK GENMASK(15, 0)
#define SPRD_GPIO_BIT(x) ((x) & (SPRD_GPIO_BANK_NR - 1))
struct sprd_gpio {
struct gpio_chip chip;
void __iomem *base;
spinlock_t lock;
int irq;
};
static inline void __iomem *sprd_gpio_bank_base(struct sprd_gpio *sprd_gpio,
unsigned int bank)
{
return sprd_gpio->base + SPRD_GPIO_BANK_SIZE * bank;
}
static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset,
u16 reg, int val)
{
struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
void __iomem *base = sprd_gpio_bank_base(sprd_gpio,
offset / SPRD_GPIO_BANK_NR);
unsigned long flags;
u32 tmp;
spin_lock_irqsave(&sprd_gpio->lock, flags);
tmp = readl_relaxed(base + reg);
if (val)
tmp |= BIT(SPRD_GPIO_BIT(offset));
else
tmp &= ~BIT(SPRD_GPIO_BIT(offset));
writel_relaxed(tmp, base + reg);
spin_unlock_irqrestore(&sprd_gpio->lock, flags);
}
static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 reg)
{
struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
void __iomem *base = sprd_gpio_bank_base(sprd_gpio,
offset / SPRD_GPIO_BANK_NR);
return !!(readl_relaxed(base + reg) & BIT(SPRD_GPIO_BIT(offset)));
}
static int sprd_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 1);
return 0;
}
static void sprd_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 0);
}
static int sprd_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 1);
return 0;
}
static int sprd_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 1);
sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value);
return 0;
}
static int sprd_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
return sprd_gpio_read(chip, offset, SPRD_GPIO_DATA);
}
static void sprd_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value);
}
static void sprd_gpio_irq_mask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
u32 offset = irqd_to_hwirq(data);
sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 0);
}
static void sprd_gpio_irq_ack(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
u32 offset = irqd_to_hwirq(data);
sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
}
static void sprd_gpio_irq_unmask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
u32 offset = irqd_to_hwirq(data);
sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 1);
}
static int sprd_gpio_irq_set_type(struct irq_data *data,
unsigned int flow_type)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
u32 offset = irqd_to_hwirq(data);
switch (flow_type) {
case IRQ_TYPE_EDGE_RISING:
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
irq_set_handler_locked(data, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_FALLING:
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
irq_set_handler_locked(data, handle_edge_irq);
break;
case IRQ_TYPE_EDGE_BOTH:
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1);
irq_set_handler_locked(data, handle_edge_irq);
break;
case IRQ_TYPE_LEVEL_HIGH:
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 1);
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
irq_set_handler_locked(data, handle_level_irq);
break;
case IRQ_TYPE_LEVEL_LOW:
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 1);
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
irq_set_handler_locked(data, handle_level_irq);
break;
default:
return -EINVAL;
}
return 0;
}
static void sprd_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc);
struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip);
u32 bank, n, girq;
chained_irq_enter(ic, desc);
for (bank = 0; bank * SPRD_GPIO_BANK_NR < chip->ngpio; bank++) {
void __iomem *base = sprd_gpio_bank_base(sprd_gpio, bank);
unsigned long reg = readl_relaxed(base + SPRD_GPIO_MIS) &
SPRD_GPIO_BANK_MASK;
for_each_set_bit(n, &reg, SPRD_GPIO_BANK_NR) {
girq = irq_find_mapping(chip->irq.domain,
bank * SPRD_GPIO_BANK_NR + n);
generic_handle_irq(girq);
}
}
chained_irq_exit(ic, desc);
}
static struct irq_chip sprd_gpio_irqchip = {
.name = "sprd-gpio",
.irq_ack = sprd_gpio_irq_ack,
.irq_mask = sprd_gpio_irq_mask,
.irq_unmask = sprd_gpio_irq_unmask,
.irq_set_type = sprd_gpio_irq_set_type,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
static int sprd_gpio_probe(struct platform_device *pdev)
{
struct gpio_irq_chip *irq;
struct sprd_gpio *sprd_gpio;
struct resource *res;
int ret;
sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL);
if (!sprd_gpio)
return -ENOMEM;
sprd_gpio->irq = platform_get_irq(pdev, 0);
if (sprd_gpio->irq < 0) {
dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n");
return sprd_gpio->irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sprd_gpio->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sprd_gpio->base))
return PTR_ERR(sprd_gpio->base);
spin_lock_init(&sprd_gpio->lock);
sprd_gpio->chip.label = dev_name(&pdev->dev);
sprd_gpio->chip.ngpio = SPRD_GPIO_NR;
sprd_gpio->chip.base = -1;
sprd_gpio->chip.parent = &pdev->dev;
sprd_gpio->chip.of_node = pdev->dev.of_node;
sprd_gpio->chip.request = sprd_gpio_request;
sprd_gpio->chip.free = sprd_gpio_free;
sprd_gpio->chip.get = sprd_gpio_get;
sprd_gpio->chip.set = sprd_gpio_set;
sprd_gpio->chip.direction_input = sprd_gpio_direction_input;
sprd_gpio->chip.direction_output = sprd_gpio_direction_output;
irq = &sprd_gpio->chip.irq;
irq->chip = &sprd_gpio_irqchip;
irq->handler = handle_bad_irq;
irq->default_type = IRQ_TYPE_NONE;
irq->parent_handler = sprd_gpio_irq_handler;
irq->parent_handler_data = sprd_gpio;
irq->num_parents = 1;
irq->parents = &sprd_gpio->irq;
ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, sprd_gpio);
return 0;
}
static const struct of_device_id sprd_gpio_of_match[] = {
{ .compatible = "sprd,sc9860-gpio", },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, sprd_gpio_of_match);
static struct platform_driver sprd_gpio_driver = {
.probe = sprd_gpio_probe,
.driver = {
.name = "sprd-gpio",
.of_match_table = sprd_gpio_of_match,
},
};
module_platform_driver_probe(sprd_gpio_driver, sprd_gpio_probe);
MODULE_DESCRIPTION("Spreadtrum GPIO driver");
MODULE_LICENSE("GPL v2");
...@@ -506,7 +506,7 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) ...@@ -506,7 +506,7 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
static int dbg_gpio_show(struct seq_file *s, void *unused) static int tegra_dbg_gpio_show(struct seq_file *s, void *unused)
{ {
struct tegra_gpio_info *tgi = s->private; struct tegra_gpio_info *tgi = s->private;
unsigned int i, j; unsigned int i, j;
...@@ -530,22 +530,12 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) ...@@ -530,22 +530,12 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
return 0; return 0;
} }
static int dbg_gpio_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(tegra_dbg_gpio);
{
return single_open(file, dbg_gpio_show, inode->i_private);
}
static const struct file_operations debug_fops = {
.open = dbg_gpio_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi)
{ {
(void) debugfs_create_file("tegra_gpio", 0444, (void) debugfs_create_file("tegra_gpio", 0444,
NULL, tgi, &debug_fops); NULL, tgi, &tegra_dbg_gpio_fops);
} }
#else #else
......
...@@ -238,11 +238,10 @@ static int timbgpio_probe(struct platform_device *pdev) ...@@ -238,11 +238,10 @@ static int timbgpio_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL); tgpio = devm_kzalloc(dev, sizeof(*tgpio), GFP_KERNEL);
if (!tgpio) { if (!tgpio)
dev_err(dev, "Memory alloc failed\n");
return -EINVAL; return -EINVAL;
}
tgpio->irq_base = pdata->irq_base; tgpio->irq_base = pdata->irq_base;
spin_lock_init(&tgpio->lock); spin_lock_init(&tgpio->lock);
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* GPIO driver for TPS68470 PMIC * GPIO driver for TPS68470 PMIC
* *
...@@ -8,15 +9,6 @@ ...@@ -8,15 +9,6 @@
* Tianshu Qiu <tian.shu.qiu@intel.com> * Tianshu Qiu <tian.shu.qiu@intel.com>
* Jian Xu Zheng <jian.xu.zheng@intel.com> * Jian Xu Zheng <jian.xu.zheng@intel.com>
* Yuning Pu <yuning.pu@intel.com> * Yuning Pu <yuning.pu@intel.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/gpio/driver.h> #include <linux/gpio/driver.h>
......
/*
* Toumaz Xenif TZ1090 PDC GPIO handling.
*
* Copyright (C) 2012-2013 Imagination Technologies Ltd.
*
* 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.
*/
#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
#include <asm/global_lock.h>
/* Register offsets from SOC_GPIO_CONTROL0 */
#define REG_SOC_GPIO_CONTROL0 0x00
#define REG_SOC_GPIO_CONTROL1 0x04
#define REG_SOC_GPIO_CONTROL2 0x08
#define REG_SOC_GPIO_CONTROL3 0x0c
#define REG_SOC_GPIO_STATUS 0x80
/* PDC GPIOs go after normal GPIOs */
#define GPIO_PDC_BASE 90
#define GPIO_PDC_NGPIO 7
/* Out of PDC gpios, only syswakes have irqs */
#define GPIO_PDC_IRQ_FIRST 2
#define GPIO_PDC_NIRQ 3
/**
* struct tz1090_pdc_gpio - GPIO bank private data
* @chip: Generic GPIO chip for GPIO bank
* @reg: Base of registers, offset for this GPIO bank
* @irq: IRQ numbers for Syswake GPIOs
*
* This is the main private data for the PDC GPIO driver. It encapsulates a
* gpio_chip, and the callbacks for the gpio_chip can access the private data
* with the to_pdc() macro below.
*/
struct tz1090_pdc_gpio {
struct gpio_chip chip;
void __iomem *reg;
int irq[GPIO_PDC_NIRQ];
};
/* Register accesses into the PDC MMIO area */
static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs,
unsigned int data)
{
writel(data, priv->reg + reg_offs);
}
static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv,
unsigned int reg_offs)
{
return readl(priv->reg + reg_offs);
}
/* Generic GPIO interface */
static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip);
u32 value;
int lstat;
__global_lock2(lstat);
value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
value |= BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
__global_unlock2(lstat);
return 0;
}
static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset,
int output_value)
{
struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip);
u32 value;
int lstat;
__global_lock2(lstat);
/* EXT_POWER doesn't seem to have an output value bit */
if (offset < 6) {
value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
if (output_value)
value |= BIT(offset);
else
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
}
value = pdc_read(priv, REG_SOC_GPIO_CONTROL1);
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL1, value);
__global_unlock2(lstat);
return 0;
}
static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip);
return !!(pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset));
}
static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
int output_value)
{
struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip);
u32 value;
int lstat;
/* EXT_POWER doesn't seem to have an output value bit */
if (offset >= 6)
return;
__global_lock2(lstat);
value = pdc_read(priv, REG_SOC_GPIO_CONTROL0);
if (output_value)
value |= BIT(offset);
else
value &= ~BIT(offset);
pdc_write(priv, REG_SOC_GPIO_CONTROL0, value);
__global_unlock2(lstat);
}
static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip);
unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST;
int irq;
/* only syswakes have irqs */
if (syswake >= GPIO_PDC_NIRQ)
return -EINVAL;
irq = priv->irq[syswake];
if (!irq)
return -EINVAL;
return irq;
}
static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res_regs;
struct tz1090_pdc_gpio *priv;
unsigned int i;
if (!np) {
dev_err(&pdev->dev, "must be instantiated via devicetree\n");
return -ENOENT;
}
res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_regs) {
dev_err(&pdev->dev, "cannot find registers resource\n");
return -ENOENT;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "unable to allocate driver data\n");
return -ENOMEM;
}
/* Ioremap the registers */
priv->reg = devm_ioremap(&pdev->dev, res_regs->start,
resource_size(res_regs));
if (!priv->reg) {
dev_err(&pdev->dev, "unable to ioremap registers\n");
return -ENOMEM;
}
/* Set up GPIO chip */
priv->chip.label = "tz1090-pdc-gpio";
priv->chip.parent = &pdev->dev;
priv->chip.direction_input = tz1090_pdc_gpio_direction_input;
priv->chip.direction_output = tz1090_pdc_gpio_direction_output;
priv->chip.get = tz1090_pdc_gpio_get;
priv->chip.set = tz1090_pdc_gpio_set;
priv->chip.free = gpiochip_generic_free;
priv->chip.request = gpiochip_generic_request;
priv->chip.to_irq = tz1090_pdc_gpio_to_irq;
priv->chip.of_node = np;
/* GPIO numbering */
priv->chip.base = GPIO_PDC_BASE;
priv->chip.ngpio = GPIO_PDC_NGPIO;
/* Map the syswake irqs */
for (i = 0; i < GPIO_PDC_NIRQ; ++i)
priv->irq[i] = irq_of_parse_and_map(np, i);
/* Add the GPIO bank */
gpiochip_add_data(&priv->chip, priv);
return 0;
}
static struct of_device_id tz1090_pdc_gpio_of_match[] = {
{ .compatible = "img,tz1090-pdc-gpio" },
{ },
};
static struct platform_driver tz1090_pdc_gpio_driver = {
.driver = {
.name = "tz1090-pdc-gpio",
.of_match_table = tz1090_pdc_gpio_of_match,
},
.probe = tz1090_pdc_gpio_probe,
};
static int __init tz1090_pdc_gpio_init(void)
{
return platform_driver_register(&tz1090_pdc_gpio_driver);
}
subsys_initcall(tz1090_pdc_gpio_init);
This diff is collapsed.
...@@ -182,7 +182,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -182,7 +182,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
dev_err(wm831x->dev, dev_err(wm831x->dev,
"GPIO control %d read failed: %d\n", "GPIO control %d read failed: %d\n",
gpio, reg); gpio, reg);
seq_printf(s, "\n"); seq_putc(s, '\n');
continue; continue;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
*/ */
#include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -129,6 +130,51 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -129,6 +130,51 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(port_state & mask); return !!(port_state & mask);
} }
static int ws16c48_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
const unsigned int gpio_reg_size = 8;
size_t i;
const size_t num_ports = chip->ngpio / gpio_reg_size;
unsigned int bits_offset;
size_t word_index;
unsigned int word_offset;
unsigned long word_mask;
const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
unsigned long port_state;
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
/* get bits are evaluated a gpio port register at a time */
for (i = 0; i < num_ports; i++) {
/* gpio offset in bits array */
bits_offset = i * gpio_reg_size;
/* word index for bits array */
word_index = BIT_WORD(bits_offset);
/* gpio offset within current word of bits array */
word_offset = bits_offset % BITS_PER_LONG;
/* mask of get bits for current gpio within current word */
word_mask = mask[word_index] & (port_mask << word_offset);
if (!word_mask) {
/* no get bits in this port so skip to next one */
continue;
}
/* read bits from current gpio port */
port_state = inb(ws16c48gpio->base + i);
/* store acquired bits at respective bits array offset */
bits[word_index] |= port_state << word_offset;
}
return 0;
}
static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
...@@ -383,6 +429,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id) ...@@ -383,6 +429,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input;
ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output;
ws16c48gpio->chip.get = ws16c48_gpio_get; ws16c48gpio->chip.get = ws16c48_gpio_get;
ws16c48gpio->chip.get_multiple = ws16c48_gpio_get_multiple;
ws16c48gpio->chip.set = ws16c48_gpio_set; ws16c48gpio->chip.set = ws16c48_gpio_set;
ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple; ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
ws16c48gpio->base = base[id]; ws16c48gpio->base = base[id];
......
...@@ -126,11 +126,16 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -126,11 +126,16 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{ {
int reg; int reg;
struct xra1403 *xra = gpiochip_get_data(chip); struct xra1403 *xra = gpiochip_get_data(chip);
int value[xra1403_regmap_cfg.max_register]; int *value;
int i; int i;
unsigned int gcr; unsigned int gcr;
unsigned int gsr; unsigned int gsr;
value = kmalloc_array(xra1403_regmap_cfg.max_register, sizeof(*value),
GFP_KERNEL);
if (!value)
return;
seq_puts(s, "xra reg:"); seq_puts(s, "xra reg:");
for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++) for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++)
seq_printf(s, " %2.2x", reg); seq_printf(s, " %2.2x", reg);
...@@ -154,6 +159,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -154,6 +159,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
(gcr & BIT(i)) ? "in" : "out", (gcr & BIT(i)) ? "in" : "out",
(gsr & BIT(i)) ? "hi" : "lo"); (gsr & BIT(i)) ? "hi" : "lo");
} }
kfree(value);
} }
#else #else
#define xra1403_dbg_show NULL #define xra1403_dbg_show NULL
......
...@@ -511,6 +511,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) ...@@ -511,6 +511,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
} }
EXPORT_SYMBOL(of_mm_gpiochip_remove); EXPORT_SYMBOL(of_mm_gpiochip_remove);
static void of_gpiochip_init_valid_mask(struct gpio_chip *chip)
{
int len, i;
u32 start, count;
struct device_node *np = chip->of_node;
len = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (len < 0 || len % 2 != 0)
return;
for (i = 0; i < len; i += 2) {
of_property_read_u32_index(np, "gpio-reserved-ranges",
i, &start);
of_property_read_u32_index(np, "gpio-reserved-ranges",
i + 1, &count);
if (start >= chip->ngpio || start + count >= chip->ngpio)
continue;
bitmap_clear(chip->valid_mask, start, count);
}
};
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
static int of_gpiochip_add_pin_range(struct gpio_chip *chip) static int of_gpiochip_add_pin_range(struct gpio_chip *chip)
{ {
...@@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip) ...@@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip)
if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS)
return -EINVAL; return -EINVAL;
of_gpiochip_init_valid_mask(chip);
status = of_gpiochip_add_pin_range(chip); status = of_gpiochip_add_pin_range(chip);
if (status) if (status)
return status; return status;
......
This diff is collapsed.
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
#define GPIOLIB_H #define GPIOLIB_H
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h> /* for enum gpiod_flags */
#include <linux/err.h> #include <linux/err.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/cdev.h> #include <linux/cdev.h>
enum of_gpio_flags; enum of_gpio_flags;
enum gpiod_flags;
enum gpio_lookup_flags; enum gpio_lookup_flags;
struct acpi_device; struct acpi_device;
......
...@@ -697,7 +697,8 @@ config STM32_DFSDM_ADC ...@@ -697,7 +697,8 @@ config STM32_DFSDM_ADC
config STX104 config STX104
tristate "Apex Embedded Systems STX104 driver" tristate "Apex Embedded Systems STX104 driver"
depends on PC104 && X86 && ISA_BUS_API depends on PC104 && X86
select ISA_BUS_API
select GPIOLIB select GPIOLIB
help help
Say yes here to build support for the Apex Embedded Systems STX104 Say yes here to build support for the Apex Embedded Systems STX104
......
...@@ -7,7 +7,8 @@ menu "Counters" ...@@ -7,7 +7,8 @@ menu "Counters"
config 104_QUAD_8 config 104_QUAD_8
tristate "ACCES 104-QUAD-8 driver" tristate "ACCES 104-QUAD-8 driver"
depends on PC104 && X86 && ISA_BUS_API depends on PC104 && X86
select ISA_BUS_API
help help
Say yes here to build support for the ACCES 104-QUAD-8 quadrature Say yes here to build support for the ACCES 104-QUAD-8 quadrature
encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
......
...@@ -195,7 +195,8 @@ config AD7303 ...@@ -195,7 +195,8 @@ config AD7303
config CIO_DAC config CIO_DAC
tristate "Measurement Computing CIO-DAC IIO driver" tristate "Measurement Computing CIO-DAC IIO driver"
depends on X86 && ISA_BUS_API depends on X86 && (ISA_BUS || PC104)
select ISA_BUS_API
help help
Say yes here to build support for the Measurement Computing CIO-DAC Say yes here to build support for the Measurement Computing CIO-DAC
analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The
......
This diff is collapsed.
...@@ -866,7 +866,8 @@ config ALIM7101_WDT ...@@ -866,7 +866,8 @@ config ALIM7101_WDT
config EBC_C384_WDT config EBC_C384_WDT
tristate "WinSystems EBC-C384 Watchdog Timer" tristate "WinSystems EBC-C384 Watchdog Timer"
depends on X86 && ISA_BUS_API depends on X86
select ISA_BUS_API
select WATCHDOG_CORE select WATCHDOG_CORE
help help
Enables watchdog timer support for the watchdog timer on the Enables watchdog timer support for the watchdog timer on the
......
This diff is collapsed.
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#ifndef __HTC_EGPIO_H__ #ifndef __HTC_EGPIO_H__
#define __HTC_EGPIO_H__ #define __HTC_EGPIO_H__
#include <linux/gpio.h>
/* Descriptive values for all-in or all-out htc_egpio_chip descriptors. */ /* Descriptive values for all-in or all-out htc_egpio_chip descriptors. */
#define HTC_EGPIO_OUTPUT (~0) #define HTC_EGPIO_OUTPUT (~0)
#define HTC_EGPIO_INPUT 0 #define HTC_EGPIO_INPUT 0
......
This diff is collapsed.
This diff is collapsed.
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