gpio updates for v5.13

- new driver for the Realtek Otto GPIO controller
 - ACPI support for gpio-mpc8xxx
 - edge event support for gpio-sch (+ Kconfig fixes)
 - Kconfig improvements in gpio-ich
 - fixes to older issues in gpio-mockup
 - ACPI quirk for ignoring EC wakeups on Dell Venue 10 Pro 5055
 - improve the GPIO aggregator code by using more generic interfaces instead of
   reimplementing them in the driver
 - convert the DT bindings for gpio-74x164 to yaml
 - documentation improvements
 - a slew of other minor fixes and improvements to GPIO drivers
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmCSptQACgkQEacuoBRx
 13KFDQ/+NOkRQuJarKAvGuR5LJ81CbBfH72/m9gJMB9gwNBS7g+esNWrZG/riWVM
 BVs2fxlC52+ppN1rV7iMEaXSyREULrcidgoZ0H7X2vsI9MRkk/fjzpTRwbJbSLPo
 C+IXBAHHfuUC1FQNtQk1cuZXl7PToHd/A14KZIkLOBxLjQddpSo7TTkv23Ub1BA7
 Se13EaDrBJxzfmLR900kAKCFDyM8VRnIt7/euhmlTcXCxOg/lCbGZ4eBpEZasUs5
 UA9PQX0dnnwtMER4b4TQPIdQ345A0l+xqALr8X2leqQ0AqsWQ7kveMwfSRlXI5Hr
 zyuXRiA0e84h6HXIHE59kXqoa4LJVnW59hgjYx0D+fcZ5gNVnaRg/4LsztJmMd/f
 uVAZazE4jd81Cr/kbtpEu5mfGPjOVBeUCeDnKtRovnaSMi24HwqvHqIauI9sM8fN
 locTCYOdLfvxucAJHZ/BWe8yl301/+IlwiHiN+7+/3ljYB+HjAH42rdPwFpP1BWJ
 bpgd90KxLHezeqsv83U9CTTrVK9ZM2yisVunQUo3bVi6Ztxl2Juv16P5Qs0IJW2F
 mly+KNTa4M6NKCdP6luEnazmifFIsnreCzTMfPoa9w+eu/vpIw6lZDFpDAbePV+A
 8XJ99TxV1Bk9kUjvKiEi2qx6uW7f5k8JIwvRvJWhRXkEzufJyUI=
 =5vLN
 -----END PGP SIGNATURE-----

Merge tag 'gpio-updates-for-v5.13-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:

 - new driver for the Realtek Otto GPIO controller

 - ACPI support for gpio-mpc8xxx

 - edge event support for gpio-sch (+ Kconfig fixes)

 - Kconfig improvements in gpio-ich

 - fixes to older issues in gpio-mockup

 - ACPI quirk for ignoring EC wakeups on Dell Venue 10 Pro 5055

 - improve the GPIO aggregator code by using more generic interfaces
   instead of reimplementing them in the driver

 - convert the DT bindings for gpio-74x164 to yaml

 - documentation improvements

 - a slew of other minor fixes and improvements to GPIO drivers

* tag 'gpio-updates-for-v5.13-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (34 commits)
  dt-bindings: gpio: add YAML description for rockchip,gpio-bank
  gpio: mxs: remove useless function
  dt-bindings: gpio: fairchild,74hc595: Convert to json-schema
  gpio: it87: remove unused code
  gpio: 104-dio-48e: Fix coding style issues
  gpio: mpc8xxx: Add ACPI support
  gpio: ich: Switch to be dependent on LPC_ICH
  gpio: sch: Drop MFD_CORE selection
  gpio: sch: depends on LPC_SCH
  gpiolib: acpi: Add quirk to ignore EC wakeups on Dell Venue 10 Pro 5055
  gpio: sch: Hook into ACPI GPE handler to catch GPIO edge events
  gpio: sch: Add edge event support
  gpio: aggregator: Replace custom get_arg() with a generic next_arg()
  lib/cmdline: Export next_arg() for being used in modules
  gpio: omap: Use device_get_match_data() helper
  gpio: Add Realtek Otto GPIO support
  dt-bindings: gpio: Binding for Realtek Otto GPIO
  docs: kernel-parameters: Add gpio_mockup_named_lines
  docs: kernel-parameters: Move gpio-mockup for alphabetic order
  lib: bitmap: provide devm_bitmap_alloc() and devm_bitmap_zalloc()
  ...
This commit is contained in:
Linus Torvalds 2021-05-05 12:39:29 -07:00
commit 5d6a1b84e0
33 changed files with 1067 additions and 349 deletions

View File

@ -17,17 +17,18 @@ module.
gpio_mockup_ranges
This parameter takes an argument in the form of an array of integer
pairs. Each pair defines the base GPIO number (if any) and the number
of lines exposed by the chip. If the base GPIO is -1, the gpiolib
will assign it automatically.
pairs. Each pair defines the base GPIO number (non-negative integer)
and the first number after the last of this chip. If the base GPIO
is -1, the gpiolib will assign it automatically. while the following
parameter is the number of lines exposed by the chip.
Example: gpio_mockup_ranges=-1,8,-1,16,405,4
Example: gpio_mockup_ranges=-1,8,-1,16,405,409
The line above creates three chips. The first one will expose 8 lines,
the second 16 and the third 4. The base GPIO for the third chip is set
to 405 while for two first chips it will be assigned automatically.
gpio_named_lines
gpio_mockup_named_lines
This parameter doesn't take any arguments. It lets the driver know that
GPIO lines exposed by it should be named.

View File

@ -1469,6 +1469,12 @@
Don't use this when you are not running on the
android emulator
gpio-mockup.gpio_mockup_ranges
[HW] Sets the ranges of gpiochip of for this device.
Format: <start1>,<end1>,<start2>,<end2>...
gpio-mockup.gpio_mockup_named_lines
[HW] Let the driver know GPIO lines should be named.
gpt [EFI] Forces disk with valid GPT signature but
invalid Protective MBR to be treated as GPT. If the
primary GPT is corrupted, it enables the backup/alternate
@ -1492,10 +1498,6 @@
Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
Default: 1024
gpio-mockup.gpio_mockup_ranges
[HW] Sets the ranges of gpiochip of for this device.
Format: <start1>,<end1>,<start2>,<end2>...
hardlockup_all_cpu_backtrace=
[KNL] Should the hard-lockup detector generate
backtraces on all cpus.

View File

@ -42,10 +42,10 @@ irq_domain usage
================
An interrupt controller driver creates and registers an irq_domain by
calling one of the irq_domain_add_*() functions (each mapping method
has a different allocator function, more on that later). The function
will return a pointer to the irq_domain on success. The caller must
provide the allocator function with an irq_domain_ops structure.
calling one of the irq_domain_add_*() or irq_domain_create_*() functions
(each mapping method has a different allocator function, more on that later).
The function will return a pointer to the irq_domain on success. The caller
must provide the allocator function with an irq_domain_ops structure.
In most cases, the irq_domain will begin empty without any mappings
between hwirq and IRQ numbers. Mappings are added to the irq_domain
@ -147,6 +147,7 @@ Legacy
irq_domain_add_simple()
irq_domain_add_legacy()
irq_domain_add_legacy_isa()
irq_domain_create_simple()
irq_domain_create_legacy()
The Legacy mapping is a special case for drivers that already have a
@ -169,13 +170,13 @@ supported. For example, ISA controllers would use the legacy map for
mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
numbers.
Most users of legacy mappings should use irq_domain_add_simple() which
will use a legacy domain only if an IRQ range is supplied by the
system and will otherwise use a linear domain mapping. The semantics
of this call are such that if an IRQ range is specified then
Most users of legacy mappings should use irq_domain_add_simple() or
irq_domain_create_simple() which will use a legacy domain only if an IRQ range
is supplied by the system and will otherwise use a linear domain mapping.
The semantics of this call are such that if an IRQ range is specified then
descriptors will be allocated on-the-fly for it, and if no range is
specified it will fall through to irq_domain_add_linear() which means
*no* irq descriptors will be allocated.
specified it will fall through to irq_domain_add_linear() or
irq_domain_create_linear() which means *no* irq descriptors will be allocated.
A typical use case for simple domains is where an irqchip provider
is supporting both dynamic and static IRQ assignments.
@ -186,6 +187,7 @@ that the driver using the simple domain call irq_create_mapping()
before any irq_find_mapping() since the latter will actually work
for the static IRQ assignment case.
irq_domain_add_simple() and irq_domain_create_simple() as well as
irq_domain_add_legacy() and irq_domain_create_legacy() are functionally
equivalent, except for the first argument is different - the former
accepts an Open Firmware specific 'struct device_node', while the latter

