This is the bulk of GPIO changes for the v4.12 kernel cycle:

Core changes
 
 - Return NULL from gpiod_get_optional() when GPIOLIB is disabled.
   This was a much discussed change. It affects use cases where people
   write drivers that might or might not be using GPIO resources.
   I have decided that this is the lesser evil right now.
 
 - Make gpiod_count() behave consistently across different hardware
   descriptions.
 
 - Fix the syntax around open drain/open source to not infer active
   high/low semantics.
 
 New drivers
 
 - A new single-register fixed-direction framework driver for hardware
   that have lines controlled by a single register that just work in
   one direction (out or in), including IRQ support.
 
 - Support the Fintek F71889A GPIO SuperIO controller.
 
 - Support the National NI 169445 MMIO GPIO.
 
 - Support for the X-Gene derivative of the DWC GPIO controller
 
 - Support for the Rohm BD9571MWV-M PMIC GPIO controller.
 
 - Refactor the Gemini GPIO driver to a generic Faraday FTGPIO driver
   and replace both the Gemini and the Moxa ART custom drivers with
   this driver.
 
 Driver improvements
 
 - A whole slew of drivers have their spinlocks chaned to raw spinlocks
   as they provide irqchips, and thus we are progressing on realtime
   compliance.
 
 - Use devm_irq_alloc_descs() in a slew of drivers, getting managed
   resources.
 
 - Support for the embedded PWM controller inside the MVEBU driver.
 
 - Debounce, open source and open drain support for the Aspeed driver.
 
 - Misc smaller fixes like spelling and syntax and whatnot.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJZCusBAAoJEEEQszewGV1zengP/i3YgmSXJdaf26t/NxG3klU3
 qx3akdQ3gEQ6BOlIY7Ew+b6qgMJynYNZa1trZgqTgLxPEKWjidyCgz+LHQ0OY+ir
 a7x6wr+gBj5WlgV+nBjVs4l6W8pVKCfnap/04OPEQDpxZOHs2LU5pqxxUZ9AxkKS
 urDFMDX55baFviQ+xAuHgamok87YoGP36A/e/fHIBepZmnochf0mCcPfIh0t8lRh
 s2x29PN5ZFRkl403RzjZfVCEMr9bMnSqmDquvPO++Kq0bL+3rOhuMErocd1Bg8ao
 LxBktkryujTaw699xK7Rq5SwcnOAPpaBY4NTmwsIJvAJuCh7qLy9JxQSBsSOT2bx
 61NWUt5T/Xsi0ECYZM4YvsNpUP6XrpSTyG3c8T3fY9vXYLNKZBv1ht6OODpLeuke
 DxULAWP+DdzUS8a3qfKQvIJzSTloU31a1MBG58DWNJ072EQfa2YNaVE75VQk/z5/
 0xZbSHdPY/0Xgx8ltpKu37bSO676JiVQZZ1HEAuti4h21+USYueYD2L8/Bx4k9e/
 4UaOcw3MaCDHP/sf5hg17kQBjhhS0lV9Zv6H9QbHZUocJTJlIU+vXtgkQlrfi3n8
 8j5m+ywVarmLtPqg1j2rqcw7LBCPe0qRXH3e5X/YmNMc3rH9bQz4cTo8ZSN9r8zS
 c17zGbbAqlGsBkpFAbQz
 =DGPb
 -----END PGP SIGNATURE-----

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

  Core changes:

   - Return NULL from gpiod_get_optional() when GPIOLIB is disabled.
     This was a much discussed change. It affects use cases where people
     write drivers that might or might not be using GPIO resources. I
     have decided that this is the lesser evil right now.

   - Make gpiod_count() behave consistently across different hardware
     descriptions.

   - Fix the syntax around open drain/open source to not infer active
     high/low semantics.

  New drivers:

   - A new single-register fixed-direction framework driver for hardware
     that have lines controlled by a single register that just work in
     one direction (out or in), including IRQ support.

   - Support the Fintek F71889A GPIO SuperIO controller.

   - Support the National NI 169445 MMIO GPIO.

   - Support for the X-Gene derivative of the DWC GPIO controller

   - Support for the Rohm BD9571MWV-M PMIC GPIO controller.

   - Refactor the Gemini GPIO driver to a generic Faraday FTGPIO driver
     and replace both the Gemini and the Moxa ART custom drivers with
     this driver.

  Driver improvements:

   - A whole slew of drivers have their spinlocks chaned to raw
     spinlocks as they provide irqchips, and thus we are progressing on
     realtime compliance.

   - Use devm_irq_alloc_descs() in a slew of drivers, getting managed
     resources.

   - Support for the embedded PWM controller inside the MVEBU driver.

   - Debounce, open source and open drain support for the Aspeed driver.

   - Misc smaller fixes like spelling and syntax and whatnot"

* tag 'gpio-v4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (77 commits)
  gpio: f7188x: Add a missing break
  gpio: omap: return error if requested debounce time is not possible
  gpio: Add ROHM BD9571MWV-M PMIC GPIO driver
  gpio: gpio-wcove: fix GPIO IRQ status mask
  gpio: DT bindings, move tca9554 from pcf857x to pca953x
  gpio: move tca9554 from pcf857x to pca953x
  gpio: arizona: Correct check whether the pin is an input
  gpio: Add XRA1403 DTS binding documentation
  dt-bindings: add exar to vendor prefixes list
  gpio: gpio-wcove: fix irq pending status bit width
  gpio: dwapb: use dwapb_read instead of readl_relaxed
  gpio: aspeed: Add open-source and open-drain support
  gpio: aspeed: Add debounce support
  gpio: aspeed: dt: Add optional clocks property
  gpio: aspeed: dt: Fix description alignment in bindings document
  gpio: mvebu: Add limited PWM support
  gpio: Use unsigned int for interrupt numbers
  gpio: f7188x: Add F71889A GPIO support.
  gpio: core: Decouple open drain/source flag with active low/high
  gpio: arizona: Correct handling for reading input GPIOs
  ...
This commit is contained in:
Linus Torvalds 2017-05-04 12:05:32 -07:00
Родитель 99a7583de5 b86c86aa98
Коммит 2bd8040174
66 изменённых файлов: 1863 добавлений и 651 удалений

Просмотреть файл

@ -1,8 +1,11 @@
Cortina Systems Gemini GPIO Controller
Faraday Technology FTGPIO010 GPIO Controller
Required properties:
- compatible : Must be "cortina,gemini-gpio"
- compatible : Should be one of
"cortina,gemini-gpio", "faraday,ftgpio010"
"moxa,moxart-gpio", "faraday,ftgpio010"
"faraday,ftgpio010"
- reg : Should contain registers location and length
- interrupts : Should contain the interrupt line for the GPIO block
- gpio-controller : marks this as a GPIO controller
@ -14,7 +17,7 @@ Required properties:
Example:
gpio@4d000000 {
compatible = "cortina,gemini-gpio";
compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
reg = <0x4d000000 0x100>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;

Просмотреть файл

@ -17,7 +17,8 @@ Required properties:
Optional properties:
- interrupt-parent : The parent interrupt controller, optional if inherited
- interrupt-parent : The parent interrupt controller, optional if inherited
- clocks : A phandle to the HPLL clock node for debounce timings
The gpio and interrupt properties are further described in their respective
bindings documentation:

Просмотреть файл

@ -38,6 +38,24 @@ Required properties:
- #gpio-cells: Should be two. The first cell is the pin number. The
second cell is reserved for flags, unused at the moment.
Optional properties:
In order to use the GPIO lines in PWM mode, some additional optional
properties are required. Only Armada 370 and XP support these properties.
- compatible: Must contain "marvell,armada-370-xp-gpio"
- reg: an additional register set is needed, for the GPIO Blink
Counter on/off registers.
- reg-names: Must contain an entry "pwm" corresponding to the
additional register range needed for PWM operation.
- #pwm-cells: Should be two. The first cell is the GPIO line number. The
second cell is the period in nanoseconds.
- clocks: Must be a phandle to the clock for the GPIO controller.
Example:
gpio0: gpio@d0018100 {
@ -51,3 +69,17 @@ Example:
#interrupt-cells = <2>;
interrupts = <16>, <17>, <18>, <19>;
};
gpio1: gpio@18140 {
compatible = "marvell,armada-370-xp-gpio";
reg = <0x18140 0x40>, <0x181c8 0x08>;
reg-names = "gpio", "pwm";
ngpios = <17>;
gpio-controller;
#gpio-cells = <2>;
#pwm-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupts = <87>, <88>, <89>;
clocks = <&coreclk 0>;
};

Просмотреть файл

@ -26,6 +26,7 @@ Required properties:
ti,tca6416
ti,tca6424
ti,tca9539
ti,tca9554
onsemi,pca9654
exar,xra1202

Просмотреть файл

@ -25,7 +25,6 @@ Required Properties:
- "nxp,pcf8574": For the NXP PCF8574
- "nxp,pcf8574a": For the NXP PCF8574A
- "nxp,pcf8575": For the NXP PCF8575
- "ti,tca9554": For the TI TCA9554
- reg: I2C slave address.

Просмотреть файл

@ -0,0 +1,27 @@
Cavium ThunderX/OCTEON-TX GPIO controller bindings
Required Properties:
- reg: The controller bus address.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Must be 2.
- First cell is the GPIO pin number relative to the controller.
- Second cell is a standard generic flag bitfield as described in gpio.txt.
Optional Properties:
- compatible: "cavium,thunder-8890-gpio", unused as PCI driver binding is used.
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells: Must be present and have value of 2 if
"interrupt-controller" is present.
- First cell is the GPIO pin number relative to the controller.
- Second cell is triggering flags as defined in interrupts.txt.
Example:
gpio_6_0: gpio@6,0 {
compatible = "cavium,thunder-8890-gpio";
reg = <0x3000 0 0 0 0>; /* DEVFN = 0x30 (6:0) */
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};

Просмотреть файл

@ -0,0 +1,46 @@
GPIO Driver for XRA1403 16-BIT GPIO Expander With Reset Input from EXAR
The XRA1403 is an 16-bit GPIO expander with an SPI interface. Features available:
- Individually programmable inputs:
- Internal pull-up resistors
- Polarity inversion
- Individual interrupt enable
- Rising edge and/or Falling edge interrupt
- Input filter
- Individually programmable outputs
- Output Level Control
- Output Three-State Control
Properties
----------
Check documentation for SPI and GPIO controllers regarding properties needed to configure the node.
- compatible = "exar,xra1403".
- reg - SPI id of the device.
- gpio-controller - marks the node as gpio.
- #gpio-cells - should be two where the first cell is the pin number
and the second one is used for optional parameters.
Optional properties:
-------------------
- reset-gpios: in case available used to control the device reset line.
- interrupt-controller - marks the node as interrupt controller.
- #interrupt-cells - should be two and represents the number of cells
needed to encode interrupt source.
Example
--------
gpioxra0: gpio@2 {
compatible = "exar,xra1403";
reg = <2>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
spi-max-frequency = <1000000>;
};

Просмотреть файл

@ -1,19 +0,0 @@
MOXA ART GPIO Controller
Required properties:
- #gpio-cells : Should be 2, The first cell is the pin number,
the second cell is used to specify polarity:
0 = active high
1 = active low
- compatible : Must be "moxa,moxart-gpio"
- reg : Should contain registers location and length
Example:
gpio: gpio@98700000 {
gpio-controller;
#gpio-cells = <2>;
compatible = "moxa,moxart-gpio";
reg = <0x98700000 0xC>;
};

Просмотреть файл

@ -0,0 +1,38 @@
Bindings for the National Instruments 169445 GPIO NAND controller
The 169445 GPIO NAND controller has two memory mapped GPIO registers, one
for input (the ready signal) and one for output (control signals). It is
intended to be used with the GPIO NAND driver.
Required properties:
- compatible: should be "ni,169445-nand-gpio"
- reg-names: must contain
"dat" - data register
- reg: address + size pairs describing the GPIO register sets;
order must correspond with the order of entries in reg-names
- #gpio-cells: must be set to 2. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- gpio-controller: Marks the device node as a gpio controller.
Optional properties:
- no-output: disables driving output on the pins
Examples:
gpio1: nand-gpio-out@1f300010 {
compatible = "ni,169445-nand-gpio";
reg = <0x1f300010 0x4>;
reg-names = "dat";
gpio-controller;
#gpio-cells = <2>;
};
gpio2: nand-gpio-in@1f300014 {
compatible = "ni,169445-nand-gpio";
reg = <0x1f300014 0x4>;
reg-names = "dat";
gpio-controller;
#gpio-cells = <2>;
no-output;
};

Просмотреть файл

@ -103,6 +103,7 @@ ettus NI Ettus Research
eukrea Eukréa Electromatique
everest Everest Semiconductor Co. Ltd.
everspin Everspin Technologies, Inc.
exar Exar Corporation
excito Excito
ezchip EZchip Semiconductor
faraday Faraday Technology Corporation

Просмотреть файл

@ -70,6 +70,12 @@ instead of -ENOENT if no GPIO has been assigned to the requested function:
unsigned int index,
enum gpiod_flags flags)
Note that gpio_get*_optional() functions (and their managed variants), unlike
the rest of gpiolib API, also return NULL when gpiolib support is disabled.
This is helpful to driver authors, since they do not need to special case
-ENOSYS return codes. System integrators should however be careful to enable
gpiolib on systems that need it.
For a function using multiple GPIOs all of those can be obtained with one call:
struct gpio_descs *gpiod_get_array(struct device *dev,

Просмотреть файл

@ -10315,6 +10315,8 @@ F: include/linux/pwm.h
F: drivers/pwm/
F: drivers/video/backlight/pwm_bl.c
F: include/linux/pwm_backlight.h
F: drivers/gpio/gpio-mvebu.c
F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
PXA2xx/PXA3xx SUPPORT
M: Daniel Mack <daniel@zonque.org>

Просмотреть файл

@ -204,14 +204,15 @@ config GPIO_GE_FPGA
and write pin state) for GPIO implemented in a number of GE single
board computers.
config GPIO_GEMINI
bool "Gemini GPIO"
depends on ARCH_GEMINI
config GPIO_FTGPIO010
bool "Faraday FTGPIO010 GPIO"
depends on OF_GPIO
select GPIO_GENERIC
select GPIOLIB_IRQCHIP
default (ARCH_GEMINI || ARCH_MOXART)
help
Support for common GPIOs found in Cortina systems Gemini platforms.
Support for common GPIOs from the Faraday FTGPIO010 IP core, found in
Cortina systems Gemini platforms, Moxa ART and others.
config GPIO_GENERIC_PLATFORM
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
@ -308,14 +309,6 @@ config GPIO_MOCKUP
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it.
config GPIO_MOXART
bool "MOXART GPIO support"
depends on ARCH_MOXART || COMPILE_TEST
select GPIO_GENERIC
help
Select this option to enable GPIO driver for
MOXA ART SoC devices.
config GPIO_MPC5200
def_bool y
depends on PPC_MPC52xx
@ -387,6 +380,12 @@ config GPIO_RCAR
help
Say yes here to support GPIO on Renesas R-Car SoCs.
config GPIO_REG
bool
help
A 32-bit single register GPIO fixed in/out implementation. This
can be used to represent any register as a set of GPIO signals.
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
@ -505,7 +504,7 @@ config GPIO_XILINX
config GPIO_XLP
tristate "Netlogic XLP GPIO support"
depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST)
depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || ARCH_THUNDER2 || COMPILE_TEST)
select GPIOLIB_IRQCHIP
help
This driver provides support for GPIO interface on Netlogic XLP MIPS64
@ -557,7 +556,7 @@ menu "Port-mapped I/O GPIO drivers"
config GPIO_104_DIO_48E
tristate "ACCES 104-DIO-48E GPIO support"
depends on ISA_BUS_API
depends on PC104 && ISA_BUS_API
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
@ -567,7 +566,7 @@ config GPIO_104_DIO_48E
config GPIO_104_IDIO_16
tristate "ACCES 104-IDIO-16 GPIO support"
depends on ISA_BUS_API
depends on PC104 && ISA_BUS_API
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
@ -578,7 +577,7 @@ config GPIO_104_IDIO_16
config GPIO_104_IDI_48
tristate "ACCES 104-IDI-48 GPIO support"
depends on ISA_BUS_API
depends on PC104 && ISA_BUS_API
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
@ -598,7 +597,7 @@ config GPIO_F7188X
config GPIO_GPIO_MM
tristate "Diamond Systems GPIO-MM GPIO support"
depends on ISA_BUS_API
depends on PC104 && ISA_BUS_API
help
Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
@ -753,7 +752,7 @@ config GPIO_PCA953X
4 bits: pca9536, pca9537
8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554,
pca9556, pca9557, pca9574, tca6408, xra1202
pca9556, pca9557, pca9574, tca6408, tca9554, xra1202
16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575,
tca6416
@ -845,6 +844,17 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
config GPIO_BD9571MWV
tristate "ROHM BD9571 GPIO support"
depends on MFD_BD9571MWV
help
Support for GPIOs on ROHM BD9571 PMIC. There are two GPIOs
available on the ROHM PMIC in total, both of which can also
generate interrupts.
This driver can also be built as a module. If so, the module
will be called gpio-bd9571mwv.
config GPIO_CRYSTAL_COVE
tristate "GPIO support for Crystal Cove PMIC"
depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC

Просмотреть файл

@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
@ -48,8 +49,8 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GEMINI) += gpio-gemini.o
obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
@ -80,7 +81,6 @@ obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o

Просмотреть файл

@ -136,7 +136,7 @@ EXPORT_SYMBOL(devm_gpiod_get_index);
* GPIO descriptors returned from this function are automatically disposed on
* driver detach.
*
* On successfull request the GPIO pin is configured in accordance with
* On successful request the GPIO pin is configured in accordance with
* provided @flags.
*/
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,

Просмотреть файл

@ -55,7 +55,7 @@ struct dio48e_gpio {
unsigned char io_state[6];
unsigned char out_state[6];
unsigned char control[2];
spinlock_t lock;
raw_spinlock_t lock;
unsigned base;
unsigned char irq_mask;
};
@ -78,7 +78,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
unsigned long flags;
unsigned control;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
/* Check if configuring Port C */
if (io_port == 2 || io_port == 5) {
@ -103,7 +103,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
control &= ~BIT(7);
outb(control, control_addr);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
return 0;
}
@ -120,7 +120,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
unsigned long flags;
unsigned control;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
/* Check if configuring Port C */
if (io_port == 2 || io_port == 5) {
@ -153,7 +153,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
control &= ~BIT(7);
outb(control, control_addr);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
return 0;
}
@ -167,17 +167,17 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
unsigned long flags;
unsigned port_state;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
/* ensure that GPIO is set for input */
if (!(dio48egpio->io_state[port] & mask)) {
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
return -EINVAL;
}
port_state = inb(dio48egpio->base + in_port);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
return !!(port_state & mask);
}
@ -190,7 +190,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
const unsigned out_port = (port > 2) ? port + 1 : port;
unsigned long flags;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
if (value)
dio48egpio->out_state[port] |= mask;
@ -199,7 +199,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
static void dio48e_gpio_set_multiple(struct gpio_chip *chip,
@ -225,14 +225,14 @@ static void dio48e_gpio_set_multiple(struct gpio_chip *chip,
out_port = (port > 2) ? port + 1 : port;
bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
/* update output state data and set device gpio register */
dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
dio48egpio->out_state[port] |= bitmask;
outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
/* prepare for next gpio register set */
mask[BIT_WORD(i)] >>= gpio_reg_size;
@ -255,7 +255,7 @@ static void dio48e_irq_mask(struct irq_data *data)
if (offset != 19 && offset != 43)
return;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
if (offset == 19)
dio48egpio->irq_mask &= ~BIT(0);
@ -266,7 +266,7 @@ static void dio48e_irq_mask(struct irq_data *data)
/* disable interrupts */
inb(dio48egpio->base + 0xB);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
static void dio48e_irq_unmask(struct irq_data *data)
@ -280,7 +280,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
if (offset != 19 && offset != 43)
return;
spin_lock_irqsave(&dio48egpio->lock, flags);
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
if (!dio48egpio->irq_mask) {
/* enable interrupts */
@ -293,7 +293,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
else
dio48egpio->irq_mask |= BIT(1);
spin_unlock_irqrestore(&dio48egpio->lock, flags);
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type)
@ -329,11 +329,11 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
generic_handle_irq(irq_find_mapping(chip->irqdomain,
19 + gpio*24));
spin_lock(&dio48egpio->lock);
raw_spin_lock(&dio48egpio->lock);
outb(0x00, dio48egpio->base + 0xF);
spin_unlock(&dio48egpio->lock);
raw_spin_unlock(&dio48egpio->lock);
return IRQ_HANDLED;
}
@ -388,7 +388,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
dio48egpio->base = base[id];
spin_lock_init(&dio48egpio->lock);
raw_spin_lock_init(&dio48egpio->lock);
err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
if (err) {

Просмотреть файл

@ -51,7 +51,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
*/
struct idi_48_gpio {
struct gpio_chip chip;
spinlock_t lock;
raw_spinlock_t lock;
spinlock_t ack_lock;
unsigned char irq_mask[6];
unsigned base;
@ -112,11 +112,12 @@ static void idi_48_irq_mask(struct irq_data *data)
if (!idi48gpio->irq_mask[boundary]) {
idi48gpio->cos_enb &= ~BIT(boundary);
spin_lock_irqsave(&idi48gpio->lock, flags);
raw_spin_lock_irqsave(&idi48gpio->lock, flags);
outb(idi48gpio->cos_enb, idi48gpio->base + 7);
spin_unlock_irqrestore(&idi48gpio->lock, flags);
raw_spin_unlock_irqrestore(&idi48gpio->lock,
flags);
}
return;
@ -145,11 +146,12 @@ static void idi_48_irq_unmask(struct irq_data *data)
if (!prev_irq_mask) {
idi48gpio->cos_enb |= BIT(boundary);
spin_lock_irqsave(&idi48gpio->lock, flags);
raw_spin_lock_irqsave(&idi48gpio->lock, flags);
outb(idi48gpio->cos_enb, idi48gpio->base + 7);
spin_unlock_irqrestore(&idi48gpio->lock, flags);
raw_spin_unlock_irqrestore(&idi48gpio->lock,
flags);
}
return;
@ -186,11 +188,11 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
spin_lock(&idi48gpio->ack_lock);
spin_lock(&idi48gpio->lock);
raw_spin_lock(&idi48gpio->lock);
cos_status = inb(idi48gpio->base + 7);
spin_unlock(&idi48gpio->lock);
raw_spin_unlock(&idi48gpio->lock);
/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
if (cos_status & BIT(6)) {
@ -256,7 +258,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
idi48gpio->chip.get = idi_48_gpio_get;
idi48gpio->base = base[id];
spin_lock_init(&idi48gpio->lock);
raw_spin_lock_init(&idi48gpio->lock);
spin_lock_init(&idi48gpio->ack_lock);
err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);

Просмотреть файл

@ -50,7 +50,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
*/
struct idio_16_gpio {
struct gpio_chip chip;
spinlock_t lock;
raw_spinlock_t lock;
unsigned long irq_mask;
unsigned base;
unsigned out_state;
@ -99,7 +99,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
if (offset > 15)
return;
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
if (value)
idio16gpio->out_state |= mask;
@ -111,7 +111,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
else
outb(idio16gpio->out_state, idio16gpio->base);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
@ -120,7 +120,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
unsigned long flags;
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
idio16gpio->out_state &= ~*mask;
idio16gpio->out_state |= *mask & *bits;
@ -130,7 +130,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
if ((*mask >> 8) & 0xFF)
outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
static void idio_16_irq_ack(struct irq_data *data)
@ -147,11 +147,11 @@ static void idio_16_irq_mask(struct irq_data *data)
idio16gpio->irq_mask &= ~mask;
if (!idio16gpio->irq_mask) {
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
outb(0, idio16gpio->base + 2);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
}
@ -166,11 +166,11 @@ static void idio_16_irq_unmask(struct irq_data *data)
idio16gpio->irq_mask |= mask;
if (!prev_irq_mask) {
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
inb(idio16gpio->base + 2);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
}
@ -201,11 +201,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
spin_lock(&idio16gpio->lock);
raw_spin_lock(&idio16gpio->lock);
outb(0, idio16gpio->base + 1);
spin_unlock(&idio16gpio->lock);
raw_spin_unlock(&idio16gpio->lock);
return IRQ_HANDLED;
}
@ -249,7 +249,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
idio16gpio->base = base[id];
idio16gpio->out_state = 0xFFFF;
spin_lock_init(&idio16gpio->lock);
raw_spin_lock_init(&idio16gpio->lock);
err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
if (err) {

Просмотреть файл

@ -38,7 +38,7 @@
*/
struct altera_gpio_chip {
struct of_mm_gpio_chip mmchip;
spinlock_t gpio_lock;
raw_spinlock_t gpio_lock;
int interrupt_trigger;
int mapped_irq;
};
@ -53,12 +53,12 @@ static void altera_gpio_irq_unmask(struct irq_data *d)
altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
/* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
intmask |= BIT(irqd_to_hwirq(d));
writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
}
static void altera_gpio_irq_mask(struct irq_data *d)
@ -71,12 +71,12 @@ static void altera_gpio_irq_mask(struct irq_data *d)
altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
/* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
intmask &= ~BIT(irqd_to_hwirq(d));
writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
}
/**
@ -140,14 +140,14 @@ static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
mm_gc = to_of_mm_gpio_chip(gc);
chip = gpiochip_get_data(gc);
spin_lock_irqsave(&chip->gpio_lock, flags);
raw_spin_lock_irqsave(&chip->gpio_lock, flags);
data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
if (value)
data_reg |= BIT(offset);
else
data_reg &= ~BIT(offset);
writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
}
static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
@ -160,12 +160,12 @@ static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
mm_gc = to_of_mm_gpio_chip(gc);
chip = gpiochip_get_data(gc);
spin_lock_irqsave(&chip->gpio_lock, flags);
raw_spin_lock_irqsave(&chip->gpio_lock, flags);
/* Set pin as input, assumes software controlled IP */
gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
gpio_ddr &= ~BIT(offset);
writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
return 0;
}
@ -181,7 +181,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
mm_gc = to_of_mm_gpio_chip(gc);
chip = gpiochip_get_data(gc);
spin_lock_irqsave(&chip->gpio_lock, flags);
raw_spin_lock_irqsave(&chip->gpio_lock, flags);
/* Sets the GPIO value */
data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
if (value)
@ -194,7 +194,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
gpio_ddr |= BIT(offset);
writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
return 0;
}
@ -262,7 +262,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
if (!altera_gc)
return -ENOMEM;
spin_lock_init(&altera_gc->gpio_lock);
raw_spin_lock_init(&altera_gc->gpio_lock);
if (of_property_read_u32(node, "altr,ngpio", &reg))
/* By default assume maximum ngpio */

Просмотреть файл

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/mfd/arizona/core.h>
@ -41,13 +42,38 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
struct arizona *arizona = arizona_gpio->arizona;
unsigned int val;
unsigned int reg, val;
int ret;
ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
reg = ARIZONA_GPIO1_CTRL + offset;
ret = regmap_read(arizona->regmap, reg, &val);
if (ret < 0)
return ret;
/* Resume to read actual registers for input pins */
if (val & ARIZONA_GPN_DIR) {
ret = pm_runtime_get_sync(chip->parent);
if (ret < 0) {
dev_err(chip->parent, "Failed to resume: %d\n", ret);
return ret;
}
/* Register is cached, drop it to ensure a physical read */
ret = regcache_drop_region(arizona->regmap, reg, reg);
if (ret < 0) {
dev_err(chip->parent, "Failed to drop cache: %d\n",
ret);
return ret;
}
ret = regmap_read(arizona->regmap, reg, &val);
if (ret < 0)
return ret;
pm_runtime_mark_last_busy(chip->parent);
pm_runtime_put_autosuspend(chip->parent);
}
if (val & ARIZONA_GPN_LVL)
return 1;
else

Просмотреть файл

@ -9,14 +9,18 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/div64.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/string.h>
struct aspeed_bank_props {
unsigned int bank;
@ -29,59 +33,85 @@ struct aspeed_gpio_config {
const struct aspeed_bank_props *props;
};
/*
* @offset_timer: Maps an offset to an @timer_users index, or zero if disabled
* @timer_users: Tracks the number of users for each timer
*
* The @timer_users has four elements but the first element is unused. This is
* to simplify accounting and indexing, as a zero value in @offset_timer
* represents disabled debouncing for the GPIO. Any other value for an element
* of @offset_timer is used as an index into @timer_users. This behaviour of
* the zero value aligns with the behaviour of zero built from the timer
* configuration registers (i.e. debouncing is disabled).
*/
struct aspeed_gpio {
struct gpio_chip chip;
spinlock_t lock;
void __iomem *base;
int irq;
const struct aspeed_gpio_config *config;
u8 *offset_timer;
unsigned int timer_users[4];
struct clk *clk;
};
struct aspeed_gpio_bank {
uint16_t val_regs;
uint16_t irq_regs;
uint16_t debounce_regs;
const char names[4][3];
};
static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
{
.val_regs = 0x0000,
.irq_regs = 0x0008,
.debounce_regs = 0x0040,
.names = { "A", "B", "C", "D" },
},
{
.val_regs = 0x0020,
.irq_regs = 0x0028,
.debounce_regs = 0x0048,
.names = { "E", "F", "G", "H" },
},
{
.val_regs = 0x0070,
.irq_regs = 0x0098,
.debounce_regs = 0x00b0,
.names = { "I", "J", "K", "L" },
},
{
.val_regs = 0x0078,
.irq_regs = 0x00e8,
.debounce_regs = 0x0100,
.names = { "M", "N", "O", "P" },
},
{
.val_regs = 0x0080,
.irq_regs = 0x0118,
.debounce_regs = 0x0130,
.names = { "Q", "R", "S", "T" },
},
{
.val_regs = 0x0088,
.irq_regs = 0x0148,
.debounce_regs = 0x0160,
.names = { "U", "V", "W", "X" },
},
{
.val_regs = 0x01E0,
.irq_regs = 0x0178,
.debounce_regs = 0x0190,
.names = { "Y", "Z", "AA", "AB" },
},
{
.val_regs = 0x01E8,
.irq_regs = 0x01A8,
.debounce_regs = 0x01c0,
.names = { "AC", "", "", "" },
},
};
@ -99,6 +129,13 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
#define GPIO_IRQ_TYPE2 0x0c
#define GPIO_IRQ_STATUS 0x10
#define GPIO_DEBOUNCE_SEL1 0x00
#define GPIO_DEBOUNCE_SEL2 0x04
#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))
#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)
#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0)
static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
{
unsigned int bank = GPIO_BANK(offset);
@ -144,6 +181,7 @@ static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
}
#define have_irq(g, o) have_input((g), (o))
#define have_debounce(g, o) have_input((g), (o))
static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
{
@ -506,6 +544,231 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
pinctrl_free_gpio(chip->base + offset);
}
static inline void __iomem *bank_debounce_reg(struct aspeed_gpio *gpio,
const struct aspeed_gpio_bank *bank,
unsigned int reg)
{
return gpio->base + bank->debounce_regs + reg;
}
static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,
u32 *cycles)
{
u64 rate;
u64 n;
u32 r;
rate = clk_get_rate(gpio->clk);
if (!rate)
return -ENOTSUPP;
n = rate * usecs;
r = do_div(n, 1000000);
if (n >= U32_MAX)
return -ERANGE;
/* At least as long as the requested time */
*cycles = n + (!!r);
return 0;
}
/* Call under gpio->lock */
static int register_allocated_timer(struct aspeed_gpio *gpio,
unsigned int offset, unsigned int timer)
{
if (WARN(gpio->offset_timer[offset] != 0,
"Offset %d already allocated timer %d\n",
offset, gpio->offset_timer[offset]))
return -EINVAL;
if (WARN(gpio->timer_users[timer] == UINT_MAX,
"Timer user count would overflow\n"))
return -EPERM;
gpio->offset_timer[offset] = timer;
gpio->timer_users[timer]++;
return 0;
}
/* Call under gpio->lock */
static int unregister_allocated_timer(struct aspeed_gpio *gpio,
unsigned int offset)
{
if (WARN(gpio->offset_timer[offset] == 0,
"No timer allocated to offset %d\n", offset))
return -EINVAL;
if (WARN(gpio->timer_users[gpio->offset_timer[offset]] == 0,
"No users recorded for timer %d\n",
gpio->offset_timer[offset]))
return -EINVAL;
gpio->timer_users[gpio->offset_timer[offset]]--;
gpio->offset_timer[offset] = 0;
return 0;
}
/* Call under gpio->lock */
static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
unsigned int offset)
{
return gpio->offset_timer[offset] > 0;
}
/* Call under gpio->lock */
static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
unsigned int timer)
{
const struct aspeed_gpio_bank *bank = to_bank(offset);
const u32 mask = GPIO_BIT(offset);
void __iomem *addr;
u32 val;
addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL1);
val = ioread32(addr);
iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr);
addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL2);
val = ioread32(addr);
iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);
}
static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
unsigned long usecs)
{
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
u32 requested_cycles;
unsigned long flags;
int rc;
int i;
rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
if (rc < 0) {
dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
usecs, clk_get_rate(gpio->clk), rc);
return rc;
}
spin_lock_irqsave(&gpio->lock, flags);
if (timer_allocation_registered(gpio, offset)) {
rc = unregister_allocated_timer(gpio, offset);
if (rc < 0)
goto out;
}
/* Try to find a timer already configured for the debounce period */
for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) {
u32 cycles;
cycles = ioread32(gpio->base + debounce_timers[i]);
if (requested_cycles == cycles)
break;
}
if (i == ARRAY_SIZE(debounce_timers)) {
int j;
/*
* As there are no timers configured for the requested debounce
* period, find an unused timer instead
*/
for (j = 1; j < ARRAY_SIZE(gpio->timer_users); j++) {
if (gpio->timer_users[j] == 0)
break;
}
if (j == ARRAY_SIZE(gpio->timer_users)) {
dev_warn(chip->parent,
"Debounce timers exhausted, cannot debounce for period %luus\n",
usecs);
rc = -EPERM;
/*
* We already adjusted the accounting to remove @offset
* as a user of its previous timer, so also configure
* the hardware so @offset has timers disabled for
* consistency.
*/
configure_timer(gpio, offset, 0);
goto out;
}
i = j;
iowrite32(requested_cycles, gpio->base + debounce_timers[i]);
}
if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
rc = -EINVAL;
goto out;
}
register_allocated_timer(gpio, offset, i);
configure_timer(gpio, offset, i);
out:
spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
{
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
unsigned long flags;
int rc;
spin_lock_irqsave(&gpio->lock, flags);
rc = unregister_allocated_timer(gpio, offset);
if (!rc)
configure_timer(gpio, offset, 0);
spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
static int set_debounce(struct gpio_chip *chip, unsigned int offset,
unsigned long usecs)
{
struct aspeed_gpio *gpio = gpiochip_get_data(chip);
if (!have_debounce(gpio, offset))
return -ENOTSUPP;
if (usecs)
return enable_debounce(chip, offset, usecs);
return disable_debounce(chip, offset);
}
static int aspeed_gpio_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 set_debounce(chip, offset, arg);
else if (param == PIN_CONFIG_BIAS_DISABLE ||
param == PIN_CONFIG_BIAS_PULL_DOWN ||
param == PIN_CONFIG_DRIVE_STRENGTH)
return pinctrl_gpio_set_config(offset, config);
else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
/* Return -ENOTSUPP to trigger emulation, as per datasheet */
return -ENOTSUPP;
return -ENOTSUPP;
}
/*
* Any banks not specified in a struct aspeed_bank_props array are assumed to
* have the properties:
@ -565,8 +828,16 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
if (!gpio_id)
return -EINVAL;
gpio->clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(gpio->clk)) {
dev_warn(&pdev->dev,
"No HPLL clock phandle provided, debouncing disabled\n");
gpio->clk = NULL;
}
gpio->config = gpio_id->data;
gpio->chip.parent = &pdev->dev;
gpio->chip.ngpio = gpio->config->nr_gpios;
gpio->chip.parent = &pdev->dev;
gpio->chip.direction_input = aspeed_gpio_dir_in;
@ -576,6 +847,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.free = aspeed_gpio_free;
gpio->chip.get = aspeed_gpio_get;
gpio->chip.set = aspeed_gpio_set;
gpio->chip.set_config = aspeed_gpio_set_config;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
gpio->chip.irq_need_valid_mask = true;
@ -584,6 +856,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
if (rc < 0)
return rc;
gpio->offset_timer =
devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
return aspeed_gpio_setup_irqs(gpio, pdev);
}

Просмотреть файл

@ -32,7 +32,7 @@
struct ath79_gpio_ctrl {
struct gpio_chip gc;
void __iomem *base;
spinlock_t lock;
raw_spinlock_t lock;
unsigned long both_edges;
};
@ -74,9 +74,9 @@ static void ath79_gpio_irq_unmask(struct irq_data *data)
u32 mask = BIT(irqd_to_hwirq(data));
unsigned long flags;
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void ath79_gpio_irq_mask(struct irq_data *data)
@ -85,9 +85,9 @@ static void ath79_gpio_irq_mask(struct irq_data *data)
u32 mask = BIT(irqd_to_hwirq(data));
unsigned long flags;
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void ath79_gpio_irq_enable(struct irq_data *data)
@ -96,10 +96,10 @@ static void ath79_gpio_irq_enable(struct irq_data *data)
u32 mask = BIT(irqd_to_hwirq(data));
unsigned long flags;
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void ath79_gpio_irq_disable(struct irq_data *data)
@ -108,10 +108,10 @@ static void ath79_gpio_irq_disable(struct irq_data *data)
u32 mask = BIT(irqd_to_hwirq(data));
unsigned long flags;
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static int ath79_gpio_irq_set_type(struct irq_data *data,
@ -140,7 +140,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
return -EINVAL;
}
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
if (flow_type == IRQ_TYPE_EDGE_BOTH) {
ctrl->both_edges |= mask;
@ -165,7 +165,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
ath79_gpio_update_bits(
ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@ -191,7 +191,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
chained_irq_enter(irqchip, desc);
spin_lock_irqsave(&ctrl->lock, flags);
raw_spin_lock_irqsave(&ctrl->lock, flags);
pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
@ -203,7 +203,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
both_edges, ~state);
}
spin_unlock_irqrestore(&ctrl->lock, flags);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
if (pending) {
for_each_set_bit(irq, &pending, gc->ngpio)
@ -262,7 +262,7 @@ static int ath79_gpio_probe(struct platform_device *pdev)
if (!ctrl->base)
return -ENOMEM;
spin_lock_init(&ctrl->lock);
raw_spin_lock_init(&ctrl->lock);
err = bgpio_init(&ctrl->gc, &pdev->dev, 4,
ctrl->base + AR71XX_GPIO_REG_IN,
ctrl->base + AR71XX_GPIO_REG_SET,

Просмотреть файл

@ -67,7 +67,7 @@
struct bcm_kona_gpio {
void __iomem *reg_base;
int num_bank;
spinlock_t lock;
raw_spinlock_t lock;
struct gpio_chip gpio_chip;
struct irq_domain *irq_domain;
struct bcm_kona_gpio_bank *banks;
@ -95,13 +95,13 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
val |= BIT(gpio);
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
@ -111,13 +111,13 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
unsigned long flags;
int bank_id = GPIO_BANK(gpio);
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
val &= ~BIT(gpio);
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
@ -141,7 +141,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
/* this function only applies to output pin */
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
@ -154,7 +154,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
writel(val, reg_base + reg_offset);
out:
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
@ -168,7 +168,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
reg_offset = GPIO_IN_STATUS(bank_id);
@ -178,7 +178,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
/* read the GPIO bank status */
val = readl(reg_base + reg_offset);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
/* return the specified bit status */
return !!(val & BIT(bit));
@ -208,14 +208,14 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
writel(val, reg_base + GPIO_CONTROL(gpio));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
val |= BIT(bit);
writel(val, reg_base + reg_offset);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@ -288,7 +288,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
}
/* spin lock for read-modify-write of the GPIO register */
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_DBR_MASK;
@ -303,7 +303,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
writel(val, reg_base + GPIO_CONTROL(gpio));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@ -347,13 +347,13 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_STATUS(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_STATUS(bank_id));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_mask(struct irq_data *d)
@ -368,13 +368,13 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_MASK(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MASK(bank_id));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
@ -389,13 +389,13 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
kona_gpio = irq_data_get_irq_chip_data(d);
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
val |= BIT(bit);
writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@ -431,14 +431,14 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
spin_lock_irqsave(&kona_gpio->lock, flags);
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_ITR_MASK;
val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
writel(val, reg_base + GPIO_CONTROL(gpio));
spin_unlock_irqrestore(&kona_gpio->lock, flags);
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
return 0;
}
@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
bank);
}
spin_lock_init(&kona_gpio->lock);
raw_spin_lock_init(&kona_gpio->lock);
return 0;

