Commit c0f234ff authored by Linus Torvalds's avatar Linus Torvalds

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

Pull gpio updates from Bartosz Golaszewski:
 "We have a new GPIO multiplexer driver, bunch of driver updates and
  refactoring in the core GPIO library.

  GPIO core:
   - teach gpiolib to work with software nodes for HW description
   - remove ARCH_NR_GPIOS treewide as we no longer impose any limit on
     the number of GPIOS since the allocation became entirely dynamic
   - add support for HW quirks for Cirrus CS42L56 codec, Marvell NFC
     controller, Freescale PCIe and Ethernet controller, Himax LCDs and
     Mediatek mt2701
   - refactor OF quirk code
   - some general refactoring of the OF and ACPI code, adding new
     helpers, minor tweaks and fixes, making fwnode usage consistent
     etc.

  GPIO uAPI:
   - fix an issue where the user-space can trigger a NULL-pointer
     dereference in the kernel by opening a device file, forcing a
     driver unbind and then calling one of the syscalls on the
     associated file descriptor

  New drivers:
   - add gpio-latch: a new GPIO multiplexer based on latches connected
     to other GPIOs

  Driver updates:
   - convert i2c GPIO expanders to using .probe_new()
   - drop the gpio-sta2x11 driver
   - factor out common code for the ACCES IDIO-16 family of controllers
     and use this new library wherever applicable in drivers
   - add DT support to gpio-hisi
   - allow building gpio-davinci as a module and increase its maxItems
     property
   - add support for a new model to gpio-pca9570
   - other minor changes to various drivers"

* tag 'gpio-updates-for-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (66 commits)
  gpio: sim: set a limit on the number of GPIOs
  gpiolib: protect the GPIO device against being dropped while in use by user-space
  gpiolib: cdev: fix NULL-pointer dereferences
  gpiolib: Provide to_gpio_device() helper
  gpiolib: Unify access to the device properties
  gpio: Do not include <linux/kernel.h> when not really needed.
  gpio: pcf857x: Convert to i2c's .probe_new()
  gpio: pca953x: Convert to i2c's .probe_new()
  gpio: max732x: Convert to i2c's .probe_new()
  dt-bindings: gpio: gpio-davinci: Increase maxItems in gpio-line-names
  gpiolib: ensure that fwnode is properly set
  gpio: sl28cpld: Replace irqchip mask_invert with unmask_base
  gpiolib: of: Use correct fwnode for DT-probed chips
  gpiolib: of: Drop redundant check in of_mm_gpiochip_remove()
  gpiolib: of: Prepare of_mm_gpiochip_add_data() for fwnode
  gpiolib: add support for software nodes
  gpiolib: consolidate GPIO lookups
  gpiolib: acpi: avoid leaking ACPI details into upper gpiolib layers
  gpiolib: acpi: teach acpi_find_gpio() to handle data-only nodes
  gpiolib: acpi: change acpi_find_gpio() to accept firmware node
  ...