View File

@ -0,0 +1,77 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/fairchild,74hc595.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic 8-bit shift register
maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
compatible:
enum:
- fairchild,74hc595
- nxp,74lvc594
reg:
maxItems: 1
gpio-controller: true
'#gpio-cells':
description:
The second cell is only used to specify the GPIO polarity.
const: 2
registers-number:
description: Number of daisy-chained shift registers
enable-gpios:
description: GPIO connected to the OE (Output Enable) pin.
maxItems: 1
spi-max-frequency: true
patternProperties:
"^(hog-[0-9]+|.+-hog(-[0-9]+)?)$":
type: object
properties:
gpio-hog: true
gpios: true
output-high: true
output-low: true
line-name: true
required:
- gpio-hog
- gpios
additionalProperties: false
required:
- compatible
- reg
- gpio-controller
- '#gpio-cells'
- registers-number
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
gpio5: gpio5@0 {
compatible = "fairchild,74hc595";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
registers-number = <4>;
spi-max-frequency = <100000>;
};
};

View File

@ -1,27 +0,0 @@
* Generic 8-bits shift register GPIO driver
Required properties:
- compatible: Should contain one of the following:
"fairchild,74hc595"
"nxp,74lvc594"
- reg : chip select number
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- registers-number: Number of daisy-chained shift registers
Optional properties:
- enable-gpios: GPIO connected to the OE (Output Enable) pin.
Example:
gpio5: gpio5@0 {
compatible = "fairchild,74hc595";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
registers-number = <4>;
spi-max-frequency = <100000>;
};

View File

@ -0,0 +1,78 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/realtek,otto-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek Otto GPIO controller
maintainers:
- Sander Vanheule <sander@svanheule.net>
- Bert Vermeulen <bert@biot.com>
description: |
Realtek's GPIO controller on their MIPS switch SoCs (Otto platform) consists
of two banks of 32 GPIOs. These GPIOs can generate edge-triggered interrupts.
Each bank's interrupts are cascased into one interrupt line on the parent
interrupt controller, if provided.
This binding allows defining a single bank in the devicetree. The interrupt
controller is not supported on the fallback compatible name, which only
allows for GPIO port use.
properties:
$nodename:
pattern: "^gpio@[0-9a-f]+$"
compatible:
items:
- enum:
- realtek,rtl8380-gpio
- realtek,rtl8390-gpio
- const: realtek,otto-gpio
reg:
maxItems: 1
"#gpio-cells":
const: 2
gpio-controller: true
ngpios:
minimum: 1
maximum: 32
interrupt-controller: true
"#interrupt-cells":
const: 2
interrupts:
maxItems: 1
required:
- compatible
- reg
- "#gpio-cells"
- gpio-controller
additionalProperties: false
dependencies:
interrupt-controller: [ interrupts ]
examples:
- |
gpio@3500 {
compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
reg = <0x3500 0x1c>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <24>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&rtlintc>;
interrupts = <23>;
};
...

View File

@ -0,0 +1,82 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/rockchip,gpio-bank.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip GPIO bank
maintainers:
- Heiko Stuebner <heiko@sntech.de>
properties:
compatible:
enum:
- rockchip,gpio-bank
- rockchip,rk3188-gpio-bank0
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
gpio-controller: true
"#gpio-cells":
const: 2
interrupt-controller: true
"#interrupt-cells":
const: 2
required:
- compatible
- reg
- interrupts
- clocks
- gpio-controller
- "#gpio-cells"
- interrupt-controller
- "#interrupt-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
pinctrl: pinctrl {
#address-cells = <1>;
#size-cells = <1>;
ranges;
gpio0: gpio@2000a000 {
compatible = "rockchip,rk3188-gpio-bank0";
reg = <0x2000a000 0x100>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates8 9>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio@2003c000 {
compatible = "rockchip,gpio-bank";
reg = <0x2003c000 0x100>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates8 10>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};

View File

@ -51,23 +51,7 @@ Deprecated properties for iomux controller:
Use rockchip,grf and rockchip,pmu described above instead.
Required properties for gpio sub nodes:
- compatible: "rockchip,gpio-bank"
- reg: register of the gpio bank (different than the iomux registerset)
- interrupts: base interrupt of the gpio bank in the interrupt controller
- clocks: clock that drives this bank
- gpio-controller: identifies the node as a gpio controller and pin bank.
- #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
binding is used, the amount of cells must be specified as 2. See generic
GPIO binding documentation for description of particular cells.
- interrupt-controller: identifies the controller node as interrupt-parent.
- #interrupt-cells: the value of this property should be 2 and the interrupt
cells should use the standard two-cell scheme described in
bindings/interrupt-controller/interrupts.txt
Deprecated properties for gpio sub nodes:
- compatible: "rockchip,rk3188-gpio-bank0"
- reg: second element: separate pull register for rk3188 bank0, use
rockchip,pmu described above instead
See rockchip,gpio-bank.yaml
Required properties for pin configuration node:
- rockchip,pins: 3 integers array, represents a group of pins mux and config
@ -128,43 +112,3 @@ uart2: serial@20064000 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_xfer>;
};
Example for rk3188:
pinctrl@20008000 {
compatible = "rockchip,rk3188-pinctrl";
rockchip,grf = <&grf>;
rockchip,pmu = <&pmu>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
gpio0: gpio0@2000a000 {
compatible = "rockchip,rk3188-gpio-bank0";
reg = <0x2000a000 0x100>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates8 9>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio1: gpio1@2003c000 {
compatible = "rockchip,gpio-bank";
reg = <0x2003c000 0x100>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_gates8 10>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
...
};

View File

@ -12,7 +12,7 @@ Guidelines for GPIOs consumers
Drivers that can't work without standard GPIO calls should have Kconfig entries
that depend on GPIOLIB or select GPIOLIB. The functions that allow a driver to
obtain and use GPIOs are available by including the following file:
obtain and use GPIOs are available by including the following file::
#include <linux/gpio/consumer.h>

View File

@ -96,6 +96,12 @@ hardware descriptions such as device tree or ACPI:
way to pass the charging parameters from hardware descriptions such as the
device tree.
- gpio-mux: drivers/mux/gpio.c is used for controlling a multiplexer using
n GPIO lines such that you can mux in 2^n different devices by activating
different GPIO lines. Often the GPIOs are on a SoC and the devices are
some SoC-external entities, such as different components on a PCB that
can be selectively enabled.
Apart from this there are special GPIO drivers in subsystems like MMC/SD to
read card detect and write protect GPIO lines, and in the TTY serial subsystem
to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The

View File

@ -321,9 +321,8 @@ config GPIO_HLWD
config GPIO_ICH
tristate "Intel ICH GPIO"
depends on PCI && X86
select MFD_CORE
select LPC_ICH
depends on X86
depends on LPC_ICH
help
Say yes here to support the GPIO functionality of a number of Intel
ICH-based chipsets. Currently supported devices: ICH6, ICH7, ICH8
@ -502,6 +501,19 @@ config GPIO_RDA
help
Say Y here to support RDA Micro GPIO controller.
config GPIO_REALTEK_OTTO
tristate "Realtek Otto GPIO support"
depends on MACH_REALTEK_RTL
default MACH_REALTEK_RTL
select GPIO_GENERIC
select GPIOLIB_IRQCHIP
help
The GPIO controller on the Otto MIPS platform supports up to two
banks of 32 GPIOs, with edge triggered interrupts. The 32 GPIOs
are grouped in four 8-bit wide ports.
When built as a module, the module will be called realtek_otto_gpio.
config GPIO_REG
bool
help
@ -847,9 +859,9 @@ config GPIO_IT87
config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
depends on (X86 || COMPILE_TEST) && PCI
select MFD_CORE
select LPC_SCH
depends on (X86 || COMPILE_TEST) && ACPI
depends on LPC_SCH
select GPIOLIB_IRQCHIP
help
Say yes here to support GPIO interface on Intel Poulsbo SCH,
Intel Tunnel Creek processor, Intel Centerton processor or

View File

@ -125,6 +125,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o

View File

@ -49,15 +49,15 @@ struct dio48e_gpio {
unsigned char out_state[6];
unsigned char control[2];
raw_spinlock_t lock;
unsigned base;
unsigned int base;
unsigned char irq_mask;
};
static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned port = offset / 8;
const unsigned mask = BIT(offset % 8);
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
if (dio48egpio->io_state[port] & mask)
return GPIO_LINE_DIRECTION_IN;
@ -65,14 +65,14 @@ static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
return GPIO_LINE_DIRECTION_OUT;
}
static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned io_port = offset / 8;
const unsigned int io_port = offset / 8;
const unsigned int control_port = io_port / 3;
const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
const unsigned int control_addr = dio48egpio->base + 3 + control_port * 4;
unsigned long flags;
unsigned control;
unsigned int control;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
@ -104,17 +104,17 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
return 0;
}
static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned io_port = offset / 8;
const unsigned int io_port = offset / 8;
const unsigned int control_port = io_port / 3;
const unsigned mask = BIT(offset % 8);
const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port;
const unsigned int mask = BIT(offset % 8);
const unsigned int control_addr = dio48egpio->base + 3 + control_port * 4;
const unsigned int out_port = (io_port > 2) ? io_port + 1 : io_port;
unsigned long flags;
unsigned control;
unsigned int control;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
@ -154,14 +154,14 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
static int dio48e_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned port = offset / 8;
const unsigned mask = BIT(offset % 8);
const unsigned in_port = (port > 2) ? port + 1 : port;
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
const unsigned int in_port = (port > 2) ? port + 1 : port;
unsigned long flags;
unsigned port_state;
unsigned int port_state;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
@ -202,12 +202,12 @@ static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
return 0;
}
static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static void dio48e_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned port = offset / 8;
const unsigned mask = BIT(offset % 8);
const unsigned out_port = (port > 2) ? port + 1 : port;
const unsigned int port = offset / 8;
const unsigned int mask = BIT(offset % 8);
const unsigned int out_port = (port > 2) ? port + 1 : port;
unsigned long flags;
raw_spin_lock_irqsave(&dio48egpio->lock, flags);
@ -306,7 +306,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type)
static int dio48e_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
const unsigned long offset = irqd_to_hwirq(data);

View File

@ -37,31 +37,6 @@ struct gpio_aggregator {
static DEFINE_MUTEX(gpio_aggregator_lock); /* protects idr */
static DEFINE_IDR(gpio_aggregator_idr);
static char *get_arg(char **args)
{
char *start, *end;
start = skip_spaces(*args);
if (!*start)
return NULL;
if (*start == '"') {
/* Quoted arg */
end = strchr(++start, '"');
if (!end)
return ERR_PTR(-EINVAL);
} else {
/* Unquoted arg */
for (end = start; *end && !isspace(*end); end++) ;
}
if (*end)
*end++ = '\0';
*args = end;
return start;
}
static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,
int hwnum, unsigned int *n)
{
@ -83,8 +58,8 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,
static int aggr_parse(struct gpio_aggregator *aggr)
{
char *args = skip_spaces(aggr->args);
char *name, *offsets, *p;
char *args = aggr->args;
unsigned long *bitmap;
unsigned int i, n = 0;
int error = 0;
@ -93,13 +68,9 @@ static int aggr_parse(struct gpio_aggregator *aggr)
if (!bitmap)
return -ENOMEM;
for (name = get_arg(&args), offsets = get_arg(&args); name;
offsets = get_arg(&args)) {
if (IS_ERR(name)) {
pr_err("Cannot get GPIO specifier: %pe\n", name);
error = PTR_ERR(name);
goto free_bitmap;
}
args = next_arg(args, &name, &p);
while (*args) {
args = next_arg(args, &offsets, &p);
p = get_options(offsets, 0, &error);
if (error == 0 || *p) {
@ -125,7 +96,7 @@ static int aggr_parse(struct gpio_aggregator *aggr)
goto free_bitmap;
}
name = get_arg(&args);
args = next_arg(args, &name, &p);
}
if (!n) {

View File

@ -5,13 +5,11 @@
* Copyright (C) 2010 Extreme Engineering Solutions.
*/
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/ioport.h>
#include <linux/mfd/lpc_ich.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#define DRV_NAME "gpio_ich"

View File

@ -125,14 +125,6 @@ static inline int superio_inw(int reg)
return val;
}
static inline void superio_outw(int val, int reg)
{
outb(reg++, REG);
outb(val >> 8, VAL);
outb(reg, REG);
outb(val, VAL);
}
static inline void superio_set_mask(int mask, int reg)
{
u8 curr_val = superio_inb(reg);

View File

@ -479,15 +479,10 @@ static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC];
static void gpio_mockup_unregister_pdevs(void)
{
struct platform_device *pdev;
int i;
for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) {
pdev = gpio_mockup_pdevs[i];
if (pdev)
platform_device_unregister(pdev);
}
for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++)
platform_device_unregister(gpio_mockup_pdevs[i]);
}
static __init char **gpio_mockup_make_line_names(const char *label,

View File

@ -9,6 +9,7 @@
* kind, whether express or implied.
*/
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@ -18,6 +19,8 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/property.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/gpio/driver.h>
@ -303,8 +306,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct mpc8xxx_gpio_chip *mpc8xxx_gc;
struct gpio_chip *gc;
const struct mpc8xxx_gpio_devtype *devtype =
of_device_get_match_data(&pdev->dev);
const struct mpc8xxx_gpio_devtype *devtype = NULL;
struct fwnode_handle *fwnode;
int ret;
mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
@ -315,14 +318,14 @@ static int mpc8xxx_probe(struct platform_device *pdev)
raw_spin_lock_init(&mpc8xxx_gc->lock);
mpc8xxx_gc->regs = of_iomap(np, 0);
if (!mpc8xxx_gc->regs)
return -ENOMEM;
mpc8xxx_gc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mpc8xxx_gc->regs))
return PTR_ERR(mpc8xxx_gc->regs);
gc = &mpc8xxx_gc->gc;
gc->parent = &pdev->dev;
if (of_property_read_bool(np, "little-endian")) {
if (device_property_read_bool(&pdev->dev, "little-endian")) {
ret = bgpio_init(gc, &pdev->dev, 4,
mpc8xxx_gc->regs + GPIO_DAT,
NULL, NULL,
@ -345,6 +348,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
mpc8xxx_gc->direction_output = gc->direction_output;
devtype = device_get_match_data(&pdev->dev);
if (!devtype)
devtype = &mpc8xxx_gpio_devtype_default;
@ -369,24 +373,29 @@ static int mpc8xxx_probe(struct platform_device *pdev)
* associated input enable must be set (GPIOxGPIE[IEn]=1) to propagate
* the port value to the GPIO Data Register.
*/
fwnode = dev_fwnode(&pdev->dev);
if (of_device_is_compatible(np, "fsl,qoriq-gpio") ||
of_device_is_compatible(np, "fsl,ls1028a-gpio") ||
of_device_is_compatible(np, "fsl,ls1088a-gpio"))
of_device_is_compatible(np, "fsl,ls1088a-gpio") ||
is_acpi_node(fwnode))
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
ret = gpiochip_add_data(gc, mpc8xxx_gc);
if (ret) {
pr_err("%pOF: GPIO chip registration failed with status %d\n",
np, ret);
dev_err(&pdev->dev,
"GPIO chip registration failed with status %d\n", ret);
goto err;
}
mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0);
mpc8xxx_gc->irqn = platform_get_irq(pdev, 0);
if (!mpc8xxx_gc->irqn)
return 0;
mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS,
&mpc8xxx_gpio_irq_ops, mpc8xxx_gc);
mpc8xxx_gc->irq = irq_domain_create_linear(fwnode,
MPC8XXX_GPIO_PINS,
&mpc8xxx_gpio_irq_ops,
mpc8xxx_gc);
if (!mpc8xxx_gc->irq)
return 0;
@ -399,8 +408,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
IRQF_SHARED, "gpio-cascade",
mpc8xxx_gc);
if (ret) {
dev_err(&pdev->dev, "%s: failed to devm_request_irq(%d), ret = %d\n",
np->full_name, mpc8xxx_gc->irqn, ret);
dev_err(&pdev->dev,
"failed to devm_request_irq(%d), ret = %d\n",
mpc8xxx_gc->irqn, ret);
goto err;
}
@ -425,12 +435,21 @@ static int mpc8xxx_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_ACPI
static const struct acpi_device_id gpio_acpi_ids[] = {
{"NXP0031",},
{ }
};
MODULE_DEVICE_TABLE(acpi, gpio_acpi_ids);
#endif
static struct platform_driver mpc8xxx_plat_driver = {
.probe = mpc8xxx_probe,
.remove = mpc8xxx_remove,
.driver = {
.name = "gpio-mpc8xxx",
.of_match_table = mpc8xxx_gpio_ids,
.acpi_match_table = ACPI_PTR(gpio_acpi_ids),
},
};

View File

@ -60,11 +60,6 @@ static inline int is_imx23_gpio(struct mxs_gpio_port *port)
return port->devid == IMX23_GPIO;
}
static inline int is_imx28_gpio(struct mxs_gpio_port *port)
{
return port->devid == IMX28_GPIO;
}
/* Note: This driver assumes 32 GPIOs are handled in one register */
static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)

View File

@ -1373,15 +1373,14 @@ static int omap_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
const struct of_device_id *match;
const struct omap_gpio_platform_data *pdata;
struct gpio_bank *bank;
struct irq_chip *irqc;
int ret;
match = of_match_device(of_match_ptr(omap_gpio_match), dev);
pdata = device_get_match_data(dev);
pdata = match ? match->data : dev_get_platdata(dev);
pdata = pdata ?: dev_get_platdata(dev);
if (!pdata)
return -EINVAL;

View File

@ -0,0 +1,325 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/gpio/driver.h>
#include <linux/irq.h>
#include <linux/minmax.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
/*
* Total register block size is 0x1C for one bank of four ports (A, B, C, D).
* An optional second bank, with ports E, F, G, and H, may be present, starting
* at register offset 0x1C.
*/
/*
* Pin select: (0) "normal", (1) "dedicate peripheral"
* Not used on RTL8380/RTL8390, peripheral selection is managed by control bits
* in the peripheral registers.
*/
#define REALTEK_GPIO_REG_CNR 0x00
/* Clear bit (0) for input, set bit (1) for output */
#define REALTEK_GPIO_REG_DIR 0x08
#define REALTEK_GPIO_REG_DATA 0x0C
/* Read bit for IRQ status, write 1 to clear IRQ */
#define REALTEK_GPIO_REG_ISR 0x10
/* Two bits per GPIO in IMR registers */
#define REALTEK_GPIO_REG_IMR 0x14
#define REALTEK_GPIO_REG_IMR_AB 0x14
#define REALTEK_GPIO_REG_IMR_CD 0x18
#define REALTEK_GPIO_IMR_LINE_MASK GENMASK(1, 0)
#define REALTEK_GPIO_IRQ_EDGE_FALLING 1
#define REALTEK_GPIO_IRQ_EDGE_RISING 2
#define REALTEK_GPIO_IRQ_EDGE_BOTH 3
#define REALTEK_GPIO_MAX 32
#define REALTEK_GPIO_PORTS_PER_BANK 4
/**
* realtek_gpio_ctrl - Realtek Otto GPIO driver data
*
* @gc: Associated gpio_chip instance
* @base: Base address of the register block for a GPIO bank
* @lock: Lock for accessing the IRQ registers and values
* @intr_mask: Mask for interrupts lines
* @intr_type: Interrupt type selection
*
* Because the interrupt mask register (IMR) combines the function of IRQ type
* selection and masking, two extra values are stored. @intr_mask is used to
* mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
* the selected interrupt types. The logical AND of these values is written to
* IMR on changes.
*/
struct realtek_gpio_ctrl {
struct gpio_chip gc;
void __iomem *base;
raw_spinlock_t lock;
u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
};
/* Expand with more flags as devices with other quirks are added */
enum realtek_gpio_flags {
/*
* Allow disabling interrupts, for cases where the port order is
* unknown. This may result in a port mismatch between ISR and IMR.
* An interrupt would appear to come from a different line than the
* line the IRQ handler was assigned to, causing uncaught interrupts.
*/
GPIO_INTERRUPTS_DISABLED = BIT(0),
};
static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
return container_of(gc, struct realtek_gpio_ctrl, gc);
}
/*
* Normal port order register access
*
* Port information is stored with the first port at offset 0, followed by the
* second, etc. Most registers store one bit per GPIO and use a u8 value per
* port. The two interrupt mask registers store two bits per GPIO, so use u16
* values.
*/
static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
unsigned int port, u16 irq_type, u16 irq_mask)
{
iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
}
static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
unsigned int port, u8 mask)
{
iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
}
static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
{
return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
}
/* Set the rising and falling edge mask bits for a GPIO port pin */
static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
{
return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
}
static void realtek_gpio_irq_ack(struct irq_data *data)
{
struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
irq_hw_number_t line = irqd_to_hwirq(data);
unsigned int port = line / 8;
unsigned int port_pin = line % 8;
realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
}
static void realtek_gpio_irq_unmask(struct irq_data *data)
{
struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
unsigned int line = irqd_to_hwirq(data);
unsigned int port = line / 8;
unsigned int port_pin = line % 8;
unsigned long flags;
u16 m;
raw_spin_lock_irqsave(&ctrl->lock, flags);
m = ctrl->intr_mask[port];
m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
ctrl->intr_mask[port] = m;
realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static void realtek_gpio_irq_mask(struct irq_data *data)
{
struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
unsigned int line = irqd_to_hwirq(data);
unsigned int port = line / 8;
unsigned int port_pin = line % 8;
unsigned long flags;
u16 m;
raw_spin_lock_irqsave(&ctrl->lock, flags);
m = ctrl->intr_mask[port];
m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
ctrl->intr_mask[port] = m;
realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
}
static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
unsigned int line = irqd_to_hwirq(data);
unsigned int port = line / 8;
unsigned int port_pin = line % 8;
unsigned long flags;
u16 type, t;
switch (flow_type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_FALLING:
type = REALTEK_GPIO_IRQ_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_RISING:
type = REALTEK_GPIO_IRQ_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_BOTH:
type = REALTEK_GPIO_IRQ_EDGE_BOTH;
break;
default:
return -EINVAL;
}
irq_set_handler_locked(data, handle_edge_irq);
raw_spin_lock_irqsave(&ctrl->lock, flags);
t = ctrl->intr_type[port];
t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
t |= realtek_gpio_imr_bits(port_pin, type);
ctrl->intr_type[port] = t;
realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
raw_spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
static void realtek_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
unsigned int lines_done;
unsigned int port_pin_count;
unsigned int irq;
unsigned long status;
int offset;
chained_irq_enter(irq_chip, desc);
for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
status = realtek_gpio_read_isr(ctrl, lines_done / 8);
port_pin_count = min(gc->ngpio - lines_done, 8U);
for_each_set_bit(offset, &status, port_pin_count) {
irq = irq_find_mapping(gc->irq.domain, offset);
generic_handle_irq(irq);
}
}
chained_irq_exit(irq_chip, desc);
}
static int realtek_gpio_irq_init(struct gpio_chip *gc)
{
struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
unsigned int port;
for (port = 0; (port * 8) < gc->ngpio; port++) {
realtek_gpio_write_imr(ctrl, port, 0, 0);
realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
}
return 0;
}
static struct irq_chip realtek_gpio_irq_chip = {
.name = "realtek-otto-gpio",
.irq_ack = realtek_gpio_irq_ack,
.irq_mask = realtek_gpio_irq_mask,
.irq_unmask = realtek_gpio_irq_unmask,
.irq_set_type = realtek_gpio_irq_set_type,
};
static const struct of_device_id realtek_gpio_of_match[] = {
{
.compatible = "realtek,otto-gpio",
.data = (void *)GPIO_INTERRUPTS_DISABLED,
},
{
.compatible = "realtek,rtl8380-gpio",
},
{
.compatible = "realtek,rtl8390-gpio",
},
{}
};
MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
static int realtek_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
unsigned int dev_flags;
struct gpio_irq_chip *girq;
struct realtek_gpio_ctrl *ctrl;
u32 ngpios;
int err, irq;
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return -ENOMEM;
dev_flags = (unsigned int) device_get_match_data(dev);
ngpios = REALTEK_GPIO_MAX;
device_property_read_u32(dev, "ngpios", &ngpios);
if (ngpios > REALTEK_GPIO_MAX) {
dev_err(&pdev->dev, "invalid ngpios (max. %d)\n",
REALTEK_GPIO_MAX);
return -EINVAL;
}
ctrl->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctrl->base))
return PTR_ERR(ctrl->base);
raw_spin_lock_init(&ctrl->lock);
err = bgpio_init(&ctrl->gc, dev, 4,
ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (err) {
dev_err(dev, "unable to init generic GPIO");
return err;
}
ctrl->gc.ngpio = ngpios;
ctrl->gc.owner = THIS_MODULE;
irq = platform_get_irq_optional(pdev, 0);
if (!(dev_flags & GPIO_INTERRUPTS_DISABLED) && irq > 0) {
girq = &ctrl->gc.irq;
girq->chip = &realtek_gpio_irq_chip;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->parent_handler = realtek_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, girq->num_parents,
sizeof(*girq->parents), GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = irq;
girq->init_hw = realtek_gpio_irq_init;
}
return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
}
static struct platform_driver realtek_gpio_driver = {
.driver = {
.name = "realtek-otto-gpio",
.of_match_table = realtek_gpio_of_match,
},
.probe = realtek_gpio_probe,
};
module_platform_driver(realtek_gpio_driver);
MODULE_DESCRIPTION("Realtek Otto GPIO support");
MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
MODULE_LICENSE("GPL v2");