Просмотреть файл

@ -0,0 +1,144 @@
/*
* ROHM BD9571MWV-M GPIO driver
*
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether expressed or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License version 2 for more details.
*
* Based on the TPS65086 driver
*
* NOTE: Interrupts are not supported yet.
*/
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/bd9571mwv.h>
struct bd9571mwv_gpio {
struct gpio_chip chip;
struct bd9571mwv *bd;
};
static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
int ret, val;
ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val);
if (ret < 0)
return ret;
return val & BIT(offset);
}
static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
BIT(offset), 0);
return 0;
}
static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
/* Set the initial value */
regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
BIT(offset), value ? BIT(offset) : 0);
regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
BIT(offset), BIT(offset));
return 0;
}
static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
int ret, val;
ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val);
if (ret < 0)
return ret;
return val & BIT(offset);
}
static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
BIT(offset), value ? BIT(offset) : 0);
}
static const struct gpio_chip template_chip = {
.label = "bd9571mwv-gpio",
.owner = THIS_MODULE,
.get_direction = bd9571mwv_gpio_get_direction,
.direction_input = bd9571mwv_gpio_direction_input,
.direction_output = bd9571mwv_gpio_direction_output,
.get = bd9571mwv_gpio_get,
.set = bd9571mwv_gpio_set,
.base = -1,
.ngpio = 2,
.can_sleep = true,
};
static int bd9571mwv_gpio_probe(struct platform_device *pdev)
{
struct bd9571mwv_gpio *gpio;
int ret;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
platform_set_drvdata(pdev, gpio);
gpio->bd = dev_get_drvdata(pdev->dev.parent);
gpio->chip = template_chip;
gpio->chip.parent = gpio->bd->dev;
ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
return ret;
}
return 0;
}
static const struct platform_device_id bd9571mwv_gpio_id_table[] = {
{ "bd9571mwv-gpio", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table);
static struct platform_driver bd9571mwv_gpio_driver = {
.driver = {
.name = "bd9571mwv-gpio",
},
.probe = bd9571mwv_gpio_probe,
.id_table = bd9571mwv_gpio_id_table,
};
module_platform_driver(bd9571mwv_gpio_driver);
MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
MODULE_DESCRIPTION("BD9571MWV GPIO driver");
MODULE_LICENSE("GPL v2");

Просмотреть файл

@ -483,7 +483,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
clk_prepare_enable(clk);
if (!pdata->gpio_unbanked) {
irq = irq_alloc_descs(-1, 0, ngpio, 0);
irq = devm_irq_alloc_descs(dev, -1, 0, ngpio, 0);
if (irq < 0) {
dev_err(dev, "Couldn't allocate IRQ numbers\n");
return irq;

Просмотреть файл

@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/property.h>
@ -55,6 +56,14 @@
#define GPIO_SWPORT_DR_SIZE (GPIO_SWPORTB_DR - GPIO_SWPORTA_DR)
#define GPIO_SWPORT_DDR_SIZE (GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR)
#define GPIO_REG_OFFSET_V2 1
#define GPIO_INTMASK_V2 0x44
#define GPIO_INTTYPE_LEVEL_V2 0x34
#define GPIO_INT_POLARITY_V2 0x38
#define GPIO_INTSTATUS_V2 0x3c
#define GPIO_PORTA_EOI_V2 0x40
struct dwapb_gpio;
#ifdef CONFIG_PM_SLEEP
@ -87,14 +96,41 @@ struct dwapb_gpio {
struct dwapb_gpio_port *ports;
unsigned int nr_ports;
struct irq_domain *domain;
unsigned int flags;
};
static inline u32 gpio_reg_v2_convert(unsigned int offset)
{
switch (offset) {
case GPIO_INTMASK:
return GPIO_INTMASK_V2;
case GPIO_INTTYPE_LEVEL:
return GPIO_INTTYPE_LEVEL_V2;
case GPIO_INT_POLARITY:
return GPIO_INT_POLARITY_V2;
case GPIO_INTSTATUS:
return GPIO_INTSTATUS_V2;
case GPIO_PORTA_EOI:
return GPIO_PORTA_EOI_V2;
}
return offset;
}
static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset)
{
if (gpio->flags & GPIO_REG_OFFSET_V2)
return gpio_reg_v2_convert(offset);
return offset;
}
static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset)
{
struct gpio_chip *gc = &gpio->ports[0].gc;
void __iomem *reg_base = gpio->regs;
return gc->read_reg(reg_base + offset);
return gc->read_reg(reg_base + gpio_reg_convert(gpio, offset));
}
static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
@ -103,7 +139,7 @@ static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
struct gpio_chip *gc = &gpio->ports[0].gc;
void __iomem *reg_base = gpio->regs;
gc->write_reg(reg_base + offset, val);
gc->write_reg(reg_base + gpio_reg_convert(gpio, offset), val);
}
static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
@ -128,7 +164,7 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
{
u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS);
u32 irq_status = dwapb_read(gpio, GPIO_INTSTATUS);
u32 ret = irq_status;
while (irq_status) {
@ -348,8 +384,8 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
ct->chip.irq_disable = dwapb_irq_disable;
ct->chip.irq_request_resources = dwapb_irq_reqres;
ct->chip.irq_release_resources = dwapb_irq_relres;
ct->regs.ack = GPIO_PORTA_EOI;
ct->regs.mask = GPIO_INTMASK;
ct->regs.ack = gpio_reg_convert(gpio, GPIO_PORTA_EOI);
ct->regs.mask = gpio_reg_convert(gpio, GPIO_INTMASK);
ct->type = IRQ_TYPE_LEVEL_MASK;
}
@ -532,6 +568,21 @@ dwapb_gpio_get_pdata(struct device *dev)
return pdata;
}
static const struct of_device_id dwapb_of_match[] = {
{ .compatible = "snps,dw-apb-gpio", .data = (void *)0},
{ .compatible = "apm,xgene-gpio-v2", .data = (void *)GPIO_REG_OFFSET_V2},
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dwapb_of_match);
static const struct acpi_device_id dwapb_acpi_match[] = {
{"HISI0181", 0},
{"APMC0D07", 0},
{"APMC0D81", GPIO_REG_OFFSET_V2},
{ }
};
MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
static int dwapb_gpio_probe(struct platform_device *pdev)
{
unsigned int i;
@ -567,6 +618,25 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
gpio->flags = 0;
if (dev->of_node) {
const struct of_device_id *of_devid;
of_devid = of_match_device(dwapb_of_match, dev);
if (of_devid) {
if (of_devid->data)
gpio->flags = (uintptr_t)of_devid->data;
}
} else if (has_acpi_companion(dev)) {
const struct acpi_device_id *acpi_id;
acpi_id = acpi_match_device(dwapb_acpi_match, dev);
if (acpi_id) {
if (acpi_id->driver_data)
gpio->flags = acpi_id->driver_data;
}
}
for (i = 0; i < gpio->nr_ports; i++) {
err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
if (err)
@ -593,19 +663,6 @@ static int dwapb_gpio_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id dwapb_of_match[] = {
{ .compatible = "snps,dw-apb-gpio" },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dwapb_of_match);
static const struct acpi_device_id dwapb_acpi_match[] = {
{"HISI0181", 0},
{"APMC0D07", 0},
{ }
};
MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
#ifdef CONFIG_PM_SLEEP
static int dwapb_gpio_suspend(struct device *dev)
{

Просмотреть файл

@ -54,7 +54,7 @@
struct etraxfs_gpio_info;
struct etraxfs_gpio_block {
spinlock_t lock;
raw_spinlock_t lock;
u32 mask;
u32 cfg;
u32 pins;
@ -233,10 +233,10 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
spin_lock(&block->lock);
raw_spin_lock(&block->lock);
block->mask &= ~BIT(grpirq);
writel(block->mask, block->regs + block->info->rw_intr_mask);
spin_unlock(&block->lock);
raw_spin_unlock(&block->lock);
}
static void etraxfs_gpio_irq_unmask(struct irq_data *d)
@ -246,10 +246,10 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
spin_lock(&block->lock);
raw_spin_lock(&block->lock);
block->mask |= BIT(grpirq);
writel(block->mask, block->regs + block->info->rw_intr_mask);
spin_unlock(&block->lock);
raw_spin_unlock(&block->lock);
}
static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
@ -280,11 +280,11 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
return -EINVAL;
}
spin_lock(&block->lock);
raw_spin_lock(&block->lock);
block->cfg &= ~(0x7 << (grpirq * 3));
block->cfg |= (cfg << (grpirq * 3));
writel(block->cfg, block->regs + block->info->rw_intr_cfg);
spin_unlock(&block->lock);
raw_spin_unlock(&block->lock);
return 0;
}
@ -297,7 +297,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
int ret = -EBUSY;
spin_lock(&block->lock);
raw_spin_lock(&block->lock);
if (block->group[grpirq])
goto out;
@ -316,7 +316,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
}
out:
spin_unlock(&block->lock);
raw_spin_unlock(&block->lock);
return ret;
}
@ -327,10 +327,10 @@ static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
spin_lock(&block->lock);
raw_spin_lock(&block->lock);
block->group[grpirq] = 0;
gpiochip_unlock_as_irq(&chip->gc, d->hwirq);
spin_unlock(&block->lock);
raw_spin_unlock(&block->lock);
}
static struct irq_chip etraxfs_gpio_irq_chip = {
@ -391,7 +391,7 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
if (!block)
return -ENOMEM;
spin_lock_init(&block->lock);
raw_spin_lock_init(&block->lock);
block->regs = regs;
block->info = info;

Просмотреть файл

@ -59,17 +59,6 @@ static int exar_set_direction(struct gpio_chip *chip, int direction,
return 0;
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
return exar_set_direction(chip, 0, offset);
}
static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
{
return exar_set_direction(chip, 1, offset);
}
static int exar_get(struct gpio_chip *chip, unsigned int reg)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
@ -116,6 +105,18 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
exar_update(chip, addr, value, offset % 8);
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
exar_set_value(chip, offset, value);
return exar_set_direction(chip, 0, offset);
}
static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
{
return exar_set_direction(chip, 1, offset);
}
static int gpio_exar_probe(struct platform_device *pdev)
{
struct pci_dev *pcidev = platform_get_drvdata(pdev);

Просмотреть файл

@ -37,14 +37,16 @@
#define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */
#define SIO_F71882_ID 0x0541 /* F71882 chipset ID */
#define SIO_F71889_ID 0x0909 /* F71889 chipset ID */
#define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */
#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */
enum chips { f71869, f71869a, f71882fg, f71889f, f81866 };
enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866 };
static const char * const f7188x_names[] = {
"f71869",
"f71869a",
"f71882fg",
"f71889a",
"f71889f",
"f81866",
};
@ -187,6 +189,17 @@ static struct f7188x_gpio_bank f71882_gpio_bank[] = {
F7188X_GPIO_BANK(40, 4, 0xB0),
};
static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
F7188X_GPIO_BANK(0, 7, 0xF0),
F7188X_GPIO_BANK(10, 7, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 8, 0xC0),
F7188X_GPIO_BANK(40, 8, 0xB0),
F7188X_GPIO_BANK(50, 5, 0xA0),
F7188X_GPIO_BANK(60, 8, 0x90),
F7188X_GPIO_BANK(70, 8, 0x80),
};
static struct f7188x_gpio_bank f71889_gpio_bank[] = {
F7188X_GPIO_BANK(0, 7, 0xF0),
F7188X_GPIO_BANK(10, 7, 0xE0),
@ -382,6 +395,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
data->bank = f71882_gpio_bank;
break;
case f71889a:
data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank);
data->bank = f71889a_gpio_bank;
break;
case f71889f:
data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
data->bank = f71889_gpio_bank;
@ -443,6 +460,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
case SIO_F71882_ID:
sio->type = f71882fg;
break;
case SIO_F71889A_ID:
sio->type = f71889a;
break;
case SIO_F71889_ID:
sio->type = f71889f;
break;
@ -538,6 +558,6 @@ static void __exit f7188x_gpio_exit(void)
}
module_exit(f7188x_gpio_exit);
MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866");
MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889A, F71889F and F81866");
MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -1,5 +1,5 @@
/*
* Gemini gpiochip and interrupt routines
* Faraday Technolog FTGPIO010 gpiochip and interrupt routines
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
*
* Based on arch/arm/mach-gemini/gpio.c:
@ -35,28 +35,28 @@
#define GPIO_DEBOUNCE_PRESCALE 0x44
/**
* struct gemini_gpio - Gemini GPIO state container
* struct ftgpio_gpio - Gemini GPIO state container
* @dev: containing device for this instance
* @gc: gpiochip for this instance
*/
struct gemini_gpio {
struct ftgpio_gpio {
struct device *dev;
struct gpio_chip gc;
void __iomem *base;
};
static void gemini_gpio_ack_irq(struct irq_data *d)
static void ftgpio_gpio_ack_irq(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gemini_gpio *g = gpiochip_get_data(gc);
struct ftgpio_gpio *g = gpiochip_get_data(gc);
writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR);
}
static void gemini_gpio_mask_irq(struct irq_data *d)
static void ftgpio_gpio_mask_irq(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gemini_gpio *g = gpiochip_get_data(gc);
struct ftgpio_gpio *g = gpiochip_get_data(gc);
u32 val;
val = readl(g->base + GPIO_INT_EN);
@ -64,10 +64,10 @@ static void gemini_gpio_mask_irq(struct irq_data *d)
writel(val, g->base + GPIO_INT_EN);
}
static void gemini_gpio_unmask_irq(struct irq_data *d)
static void ftgpio_gpio_unmask_irq(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gemini_gpio *g = gpiochip_get_data(gc);
struct ftgpio_gpio *g = gpiochip_get_data(gc);
u32 val;
val = readl(g->base + GPIO_INT_EN);
@ -75,10 +75,10 @@ static void gemini_gpio_unmask_irq(struct irq_data *d)
writel(val, g->base + GPIO_INT_EN);
}
static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type)
static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gemini_gpio *g = gpiochip_get_data(gc);
struct ftgpio_gpio *g = gpiochip_get_data(gc);
u32 mask = BIT(irqd_to_hwirq(d));
u32 reg_both, reg_level, reg_type;
@ -123,23 +123,23 @@ static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type)
writel(reg_level, g->base + GPIO_INT_LEVEL);
writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);
gemini_gpio_ack_irq(d);
ftgpio_gpio_ack_irq(d);
return 0;
}
static struct irq_chip gemini_gpio_irqchip = {
.name = "GPIO",
.irq_ack = gemini_gpio_ack_irq,
.irq_mask = gemini_gpio_mask_irq,
.irq_unmask = gemini_gpio_unmask_irq,
.irq_set_type = gemini_gpio_set_irq_type,
static struct irq_chip ftgpio_gpio_irqchip = {
.name = "FTGPIO010",
.irq_ack = ftgpio_gpio_ack_irq,
.irq_mask = ftgpio_gpio_mask_irq,
.irq_unmask = ftgpio_gpio_unmask_irq,
.irq_set_type = ftgpio_gpio_set_irq_type,
};
static void gemini_gpio_irq_handler(struct irq_desc *desc)
static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct gemini_gpio *g = gpiochip_get_data(gc);
struct ftgpio_gpio *g = gpiochip_get_data(gc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
int offset;
unsigned long stat;
@ -155,11 +155,11 @@ static void gemini_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(irqchip, desc);
}
static int gemini_gpio_probe(struct platform_device *pdev)
static int ftgpio_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct gemini_gpio *g;
struct ftgpio_gpio *g;
int irq;
int ret;
@ -189,7 +189,7 @@ static int gemini_gpio_probe(struct platform_device *pdev)
dev_err(dev, "unable to init generic GPIO\n");
return ret;
}
g->gc.label = "Gemini";
g->gc.label = "FTGPIO010";
g->gc.base = -1;
g->gc.parent = dev;
g->gc.owner = THIS_MODULE;
@ -204,33 +204,39 @@ static int gemini_gpio_probe(struct platform_device *pdev)
writel(0x0, g->base + GPIO_INT_MASK);
writel(~0x0, g->base + GPIO_INT_CLR);
ret = gpiochip_irqchip_add(&g->gc, &gemini_gpio_irqchip,
ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip,
0, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_info(dev, "could not add irqchip\n");
return ret;
}
gpiochip_set_chained_irqchip(&g->gc, &gemini_gpio_irqchip,
irq, gemini_gpio_irq_handler);
gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip,
irq, ftgpio_gpio_irq_handler);
dev_info(dev, "Gemini GPIO @%p registered\n", g->base);
dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
return 0;
}
static const struct of_device_id gemini_gpio_of_match[] = {
static const struct of_device_id ftgpio_gpio_of_match[] = {
{
.compatible = "cortina,gemini-gpio",
},
{
.compatible = "moxa,moxart-gpio",
},
{
.compatible = "faraday,ftgpio010",
},
{},
};
static struct platform_driver gemini_gpio_driver = {
static struct platform_driver ftgpio_gpio_driver = {
.driver = {
.name = "gemini-gpio",
.of_match_table = of_match_ptr(gemini_gpio_of_match),
.name = "ftgpio010-gpio",
.of_match_table = of_match_ptr(ftgpio_gpio_of_match),
},
.probe = gemini_gpio_probe,
.probe = ftgpio_gpio_probe,
};
builtin_platform_driver(gemini_gpio_driver);
builtin_platform_driver(ftgpio_gpio_driver);

Просмотреть файл

@ -166,7 +166,7 @@ static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
return !(readl(gpdr) & BIT(offset % 32));
}
static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,

Просмотреть файл

@ -459,41 +459,31 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
chip = chip_save;
for (j = 0; j < 8; j++, chip++) {
irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
NUMA_NO_NODE);
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE,
num_ports[j], NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev,
"ml_ioh_gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
ret = irq_base;
goto err_irq_alloc_descs;
goto err_gpiochip_add;
}
chip->irq_base = irq_base;
ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
}
chip = chip_save;
ret = request_irq(pdev->irq, ioh_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
goto err_request_irq;
goto err_gpiochip_add;
}
pci_set_drvdata(pdev, chip);
return 0;
err_request_irq:
chip = chip_save;
err_irq_alloc_descs:
while (--j >= 0) {
chip--;
irq_free_descs(chip->irq_base, num_ports[j]);
}
chip = chip_save;
err_gpiochip_add:
while (--i >= 0) {
chip--;
@ -524,12 +514,8 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
chip_save = chip;
free_irq(pdev->irq, chip);
for (i = 0; i < 8; i++, chip++) {
irq_free_descs(chip->irq_base, num_ports[i]);
for (i = 0; i < 8; i++, chip++)
gpiochip_remove(&chip->gpio);
}
chip = chip_save;
pci_iounmap(pdev, chip->base);

Просмотреть файл

@ -575,6 +575,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
static const struct of_device_id bgpio_of_match[] = {
{ .compatible = "brcm,bcm6345-gpio" },
{ .compatible = "wd,mbl-gpio" },
{ .compatible = "ni,169445-nand-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, bgpio_of_match);

Просмотреть файл

@ -169,7 +169,7 @@ static int gpio_mockup_irqchip_setup(struct device *dev,
struct gpio_chip *gc = &chip->gc;
int irq_base, i;
irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0);
if (irq_base < 0)
return irq_base;
@ -372,25 +372,11 @@ static int gpio_mockup_probe(struct platform_device *pdev)
return 0;
}
static int gpio_mockup_remove(struct platform_device *pdev)
{
struct gpio_mockup_chip *chips;
int i;
chips = platform_get_drvdata(pdev);
for (i = 0; i < gpio_mockup_params_nr >> 1; i++)
irq_free_descs(chips[i].gc.irq_base, chips[i].gc.ngpio);
return 0;
}
static struct platform_driver gpio_mockup_driver = {
.driver = {
.name = GPIO_MOCKUP_NAME,
},
.probe = gpio_mockup_probe,
.remove = gpio_mockup_remove,
};
static struct platform_device *pdev;

Просмотреть файл

@ -1,84 +0,0 @@
/*
* MOXA ART SoCs GPIO driver.
*
* Copyright (C) 2013 Jonas Jensen
*
* Jonas Jensen <jonas.jensen@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#define GPIO_DATA_OUT 0x00
#define GPIO_DATA_IN 0x04
#define GPIO_PIN_DIRECTION 0x08
static int moxart_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct gpio_chip *gc;
void __iomem *base;
int ret;
gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
if (!gc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
base + GPIO_DATA_OUT, NULL,
base + GPIO_PIN_DIRECTION, NULL,
BGPIOF_READ_OUTPUT_REG_SET);
if (ret) {
dev_err(&pdev->dev, "bgpio_init failed\n");
return ret;
}
gc->label = "moxart-gpio";
gc->request = gpiochip_generic_request;
gc->free = gpiochip_generic_free;
gc->base = 0;
gc->owner = THIS_MODULE;
ret = devm_gpiochip_add_data(dev, gc, NULL);
if (ret) {
dev_err(dev, "%s: gpiochip_add failed\n",
dev->of_node->full_name);
return ret;
}
return ret;
}
static const struct of_device_id moxart_gpio_match[] = {
{ .compatible = "moxa,moxart-gpio" },
{ }
};
static struct platform_driver moxart_gpio_driver = {
.driver = {
.name = "moxart-gpio",
.of_match_table = moxart_gpio_match,
},
.probe = moxart_gpio_probe,
};
builtin_platform_driver(moxart_gpio_driver);

Просмотреть файл

@ -42,29 +42,44 @@
#include <linux/io.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/pwm.h>
#include <linux/clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include "gpiolib.h"
/*
* GPIO unit register offsets.
*/
#define GPIO_OUT_OFF 0x0000
#define GPIO_IO_CONF_OFF 0x0004
#define GPIO_BLINK_EN_OFF 0x0008
#define GPIO_IN_POL_OFF 0x000c
#define GPIO_DATA_IN_OFF 0x0010
#define GPIO_EDGE_CAUSE_OFF 0x0014
#define GPIO_EDGE_MASK_OFF 0x0018
#define GPIO_LEVEL_MASK_OFF 0x001c
#define GPIO_OUT_OFF 0x0000
#define GPIO_IO_CONF_OFF 0x0004
#define GPIO_BLINK_EN_OFF 0x0008
#define GPIO_IN_POL_OFF 0x000c
#define GPIO_DATA_IN_OFF 0x0010
#define GPIO_EDGE_CAUSE_OFF 0x0014
#define GPIO_EDGE_MASK_OFF 0x0018
#define GPIO_LEVEL_MASK_OFF 0x001c
#define GPIO_BLINK_CNT_SELECT_OFF 0x0020
/*
* PWM register offsets.
*/
#define PWM_BLINK_ON_DURATION_OFF 0x0
#define PWM_BLINK_OFF_DURATION_OFF 0x4
/* The MV78200 has per-CPU registers for edge mask and level mask */
#define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
#define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C)
/* The Armada XP has per-CPU registers for interrupt cause, interrupt
/*
* The Armada XP has per-CPU registers for interrupt cause, interrupt
* mask and interrupt level mask. Those are relative to the
* percpu_membase. */
* percpu_membase.
*/
#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
@ -75,6 +90,20 @@
#define MVEBU_MAX_GPIO_PER_BANK 32
struct mvebu_pwm {
void __iomem *membase;
unsigned long clk_rate;
struct gpio_desc *gpiod;
struct pwm_chip chip;
spinlock_t lock;
struct mvebu_gpio_chip *mvchip;
/* Used to preserve GPIO/PWM registers across suspend/resume */
u32 blink_select;
u32 blink_on_duration;
u32 blink_off_duration;
};
struct mvebu_gpio_chip {
struct gpio_chip chip;
spinlock_t lock;
@ -84,48 +113,55 @@ struct mvebu_gpio_chip {
struct irq_domain *domain;
int soc_variant;
/* Used for PWM support */
struct clk *clk;
struct mvebu_pwm *mvpwm;
/* Used to preserve GPIO registers across suspend/resume */
u32 out_reg;
u32 io_conf_reg;
u32 blink_en_reg;
u32 in_pol_reg;
u32 edge_mask_regs[4];
u32 level_mask_regs[4];
u32 out_reg;
u32 io_conf_reg;
u32 blink_en_reg;
u32 in_pol_reg;
u32 edge_mask_regs[4];
u32 level_mask_regs[4];
};
/*
* Functions returning addresses of individual registers for a given
* GPIO controller.
*/
static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_OUT_OFF;
}
static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_BLINK_EN_OFF;
}
static inline void __iomem *
mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip
*mvchip)
{
return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF;
}
static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_IO_CONF_OFF;
}
static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_IN_POL_OFF;
}
static inline void __iomem *
mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_DATA_IN_OFF;
}
static inline void __iomem *
mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
{
int cpu;
@ -142,8 +178,7 @@ mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
}
}
static inline void __iomem *
mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
static void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
{
int cpu;
@ -181,11 +216,24 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
}
}
/*
* Functions returning addresses of individual registers for a given
* PWM controller.
*/
static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
{
return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF;
}
static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
{
return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF;
}
/*
* Functions implementing the gpio_chip methods
*/
static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
unsigned long flags;
@ -194,19 +242,19 @@ static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_out(mvchip));
if (value)
u |= 1 << pin;
u |= BIT(pin);
else
u &= ~(1 << pin);
u &= ~BIT(pin);
writel_relaxed(u, mvebu_gpioreg_out(mvchip));
spin_unlock_irqrestore(&mvchip->lock, flags);
}
static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
u32 u;
if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin)) {
u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
} else {
@ -216,7 +264,8 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
return (u >> pin) & 1;
}
static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin,
int value)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
unsigned long flags;
@ -225,36 +274,38 @@ static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
if (value)
u |= 1 << pin;
u |= BIT(pin);
else
u &= ~(1 << pin);
u &= ~BIT(pin);
writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
spin_unlock_irqrestore(&mvchip->lock, flags);
}
static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
unsigned long flags;
int ret;
u32 u;
/* Check with the pinctrl driver whether this pin is usable as
* an input GPIO */
/*
* Check with the pinctrl driver whether this pin is usable as
* an input GPIO
*/
ret = pinctrl_gpio_direction_input(chip->base + pin);
if (ret)
return ret;
spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
u |= 1 << pin;
u |= BIT(pin);
writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
spin_unlock_irqrestore(&mvchip->lock, flags);
return 0;
}
static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
int value)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
@ -262,8 +313,10 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
int ret;
u32 u;
/* Check with the pinctrl driver whether this pin is usable as
* an output GPIO */
/*
* Check with the pinctrl driver whether this pin is usable as
* an output GPIO
*/
ret = pinctrl_gpio_direction_output(chip->base + pin);
if (ret)
return ret;
@ -273,16 +326,17 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
u &= ~(1 << pin);
u &= ~BIT(pin);
writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
spin_unlock_irqrestore(&mvchip->lock, flags);
return 0;
}
static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
return irq_create_mapping(mvchip->domain, pin);
}
@ -389,7 +443,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
pin = d->hwirq;
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin);
if (!u)
return -EINVAL;
@ -409,13 +463,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_LEVEL_HIGH:
u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
u &= ~(1 << pin);
u &= ~BIT(pin);
writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
break;
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_LEVEL_LOW:
u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
u |= 1 << pin;
u |= BIT(pin);
writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
break;
case IRQ_TYPE_EDGE_BOTH: {
@ -428,10 +482,10 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
* set initial polarity based on current input level
*/
u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
if (v & (1 << pin))
u |= 1 << pin; /* falling */
if (v & BIT(pin))
u |= BIT(pin); /* falling */
else
u &= ~(1 << pin); /* rising */
u &= ~BIT(pin); /* rising */
writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
break;
}
@ -461,7 +515,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
irq = irq_find_mapping(mvchip->domain, i);
if (!(cause & (1 << i)))
if (!(cause & BIT(i)))
continue;
type = irq_get_trigger_type(irq);
@ -470,7 +524,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
u32 polarity;
polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
polarity ^= 1 << i;
polarity ^= BIT(i);
writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
}
@ -480,6 +534,246 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
/*
* Functions implementing the pwm_chip methods
*/
static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
{
return container_of(chip, struct mvebu_pwm, chip);
}
static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
struct gpio_desc *desc;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&mvpwm->lock, flags);
if (mvpwm->gpiod) {
ret = -EBUSY;
} else {
desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm);
if (!desc) {
ret = -ENODEV;
goto out;
}
ret = gpiod_request(desc, "mvebu-pwm");
if (ret)
goto out;
ret = gpiod_direction_output(desc, 0);
if (ret) {
gpiod_free(desc);
goto out;
}
mvpwm->gpiod = desc;
}
out:
spin_unlock_irqrestore(&mvpwm->lock, flags);
return ret;
}
static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
unsigned long flags;
spin_lock_irqsave(&mvpwm->lock, flags);
gpiod_free(mvpwm->gpiod);
mvpwm->gpiod = NULL;
spin_unlock_irqrestore(&mvpwm->lock, flags);
}
static void mvebu_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state) {
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
unsigned long long val;
unsigned long flags;
u32 u;
spin_lock_irqsave(&mvpwm->lock, flags);
val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
val *= NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val > UINT_MAX)
state->duty_cycle = UINT_MAX;
else if (val)
state->duty_cycle = val;
else
state->duty_cycle = 1;
val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
val *= NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val < state->duty_cycle) {
state->period = 1;
} else {
val -= state->duty_cycle;
if (val > UINT_MAX)
state->period = UINT_MAX;
else if (val)
state->period = val;
else
state->period = 1;
}
u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
if (u)
state->enabled = true;
else
state->enabled = false;
spin_unlock_irqrestore(&mvpwm->lock, flags);
}
static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
unsigned long long val;
unsigned long flags;
unsigned int on, off;
val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
do_div(val, NSEC_PER_SEC);
if (val > UINT_MAX)
return -EINVAL;
if (val)
on = val;
else
on = 1;
val = (unsigned long long) mvpwm->clk_rate *
(state->period - state->duty_cycle);
do_div(val, NSEC_PER_SEC);
if (val > UINT_MAX)
return -EINVAL;
if (val)
off = val;
else
off = 1;
spin_lock_irqsave(&mvpwm->lock, flags);
writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm));
writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm));
if (state->enabled)
mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
else
mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0);
spin_unlock_irqrestore(&mvpwm->lock, flags);
return 0;
}
static const struct pwm_ops mvebu_pwm_ops = {
.request = mvebu_pwm_request,
.free = mvebu_pwm_free,
.get_state = mvebu_pwm_get_state,
.apply = mvebu_pwm_apply,
.owner = THIS_MODULE,
};
static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
{
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
mvpwm->blink_select =
readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip));
mvpwm->blink_on_duration =
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
mvpwm->blink_off_duration =
readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
}
static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
{
struct mvebu_pwm *mvpwm = mvchip->mvpwm;
writel_relaxed(mvpwm->blink_select,
mvebu_gpioreg_blink_counter_select(mvchip));
writel_relaxed(mvpwm->blink_on_duration,
mvebu_pwmreg_blink_on_duration(mvpwm));
writel_relaxed(mvpwm->blink_off_duration,
mvebu_pwmreg_blink_off_duration(mvpwm));
}
static int mvebu_pwm_probe(struct platform_device *pdev,
struct mvebu_gpio_chip *mvchip,
int id)
{
struct device *dev = &pdev->dev;
struct mvebu_pwm *mvpwm;
struct resource *res;
u32 set;
if (!of_device_is_compatible(mvchip->chip.of_node,
"marvell,armada-370-xp-gpio"))
return 0;
if (IS_ERR(mvchip->clk))
return PTR_ERR(mvchip->clk);
/*
* There are only two sets of PWM configuration registers for
* all the GPIO lines on those SoCs which this driver reserves
* for the first two GPIO chips. So if the resource is missing
* we can't treat it as an error.
*/
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
if (!res)
return 0;
/*
* Use set A for lines of GPIO chip with id 0, B for GPIO chip
* with id 1. Don't allow further GPIO chips to be used for PWM.
*/
if (id == 0)
set = 0;
else if (id == 1)
set = U32_MAX;
else
return -EINVAL;
writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip));
mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
if (!mvpwm)
return -ENOMEM;
mvchip->mvpwm = mvpwm;
mvpwm->mvchip = mvchip;
mvpwm->membase = devm_ioremap_resource(dev, res);
if (IS_ERR(mvpwm->membase))
return PTR_ERR(mvpwm->membase);
mvpwm->clk_rate = clk_get_rate(mvchip->clk);
if (!mvpwm->clk_rate) {
dev_err(dev, "failed to get clock rate\n");
return -EINVAL;
}
mvpwm->chip.dev = dev;
mvpwm->chip.ops = &mvebu_pwm_ops;
mvpwm->chip.npwm = mvchip->chip.ngpio;
spin_lock_init(&mvpwm->lock);
return pwmchip_add(&mvpwm->chip);
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
@ -507,7 +801,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
if (!label)
continue;
msk = 1 << i;
msk = BIT(i);
is_out = !(io_conf & msk);
seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
@ -550,6 +844,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
.compatible = "marvell,armadaxp-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
},
{
.compatible = "marvell,armada-370-xp-gpio",
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
},
{
/* sentinel */
},
@ -596,6 +894,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
BUG();
}
if (IS_ENABLED(CONFIG_PWM))
mvebu_pwm_suspend(mvchip);
return 0;
}
@ -639,6 +940,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
BUG();
}
if (IS_ENABLED(CONFIG_PWM))
mvebu_pwm_resume(mvchip);
return 0;
}
@ -650,7 +954,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
struct resource *res;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
struct clk *clk;
unsigned int ngpios;
bool have_irqs;
int soc_variant;
@ -684,10 +987,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
return id;
}
clk = devm_clk_get(&pdev->dev, NULL);
mvchip->clk = devm_clk_get(&pdev->dev, NULL);
/* Not all SoCs require a clock.*/
if (!IS_ERR(clk))
clk_prepare_enable(clk);
if (!IS_ERR(mvchip->clk))
clk_prepare_enable(mvchip->clk);
mvchip->soc_variant = soc_variant;
mvchip->chip.label = dev_name(&pdev->dev);
@ -712,8 +1015,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (IS_ERR(mvchip->membase))
return PTR_ERR(mvchip->membase);
/* The Armada XP has a second range of registers for the
* per-CPU registers */
/*
* The Armada XP has a second range of registers for the
* per-CPU registers
*/
if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
@ -780,7 +1085,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
goto err_domain;
}
/* NOTE: The common accessors cannot be used because of the percpu
/*
* NOTE: The common accessors cannot be used because of the percpu
* access to the mask registers
*/
gc = irq_get_domain_generic_chip(mvchip->domain, 0);
@ -801,7 +1107,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
ct->handler = handle_edge_irq;
ct->chip.name = mvchip->chip.label;
/* Setup the interrupt handlers. Each chip can have up to 4
/*
* Setup the interrupt handlers. Each chip can have up to 4
* interrupt handlers, with each handler dealing with 8 GPIO
* pins.
*/
@ -814,6 +1121,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip);
}
/* Armada 370/XP has simple PWM support for GPIO lines */
if (IS_ENABLED(CONFIG_PWM))
return mvebu_pwm_probe(pdev, mvchip, id);
return 0;
err_domain:

Просмотреть файл

@ -471,7 +471,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
if (err)
goto out_bgio;
irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
if (irq_base < 0) {
err = irq_base;
goto out_bgio;
@ -481,7 +481,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
&irq_domain_simple_ops, NULL);
if (!port->domain) {
err = -ENODEV;
goto out_irqdesc_free;
goto out_bgio;
}
/* gpio-mxc can be a generic irq chip */
@ -495,8 +495,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
out_irqdomain_remove:
irq_domain_remove(port->domain);
out_irqdesc_free:
irq_free_descs(irq_base, 32);
out_bgio:
dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
return err;

Просмотреть файл

@ -328,7 +328,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
/* clear address has to be used to clear IRQSTAT bits */
writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
if (irq_base < 0) {
err = irq_base;
goto out_iounmap;
@ -338,7 +338,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
&irq_domain_simple_ops, NULL);
if (!port->domain) {
err = -ENODEV;
goto out_irqdesc_free;
goto out_iounmap;
}
/* gpio-mxs can be a generic irq chip */
@ -370,8 +370,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)
out_irqdomain_remove:
irq_domain_remove(port->domain);
out_irqdesc_free:
irq_free_descs(irq_base, 32);
out_iounmap:
iounmap(port->base);
return err;

Просмотреть файл

@ -208,9 +208,11 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
* OMAP's debounce time is in 31us steps
* <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
* so we need to convert and round up to the closest unit.
*
* Return: 0 on success, negative error otherwise.
*/
static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
unsigned debounce)
static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
unsigned debounce)
{
void __iomem *reg;
u32 val;
@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
bool enable = !!debounce;
if (!bank->dbck_flag)
return;
return -ENOTSUPP;
if (enable) {
debounce = DIV_ROUND_UP(debounce, 31) - 1;
debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
return -EINVAL;
}
l = BIT(offset);
@ -255,6 +258,8 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
bank->context.debounce = debounce;
bank->context.debounce_en = val;
}
return 0;
}
/**
@ -964,14 +969,20 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
{
struct gpio_bank *bank;
unsigned long flags;
int ret;
bank = gpiochip_get_data(chip);
raw_spin_lock_irqsave(&bank->lock, flags);
omap2_set_gpio_debounce(bank, offset, debounce);
ret = omap2_set_gpio_debounce(bank, offset, debounce);
raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0;
if (ret)
dev_info(chip->parent,
"Could not set line %u debounce to %u microseconds (%d)",
offset, debounce, ret);
return ret;
}
static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
@ -1085,7 +1096,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
* REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
* irq_alloc_descs() since a base IRQ offset will no longer be needed.
*/
irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
irq_base = devm_irq_alloc_descs(bank->chip.parent,
-1, 0, bank->width, 0);
if (irq_base < 0) {
dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n");
return -ENODEV;

Просмотреть файл

@ -11,18 +11,19 @@
* the Free Software Foundation; version 2 of the License.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/acpi.h>
#include <linux/platform_data/pca953x.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
@ -81,6 +82,7 @@ static const struct i2c_device_id pca953x_id[] = {
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
{ "tca9554", 8 | PCA953X_TYPE | PCA_INT, },
{ "xra1202", 8 | PCA953X_TYPE },
{ }
};
@ -363,6 +365,21 @@ exit:
mutex_unlock(&chip->i2c_lock);
}
static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
{
struct pca953x_chip *chip = gpiochip_get_data(gc);
u32 reg_val;
int ret;
mutex_lock(&chip->i2c_lock);
ret = pca953x_read_single(chip, chip->regs->direction, &reg_val, off);
mutex_unlock(&chip->i2c_lock);
if (ret < 0)
return ret;
return !!(reg_val & (1u << (off % BANK_SZ)));
}
static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
@ -408,6 +425,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->direction_output = pca953x_gpio_direction_output;
gc->get = pca953x_gpio_get_value;
gc->set = pca953x_gpio_set_value;
gc->get_direction = pca953x_gpio_get_direction;
gc->set_multiple = pca953x_gpio_set_multiple;
gc->can_sleep = true;
@ -760,7 +778,13 @@ static int pca953x_probe(struct i2c_client *client,
chip->gpio_start = -1;
irq_base = 0;
/* See if we need to de-assert a reset pin */
/*
* See if we need to de-assert a reset pin.
*
* There is no known ACPI-enabled platforms that are
* using "reset" GPIO. Otherwise any of those platform
* must use _DSD method with corresponding property.
*/
reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(reset_gpio))

