Merge tag 'gpio-updates-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:
 "We have a lot of code refactoring using common helpers and ended up
  removing more lines then we're adding this release cycle.

  Nothing really stands out, just small updates all over the place.

  Core GPIOLIB updates:
   - wake-up poll() in user-space on device unbind
   - improve fwnode usage
   - interrupt domain handling improvements
   - correctly handle the ngpios property in gpio-mmio

  Driver cleanups:
   - remove unneeded calls to platform_set_drvdata() all around the
     place
   - remove unneeded of_match_ptr() expansions whenever a driver depends
     on CONFIG_OF
   - remove redundant calls to dev_err_probe() from gpio-omap and
     gpio-davinci

  Driver improvements:
   - use autopointers and guards from cleanup.h in gpio-sim
   - shrink code in gpio-sim using some common helpers
   - convert the idio family of drivers to using gpio-regmap
   - convert gpio-ws16c48 to using gpio-regmap
   - use devres to simplify code in gpio-pisosr and gpio-mxc
   - update gpio-sifive: support IRQ wake, improve interrupt handling,
     allow building as module
   - make gpio-ge and gpio-bcm-kona OF-independent (plus some minor
     tweaks)
   - add support for new models in gpio-pca953x and gpio-ds4520
   - add runtime PM support to gpio-mxc
   - fix a build warning in gpio-mxs
   - add support for adding pin ranges to gpio-mlxbf3
   - add counter/timer support to gpio-104-dio-48e
   - switch to dynamic GPIO base allocation in gpio-vf610
   - minor oneliners here and there

  Device-tree bindings updates:
   - enable the gpio-line-names property in snps,dw-apb and STMPE GPIO
   - document new models in fsl-imx-gpio, ds4520 and pca95xx
   - convert the bindings for brcm,kona-gpio to YAML"

* tag 'gpio-updates-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (94 commits)
  gpio: pca953x: add support for TCA9538
  dt-bindings: gpio: pca95xx: document new tca9538 chip
  gpio: pca953x: Use i2c_get_match_data()
  gpio: mlxbf3: use capital "OR" for multiple licenses in SPDX
  gpio: pcf857x: Extend match data support for OF tables
  gpio: vf610: switch to dynamic allocat GPIO base
  gpiolib: provide and use gpiod_line_state_notify()
  gpio: cdev: wake up lineevent poll() on device unbind
  gpio: cdev: wake up linereq poll() on device unbind
  gpio: cdev: wake up chardev poll() on device unbind
  gpiolib: add a second blocking notifier to struct gpio_device
  gpio: cdev: open-code to_gpio_chardev_data()
  gpiolib: rename the gpio_device notifier
  gpio: mlxbf3: Support add_pin_ranges()
  gpio: mxc: Use helper function devm_clk_get_optional_enabled()
  gpio: pca9570: fix kerneldoc
  gpio: sim: simplify code with cleanup helpers
  gpio: sim: replace memmove() + strstrip() with skip_spaces() + strim()
  gpio: sim: simplify gpio_sim_device_config_live_store()
  gpio: mxc: release the parent IRQ in runtime suspend
  ...