View File

@ -7,33 +7,55 @@
*/
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#define GEN 0x00
#define GIO 0x04
#define GLV 0x08
#define GTPE 0x0c
#define GTNE 0x10
#define GGPE 0x14
#define GSMI 0x18
#define GTS 0x1c
#define CORE_BANK_OFFSET 0x00
#define RESUME_BANK_OFFSET 0x20
/*
* iLB datasheet describes GPE0BLK registers, in particular GPE0E.GPIO bit.
* Document Number: 328195-001
*/
#define GPE0E_GPIO 14
struct sch_gpio {
struct gpio_chip chip;
struct irq_chip irqchip;
spinlock_t lock;
unsigned short iobase;
unsigned short resume_base;
/* GPE handling */
u32 gpe;
acpi_gpe_handler gpe_handler;
};
static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio,
unsigned int reg)
{
unsigned int base = 0;
unsigned int base = CORE_BANK_OFFSET;
if (gpio >= sch->resume_base) {
gpio -= sch->resume_base;
base += 0x20;
base = RESUME_BANK_OFFSET;
}
return base + reg + gpio / 8;
@ -79,10 +101,11 @@ static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned int gpio, unsigned i
static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
unsigned long flags;
spin_lock(&sch->lock);
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GIO, 1);
spin_unlock(&sch->lock);
spin_unlock_irqrestore(&sch->lock, flags);
return 0;
}
@ -96,20 +119,22 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num)
static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
unsigned long flags;
spin_lock(&sch->lock);
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GLV, val);
spin_unlock(&sch->lock);
spin_unlock_irqrestore(&sch->lock, flags);
}
static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
int val)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
unsigned long flags;
spin_lock(&sch->lock);
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GIO, 0);
spin_unlock(&sch->lock);
spin_unlock_irqrestore(&sch->lock, flags);
/*
* according to the datasheet, writing to the level register has no
@ -144,10 +169,145 @@ static const struct gpio_chip sch_gpio_chip = {
.get_direction = sch_gpio_get_direction,
};
static int sch_irq_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sch_gpio *sch = gpiochip_get_data(gc);
irq_hw_number_t gpio_num = irqd_to_hwirq(d);
unsigned long flags;
int rising, falling;
switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_RISING:
rising = 1;
falling = 0;
break;
case IRQ_TYPE_EDGE_FALLING:
rising = 0;
falling = 1;
break;
case IRQ_TYPE_EDGE_BOTH:
rising = 1;
falling = 1;
break;
default:
return -EINVAL;
}
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
irq_set_handler_locked(d, handle_edge_irq);
spin_unlock_irqrestore(&sch->lock, flags);
return 0;
}
static void sch_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sch_gpio *sch = gpiochip_get_data(gc);
irq_hw_number_t gpio_num = irqd_to_hwirq(d);
unsigned long flags;
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GTS, 1);
spin_unlock_irqrestore(&sch->lock, flags);
}
static void sch_irq_mask_unmask(struct irq_data *d, int val)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sch_gpio *sch = gpiochip_get_data(gc);
irq_hw_number_t gpio_num = irqd_to_hwirq(d);
unsigned long flags;
spin_lock_irqsave(&sch->lock, flags);
sch_gpio_reg_set(sch, gpio_num, GGPE, val);
spin_unlock_irqrestore(&sch->lock, flags);
}
static void sch_irq_mask(struct irq_data *d)
{
sch_irq_mask_unmask(d, 0);
}
static void sch_irq_unmask(struct irq_data *d)
{
sch_irq_mask_unmask(d, 1);
}
static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
{
struct sch_gpio *sch = context;
struct gpio_chip *gc = &sch->chip;
unsigned long core_status, resume_status;
unsigned long pending;
unsigned long flags;
int offset;
u32 ret;
spin_lock_irqsave(&sch->lock, flags);
core_status = inl(sch->iobase + CORE_BANK_OFFSET + GTS);
resume_status = inl(sch->iobase + RESUME_BANK_OFFSET + GTS);
spin_unlock_irqrestore(&sch->lock, flags);
pending = (resume_status << sch->resume_base) | core_status;
for_each_set_bit(offset, &pending, sch->chip.ngpio)
generic_handle_irq(irq_find_mapping(gc->irq.domain, offset));
/* Set returning value depending on whether we handled an interrupt */
ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
/* Acknowledge GPE to ACPICA */
ret |= ACPI_REENABLE_GPE;
return ret;
}
static void sch_gpio_remove_gpe_handler(void *data)
{
struct sch_gpio *sch = data;
acpi_disable_gpe(NULL, sch->gpe);
acpi_remove_gpe_handler(NULL, sch->gpe, sch->gpe_handler);
}
static int sch_gpio_install_gpe_handler(struct sch_gpio *sch)
{
struct device *dev = sch->chip.parent;
acpi_status status;
status = acpi_install_gpe_handler(NULL, sch->gpe, ACPI_GPE_LEVEL_TRIGGERED,
sch->gpe_handler, sch);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to install GPE handler for %u: %s\n",
sch->gpe, acpi_format_exception(status));
return -ENODEV;
}
status = acpi_enable_gpe(NULL, sch->gpe);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to enable GPE handler for %u: %s\n",
sch->gpe, acpi_format_exception(status));
acpi_remove_gpe_handler(NULL, sch->gpe, sch->gpe_handler);
return -ENODEV;
}
return devm_add_action_or_reset(dev, sch_gpio_remove_gpe_handler, sch);
}
static int sch_gpio_probe(struct platform_device *pdev)
{
struct gpio_irq_chip *girq;
struct sch_gpio *sch;
struct resource *res;
int ret;
sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
if (!sch)
@ -207,6 +367,28 @@ static int sch_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, sch);
sch->irqchip.name = "sch_gpio";
sch->irqchip.irq_ack = sch_irq_ack;
sch->irqchip.irq_mask = sch_irq_mask;
sch->irqchip.irq_unmask = sch_irq_unmask;
sch->irqchip.irq_set_type = sch_irq_type;
girq = &sch->chip.irq;
girq->chip = &sch->irqchip;
girq->num_parents = 0;
girq->parents = NULL;
girq->parent_handler = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
/* GPE setup is optional */
sch->gpe = GPE0E_GPIO;
sch->gpe_handler = sch_gpio_gpe_handler;
ret = sch_gpio_install_gpe_handler(sch);
if (ret)
dev_warn(&pdev->dev, "Can't setup GPE, no IRQ support\n");
return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
}