Просмотреть файл

@ -46,7 +46,6 @@ static const struct i2c_device_id pcf857x_id[] = {
{ "pca9675", 16 },
{ "max7328", 8 },
{ "max7329", 8 },
{ "tca9554", 8 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@ -66,7 +65,6 @@ static const struct of_device_id pcf857x_of_table[] = {
{ .compatible = "nxp,pca9675" },
{ .compatible = "maxim,max7328" },
{ .compatible = "maxim,max7329" },
{ .compatible = "ti,tca9554" },
{ }
};
MODULE_DEVICE_TABLE(of, pcf857x_of_table);

Просмотреть файл

@ -403,7 +403,8 @@ static int pch_gpio_probe(struct pci_dev *pdev,
goto err_gpiochip_add;
}
irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
gpio_pins[chip->ioh], NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
@ -416,8 +417,8 @@ static int pch_gpio_probe(struct pci_dev *pdev,
iowrite32(msk, &chip->reg->imask);
iowrite32(msk, &chip->reg->ien);
ret = request_irq(pdev->irq, pch_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
@ -430,7 +431,6 @@ end:
return 0;
err_request_irq:
irq_free_descs(irq_base, gpio_pins[chip->ioh]);
gpiochip_remove(&chip->gpio);
err_gpiochip_add:
@ -452,12 +452,6 @@ static void pch_gpio_remove(struct pci_dev *pdev)
{
struct pch_gpio *chip = pci_get_drvdata(pdev);
if (chip->irq_base != -1) {
free_irq(pdev->irq, chip);
irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
}
gpiochip_remove(&chip->gpio);
pci_iounmap(pdev, chip->base);
pci_release_regions(pdev);

Просмотреть файл

@ -59,7 +59,7 @@ struct idio_16_gpio_reg {
*/
struct idio_16_gpio {
struct gpio_chip chip;
spinlock_t lock;
raw_spinlock_t lock;
struct idio_16_gpio_reg __iomem *reg;
unsigned long irq_mask;
};
@ -121,7 +121,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
} else
base = &idio16gpio->reg->out0_7;
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
if (value)
out_state = ioread8(base) | mask;
@ -130,7 +130,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
iowrite8(out_state, base);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
@ -140,7 +140,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
unsigned long flags;
unsigned int out_state;
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
/* process output lines 0-7 */
if (*mask & 0xFF) {
@ -160,7 +160,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
iowrite8(out_state, &idio16gpio->reg->out8_15);
}
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
static void idio_16_irq_ack(struct irq_data *data)
@ -177,11 +177,11 @@ static void idio_16_irq_mask(struct irq_data *data)
idio16gpio->irq_mask &= ~mask;
if (!idio16gpio->irq_mask) {
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
iowrite8(0, &idio16gpio->reg->irq_ctl);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
}
@ -196,11 +196,11 @@ static void idio_16_irq_unmask(struct irq_data *data)
idio16gpio->irq_mask |= mask;
if (!prev_irq_mask) {
spin_lock_irqsave(&idio16gpio->lock, flags);
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
ioread8(&idio16gpio->reg->irq_ctl);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
}
@ -229,11 +229,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
struct gpio_chip *const chip = &idio16gpio->chip;
int gpio;
spin_lock(&idio16gpio->lock);
raw_spin_lock(&idio16gpio->lock);
irq_status = ioread8(&idio16gpio->reg->irq_status);
spin_unlock(&idio16gpio->lock);
raw_spin_unlock(&idio16gpio->lock);
/* Make sure our device generated IRQ */
if (!(irq_status & 0x3) || !(irq_status & 0x4))
@ -242,12 +242,12 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
spin_lock(&idio16gpio->lock);
raw_spin_lock(&idio16gpio->lock);
/* Clear interrupt */
iowrite8(0, &idio16gpio->reg->in0_7);
spin_unlock(&idio16gpio->lock);
raw_spin_unlock(&idio16gpio->lock);
return IRQ_HANDLED;
}
@ -302,7 +302,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
spin_lock_init(&idio16gpio->lock);
raw_spin_lock_init(&idio16gpio->lock);
err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
if (err) {

Просмотреть файл

@ -50,7 +50,7 @@ struct pl061_context_save_regs {
#endif
struct pl061 {
spinlock_t lock;
raw_spinlock_t lock;
void __iomem *base;
struct gpio_chip gc;
@ -74,11 +74,11 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
unsigned long flags;
unsigned char gpiodir;
spin_lock_irqsave(&pl061->lock, flags);
raw_spin_lock_irqsave(&pl061->lock, flags);
gpiodir = readb(pl061->base + GPIODIR);
gpiodir &= ~(BIT(offset));
writeb(gpiodir, pl061->base + GPIODIR);
spin_unlock_irqrestore(&pl061->lock, flags);
raw_spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
@ -90,7 +90,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
unsigned long flags;
unsigned char gpiodir;
spin_lock_irqsave(&pl061->lock, flags);
raw_spin_lock_irqsave(&pl061->lock, flags);
writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
gpiodir = readb(pl061->base + GPIODIR);
gpiodir |= BIT(offset);
@ -101,7 +101,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
* a gpio pin before configuring it in OUT mode.
*/
writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
spin_unlock_irqrestore(&pl061->lock, flags);
raw_spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
@ -143,7 +143,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
}
spin_lock_irqsave(&pl061->lock, flags);
raw_spin_lock_irqsave(&pl061->lock, flags);
gpioiev = readb(pl061->base + GPIOIEV);
gpiois = readb(pl061->base + GPIOIS);
@ -203,7 +203,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
writeb(gpioibe, pl061->base + GPIOIBE);
writeb(gpioiev, pl061->base + GPIOIEV);
spin_unlock_irqrestore(&pl061->lock, flags);
raw_spin_unlock_irqrestore(&pl061->lock, flags);
return 0;
}
@ -235,10 +235,10 @@ static void pl061_irq_mask(struct irq_data *d)
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
spin_lock(&pl061->lock);
raw_spin_lock(&pl061->lock);
gpioie = readb(pl061->base + GPIOIE) & ~mask;
writeb(gpioie, pl061->base + GPIOIE);
spin_unlock(&pl061->lock);
raw_spin_unlock(&pl061->lock);
}
static void pl061_irq_unmask(struct irq_data *d)
@ -248,10 +248,10 @@ static void pl061_irq_unmask(struct irq_data *d)
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
u8 gpioie;
spin_lock(&pl061->lock);
raw_spin_lock(&pl061->lock);
gpioie = readb(pl061->base + GPIOIE) | mask;
writeb(gpioie, pl061->base + GPIOIE);
spin_unlock(&pl061->lock);
raw_spin_unlock(&pl061->lock);
}
/**
@ -268,9 +268,9 @@ static void pl061_irq_ack(struct irq_data *d)
struct pl061 *pl061 = gpiochip_get_data(gc);
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
spin_lock(&pl061->lock);
raw_spin_lock(&pl061->lock);
writeb(mask, pl061->base + GPIOIC);
spin_unlock(&pl061->lock);
raw_spin_unlock(&pl061->lock);
}
static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
@ -304,7 +304,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
if (IS_ERR(pl061->base))
return PTR_ERR(pl061->base);
spin_lock_init(&pl061->lock);
raw_spin_lock_init(&pl061->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
pl061->gc.request = gpiochip_generic_request;
pl061->gc.free = gpiochip_generic_free;

Просмотреть файл

@ -601,7 +601,7 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev,
nr_gpios = gpio_id->gpio_nums;
pxa_last_gpio = nr_gpios - 1;
irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, nr_gpios, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
return irq_base;

185
drivers/gpio/gpio-reg.c Normal file
Просмотреть файл

@ -0,0 +1,185 @@
/*
* gpio-reg: single register individually fixed-direction GPIOs
*
* Copyright (C) 2016 Russell King
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*/
#include <linux/gpio/driver.h>
#include <linux/gpio/gpio-reg.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
struct gpio_reg {
struct gpio_chip gc;
spinlock_t lock;
u32 direction;
u32 out;
void __iomem *reg;
struct irq_domain *irqdomain;
const int *irqs;
};
#define to_gpio_reg(x) container_of(x, struct gpio_reg, gc)
static int gpio_reg_get_direction(struct gpio_chip *gc, unsigned offset)
{
struct gpio_reg *r = to_gpio_reg(gc);
return r->direction & BIT(offset) ? 1 : 0;
}
static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct gpio_reg *r = to_gpio_reg(gc);
if (r->direction & BIT(offset))
return -ENOTSUPP;
gc->set(gc, offset, value);
return 0;
}
static int gpio_reg_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct gpio_reg *r = to_gpio_reg(gc);
return r->direction & BIT(offset) ? 0 : -ENOTSUPP;
}
static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct gpio_reg *r = to_gpio_reg(gc);
unsigned long flags;
u32 val, mask = BIT(offset);
spin_lock_irqsave(&r->lock, flags);
val = r->out;
if (value)
val |= mask;
else
val &= ~mask;
r->out = val;
writel_relaxed(val, r->reg);
spin_unlock_irqrestore(&r->lock, flags);
}
static int gpio_reg_get(struct gpio_chip *gc, unsigned offset)
{
struct gpio_reg *r = to_gpio_reg(gc);
u32 val, mask = BIT(offset);
if (r->direction & mask) {
/*
* double-read the value, some registers latch after the
* first read.
*/
readl_relaxed(r->reg);
val = readl_relaxed(r->reg);
} else {
val = r->out;
}
return !!(val & mask);
}
static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
struct gpio_reg *r = to_gpio_reg(gc);
unsigned long flags;
spin_lock_irqsave(&r->lock, flags);
r->out = (r->out & ~*mask) | (*bits & *mask);
writel_relaxed(r->out, r->reg);
spin_unlock_irqrestore(&r->lock, flags);
}
static int gpio_reg_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct gpio_reg *r = to_gpio_reg(gc);
int irq = r->irqs[offset];
if (irq >= 0 && r->irqdomain)
irq = irq_find_mapping(r->irqdomain, irq);
return irq;
}
/**
* gpio_reg_init - add a fixed in/out register as gpio
* @dev: optional struct device associated with this register
* @base: start gpio number, or -1 to allocate
* @num: number of GPIOs, maximum 32
* @label: GPIO chip label
* @direction: bitmask of fixed direction, one per GPIO signal, 1 = in
* @def_out: initial GPIO output value
* @names: array of %num strings describing each GPIO signal or %NULL
* @irqdom: irq domain or %NULL
* @irqs: array of %num ints describing the interrupt mapping for each
* GPIO signal, or %NULL. If @irqdom is %NULL, then this
* describes the Linux interrupt number, otherwise it describes
* the hardware interrupt number in the specified irq domain.
*
* Add a single-register GPIO device containing up to 32 GPIO signals,
* where each GPIO has a fixed input or output configuration. Only
* input GPIOs are assumed to be readable from the register, and only
* then after a double-read. Output values are assumed not to be
* readable.
*/
struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg,
int base, int num, const char *label, u32 direction, u32 def_out,
const char *const *names, struct irq_domain *irqdom, const int *irqs)
{
struct gpio_reg *r;
int ret;
if (dev)
r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
else
r = kzalloc(sizeof(*r), GFP_KERNEL);
if (!r)
return ERR_PTR(-ENOMEM);
spin_lock_init(&r->lock);
r->gc.label = label;
r->gc.get_direction = gpio_reg_get_direction;
r->gc.direction_input = gpio_reg_direction_input;
r->gc.direction_output = gpio_reg_direction_output;
r->gc.set = gpio_reg_set;
r->gc.get = gpio_reg_get;
r->gc.set_multiple = gpio_reg_set_multiple;
if (irqs)
r->gc.to_irq = gpio_reg_to_irq;
r->gc.base = base;
r->gc.ngpio = num;
r->gc.names = names;
r->direction = direction;
r->out = def_out;
r->reg = reg;
r->irqs = irqs;
if (dev)
ret = devm_gpiochip_add_data(dev, &r->gc, r);
else
ret = gpiochip_add_data(&r->gc, r);
return ret ? ERR_PTR(ret) : &r->gc;
}
int gpio_reg_resume(struct gpio_chip *gc)
{
struct gpio_reg *r = to_gpio_reg(gc);
unsigned long flags;
spin_lock_irqsave(&r->lock, flags);
writel_relaxed(r->out, r->reg);
spin_unlock_irqrestore(&r->lock, flags);
return 0;
}