This commit is contained in:
Linus Torvalds
2023-08-29 10:21:56 -07:00
88 changed files with 1668 additions and 2068 deletions
@@ -0,0 +1,51 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/adi,ds4520-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: DS4520 I2C GPIO expander
maintainers:
- Okan Sahin <okan.sahin@analog.com>
properties:
compatible:
enum:
- adi,ds4520-gpio
reg:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 2
ngpios:
minimum: 1
maximum: 9
required:
- compatible
- reg
- gpio-controller
- "#gpio-cells"
- ngpios
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
gpio@50 {
compatible = "adi,ds4520-gpio";
reg = <0x50>;
ngpios = <9>;
gpio-controller;
#gpio-cells = <2>;
};
};
@@ -1,52 +0,0 @@
Broadcom Kona Family GPIO
=========================
This GPIO driver is used in the following Broadcom SoCs:
BCM11130, BCM11140, BCM11351, BCM28145, BCM28155
The Broadcom GPIO Controller IP can be configured prior to synthesis to
support up to 8 banks of 32 GPIOs where each bank has its own IRQ. The
GPIO controller only supports edge, not level, triggering of interrupts.
Required properties
-------------------
- compatible: "brcm,bcm11351-gpio", "brcm,kona-gpio"
- reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt outputs from the controller. There is one GPIO
interrupt per GPIO bank. The number of interrupts listed depends on the
number of GPIO banks on the SoC. The interrupts must be ordered by bank,
starting with bank 0. There is always a 1:1 mapping between banks and
IRQs.
- #gpio-cells: Should be <2>. The first cell is the pin number, the second
cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
See also "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
- #interrupt-cells: Should be <2>. The first cell is the GPIO number. The
second cell is used to specify flags. The following subset of flags is
supported:
- trigger type (bits[1:0]):
1 = low-to-high edge triggered.
2 = high-to-low edge triggered.
3 = low-to-high or high-to-low edge triggered
Valid values are 1, 2, 3
See also .../devicetree/bindings/interrupt-controller/interrupts.txt.
- gpio-controller: Marks the device node as a GPIO controller.
- interrupt-controller: Marks the device node as an interrupt controller.
Example:
gpio: gpio@35003000 {
compatible = "brcm,bcm11351-gpio", "brcm,kona-gpio";
reg = <0x35003000 0x800>;
interrupts =
<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
#interrupt-cells = <2>;
gpio-controller;
interrupt-controller;
};
@@ -0,0 +1,100 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/brcm,kona-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom Kona family GPIO controller
description:
The Broadcom GPIO Controller IP can be configured prior to synthesis to
support up to 8 banks of 32 GPIOs where each bank has its own IRQ. The
GPIO controller only supports edge, not level, triggering of interrupts.
maintainers:
- Ray Jui <rjui@broadcom.com>
properties:
compatible:
items:
- enum:
- brcm,bcm11351-gpio
- brcm,bcm21664-gpio
- brcm,bcm23550-gpio
- const: brcm,kona-gpio
reg:
maxItems: 1
interrupts:
minItems: 4
maxItems: 6
description:
The interrupt outputs from the controller. There is one GPIO interrupt
per GPIO bank. The number of interrupts listed depends on the number of
GPIO banks on the SoC. The interrupts must be ordered by bank, starting
with bank 0. There is always a 1:1 mapping between banks and IRQs.
'#gpio-cells':
const: 2
'#interrupt-cells':
const: 2
gpio-controller: true
interrupt-controller: true
required:
- compatible
- reg
- interrupts
- '#gpio-cells'
- '#interrupt-cells'
- gpio-controller
- interrupt-controller
allOf:
- if:
properties:
compatible:
contains:
const: brcm,bcm11351-gpio
then:
properties:
interrupts:
minItems: 6
- if:
properties:
compatible:
contains:
enum:
- brcm,bcm21664-gpio
- brcm,bcm23550-gpio
then:
properties:
interrupts:
maxItems: 4
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
gpio@35003000 {
compatible = "brcm,bcm11351-gpio", "brcm,kona-gpio";
reg = <0x35003000 0x800>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
#interrupt-cells = <2>;
gpio-controller;
interrupt-controller;
};
...
@@ -32,10 +32,12 @@ properties:
- fsl,imx6sx-gpio
- fsl,imx6ul-gpio
- fsl,imx7d-gpio
- fsl,imx8dxl-gpio
- fsl,imx8mm-gpio
- fsl,imx8mn-gpio
- fsl,imx8mp-gpio
- fsl,imx8mq-gpio
- fsl,imx8qm-gpio
- fsl,imx8qxp-gpio
- fsl,imxrt1050-gpio
- fsl,imxrt1170-gpio
@@ -66,6 +66,7 @@ properties:
- ti,tca6408
- ti,tca6416
- ti,tca6424
- ti,tca9538
- ti,tca9539
- ti,tca9554
@@ -61,6 +61,10 @@ patternProperties:
'#gpio-cells':
const: 2
gpio-line-names:
minItems: 1
maxItems: 32
ngpios:
default: 32
minimum: 1
@@ -28,6 +28,10 @@ properties:
gpio-controller: true
gpio-line-names:
minItems: 1
maxItems: 24
interrupt-controller: true
st,norequest-mask:
+1 -1
View File
@@ -4195,7 +4195,7 @@ BROADCOM KONA GPIO DRIVER
M: Ray Jui <rjui@broadcom.com>
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
S: Supported
F: Documentation/devicetree/bindings/gpio/brcm,kona-gpio.txt
F: Documentation/devicetree/bindings/gpio/brcm,kona-gpio.yaml
F: drivers/gpio/gpio-bcm-kona.c
BROADCOM MPI3 STORAGE CONTROLLER DRIVER
+26 -5
View File
@@ -111,6 +111,9 @@ config GPIO_MAX730X
config GPIO_IDIO_16
tristate
select REGMAP_IRQ
select GPIOLIB_IRQCHIP
select GPIO_REGMAP
help
Enables support for the idio-16 library functions. The idio-16 library
provides functions to facilitate communication with devices within the
@@ -191,7 +194,7 @@ config GPIO_RASPBERRYPI_EXP
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
depends on ARCH_BCM_MOBILE || COMPILE_TEST
help
Turn on GPIO support for Broadcom "Kona" chips.
@@ -283,7 +286,7 @@ config GPIO_EXAR
config GPIO_GE_FPGA
bool "GE FPGA based GPIO"
depends on GE_FPGA
depends on GE_FPGA || COMPILE_TEST
select GPIO_GENERIC
help
Support for common GPIO functionality provided on some GE Single Board
@@ -564,7 +567,7 @@ config GPIO_SAMA5D2_PIOBU
maintain their value during backup/self-refresh.
config GPIO_SIFIVE
bool "SiFive GPIO support"
tristate "SiFive GPIO support"
depends on OF_GPIO
select IRQ_DOMAIN_HIERARCHY
select GPIO_GENERIC
@@ -858,6 +861,7 @@ config GPIO_104_DIO_48E
select REGMAP_IRQ
select GPIOLIB_IRQCHIP
select GPIO_I8255
select I8254
help
Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
104-DIO-24E). The base port addresses for the devices may be
@@ -868,7 +872,7 @@ config GPIO_104_IDIO_16
tristate "ACCES 104-IDIO-16 GPIO support"
depends on PC104
select ISA_BUS_API
select GPIOLIB_IRQCHIP
select REGMAP_MMIO
select GPIO_IDIO_16
help
Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
@@ -994,7 +998,10 @@ config GPIO_WINBOND
config GPIO_WS16C48
tristate "WinSystems WS16C48 GPIO support"
select ISA_BUS_API
select REGMAP_IRQ
select REGMAP_MMIO
select GPIOLIB_IRQCHIP
select GPIO_REGMAP
help
Enables GPIO support for the WinSystems WS16C48. The base port
addresses for the devices may be configured via the base module
@@ -1028,6 +1035,17 @@ config GPIO_FXL6408
To compile this driver as a module, choose M here: the module will
be called gpio-fxl6408.
config GPIO_DS4520
tristate "DS4520 I2C GPIO expander"
select REGMAP_I2C
select GPIO_REGMAP
help
GPIO driver for ADI DS4520 I2C-based GPIO expander.
Say yes here to enable the GPIO driver for the ADI DS4520 chip.
To compile this driver as a module, choose M here: the module will
be called gpio-ds4520.
config GPIO_GW_PLD
tristate "Gateworks PLD GPIO Expander"
depends on OF_GPIO
@@ -1640,7 +1658,7 @@ config GPIO_PCH
config GPIO_PCI_IDIO_16
tristate "ACCES PCI-IDIO-16 GPIO support"
select GPIOLIB_IRQCHIP
select REGMAP_MMIO
select GPIO_IDIO_16
help
Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is
@@ -1650,7 +1668,10 @@ config GPIO_PCI_IDIO_16
config GPIO_PCIE_IDIO_24
tristate "ACCES PCIe-IDIO-24 GPIO support"
select REGMAP_IRQ
select REGMAP_MMIO
select GPIOLIB_IRQCHIP
select GPIO_REGMAP
help
Enables GPIO support for the ACCES PCIe-IDIO-24 family (PCIe-IDIO-24,
PCIe-IDI-24, PCIe-IDO-24, PCIe-IDIO-12). An interrupt is generated
+1
View File
@@ -52,6 +52,7 @@ obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o
obj-$(CONFIG_GPIO_DS4520) += gpio-ds4520.o
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o
obj-$(CONFIG_GPIO_ELKHARTLAKE) += gpio-elkhartlake.o
+111 -16
View File
@@ -9,6 +9,7 @@
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i8254.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/isa.h>
@@ -16,6 +17,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/regmap.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include "gpio-i8255.h"
@@ -37,6 +39,8 @@ MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
#define DIO48E_ENABLE_INTERRUPT 0xB
#define DIO48E_DISABLE_INTERRUPT DIO48E_ENABLE_INTERRUPT
#define DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING 0xD
#define DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING
#define DIO48E_CLEAR_INTERRUPT 0xF
#define DIO48E_NUM_PPI 2
@@ -75,18 +79,20 @@ static const struct regmap_access_table dio48e_precious_table = {
.yes_ranges = dio48e_precious_ranges,
.n_yes_ranges = ARRAY_SIZE(dio48e_precious_ranges),
};
static const struct regmap_config dio48e_regmap_config = {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.io_port = true,
.max_register = 0xF,
.wr_table = &dio48e_wr_table,
.rd_table = &dio48e_rd_table,
.volatile_table = &dio48e_volatile_table,
.precious_table = &dio48e_precious_table,
.cache_type = REGCACHE_FLAT,
.use_raw_spinlock = true,
static const struct regmap_range pit_wr_ranges[] = {
regmap_reg_range(0x0, 0x3),
};
static const struct regmap_range pit_rd_ranges[] = {
regmap_reg_range(0x0, 0x2),
};
static const struct regmap_access_table pit_wr_table = {
.yes_ranges = pit_wr_ranges,
.n_yes_ranges = ARRAY_SIZE(pit_wr_ranges),
};
static const struct regmap_access_table pit_rd_table = {
.yes_ranges = pit_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(pit_rd_ranges),
};
/* only bit 3 on each respective Port C supports interrupts */
@@ -102,14 +108,56 @@ static const struct regmap_irq dio48e_regmap_irqs[] = {
/**
* struct dio48e_gpio - GPIO device private data structure
* @lock: synchronization lock to prevent I/O race conditions
* @map: Regmap for the device
* @regs: virtual mapping for device registers
* @flags: IRQ flags saved during locking
* @irq_mask: Current IRQ mask state on the device
*/
struct dio48e_gpio {
raw_spinlock_t lock;
struct regmap *map;
void __iomem *regs;
unsigned long flags;
unsigned int irq_mask;
};
static void dio48e_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
{
struct dio48e_gpio *const dio48egpio = lock_arg;
unsigned long flags;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
dio48egpio->flags = flags;
}
static void dio48e_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
{
struct dio48e_gpio *const dio48egpio = lock_arg;
raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
}
static void pit_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
{
struct dio48e_gpio *const dio48egpio = lock_arg;
unsigned long flags;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
dio48egpio->flags = flags;
iowrite8(0x00, dio48egpio->regs + DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING);
}
static void pit_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
{
struct dio48e_gpio *const dio48egpio = lock_arg;
ioread8(dio48egpio->regs + DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING);
raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
}
static int dio48e_handle_mask_sync(const int index,
const unsigned int mask_buf_def,
const unsigned int mask_buf,
@@ -176,6 +224,9 @@ static int dio48e_probe(struct device *dev, unsigned int id)
struct i8255_regmap_config config = {};
void __iomem *regs;
struct regmap *map;
struct regmap_config dio48e_regmap_config;
struct regmap_config pit_regmap_config;
struct i8254_regmap_config pit_config;
int err;
struct regmap_irq_chip *chip;
struct dio48e_gpio *dio48egpio;
@@ -187,21 +238,58 @@ static int dio48e_probe(struct device *dev, unsigned int id)
return -EBUSY;
}
dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
if (!dio48egpio)
return -ENOMEM;
regs = devm_ioport_map(dev, base[id], DIO48E_EXTENT);
if (!regs)
return -ENOMEM;
dio48egpio->regs = regs;
raw_spin_lock_init(&dio48egpio->lock);
dio48e_regmap_config = (struct regmap_config) {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.lock = dio48e_regmap_lock,
.unlock = dio48e_regmap_unlock,
.lock_arg = dio48egpio,
.io_port = true,
.wr_table = &dio48e_wr_table,
.rd_table = &dio48e_rd_table,
.volatile_table = &dio48e_volatile_table,
.precious_table = &dio48e_precious_table,
.cache_type = REGCACHE_FLAT,
};
map = devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config);
if (IS_ERR(map))
return dev_err_probe(dev, PTR_ERR(map),
"Unable to initialize register map\n");
dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
if (!dio48egpio)
return -ENOMEM;
dio48egpio->map = map;
pit_regmap_config = (struct regmap_config) {
.name = "i8254",
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.lock = pit_regmap_lock,
.unlock = pit_regmap_unlock,
.lock_arg = dio48egpio,
.io_port = true,
.wr_table = &pit_wr_table,
.rd_table = &pit_rd_table,
};
pit_config.map = devm_regmap_init_mmio(dev, regs, &pit_regmap_config);
if (IS_ERR(pit_config.map))
return dev_err_probe(dev, PTR_ERR(pit_config.map),
"Unable to initialize i8254 register map\n");
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
@@ -225,6 +313,12 @@ static int dio48e_probe(struct device *dev, unsigned int id)
if (err)
return dev_err_probe(dev, err, "IRQ registration failed\n");
pit_config.parent = dev;
err = devm_i8254_regmap_register(dev, &pit_config);
if (err)
return err;
config.parent = dev;
config.map = map;
config.num_ppi = DIO48E_NUM_PPI;
@@ -245,3 +339,4 @@ module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(I8254);
+63 -223
View File
@@ -6,19 +6,16 @@
* This driver supports the following ACCES devices: 104-IDIO-16,
* 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
*/
#include <linux/bitmap.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
#include <linux/irq.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include "gpio-idio-16.h"
@@ -36,187 +33,62 @@ static unsigned int num_irq;
module_param_hw_array(irq, uint, irq, &num_irq, 0);
MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
/**
* struct idio_16_gpio - GPIO device private data structure
* @chip: instance of the gpio_chip
* @lock: synchronization lock to prevent I/O race conditions
* @irq_mask: I/O bits affected by interrupts
* @reg: I/O address offset for the device registers
* @state: ACCES IDIO-16 device state
*/
struct idio_16_gpio {
struct gpio_chip chip;
raw_spinlock_t lock;
unsigned long irq_mask;
struct idio_16 __iomem *reg;
struct idio_16_state state;
static const struct regmap_range idio_16_wr_ranges[] = {
regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x4),
};
static const struct regmap_range idio_16_rd_ranges[] = {
regmap_reg_range(0x1, 0x2), regmap_reg_range(0x5, 0x5),
};
static const struct regmap_range idio_16_precious_ranges[] = {
regmap_reg_range(0x2, 0x2),
};
static const struct regmap_access_table idio_16_wr_table = {
.yes_ranges = idio_16_wr_ranges,
.n_yes_ranges = ARRAY_SIZE(idio_16_wr_ranges),
};
static const struct regmap_access_table idio_16_rd_table = {
.yes_ranges = idio_16_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(idio_16_rd_ranges),
};
static const struct regmap_access_table idio_16_precious_table = {
.yes_ranges = idio_16_precious_ranges,
.n_yes_ranges = ARRAY_SIZE(idio_16_precious_ranges),
};
static const struct regmap_config idio_16_regmap_config = {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
.io_port = true,
.wr_table = &idio_16_wr_table,
.rd_table = &idio_16_rd_table,
.volatile_table = &idio_16_rd_table,
.precious_table = &idio_16_precious_table,
.cache_type = REGCACHE_FLAT,
.use_raw_spinlock = true,
};
static int idio_16_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
if (idio_16_get_direction(offset))
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
}
static int idio_16_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
return 0;
}
static int idio_16_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
chip->set(chip, offset, value);
return 0;
}
static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
}
static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
return 0;
}
static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value);
}
static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
}
static void idio_16_irq_ack(struct irq_data *data)
{
}
static void idio_16_irq_mask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
const unsigned long offset = irqd_to_hwirq(data);
unsigned long flags;
idio16gpio->irq_mask &= ~BIT(offset);
gpiochip_disable_irq(chip, offset);
if (!idio16gpio->irq_mask) {
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
iowrite8(0, &idio16gpio->reg->irq_ctl);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
/* Only input lines (GPIO 16-31) support interrupts */
#define IDIO_16_REGMAP_IRQ(_id) \
[16 + _id] = { \
.mask = BIT(_id), \
.type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \
}
}
static void idio_16_irq_unmask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
const unsigned long offset = irqd_to_hwirq(data);
const unsigned long prev_irq_mask = idio16gpio->irq_mask;
unsigned long flags;
gpiochip_enable_irq(chip, offset);
idio16gpio->irq_mask |= BIT(offset);
if (!prev_irq_mask) {
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
ioread8(&idio16gpio->reg->irq_ctl);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
}
static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
/* The only valid irq types are none and both-edges */
if (flow_type != IRQ_TYPE_NONE &&
(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
return -EINVAL;
return 0;
}
static const struct irq_chip idio_16_irqchip = {
.name = "104-idio-16",
.irq_ack = idio_16_irq_ack,
.irq_mask = idio_16_irq_mask,
.irq_unmask = idio_16_irq_unmask,
.irq_set_type = idio_16_irq_set_type,
.flags = IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
static const struct regmap_irq idio_16_regmap_irqs[] = {
IDIO_16_REGMAP_IRQ(0), IDIO_16_REGMAP_IRQ(1), IDIO_16_REGMAP_IRQ(2), /* 0-2 */
IDIO_16_REGMAP_IRQ(3), IDIO_16_REGMAP_IRQ(4), IDIO_16_REGMAP_IRQ(5), /* 3-5 */
IDIO_16_REGMAP_IRQ(6), IDIO_16_REGMAP_IRQ(7), IDIO_16_REGMAP_IRQ(8), /* 6-8 */
IDIO_16_REGMAP_IRQ(9), IDIO_16_REGMAP_IRQ(10), IDIO_16_REGMAP_IRQ(11), /* 9-11 */
IDIO_16_REGMAP_IRQ(12), IDIO_16_REGMAP_IRQ(13), IDIO_16_REGMAP_IRQ(14), /* 12-14 */
IDIO_16_REGMAP_IRQ(15), /* 15 */
};
static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
{
struct idio_16_gpio *const idio16gpio = dev_id;
struct gpio_chip *const chip = &idio16gpio->chip;
int gpio;
for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
generic_handle_domain_irq(chip->irq.domain, gpio);
raw_spin_lock(&idio16gpio->lock);
iowrite8(0, &idio16gpio->reg->in0_7);
raw_spin_unlock(&idio16gpio->lock);
return IRQ_HANDLED;
}
#define IDIO_16_NGPIO 32
static const char *idio_16_names[IDIO_16_NGPIO] = {
"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
};
static int idio_16_irq_init_hw(struct gpio_chip *gc)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
/* Disable IRQ by default */
iowrite8(0, &idio16gpio->reg->irq_ctl);
iowrite8(0, &idio16gpio->reg->in0_7);
return 0;
}
static int idio_16_probe(struct device *dev, unsigned int id)
{
struct idio_16_gpio *idio16gpio;
const char *const name = dev_name(dev);
struct gpio_irq_chip *girq;
int err;
idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
if (!idio16gpio)
return -ENOMEM;
struct idio_16_regmap_config config = {};
void __iomem *regs;
struct regmap *map;
if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
@@ -224,54 +96,22 @@ static int idio_16_probe(struct device *dev, unsigned int id)
return -EBUSY;
}
idio16gpio->reg = devm_ioport_map(dev, base[id], IDIO_16_EXTENT);
if (!idio16gpio->reg)
regs = devm_ioport_map(dev, base[id], IDIO_16_EXTENT);
if (!regs)
return -ENOMEM;
idio16gpio->chip.label = name;
idio16gpio->chip.parent = dev;
idio16gpio->chip.owner = THIS_MODULE;
idio16gpio->chip.base = -1;
idio16gpio->chip.ngpio = IDIO_16_NGPIO;
idio16gpio->chip.names = idio_16_names;
idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
map = devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config);
if (IS_ERR(map))
return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register map\n");
idio_16_state_init(&idio16gpio->state);
/* FET off states are represented by bit values of "1" */
bitmap_fill(idio16gpio->state.out_state, IDIO_16_NOUT);
config.parent = dev;
config.map = map;
config.regmap_irqs = idio_16_regmap_irqs;
config.num_regmap_irqs = ARRAY_SIZE(idio_16_regmap_irqs);
config.irq = irq[id];
config.no_status = true;
girq = &idio16gpio->chip.irq;
gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = idio_16_irq_init_hw;
raw_spin_lock_init(&idio16gpio->lock);
err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
}
err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
idio16gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
return err;
}
return 0;
return devm_idio_16_regmap_register(dev, &config);
}
static struct isa_driver idio_16_driver = {
-2
View File
@@ -135,8 +135,6 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev)
priv->gc.ngpio = MMIO_74XX_BIT_CNT(priv->flags);
priv->gc.owner = THIS_MODULE;
platform_set_drvdata(pdev, priv);
return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
}
+2 -1
View File
@@ -9,6 +9,7 @@
#include <linux/gpio/driver.h>
#include <linux/mfd/altera-a10sr.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/property.h>
@@ -104,7 +105,7 @@ static struct platform_driver altr_a10sr_gpio_driver = {
.probe = altr_a10sr_gpio_probe,
.driver = {
.name = "altr_a10sr_gpio",
.of_match_table = of_match_ptr(altr_a10sr_gpio_of_match),
.of_match_table = altr_a10sr_gpio_of_match,
},
};
module_platform_driver(altr_a10sr_gpio_driver);
+2 -1
View File
@@ -9,8 +9,9 @@
*/
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/platform_data/gpio-ath79.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/irq.h>
+8 -16
View File
@@ -8,12 +8,14 @@
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/of_device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#define BCM_GPIO_PASSWD 0x00a5a501
#define GPIO_PER_BANK 32
@@ -62,7 +64,6 @@ struct bcm_kona_gpio {
struct gpio_chip gpio_chip;
struct irq_domain *irq_domain;
struct bcm_kona_gpio_bank *banks;
struct platform_device *pdev;
};
struct bcm_kona_gpio_bank {
@@ -556,19 +557,12 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
static int bcm_kona_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct bcm_kona_gpio_bank *bank;
struct bcm_kona_gpio *kona_gpio;
struct gpio_chip *chip;
int ret;
int i;
match = of_match_device(bcm_kona_gpio_of_match, dev);
if (!match) {
dev_err(dev, "Failed to find gpio controller\n");
return -ENODEV;
}
kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
if (!kona_gpio)
return -ENOMEM;
@@ -596,15 +590,13 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
if (!kona_gpio->banks)
return -ENOMEM;
kona_gpio->pdev = pdev;
platform_set_drvdata(pdev, kona_gpio);
chip->parent = dev;
chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
chip->ngpio,
&bcm_kona_irq_ops,
kona_gpio);
kona_gpio->irq_domain = irq_domain_create_linear(dev_fwnode(dev),
chip->ngpio,
&bcm_kona_irq_ops,
kona_gpio);
if (!kona_gpio->irq_domain) {
dev_err(dev, "Couldn't allocate IRQ domain\n");
return -ENXIO;
+2 -2
View File
@@ -3,12 +3,12 @@
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
enum gio_reg_index {
GIO_REG_ODEN = 0,
+2 -2
View File
@@ -67,7 +67,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev)
return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
}
static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
static const struct of_device_id clps711x_gpio_ids[] = {
{ .compatible = "cirrus,ep7209-gpio" },
{ }
};
@@ -76,7 +76,7 @@ MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
static struct platform_driver clps711x_gpio_driver = {
.driver = {
.name = "clps711x-gpio",
.of_match_table = of_match_ptr(clps711x_gpio_ids),
.of_match_table = clps711x_gpio_ids,
},
.probe = clps711x_gpio_probe,
};
+1 -1
View File
@@ -8,7 +8,7 @@
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#define MAX_GPIO 32
+1 -1
View File
@@ -236,7 +236,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
for (i = 0; i < nirq; i++) {
chips->irqs[i] = platform_get_irq(pdev, i);
if (chips->irqs[i] < 0)
return dev_err_probe(dev, chips->irqs[i], "IRQ not populated\n");
return chips->irqs[i];
}
chips->chip.label = dev_name(dev);

Some files were not shown because too many files have changed in this diff Show More