View File

@ -1291,6 +1291,13 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
kfree(acpi_gpio);
}
void acpi_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev)
{
/* Set default fwnode to parent's one if present */
if (gc->parent)
ACPI_COMPANION_SET(&gdev->dev, ACPI_COMPANION(gc->parent));
}
static int acpi_gpio_package_count(const union acpi_object *obj)
{
const union acpi_object *element = obj->package.elements;
@ -1438,6 +1445,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
.no_edge_events_on_boot = true,
},
},
{
/*
* The Dell Venue 10 Pro 5055, with Bay Trail SoC + TI PMIC uses an
* external embedded-controller connected via I2C + an ACPI GPIO
* event handler on INT33FFC:02 pin 12, causing spurious wakeups.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
},
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
.ignore_wake = "INT33FC:02@12",
},
},
{
/*
* HP X2 10 models with Cherry Trail SoC + TI PMIC use an

View File

@ -36,6 +36,8 @@ struct acpi_gpio_info {
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
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);
@ -58,6 +60,8 @@ int acpi_gpio_count(struct device *dev, const char *con_id);
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
static inline void acpi_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev) { }
static inline void
acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }

View File

@ -1042,11 +1042,13 @@ void of_gpiochip_remove(struct gpio_chip *chip)
void of_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev)
{
/* Set default OF node to parent's one if present */
if (gc->parent)
gdev->dev.of_node = gc->parent->of_node;
/* If the gpiochip has an assigned OF node this takes precedence */
if (gc->of_node)
gdev->dev.of_node = gc->of_node;
else
gc->of_node = gdev->dev.of_node;
if (gdev->dev.of_node)
gdev->dev.fwnode = of_fwnode_handle(gdev->dev.of_node);
}

View File

@ -586,14 +586,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (!gdev)
return -ENOMEM;
gdev->dev.bus = &gpio_bus_type;
gdev->dev.parent = gc->parent;
gdev->chip = gc;
gc->gpiodev = gdev;
if (gc->parent) {
gdev->dev.parent = gc->parent;
gdev->dev.of_node = gc->parent->of_node;
}
of_gpio_dev_init(gc, gdev);
acpi_gpio_dev_init(gc, gdev);
/*
* Assign fwnode depending on the result of the previous calls,
@ -1465,9 +1463,8 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
struct fwnode_handle *fwnode = dev_fwnode(&gc->gpiodev->dev);
struct irq_chip *irqchip = gc->irq.chip;
const struct irq_domain_ops *ops = NULL;
struct device_node *np;
unsigned int type;
unsigned int i;
@ -1479,7 +1476,6 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
return -EINVAL;
}
np = gc->gpiodev->dev.of_node;
type = gc->irq.default_type;
/*
@ -1487,16 +1483,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
* used to configure the interrupts, as you may end up with
* conflicting triggers. Tell the user, and reset to NONE.
*/
if (WARN(np && type != IRQ_TYPE_NONE,
"%s: Ignoring %u default trigger\n", np->full_name, type))
if (WARN(fwnode && type != IRQ_TYPE_NONE,
"%pfw: Ignoring %u default trigger\n", fwnode, type))
type = IRQ_TYPE_NONE;
if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) {
acpi_handle_warn(ACPI_HANDLE(gc->parent),
"Ignoring %u default trigger\n", type);
type = IRQ_TYPE_NONE;
}
if (gc->to_irq)
chip_warn(gc, "to_irq is redefined in %s and you shouldn't rely on it\n", __func__);
@ -1512,15 +1502,11 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
return ret;
} else {
/* Some drivers provide custom irqdomain ops */
if (gc->irq.domain_ops)
ops = gc->irq.domain_ops;
if (!ops)
ops = &gpiochip_domain_ops;
gc->irq.domain = irq_domain_add_simple(np,
gc->irq.domain = irq_domain_create_simple(fwnode,
gc->ngpio,
gc->irq.first,
ops, gc);
gc->irq.domain_ops ?: &gpiochip_domain_ops,
gc);
if (!gc->irq.domain)
return -EINVAL;
}
@ -3684,11 +3670,12 @@ EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index);
*/
int gpiod_count(struct device *dev, const char *con_id)
{
const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL;
int count = -ENOENT;
if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
if (is_of_node(fwnode))
count = of_gpio_get_count(dev, con_id);
else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev))
else if (is_acpi_node(fwnode))
count = acpi_gpio_count(dev, con_id);
if (count < 0)
@ -3826,18 +3813,17 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
int ret;
/* Maybe we have a device name, maybe not */
const char *devname = dev ? dev_name(dev) : "?";
const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL;
dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
if (dev) {
/* Using device tree? */
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
dev_dbg(dev, "using device tree for GPIO lookup\n");
desc = of_find_gpio(dev, con_id, idx, &lookupflags);
} else if (ACPI_COMPANION(dev)) {
dev_dbg(dev, "using ACPI for GPIO lookup\n");
desc = acpi_find_gpio(dev, con_id, idx, &flags, &lookupflags);
}
/* Using device tree? */
if (is_of_node(fwnode)) {
dev_dbg(dev, "using device tree for GPIO lookup\n");
desc = of_find_gpio(dev, con_id, idx, &lookupflags);
} else if (is_acpi_node(fwnode)) {
dev_dbg(dev, "using ACPI for GPIO lookup\n");
desc = acpi_find_gpio(dev, con_id, idx, &flags, &lookupflags);
}
/*
@ -3921,9 +3907,6 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
struct gpio_desc *desc = ERR_PTR(-ENODEV);
int ret;
if (!fwnode)
return ERR_PTR(-EINVAL);
if (is_of_node(fwnode)) {
desc = gpiod_get_from_of_node(to_of_node(fwnode),
propname, index,
@ -3939,7 +3922,8 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
acpi_gpio_update_gpiod_flags(&dflags, &info);
acpi_gpio_update_gpiod_lookup_flags(&lflags, &info);
}
} else
return ERR_PTR(-EINVAL);
/* Currently only ACPI takes this path */
ret = gpiod_request(desc, label);
@ -4220,11 +4204,13 @@ EXPORT_SYMBOL_GPL(gpiod_put_array);
static int gpio_bus_match(struct device *dev, struct device_driver *drv)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
/*
* Only match if the fwnode doesn't already have a proper struct device
* created for it.
*/
if (dev->fwnode && dev->fwnode->dev != dev)
if (fwnode && fwnode->dev != dev)
return 0;
return 1;
}

