Commit 510965dd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.1 development cycle:

   - A new GPIO hogging mechanism has been added.  This can be used on
     boards that want to drive some GPIO line high, low, or set it as
     input on boot and then never touch it again.  For some embedded
     systems this is bliss and simplifies things to a great extent.

   - Some API cleanup and closure: gpiod_get_array() and
     gpiod_put_array() has been added to get and put GPIOs in bulk as
     was possible with the non-descriptor API.

   - Encapsulate cross-calls to the pin control subsystem in
     <linux/gpio/driver.h>.  Now this should be the only header any GPIO
     driver needs to include or something is wrong.  Cleanups
     restricting drivers to this include are welcomed if tested.

   - Sort the GPIO Kconfig and split it into submenus, as it was
     becoming and unstructured, illogical and unnavigatable mess.  I
     hope this is easier to follow.  Menus that require a certain
     subsystem like I2C can now be hidden nicely for example, still
     working on others.

   - New drivers:

       - New driver for the Altera Soft GPIO.

       - The F7188x driver now handles the F71869 and F71869A variants.

       - The MIPS Loongson driver has been moved to drivers/gpio for
         consolidation and cleanup.

   - Cleanups:

       - The MAX732x is converted to use the GPIOLIB_IRQCHIP
         infrastructure.

       - The PCF857x is converted to use the GPIOLIB_IRQCHIP
         infrastructure.

       - Radical cleanup of the OMAP driver.

   - Misc:

       - Enable the DWAPB GPIO for all architectures.  This is a "hard
         IP" block from Synopsys which has started to turn up in so
         diverse architectures as X86 Quark, ARC and a slew of ARM
         systems.  So even though it's not an expander, it's generic
         enough to be available for all.

       - We add a mock GPIO on Crystalcove PMIC after a long discussion
         with Daniel Vetter et al, tracing back to the shootout at the
         kernel summit where DRM drivers and sub-componentization was
         discussed.  In this case a mock GPIO is assumed to be the best
         compromise gaining some reuse of infrastructure without making
         DRM drivers overly complex at the same time.  Let's see"

* tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (62 commits)
  Revert "gpio: sch: use uapi/linux/pci_ids.h directly"
  gpio: dwapb: remove dependencies
  gpio: dwapb: enable for ARC
  gpio: removing kfree remove functionality
  gpio: mvebu: Fix mask/unmask managment per irq chip type
  gpio: split GPIO drivers in submenus
  gpio: move MFD GPIO drivers under their own comment
  gpio: move BCM Kona Kconfig option
  gpio: arrange SPI Kconfig symbols alphabetically
  gpio: arrange PCI GPIO controllers alphabetically
  gpio: arrange I2C Kconfig symbols alphabetically
  gpio: arrange Kconfig symbols alphabetically
  gpio: ich: Implement get_direction function
  gpio: use (!foo) instead of (foo == NULL)
  gpio: arizona: drop owner assignment from platform_drivers
  gpio: max7300: remove 'ret' variable
  gpio: use devm_kzalloc
  gpio: sch: use uapi/linux/pci_ids.h directly
  gpio: x-gene: fix devm_ioremap_resource() check
  gpio: loongson: Add Loongson-3A/3B GPIO driver support
  ...
