Commit 10b4b096 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull gpio updates from Linus Walleij:
 "This is the big bulk of GPIO changes queued for the v4.2 kernel
  series:

   - a big set of cleanups to the aged sysfs interface from Johan
     Hovold.  To get these in, v4.1-rc3 was merged into the tree as the
     first patch in that series had to go into stable.  This makes the
     locking much more fine-grained (get rid of the "big GPIO lock(s)"
     and store states in the GPIO descriptors.

   - rename gpiod_[g|s]et_array() to gpiod_[g|s]et_array_value() to
     avoid confusions.

   - New drivers for:
      * NXP LPC18xx (currently LPC1850)
      * NetLogic XLP
      * Broadcom STB SoC's
      * Axis ETRAXFS
      * Zynq Ultrascale+ (subdriver)

   - ACPI:
      * make it possible to retrieve GpioInt resources from a GPIO
        device using acpi_dev_gpio_irq_get()
      * merge some dependent I2C changes exploiting this.
      * support the ARM X-Gene GPIO standby driver.

   - make it possible for the generic GPIO driver to read back the value
     set registers to reflect current status.

   - loads of OMAP IRQ handling fixes.

   - incremental improvements to Kona, max732x, OMAP, MXC, RCAR,
     PCA953x, STP-XWAY, PCF857x, Crystalcove, TB10x.

   - janitorial (constification, checkpatch cleanups)"

* tag 'gpio-v4.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (71 commits)
  gpio: Fix checkpatch.pl issues
  gpio: pcf857x: handle only enabled irqs
  gpio / ACPI: Return -EPROBE_DEFER if the gpiochip was not found
  GPIO / ACPI: export acpi_gpiochip_request(free)_interrupts for module use
  gpio: improve error reporting on own descriptors
  gpio: promote own request failure to pr_err()
  gpio: Added support to Zynq Ultrascale+ MPSoC
  gpio: add ETRAXFS GPIO driver
  fix documentation after renaming gpiod_set_array to gpiod_set_array_value
  gpio: Add GPIO support for Broadcom STB SoCs
  gpio: xgene: add ACPI support for APM X-Gene GPIO standby driver
  gpio: tb10x: Drop unneeded free_irq() call
  gpio: crystalcove: set IRQCHIP_SKIP_SET_WAKE for the irqchip
  gpio: stp-xway: Use the of_property_read_u32 helper
  gpio: pcf857x: Check for irq_set_irq_wake() failures
  gpio-stp-xway: Fix enabling the highest bit of the PHY LEDs
  gpio: Prevent an integer overflow in the pca953x driver
  gpio: omap: rework omap_gpio_irq_startup to handle current pin state properly
  gpio: omap: rework omap_gpio_request to touch only gpio specific registers
  gpio: omap: rework omap_x_irq_shutdown to touch only irqs specific registers
  ...
parents c70c5fb2 38e003f4
Broadcom STB "UPG GIO" GPIO controller
The controller's registers are organized as sets of eight 32-bit
registers with each set controlling a bank of up to 32 pins. A single
interrupt is shared for all of the banks handled by the controller.
Required properties:
- compatible:
Must be "brcm,brcmstb-gpio"
- reg:
Define the base and range of the I/O address space containing
the brcmstb GPIO controller registers
- #gpio-cells:
Should be <2>. The first cell is the pin number (within the controller's
pin space), and the second is used for the following:
bit[0]: polarity (0 for active-high, 1 for active-low)
- gpio-controller:
Specifies that the node is a GPIO controller.
- brcm,gpio-bank-widths:
Number of GPIO lines for each bank. Number of elements must
correspond to number of banks suggested by the 'reg' property.
Optional properties:
- interrupts:
The interrupt shared by all GPIO lines for this controller.
- interrupt-parent:
phandle of the parent interrupt controller
- #interrupt-cells:
Should be <2>. The first cell is the GPIO number, the second should specify
flags. The following subset of flags is supported:
- bits[3:0] trigger type and level flags
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
Valid combinations are 1, 2, 3, 4, 8.
See also Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- interrupt-controller:
Marks the device node as an interrupt controller
- interrupt-names:
The name of the IRQ resource used by this controller
Example:
upg_gio: gpio@f040a700 {
#gpio-cells = <0x2>;
#interrupt-cells = <0x2>;
compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio";
gpio-controller;
interrupt-controller;
reg = <0xf040a700 0x80>;
interrupt-parent = <0xf>;
interrupts = <0x6>;
interrupt-names = "upg_gio";
brcm,gpio-bank-widths = <0x20 0x20 0x20 0x18>;
};
Axis ETRAX FS General I/O controller bindings
Required properties:
- compatible:
- "axis,etraxfs-gio"
- reg: Physical base address and length of the controller's registers.
- #gpio-cells: Should be 3
- The first cell is the gpio offset number.
- The second cell is reserved and is currently unused.
- The third cell is the port number (hex).
- gpio-controller: Marks the device node as a GPIO controller.
Example:
gio: gpio@b001a000 {
compatible = "axis,etraxfs-gio";
reg = <0xb001a000 0x1000>;
gpio-controller;
#gpio-cells = <3>;
};
Netlogic XLP Family GPIO
========================
This GPIO driver is used for following Netlogic XLP SoCs:
XLP832, XLP316, XLP208, XLP980, XLP532
Required properties:
-------------------
- compatible: Should be one of the following:
- "netlogic,xlp832-gpio": For Netlogic XLP832
- "netlogic,xlp316-gpio": For Netlogic XLP316
- "netlogic,xlp208-gpio": For Netlogic XLP208
- "netlogic,xlp980-gpio": For Netlogic XLP980
- "netlogic,xlp532-gpio": For Netlogic XLP532
- reg: Physical base address and length of the controller's registers.
- #gpio-cells: Should be two. The first cell is the pin number and the second
cell is used to specify optional parameters (currently unused).
- gpio-controller: Marks the device node as a GPIO controller.
- nr-gpios: Number of GPIO pins supported by the controller.
- interrupt-cells: Should be two. The first cell is the GPIO Number. The
second cell is used to specify flags. The following subset of flags is
supported:
- trigger type:
1 = low to high edge triggered.
2 = high to low edge triggered.
4 = active high level-sensitive.
8 = active low level-sensitive.
- interrupts: Interrupt number for this device.
- interrupt-parent: phandle of the parent interrupt controller.
- interrupt-controller: Identifies the node as an interrupt controller.
Example:
gpio: xlp_gpio@34000 {
compatible = "netlogic,xlp316-gpio";
reg = <0 0x34100 0x1000
0 0x35100 0x1000>;
#gpio-cells = <2>;
gpio-controller;
nr-gpios = <57>;
#interrupt-cells = <2>;
interrupt-parent = <&pic>;
interrupts = <39>;
interrupt-controller;
};
......@@ -6,7 +6,7 @@ Required properties:
- First cell is the GPIO line number
- Second cell is used to specify optional
parameters (unused)
- compatible : Should be "xlnx,zynq-gpio-1.0"
- compatible : Should be "xlnx,zynq-gpio-1.0" or "xlnx,zynqmp-gpio-1.0"
- clocks : Clock specifier (see clock bindings for details)
- gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt specifier (see interrupt bindings for
......
NXP LPC18xx/43xx GPIO controller Device Tree Bindings
-----------------------------------------------------
Required properties:
- compatible : Should be "nxp,lpc1850-gpio"
- reg : Address and length of the register set for the device
- clocks : Clock specifier (see clock bindings for details)
- gpio-controller : Marks the device node as a GPIO controller.
- #gpio-cells : Should be two
- First cell is the GPIO line number
- Second cell is used to specify polarity
Optional properties:
- gpio-ranges : Mapping between GPIO and pinctrl
Example:
#define LPC_GPIO(port, pin) (port * 32 + pin)
#define LPC_PIN(port, pin) (0x##port * 32 + pin)
gpio: gpio@400f4000 {
compatible = "nxp,lpc1850-gpio";
reg = <0x400f4000 0x4000>;
clocks = <&ccu1 CLK_CPU_GPIO>;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl LPC_GPIO(0,0) LPC_PIN(0,0) 2>,
...
<&pinctrl LPC_GPIO(7,19) LPC_PIN(f,5) 7>;
};
gpio_joystick {
compatible = "gpio-keys-polled";
...
button@0 {
...
gpios = <&gpio LPC_GPIO(4,8) GPIO_ACTIVE_LOW>;
};
};
......@@ -241,18 +241,18 @@ Set multiple GPIO outputs with a single function call
-----------------------------------------------------
The following functions set the output values of an array of GPIOs:
void gpiod_set_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
The array can be an arbitrary set of GPIOs. The functions will try to set
GPIOs belonging to the same bank or chip simultaneously if supported by the
......@@ -271,8 +271,8 @@ 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);
gpiod_set_array_value(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
......
......@@ -751,9 +751,6 @@ requested using gpio_request():
int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
/* change the polarity of a GPIO node in sysfs */
int gpio_sysfs_set_active_low(unsigned gpio, int value);
After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpio_export(). The driver can control whether the
signal direction may change. This helps drivers prevent userspace code
......@@ -767,9 +764,3 @@ After the GPIO has been exported, gpio_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name.
Drivers can use gpio_sysfs_set_active_low() to hide GPIO line polarity
differences between boards from user space. This only affects the
sysfs interface. Polarity change can be done both before and after
gpio_export(), and previously enabled poll(2) support for either
rising or falling edge will be reconfigured to follow this setting.
......@@ -132,9 +132,6 @@ requested using gpio_request():
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
/* change the polarity of a GPIO node in sysfs */
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpiod_export(). The driver can control whether the
signal direction may change. This helps drivers prevent userspace code
......@@ -148,8 +145,3 @@ After the GPIO has been exported, gpiod_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name.
Drivers can use gpiod_sysfs_set_active_low() to hide GPIO line polarity
differences between boards from user space. Polarity change can be done both
before and after gpiod_export(), and previously enabled poll(2) support for
either rising or falling edge will be reconfigured to follow this setting.
......@@ -638,9 +638,6 @@ GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
/* 改变 sysfs 中的一个 GPIO 节点的极性 */
int gpio_sysfs_set_active_low(unsigned gpio, int value);
在一个内核驱动申请一个 GPIO 之后,它可以通过 gpio_export()使其在 sysfs
接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间
破坏重要的系统状态。
......@@ -651,8 +648,3 @@ GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
在 GPIO 被导出之后,gpio_export_link()允许在 sysfs 文件系统的任何地方
创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
名字,在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
驱动可以使用 gpio_sysfs_set_active_low() 来在用户空间隐藏电路板之间
GPIO 线的极性差异。这个仅对 sysfs 接口起作用。极性的改变可以在 gpio_export()
前后进行,且之前使能的轮询操作(poll(2))支持(上升或下降沿)将会被重新配置来遵循
这个设置。
......@@ -2250,6 +2250,13 @@ N: bcm9583*
N: bcm583*
N: bcm113*
BROADCOM BRCMSTB GPIO DRIVER
M: Gregory Fong <gregory.0xf0@gmail.com>
L: bcm-kernel-feedback-list@broadcom.com>
S: Supported
F: drivers/gpio/gpio-brcmstb.c
F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
BROADCOM KONA GPIO DRIVER
M: Ray Jui <rjui@broadcom.com>
L: bcm-kernel-feedback-list@broadcom.com
......
......@@ -126,6 +126,14 @@ config GPIO_BCM_KONA
help
Turn on GPIO support for Broadcom "Kona" chips.
config GPIO_BRCMSTB
tristate "BRCMSTB GPIO support"
default y if ARCH_BRCMSTB
depends on OF_GPIO && (ARCH_BRCMSTB || COMPILE_TEST)
select GPIO_GENERIC
help
Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
config GPIO_CLPS711X
tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST
......@@ -159,6 +167,14 @@ config GPIO_EP93XX
depends on ARCH_EP93XX
select GPIO_GENERIC
config GPIO_ETRAXFS
bool "Axis ETRAX FS General I/O"
depends on CRIS || COMPILE_TEST
depends on OF
select GPIO_GENERIC
help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
config GPIO_F7188X
tristate "F71869, F71869A, F71882FG and F71889F GPIO support"
depends on X86
......@@ -230,6 +246,14 @@ config GPIO_LOONGSON
help
driver for GPIO functionality on Loongson-2F/3A/3B processors.
config GPIO_LPC18XX
bool "NXP LPC18XX/43XX GPIO support"
default y if ARCH_LPC18XX
depends on OF_GPIO && (ARCH_LPC18XX || COMPILE_TEST)
help
Select this option to enable GPIO driver for
NXP LPC18XX/43XX devices.
config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
......@@ -308,7 +332,7 @@ config GPIO_OCTEON
family of SOCs.
config GPIO_OMAP
bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS
tristate "TI OMAP GPIO support" if ARCH_OMAP2PLUS || COMPILE_TEST
default y if ARCH_OMAP
depends on ARM
select GENERIC_IRQ_CHIP
......@@ -488,6 +512,17 @@ config GPIO_XILINX
help
Say yes here to support the Xilinx FPGA GPIO device
config GPIO_XLP
tristate "Netlogic XLP GPIO support"
depends on CPU_XLP
select GPIOLIB_IRQCHIP
help
This driver provides support for GPIO interface on Netlogic XLP MIPS64
SoCs. Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX,
XLP9XX and XLP5XX.
If unsure, say N.
config GPIO_XTENSA
bool "Xtensa GPIO32 support"
depends on XTENSA
......@@ -505,7 +540,7 @@ config GPIO_ZEVIO
config GPIO_ZYNQ
tristate "Xilinx Zynq GPIO support"
depends on ARCH_ZYNQ
depends on ARCH_ZYNQ || ARCH_ZYNQMP
select GPIOLIB_IRQCHIP
help
Say yes here to support Xilinx Zynq GPIO controller.
......
......@@ -21,6 +21,7 @@ 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
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
......@@ -32,6 +33,7 @@ obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
......@@ -44,6 +46,7 @@ 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_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
......@@ -109,6 +112,7 @@ obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o
obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
......@@ -107,7 +107,8 @@ static int altera_gpio_irq_set_type(struct irq_data *d,
return -EINVAL;
}
static unsigned int altera_gpio_irq_startup(struct irq_data *d) {
static unsigned int altera_gpio_irq_startup(struct irq_data *d)
{
altera_gpio_irq_unmask(d);
return 0;
......
......@@ -122,6 +122,16 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
spin_unlock_irqrestore(&kona_gpio->lock, flags);
}
static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
{
struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip);
void __iomem *reg_base = kona_gpio->reg_base;
u32 val;
val = readl(reg_base + GPIO_CONTROL(gpio)) & GPIO_GPCTR0_IOTR_MASK;
return val ? GPIOF_DIR_IN : GPIOF_DIR_OUT;
}
static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
struct bcm_kona_gpio *kona_gpio;
......@@ -135,12 +145,8 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
/* determine the GPIO pin direction */
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
/* this function only applies to output pin */
if (GPIO_GPCTR0_IOTR_CMD_INPUT == val)
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
goto out;
reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
......@@ -166,13 +172,12 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
reg_base = kona_gpio->reg_base;
spin_lock_irqsave(&kona_gpio->lock, flags);
/* determine the GPIO pin direction */
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= GPIO_GPCTR0_IOTR_MASK;
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
reg_offset = GPIO_IN_STATUS(bank_id);
else
reg_offset = GPIO_OUT_STATUS(bank_id);
/* read the GPIO bank status */
reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
val = readl(reg_base + reg_offset);
spin_unlock_irqrestore(&kona_gpio->lock, flags);
......@@ -310,6 +315,7 @@ static struct gpio_chip template_chip = {
.owner = THIS_MODULE,
.request = bcm_kona_gpio_request,
.free = bcm_kona_gpio_free,
.get_direction = bcm_kona_gpio_get_dir,
.direction_input = bcm_kona_gpio_direction_input,
.get = bcm_kona_gpio_get,
.direction_output = bcm_kona_gpio_direction_output,
......
/*
* Copyright (C) 2015 Broadcom Corporation
*
* 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 the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/module.h>
#include <linux/basic_mmio_gpio.h>
#define GIO_BANK_SIZE 0x20
#define GIO_ODEN(bank) (((bank) * GIO_BANK_SIZE) + 0x00)
#define GIO_DATA(bank) (((bank) * GIO_BANK_SIZE) + 0x04)
#define GIO_IODIR(bank) (((bank) * GIO_BANK_SIZE) + 0x08)
#define GIO_EC(bank) (((bank) * GIO_BANK_SIZE) + 0x0c)
#define GIO_EI(bank) (((bank) * GIO_BANK_SIZE) + 0x10)
#define GIO_MASK(bank) (((bank) * GIO_BANK_SIZE) + 0x14)
#define GIO_LEVEL(bank) (((bank) * GIO_BANK_SIZE) + 0x18)
#define GIO_STAT(bank) (((bank) * GIO_BANK_SIZE) + 0x1c)
struct brcmstb_gpio_bank {
struct list_head node;
int id;
struct bgpio_chip bgc;
struct brcmstb_gpio_priv *parent_priv;
u32 width;
};
struct brcmstb_gpio_priv {
struct list_head bank_list;
void __iomem *reg_base;
int num_banks;
struct platform_device *pdev;
int gpio_base;
};
#define MAX_GPIO_PER_BANK 32
#define GPIO_BANK(gpio) ((gpio) >> 5)
/* assumes MAX_GPIO_PER_BANK is a multiple of 2 */
#define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1))
static inline struct brcmstb_gpio_bank *
brcmstb_gpio_gc_to_bank(struct gpio_chip *gc)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
return container_of(bgc, struct brcmstb_gpio_bank, bgc);
}
static inline struct brcmstb_gpio_priv *
brcmstb_gpio_gc_to_priv(struct gpio_chip *gc)
{
struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
return bank->parent_priv;
}
/* Make sure that the number of banks matches up between properties */
static int brcmstb_gpio_sanity_check_banks(struct device *dev,
struct device_node *np, struct resource *res)
{
int res_num_banks = resource_size(res) / GIO_BANK_SIZE;
int num_banks =
of_property_count_u32_elems(np, "brcm,gpio-bank-widths");
if (res_num_banks != num_banks) {
dev_err(dev, "Mismatch in banks: res had %d, bank-widths had %d\n",
res_num_banks, num_banks);
return -EINVAL;
} else {
return 0;
}
}
static int brcmstb_gpio_remove(struct platform_device *pdev)
{
struct brcmstb_gpio_priv *priv = platform_get_drvdata(pdev);
struct list_head *pos;
struct brcmstb_gpio_bank *bank;
int ret = 0;
list_for_each(pos, &priv->bank_list) {
bank = list_entry(pos, struct brcmstb_gpio_bank, node);
ret = bgpio_remove(&bank->bgc);
if (ret)
dev_err(&pdev->dev, "gpiochip_remove fail in cleanup");
}
return ret;
}
static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags)
{
struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
int offset;
if (gc->of_gpio_n_cells != 2) {
WARN_ON(1);
return -EINVAL;
}
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
offset = gpiospec->args[0] - (gc->base - priv->gpio_base);
if (offset >= gc->ngpio)
return -EINVAL;
if (unlikely(offset >= bank->width)) {
dev_warn_ratelimited(&priv->pdev->dev,
"Received request for invalid GPIO offset %d\n",
gpiospec->args[0]);
}
if (flags)
*flags = gpiospec->args[1];
return offset;
}
static int brcmstb_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *reg_base;
struct brcmstb_gpio_priv *priv;
struct resource *res;
struct property *prop;
const __be32 *p;
u32 bank_width;
int err;
static int gpio_base;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)