Просмотреть файл

@ -12,57 +12,97 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/syscore_ops.h>
#include <soc/sa1100/pwer.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
struct sa1100_gpio_chip {
struct gpio_chip chip;
void __iomem *membase;
int irqbase;
u32 irqmask;
u32 irqrising;
u32 irqfalling;
u32 irqwake;
};
#define sa1100_gpio_chip(x) container_of(x, struct sa1100_gpio_chip, chip)
enum {
R_GPLR = 0x00,
R_GPDR = 0x04,
R_GPSR = 0x08,
R_GPCR = 0x0c,
R_GRER = 0x10,
R_GFER = 0x14,
R_GEDR = 0x18,
R_GAFR = 0x1c,
};
static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
{
return !!(GPLR & GPIO_GPIO(offset));
return readl_relaxed(sa1100_gpio_chip(chip)->membase + R_GPLR) &
BIT(offset);
}
static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
if (value)
GPSR = GPIO_GPIO(offset);
else
GPCR = GPIO_GPIO(offset);
int reg = value ? R_GPSR : R_GPCR;
writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg);
}
static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
return !(readl_relaxed(gpdr) & BIT(offset));
}
static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
{
void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
unsigned long flags;
local_irq_save(flags);
GPDR &= ~GPIO_GPIO(offset);
writel_relaxed(readl_relaxed(gpdr) & ~BIT(offset), gpdr);
local_irq_restore(flags);
return 0;
}
static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
unsigned long flags;
local_irq_save(flags);
sa1100_gpio_set(chip, offset, value);
GPDR |= GPIO_GPIO(offset);
writel_relaxed(readl_relaxed(gpdr) | BIT(offset), gpdr);
local_irq_restore(flags);
return 0;
}
static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
{
return IRQ_GPIO0 + offset;
return sa1100_gpio_chip(chip)->irqbase + offset;
}
static struct gpio_chip sa1100_gpio_chip = {
.label = "gpio",
.direction_input = sa1100_direction_input,
.direction_output = sa1100_direction_output,
.set = sa1100_gpio_set,
.get = sa1100_gpio_get,
.to_irq = sa1100_to_irq,
.base = 0,
.ngpio = GPIO_MAX + 1,
static struct sa1100_gpio_chip sa1100_gpio_chip = {
.chip = {
.label = "gpio",
.get_direction = sa1100_get_direction,
.direction_input = sa1100_direction_input,
.direction_output = sa1100_direction_output,
.set = sa1100_gpio_set,
.get = sa1100_gpio_get,
.to_irq = sa1100_to_irq,
.base = 0,
.ngpio = GPIO_MAX + 1,
},
.membase = (void *)&GPLR,
.irqbase = IRQ_GPIO0,
};
/*
@ -70,33 +110,39 @@ static struct gpio_chip sa1100_gpio_chip = {
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
* Use this instead of directly setting GRER/GFER.
*/
static int GPIO_IRQ_rising_edge;
static int GPIO_IRQ_falling_edge;
static int GPIO_IRQ_mask;
static void sa1100_update_edge_regs(struct sa1100_gpio_chip *sgc)
{
void *base = sgc->membase;
u32 grer, gfer;
grer = sgc->irqrising & sgc->irqmask;
gfer = sgc->irqfalling & sgc->irqmask;
writel_relaxed(grer, base + R_GRER);
writel_relaxed(gfer, base + R_GFER);
}
static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
{
unsigned int mask;
mask = BIT(d->hwirq);
struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
unsigned int mask = BIT(d->hwirq);
if (type == IRQ_TYPE_PROBE) {
if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
if ((sgc->irqrising | sgc->irqfalling) & mask)
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
}
if (type & IRQ_TYPE_EDGE_RISING)
GPIO_IRQ_rising_edge |= mask;
sgc->irqrising |= mask;
else
GPIO_IRQ_rising_edge &= ~mask;
sgc->irqrising &= ~mask;
if (type & IRQ_TYPE_EDGE_FALLING)
GPIO_IRQ_falling_edge |= mask;
sgc->irqfalling |= mask;
else
GPIO_IRQ_falling_edge &= ~mask;
sgc->irqfalling &= ~mask;
GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
sa1100_update_edge_regs(sgc);
return 0;
}
@ -106,36 +152,42 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
*/
static void sa1100_gpio_ack(struct irq_data *d)
{
GEDR = BIT(d->hwirq);
struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
writel_relaxed(BIT(d->hwirq), sgc->membase + R_GEDR);
}
static void sa1100_gpio_mask(struct irq_data *d)
{
struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
unsigned int mask = BIT(d->hwirq);
GPIO_IRQ_mask &= ~mask;
sgc->irqmask &= ~mask;
GRER &= ~mask;
GFER &= ~mask;
sa1100_update_edge_regs(sgc);
}
static void sa1100_gpio_unmask(struct irq_data *d)
{
struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
unsigned int mask = BIT(d->hwirq);
GPIO_IRQ_mask |= mask;
sgc->irqmask |= mask;
GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
sa1100_update_edge_regs(sgc);
}
static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
{
if (on)
PWER |= BIT(d->hwirq);
else
PWER &= ~BIT(d->hwirq);
return 0;
struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
int ret = sa11x0_gpio_set_wake(d->hwirq, on);
if (!ret) {
if (on)
sgc->irqwake |= BIT(d->hwirq);
else
sgc->irqwake &= ~BIT(d->hwirq);
}
return ret;
}
/*
@ -153,8 +205,10 @@ static struct irq_chip sa1100_gpio_irq_chip = {
static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
unsigned int irq, irq_hw_number_t hwirq)
{
irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
handle_edge_irq);
struct sa1100_gpio_chip *sgc = d->host_data;
irq_set_chip_data(irq, sgc);
irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, handle_edge_irq);
irq_set_probe(irq);
return 0;
@ -174,17 +228,19 @@ static struct irq_domain *sa1100_gpio_irqdomain;
*/
static void sa1100_gpio_handler(struct irq_desc *desc)
{
struct sa1100_gpio_chip *sgc = irq_desc_get_handler_data(desc);
unsigned int irq, mask;
void __iomem *gedr = sgc->membase + R_GEDR;
mask = GEDR;
mask = readl_relaxed(gedr);
do {
/*
* clear down all currently active IRQ sources.
* We will be processing them all.
*/
GEDR = mask;
writel_relaxed(mask, gedr);
irq = IRQ_GPIO0;
irq = sgc->irqbase;
do {
if (mask & 1)
generic_handle_irq(irq);
@ -192,30 +248,32 @@ static void sa1100_gpio_handler(struct irq_desc *desc)
irq++;
} while (mask);
mask = GEDR;
mask = readl_relaxed(gedr);
} while (mask);
}
static int sa1100_gpio_suspend(void)
{
struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
/*
* Set the appropriate edges for wakeup.
*/
GRER = PWER & GPIO_IRQ_rising_edge;
GFER = PWER & GPIO_IRQ_falling_edge;
writel_relaxed(sgc->irqwake & sgc->irqrising, sgc->membase + R_GRER);
writel_relaxed(sgc->irqwake & sgc->irqfalling, sgc->membase + R_GFER);
/*
* Clear any pending GPIO interrupts.
*/
GEDR = GEDR;
writel_relaxed(readl_relaxed(sgc->membase + R_GEDR),
sgc->membase + R_GEDR);
return 0;
}
static void sa1100_gpio_resume(void)
{
GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
sa1100_update_edge_regs(&sa1100_gpio_chip);
}
static struct syscore_ops sa1100_gpio_syscore_ops = {
@ -231,36 +289,40 @@ static int __init sa1100_gpio_init_devicefs(void)
device_initcall(sa1100_gpio_init_devicefs);
static const int sa1100_gpio_irqs[] __initconst = {
/* Install handlers for GPIO 0-10 edge detect interrupts */
IRQ_GPIO0_SC,
IRQ_GPIO1_SC,
IRQ_GPIO2_SC,
IRQ_GPIO3_SC,
IRQ_GPIO4_SC,
IRQ_GPIO5_SC,
IRQ_GPIO6_SC,
IRQ_GPIO7_SC,
IRQ_GPIO8_SC,
IRQ_GPIO9_SC,
IRQ_GPIO10_SC,
/* Install handler for GPIO 11-27 edge detect interrupts */
IRQ_GPIO11_27,
};
void __init sa1100_init_gpio(void)
{
/* clear all GPIO edge detects */
GFER = 0;
GRER = 0;
GEDR = -1;
struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
int i;
gpiochip_add_data(&sa1100_gpio_chip, NULL);
/* clear all GPIO edge detects */
writel_relaxed(0, sgc->membase + R_GFER);
writel_relaxed(0, sgc->membase + R_GRER);
writel_relaxed(-1, sgc->membase + R_GEDR);
gpiochip_add_data(&sa1100_gpio_chip.chip, NULL);
sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
28, IRQ_GPIO0,
&sa1100_gpio_irqdomain_ops, NULL);
/*
* Install handlers for GPIO 0-10 edge detect interrupts
*/
irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler);
irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler);
/*
* Install handler for GPIO 11-27 edge detect interrupts
*/
irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler);
&sa1100_gpio_irqdomain_ops, sgc);
for (i = 0; i < ARRAY_SIZE(sa1100_gpio_irqs); i++)
irq_set_chained_handler_and_data(sa1100_gpio_irqs[i],
sa1100_gpio_handler, sgc);
}

Просмотреть файл

@ -135,7 +135,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
struct irq_chip_type *ct;
int ret;
sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1);
sd->irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
SDV_NUM_PUB_GPIOS, -1);
if (sd->irq_base < 0)
return sd->irq_base;
@ -143,10 +144,11 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
writel(0, sd->gpio_pub_base + GPIO_INT);
writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR);
ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED,
"sdv_gpio", sd);
ret = devm_request_irq(&pdev->dev, pdev->irq,
sdv_gpio_pub_irq_handler, IRQF_SHARED,
"sdv_gpio", sd);
if (ret)
goto out_free_desc;
return ret;
/*
* This gpio irq controller latches level irqs. Testing shows that if
@ -155,10 +157,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
*/
sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base,
sd->gpio_pub_base, handle_fasteoi_irq);
if (!sd->gc) {
ret = -ENOMEM;
goto out_free_irq;
}
if (!sd->gc)
return -ENOMEM;
sd->gc->private = sd;
ct = sd->gc->chip_types;
@ -176,16 +176,10 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
sd->irq_base, 0, &irq_domain_sdv_ops, sd);
if (!sd->id) {
ret = -ENODEV;
goto out_free_irq;
}
if (!sd->id)
return -ENODEV;
return 0;
out_free_irq:
free_irq(pdev->irq, sd);
out_free_desc:
irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
return ret;
}
static int sdv_gpio_probe(struct pci_dev *pdev,

Просмотреть файл

@ -392,7 +392,8 @@ static int gsta_probe(struct platform_device *dev)
gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
/* 384 was used in previous code: be compatible for other drivers */
err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE);
err = devm_irq_alloc_descs(&dev->dev, -1, 384,
GSTA_NR_GPIO, NUMA_NO_NODE);
if (err < 0) {
dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
-err);
@ -401,29 +402,23 @@ static int gsta_probe(struct platform_device *dev)
chip->irq_base = err;
gsta_alloc_irq_chip(chip);
err = request_irq(pdev->irq, gsta_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
err = devm_request_irq(&dev->dev, pdev->irq, gsta_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (err < 0) {
dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
-err);
goto err_free_descs;
return err;
}
err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip);
if (err < 0) {
dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
-err);
goto err_free_irq;
return err;
}
platform_set_drvdata(dev, chip);
return 0;
err_free_irq:
free_irq(pdev->irq, chip);
err_free_descs:
irq_free_descs(chip->irq_base, GSTA_NR_GPIO);
return err;
}
static struct platform_driver sta2x11_gpio_platform_driver = {

Просмотреть файл

@ -485,7 +485,8 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
goto no_irqs;
}
irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0);
irq_base = devm_irq_alloc_descs(&pdev->dev, -1,
0, TWL4030_GPIO_MAX, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
return irq_base;

Просмотреть файл

@ -51,6 +51,8 @@
#define GROUP1_NR_IRQS 6
#define IRQ_MASK_BASE 0x4e19
#define IRQ_STATUS_BASE 0x4e0b
#define GPIO_IRQ0_MASK GENMASK(6, 0)
#define GPIO_IRQ1_MASK GENMASK(5, 0)
#define UPDATE_IRQ_TYPE BIT(0)
#define UPDATE_IRQ_MASK BIT(1)
@ -309,7 +311,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
return IRQ_NONE;
}
pending = p[0] | (p[1] << 8);
pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
if (!pending)
return IRQ_NONE;
@ -317,7 +319,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
while (pending) {
/* One iteration is for all pending bits */
for_each_set_bit(gpio, (const unsigned long *)&pending,
GROUP0_NR_IRQS) {
WCOVE_GPIO_NUM) {
offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
BIT(gpio);
@ -333,7 +335,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
break;
}
pending = p[0] | (p[1] << 8);
pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
}
return IRQ_HANDLED;

Просмотреть файл

@ -51,7 +51,7 @@ struct ws16c48_gpio {
struct gpio_chip chip;
unsigned char io_state[6];
unsigned char out_state[6];
spinlock_t lock;
raw_spinlock_t lock;
unsigned long irq_mask;
unsigned long flow_mask;
unsigned base;
@ -73,13 +73,13 @@ static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
const unsigned mask = BIT(offset % 8);
unsigned long flags;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
ws16c48gpio->io_state[port] |= mask;
ws16c48gpio->out_state[port] &= ~mask;
outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return 0;
}
@ -92,7 +92,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
const unsigned mask = BIT(offset % 8);
unsigned long flags;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
ws16c48gpio->io_state[port] &= ~mask;
if (value)
@ -101,7 +101,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
ws16c48gpio->out_state[port] &= ~mask;
outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return 0;
}
@ -114,17 +114,17 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset)
unsigned long flags;
unsigned port_state;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
/* ensure that GPIO is set for input */
if (!(ws16c48gpio->io_state[port] & mask)) {
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return -EINVAL;
}
port_state = inb(ws16c48gpio->base + port);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return !!(port_state & mask);
}
@ -136,11 +136,11 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
const unsigned mask = BIT(offset % 8);
unsigned long flags;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
/* ensure that GPIO is set for output */
if (ws16c48gpio->io_state[port] & mask) {
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return;
}
@ -150,7 +150,7 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
ws16c48gpio->out_state[port] &= ~mask;
outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
}
static void ws16c48_gpio_set_multiple(struct gpio_chip *chip,
@ -178,14 +178,14 @@ static void ws16c48_gpio_set_multiple(struct gpio_chip *chip,
iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
bitmask = iomask & bits[BIT_WORD(i)];
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
/* update output state data and set device gpio register */
ws16c48gpio->out_state[port] &= ~iomask;
ws16c48gpio->out_state[port] |= bitmask;
outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
/* prepare for next gpio register set */
mask[BIT_WORD(i)] >>= gpio_reg_size;
@ -207,7 +207,7 @@ static void ws16c48_irq_ack(struct irq_data *data)
if (port > 2)
return;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
port_state = ws16c48gpio->irq_mask >> (8*port);
@ -216,7 +216,7 @@ static void ws16c48_irq_ack(struct irq_data *data)
outb(port_state | mask, ws16c48gpio->base + 8 + port);
outb(0xC0, ws16c48gpio->base + 7);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
}
static void ws16c48_irq_mask(struct irq_data *data)
@ -232,7 +232,7 @@ static void ws16c48_irq_mask(struct irq_data *data)
if (port > 2)
return;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
ws16c48gpio->irq_mask &= ~mask;
@ -240,7 +240,7 @@ static void ws16c48_irq_mask(struct irq_data *data)
outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
outb(0xC0, ws16c48gpio->base + 7);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
}
static void ws16c48_irq_unmask(struct irq_data *data)
@ -256,7 +256,7 @@ static void ws16c48_irq_unmask(struct irq_data *data)
if (port > 2)
return;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
ws16c48gpio->irq_mask |= mask;
@ -264,7 +264,7 @@ static void ws16c48_irq_unmask(struct irq_data *data)
outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
outb(0xC0, ws16c48gpio->base + 7);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
}
static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
@ -280,7 +280,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
if (port > 2)
return -EINVAL;
spin_lock_irqsave(&ws16c48gpio->lock, flags);
raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
switch (flow_type) {
case IRQ_TYPE_NONE:
@ -292,7 +292,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
ws16c48gpio->flow_mask &= ~mask;
break;
default:
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return -EINVAL;
}
@ -300,7 +300,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port);
outb(0xC0, ws16c48gpio->base + 7);
spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
return 0;
}
@ -387,7 +387,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
ws16c48gpio->base = base[id];
spin_lock_init(&ws16c48gpio->lock);
raw_spin_lock_init(&ws16c48gpio->lock);
err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
if (err) {

Просмотреть файл

@ -404,7 +404,9 @@ static int xlp_gpio_probe(struct platform_device *pdev)
/* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */
if (soc_type != GPIO_VARIANT_VULCAN) {
irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
irq_base = devm_irq_alloc_descs(&pdev->dev, -1,
XLP_GPIO_IRQ_BASE,
gc->ngpio, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
return irq_base;
@ -415,7 +417,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
err = gpiochip_add_data(gc, priv);
if (err < 0)
goto out_free_desc;
return err;
err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
handle_level_irq, IRQ_TYPE_NONE);
@ -433,14 +435,13 @@ static int xlp_gpio_probe(struct platform_device *pdev)
out_gpio_remove:
gpiochip_remove(gc);
out_free_desc:
irq_free_descs(irq_base, gc->ngpio);
return err;
}
#ifdef CONFIG_ACPI
static const struct acpi_device_id xlp_gpio_acpi_match[] = {
{ "BRCM9006", GPIO_VARIANT_VULCAN },
{ "CAV9006", GPIO_VARIANT_VULCAN },
{},
};
MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);

Просмотреть файл

@ -41,7 +41,7 @@
#define ZX_GPIO_NR 16
struct zx_gpio {
spinlock_t lock;
raw_spinlock_t lock;
void __iomem *base;
struct gpio_chip gc;
@ -56,11 +56,11 @@ static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
if (offset >= gc->ngpio)
return -EINVAL;
spin_lock_irqsave(&chip->lock, flags);
raw_spin_lock_irqsave(&chip->lock, flags);
gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
gpiodir &= ~BIT(offset);
writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
spin_unlock_irqrestore(&chip->lock, flags);
raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@ -75,7 +75,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
if (offset >= gc->ngpio)
return -EINVAL;
spin_lock_irqsave(&chip->lock, flags);
raw_spin_lock_irqsave(&chip->lock, flags);
gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
gpiodir |= BIT(offset);
writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
@ -84,7 +84,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1);
else
writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
spin_unlock_irqrestore(&chip->lock, flags);
raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@ -118,7 +118,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
if (offset < 0 || offset >= ZX_GPIO_NR)
return -EINVAL;
spin_lock_irqsave(&chip->lock, flags);
raw_spin_lock_irqsave(&chip->lock, flags);
gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV);
gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE);
@ -151,7 +151,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
writew_relaxed(gpioi_epos, chip->base + ZX_GPIO_IEP);
writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN);
writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV);
spin_unlock_irqrestore(&chip->lock, flags);
raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@ -184,12 +184,12 @@ static void zx_irq_mask(struct irq_data *d)
u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
u16 gpioie;
spin_lock(&chip->lock);
raw_spin_lock(&chip->lock);
gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask;
writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask;
writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
spin_unlock(&chip->lock);
raw_spin_unlock(&chip->lock);
}
static void zx_irq_unmask(struct irq_data *d)
@ -199,12 +199,12 @@ static void zx_irq_unmask(struct irq_data *d)
u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
u16 gpioie;
spin_lock(&chip->lock);
raw_spin_lock(&chip->lock);
gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask;
writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask;
writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
spin_unlock(&chip->lock);
raw_spin_unlock(&chip->lock);
}
static struct irq_chip zx_irqchip = {
@ -230,7 +230,7 @@ static int zx_gpio_probe(struct platform_device *pdev)
if (IS_ERR(chip->base))
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
raw_spin_lock_init(&chip->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
chip->gc.request = gpiochip_generic_request;
chip->gc.free = gpiochip_generic_free;

Просмотреть файл

@ -368,6 +368,37 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev,
}
EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res)
{
acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev));
}
int devm_acpi_dev_add_driver_gpios(struct device *dev,
const struct acpi_gpio_mapping *gpios)
{
void *res;
int ret;
res = devres_alloc(devm_acpi_dev_release_driver_gpios, 0, GFP_KERNEL);
if (!res)
return -ENOMEM;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), gpios);
if (ret) {
devres_free(res);
return ret;
}
devres_add(dev, res);
return 0;
}
EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios);
void devm_acpi_dev_remove_driver_gpios(struct device *dev)
{
WARN_ON(devres_release(dev, devm_acpi_dev_release_driver_gpios, NULL, NULL));
}
EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
const char *name, int index,
struct acpi_reference_args *args)
@ -661,20 +692,24 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
{
int idx, i;
unsigned int irq_flags;
int ret = -ENOENT;
for (i = 0, idx = 0; idx <= index; i++) {
struct acpi_gpio_info info;
struct gpio_desc *desc;
desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
if (IS_ERR(desc)) {
ret = PTR_ERR(desc);
break;
}
if (info.gpioint && idx++ == index) {
int irq = gpiod_to_irq(desc);
/* Ignore -EPROBE_DEFER, it only matters if idx matches */
if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
return PTR_ERR(desc);
if (info.gpioint && idx++ == index) {
int irq;
if (IS_ERR(desc))
return PTR_ERR(desc);
irq = gpiod_to_irq(desc);
if (irq < 0)
return irq;
@ -690,7 +725,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
}
}
return ret;
return -ENOENT;
}
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
@ -1075,7 +1110,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
break;
}
}
if (count >= 0)
if (count > 0)
break;
}
@ -1091,7 +1126,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
if (crs_count > 0)
count = crs_count;
}
return count;
return count ? count : -ENOENT;
}
struct acpi_crs_lookup {

Просмотреть файл

@ -147,7 +147,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
*flags |= GPIO_ACTIVE_LOW;
if (of_flags & OF_GPIO_SINGLE_ENDED) {
if (of_flags & OF_GPIO_ACTIVE_LOW)
if (of_flags & OF_GPIO_OPEN_DRAIN)
*flags |= GPIO_OPEN_DRAIN;
else
*flags |= GPIO_OPEN_SOURCE;

Просмотреть файл

@ -1522,7 +1522,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
*/
static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
unsigned int parent_irq,
irq_flow_handler_t parent_handler)
{
unsigned int offset;
@ -1571,7 +1571,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
*/
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
unsigned int parent_irq,
irq_flow_handler_t parent_handler)
{
gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
@ -1588,7 +1588,7 @@ EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
*/
void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq)
unsigned int parent_irq)
{
if (!gpiochip->irq_nested) {
chip_err(gpiochip, "tried to nest a chained gpiochip\n");
@ -3122,10 +3122,10 @@ static int dt_gpio_count(struct device *dev, const char *con_id)
gpio_suffixes[i]);
ret = of_gpio_named_count(dev->of_node, propname);
if (ret >= 0)
if (ret > 0)
break;
}
return ret;
return ret ? ret : -ENOENT;
}
static int platform_gpio_count(struct device *dev, const char *con_id)
@ -3326,7 +3326,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
* underlying firmware interface and then makes sure that the GPIO
* descriptor is requested before it is returned to the caller.
*
* On successfull request the GPIO pin is configured in accordance with
* On successful request the GPIO pin is configured in accordance with
* provided @dflags.
*
* In case of error an ERR_PTR() is returned.
@ -3340,6 +3340,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
unsigned long lflags = 0;
bool active_low = false;
bool single_ended = false;
bool open_drain = false;
int ret;
if (!fwnode)
@ -3353,6 +3354,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (!IS_ERR(desc)) {
active_low = flags & OF_GPIO_ACTIVE_LOW;
single_ended = flags & OF_GPIO_SINGLE_ENDED;
open_drain = flags & OF_GPIO_OPEN_DRAIN;
}
} else if (is_acpi_node(fwnode)) {
struct acpi_gpio_info info;
@ -3373,7 +3375,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
lflags |= GPIO_ACTIVE_LOW;
if (single_ended) {
if (active_low)
if (open_drain)
lflags |= GPIO_OPEN_DRAIN;
else
lflags |= GPIO_OPEN_SOURCE;

Просмотреть файл

@ -320,9 +320,10 @@ static int soc_button_probe(struct platform_device *pdev)
button_info = (struct soc_button_info *)id->driver_data;
}
if (gpiod_count(dev, NULL) <= 0) {
error = gpiod_count(dev, NULL);
if (error < 0) {
dev_dbg(dev, "no GPIO attached, ignoring...\n");
return -ENODEV;
return error;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

Просмотреть файл

@ -196,9 +196,10 @@ static int surface3_button_probe(struct i2c_client *client,
strlen(SURFACE_BUTTON_OBJ_NAME)))
return -ENODEV;
if (gpiod_count(dev, KBUILD_MODNAME) <= 0) {
error = gpiod_count(dev, NULL);
if (error < 0) {
dev_dbg(dev, "no GPIO attached, ignoring...\n");
return -ENODEV;
return error;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

Просмотреть файл

@ -125,8 +125,10 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
struct gpio_desc *gpio;
acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
ret = devm_acpi_dev_add_driver_gpios(&pdev->dev,
acpi_dwc3_byt_gpios);
if (ret)
dev_dbg(&pdev->dev, "failed to add mapping table\n");
/*
* These GPIOs will turn on the USB2 PHY. Note that we have to
@ -242,7 +244,6 @@ static void dwc3_pci_remove(struct pci_dev *pci)
device_init_wakeup(&pci->dev, false);
pm_runtime_get(&pci->dev);
acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
platform_device_unregister(dwc->dwc3);
}

Просмотреть файл

@ -17,11 +17,15 @@
#define GPIO_PUSH_PULL 0
#define GPIO_SINGLE_ENDED 2
/* Bit 2 express Open drain or open source */
#define GPIO_LINE_OPEN_SOURCE 0
#define GPIO_LINE_OPEN_DRAIN 4
/*
* Open Drain/Collector is the combination of single-ended active low,
* Open Source/Emitter is the combination of single-ended active high.
* Open Drain/Collector is the combination of single-ended open drain interface.
* Open Source/Emitter is the combination of single-ended open source interface.
*/
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH)
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE)
#endif

Просмотреть файл

@ -957,6 +957,10 @@ static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
adev->driver_gpios = NULL;
}
int devm_acpi_dev_add_driver_gpios(struct device *dev,
const struct acpi_gpio_mapping *gpios);
void devm_acpi_dev_remove_driver_gpios(struct device *dev);
int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);
#else
static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
@ -966,6 +970,13 @@ static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
}
static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
const struct acpi_gpio_mapping *gpios)
{
return -ENXIO;
}
static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {}
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
{
return -ENXIO;

Просмотреть файл

@ -170,14 +170,14 @@ static inline struct gpio_desc *__must_check
gpiod_get_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline struct gpio_desc *__must_check
gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline struct gpio_descs *__must_check
@ -191,7 +191,7 @@ static inline struct gpio_descs *__must_check
gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline void gpiod_put(struct gpio_desc *desc)
@ -231,14 +231,14 @@ static inline struct gpio_desc *__must_check
devm_gpiod_get_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline struct gpio_desc *__must_check
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline struct gpio_descs *__must_check
@ -252,7 +252,7 @@ static inline struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
return NULL;
}
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)

Просмотреть файл

@ -168,7 +168,7 @@ struct gpio_chip {
unsigned int irq_base;
irq_flow_handler_t irq_handler;
unsigned int irq_default_type;
int irq_chained_parent;
unsigned int irq_chained_parent;
bool irq_nested;
bool irq_need_valid_mask;
unsigned long *irq_valid_mask;
@ -244,12 +244,12 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq,
unsigned int parent_irq,
irq_flow_handler_t parent_handler);
void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,
int parent_irq);
unsigned int parent_irq);
int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
struct irq_chip *irqchip,

Просмотреть файл

@ -0,0 +1,13 @@
#ifndef GPIO_REG_H
#define GPIO_REG_H
struct device;
struct irq_domain;
struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg,
int base, int num, const char *label, u32 direction, u32 def_out,
const char *const *names, struct irq_domain *irqdom, const int *irqs);
int gpio_reg_resume(struct gpio_chip *gc);
#endif

Просмотреть файл

@ -30,6 +30,7 @@ struct device_node;
enum of_gpio_flags {
OF_GPIO_ACTIVE_LOW = 0x1,
OF_GPIO_SINGLE_ENDED = 0x2,
OF_GPIO_OPEN_DRAIN = 0x4,
};
#ifdef CONFIG_OF_GPIO