View File

@ -4,10 +4,12 @@
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
struct device;
/*
* bitmaps provide bit arrays that consume one or more unsigned
@ -118,54 +120,59 @@
* Allocation and deallocation of bitmap.
* Provided in lib/bitmap.c to avoid circular dependency.
*/
extern unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags);
extern unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags);
extern void bitmap_free(const unsigned long *bitmap);
unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags);
unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags);
void bitmap_free(const unsigned long *bitmap);
/* Managed variants of the above. */
unsigned long *devm_bitmap_alloc(struct device *dev,
unsigned int nbits, gfp_t flags);
unsigned long *devm_bitmap_zalloc(struct device *dev,
unsigned int nbits, gfp_t flags);
/*
* lib/bitmap.c provides these functions:
*/
extern int __bitmap_equal(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern bool __pure __bitmap_or_equal(const unsigned long *src1,
const unsigned long *src2,
const unsigned long *src3,
unsigned int nbits);
extern void __bitmap_complement(unsigned long *dst, const unsigned long *src,
unsigned int nbits);
extern void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
unsigned int shift, unsigned int nbits);
extern void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
unsigned int shift, unsigned int nbits);
extern void bitmap_cut(unsigned long *dst, const unsigned long *src,
unsigned int first, unsigned int cut,
unsigned int nbits);
extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
int __bitmap_equal(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
bool __pure __bitmap_or_equal(const unsigned long *src1,
const unsigned long *src2,
const unsigned long *src3,
unsigned int nbits);
void __bitmap_complement(unsigned long *dst, const unsigned long *src,
unsigned int nbits);
void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
unsigned int shift, unsigned int nbits);
void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
unsigned int shift, unsigned int nbits);
void bitmap_cut(unsigned long *dst, const unsigned long *src,
unsigned int first, unsigned int cut, unsigned int nbits);
int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
void __bitmap_replace(unsigned long *dst,
const unsigned long *old, const unsigned long *new,
const unsigned long *mask, unsigned int nbits);
int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern void __bitmap_replace(unsigned long *dst,
const unsigned long *old, const unsigned long *new,
const unsigned long *mask, unsigned int nbits);
extern int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern int __bitmap_subset(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
extern int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
extern void __bitmap_set(unsigned long *map, unsigned int start, int len);
extern void __bitmap_clear(unsigned long *map, unsigned int start, int len);
int __bitmap_subset(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int nbits);
int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
void __bitmap_set(unsigned long *map, unsigned int start, int len);
void __bitmap_clear(unsigned long *map, unsigned int start, int len);
extern unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long size,
unsigned long start,
unsigned int nr,
unsigned long align_mask,
unsigned long align_offset);
unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long size,
unsigned long start,
unsigned int nr,
unsigned long align_mask,
unsigned long align_offset);
/**
* bitmap_find_next_zero_area - find a contiguous aligned zero area
@ -190,33 +197,33 @@ bitmap_find_next_zero_area(unsigned long *map,
align_mask, 0);
}
extern int bitmap_parse(const char *buf, unsigned int buflen,
int bitmap_parse(const char *buf, unsigned int buflen,
unsigned long *dst, int nbits);
extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
unsigned long *dst, int nbits);
extern int bitmap_parselist(const char *buf, unsigned long *maskp,
int bitmap_parselist(const char *buf, unsigned long *maskp,
int nmaskbits);
extern int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen,
int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen,
unsigned long *dst, int nbits);
extern void bitmap_remap(unsigned long *dst, const unsigned long *src,
void bitmap_remap(unsigned long *dst, const unsigned long *src,
const unsigned long *old, const unsigned long *new, unsigned int nbits);
extern int bitmap_bitremap(int oldbit,
int bitmap_bitremap(int oldbit,
const unsigned long *old, const unsigned long *new, int bits);
extern void bitmap_onto(unsigned long *dst, const unsigned long *orig,
void bitmap_onto(unsigned long *dst, const unsigned long *orig,
const unsigned long *relmap, unsigned int bits);
extern void bitmap_fold(unsigned long *dst, const unsigned long *orig,
void bitmap_fold(unsigned long *dst, const unsigned long *orig,
unsigned int sz, unsigned int nbits);
extern int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order);
extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order);
extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order);
int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order);
void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order);
int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order);
#ifdef __BIG_ENDIAN
extern void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits);
void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits);
#else
#define bitmap_copy_le bitmap_copy
#endif
extern unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int ord, unsigned int nbits);
extern int bitmap_print_to_pagebuf(bool list, char *buf,
unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int ord, unsigned int nbits);
int bitmap_print_to_pagebuf(bool list, char *buf,
const unsigned long *maskp, int nmaskbits);
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
@ -265,9 +272,9 @@ static inline void bitmap_copy_clear_tail(unsigned long *dst,
* therefore conversion is not needed when copying data from/to arrays of u32.
*/
#if BITS_PER_LONG == 64
extern void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
unsigned int nbits);
extern void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap,
void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap,
unsigned int nbits);
#else
#define bitmap_from_arr32(bitmap, buf, nbits) \

View File

@ -227,7 +227,7 @@ struct gpio_irq_chip {
/**
* @valid_mask:
*
* If not %NULL holds bitmask of GPIOs which are valid to be included
* If not %NULL, holds bitmask of GPIOs which are valid to be included
* in IRQ domain of the chip.
*/
unsigned long *valid_mask;
@ -346,7 +346,7 @@ struct gpio_irq_chip {
* output.
*
* A gpio_chip can help platforms abstract various sources of GPIOs so
* they can all be accessed through a common programing interface.
* they can all be accessed through a common programming interface.
* Example sources would be SOC controllers, FPGAs, multifunction
* chips, dedicated GPIO expanders, and so on.
*
@ -435,15 +435,15 @@ struct gpio_chip {
/**
* @valid_mask:
*
* If not %NULL holds bitmask of GPIOs which are valid to be used
* If not %NULL, holds bitmask of GPIOs which are valid to be used
* from the chip.
*/
unsigned long *valid_mask;
#if defined(CONFIG_OF_GPIO)
/*
* If CONFIG_OF is enabled, then all GPIO controllers described in the
* device tree automatically may have an OF translation
* If CONFIG_OF_GPIO is enabled, then all GPIO controllers described in
* the device tree automatically may have an OF translation
*/
/**
@ -508,7 +508,7 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
* for GPIOs will fail rudely.
*
* gpiochip_add_data() must only be called after gpiolib initialization,
* ie after core_initcall().
* i.e. after core_initcall().
*
* If gc->base is negative, this requests dynamic assignment of
* a range of valid GPIOs.

View File

@ -256,11 +256,11 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
void *host_data);
struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
unsigned int size,
unsigned int first_irq,
const struct irq_domain_ops *ops,
void *host_data);
struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode,
unsigned int size,
unsigned int first_irq,
const struct irq_domain_ops *ops,
void *host_data);
struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
unsigned int size,
unsigned int first_irq,
@ -325,6 +325,15 @@ static inline struct irq_domain *irq_find_host(struct device_node *node)
return d;
}
static inline struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
unsigned int size,
unsigned int first_irq,
const struct irq_domain_ops *ops,
void *host_data)
{
return irq_domain_create_simple(of_node_to_fwnode(of_node), size, first_irq, ops, host_data);
}
/**
* irq_domain_add_linear() - Allocate and register a linear revmap irq_domain.
* @of_node: pointer to interrupt controller's device tree node.

View File

@ -295,8 +295,8 @@ void irq_domain_update_bus_token(struct irq_domain *domain,
EXPORT_SYMBOL_GPL(irq_domain_update_bus_token);
/**
* irq_domain_add_simple() - Register an irq_domain and optionally map a range of irqs
* @of_node: pointer to interrupt controller's device tree node.
* irq_domain_create_simple() - Register an irq_domain and optionally map a range of irqs
* @fwnode: firmware node for the interrupt controller
* @size: total number of irqs in mapping
* @first_irq: first number of irq block assigned to the domain,
* pass zero to assign irqs on-the-fly. If first_irq is non-zero, then
@ -312,15 +312,15 @@ EXPORT_SYMBOL_GPL(irq_domain_update_bus_token);
* irqs get mapped dynamically on the fly. However, if the controller requires
* static virq assignments (non-DT boot) then it will set that up correctly.
*/
struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
unsigned int size,
unsigned int first_irq,
const struct irq_domain_ops *ops,
void *host_data)
struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode,
unsigned int size,
unsigned int first_irq,
const struct irq_domain_ops *ops,
void *host_data)
{
struct irq_domain *domain;
domain = __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
domain = __irq_domain_add(fwnode, size, size, 0, ops, host_data);
if (!domain)
return NULL;
@ -328,7 +328,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {
/* attempt to allocated irq_descs */
int rc = irq_alloc_descs(first_irq, first_irq, size,
of_node_to_nid(of_node));
of_node_to_nid(to_of_node(fwnode)));
if (rc < 0)
pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
first_irq);
@ -338,7 +338,7 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
return domain;
}
EXPORT_SYMBOL_GPL(irq_domain_add_simple);
EXPORT_SYMBOL_GPL(irq_domain_create_simple);
/**
* irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.

View File

@ -3,17 +3,19 @@
* lib/bitmap.c
* Helper functions for bitmap.h.
*/
#include <linux/export.h>
#include <linux/thread_info.h>
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/thread_info.h>
#include <linux/uaccess.h>
#include <asm/page.h>
@ -1271,6 +1273,38 @@ void bitmap_free(const unsigned long *bitmap)
}
EXPORT_SYMBOL(bitmap_free);
static void devm_bitmap_free(void *data)
{
unsigned long *bitmap = data;
bitmap_free(bitmap);
}
unsigned long *devm_bitmap_alloc(struct device *dev,
unsigned int nbits, gfp_t flags)
{
unsigned long *bitmap;
int ret;
bitmap = bitmap_alloc(nbits, flags);
if (!bitmap)
return NULL;
ret = devm_add_action_or_reset(dev, devm_bitmap_free, bitmap);
if (ret)
return NULL;
return bitmap;
}
EXPORT_SYMBOL_GPL(devm_bitmap_alloc);
unsigned long *devm_bitmap_zalloc(struct device *dev,
unsigned int nbits, gfp_t flags)
{
return devm_bitmap_alloc(dev, nbits, flags | __GFP_ZERO);
}
EXPORT_SYMBOL_GPL(devm_bitmap_zalloc);
#if BITS_PER_LONG == 64
/**
* bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap

View File

@ -272,3 +272,4 @@ char *next_arg(char *args, char **param, char **val)
/* Chew up trailing spaces. */
return skip_spaces(args);
}
EXPORT_SYMBOL(next_arg);

View File

@ -20,7 +20,7 @@
#define CONSUMER "gpio-utils"
/**
* doc: Operation of gpio
* DOC: Operation of gpio
*
* Provide the api of gpiochip for chardev interface. There are two
* types of api. The first one provide as same function as each
@ -100,7 +100,7 @@ exit_free_name:
}
/**
* gpiotools_set_values(): Set the value of gpio(s)
* gpiotools_set_values() - Set the value of gpio(s)
* @fd: The fd returned by
* gpiotools_request_line().
* @values: The array of values want to set.
@ -124,7 +124,7 @@ int gpiotools_set_values(const int fd, struct gpio_v2_line_values *values)
}
/**
* gpiotools_get_values(): Get the value of gpio(s)
* gpiotools_get_values() - Get the value of gpio(s)
* @fd: The fd returned by
* gpiotools_request_line().
* @values: The array of values get from hardware.
@ -148,7 +148,7 @@ int gpiotools_get_values(const int fd, struct gpio_v2_line_values *values)
}
/**
* gpiotools_release_line(): Release the line(s) of gpiochip
* gpiotools_release_line() - Release the line(s) of gpiochip
* @fd: The fd returned by
* gpiotools_request_line().
*
@ -169,7 +169,7 @@ int gpiotools_release_line(const int fd)
}
/**
* gpiotools_get(): Get value from specific line
* gpiotools_get() - Get value from specific line
* @device_name: The name of gpiochip without prefix "/dev/",
* such as "gpiochip0"
* @line: number of line, such as 2.
@ -191,7 +191,7 @@ int gpiotools_get(const char *device_name, unsigned int line)
/**
* gpiotools_gets(): Get values from specific lines.
* gpiotools_gets() - Get values from specific lines.
* @device_name: The name of gpiochip without prefix "/dev/",
* such as "gpiochip0".
* @lines: An array desired lines, specified by offset
@ -230,7 +230,7 @@ int gpiotools_gets(const char *device_name, unsigned int *lines,
}
/**
* gpiotools_set(): Set value to specific line
* gpiotools_set() - Set value to specific line
* @device_name: The name of gpiochip without prefix "/dev/",
* such as "gpiochip0"
* @line: number of line, such as 2.
@ -248,13 +248,13 @@ int gpiotools_set(const char *device_name, unsigned int line,
}
/**
* gpiotools_sets(): Set values to specific lines.
* gpiotools_sets() - Set values to specific lines.
* @device_name: The name of gpiochip without prefix "/dev/",
* such as "gpiochip0".
* @lines: An array desired lines, specified by offset
* index for the associated GPIO device.
* @num_lines: The number of lines to request.
* @value: The array of values set to gpiochip, must be
* @values: The array of values set to gpiochip, must be
* 0(low) or 1(high).
*
* Return: On success return 0;