parents 40d78398 03daa6f8
Altera GPIO controller bindings
Required properties:
- compatible:
- "altr,pio-1.0"
- reg: Physical base address and length of the controller's registers.
- #gpio-cells : Should be 2
- The first cell is the gpio offset number.
- The second cell is reserved and is currently unused.
- gpio-controller : Marks the device node as a GPIO controller.
- interrupt-controller: Mark the device node as an interrupt controller
- #interrupt-cells : Should be 1. The interrupt type is fixed in the hardware.
- The first cell is the GPIO offset number within the GPIO controller.
- interrupts: Specify the interrupt.
- altr,interrupt-trigger: Specifies the interrupt trigger type the GPIO
hardware is synthesized. This field is required if the Altera GPIO controller
used has IRQ enabled as the interrupt type is not software controlled,
but hardware synthesized. Required if GPIO is used as an interrupt
controller. The value is defined in <dt-bindings/interrupt-controller/irq.h>
Only the following flags are supported:
IRQ_TYPE_EDGE_RISING
IRQ_TYPE_EDGE_FALLING
IRQ_TYPE_EDGE_BOTH
IRQ_TYPE_LEVEL_HIGH
Optional properties:
- altr,ngpio: Width of the GPIO bank. This defines how many pins the
GPIO device has. Ranges between 1-32. Optional and defaults to 32 if not
specified.
Example:
gpio_altr: gpio@0xff200000 {
compatible = "altr,pio-1.0";
reg = <0xff200000 0x10>;
interrupts = <0 45 4>;
altr,ngpio = <32>;
altr,interrupt-trigger = <IRQ_TYPE_EDGE_RISING>;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <1>;
interrupt-controller;
};
......@@ -116,6 +116,29 @@ Every GPIO controller node must contain both an empty "gpio-controller"
property, and a #gpio-cells integer property, which indicates the number of
cells in a gpio-specifier.
The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
providing automatic GPIO request and configuration as part of the
gpio-controller's driver probe function.
Each GPIO hog definition is represented as a child node of the GPIO controller.
Required properties:
- gpio-hog: A property specifying that this child node represent a GPIO hog.
- gpios: Store the GPIO information (id, flags, ...). Shall contain the
number of cells specified in its parent node (GPIO controller
node).
Only one of the following properties scanned in the order shown below.
This means that when multiple properties are present they will be searched
in the order presented below and the first match is taken as the intended
configuration.
- input: A property specifying to set the GPIO direction as input.
- output-low A property specifying to set the GPIO direction as output with
the value low.
- output-high A property specifying to set the GPIO direction as output with
the value high.
Optional properties:
- line-name: The GPIO label name. If not present the node name is used.
Example of two SOC GPIO banks defined as gpio-controller nodes:
qe_pio_a: gpio-controller@1400 {
......@@ -123,6 +146,13 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
reg = <0x1400 0x18>;
gpio-controller;
#gpio-cells = <2>;
line_b {
gpio-hog;
gpios = <6 0>;
output-low;
line-name = "foo-bar-gpio";
};
};
qe_pio_e: gpio-controller@1460 {
......
......@@ -12,7 +12,7 @@ Required properties:
gpio_mux.
- interrupt-names : Should be the names of irq resources. Each interrupt
uses its own interrupt name, so there should be as many interrupt names
as referenced interrups.
as referenced interrupts.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells: Specifies the number of cells needed to encode an
interrupt source.
......
......@@ -58,7 +58,6 @@ pattern where a GPIO is optional, the gpiod_get_optional() and
gpiod_get_index_optional() functions can be used. These functions return NULL
instead of -ENOENT if no GPIO has been assigned to the requested function:
struct gpio_desc *gpiod_get_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
......@@ -68,6 +67,27 @@ instead of -ENOENT if no GPIO has been assigned to the requested function:
unsigned int index,
enum gpiod_flags flags)
For a function using multiple GPIOs all of those can be obtained with one call:
struct gpio_descs *gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
This function returns a struct gpio_descs which contains an array of
descriptors:
struct gpio_descs {
unsigned int ndescs;
struct gpio_desc *desc[];
}
The following function returns NULL instead of -ENOENT if no GPIOs have been
assigned to the requested function:
struct gpio_descs *gpiod_get_array_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
Device-managed variants of these functions are also defined:
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
......@@ -82,20 +102,37 @@ Device-managed variants of these functions are also defined:
const char *con_id,
enum gpiod_flags flags)
struct gpio_desc * devm_gpiod_get_index_optional(struct device *dev,
struct gpio_desc *devm_gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index,
enum gpiod_flags flags)
struct gpio_descs *devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
struct gpio_descs *devm_gpiod_get_array_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
A GPIO descriptor can be disposed of using the gpiod_put() function:
void gpiod_put(struct gpio_desc *desc)
It is strictly forbidden to use a descriptor after calling this function. The
device-managed variant is, unsurprisingly:
For an array of GPIOs this function can be used:
void gpiod_put_array(struct gpio_descs *descs)
It is strictly forbidden to use a descriptor after calling these functions.
It is also not allowed to individually release descriptors (using gpiod_put())
from an array acquired with gpiod_get_array().
The device-managed variants are, unsurprisingly:
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
Using GPIOs
===========
......@@ -222,6 +259,26 @@ GPIOs belonging to the same bank or chip simultaneously if supported by the
corresponding chip driver. In that case a significantly improved performance
can be expected. If simultaneous setting is not possible the GPIOs will be set
sequentially.
The gpiod_set_array() functions take three arguments:
* array_size - the number of array elements
* desc_array - an array of GPIO descriptors
* value_array - an array of values to assign to the GPIOs
The descriptor array can be obtained using the gpiod_get_array() function
or one of its variants. If the group of descriptors returned by that function
matches the desired group of GPIOs, those GPIOs can be set by simply using
the struct gpio_descs returned by gpiod_get_array():
struct gpio_descs *my_gpio_descs = gpiod_get_array(...);
gpiod_set_array(my_gpio_descs->ndescs, my_gpio_descs->desc,
my_gpio_values);
It is also possible to set a completely arbitrary array of descriptors. The
descriptors may be obtained using any combination of gpiod_get() and
gpiod_get_array(). Afterwards the array of descriptors has to be setup
manually before it can be used with gpiod_set_array().
Note that for optimal performance GPIOs belonging to the same chip should be
contiguous within the array of descriptors.
......
......@@ -569,6 +569,12 @@ L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
S: Maintained
F: drivers/mailbox/mailbox-altera.c
ALTERA PIO DRIVER
M: Tien Hock Loh <thloh@altera.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-altera.c
ALTERA TRIPLE SPEED ETHERNET DRIVER
M: Vince Bridgers <vbridger@opensource.altera.com>
L: netdev@vger.kernel.org
......
......@@ -1288,6 +1288,7 @@ config CPU_LOONGSON3
select CPU_SUPPORTS_HUGEPAGES
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
select ARCH_REQUIRE_GPIOLIB
help
The Loongson 3 processor implements the MIPS64R2 instruction
set with many extensions.
......
......@@ -171,6 +171,7 @@ CONFIG_SERIAL_8250_FOURPORT=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_HW_RANDOM=y
CONFIG_RTC=y
CONFIG_GPIO_LOONGSON=y
CONFIG_THERMAL=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_VIDEO_DEV=m
......
......@@ -243,6 +243,7 @@ CONFIG_HW_RANDOM=y
CONFIG_RAW_DRIVER=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PIIX4=y
CONFIG_GPIO_LOONGSON=y
CONFIG_SENSORS_LM75=m
CONFIG_SENSORS_LM93=m
CONFIG_SENSORS_W83627HF=m
......
/*
* STLS2F GPIO Support
* Loongson GPIO Support
*
* Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
* Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
* Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -10,14 +11,14 @@
* (at your option) any later version.
*/
#ifndef __STLS2F_GPIO_H
#define __STLS2F_GPIO_H
#ifndef __LOONGSON_GPIO_H
#define __LOONGSON_GPIO_H
#include <asm-generic/gpio.h>
extern void gpio_set_value(unsigned gpio, int value);
extern int gpio_get_value(unsigned gpio);
extern int gpio_cansleep(unsigned gpio);
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
/* The chip can do interrupt
* but it has not been tested and doc not clear
......@@ -32,4 +33,4 @@ static inline int irq_to_gpio(int gpio)
return -EINVAL;
}
#endif /* __STLS2F_GPIO_H */
#endif /* __LOONGSON_GPIO_H */
......@@ -4,7 +4,6 @@
obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
bonito-irq.o mem.o machtype.o platform.o
obj-$(CONFIG_GPIOLIB) += gpio.o
obj-$(CONFIG_PCI) += pci.o
#
......
This diff is collapsed.
......@@ -17,6 +17,7 @@ obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
......@@ -41,6 +42,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
......
......@@ -35,6 +35,20 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
return *this == *gpio;
}
static void devm_gpiod_release_array(struct device *dev, void *res)
{
struct gpio_descs **descs = res;
gpiod_put_array(*descs);
}
static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
{
struct gpio_descs **this = res, **gpios = data;
return *this == *gpios;
}
/**
* devm_gpiod_get - Resource-managed gpiod_get()
* @dev: GPIO consumer
......@@ -111,23 +125,39 @@ EXPORT_SYMBOL(__devm_gpiod_get_index);
/**
* devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @child: firmware node (child of @dev)
*
* GPIO descriptors returned from this function are automatically disposed on
* driver detach.
*/
struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
const char *con_id,
struct fwnode_handle *child)
{
static const char * const suffixes[] = { "gpios", "gpio" };
char prop_name[32]; /* 32 is max size of property name */
struct gpio_desc **dr;
struct gpio_desc *desc;
unsigned int i;
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
desc = fwnode_get_named_gpiod(child, "gpios");
for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s",
con_id, suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
suffixes[i]);
desc = fwnode_get_named_gpiod(child, prop_name);
if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
break;
}
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
......@@ -169,6 +199,66 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de
}
EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
/**
* devm_gpiod_get_array - Resource-managed gpiod_get_array()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_array(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get_array() for detailed
* information about behavior and return values.
*/
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
{
struct gpio_descs **dr;
struct gpio_descs *descs;
dr = devres_alloc(devm_gpiod_release_array,
sizeof(struct gpio_descs *), GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
descs = gpiod_get_array(dev, con_id, flags);
if (IS_ERR(descs)) {
devres_free(dr);
return descs;
}
*dr = descs;
devres_add(dev, dr);
return descs;
}
EXPORT_SYMBOL(devm_gpiod_get_array);
/**
* devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_array_optional(). GPIO descriptors returned from this
* function are automatically disposed on driver detach.
* See gpiod_get_array_optional() for detailed information about behavior and
* return values.
*/
struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
struct gpio_descs *descs;
descs = devm_gpiod_get_array(dev, con_id, flags);
if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
return NULL;
return descs;
}
EXPORT_SYMBOL(devm_gpiod_get_array_optional);
/**
* devm_gpiod_put - Resource-managed gpiod_put()
* @desc: GPIO descriptor to dispose of
......@@ -184,6 +274,21 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
}
EXPORT_SYMBOL(devm_gpiod_put);
/**
* devm_gpiod_put_array - Resource-managed gpiod_put_array()
* @descs: GPIO descriptor array to dispose of
*
* Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array().
* Normally this function will not be called as the GPIOs will be disposed of
* by the resource management code.
*/
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
{
WARN_ON(devres_release(dev, devm_gpiod_release_array,
devm_gpiod_match_array, &descs));
}
EXPORT_SYMBOL(devm_gpiod_put_array);
......
......@@ -367,7 +367,7 @@ static int adp5588_gpio_probe(struct i2c_client *client,
struct gpio_chip *gc;
int ret, i, revid;
if (pdata == NULL) {
if (!pdata) {
dev_err(&client->dev, "missing platform data\n");
return -ENODEV;
}
......@@ -378,8 +378,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,
return -EIO;
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->client = client;
......@@ -446,7 +446,6 @@ static int adp5588_gpio_probe(struct i2c_client *client,
err_irq:
adp5588_irq_teardown(dev);
err:
kfree(dev);
return ret;
}
......@@ -472,7 +471,6 @@ static int adp5588_gpio_remove(struct i2c_client *client)
gpiochip_remove(&dev->gpio_chip);
kfree(dev);
return 0;
}
......
This diff is collapsed.
......@@ -103,7 +103,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio),
GFP_KERNEL);
if (arizona_gpio == NULL)
if (!arizona_gpio)
return -ENOMEM;
arizona_gpio->arizona = arizona;
......@@ -156,7 +156,6 @@ static int arizona_gpio_remove(struct platform_device *pdev)
static struct platform_driver arizona_gpio_driver = {
.driver.name = "arizona-gpio",
.driver.owner = THIS_MODULE,
.probe = arizona_gpio_probe,
.remove = arizona_gpio_remove,
};
......
......@@ -24,7 +24,7 @@
#include <linux/mfd/intel_soc_pmic.h>
#define CRYSTALCOVE_GPIO_NUM 16
#define CRYSTALCOVE_VGPIO_NUM 94
#define CRYSTALCOVE_VGPIO_NUM 95
#define UPDATE_IRQ_TYPE BIT(0)
#define UPDATE_IRQ_MASK BIT(1)
......@@ -39,6 +39,7 @@
#define GPIO0P0CTLI 0x33
#define GPIO1P0CTLO 0x3b
#define GPIO1P0CTLI 0x43
#define GPIOPANELCTL 0x52
#define CTLI_INTCNT_DIS (0)
#define CTLI_INTCNT_NE (1 << 1)
......@@ -93,6 +94,10 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
{
int reg;
if (gpio == 94) {
return GPIOPANELCTL;
}
if (reg_type == CTRL_IN) {
if (gpio < 8)
reg = GPIO0P0CTLI;
......
......@@ -212,7 +212,7 @@ static int da9052_gpio_probe(struct platform_device *pdev)
int ret;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL)
if (!gpio)
return -ENOMEM;
gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
......
......@@ -146,7 +146,7 @@ static int da9055_gpio_probe(struct platform_device *pdev)
int ret;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL)
if (!gpio)
return -ENOMEM;
gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
......
/*
* GPIO driver for Fintek Super-I/O F71882 and F71889
* GPIO driver for Fintek Super-I/O F71869, F71869A, F71882 and F71889
*
* Copyright (C) 2010-2013 LaCie
*
......@@ -32,12 +32,16 @@
#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */
#define SIO_F71869_ID 0x0814 /* F71869 chipset ID */
#define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */
#define SIO_F71882_ID 0x0541 /* F71882 chipset ID */
#define SIO_F71889_ID 0x0909 /* F71889 chipset ID */
enum chips { f71882fg, f71889f };
enum chips { f71869, f71869a, f71882fg, f71889f };
static const char * const f7188x_names[] = {
"f71869",
"f71869a",
"f71882fg",
"f71889f",
};
......@@ -146,6 +150,27 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
/* Output mode register (0:open drain 1:push-pull). */
#define gpio_out_mode(base) (base + 3)
static struct f7188x_gpio_bank f71869_gpio_bank[] = {
F7188X_GPIO_BANK(0, 6, 0xF0),
F7188X_GPIO_BANK(10, 8, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 8, 0xC0),
F7188X_GPIO_BANK(40, 8, 0xB0),
F7188X_GPIO_BANK(50, 5, 0xA0),
F7188X_GPIO_BANK(60, 6, 0x90),
};
static struct f7188x_gpio_bank f71869a_gpio_bank[] = {
F7188X_GPIO_BANK(0, 6, 0xF0),
F7188X_GPIO_BANK(10, 8, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 8, 0xC0),
F7188X_GPIO_BANK(40, 8, 0xB0),
F7188X_GPIO_BANK(50, 5, 0xA0),
F7188X_GPIO_BANK(60, 8, 0x90),
F7188X_GPIO_BANK(70, 8, 0x80),
};
static struct f7188x_gpio_bank f71882_gpio_bank[] = {
F7188X_GPIO_BANK(0 , 8, 0xF0),
F7188X_GPIO_BANK(10, 8, 0xE0),
......@@ -281,6 +306,14 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
switch (sio->type) {
case f71869:
data->nr_bank = ARRAY_SIZE(f71869_gpio_bank);
data->bank = f71869_gpio_bank;
break;
case f71869a:
data->nr_bank = ARRAY_SIZE(f71869a_gpio_bank);
data->bank = f71869a_gpio_bank;
break;
case f71882fg:
data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
data->bank = f71882_gpio_bank;
......@@ -354,6 +387,12 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
devid = superio_inw(addr, SIO_DEVID);
switch (devid) {
case SIO_F71869_ID:
sio->type = f71869;
break;
case SIO_F71869A_ID:
sio->type = f71869a;
break;
case SIO_F71882_ID:
sio->type = f71882fg;
break;
......@@ -410,7 +449,7 @@ f7188x_gpio_device_add(const struct f7188x_sio *sio)
}
/*
* Try to match a supported Fintech device by reading the (hard-wired)
* Try to match a supported Fintek device by reading the (hard-wired)
* configuration I/O ports. If available, then register both the platform
* device and driver to support the GPIOs.
*/
......@@ -450,6 +489,6 @@ static void __exit f7188x_gpio_exit(void)
}
module_exit(f7188x_gpio_exit);
MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71882FG and F71889F");
MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG and F71889F");
MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
MODULE_LICENSE("GPL");
......@@ -173,6 +173,11 @@ static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
return !!(ichx_priv.use_gpio & (1 << (nr / 32)));
}
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
{
return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT;
}
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{
/*
......@@ -286,6 +291,7 @@ static void ichx_gpiolib_setup(struct gpio_chip *chip)
ichx_priv.desc->get : ichx_gpio_get;
chip->set = ichx_gpio_set;
chip->get_direction = ichx_gpio_get_direction;
chip->direction_input = ichx_gpio_direction_input;
chip->direction_output = ichx_gpio_direction_output;
chip->base = modparam_gpiobase;
......
......@@ -156,7 +156,7 @@ static int kempld_gpio_probe(struct platform_device *pdev)
}
gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
if (gpio == NULL)
if (!gpio)
return -ENOMEM;
gpio->pld = pld;
......
/*
* STLS2F GPIO Support
* Loongson-2F/3A/3B GPIO Support
*
* Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
* Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
* Copyright (c) 2013 Hongbing Hu <huhb@lemote.com>
* Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -20,67 +22,23 @@
#include <linux/gpio.h>
#define STLS2F_N_GPIO 4
#define STLS2F_GPIO_IN_OFFSET 16
#define STLS3A_N_GPIO 16
static DEFINE_SPINLOCK(gpio_lock);
int gpio_get_value(unsigned gpio)
{
u32 val;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return __gpio_get_value(gpio);
mask = 1 << (gpio + STLS2F_GPIO_IN_OFFSET);
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
spin_unlock(&gpio_lock);
return (val & mask) != 0;
}
EXPORT_SYMBOL(gpio_get_value);
void gpio_set_value(unsigned gpio, int state)
{
u32 val;
u32 mask;
if (gpio >= STLS2F_N_GPIO) {
__gpio_set_value(gpio, state);
return ;
}
#ifdef CONFIG_CPU_LOONGSON3
#define LOONGSON_N_GPIO STLS3A_N_GPIO
#else
#define LOONGSON_N_GPIO STLS2F_N_GPIO
#endif
mask = 1 << gpio;
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
if (state)
val |= mask;
else
val &= (~mask);
LOONGSON_GPIODATA = val;
spin_unlock(&gpio_lock);
}
EXPORT_SYMBOL(gpio_set_value);
#define LOONGSON_GPIO_IN_OFFSET 16
int gpio_cansleep(unsigned gpio)
{
if (gpio < STLS2F_N_GPIO)
return 0;
else
return __gpio_cansleep(gpio);
}
EXPORT_SYMBOL(gpio_cansleep);
static DEFINE_SPINLOCK(gpio_lock);
static int ls2f_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
u32 temp;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return -EINVAL;
spin_lock(&gpio_lock);
mask = 1 << gpio;
temp = LOONGSON_GPIOIE;
......@@ -91,15 +49,12 @@ static int ls2f_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
return 0;
}
static int ls2f_gpio_direction_output(struct gpio_chip *chip,
static int loongson_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int level)
{
u32 temp;
u32 mask;
if (gpio >= STLS2F_N_GPIO)
return -EINVAL;
gpio_set_value(gpio, level);
spin_lock(&gpio_lock);
mask = 1 << gpio;
......@@ -111,29 +66,50 @@ static int ls2f_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
static int ls2f_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
return gpio_get_value(gpio);
u32 val;
u32 mask;
mask = 1 << (gpio + LOONGSON_GPIO_IN_OFFSET);
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
spin_unlock(&gpio_lock);
return (val & mask) != 0;
}
static void ls2f_gpio_set_value(struct gpio_chip *chip,
static void loongson_gpio_set_value(struct gpio_chip *chip,
unsigned gpio, int value)
{
gpio_set_value(gpio, value);
u32 val;
u32 mask;
mask = 1 << gpio;
spin_lock(&gpio_lock);
val = LOONGSON_GPIODATA;
if (value)
val |= mask;
else
val &= (~mask);
LOONGSON_GPIODATA = val;
spin_unlock(&gpio_lock);
}
static struct gpio_chip ls2f_chip = {
.label = "ls2f",
.direction_input = ls2f_gpio_direction_input,
.get = ls2f_gpio_get_value,
.direction_output = ls2f_gpio_direction_output,
.set = ls2f_gpio_set_value,
static struct gpio_chip loongson_chip = {
.label = "Loongson-gpio-chip",
.direction_input = loongson_gpio_direction_input,
.get = loongson_gpio_get_value,
.direction_output = loongson_gpio_direction_output,
.set = loongson_gpio_set_value,
.base = 0,
.ngpio = STLS2F_N_GPIO,
.ngpio = LOONGSON_N_GPIO,
.can_sleep = false,
};
static int __init ls2f_gpio_setup(void)
static int __init loongson_gpio_setup(void)
{
return gpiochip_add(&ls2f_chip);
return gpiochip_add(&loongson_chip);
}
arch_initcall(ls2f_gpio_setup);
postcore_initcall(loongson_gpio_setup);
......@@ -35,7 +35,6 @@ static int max7300_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max7301 *ts;
int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
......@@ -49,8 +48,7 @@ static int max7300_probe(struct i2c_client *client,
ts->write = max7300_i2c_write;
ts->dev = &client->dev;
ret = __max730x_probe(ts);
return ret;
return __max730x_probe(ts);
}
static int max7300_remove(struct i2c_client *client)
......
......@@ -4,6 +4,7 @@
* Copyright (C) 2007 Marvell International Ltd.
* Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
* Copyright (C) 2008 Eric Miao <eric.miao@marvell.com>
* Copyright (C) 2015 Linus Walleij <linus.walleij@linaro.org>
*
* Derived from drivers/gpio/pca953x.c
*
......@@ -16,10 +17,8 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/i2c.h>
#include <linux/i2c/max732x.h>
#include <linux/of.h>
......@@ -150,9 +149,7 @@ struct max732x_chip {
uint8_t reg_out[2];
#ifdef CONFIG_GPIO_MAX732X_IRQ
struct irq_domain *irq_domain;
struct mutex irq_lock;
int irq_base;
uint8_t irq_mask;
uint8_t irq_mask_cur;
uint8_t irq_trig_raise;
......@@ -356,35 +353,26 @@ static void max732x_irq_update_mask(struct max732x_chip *chip)
mutex_unlock(&chip->lock);
}
static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
{
struct max732x_chip *chip = to_max732x(gc);
if (chip->irq_domain) {
return irq_create_mapping(chip->irq_domain,
chip->irq_base + off);
} else {
return -ENXIO;
}
}
static void max732x_irq_mask(struct irq_data *d)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct max732x_chip *chip = to_max732x(gc);
chip->irq_mask_cur &= ~(1 << d->hwirq);
}
static void max732x_irq_unmask(struct irq_data *d)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct max732x_chip *chip = to_max732x(gc);
chip->irq_mask_cur |= 1 << d->hwirq;
}
static void max732x_irq_bus_lock(struct irq_data *d)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct max732x_chip *chip = to_max732x(gc);
mutex_lock(&chip->irq_lock);
chip->irq_mask_cur = chip->irq_mask;
......@@ -392,7 +380,8 @@ static void max732x_irq_bus_lock(struct irq_data *d)
static void max732x_irq_bus_sync_unlock(struct irq_data *d)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct max732x_chip *chip = to_max732x(gc);
uint16_t new_irqs;
uint16_t level;
......@@ -410,7 +399,8 @@ static void max732x_irq_bus_sync_unlock(struct irq_data *d)
static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
{
struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct max732x_chip *chip = to_max732x(gc);
uint16_t off = d->hwirq;
uint16_t mask = 1 << off;
......@@ -492,7 +482,8 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
handle_nested_irq(irq_find_mapping(chip->irq_domain, level));
handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
level));
pending &= ~(1 << level);
} while (pending);
......@@ -500,68 +491,24 @@ static irqreturn_t max732x_irq_handler(int irq, void *devid)
return IRQ_HANDLED;
}
static int max732x_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct max732x_chip *chip = h->host_data;
if (!(chip->dir_input & (1 << hw))) {
dev_err(&chip->client->dev,
"Attempt to map output line as IRQ line: %lu\n",
hw);
return -EPERM;
}
irq_set_chip_data(virq, chip);
irq_set_chip_and_handler(virq, &max732x_irq_chip,
handle_edge_irq);
irq_set_nested_thread(virq, 1);
#ifdef CONFIG_ARM
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
set_irq_flags(virq, IRQF_VALID);
#else
irq_set_noprobe(virq);
#endif
return 0;
}
static struct irq_domain_ops max732x_irq_domain_ops = {
.map = max732x_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static void max732x_irq_teardown(struct max732x_chip *chip)
{
if (chip->client->irq && chip->irq_domain)
irq_domain_remove(chip->irq_domain);
}
static int max732x_irq_setup(struct max732x_chip *chip,
const struct i2c_device_id *id)
{
struct i2c_client *client = chip->client;
struct max732x_platform_data *pdata = dev_get_platdata(&client->dev);
int has_irq = max732x_features[id->driver_data] >> 32;
int irq_base = 0;
int ret;
if (((pdata && pdata->irq_base) || client->irq)
&& has_irq != INT_NONE) {
if (pdata)
chip->irq_base = pdata->irq_base;
irq_base = pdata->irq_base;
chip->irq_features = has_irq;
mutex_init(&chip->irq_lock);
chip->irq_domain = irq_domain_add_simple(client->dev.of_node,
chip->gpio_chip.ngpio, chip->irq_base,
&max732x_irq_domain_ops, chip);
if (!chip->irq_domain) {
dev_err(&client->dev, "Failed to create IRQ domain\n");
return -ENOMEM;
}
ret = request_threaded_irq(client->irq,
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
max732x_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
......@@ -569,17 +516,25 @@ static int max732x_irq_setup(struct max732x_chip *chip,
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
goto out_failed;
return ret;
}
chip->gpio_chip.to_irq = max732x_gpio_to_irq;
ret = gpiochip_irqchip_add(&chip->gpio_chip,
&max732x_irq_chip,
irq_base,
handle_edge_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_chained_irqchip(&chip->gpio_chip,
&max732x_irq_chip,
client->irq,
NULL);
}
return 0;
out_failed:
max732x_irq_teardown(chip);
return ret;
}
#else /* CONFIG_GPIO_MAX732X_IRQ */
......@@ -595,10 +550,6 @@ static int max732x_irq_setup(struct max732x_chip *chip,
return 0;
}
static void max732x_irq_teardown(struct max732x_chip *chip)
{
}
#endif
static int max732x_setup_gpio(struct max732x_chip *chip,
......@@ -730,13 +681,15 @@ static int max732x_probe(struct i2c_client *client,
if (nr_port > 8)
max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
ret = max732x_irq_setup(chip, id);
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
goto out_failed;
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
ret = max732x_irq_setup(chip, id);
if (ret) {
gpiochip_remove(&chip->gpio_chip);
goto out_failed;
}
if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
......@@ -751,7 +704,6 @@ static int max732x_probe(struct i2c_client *client,
out_failed:
if (chip->client_dummy)
i2c_unregister_device(chip->client_dummy);
max732x_irq_teardown(chip);
return ret;
}
......@@ -774,8 +726,6 @@ static int max732x_remove(struct i2c_client *client)
gpiochip_remove(&chip->gpio_chip);
max732x_irq_teardown(chip);
/* unregister any dummy i2c_client */
if (chip->client_dummy)
i2c_unregister_device(chip->client_dummy);
......
......@@ -58,6 +58,11 @@ static int mb86s70_gpio_request(struct gpio_chip *gc, unsigned gpio)
spin_lock_irqsave(&gchip->lock, flags);
val = readl(gchip->base + PFR(gpio));
if (!(val & OFFSET(gpio))) {
spin_unlock_irqrestore(&gchip->lock, flags);
return -EINVAL;
}
val &= ~OFFSET(gpio);
writel(val, gchip->base + PFR(gpio));
......
......@@ -151,7 +151,7 @@ static int mc33880_remove(struct spi_device *spi)
struct mc33880 *mc;
mc = spi_get_drvdata(spi);
if (mc == NULL)
if (!mc)
return -ENODEV;
gpiochip_remove(&mc->chip);
......
......@@ -949,10 +949,12 @@ static int mcp23s08_probe(struct spi_device *spi)
if (!chips)
return -ENODEV;
data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08),
data = devm_kzalloc(&spi->dev,
sizeof(*data) + chips * sizeof(struct mcp23s08),
GFP_KERNEL);
if (!data)
return -ENOMEM;
spi_set_drvdata(spi, data);
spi->irq = irq_of_parse_and_map(spi->dev.of_node, 0);
......@@ -989,7 +991,6 @@ static int mcp23s08_probe(struct spi_device *spi)
continue;
gpiochip_remove(&data->mcp[addr]->chip);
}
kfree(data);
return status;
}
......@@ -1007,7 +1008,7 @@ static int mcp23s08_remove(struct spi_device *spi)
mcp23s08_irq_teardown(data->mcp[addr]);
gpiochip_remove(&data->mcp[addr]->chip);
}
kfree(data);
return 0;
}
......
......@@ -320,11 +320,13 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache &= ~mask;
writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
ct->mask_cache_priv &= ~mask;
writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
......@@ -332,11 +334,13 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache |= mask;
writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
ct->mask_cache_priv |= mask;
writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
irq_gc_unlock(gc);
}
......@@ -344,11 +348,13 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache &= ~mask;
writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
ct->mask_cache_priv &= ~mask;
writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
......@@ -356,11 +362,13 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mvebu_gpio_chip *mvchip = gc->private;
struct irq_chip_type *ct = irq_data_get_chip_type(d);
u32 mask = 1 << (d->irq - gc->irq_base);
irq_gc_lock(gc);
gc->mask_cache |= mask;
writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
ct->mask_cache_priv |= mask;
writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
irq_gc_unlock(gc);
}
......
This diff is collapsed.
......@@ -88,11 +88,9 @@ struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
struct irq_domain *irq_domain; /* for irq demux */
spinlock_t slock; /* protect irq demux */
unsigned out; /* software latch */
unsigned status; /* current status */
unsigned irq_mapped; /* mapped gpio irqs */
int (*write)(struct i2c_client *client, unsigned data);
int (*read)(struct i2c_client *client);
......@@ -182,18 +180,6 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
/*-------------------------------------------------------------------------*/
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
int ret;
ret = irq_create_mapping(gpio->irq_domain, offset);
if (ret > 0)
gpio->irq_mapped |= (1 << offset);
return ret;
}
static irqreturn_t pcf857x_irq(int irq, void *data)
{
struct pcf857x *gpio = data;
......@@ -208,9 +194,9 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
* interrupt source, just to avoid bad irqs
*/
change = ((gpio->status ^ status) & gpio->irq_mapped);
change = (gpio->status ^ status);
for_each_set_bit(i, &change, gpio->chip.ngpio)
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
gpio->status = status;
spin_unlock_irqrestore(&gpio->slock, flags);
......@@ -218,66 +204,36 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
return IRQ_HANDLED;
}
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hw)
{
struct pcf857x *gpio = domain->host_data;
irq_set_chip_and_handler(irq,
&dummy_irq_chip,
handle_level_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
gpio->irq_mapped |= (1 << hw);
return 0;
}
static struct irq_domain_ops pcf857x_irq_domain_ops = {
.map = pcf857x_irq_domain_map,
};
/*
* NOP functions
*/
static void noop(struct irq_data *data) { }
static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
static unsigned int noop_ret(struct irq_data *data)
{
if (gpio->irq_domain)
irq_domain_remove(gpio->irq_domain);
return 0;
}
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
struct i2c_client *client)
static int pcf857x_irq_set_wake(struct irq_data *data, unsigned int on)
{
int status;
gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
gpio->chip.ngpio,
&pcf857x_irq_domain_ops,
gpio);
if (!gpio->irq_domain)
goto fail;
/* enable real irq */
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf857x_irq, IRQF_ONESHOT |
IRQF_TRIGGER_FALLING | IRQF_SHARED,
dev_name(&client->dev), gpio);
if (status)
goto fail;
/* enable gpio_to_irq() */
gpio->chip.to_irq = pcf857x_to_irq;
struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
irq_set_irq_wake(gpio->client->irq, on);
return 0;
fail:
pcf857x_irq_domain_cleanup(gpio);
return -EINVAL;
}
static struct irq_chip pcf857x_irq_chip = {
.name = "pcf857x",
.irq_startup = noop_ret,
.irq_shutdown = noop,
.irq_enable = noop,
.irq_disable = noop,
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
.irq_set_wake = pcf857x_irq_set_wake,
};
/*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client,
......@@ -314,15 +270,6 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->chip.direction_output = pcf857x_output;
gpio->chip.ngpio = id->driver_data;
/* enable gpio_to_irq() if platform has settings */
if (client->irq) {
status = pcf857x_irq_domain_init(gpio, client);
if (status < 0) {
dev_err(&client->dev, "irq_domain init failed\n");
goto fail_irq_domain;
}
}
/* NOTE: the OnSemi jlc1562b is also largely compatible with
* these parts, notably for output. It has a low-resolution
* DAC instead of pin change IRQs; and its inputs can be the
......@@ -398,6 +345,27 @@ static int pcf857x_probe(struct i2c_client *client,
if (status < 0)
goto fail;
/* Enable irqchip if we have an interrupt */
if (client->irq) {
status = gpiochip_irqchip_add(&gpio->chip, &pcf857x_irq_chip,
0, handle_level_irq,
IRQ_TYPE_NONE);
if (status) {
dev_err(&client->dev, "cannot add irqchip\n");
goto fail_irq;
}
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf857x_irq, IRQF_ONESHOT |
IRQF_TRIGGER_FALLING | IRQF_SHARED,
dev_name(&client->dev), gpio);
if (status)
goto fail_irq;
gpiochip_set_chained_irqchip(&gpio->chip, &pcf857x_irq_chip,
client->irq, NULL);
}
/* Let platform code set up the GPIOs and their users.
* Now is the first time anyone could use them.
*/
......@@ -413,13 +381,12 @@ static int pcf857x_probe(struct i2c_client *client,
return 0;
fail:
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
fail_irq:
gpiochip_remove(&gpio->chip);
fail_irq_domain:
dev_dbg(&client->dev, "probe error %d for '%s'\n",
status, client->name);
fail:
dev_dbg(&client->dev, "probe error %d for '%s'\n", status,
client->name);
return status;
}
......@@ -441,9 +408,6 @@ static int pcf857x_remove(struct i2c_client *client)
}
}
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
gpiochip_remove(&gpio->chip);
return status;
}
......
......@@ -59,8 +59,7 @@
#define GAFR_OFFSET 0x54
#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : ((n) > 5 ? 0x200 : 0x100) \
+ (((n) % 3) << 2))
#define BANK_OFF(n) (((n) / 3) << 8) + (((n) % 3) << 2)
int pxa_last_gpio;
static int irq_base;
......
......@@ -14,6 +14,7 @@
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
......@@ -37,20 +38,22 @@ struct gpio_rcar_priv {
struct platform_device *pdev;
struct gpio_chip gpio_chip;
struct irq_chip irq_chip;
unsigned int irq_parent;
struct clk *clk;
};
#define IOINTSEL 0x00
#define INOUTSEL 0x04
#define OUTDT 0x08
#define INDT 0x0c
#define INTDT 0x10
#define INTCLR 0x14
#define INTMSK 0x18
#define MSKCLR 0x1c
#define POSNEG 0x20
#define EDGLEVEL 0x24
#define FILONOFF 0x28
#define BOTHEDGE 0x4c
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
#define INOUTSEL 0x04 /* General Input/Output Switching Register */
#define OUTDT 0x08 /* General Output Register */
#define INDT 0x0c /* General Input Register */
#define INTDT 0x10 /* Interrupt Display Register */
#define INTCLR 0x14 /* Interrupt Clear Register */
#define INTMSK 0x18 /* Interrupt Mask Register */
#define MSKCLR 0x1c /* Interrupt Mask Clear Register */
#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
#define EDGLEVEL 0x24 /* Edge/level Select Register */
#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
#define RCAR_MAX_GPIO_PER_BANK 32
......@@ -169,6 +172,25 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
return 0;
}
static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct gpio_rcar_priv *p = container_of(gc, struct gpio_rcar_priv,
gpio_chip);
irq_set_irq_wake(p->irq_parent, on);
if (!p->clk)
return 0;
if (on)
clk_enable(p->clk);
else
clk_disable(p->clk);
return 0;
}
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
{
struct gpio_rcar_priv *p = dev_id;
......@@ -367,6 +389,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p);
p->clk = devm_clk_get(dev, NULL);
if (IS_ERR(p->clk)) {
dev_warn(dev, "unable to get clock\n");
p->clk = NULL;
}
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
......@@ -404,8 +432,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
irq_chip->irq_mask = gpio_rcar_irq_disable;
irq_chip->irq_unmask = gpio_rcar_irq_enable;
irq_chip->irq_set_type = gpio_rcar_irq_set_type;
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED
| IRQCHIP_MASK_ON_SUSPEND;
irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
ret = gpiochip_add(gpio_chip);
if (ret) {
......@@ -413,13 +441,14 @@ static int gpio_rcar_probe(struct platform_device *pdev)
goto err0;
}
ret = gpiochip_irqchip_add(&p->gpio_chip, irq_chip, p->config.irq_base,
ret = gpiochip_irqchip_add(gpio_chip, irq_chip, p->config.irq_base,
handle_level_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "cannot add irqchip\n");
goto err1;
}
p->irq_parent = irq->start;
if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
IRQF_SHARED, name, p)) {
dev_err(dev, "failed to request IRQ\n");
......@@ -431,7 +460,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
/* warn in case of mismatch if irq base is specified */
if (p->config.irq_base) {
ret = irq_find_mapping(p->gpio_chip.irqdomain, 0);
ret = irq_find_mapping(gpio_chip->irqdomain, 0);
if (p->config.irq_base != ret)
dev_warn(dev, "irq base mismatch (%u/%u)\n",
p->config.irq_base, ret);
......@@ -447,7 +476,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
return 0;
err1:
gpiochip_remove(&p->gpio_chip);
gpiochip_remove(gpio_chip);
err0:
pm_runtime_put(dev);
pm_runtime_disable(dev);
......
......@@ -283,7 +283,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
return ret;
}
static int __exit tb10x_gpio_remove(struct platform_device *pdev)
static int tb10x_gpio_remove(struct platform_device *pdev)
{
struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
......
......@@ -244,16 +244,16 @@ static int vf610_gpio_probe(struct platform_device *pdev)
gc = &port->gc;
gc->of_node = np;
gc->dev = dev;
gc->label = "vf610-gpio",
gc->ngpio = VF610_GPIO_PER_PORT,
gc->label = "vf610-gpio";
gc->ngpio = VF610_GPIO_PER_PORT;
gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
gc->request = vf610_gpio_request,
gc->free = vf610_gpio_free,
gc->direction_input = vf610_gpio_direction_input,
gc->get = vf610_gpio_get,
gc->direction_output = vf610_gpio_direction_output,
gc->set = vf610_gpio_set,
gc->request = vf610_gpio_request;
gc->free = vf610_gpio_free;
gc->direction_input = vf610_gpio_direction_input;
gc->get = vf610_gpio_get;
gc->direction_output = vf610_gpio_direction_output;
gc->set = vf610_gpio_set;
ret = gpiochip_add(gc);
if (ret < 0)
......
......@@ -93,7 +93,7 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(&pdev->dev, res);
if (!regs)
if (IS_ERR(regs))
return PTR_ERR(regs);
ret = bgpio_init(&priv->bgc, &pdev->dev, 4,
......
......@@ -304,7 +304,7 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
return;
INIT_LIST_HEAD(&acpi_gpio->events);
acpi_walk_resources(ACPI_HANDLE(chip->dev), "_AEI",
acpi_walk_resources(handle, "_AEI",
acpi_gpiochip_request_interrupt, acpi_gpio);
}
......@@ -722,3 +722,87 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
acpi_detach_data(handle, acpi_gpio_chip_dh);
kfree(acpi_gpio);
}
static unsigned int acpi_gpio_package_count(const union acpi_object *obj)
{
const union acpi_object *element = obj->package.elements;
const union acpi_object *end = element + obj->package.count;
unsigned int count = 0;
while (element < end) {
if (element->type == ACPI_TYPE_LOCAL_REFERENCE)
count++;
element++;
}
return count;
}
static int acpi_find_gpio_count(struct acpi_resource *ares, void *data)
{
unsigned int *count = data;
if (ares->type == ACPI_RESOURCE_TYPE_GPIO)
*count += ares->data.gpio.pin_table_length;
return 1;
}
/**
* acpi_gpio_count - return the number of GPIOs associated with a
* device / function or -ENOENT if no GPIO has been
* assigned to the requested function.
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
*/
int acpi_gpio_count(struct device *dev, const char *con_id)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
const union acpi_object *obj;
const struct acpi_gpio_mapping *gm;
int count = -ENOENT;
int ret;
char propname[32];
unsigned int i;
/* Try first from _DSD */
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id && strcmp(con_id, "gpios"))
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
else
snprintf(propname, sizeof(propname), "%s",
gpio_suffixes[i]);
ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
&obj);
if (ret == 0) {
if (obj->type == ACPI_TYPE_LOCAL_REFERENCE)
count = 1;
else if (obj->type == ACPI_TYPE_PACKAGE)
count = acpi_gpio_package_count(obj);
} else if (adev->driver_gpios) {
for (gm = adev->driver_gpios; gm->name; gm++)
if (strcmp(propname, gm->name) == 0) {
count = gm->size;
break;
}
}
if (count >= 0)
break;
}
/* Then from plain _CRS GPIOs */
if (count < 0) {
struct list_head resource_list;
unsigned int crs_count = 0;
INIT_LIST_HEAD(&resource_list);
acpi_dev_get_resources(adev, &resource_list,
acpi_find_gpio_count, &crs_count);
acpi_dev_free_resource_list(&resource_list);
if (crs_count > 0)
count = crs_count;
}
return count;
}
......@@ -22,6 +22,7 @@
#include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include <linux/gpio/machine.h>
#include "gpiolib.h"
......@@ -117,6 +118,114 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
}
EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
* of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
* @np: device node to get GPIO from
* @name: GPIO line name
* @lflags: gpio_lookup_flags - returned from of_find_gpio() or
* of_get_gpio_hog()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
* value on the error condition.
*/
static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
const char **name,
enum gpio_lookup_flags *lflags,
enum gpiod_flags *dflags)
{
struct device_node *chip_np;
enum of_gpio_flags xlate_flags;
struct gpio_desc *desc;
struct gg_data gg_data = {
.flags = &xlate_flags,
};
u32 tmp;
int i, ret;
chip_np = np->parent;
if (!chip_np)
return ERR_PTR(-EINVAL);
xlate_flags = 0;
*lflags = 0;
*dflags = 0;
ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
if (ret)
return ERR_PTR(ret);
if (tmp > MAX_PHANDLE_ARGS)
return ERR_PTR(-EINVAL);
gg_data.gpiospec.args_count = tmp;
gg_data.gpiospec.np = chip_np;
for (i = 0; i < tmp; i++) {
ret = of_property_read_u32_index(np, "gpios", i,
&gg_data.gpiospec.args[i]);
if (ret)
return ERR_PTR(ret);
}
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
if (!gg_data.out_gpio) {
if (np->parent == np)
return ERR_PTR(-ENXIO);
else
return ERR_PTR(-EINVAL);
}
if (xlate_flags & OF_GPIO_ACTIVE_LOW)
*lflags |= GPIO_ACTIVE_LOW;
if (of_property_read_bool(np, "input"))
*dflags |= GPIOD_IN;
else if (of_property_read_bool(np, "output-low"))
*dflags |= GPIOD_OUT_LOW;
else if (of_property_read_bool(np, "output-high"))
*dflags |= GPIOD_OUT_HIGH;
else {
pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n",
desc_to_gpio(gg_data.out_gpio), np->name);
return ERR_PTR(-EINVAL);
}
if (name && of_property_read_string(np, "line-name", name))
*name = np->name;
desc = gg_data.out_gpio;
return desc;
}
/**
* of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested
* @chip: gpio chip to act on
*
* This is only used by of_gpiochip_add to request/set GPIO initial
* configuration.
*/
static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
{
struct gpio_desc *desc = NULL;
struct device_node *np;
const char *name;
enum gpio_lookup_flags lflags;
enum gpiod_flags dflags;
for_each_child_of_node(chip->of_node, np) {
if (!of_property_read_bool(np, "gpio-hog"))
continue;
desc = of_get_gpio_hog(np, &name, &lflags, &dflags);
if (IS_ERR(desc))
continue;
if (gpiod_hog(desc, name, lflags, dflags))
continue;
}
}
/**
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
* @gc: pointer to the gpio_chip structure
......@@ -326,6 +435,8 @@ void of_gpiochip_add(struct gpio_chip *chip)
of_gpiochip_add_pin_range(chip);
of_node_get(chip->of_node);
of_gpiochip_scan_hogs(chip);
}
void of_gpiochip_remove(struct gpio_chip *chip)
......
This diff is collapsed.
......@@ -29,6 +29,9 @@ struct acpi_gpio_info {
bool active_low;
};
/* gpio suffixes used for ACPI and device tree lookup */
static const char * const gpio_suffixes[] = { "gpios", "gpio" };
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
......@@ -39,6 +42,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
const char *propname, int index,
struct acpi_gpio_info *info);
int acpi_gpio_count(struct device *dev, const char *con_id);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
......@@ -55,6 +60,11 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
{
return ERR_PTR(-ENOSYS);
}
static inline int acpi_gpio_count(struct device *dev, const char *con_id)
{
return -ENODEV;
}
#endif
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
......@@ -80,6 +90,7 @@ struct gpio_desc {
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_SYSFS_DIR 10 /* show sysfs direction attribute */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
#define ID_SHIFT 16 /* add new flags before this one */
......@@ -91,6 +102,8 @@ struct gpio_desc {
int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags);
/*
* Return the GPIO number of the passed descriptor relative to its chip
......
......@@ -125,7 +125,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
device_for_each_child_node(dev, child) {
struct gpio_desc *desc;
desc = devm_get_gpiod_from_child(dev, child);
desc = devm_get_gpiod_from_child(dev, NULL, child);
if (IS_ERR(desc)) {
error = PTR_ERR(desc);
if (error != -EPROBE_DEFER)
......
......@@ -184,7 +184,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
struct gpio_led led = {};
const char *state = NULL;
led.gpiod = devm_get_gpiod_from_child(dev, child);
led.gpiod = devm_get_gpiod_from_child(dev, NULL, child);
if (IS_ERR(led.gpiod)) {
fwnode_handle_put(child);
ret = PTR_ERR(led.gpiod);
......
......@@ -5,7 +5,6 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#ifdef CONFIG_GPIOLIB
......@@ -139,53 +138,6 @@ static inline void gpio_unexport(unsigned gpio)
gpiod_unexport(gpio_to_desc(gpio));
}
#ifdef CONFIG_PINCTRL
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @head: list for maintaining set of pin ranges, used internally
* @pctldev: pinctrl device which handles corresponding pins
* @range: actual range of pins controlled by a gpio controller
*/
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_gpio_range range;
};
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins);
int gpiochip_add_pingroup_range(struct gpio_chip *chip,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins)
{
return 0;
}
static inline int
gpiochip_add_pingroup_range(struct gpio_chip *chip,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group)
{
return 0;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
}
#endif /* CONFIG_PINCTRL */
#else /* !CONFIG_GPIOLIB */
static inline bool gpio_is_valid(int number)
......
......@@ -16,6 +16,15 @@ struct device;
*/
struct gpio_desc;
/**
* Struct containing an array of descriptors that can be obtained using
* gpiod_get_array().
*/
struct gpio_descs {
unsigned int ndescs;
struct gpio_desc *desc[];
};
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
......@@ -34,6 +43,9 @@ enum gpiod_flags {
#ifdef CONFIG_GPIOLIB
/* Return the number of GPIOs associated with a device / function */
int gpiod_count(struct device *dev, const char *con_id);
/* Acquire and dispose GPIOs */
struct gpio_desc *__must_check __gpiod_get(struct device *dev,
const char *con_id,
......@@ -49,7 +61,14 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index,
enum gpiod_flags flags);
struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
void gpiod_put(struct gpio_desc *desc);
void gpiod_put_array(struct gpio_descs *descs);
struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
const char *con_id,
......@@ -64,7 +83,14 @@ struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
struct gpio_desc *__must_check
__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags);
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags);
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
int gpiod_get_direction(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
......@@ -110,9 +136,15 @@ struct fwnode_handle;
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname);
struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
const char *con_id,
struct fwnode_handle *child);
#else /* CONFIG_GPIOLIB */
static inline int gpiod_count(struct device *dev, const char *con_id)
{
return 0;
}
static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
......@@ -142,6 +174,20 @@ __gpiod_get_index_optional(struct device *dev, const char *con_id,
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
gpiod_get_array(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline void gpiod_put(struct gpio_desc *desc)
{
might_sleep();
......@@ -150,6 +196,14 @@ static inline void gpiod_put(struct gpio_desc *desc)
WARN_ON(1);
}
static inline void gpiod_put_array(struct gpio_descs *descs)
{
might_sleep();
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline struct gpio_desc *__must_check
__devm_gpiod_get(struct device *dev,
const char *con_id,
......@@ -181,6 +235,20 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
devm_gpiod_get_array(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{
might_sleep();
......@@ -189,6 +257,15 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
WARN_ON(1);
}
static inline void devm_gpiod_put_array(struct device *dev,
struct gpio_descs *descs)
{
might_sleep();
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_get_direction(const struct gpio_desc *desc)
{
......
......@@ -6,6 +6,7 @@
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/pinctrl/pinctrl.h>
struct device;
struct gpio_desc;
......@@ -173,6 +174,53 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
#endif /* CONFIG_GPIOLIB_IRQCHIP */
#ifdef CONFIG_PINCTRL
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @head: list for maintaining set of pin ranges, used internally
* @pctldev: pinctrl device which handles corresponding pins
* @range: actual range of pins controlled by a gpio controller
*/
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_gpio_range range;
};
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins);
int gpiochip_add_pingroup_range(struct gpio_chip *chip,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins)
{
return 0;
}
static inline int
gpiochip_add_pingroup_range(struct gpio_chip *chip,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group)
{
return 0;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
}
#endif /* CONFIG_PINCTRL */
struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum,
const char *label);
void gpiochip_free_own_desc(struct gpio_desc *desc);
......
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