parents 9fa4abc9 11e47bbd
......@@ -35,7 +35,7 @@ properties:
gpio-line-names:
description: strings describing the names of each gpio line.
minItems: 1
maxItems: 100
maxItems: 144
"#gpio-cells":
const: 2
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/gpio-latch.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPIO latch controller
maintainers:
- Sascha Hauer <s.hauer@pengutronix.de>
description: |
This binding describes a GPIO multiplexer based on latches connected to
other GPIOs, like this:
CLK0 ----------------------. ,--------.
CLK1 -------------------. `--------|> #0 |
| | |
OUT0 ----------------+--|-----------|D0 Q0|-----|<
OUT1 --------------+-|--|-----------|D1 Q1|-----|<
OUT2 ------------+-|-|--|-----------|D2 Q2|-----|<
OUT3 ----------+-|-|-|--|-----------|D3 Q3|-----|<
OUT4 --------+-|-|-|-|--|-----------|D4 Q4|-----|<
OUT5 ------+-|-|-|-|-|--|-----------|D5 Q5|-----|<
OUT6 ----+-|-|-|-|-|-|--|-----------|D6 Q6|-----|<
OUT7 --+-|-|-|-|-|-|-|--|-----------|D7 Q7|-----|<
| | | | | | | | | `--------'
| | | | | | | | |
| | | | | | | | | ,--------.
| | | | | | | | `-----------|> #1 |
| | | | | | | | | |
| | | | | | | `--------------|D0 Q0|-----|<
| | | | | | `----------------|D1 Q1|-----|<
| | | | | `------------------|D2 Q2|-----|<
| | | | `--------------------|D3 Q3|-----|<
| | | `----------------------|D4 Q4|-----|<
| | `------------------------|D5 Q5|-----|<
| `--------------------------|D6 Q6|-----|<
`----------------------------|D7 Q7|-----|<
`--------'
The number of clk-gpios and latched-gpios is not fixed. The actual number
of number of latches and the number of inputs per latch is derived from
the number of GPIOs given in the corresponding device tree properties.
properties:
compatible:
const: gpio-latch
"#gpio-cells":
const: 2
clk-gpios:
description: Array of GPIOs to be used to clock a latch
latched-gpios:
description: Array of GPIOs to be used as inputs per latch
setup-duration-ns:
description: Delay in nanoseconds to wait after the latch inputs have been
set up
clock-duration-ns:
description: Delay in nanoseconds to wait between clock output changes
gpio-controller: true
gpio-line-names: true
required:
- compatible
- "#gpio-cells"
- gpio-controller
- clk-gpios
- latched-gpios
additionalProperties: false
examples:
- |
gpio-latch {
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_di_do_leds>;
compatible = "gpio-latch";
gpio-controller;
setup-duration-ns = <100>;
clock-duration-ns = <100>;
clk-gpios = <&gpio3 7 0>, <&gpio3 8 0>;
latched-gpios = <&gpio3 21 0>, <&gpio3 22 0>,
<&gpio3 23 0>, <&gpio3 24 0>,
<&gpio3 25 0>, <&gpio3 26 0>,
<&gpio3 27 0>, <&gpio3 28 0>;
};
......@@ -12,6 +12,7 @@ maintainers:
properties:
compatible:
enum:
- dlg,slg7xl45106
- nxp,pca9570
- nxp,pca9571
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/hisilicon,ascend910-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HiSilicon common GPIO controller
maintainers:
- Jay Fang <f.fangjian@huawei.com>
description:
The HiSilicon common GPIO controller can be used for many different
types of SoC such as Huawei Ascend AI series chips.
properties:
compatible:
const: hisilicon,ascend910-gpio
reg:
maxItems: 1
interrupts:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 2
ngpios:
minimum: 1
maximum: 32
required:
- compatible
- reg
- interrupts
- gpio-controller
- "#gpio-cells"
- ngpios
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
gpio@840d0000 {
compatible = "hisilicon,ascend910-gpio";
reg = <0x840d0000 0x1000>;
ngpios = <32>;
gpio-controller;
#gpio-cells = <2>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -558,11 +558,6 @@ Platform Support
To force-enable this framework, a platform's Kconfig will "select" GPIOLIB,
else it is up to the user to configure support for GPIO.
It may also provide a custom value for ARCH_NR_GPIOS, so that it better
reflects the number of GPIOs in actual use on that platform, without
wasting static table space. (It should count both built-in/SoC GPIOs and
also ones on GPIO expanders.
If neither of these options are selected, the platform does not support
GPIOs through GPIO-lib and the code cannot be enabled by the user.
......
......@@ -312,6 +312,13 @@ L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/counter/104-quad-8.c
ACCES IDIO-16 GPIO LIBRARY
M: William Breathitt Gray <william.gray@linaro.org>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-idio-16.c
F: drivers/gpio/gpio-idio-16.h
ACCES PCI-IDIO-16 GPIO DRIVER
M: William Breathitt Gray <william.gray@linaro.org>
L: linux-gpio@vger.kernel.org
......@@ -9266,6 +9273,7 @@ HISILICON GPIO DRIVER
M: Jay Fang <f.fangjian@huawei.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/gpio/hisilicon,ascend910-gpio.yaml
F: drivers/gpio/gpio-hisi.c
HISILICON HIGH PERFORMANCE RSA ENGINE DRIVER (HPRE)
......
......@@ -1158,27 +1158,6 @@ config ARM_PSCI
0022A ("Power State Coordination Interface System Software on
ARM processors").
# The GPIO number here must be sorted by descending number. In case of
# a multiplatform kernel, we just want the highest value required by the
# selected platforms.
config ARCH_NR_GPIO
int
default 2048 if ARCH_INTEL_SOCFPGA
default 1024 if ARCH_BRCMSTB || ARCH_RENESAS || ARCH_TEGRA || \
ARCH_ZYNQ || ARCH_ASPEED
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
default 416 if ARCH_SUNXI
default 392 if ARCH_U8500
default 352 if ARCH_VT8500
default 288 if ARCH_ROCKCHIP
default 264 if MACH_H4700
default 0
help
Maximum number of GPIOs in the system.
If unsure, leave the default value.
config HZ_FIXED
int
default 128 if SOC_AT91RM9200
......
......@@ -2,7 +2,6 @@
#ifndef _ARCH_ARM_GPIO_H
#define _ARCH_ARM_GPIO_H
/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
#include <asm-generic/gpio.h>
/* The trivial gpiolib dispatchers */
......
......@@ -2168,18 +2168,6 @@ config STACKPROTECTOR_PER_TASK
def_bool y
depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_SYSREG
# The GPIO number here must be sorted by descending number. In case of
# a multiplatform kernel, we just want the highest value required by the
# selected platforms.
config ARCH_NR_GPIO
int
default 2048 if ARCH_APPLE
default 0
help
Maximum number of GPIOs in the system.
If unsure, leave the default value.
config UNWIND_PATCH_PAC_INTO_SCS
bool "Enable shadow call stack dynamically using code patching"
# needs Clang with https://reviews.llvm.org/D111780 incorporated
......
......@@ -361,11 +361,6 @@ config ARCH_HAS_CPU_RELAX
config ARCH_HIBERNATION_POSSIBLE
def_bool y
config ARCH_NR_GPIO
int
default 1024 if X86_64
default 512
config ARCH_SUSPEND_POSSIBLE
def_bool y
......
......@@ -109,6 +109,15 @@ config GPIO_REGMAP
config GPIO_MAX730X
tristate
config GPIO_IDIO_16
tristate
help
Enables support for the idio-16 library functions. The idio-16 library
provides functions to facilitate communication with devices within the
ACCES IDIO-16 family such as the 104-IDIO-16 and the PCI-IDIO-16.
If built as a module its name will be gpio-idio-16.
menu "Memory mapped GPIO drivers"
depends on HAS_IOMEM
......@@ -219,7 +228,7 @@ config GPIO_CLPS711X
Say yes here to support GPIO on CLPS711X SoCs.
config GPIO_DAVINCI
bool "TI Davinci/Keystone GPIO support"
tristate "TI Davinci/Keystone GPIO support"
default y if ARCH_DAVINCI
depends on (ARM || ARM64) && (ARCH_DAVINCI || ARCH_KEYSTONE || ARCH_K3)
help
......@@ -310,7 +319,7 @@ config GPIO_GRGPIO
config GPIO_HISI
tristate "HiSilicon GPIO controller driver"
depends on (ARM64 && ACPI) || COMPILE_TEST
depends on ARM64 || COMPILE_TEST
select GPIO_GENERIC
select GPIOLIB_IRQCHIP
help
......@@ -600,14 +609,6 @@ config GPIO_SPRD
help
Say yes here to support Spreadtrum GPIO device.
config GPIO_STA2X11
bool "STA2x11/ConneXt GPIO support"
depends on MFD_STA2X11
select GENERIC_IRQ_CHIP
help
Say yes here to support the STA2x11/ConneXt GPIO device.
The GPIO module has 128 GPIO pins with alternate functions.
config GPIO_STP_XWAY
bool "XWAY STP GPIOs"
depends on SOC_XWAY || COMPILE_TEST
......@@ -857,6 +858,7 @@ config GPIO_104_IDIO_16
depends on PC104
select ISA_BUS_API
select GPIOLIB_IRQCHIP
select GPIO_IDIO_16
help
Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The
......@@ -1561,6 +1563,7 @@ config GPIO_PCH
config GPIO_PCI_IDIO_16
tristate "ACCES PCI-IDIO-16 GPIO support"
select GPIOLIB_IRQCHIP
select GPIO_IDIO_16
help
Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is
generated when any of the inputs change state (low to high or high to
......@@ -1681,6 +1684,12 @@ config GPIO_AGGREGATOR
industrial control context, to be operated from userspace using
the GPIO chardev interface.
config GPIO_LATCH
tristate "GPIO latch driver"
help
Say yes here to enable a driver for GPIO multiplexers based on latches
connected to other GPIOs.
config GPIO_MOCKUP
tristate "GPIO Testing Driver"
select IRQ_SIM
......
......@@ -10,6 +10,7 @@ obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_CDEV) += gpiolib-cdev.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
obj-$(CONFIG_GPIOLIB) += gpiolib-swnode.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_REGMAP) += gpio-regmap.o
......@@ -68,6 +69,7 @@ obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_I8255) += gpio-i8255.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IDIO_16) += gpio-idio-16.o
obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o
obj-$(CONFIG_GPIO_IMX_SCU) += gpio-imx-scu.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
......@@ -75,6 +77,7 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o
obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
......@@ -140,7 +143,6 @@ obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o
......
......@@ -124,6 +124,13 @@ Work items:
this with dry-coding and sending to maintainers to test
Generic regmap GPIO
In the very similar way to Generic MMIO GPIO convert the users which can
take advantage of using regmap over direct IO accessors. Note, even in
MMIO case the regmap MMIO with gpio-regmap.c is preferable over gpio-mmio.c.
GPIOLIB irqchip
The GPIOLIB irqchip is a helper irqchip for "simple cases" that should
......
......@@ -6,7 +6,7 @@
* 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/bits.h>
#include <linux/bitmap.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
......@@ -21,6 +21,8 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include "gpio-idio-16.h"
#define IDIO_16_EXTENT 8
#define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
......@@ -34,49 +36,26 @@ 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_reg - device registers structure
* @out0_7: Read: N/A
* Write: FET Drive Outputs 0-7
* @in0_7: Read: Isolated Inputs 0-7
* Write: Clear Interrupt
* @irq_ctl: Read: Enable IRQ
* Write: Disable IRQ
* @unused: N/A
* @out8_15: Read: N/A
* Write: FET Drive Outputs 8-15
* @in8_15: Read: Isolated Inputs 8-15
* Write: N/A
*/
struct idio_16_reg {
u8 out0_7;
u8 in0_7;
u8 irq_ctl;
u8 unused;
u8 out8_15;
u8 in8_15;
};
/**
* 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
* @out_state: output bits state
* @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_reg __iomem *reg;
unsigned int out_state;
struct idio_16 __iomem *reg;
struct idio_16_state state;
};
static int idio_16_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
if (offset > 15)
if (idio_16_get_direction(offset))
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
......@@ -98,15 +77,8 @@ static int idio_16_gpio_direction_output(struct gpio_chip *chip,
static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
const unsigned int mask = BIT(offset-16);
if (offset < 16)
return -EINVAL;
if (offset < 24)
return !!(ioread8(&idio16gpio->reg->in0_7) & mask);
return !!(ioread8(&idio16gpio->reg->in8_15) & (mask>>8));
return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
}
static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
......@@ -114,11 +86,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
*bits = 0;
if (*mask & GENMASK(23, 16))
*bits |= (unsigned long)ioread8(&idio16gpio->reg->in0_7) << 16;
if (*mask & GENMASK(31, 24))
*bits |= (unsigned long)ioread8(&idio16gpio->reg->in8_15) << 24;
idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
return 0;
}
......@@ -127,44 +95,16 @@ 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);
const unsigned int mask = BIT(offset);
unsigned long flags;
if (offset > 15)
return;
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
if (value)
idio16gpio->out_state |= mask;
else
idio16gpio->out_state &= ~mask;
if (offset > 7)
iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
else
iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
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);
unsigned long flags;
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
idio16gpio->out_state &= ~*mask;
idio16gpio->out_state |= *mask & *bits;
if (*mask & 0xFF)
iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
if ((*mask >> 8) & 0xFF)
iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
}
static void idio_16_irq_ack(struct irq_data *data)
......@@ -301,7 +241,10 @@ static int idio_16_probe(struct device *dev, unsigned int id)
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;
idio16gpio->out_state = 0xFFFF;
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);
girq = &idio16gpio->chip.irq;
gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
......@@ -343,3 +286,4 @@ module_isa_driver_with_irq(idio_16_driver, num_idio_16, num_irq);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(GPIO_IDIO_16);
......@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#define AGGREGATOR_MAX_GPIOS 512
/*
* GPIO Aggregator sysfs interface
......@@ -64,7 +65,7 @@ static int aggr_parse(struct gpio_aggregator *aggr)
unsigned int i, n = 0;
int error = 0;
bitmap = bitmap_alloc(ARCH_NR_GPIOS, GFP_KERNEL);
bitmap = bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
......@@ -84,13 +85,13 @@ static int aggr_parse(struct gpio_aggregator *aggr)
}
/* GPIO chip + offset(s) */
error = bitmap_parselist(offsets, bitmap, ARCH_NR_GPIOS);
error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS);
if (error) {
pr_err("Cannot parse %s: %d\n", offsets, error);
goto free_bitmap;
}
for_each_set_bit(i, bitmap, ARCH_NR_GPIOS) {
for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) {
error = aggr_add_gpio(aggr, name, i, &n);
if (error)
goto free_bitmap;
......
......@@ -217,9 +217,6 @@ static int davinci_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}
if (WARN_ON(ARCH_NR_GPIOS < ngpio))
ngpio = ARCH_NR_GPIOS;
/*
* If there are unbanked interrupts then the number of
* interrupts is equal to number of gpios else all are banked so
......@@ -730,3 +727,14 @@ static int __init davinci_gpio_drv_reg(void)
return platform_driver_register(&davinci_gpio_driver);
}
postcore_initcall(davinci_gpio_drv_reg);
static void __exit davinci_gpio_exit(void)
{
platform_driver_unregister(&davinci_gpio_driver);
}
module_exit(davinci_gpio_exit);
MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
MODULE_DESCRIPTION("DAVINCI GPIO driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-davinci");
......@@ -141,6 +141,7 @@ static const struct regmap_config exar_regmap_config = {
.name = "exar-gpio",
.reg_bits = 16,
.val_bits = 8,
.io_port = true,
};
static int gpio_exar_probe(struct platform_device *pdev)
......
......@@ -277,7 +277,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
dev_err(dev, "unable to init generic GPIO\n");
goto dis_clk;
}
g->gc.label = "FTGPIO010";
g->gc.label = dev_name(dev);
g->gc.base = -1;
g->gc.parent = dev;
g->gc.owner = THIS_MODULE;
......
......@@ -67,8 +67,7 @@ static void gw_pld_set8(struct gpio_chip *gc, unsigned offset, int value)
gw_pld_output8(gc, offset, value);
}
static int gw_pld_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int gw_pld_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct gw_pld *gw;
......@@ -126,7 +125,7 @@ static struct i2c_driver gw_pld_driver = {
.name = "gw_pld",
.of_match_table = gw_pld_dt_ids,
},
.probe = gw_pld_probe,
.probe_new = gw_pld_probe,
.id_table = gw_pld_id,
};
module_i2c_driver(gw_pld_driver);
......
......@@ -221,6 +221,12 @@ static const struct acpi_device_id hisi_gpio_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, hisi_gpio_acpi_match);
static const struct of_device_id hisi_gpio_dts_match[] = {
{ .compatible = "hisilicon,ascend910-gpio", },
{ }
};
MODULE_DEVICE_TABLE(of, hisi_gpio_dts_match);
static void hisi_gpio_get_pdata(struct device *dev,
struct hisi_gpio *hisi_gpio)
{
......@@ -311,6 +317,7 @@ static struct platform_driver hisi_gpio_driver = {
.driver = {
.name = HISI_GPIO_DRIVER_NAME,
.acpi_match_table = hisi_gpio_acpi_match,
.of_match_table = hisi_gpio_dts_match,
},
.probe = hisi_gpio_probe,
};
......
// SPDX-License-Identifier: GPL-2.0
/*
* GPIO library for the ACCES IDIO-16 family
* Copyright (C) 2022 William Breathitt Gray
*/
#include <linux/bitmap.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include "gpio-idio-16.h"
#define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16
/**
* idio_16_get - get signal value at signal offset
* @reg: ACCES IDIO-16 device registers
* @state: ACCES IDIO-16 device state
* @offset: offset of signal to get
*
* Returns the signal value (0=low, 1=high) for the signal at @offset.
*/
int idio_16_get(struct idio_16 __iomem *const reg,
struct idio_16_state *const state, const unsigned long offset)
{
const unsigned long mask = BIT(offset);
if (offset < IDIO_16_NOUT)
return test_bit(offset, state->out_state);
if (offset < 24)
return !!(ioread8(&reg->in0_7) & (mask >> IDIO_16_NOUT));
if (offset < 32)
return !!(ioread8(&reg->in8_15) & (mask >> 24));
return -EINVAL;
}
EXPORT_SYMBOL_GPL(idio_16_get);
/**
* idio_16_get_multiple - get multiple signal values at multiple signal offsets
* @reg: ACCES IDIO-16 device registers
* @state: ACCES IDIO-16 device state
* @mask: mask of signals to get
* @bits: bitmap to store signal values
*
* Stores in @bits the values (0=low, 1=high) for the signals defined by @mask.
*/
void idio_16_get_multiple(struct idio_16 __iomem *const reg,
struct idio_16_state *const state,
const unsigned long *const mask,
unsigned long *const bits)
{
unsigned long flags;
const unsigned long out_mask = GENMASK(IDIO_16_NOUT - 1, 0);
spin_lock_irqsave(&state->lock, flags);
bitmap_replace(bits, bits, state->out_state, &out_mask, IDIO_16_NOUT);
if (*mask & GENMASK(23, 16))
bitmap_set_value8(bits, ioread8(&reg->in0_7), 16);
if (*mask & GENMASK(31, 24))
bitmap_set_value8(bits, ioread8(&reg->in8_15), 24);
spin_unlock_irqrestore(&state->lock, flags);
}
EXPORT_SYMBOL_GPL(idio_16_get_multiple);
/**
* idio_16_set - set signal value at signal offset
* @reg: ACCES IDIO-16 device registers
* @state: ACCES IDIO-16 device state
* @offset: offset of signal to set
* @value: value of signal to set
*
* Assigns output @value for the signal at @offset.
*/
void idio_16_set(struct idio_16 __iomem *const reg,
struct idio_16_state *const state, const unsigned long offset,
const unsigned long value)
{
unsigned long flags;
if (offset >= IDIO_16_NOUT)
return;
spin_lock_irqsave(&state->lock, flags);
__assign_bit(offset, state->out_state, value);
if (offset < 8)
iowrite8(bitmap_get_value8(state->out_state, 0), &reg->out0_7);
else
iowrite8(bitmap_get_value8(state->out_state, 8), &reg->out8_15);
spin_unlock_irqrestore(&state->lock, flags);
}
EXPORT_SYMBOL_GPL(idio_16_set);
/**
* idio_16_set_multiple - set signal values at multiple signal offsets
* @reg: ACCES IDIO-16 device registers
* @state: ACCES IDIO-16 device state
* @mask: mask of signals to set
* @bits: bitmap of signal output values
*
* Assigns output values defined by @bits for the signals defined by @mask.
*/
void idio_16_set_multiple(struct idio_16 __iomem *const reg,
struct idio_16_state *const state,
const unsigned long *const mask,
const unsigned long *const bits)
{
unsigned long flags;
spin_lock_irqsave(&state->lock, flags);
bitmap_replace(state->out_state, state->out_state, bits, mask,
IDIO_16_NOUT);
if (*mask & GENMASK(7, 0))
iowrite8(bitmap_get_value8(state->out_state, 0), &reg->out0_7);
if (*mask & GENMASK(15, 8))
iowrite8(bitmap_get_value8(state->out_state, 8), &reg->out8_15);
spin_unlock_irqrestore(&state->lock, flags);
}
EXPORT_SYMBOL_GPL(idio_16_set_multiple);
/**
* idio_16_state_init - initialize idio_16_state structure
* @state: ACCES IDIO-16 device state
*
* Initializes the ACCES IDIO-16 device @state for use in idio-16 library
* functions.
*/
void idio_16_state_init(struct idio_16_state *const state)
{
spin_lock_init(&state->lock);
}
EXPORT_SYMBOL_GPL(idio_16_state_init);
MODULE_AUTHOR("William Breathitt Gray");
MODULE_DESCRIPTION("ACCES IDIO-16 GPIO Library");
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2022 William Breathitt Gray */
#ifndef _IDIO_16_H_
#define _IDIO_16_H_
#include <linux/spinlock.h>
#include <linux/types.h>
/**
* struct idio_16 - IDIO-16 registers structure
* @out0_7: Read: FET Drive Outputs 0-7
* Write: FET Drive Outputs 0-7
* @in0_7: Read: Isolated Inputs 0-7
* Write: Clear Interrupt
* @irq_ctl: Read: Enable IRQ
* Write: Disable IRQ
* @filter_ctl: Read: Activate Input Filters 0-15
* Write: Deactivate Input Filters 0-15
* @out8_15: Read: FET Drive Outputs 8-15
* Write: FET Drive Outputs 8-15
* @in8_15: Read: Isolated Inputs 8-15
* Write: Unused
* @irq_status: Read: Interrupt status
* Write: Unused
*/
struct idio_16 {
u8 out0_7;
u8 in0_7;
u8 irq_ctl;
u8 filter_ctl;
u8 out8_15;
u8 in8_15;
u8 irq_status;
};
#define IDIO_16_NOUT 16
/**
* struct idio_16_state - IDIO-16 state structure
* @lock: synchronization lock for accessing device state
* @out_state: output signals state
*/
struct idio_16_state {
spinlock_t lock;
DECLARE_BITMAP(out_state, IDIO_16_NOUT);
};
/**
* idio_16_get_direction - get the I/O direction for a signal offset
* @offset: offset of signal to get direction
*
* Returns the signal direction (0=output, 1=input) for the signal at @offset.
*/
static inline int idio_16_get_direction(const unsigned long offset)
{
return (offset >= IDIO_16_NOUT) ? 1 : 0;
}
int idio_16_get(struct idio_16 __iomem *reg, struct idio_16_state *state,
unsigned long offset);
void idio_16_get_multiple(struct idio_16 __iomem *reg,
struct idio_16_state *state,
const unsigned long *mask, unsigned long *bits);
void idio_16_set(struct idio_16 __iomem *reg, struct idio_16_state *state,
unsigned long offset, unsigned long value);
void idio_16_set_multiple(struct idio_16 __iomem *reg,
struct idio_16_state *state,
const unsigned long *mask, const unsigned long *bits);
void idio_16_state_init(struct idio_16_state *state);
#endif /* _IDIO_16_H_ */
// SPDX-License-Identifier: GPL-2.0
/*
* GPIO latch driver
*
* Copyright (C) 2022 Sascha Hauer <s.hauer@pengutronix.de>
*
* This driver implements a GPIO (or better GPO as there is no input)
* multiplexer based on latches like this:
*
* CLK0 ----------------------. ,--------.
* CLK1 -------------------. `--------|> #0 |
* | | |
* OUT0 ----------------+--|-----------|D0 Q0|-----|<
* OUT1 --------------+-|--|-----------|D1 Q1|-----|<
* OUT2 ------------+-|-|--|-----------|D2 Q2|-----|<
* OUT3 ----------+-|-|-|--|-----------|D3 Q3|-----|<
* OUT4 --------+-|-|-|-|--|-----------|D4 Q4|-----|<
* OUT5 ------+-|-|-|-|-|--|-----------|D5 Q5|-----|<
* OUT6 ----+-|-|-|-|-|-|--|-----------|D6 Q6|-----|<
* OUT7 --+-|-|-|-|-|-|-|--|-----------|D7 Q7|-----|<
* | | | | | | | | | `--------'
* | | | | | | | | |
* | | | | | | | | | ,--------.
* | | | | | | | | `-----------|> #1 |
* | | | | | | | | | |
* | | | | | | | `--------------|D0 Q0|-----|<
* | | | | | | `----------------|D1 Q1|-----|<
* | | | | | `------------------|D2 Q2|-----|<
* | | | | `--------------------|D3 Q3|-----|<
* | | | `----------------------|D4 Q4|-----|<
* | | `------------------------|D5 Q5|-----|<
* | `--------------------------|D6 Q6|-----|<
* `----------------------------|D7 Q7|-----|<
* `--------'
*
* The above is just an example. The actual number of number of latches and
* the number of inputs per latch is derived from the number of GPIOs given
* in the corresponding device tree properties.
*/
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include "gpiolib.h"
struct gpio_latch_priv {
struct gpio_chip gc;
struct gpio_descs *clk_gpios;
struct gpio_descs *latched_gpios;
int n_latched_gpios;
unsigned int setup_duration_ns;
unsigned int clock_duration_ns;
unsigned long *shadow;
/*
* Depending on whether any of the underlying GPIOs may sleep we either
* use a mutex or a spinlock to protect our shadow map.
*/
union {
struct mutex mutex; /* protects @shadow */
spinlock_t spinlock; /* protects @shadow */
};
};
static int gpio_latch_get_direction(struct gpio_chip *gc, unsigned int offset)
{
return GPIO_LINE_DIRECTION_OUT;
}
static void gpio_latch_set_unlocked(struct gpio_latch_priv *priv,
void (*set)(struct gpio_desc *desc, int value),
unsigned int offset, bool val)
{
int latch = offset / priv->n_latched_gpios;
int i;
assign_bit(offset, priv->shadow, val);
for (i = 0; i < priv->n_latched_gpios; i++)
set(priv->latched_gpios->desc[i],
test_bit(latch * priv->n_latched_gpios + i, priv->shadow));
ndelay(priv->setup_duration_ns);
set(priv->clk_gpios->desc[latch], 1);
ndelay(priv->clock_duration_ns);
set(priv->clk_gpios->desc[latch], 0);
}
static void gpio_latch_set(struct gpio_chip *gc, unsigned int offset, int val)
{
struct gpio_latch_priv *priv = gpiochip_get_data(gc);
unsigned long flags;
spin_lock_irqsave(&priv->spinlock, flags);
gpio_latch_set_unlocked(priv, gpiod_set_value, offset, val);
spin_unlock_irqrestore(&priv->spinlock, flags);
}
static void gpio_latch_set_can_sleep(struct gpio_chip *gc, unsigned int offset, int val)
{
struct gpio_latch_priv *priv = gpiochip_get_data(gc);
mutex_lock(&priv->mutex);
gpio_latch_set_unlocked(priv, gpiod_set_value_cansleep, offset, val);
mutex_unlock(&priv->mutex);
}
static bool gpio_latch_can_sleep(struct gpio_latch_priv *priv, unsigned int n_latches)
{
int i;
for (i = 0; i < n_latches; i++)
if (gpiod_cansleep(priv->clk_gpios->desc[i]))
return true;
for (i = 0; i < priv->n_latched_gpios; i++)
if (gpiod_cansleep(priv->latched_gpios->desc[i]))
return true;
return false;
}
/*
* Some value which is still acceptable to delay in atomic context.
* If we need to go higher we might have to switch to usleep_range(),
* but that cannot ne used in atomic context and the driver would have
* to be adjusted to support that.
*/
#define DURATION_NS_MAX 5000
static int gpio_latch_probe(struct platform_device *pdev)
{
struct gpio_latch_priv *priv;
unsigned int n_latches;
struct device_node *np = pdev->dev.of_node;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->clk_gpios = devm_gpiod_get_array(&pdev->dev, "clk", GPIOD_OUT_LOW);
if (IS_ERR(priv->clk_gpios))
return PTR_ERR(priv->clk_gpios);
priv->latched_gpios = devm_gpiod_get_array(&pdev->dev, "latched", GPIOD_OUT_LOW);
if (IS_ERR(priv->latched_gpios))
return PTR_ERR(priv->latched_gpios);
n_latches = priv->clk_gpios->ndescs;
priv->n_latched_gpios = priv->latched_gpios->ndescs;
priv->shadow = devm_bitmap_zalloc(&pdev->dev, n_latches * priv->n_latched_gpios,
GFP_KERNEL);
if (!priv->shadow)
return -ENOMEM;
if (gpio_latch_can_sleep(priv, n_latches)) {
priv->gc.can_sleep = true;
priv->gc.set = gpio_latch_set_can_sleep;
mutex_init(&priv->mutex);
} else {
priv->gc.can_sleep = false;
priv->gc.set = gpio_latch_set;
spin_lock_init(&priv->spinlock);
}
of_property_read_u32(np, "setup-duration-ns", &priv->setup_duration_ns);
if (priv->setup_duration_ns > DURATION_NS_MAX) {
dev_warn(&pdev->dev, "setup-duration-ns too high, limit to %d\n",
DURATION_NS_MAX);
priv->setup_duration_ns = DURATION_NS_MAX;
}
of_property_read_u32(np, "clock-duration-ns", &priv->clock_duration_ns);
if (priv->clock_duration_ns > DURATION_NS_MAX) {
dev_warn(&pdev->dev, "clock-duration-ns too high, limit to %d\n",
DURATION_NS_MAX);
priv->clock_duration_ns = DURATION_NS_MAX;
}
priv->gc.get_direction = gpio_latch_get_direction;
priv->gc.ngpio = n_latches * priv->n_latched_gpios;
priv->gc.owner = THIS_MODULE;
priv->gc.base = -1;
priv->gc.parent = &pdev->dev;
platform_set_drvdata(pdev, priv);
return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv);
}
static const struct of_device_id gpio_latch_ids[] = {
{
.compatible = "gpio-latch",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, gpio_latch_ids);
static struct platform_driver gpio_latch_driver = {
.driver = {
.name = "gpio-latch",
.of_match_table = gpio_latch_ids,
},
.probe = gpio_latch_probe,
};
module_platform_driver(gpio_latch_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
MODULE_DESCRIPTION("GPIO latch driver");
......@@ -28,8 +28,7 @@ static int max7300_i2c_read(struct device *dev, unsigned int reg)
return i2c_smbus_read_byte_data(client, reg);
}
static int max7300_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int max7300_probe(struct i2c_client *client)
{
struct max7301 *ts;
......@@ -63,7 +62,7 @@ static struct i2c_driver max7300_driver = {
.driver = {
.name = "max7300",
},
.probe = max7300_probe,
.probe_new = max7300_probe,
.remove = max7300_remove,
.id_table = max7300_id,
};
......
......@@ -608,9 +608,9 @@ static struct max732x_platform_data *of_gpio_max732x(struct device *dev)
return pdata;
}
static int max732x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int max732x_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct max732x_platform_data *pdata;
struct device_node *node;
struct max732x_chip *chip;
......@@ -707,7 +707,7 @@ static struct i2c_driver max732x_driver = {
.name = "max732x",
.of_match_table = of_match_ptr(max732x_of_table),
},
.probe = max732x_probe,
.probe_new = max732x_probe,
.id_table = max732x_id,
};
......
......@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pinctrl/consumer.h>
#include <linux/string_helpers.h>
#define GCCR 0x000 /* controller configuration */
#define GPLR 0x004 /* pin level r/o */
......@@ -331,7 +332,7 @@ static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on)
raw_spin_unlock_irqrestore(&priv->lock, flags);
dev_dbg(priv->dev, "%sable wake for gpio %u\n", on ? "en" : "dis", gpio);
dev_dbg(priv->dev, "%s wake for gpio %u\n", str_enable_disable(on), gpio);
return 0;
}
......
......@@ -1050,9 +1050,9 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
return ret;
}
static int pca953x_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
static int pca953x_probe(struct i2c_client *client)
{
const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client);
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
int irq_base = 0;
......@@ -1376,7 +1376,7 @@ static struct i2c_driver pca953x_driver = {
.of_match_table = pca953x_dt_ids,
.acpi_match_table = pca953x_acpi_ids,
},
.probe = pca953x_probe,
.probe_new = pca953x_probe,
.remove = pca953x_remove,
.id_table = pca953x_id,
};
......
......@@ -15,14 +15,28 @@
#include <linux/mutex.h>
#include <linux/property.h>
#define SLG7XL45106_GPO_REG 0xDB
/**
* struct pca9570_platform_data - GPIO platformdata
* @ngpio: no of gpios
* @command: Command to be sent
*/
struct pca9570_platform_data {
u16 ngpio;
u32 command;
};
/**
* struct pca9570 - GPIO driver data
* @chip: GPIO controller chip
* @p_data: GPIO controller platform data
* @lock: Protects write sequences
* @out: Buffer for device register
*/
struct pca9570 {
struct gpio_chip chip;
const struct pca9570_platform_data *p_data;
struct mutex lock;
u8 out;
};
......@@ -32,7 +46,11 @@ static int pca9570_read(struct pca9570 *gpio, u8 *value)
struct i2c_client *client = to_i2c_client(gpio->chip.parent);
int ret;
ret = i2c_smbus_read_byte(client);
if (gpio->p_data->command != 0)
ret = i2c_smbus_read_byte_data(client, gpio->p_data->command);
else
ret = i2c_smbus_read_byte(client);
if (ret < 0)
return ret;
......@@ -44,6 +62,9 @@ static int pca9570_write(struct pca9570 *gpio, u8 value)
{
struct i2c_client *client = to_i2c_client(gpio->chip.parent);
if (gpio->p_data->command != 0)
return i2c_smbus_write_byte_data(client, gpio->p_data->command, value);
return i2c_smbus_write_byte(client, value);
}
......@@ -106,7 +127,8 @@ static int pca9570_probe(struct i2c_client *client)
gpio->chip.get = pca9570_get;
gpio->chip.set = pca9570_set;
gpio->chip.base = -1;
gpio->chip.ngpio = (uintptr_t)device_get_match_data(&client->dev);
gpio->p_data = device_get_match_data(&client->dev);
gpio->chip.ngpio = gpio->p_data->ngpio;
gpio->chip.can_sleep = true;
mutex_init(&gpio->lock);
......@@ -119,16 +141,31 @@ static int pca9570_probe(struct i2c_client *client)
return devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
}
static const struct pca9570_platform_data pca9570_gpio = {
.ngpio = 4,
};
static const struct pca9570_platform_data pca9571_gpio = {
.ngpio = 8,
};
static const struct pca9570_platform_data slg7xl45106_gpio = {
.ngpio = 8,
.command = SLG7XL45106_GPO_REG,
};
static const struct i2c_device_id pca9570_id_table[] = {
{ "pca9570", 4 },
{ "pca9571", 8 },
{ "pca9570", (kernel_ulong_t)&pca9570_gpio},
{ "pca9571", (kernel_ulong_t)&pca9571_gpio },
{ "slg7xl45106", (kernel_ulong_t)&slg7xl45106_gpio },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, pca9570_id_table);
static const struct of_device_id pca9570_of_match_table[] = {
{ .compatible = "nxp,pca9570", .data = (void *)4 },
{ .compatible = "nxp,pca9571", .data = (void *)8 },
{ .compatible = "dlg,slg7xl45106", .data = &slg7xl45106_gpio},
{ .compatible = "nxp,pca9570", .data = &pca9570_gpio },
{ .compatible = "nxp,pca9571", .data = &pca9571_gpio },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pca9570_of_match_table);
......
......@@ -247,9 +247,9 @@ static const struct irq_chip pcf857x_irq_chip = {
/*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf857x_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
struct device_node *np = client->dev.of_node;
struct pcf857x *gpio;
......@@ -422,7 +422,7 @@ static struct i2c_driver pcf857x_driver = {
.name = "pcf857x",
.of_match_table = of_match_ptr(pcf857x_of_table),
},
.probe = pcf857x_probe,
.probe_new = pcf857x_probe,
.remove = pcf857x_remove,
.shutdown = pcf857x_shutdown,
.id_table = pcf857x_id,
......
......@@ -3,8 +3,7 @@
* GPIO driver for the ACCES PCI-IDIO-16
* Copyright (C) 2017 William Breathitt Gray
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
......@@ -16,51 +15,28 @@
#include <linux/spinlock.h>
#include <linux/types.h>
/**
* struct idio_16_gpio_reg - GPIO device registers structure
* @out0_7: Read: FET Drive Outputs 0-7
* Write: FET Drive Outputs 0-7
* @in0_7: Read: Isolated Inputs 0-7
* Write: Clear Interrupt
* @irq_ctl: Read: Enable IRQ
* Write: Disable IRQ
* @filter_ctl: Read: Activate Input Filters 0-15
* Write: Deactivate Input Filters 0-15
* @out8_15: Read: FET Drive Outputs 8-15
* Write: FET Drive Outputs 8-15
* @in8_15: Read: Isolated Inputs 8-15
* Write: Unused
* @irq_status: Read: Interrupt status
* Write: Unused
*/
struct idio_16_gpio_reg {
u8 out0_7;
u8 in0_7;
u8 irq_ctl;
u8 filter_ctl;
u8 out8_15;
u8 in8_15;
u8 irq_status;
};
#include "gpio-idio-16.h"
/**
* struct idio_16_gpio - GPIO device private data structure
* @chip: instance of the gpio_chip
* @lock: synchronization lock to prevent I/O race conditions
* @reg: I/O address offset for the GPIO device registers
* @state: ACCES IDIO-16 device state
* @irq_mask: I/O bits affected by interrupts
*/
struct idio_16_gpio {
struct gpio_chip chip;
raw_spinlock_t lock;
struct idio_16_gpio_reg __iomem *reg;
struct idio_16 __iomem *reg;
struct idio_16_state state;
unsigned long irq_mask;
};
static int idio_16_gpio_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
if (offset > 15)
if (idio_16_get_direction(offset))
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
......@@ -82,43 +58,16 @@ static int idio_16_gpio_direction_output(struct gpio_chip *chip,
static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
unsigned long mask = BIT(offset);
if (offset < 8)
return !!(ioread8(&idio16gpio->reg->out0_7) & mask);
if (offset < 16)
return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8));
if (offset < 24)
return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16));
return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
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);
unsigned long offset;
unsigned long gpio_mask;
void __iomem *ports[] = {
&idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
&idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
};
void __iomem *port_addr;
unsigned long port_state;
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
port_addr = ports[offset / 8];
port_state = ioread8(port_addr) & gpio_mask;
bitmap_set_value8(bits, port_state, offset);
}
idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
return 0;
}
......@@ -126,61 +75,16 @@ 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);
unsigned int mask = BIT(offset);
void __iomem *base;
unsigned long flags;
unsigned int out_state;
if (offset > 15)
return;
if (offset > 7) {
mask >>= 8;
base = &idio16gpio->reg->out8_15;
} else
base = &idio16gpio->reg->out0_7;
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
if (value)
out_state = ioread8(base) | mask;
else
out_state = ioread8(base) & ~mask;
iowrite8(out_state, base);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
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);
unsigned long offset;
unsigned long gpio_mask;
void __iomem *ports[] = {
&idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
};
size_t index;
void __iomem *port_addr;
unsigned long bitmask;
unsigned long flags;
unsigned long out_state;
for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
index = offset / 8;
port_addr = ports[index];
bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
raw_spin_lock_irqsave(&idio16gpio->lock, flags);
out_state = ioread8(port_addr) & ~gpio_mask;
out_state |= bitmask;
iowrite8(out_state, port_addr);
raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
}
static void idio_16_irq_ack(struct irq_data *data)
......@@ -335,6 +239,8 @@ 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;
idio_16_state_init(&idio16gpio->state);
girq = &idio16gpio->chip.irq;
girq->chip = &idio_16_irqchip;
/* This will let us handle the parent IRQ in the driver */
......@@ -379,3 +285,4 @@ module_pci_driver(idio_16_driver);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(GPIO_IDIO_16);
......@@ -31,6 +31,7 @@
#include "gpiolib.h"
#define GPIO_SIM_NGPIO_MAX 1024
#define GPIO_SIM_PROP_MAX 4 /* Max 3 properties + sentinel. */
#define GPIO_SIM_NUM_ATTRS 3 /* value, pull and sentinel */
......@@ -371,6 +372,9 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
if (ret)
return ret;
if (num_lines > GPIO_SIM_NGPIO_MAX)
return -ERANGE;
ret = fwnode_property_read_string(swnode, "gpio-sim,label", &label);
if (ret) {
label = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
......
......@@ -70,8 +70,7 @@ static int sl28cpld_gpio_irq_init(struct platform_device *pdev,
irq_chip->num_irqs = ARRAY_SIZE(sl28cpld_gpio_irqs);
irq_chip->num_regs = 1;
irq_chip->status_base = base + GPIO_REG_IP;
irq_chip->mask_base = base + GPIO_REG_IE;
irq_chip->mask_invert = true;
irq_chip->unmask_base = base + GPIO_REG_IE;
irq_chip->ack_base = base + GPIO_REG_IP;
ret = devm_regmap_add_irq_chip_fwnode(dev, dev_fwnode(dev),
......
This diff is collapsed.
......@@ -98,8 +98,7 @@ static const struct of_device_id tpic2810_of_match_table[] = {
};
MODULE_DEVICE_TABLE(of, tpic2810_of_match_table);
static int tpic2810_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int tpic2810_probe(struct i2c_client *client)
{
struct tpic2810 *gpio;
int ret;
......@@ -144,7 +143,7 @@ static struct i2c_driver tpic2810_driver = {
.name = "tpic2810",
.of_match_table = tpic2810_of_match_table,
},
.probe = tpic2810_probe,
.probe_new = tpic2810_probe,
.remove = tpic2810_remove,
.id_table = tpic2810_id_table,
};
......
......@@ -136,8 +136,7 @@ static const struct of_device_id ts4900_gpio_of_match_table[] = {
};
MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table);
static int ts4900_gpio_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int ts4900_gpio_probe(struct i2c_client *client)
{
struct ts4900_gpio_priv *priv;
u32 ngpio;
......@@ -186,7 +185,7 @@ static struct i2c_driver ts4900_gpio_driver = {
.name = "ts4900-gpio",
.of_match_table = ts4900_gpio_of_match_table,
},
.probe = ts4900_gpio_probe,
.probe_new = ts4900_gpio_probe,
.id_table = ts4900_gpio_id_table,
};
module_i2c_driver(ts4900_gpio_driver);
......
......@@ -89,6 +89,30 @@ struct acpi_gpio_chip {
struct list_head deferred_req_irqs_list_entry;
};
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @adev: reference to ACPI device which consumes GPIO resource
* @flags: GPIO initialization flags
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
* @wake_capable: wake capability as provided by ACPI
* @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
struct acpi_device *adev;
enum gpiod_flags flags;
bool gpioint;
int pin_config;
int polarity;
int triggering;
bool wake_capable;
unsigned int debounce;
unsigned int quirks;
};
/*
* For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init
* (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a
......@@ -512,7 +536,7 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
if (ACPI_FAILURE(status))
return;
acpi_walk_resources(handle, "_AEI",
acpi_walk_resources(handle, METHOD_NAME__AEI,
acpi_gpiochip_alloc_event, acpi_gpio);
mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
......@@ -670,8 +694,8 @@ __acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
return ret;
}
int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
static int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
struct acpi_gpio_info *info)
{
struct device *dev = &info->adev->dev;
enum gpiod_flags old = *flags;
......@@ -690,8 +714,8 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf
return ret;
}
int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info)
static int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info)
{
switch (info->pin_config) {
case ACPI_PIN_CONFIG_PULLUP:
......@@ -864,8 +888,9 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
* function only returns the first.
*/
static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
const char *propname, int index,
struct acpi_gpio_info *info)
const char *propname,
int index,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
int ret;
......@@ -896,6 +921,44 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ret ? ERR_PTR(ret) : lookup.desc;
}
/**
* acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node
* @fwnode: pointer to an ACPI firmware node to get the GPIO information from
* @propname: Property name of the GPIO
* @index: index of GpioIo/GpioInt resource (starting from %0)
* @info: info pointer to fill in (optional)
*
* This function uses the property-based GPIO lookup to get to the GPIO
* resource with the relevant information from a data-only ACPI firmware node
* and uses that to obtain the GPIO descriptor to return.
*
* If the GPIO cannot be translated or there is an error an ERR_PTR is
* returned.
*/
static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode,
const char *propname,
int index,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
int ret;
if (!is_acpi_data_node(fwnode))
return ERR_PTR(-ENODEV);
if (!propname)
return ERR_PTR(-EINVAL);
lookup.index = index;
ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
if (ret)
return ERR_PTR(ret);
ret = acpi_gpio_resource_lookup(&lookup, info);
return ret ? ERR_PTR(ret) : lookup.desc;
}
static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
const char *con_id)
{
......@@ -906,13 +969,13 @@ static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
return con_id == NULL;
}
struct gpio_desc *acpi_find_gpio(struct device *dev,
struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
const char *con_id,
unsigned int idx,
enum gpiod_flags *dflags,
unsigned long *lookupflags)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_device *adev = to_acpi_device_node(fwnode);
struct acpi_gpio_info info;
struct gpio_desc *desc;
char propname[32];
......@@ -928,7 +991,12 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
gpio_suffixes[i]);
}
desc = acpi_get_gpiod_by_index(adev, propname, idx, &info);
if (adev)
desc = acpi_get_gpiod_by_index(adev,
propname, idx, &info);
else
desc = acpi_get_gpiod_from_data(fwnode,
propname, idx, &info);
if (!IS_ERR(desc))
break;
if (PTR_ERR(desc) == -EPROBE_DEFER)
......@@ -937,7 +1005,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
/* Then from plain _CRS GPIOs */
if (IS_ERR(desc)) {
if (!acpi_can_fallback_to_crs(adev, con_id))
if (!adev || !acpi_can_fallback_to_crs(adev, con_id))
return ERR_PTR(-ENOENT);
desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
......@@ -956,50 +1024,6 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
return desc;
}
/**
* acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources
* @fwnode: pointer to an ACPI firmware node to get the GPIO information from
* @propname: Property name of the GPIO
* @index: index of GpioIo/GpioInt resource (starting from %0)
* @info: info pointer to fill in (optional)
*
* If @fwnode is an ACPI device object, call acpi_get_gpiod_by_index() for it.
* Otherwise (i.e. it is a data-only non-device object), use the property-based
* GPIO lookup to get to the GPIO resource with the relevant information and use
* that to obtain the GPIO descriptor to return.
*
* If the GPIO cannot be translated or there is an error an ERR_PTR is
* returned.
*/
struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
struct acpi_gpio_info *info)
{
struct acpi_gpio_lookup lookup;
struct acpi_device *adev;
int ret;
adev = to_acpi_device_node(fwnode);
if (adev)
return acpi_get_gpiod_by_index(adev, propname, index, info);
if (!is_acpi_data_node(fwnode))
return ERR_PTR(-ENODEV);
if (!propname)
return ERR_PTR(-EINVAL);
memset(&lookup, 0, sizeof(lookup));
lookup.index = index;
ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
if (ret)
return ERR_PTR(ret);
ret = acpi_gpio_resource_lookup(&lookup, info);
return ret ? ERR_PTR(ret) : lookup.desc;
}
/**
* acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number
* @adev: pointer to a ACPI device to get IRQ from
......
......@@ -22,30 +22,6 @@ struct gpio_chip;
struct gpio_desc;
struct gpio_device;
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @adev: reference to ACPI device which consumes GPIO resource
* @flags: GPIO initialization flags
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
* @wake_capable: wake capability as provided by ACPI
* @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
struct acpi_device *adev;
enum gpiod_flags flags;
bool gpioint;
int pin_config;
int polarity;
int triggering;
bool wake_capable;
unsigned int debounce;
unsigned int quirks;
};
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
......@@ -55,19 +31,11 @@ void acpi_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
struct acpi_gpio_info *info);
int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info);
struct gpio_desc *acpi_find_gpio(struct device *dev,
struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
const char *con_id,
unsigned int idx,
enum gpiod_flags *dflags,
unsigned long *lookupflags);
struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
struct acpi_gpio_info *info);
int acpi_gpio_count(struct device *dev, const char *con_id);
#else
......@@ -82,31 +50,13 @@ acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
{
return 0;
}
static inline int
acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info)
{
return 0;
}
static inline struct gpio_desc *
acpi_find_gpio(struct device *dev, const char *con_id,
acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id,
unsigned int idx, enum gpiod_flags *dflags,
unsigned long *lookupflags)
{
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *
acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
int index, struct acpi_gpio_info *info)
{
return ERR_PTR(-ENXIO);
}
static inline int acpi_gpio_count(struct device *dev, const char *con_id)
{
return -ENODEV;
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,17 +16,16 @@ struct gpio_desc;
struct gpio_device;
#ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev,
struct gpio_desc *of_find_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
int of_gpio_get_count(struct device *dev, const char *con_id);
bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
void of_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev);
#else
static inline struct gpio_desc *of_find_gpio(struct device *dev,
static inline struct gpio_desc *of_find_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags)
......@@ -39,10 +38,6 @@ static inline int of_gpio_get_count(struct device *dev, const char *con_id)
{
return 0;
}
static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
{
return false;
}
static inline void of_gpio_dev_init(struct gpio_chip *gc,
struct gpio_device *gdev)
{
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Software Node helpers for the GPIO API
*
* Copyright 2022 Google LLC
*/
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/property.h>
#include <linux/string.h>
#include "gpiolib.h"
#include "gpiolib-swnode.h"
static void swnode_format_propname(const char *con_id, char *propname,
size_t max_size)
{
/*
* Note we do not need to try both -gpios and -gpio suffixes,
* as, unlike OF and ACPI, we can fix software nodes to conform
* to the proper binding.
*/
if (con_id)
snprintf(propname, max_size, "%s-gpios", con_id);
else
strscpy(propname, "gpios", max_size);
}
static int swnode_gpiochip_match_name(struct gpio_chip *chip, void *data)
{
return !strcmp(chip->label, data);
}
static struct gpio_chip *swnode_get_chip(struct fwnode_handle *fwnode)
{
const struct software_node *chip_node;
struct gpio_chip *chip;
chip_node = to_software_node(fwnode);
if (!chip_node || !chip_node->name)
return ERR_PTR(-EINVAL);
chip = gpiochip_find((void *)chip_node->name, swnode_gpiochip_match_name);
return chip ?: ERR_PTR(-EPROBE_DEFER);
}
struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
const char *con_id, unsigned int idx,
unsigned long *flags)
{
const struct software_node *swnode;
struct fwnode_reference_args args;
struct gpio_chip *chip;
struct gpio_desc *desc;
char propname[32]; /* 32 is max size of property name */
int error;
swnode = to_software_node(fwnode);
if (!swnode)
return ERR_PTR(-EINVAL);
swnode_format_propname(con_id, propname, sizeof(propname));
/*
* We expect all swnode-described GPIOs have GPIO number and
* polarity arguments, hence nargs is set to 2.
*/
error = fwnode_property_get_reference_args(fwnode, propname, NULL, 2, idx, &args);
if (error) {
pr_debug("%s: can't parse '%s' property of node '%pfwP[%d]'\n",
__func__, propname, fwnode, idx);
return ERR_PTR(error);
}
chip = swnode_get_chip(args.fwnode);
fwnode_handle_put(args.fwnode);
if (IS_ERR(chip))
return ERR_CAST(chip);
desc = gpiochip_get_desc(chip, args.args[0]);
*flags = args.args[1]; /* We expect native GPIO flags */
pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n",
__func__, propname, fwnode, idx, PTR_ERR_OR_ZERO(desc));
return desc;
}
/**
* swnode_gpio_count - count the GPIOs associated with a device / function
* @fwnode: firmware node of the GPIO consumer, can be %NULL for
* system-global GPIOs
* @con_id: function within the GPIO consumer
*
* Return:
* The number of GPIOs associated with a device / function or %-ENOENT,
* if no GPIO has been assigned to the requested function.
*/
int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
{
struct fwnode_reference_args args;
char propname[32];
int count;
swnode_format_propname(con_id, propname, sizeof(propname));
/*
* This is not very efficient, but GPIO lists usually have only
* 1 or 2 entries.
*/
count = 0;
while (fwnode_property_get_reference_args(fwnode, propname, NULL, 0,
count, &args) == 0) {
fwnode_handle_put(args.fwnode);
count++;
}
return count ?: -ENOENT;
}
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef GPIOLIB_SWNODE_H
#define GPIOLIB_SWNODE_H
struct fwnode_handle;
struct gpio_desc;
struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode,
const char *con_id, unsigned int idx,
unsigned long *flags);
int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id);
#endif /* GPIOLIB_SWNODE_H */
This diff is collapsed.
......@@ -15,14 +15,15 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/rwsem.h>
#define GPIOCHIP_NAME "gpiochip"
/**
* struct gpio_device - internal state container for GPIO devices
* @id: numerical ID number for the GPIO chip
* @dev: the GPIO device struct
* @chrdev: character device for the GPIO device
* @id: numerical ID number for the GPIO chip
* @mockdev: class device used by the deprecated sysfs interface (may be
* NULL)
* @owner: helps prevent removal of modules exporting active GPIOs
......@@ -39,6 +40,9 @@
* @list: links gpio_device:s together for traversal
* @notifier: used to notify subscribers about lines being requested, released
* or reconfigured
* @sem: protects the structure from a NULL-pointer dereference of @chip by
* user-space operations when the device gets unregistered during
* a hot-unplug event
* @pin_ranges: range of pins served by the GPIO driver
*
* This state container holds most of the runtime variable data
......@@ -47,9 +51,9 @@
* userspace.
*/
struct gpio_device {
int id;
struct device dev;
struct cdev chrdev;
int id;
struct device *mockdev;
struct module *owner;
struct gpio_chip *chip;
......@@ -60,6 +64,7 @@ struct gpio_device {
void *data;
struct list_head list;
struct blocking_notifier_head notifier;
struct rw_semaphore sem;
#ifdef CONFIG_PINCTRL
/*
......@@ -72,6 +77,11 @@ struct gpio_device {
#endif
};
static inline struct gpio_device *to_gpio_device(struct device *dev)
{
return container_of(dev, struct gpio_device, dev);
}
/* gpio suffixes used for ACPI and device tree lookup */
static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
......
......@@ -635,9 +635,8 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled)
led->priv = priv;
desc = &led->desc;
led->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,
fwnode_child,
GPIOD_ASIS, NULL);
led->gpiod = devm_fwnode_gpiod_get(dev, fwnode_child, NULL,
GPIOD_ASIS, NULL);
if (IS_ERR(led->gpiod)) {
ret = dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n");
goto __dt_err;
......
......@@ -151,9 +151,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
* will be updated after LED class device is registered,
* Only then the final LED name is known.
*/
led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
GPIOD_ASIS,
NULL);
led.gpiod = devm_fwnode_gpiod_get(dev, child, NULL, GPIOD_ASIS,
NULL);
if (IS_ERR(led.gpiod)) {
fwnode_handle_put(child);
return ERR_CAST(led.gpiod);
......
......@@ -11,40 +11,18 @@
#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
/* Platforms may implement their GPIO interface with library code,
/*
* Platforms may implement their GPIO interface with library code,
* at a small performance cost for non-inlined operations and some
* extra memory (for code and for per-GPIO table entries).
*
* While the GPIO programming interface defines valid GPIO numbers
* to be in the range 0..MAX_INT, this library restricts them to the
* smaller range 0..ARCH_NR_GPIOS-1.
*
* ARCH_NR_GPIOS is somewhat arbitrary; it usually reflects the sum of
* builtin/SoC GPIOs plus a number of GPIOs on expanders; the latter is
* actually an estimate of a board-specific value.
*/
#ifndef ARCH_NR_GPIOS
#if defined(CONFIG_ARCH_NR_GPIO) && CONFIG_ARCH_NR_GPIO > 0
#define ARCH_NR_GPIOS CONFIG_ARCH_NR_GPIO
#else
#define ARCH_NR_GPIOS 512
#endif
#endif
/*
* "valid" GPIO numbers are nonnegative and may be passed to
* setup routines like gpio_request(). only some valid numbers
* can successfully be requested and used.
*
* Invalid GPIO numbers are useful for indicating no-such-GPIO in
* platform data and other tables.
* At the end we want all GPIOs to be dynamically allocated from 0.
* However, some legacy drivers still perform fixed allocation.
* Until they are all fixed, leave 0-512 space for them.
*/
static inline bool gpio_is_valid(int number)
{
return number >= 0 && number < ARCH_NR_GPIOS;
}
#define GPIO_DYNAMIC_BASE 512
struct device;
struct gpio;
......@@ -140,12 +118,6 @@ static inline void gpio_unexport(unsigned gpio)
#include <linux/kernel.h>
static inline bool gpio_is_valid(int number)
{
/* only non-negative numbers are valid */
return number >= 0;
}
/* platforms that don't directly support access to GPIOs through I2C, SPI,
* or other blocking infrastructure can use these wrappers.
*/
......@@ -169,4 +141,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
#endif /* !CONFIG_GPIOLIB */
/*
* "valid" GPIO numbers are nonnegative and may be passed to
* setup routines like gpio_request(). only some valid numbers
* can successfully be requested and used.
*
* Invalid GPIO numbers are useful for indicating no-such-GPIO in
* platform data and other tables.
*/
static inline bool gpio_is_valid(int number)
{
/* only non-negative numbers are valid */
return number >= 0;
}
#endif /* _ASM_GENERIC_GPIO_H */
......@@ -581,27 +581,6 @@ struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
flags, label);
}
static inline
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
const char *con_id, int index,
struct fwnode_handle *child,
enum gpiod_flags flags,
const char *label)
{
return devm_fwnode_gpiod_get_index(dev, child, con_id, index,
flags, label);
}
static inline
struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
const char *con_id,
struct fwnode_handle *child,
enum gpiod_flags flags,
const char *label)
{
return devm_fwnode_gpiod_get_index(dev, child, con_id, 0, flags, label);
}
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
struct device_node;
......
// SPDX-License-Identifier: GPL-2.0+
#ifndef __LINUX_GPIO_PROPERTY_H
#define __LINUX_GPIO_PROPERTY_H
#include <dt-bindings/gpio/gpio.h> /* for GPIO_* flags */
#include <linux/property.h>
#define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
PROPERTY_ENTRY_REF(_name_, _chip_node_, _idx_, _flags_)
#endif /* __LINUX_GPIO_PROPERTY_H */
......@@ -34,7 +34,7 @@ enum of_gpio_flags {
#ifdef CONFIG_OF_GPIO
#include <linux/kernel.h>
#include <linux/container_of.h>
/*
* OF GPIO chip for memory mapped banks
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment