Merge remote-tracking branch 'linusw/for-next' into gpio/for-next
This commit is contained in:
commit
5be85ec0de
@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/gpio/brcm,xgs-iproc-gpio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom XGS iProc GPIO controller
|
||||
|
||||
maintainers:
|
||||
- Chris Packham <chris.packham@alliedtelesis.co.nz>
|
||||
|
||||
description: |
|
||||
This controller is the Chip Common A GPIO present on a number of Broadcom
|
||||
switch ASICs with integrated SoCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,iproc-gpio-cca
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: the I/O address containing the GPIO controller
|
||||
registers.
|
||||
- description: the I/O address containing the Chip Common A interrupt
|
||||
registers.
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- "#gpio-cells"
|
||||
- gpio-controller
|
||||
|
||||
dependencies:
|
||||
interrupt-controller: [ interrupts ]
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
gpio@18000060 {
|
||||
compatible = "brcm,iproc-gpio-cca";
|
||||
#gpio-cells = <2>;
|
||||
reg = <0x18000060 0x50>,
|
||||
<0x18000000 0x50>;
|
||||
ngpios = <12>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
|
||||
...
|
50
Documentation/devicetree/bindings/gpio/gpio-rda.yaml
Normal file
50
Documentation/devicetree/bindings/gpio/gpio-rda.yaml
Normal file
@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/gpio/gpio-rda.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: RDA Micro GPIO controller
|
||||
|
||||
maintainers:
|
||||
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rda,8810pl-gpio
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
description:
|
||||
Number of available gpios in a bank.
|
||||
minimum: 1
|
||||
maximum: 32
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- "#gpio-cells"
|
||||
- ngpios
|
||||
- interrupt-controller
|
||||
- "#interrupt-cells"
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
...
|
@ -2,7 +2,7 @@
|
||||
A driver for a selfmade cheap BT8xx based PCI GPIO-card (bt8xxgpio)
|
||||
===================================================================
|
||||
|
||||
For advanced documentation, see http://www.bu3sch.de/btgpio.php
|
||||
For advanced documentation, see https://bues.ch/cms/unmaintained/btgpio.html
|
||||
|
||||
A generic digital 24-port PCI GPIO card can be built out of an ordinary
|
||||
Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
|
@ -13,6 +13,7 @@ Contents:
|
||||
board
|
||||
drivers-on-gpio
|
||||
legacy
|
||||
bt8xxgpio
|
||||
|
||||
Core
|
||||
====
|
||||
|
@ -69,7 +69,6 @@ available subsections can be seen below.
|
||||
fpga/index
|
||||
acpi/index
|
||||
backlight/lp855x-driver.rst
|
||||
bt8xxgpio
|
||||
connector
|
||||
console
|
||||
dcdbas
|
||||
|
@ -2150,9 +2150,11 @@ L: linux-unisoc@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/boot/dts/rda8810pl-*
|
||||
F: drivers/clocksource/timer-rda.c
|
||||
F: drivers/gpio/gpio-rda.c
|
||||
F: drivers/irqchip/irq-rda-intc.c
|
||||
F: drivers/tty/serial/rda-uart.c
|
||||
F: Documentation/devicetree/bindings/arm/rda.yaml
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-rda.yaml
|
||||
F: Documentation/devicetree/bindings/interrupt-controller/rda,8810pl-intc.txt
|
||||
F: Documentation/devicetree/bindings/serial/rda,8810pl-uart.txt
|
||||
F: Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/ahci_platform.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/libata.h>
|
||||
@ -100,7 +100,7 @@ struct imx_ahci_priv {
|
||||
struct clk *phy_pclk0;
|
||||
struct clk *phy_pclk1;
|
||||
void __iomem *phy_base;
|
||||
int clkreq_gpio;
|
||||
struct gpio_desc *clkreq_gpiod;
|
||||
struct regmap *gpr;
|
||||
bool no_device;
|
||||
bool first_time;
|
||||
@ -980,7 +980,6 @@ static struct scsi_host_template ahci_platform_sht = {
|
||||
|
||||
static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv)
|
||||
{
|
||||
int ret;
|
||||
struct resource *phy_res;
|
||||
struct platform_device *pdev = imxpriv->ahci_pdev;
|
||||
struct device_node *np = dev->of_node;
|
||||
@ -1033,20 +1032,12 @@ static int imx8_sata_probe(struct device *dev, struct imx_ahci_priv *imxpriv)
|
||||
}
|
||||
|
||||
/* Fetch GPIO, then enable the external OSC */
|
||||
imxpriv->clkreq_gpio = of_get_named_gpio(np, "clkreq-gpio", 0);
|
||||
if (gpio_is_valid(imxpriv->clkreq_gpio)) {
|
||||
ret = devm_gpio_request_one(dev, imxpriv->clkreq_gpio,
|
||||
GPIOF_OUT_INIT_LOW,
|
||||
"SATA CLKREQ");
|
||||
if (ret == -EBUSY) {
|
||||
dev_info(dev, "clkreq had been initialized.\n");
|
||||
} else if (ret) {
|
||||
dev_err(dev, "%d unable to get clkreq.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (imxpriv->clkreq_gpio == -EPROBE_DEFER) {
|
||||
return imxpriv->clkreq_gpio;
|
||||
}
|
||||
imxpriv->clkreq_gpiod = devm_gpiod_get_optional(dev, "clkreq",
|
||||
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
if (IS_ERR(imxpriv->clkreq_gpiod))
|
||||
return PTR_ERR(imxpriv->clkreq_gpiod);
|
||||
if (imxpriv->clkreq_gpiod)
|
||||
gpiod_set_consumer_name(imxpriv->clkreq_gpiod, "SATA CLKREQ");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -120,6 +120,14 @@ config GPIO_ASPEED
|
||||
help
|
||||
Say Y here to support Aspeed AST2400 and AST2500 GPIO controllers.
|
||||
|
||||
config GPIO_ASPEED_SGPIO
|
||||
bool "Aspeed SGPIO support"
|
||||
depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO
|
||||
select GPIO_GENERIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say Y here to support Aspeed AST2500 SGPIO functionality.
|
||||
|
||||
config GPIO_ATH79
|
||||
tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
|
||||
default y if ATH79
|
||||
@ -147,6 +155,15 @@ config GPIO_BCM_KONA
|
||||
help
|
||||
Turn on GPIO support for Broadcom "Kona" chips.
|
||||
|
||||
config GPIO_BCM_XGS_IPROC
|
||||
tristate "BRCM XGS iProc GPIO support"
|
||||
depends on OF_GPIO && (ARCH_BCM_IPROC || COMPILE_TEST)
|
||||
select GPIO_GENERIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
default ARCH_BCM_IPROC
|
||||
help
|
||||
Say yes here to enable GPIO support for Broadcom XGS iProc SoCs.
|
||||
|
||||
config GPIO_BRCMSTB
|
||||
tristate "BRCMSTB GPIO support"
|
||||
default y if (ARCH_BRCMSTB || BMIPS_GENERIC)
|
||||
@ -435,6 +452,15 @@ config GPIO_RCAR
|
||||
help
|
||||
Say yes here to support GPIO on Renesas R-Car SoCs.
|
||||
|
||||
config GPIO_RDA
|
||||
bool "RDA Micro GPIO controller support"
|
||||
depends on ARCH_RDA || COMPILE_TEST
|
||||
depends on OF_GPIO
|
||||
select GPIO_GENERIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say Y here to support RDA Micro GPIO controller.
|
||||
|
||||
config GPIO_REG
|
||||
bool
|
||||
help
|
||||
@ -531,6 +557,7 @@ config GPIO_TEGRA186
|
||||
depends on ARCH_TEGRA_186_SOC || COMPILE_TEST
|
||||
depends on OF_GPIO
|
||||
select GPIOLIB_IRQCHIP
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
help
|
||||
Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.
|
||||
|
||||
@ -1320,7 +1347,7 @@ config GPIO_BT8XX
|
||||
The card needs to be physically altered for using it as a
|
||||
GPIO card. For more information on how to build a GPIO card
|
||||
from a BT8xx TV card, see the documentation file at
|
||||
Documentation/driver-api/bt8xxgpio.rst
|
||||
Documentation/driver-api/gpio/bt8xxgpio.rst
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -32,8 +32,10 @@ obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o
|
||||
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
|
||||
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
|
||||
obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio-aspeed-sgpio.o
|
||||
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
|
||||
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
|
||||
obj-$(CONFIG_GPIO_BCM_XGS_IPROC) += gpio-xgs-iproc.o
|
||||
obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
|
||||
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
@ -115,6 +117,7 @@ obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
|
||||
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
|
||||
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_REG) += gpio-reg.o
|
||||
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
|
||||
|
@ -59,7 +59,10 @@ static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
const unsigned port = offset / 8;
|
||||
const unsigned mask = BIT(offset % 8);
|
||||
|
||||
return !!(dio48egpio->io_state[port] & mask);
|
||||
if (dio48egpio->io_state[port] & mask)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -53,7 +53,7 @@ struct idi_48_gpio {
|
||||
|
||||
static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -51,9 +51,9 @@ struct idio_16_gpio {
|
||||
static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
if (offset > 15)
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -77,7 +77,10 @@ static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct mmio_74xx_gpio_priv *priv = gpiochip_get_data(gc);
|
||||
|
||||
return !(priv->flags & MMIO_74XX_DIR_OUT);
|
||||
if (priv->flags & MMIO_74XX_DIR_OUT)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
|
@ -92,7 +92,7 @@ static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
||||
ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return ret;
|
||||
return ret ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void amd_fch_gpio_set(struct gpio_chip *gc,
|
||||
|
@ -487,10 +487,10 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
u32 val;
|
||||
|
||||
if (!have_input(gpio, offset))
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
if (!have_output(gpio, offset))
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
|
||||
@ -498,8 +498,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return !val;
|
||||
|
||||
return val ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
|
||||
|
@ -127,7 +127,7 @@ static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
|
||||
u32 val;
|
||||
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio)) & GPIO_GPCTR0_IOTR_MASK;
|
||||
return !!val;
|
||||
return val ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
@ -144,7 +144,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
/* this function only applies to output pin */
|
||||
if (bcm_kona_gpio_get_dir(chip, gpio) == 1)
|
||||
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIO_LINE_DIRECTION_IN)
|
||||
goto out;
|
||||
|
||||
reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
|
||||
@ -170,7 +170,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
reg_base = kona_gpio->reg_base;
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
if (bcm_kona_gpio_get_dir(chip, gpio) == 1)
|
||||
if (bcm_kona_gpio_get_dir(chip, gpio) == GPIO_LINE_DIRECTION_IN)
|
||||
reg_offset = GPIO_IN_STATUS(bank_id);
|
||||
else
|
||||
reg_offset = GPIO_OUT_STATUS(bank_id);
|
||||
|
@ -54,8 +54,10 @@ static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
dev_err(bdgpio->chip.dev, "Could not read gpio direction\n");
|
||||
return ret;
|
||||
}
|
||||
if (val & BD70528_GPIO_OUT_EN_MASK)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return !(val & BD70528_GPIO_OUT_EN_MASK);
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
@ -166,9 +168,9 @@ static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
* locking would make no sense.
|
||||
*/
|
||||
ret = bd70528_get_direction(chip, offset);
|
||||
if (ret == 0)
|
||||
if (ret == GPIO_LINE_DIRECTION_OUT)
|
||||
ret = bd70528_gpio_get_o(bdgpio, offset);
|
||||
else if (ret == 1)
|
||||
else if (ret == GPIO_LINE_DIRECTION_IN)
|
||||
ret = bd70528_gpio_get_i(bdgpio, offset);
|
||||
else
|
||||
dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n");
|
||||
|
@ -37,8 +37,10 @@ static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip,
|
||||
ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (val & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return val & BIT(offset);
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -200,9 +200,9 @@ static int dln2_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
struct dln2_gpio *dln2 = gpiochip_get_data(chip);
|
||||
|
||||
if (test_bit(offset, dln2->output_enabled))
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
@ -214,7 +214,7 @@ static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
if (dir < 0)
|
||||
return dir;
|
||||
|
||||
if (dir == 1)
|
||||
if (dir == GPIO_LINE_DIRECTION_IN)
|
||||
return dln2_gpio_pin_get_in_val(dln2, offset);
|
||||
|
||||
return dln2_gpio_pin_get_out_val(dln2, offset);
|
||||
|
@ -77,7 +77,10 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
|
||||
unsigned int bit = (offset + exar_gpio->first_pin) % 8;
|
||||
|
||||
return !!(exar_get(chip, addr) & BIT(bit));
|
||||
if (exar_get(chip, addr) & BIT(bit))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
|
||||
|
@ -250,7 +250,10 @@ static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
superio_exit(sio->addr);
|
||||
|
||||
return !(dir & 1 << offset);
|
||||
if (dir & 1 << offset)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -52,7 +52,10 @@ static int gpiomm_gpio_get_direction(struct gpio_chip *chip,
|
||||
const unsigned int port = offset / 8;
|
||||
const unsigned int mask = BIT(offset % 8);
|
||||
|
||||
return !!(gpiommgpio->io_state[port] & mask);
|
||||
if (gpiommgpio->io_state[port] & mask)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int gpiomm_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -220,7 +220,10 @@ static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
egpio = gpiochip_get_data(chip);
|
||||
|
||||
return !test_bit(offset, &egpio->is_out);
|
||||
if (test_bit(offset, &egpio->is_out))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static void egpio_write_cache(struct egpio_info *ei)
|
||||
|
@ -159,7 +159,10 @@ static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
|
||||
|
||||
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
return ichx_read_bit(GPIO_IO_SEL, nr);
|
||||
if (ichx_read_bit(GPIO_IO_SEL, nr))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||
|
@ -104,7 +104,10 @@ static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
|
||||
struct kempld_device_data *pld = gpio->pld;
|
||||
|
||||
return !kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset);
|
||||
if (kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int kempld_gpio_pincount(struct kempld_device_data *pld)
|
||||
|
@ -33,7 +33,7 @@ static int lp873x_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
/* This device is output only */
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int lp873x_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -57,7 +57,10 @@ static int lp87565_gpio_get_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !(val & BIT(offset));
|
||||
if (val & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int lp87565_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -34,7 +34,10 @@ static int madera_gpio_get_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(val & MADERA_GP1_DIR_MASK);
|
||||
if (val & MADERA_GP1_DIR_MASK)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
|
||||
|
@ -94,7 +94,7 @@ DECLARE_CRC8_TABLE(max3191x_crc8);
|
||||
|
||||
static int max3191x_get_direction(struct gpio_chip *gpio, unsigned int offset)
|
||||
{
|
||||
return 1; /* always in */
|
||||
return GPIO_LINE_DIRECTION_IN; /* always in */
|
||||
}
|
||||
|
||||
static int max3191x_direction_input(struct gpio_chip *gpio, unsigned int offset)
|
||||
|
@ -18,109 +18,115 @@ struct max77620_gpio {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct regmap *rmap;
|
||||
struct device *dev;
|
||||
struct mutex buslock; /* irq_bus_lock */
|
||||
unsigned int irq_type[8];
|
||||
bool irq_enabled[8];
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77620_gpio_irqs[] = {
|
||||
[0] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE0,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 0,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[1] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE1,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 1,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[2] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE2,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 2,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[3] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE3,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 3,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[4] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE4,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 4,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[5] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE5,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 5,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[6] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE6,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 6,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
[7] = {
|
||||
.reg_offset = 0,
|
||||
.mask = MAX77620_IRQ_LVL2_GPIO_EDGE7,
|
||||
.type = {
|
||||
.type_rising_val = MAX77620_CNFG_GPIO_INT_RISING,
|
||||
.type_falling_val = MAX77620_CNFG_GPIO_INT_FALLING,
|
||||
.type_reg_mask = MAX77620_CNFG_GPIO_INT_MASK,
|
||||
.type_reg_offset = 7,
|
||||
.types_supported = IRQ_TYPE_EDGE_BOTH,
|
||||
},
|
||||
},
|
||||
};
|
||||
static irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
|
||||
{
|
||||
struct max77620_gpio *gpio = data;
|
||||
unsigned int value, offset;
|
||||
unsigned long pending;
|
||||
int err;
|
||||
|
||||
static const struct regmap_irq_chip max77620_gpio_irq_chip = {
|
||||
.name = "max77620-gpio",
|
||||
.irqs = max77620_gpio_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77620_gpio_irqs),
|
||||
.num_regs = 1,
|
||||
.num_type_reg = 8,
|
||||
.irq_reg_stride = 1,
|
||||
.type_reg_stride = 1,
|
||||
.status_base = MAX77620_REG_IRQ_LVL2_GPIO,
|
||||
.type_base = MAX77620_REG_GPIO0,
|
||||
err = regmap_read(gpio->rmap, MAX77620_REG_IRQ_LVL2_GPIO, &value);
|
||||
if (err < 0) {
|
||||
dev_err(gpio->dev, "REG_IRQ_LVL2_GPIO read failed: %d\n", err);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
pending = value;
|
||||
|
||||
for_each_set_bit(offset, &pending, 8) {
|
||||
unsigned int virq;
|
||||
|
||||
virq = irq_find_mapping(gpio->gpio_chip.irq.domain, offset);
|
||||
handle_nested_irq(virq);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void max77620_gpio_irq_mask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct max77620_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
gpio->irq_enabled[data->hwirq] = false;
|
||||
}
|
||||
|
||||
static void max77620_gpio_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct max77620_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
gpio->irq_enabled[data->hwirq] = true;
|
||||
}
|
||||
|
||||
static int max77620_gpio_set_irq_type(struct irq_data *data, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct max77620_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned int irq_type;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
irq_type = MAX77620_CNFG_GPIO_INT_RISING;
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
irq_type = MAX77620_CNFG_GPIO_INT_FALLING;
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
irq_type = MAX77620_CNFG_GPIO_INT_RISING |
|
||||
MAX77620_CNFG_GPIO_INT_FALLING;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio->irq_type[data->hwirq] = irq_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max77620_gpio_bus_lock(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct max77620_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
mutex_lock(&gpio->buslock);
|
||||
}
|
||||
|
||||
static void max77620_gpio_bus_sync_unlock(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct max77620_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned int value, offset = data->hwirq;
|
||||
int err;
|
||||
|
||||
value = gpio->irq_enabled[offset] ? gpio->irq_type[offset] : 0;
|
||||
|
||||
err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(offset),
|
||||
MAX77620_CNFG_GPIO_INT_MASK, value);
|
||||
if (err < 0)
|
||||
dev_err(chip->parent, "failed to update interrupt mask: %d\n",
|
||||
err);
|
||||
|
||||
mutex_unlock(&gpio->buslock);
|
||||
}
|
||||
|
||||
static struct irq_chip max77620_gpio_irqchip = {
|
||||
.name = "max77620-gpio",
|
||||
.irq_mask = max77620_gpio_irq_mask,
|
||||
.irq_unmask = max77620_gpio_irq_unmask,
|
||||
.irq_set_type = max77620_gpio_set_irq_type,
|
||||
.irq_bus_lock = max77620_gpio_bus_lock,
|
||||
.irq_bus_sync_unlock = max77620_gpio_bus_sync_unlock,
|
||||
.flags = IRQCHIP_MASK_ON_SUSPEND,
|
||||
};
|
||||
|
||||
static int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
|
||||
@ -254,14 +260,6 @@ static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int max77620_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct max77620_gpio *mgpio = gpiochip_get_data(gc);
|
||||
struct max77620_chip *chip = dev_get_drvdata(mgpio->dev->parent);
|
||||
|
||||
return regmap_irq_get_virq(chip->gpio_irq_data, offset);
|
||||
}
|
||||
|
||||
static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -287,7 +285,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
|
||||
mgpio->gpio_chip.set = max77620_gpio_set;
|
||||
mgpio->gpio_chip.set_config = max77620_gpio_set_config;
|
||||
mgpio->gpio_chip.to_irq = max77620_gpio_to_irq;
|
||||
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
|
||||
mgpio->gpio_chip.can_sleep = 1;
|
||||
mgpio->gpio_chip.base = -1;
|
||||
@ -303,15 +300,21 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq,
|
||||
IRQF_ONESHOT, -1,
|
||||
&max77620_gpio_irq_chip,
|
||||
&chip->gpio_irq_data);
|
||||
mutex_init(&mgpio->buslock);
|
||||
|
||||
gpiochip_irqchip_add_nested(&mgpio->gpio_chip, &max77620_gpio_irqchip,
|
||||
0, handle_edge_irq, IRQ_TYPE_NONE);
|
||||
|
||||
ret = request_threaded_irq(gpio_irq, NULL, max77620_gpio_irqhandler,
|
||||
IRQF_ONESHOT, "max77620-gpio", mgpio);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to add gpio irq_chip %d\n", ret);
|
||||
dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpiochip_set_nested_irqchip(&mgpio->gpio_chip, &max77620_gpio_irqchip,
|
||||
gpio_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,10 @@ static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
|
||||
|
||||
return !(readl(gpdr) & BIT(offset % 32));
|
||||
if (readl(gpdr) & BIT(offset % 32))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
|
||||
@ -362,9 +365,8 @@ static void mrfld_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
static int mrfld_irq_init_hw(struct gpio_chip *chip)
|
||||
static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
|
||||
{
|
||||
struct mrfld_gpio *priv = gpiochip_get_data(chip);
|
||||
void __iomem *reg;
|
||||
unsigned int base;
|
||||
|
||||
@ -376,8 +378,6 @@ static int mrfld_irq_init_hw(struct gpio_chip *chip)
|
||||
reg = gpio_reg(&priv->chip, base, GFER);
|
||||
writel(0, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv)
|
||||
@ -400,7 +400,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
{
|
||||
const struct mrfld_gpio_pinrange *range;
|
||||
const char *pinctrl_dev_name;
|
||||
struct gpio_irq_chip *girq;
|
||||
struct mrfld_gpio *priv;
|
||||
u32 gpio_base, irq_base;
|
||||
void __iomem *base;
|
||||
@ -448,21 +447,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
|
||||
raw_spin_lock_init(&priv->lock);
|
||||
|
||||
girq = &priv->chip.irq;
|
||||
girq->chip = &mrfld_irqchip;
|
||||
girq->init_hw = mrfld_irq_init_hw;
|
||||
girq->parent_handler = mrfld_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
||||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents)
|
||||
return -ENOMEM;
|
||||
girq->parents[0] = pdev->irq;
|
||||
girq->first = irq_base;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_bad_irq;
|
||||
|
||||
pci_set_drvdata(pdev, priv);
|
||||
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
||||
if (retval) {
|
||||
@ -484,6 +468,18 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
}
|
||||
}
|
||||
|
||||
retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
|
||||
handle_bad_irq, IRQ_TYPE_NONE);
|
||||
if (retval) {
|
||||
dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
mrfld_irq_init_hw(priv);
|
||||
|
||||
gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
|
||||
mrfld_irq_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -370,15 +370,24 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
/* Return 0 if output, 1 if input */
|
||||
if (gc->bgpio_dir_unreadable)
|
||||
return !(gc->bgpio_dir & bgpio_line2mask(gc, gpio));
|
||||
if (gc->reg_dir_out)
|
||||
return !(gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio));
|
||||
if (gc->bgpio_dir_unreadable) {
|
||||
if (gc->bgpio_dir & bgpio_line2mask(gc, gpio))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
if (gc->reg_dir_out) {
|
||||
if (gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
if (gc->reg_dir_in)
|
||||
return !!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio));
|
||||
if (!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio)))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
/* This should not happen */
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
|
@ -34,14 +34,9 @@
|
||||
|
||||
#define gpio_mockup_err(...) pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__)
|
||||
|
||||
enum {
|
||||
GPIO_MOCKUP_DIR_IN = 0,
|
||||
GPIO_MOCKUP_DIR_OUT = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct gpio_pin_status - structure describing a GPIO status
|
||||
* @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out
|
||||
* @dir: Configures direction of gpio as "in" or "out"
|
||||
* @value: Configures status of the gpio as 0(low) or 1(high)
|
||||
*/
|
||||
struct gpio_mockup_line_status {
|
||||
@ -152,7 +147,7 @@ static int gpio_mockup_dirout(struct gpio_chip *gc,
|
||||
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT;
|
||||
chip->lines[offset].dir = GPIO_LINE_DIRECTION_OUT;
|
||||
__gpio_mockup_set(chip, offset, value);
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
@ -164,7 +159,7 @@ static int gpio_mockup_dirin(struct gpio_chip *gc, unsigned int offset)
|
||||
struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN;
|
||||
chip->lines[offset].dir = GPIO_LINE_DIRECTION_IN;
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
return 0;
|
||||
|
@ -78,9 +78,9 @@ static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
|
||||
/* All lines are hard wired to be either input or output, not both. */
|
||||
if (chip->desc->in_mask & BIT(offset))
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
else if (chip->desc->out_mask & BIT(offset))
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#define MPC8XXX_GPIO_PINS 32
|
||||
|
||||
@ -127,20 +128,19 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc)
|
||||
static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = data;
|
||||
struct gpio_chip *gc = &mpc8xxx_gc->gc;
|
||||
unsigned int mask;
|
||||
unsigned long mask;
|
||||
int i;
|
||||
|
||||
mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER)
|
||||
& gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR);
|
||||
if (mask)
|
||||
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
|
||||
32 - ffs(mask)));
|
||||
if (chip->irq_eoi)
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
for_each_set_bit(i, &mask, 32)
|
||||
generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, 31 - i));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_unmask(struct irq_data *d)
|
||||
@ -409,8 +409,16 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
if (devtype->gpio_dir_in_init)
|
||||
devtype->gpio_dir_in_init(gc);
|
||||
|
||||
irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
|
||||
mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
|
||||
ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn,
|
||||
mpc8xxx_gpio_irq_cascade,
|
||||
IRQF_NO_THREAD | 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);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
iounmap(mpc8xxx_gc->regs);
|
||||
|
@ -384,7 +384,10 @@ static int mvebu_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
|
||||
|
||||
regmap_read(mvchip->regs, GPIO_IO_CONF_OFF + mvchip->offset, &u);
|
||||
|
||||
return !!(u & BIT(pin));
|
||||
if (u & BIT(pin))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin)
|
||||
|
@ -248,7 +248,10 @@ static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
u32 dir;
|
||||
|
||||
dir = readl(port->base + PINCTRL_DOE(port));
|
||||
return !(dir & mask);
|
||||
if (dir & mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static const struct platform_device_id mxs_gpio_ids[] = {
|
||||
|
@ -805,8 +805,10 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct gpio_bank *bank = gpiochip_get_data(chip);
|
||||
|
||||
return !!(readl_relaxed(bank->base + bank->regs->direction) &
|
||||
BIT(offset));
|
||||
if (readl_relaxed(bank->base + bank->regs->direction) & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -449,7 +449,10 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(reg_val & bit);
|
||||
if (reg_val & bit)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
|
||||
|
@ -61,9 +61,9 @@ static int idio_16_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
if (offset > 15)
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int idio_16_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -104,15 +104,18 @@ static int idio_24_gpio_get_direction(struct gpio_chip *chip,
|
||||
|
||||
/* FET Outputs */
|
||||
if (offset < 24)
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
/* Isolated Inputs */
|
||||
if (offset < 48)
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
/* TTL/CMOS I/O */
|
||||
/* OUT MODE = 1 when TTL/CMOS Output Mode is set */
|
||||
return !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask);
|
||||
if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int idio_24_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -65,7 +65,7 @@ static int pisosr_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
/* This device always input */
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int pisosr_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -63,7 +63,10 @@ static int pl061_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct pl061 *pl061 = gpiochip_get_data(gc);
|
||||
|
||||
return !(readb(pl061->base + GPIODIR) & BIT(offset));
|
||||
if (readb(pl061->base + GPIODIR) & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
|
@ -147,7 +147,10 @@ static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
|
||||
get.gpio);
|
||||
return ret ? ret : -EIO;
|
||||
}
|
||||
return !get.direction;
|
||||
if (get.direction)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off)
|
||||
|
@ -279,7 +279,10 @@ static int gpio_rcar_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct gpio_rcar_priv *p = gpiochip_get_data(chip);
|
||||
|
||||
return !(gpio_rcar_read(p, INOUTSEL) & BIT(offset));
|
||||
if (gpio_rcar_read(p, INOUTSEL) & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
294
drivers/gpio/gpio-rda.c
Normal file
294
drivers/gpio/gpio-rda.c
Normal file
@ -0,0 +1,294 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* RDA Micro GPIO driver
|
||||
*
|
||||
* Copyright (C) 2012 RDA Micro Inc.
|
||||
* Copyright (C) 2019 Manivannan Sadhasivam
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define RDA_GPIO_OEN_VAL 0x00
|
||||
#define RDA_GPIO_OEN_SET_OUT 0x04
|
||||
#define RDA_GPIO_OEN_SET_IN 0x08
|
||||
#define RDA_GPIO_VAL 0x0c
|
||||
#define RDA_GPIO_SET 0x10
|
||||
#define RDA_GPIO_CLR 0x14
|
||||
#define RDA_GPIO_INT_CTRL_SET 0x18
|
||||
#define RDA_GPIO_INT_CTRL_CLR 0x1c
|
||||
#define RDA_GPIO_INT_CLR 0x20
|
||||
#define RDA_GPIO_INT_STATUS 0x24
|
||||
|
||||
#define RDA_GPIO_IRQ_RISE_SHIFT 0
|
||||
#define RDA_GPIO_IRQ_FALL_SHIFT 8
|
||||
#define RDA_GPIO_DEBOUCE_SHIFT 16
|
||||
#define RDA_GPIO_LEVEL_SHIFT 24
|
||||
|
||||
#define RDA_GPIO_IRQ_MASK 0xff
|
||||
|
||||
/* Each bank consists of 32 GPIOs */
|
||||
#define RDA_GPIO_BANK_NR 32
|
||||
|
||||
struct rda_gpio {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *base;
|
||||
spinlock_t lock;
|
||||
struct irq_chip irq_chip;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static inline void rda_gpio_update(struct gpio_chip *chip, unsigned int offset,
|
||||
u16 reg, int val)
|
||||
{
|
||||
struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
|
||||
void __iomem *base = rda_gpio->base;
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
|
||||
spin_lock_irqsave(&rda_gpio->lock, flags);
|
||||
tmp = readl_relaxed(base + reg);
|
||||
|
||||
if (val)
|
||||
tmp |= BIT(offset);
|
||||
else
|
||||
tmp &= ~BIT(offset);
|
||||
|
||||
writel_relaxed(tmp, base + reg);
|
||||
spin_unlock_irqrestore(&rda_gpio->lock, flags);
|
||||
}
|
||||
|
||||
static void rda_gpio_irq_mask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
|
||||
void __iomem *base = rda_gpio->base;
|
||||
u32 offset = irqd_to_hwirq(data);
|
||||
u32 value;
|
||||
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
|
||||
value |= BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
|
||||
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
|
||||
}
|
||||
|
||||
static void rda_gpio_irq_ack(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
u32 offset = irqd_to_hwirq(data);
|
||||
|
||||
rda_gpio_update(chip, offset, RDA_GPIO_INT_CLR, 1);
|
||||
}
|
||||
|
||||
static int rda_gpio_set_irq(struct gpio_chip *chip, u32 offset,
|
||||
unsigned int flow_type)
|
||||
{
|
||||
struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
|
||||
void __iomem *base = rda_gpio->base;
|
||||
u32 value;
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
/* Set rising edge trigger */
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
|
||||
|
||||
/* Switch to edge trigger interrupt */
|
||||
value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
/* Set falling edge trigger */
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
|
||||
|
||||
/* Switch to edge trigger interrupt */
|
||||
value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
/* Set both edge trigger */
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
|
||||
value |= BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
|
||||
|
||||
/* Switch to edge trigger interrupt */
|
||||
value = BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_CLR);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
/* Set high level trigger */
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_RISE_SHIFT;
|
||||
|
||||
/* Switch to level trigger interrupt */
|
||||
value |= BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
/* Set low level trigger */
|
||||
value = BIT(offset) << RDA_GPIO_IRQ_FALL_SHIFT;
|
||||
|
||||
/* Switch to level trigger interrupt */
|
||||
value |= BIT(offset) << RDA_GPIO_LEVEL_SHIFT;
|
||||
writel_relaxed(value, base + RDA_GPIO_INT_CTRL_SET);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rda_gpio_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
u32 offset = irqd_to_hwirq(data);
|
||||
u32 trigger = irqd_get_trigger_type(data);
|
||||
|
||||
rda_gpio_set_irq(chip, offset, trigger);
|
||||
}
|
||||
|
||||
static int rda_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
{
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
|
||||
u32 offset = irqd_to_hwirq(data);
|
||||
int ret;
|
||||
|
||||
ret = rda_gpio_set_irq(chip, offset, flow_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
else if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rda_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
|
||||
struct irq_chip *ic = irq_desc_get_chip(desc);
|
||||
struct rda_gpio *rda_gpio = gpiochip_get_data(chip);
|
||||
unsigned long status;
|
||||
u32 n, girq;
|
||||
|
||||
chained_irq_enter(ic, desc);
|
||||
|
||||
status = readl_relaxed(rda_gpio->base + RDA_GPIO_INT_STATUS);
|
||||
/* Only lower 8 bits are capable of generating interrupts */
|
||||
status &= RDA_GPIO_IRQ_MASK;
|
||||
|
||||
for_each_set_bit(n, &status, RDA_GPIO_BANK_NR) {
|
||||
girq = irq_find_mapping(chip->irq.domain, n);
|
||||
generic_handle_irq(girq);
|
||||
}
|
||||
|
||||
chained_irq_exit(ic, desc);
|
||||
}
|
||||
|
||||
static int rda_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_irq_chip *girq;
|
||||
struct rda_gpio *rda_gpio;
|
||||
u32 ngpios;
|
||||
int ret;
|
||||
|
||||
rda_gpio = devm_kzalloc(dev, sizeof(*rda_gpio), GFP_KERNEL);
|
||||
if (!rda_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = device_property_read_u32(dev, "ngpios", &ngpios);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Not all ports have interrupt capability. For instance, on
|
||||
* RDA8810PL, GPIOC doesn't support interrupt. So we must handle
|
||||
* those also.
|
||||
*/
|
||||
rda_gpio->irq = platform_get_irq(pdev, 0);
|
||||
|
||||
rda_gpio->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(rda_gpio->base))
|
||||
return PTR_ERR(rda_gpio->base);
|
||||
|
||||
spin_lock_init(&rda_gpio->lock);
|
||||
|
||||
ret = bgpio_init(&rda_gpio->chip, dev, 4,
|
||||
rda_gpio->base + RDA_GPIO_VAL,
|
||||
rda_gpio->base + RDA_GPIO_SET,
|
||||
rda_gpio->base + RDA_GPIO_CLR,
|
||||
rda_gpio->base + RDA_GPIO_OEN_SET_OUT,
|
||||
rda_gpio->base + RDA_GPIO_OEN_SET_IN,
|
||||
BGPIOF_READ_OUTPUT_REG_SET);
|
||||
if (ret) {
|
||||
dev_err(dev, "bgpio_init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rda_gpio->chip.label = dev_name(dev);
|
||||
rda_gpio->chip.ngpio = ngpios;
|
||||
rda_gpio->chip.base = -1;
|
||||
rda_gpio->chip.parent = dev;
|
||||
rda_gpio->chip.of_node = np;
|
||||
|
||||
if (rda_gpio->irq >= 0) {
|
||||
rda_gpio->irq_chip.name = "rda-gpio",
|
||||
rda_gpio->irq_chip.irq_ack = rda_gpio_irq_ack,
|
||||
rda_gpio->irq_chip.irq_mask = rda_gpio_irq_mask,
|
||||
rda_gpio->irq_chip.irq_unmask = rda_gpio_irq_unmask,
|
||||
rda_gpio->irq_chip.irq_set_type = rda_gpio_irq_set_type,
|
||||
rda_gpio->irq_chip.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
|
||||
girq = &rda_gpio->chip.irq;
|
||||
girq->chip = &rda_gpio->irq_chip;
|
||||
girq->handler = handle_bad_irq;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->parent_handler = rda_gpio_irq_handler;
|
||||
girq->parent_handler_data = rda_gpio;
|
||||
girq->num_parents = 1;
|
||||
girq->parents = devm_kcalloc(dev, 1,
|
||||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents)
|
||||
return -ENOMEM;
|
||||
girq->parents[0] = rda_gpio->irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rda_gpio);
|
||||
|
||||
return devm_gpiochip_add_data(dev, &rda_gpio->chip, rda_gpio);
|
||||
}
|
||||
|
||||
static const struct of_device_id rda_gpio_of_match[] = {
|
||||
{ .compatible = "rda,8810pl-gpio", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rda_gpio_of_match);
|
||||
|
||||
static struct platform_driver rda_gpio_driver = {
|
||||
.probe = rda_gpio_probe,
|
||||
.driver = {
|
||||
.name = "rda-gpio",
|
||||
.of_match_table = rda_gpio_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(rda_gpio_driver, rda_gpio_probe);
|
||||
|
||||
MODULE_DESCRIPTION("RDA Micro GPIO driver");
|
||||
MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -26,7 +26,8 @@ static int gpio_reg_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct gpio_reg *r = to_gpio_reg(gc);
|
||||
|
||||
return r->direction & BIT(offset) ? 1 : 0;
|
||||
return r->direction & BIT(offset) ? GPIO_LINE_DIRECTION_IN :
|
||||
GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset,
|
||||
|
@ -53,7 +53,10 @@ static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
|
||||
|
||||
return !(readl_relaxed(gpdr) & BIT(offset));
|
||||
if (readl_relaxed(gpdr) & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -119,7 +119,8 @@ static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ret == PIOBU_IN) ? 1 : 0;
|
||||
return (ret == PIOBU_IN) ? GPIO_LINE_DIRECTION_IN :
|
||||
GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,9 +155,9 @@ static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
|
||||
/* if pin is input, read value from PDS else read from SOD */
|
||||
int ret = sama5d2_piobu_get_direction(chip, pin);
|
||||
|
||||
if (ret == 1)
|
||||
if (ret == GPIO_LINE_DIRECTION_IN)
|
||||
ret = sama5d2_piobu_read_value(chip, pin, PIOBU_PDS);
|
||||
else if (!ret)
|
||||
else if (ret == GPIO_LINE_DIRECTION_OUT)
|
||||
ret = sama5d2_piobu_read_value(chip, pin, PIOBU_SOD);
|
||||
|
||||
if (ret < 0)
|
||||
|
@ -127,7 +127,10 @@ static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
|
||||
{
|
||||
struct sch_gpio *sch = gpiochip_get_data(gc);
|
||||
|
||||
return sch_gpio_reg_get(sch, gpio_num, GIO);
|
||||
if (sch_gpio_reg_get(sch, gpio_num, GIO))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static const struct gpio_chip sch_gpio_chip = {
|
||||
|
@ -228,7 +228,10 @@ static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
data = inb(block->runtime_reg + block->config_regs[offset]);
|
||||
spin_unlock(&block->lock);
|
||||
|
||||
return !!(data & SCH311X_GPIO_CONF_DIR);
|
||||
if (data & SCH311X_GPIO_CONF_DIR)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
|
@ -203,9 +203,9 @@ static int gpio_siox_direction_output(struct gpio_chip *chip,
|
||||
static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
if (offset < 12)
|
||||
return 1; /* input */
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
else
|
||||
return 0; /* output */
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int gpio_siox_probe(struct siox_device *sdevice)
|
||||
|
@ -84,7 +84,10 @@ static int stmpe_gpio_get_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !(ret & mask);
|
||||
if (ret & mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int stmpe_gpio_direction_output(struct gpio_chip *chip,
|
||||
|
@ -97,7 +97,10 @@ static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !(ret & BIT(pos));
|
||||
if (ret & BIT(pos))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
|
@ -215,7 +215,10 @@ static int tegra_gpio_get_direction(struct gpio_chip *chip,
|
||||
|
||||
oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset));
|
||||
|
||||
return !(oe & pin_mask);
|
||||
if (oe & pin_mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
|
||||
|
@ -53,6 +53,7 @@ struct tegra_gpio_soc {
|
||||
const struct tegra_gpio_port *ports;
|
||||
unsigned int num_ports;
|
||||
const char *name;
|
||||
unsigned int instance;
|
||||
};
|
||||
|
||||
struct tegra_gpio {
|
||||
@ -110,9 +111,9 @@ static int tegra186_gpio_get_direction(struct gpio_chip *chip,
|
||||
|
||||
value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
|
||||
if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int tegra186_gpio_direction_input(struct gpio_chip *chip,
|
||||
@ -327,7 +328,7 @@ static int tegra186_irq_set_type(struct irq_data *data, unsigned int type)
|
||||
else
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
return irq_chip_set_type_parent(data, type);
|
||||
}
|
||||
|
||||
static void tegra186_gpio_irq(struct irq_desc *desc)
|
||||
@ -367,39 +368,80 @@ skip:
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,
|
||||
struct device_node *np,
|
||||
const u32 *spec, unsigned int size,
|
||||
unsigned long *hwirq,
|
||||
unsigned int *type)
|
||||
static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain,
|
||||
struct irq_fwspec *fwspec,
|
||||
unsigned long *hwirq,
|
||||
unsigned int *type)
|
||||
{
|
||||
struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
|
||||
unsigned int port, pin, i, offset = 0;
|
||||
|
||||
if (size < 2)
|
||||
if (WARN_ON(gpio->gpio.of_gpio_n_cells < 2))
|
||||
return -EINVAL;
|
||||
|
||||
port = spec[0] / 8;
|
||||
pin = spec[0] % 8;
|
||||
|
||||
if (port >= gpio->soc->num_ports) {
|
||||
dev_err(gpio->gpio.parent, "invalid port number: %u\n", port);
|
||||
if (WARN_ON(fwspec->param_count < gpio->gpio.of_gpio_n_cells))
|
||||
return -EINVAL;
|
||||
|
||||
port = fwspec->param[0] / 8;
|
||||
pin = fwspec->param[0] % 8;
|
||||
|
||||
if (port >= gpio->soc->num_ports)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < port; i++)
|
||||
offset += gpio->soc->ports[i].pins;
|
||||
|
||||
*type = spec[1] & IRQ_TYPE_SENSE_MASK;
|
||||
*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
|
||||
*hwirq = offset + pin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
|
||||
.map = gpiochip_irq_map,
|
||||
.unmap = gpiochip_irq_unmap,
|
||||
.xlate = tegra186_gpio_irq_domain_xlate,
|
||||
static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip,
|
||||
struct irq_fwspec *fwspec,
|
||||
unsigned int parent_hwirq,
|
||||
unsigned int parent_type)
|
||||
{
|
||||
struct tegra_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
fwspec->param_count = 3;
|
||||
fwspec->param[0] = gpio->soc->instance;
|
||||
fwspec->param[1] = parent_hwirq;
|
||||
fwspec->param[2] = parent_type;
|
||||
}
|
||||
|
||||
static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
|
||||
unsigned int hwirq,
|
||||
unsigned int type,
|
||||
unsigned int *parent_hwirq,
|
||||
unsigned int *parent_type)
|
||||
{
|
||||
*parent_hwirq = chip->irq.child_offset_to_irq(chip, hwirq);
|
||||
*parent_type = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tegra186_gpio_child_offset_to_irq(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct tegra_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < gpio->soc->num_ports; i++) {
|
||||
if (offset < gpio->soc->ports[i].pins)
|
||||
break;
|
||||
|
||||
offset -= gpio->soc->ports[i].pins;
|
||||
}
|
||||
|
||||
return offset + i * 8;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra186_pmc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra186-pmc" },
|
||||
{ .compatible = "nvidia,tegra194-pmc" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
@ -407,6 +449,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
unsigned int i, j, offset;
|
||||
struct gpio_irq_chip *irq;
|
||||
struct tegra_gpio *gpio;
|
||||
struct device_node *np;
|
||||
struct resource *res;
|
||||
char **names;
|
||||
int err;
|
||||
@ -487,10 +530,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
gpio->intc.irq_mask = tegra186_irq_mask;
|
||||
gpio->intc.irq_unmask = tegra186_irq_unmask;
|
||||
gpio->intc.irq_set_type = tegra186_irq_set_type;
|
||||
gpio->intc.irq_set_wake = irq_chip_set_wake_parent;
|
||||
|
||||
irq = &gpio->gpio.irq;
|
||||
irq->chip = &gpio->intc;
|
||||
irq->domain_ops = &tegra186_gpio_irq_domain_ops;
|
||||
irq->fwnode = of_node_to_fwnode(pdev->dev.of_node);
|
||||
irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq;
|
||||
irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec;
|
||||
irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq;
|
||||
irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate;
|
||||
irq->handler = handle_simple_irq;
|
||||
irq->default_type = IRQ_TYPE_NONE;
|
||||
irq->parent_handler = tegra186_gpio_irq;
|
||||
@ -498,6 +546,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
|
||||
irq->num_parents = gpio->num_irq;
|
||||
irq->parents = gpio->irq;
|
||||
|
||||
np = of_find_matching_node(NULL, tegra186_pmc_of_match);
|
||||
if (np) {
|
||||
irq->parent_domain = irq_find_host(np);
|
||||
of_node_put(np);
|
||||
|
||||
if (!irq->parent_domain)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
|
||||
sizeof(*irq->map), GFP_KERNEL);
|
||||
if (!irq->map)
|
||||
@ -564,6 +621,7 @@ static const struct tegra_gpio_soc tegra186_main_soc = {
|
||||
.num_ports = ARRAY_SIZE(tegra186_main_ports),
|
||||
.ports = tegra186_main_ports,
|
||||
.name = "tegra186-gpio",
|
||||
.instance = 0,
|
||||
};
|
||||
|
||||
#define TEGRA186_AON_GPIO_PORT(port, base, count, controller) \
|
||||
@ -589,6 +647,7 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {
|
||||
.num_ports = ARRAY_SIZE(tegra186_aon_ports),
|
||||
.ports = tegra186_aon_ports,
|
||||
.name = "tegra186-gpio-aon",
|
||||
.instance = 1,
|
||||
};
|
||||
|
||||
#define TEGRA194_MAIN_GPIO_PORT(port, base, count, controller) \
|
||||
@ -634,6 +693,7 @@ static const struct tegra_gpio_soc tegra194_main_soc = {
|
||||
.num_ports = ARRAY_SIZE(tegra194_main_ports),
|
||||
.ports = tegra194_main_ports,
|
||||
.name = "tegra194-gpio",
|
||||
.instance = 0,
|
||||
};
|
||||
|
||||
#define TEGRA194_AON_GPIO_PORT(port, base, count, controller) \
|
||||
@ -656,6 +716,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
|
||||
.num_ports = ARRAY_SIZE(tegra194_aon_ports),
|
||||
.ports = tegra194_aon_ports,
|
||||
.name = "tegra194-gpio-aon",
|
||||
.instance = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra186_gpio_of_match[] = {
|
||||
|
@ -169,7 +169,10 @@ static int thunderx_gpio_get_direction(struct gpio_chip *chip, unsigned int line
|
||||
|
||||
bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
|
||||
|
||||
return !(bit_cfg & GPIO_BIT_CFG_TX_OE);
|
||||
if (bit_cfg & GPIO_BIT_CFG_TX_OE)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int thunderx_gpio_set_config(struct gpio_chip *chip,
|
||||
|
@ -39,7 +39,7 @@ static int tpic2810_get_direction(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
/* This device always output */
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int tpic2810_direction_input(struct gpio_chip *chip,
|
||||
|
@ -21,7 +21,7 @@ static int tps65086_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
/* This device is output only */
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int tps65086_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -32,9 +32,9 @@ static int tps65912_gpio_get_direction(struct gpio_chip *gc,
|
||||
return ret;
|
||||
|
||||
if (val & GPIO_CFG_MASK)
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
else
|
||||
return 1;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int tps65912_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
|
@ -47,7 +47,6 @@ static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
return !!(val & BIT(offset));
|
||||
}
|
||||
|
||||
/* Return 0 if output, 1 if input */
|
||||
static int tps68470_gpio_get_direction(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
@ -57,7 +56,7 @@ static int tps68470_gpio_get_direction(struct gpio_chip *gc,
|
||||
|
||||
/* rest are always outputs */
|
||||
if (offset >= TPS68470_N_REGULAR_GPIO)
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val);
|
||||
if (ret) {
|
||||
@ -67,7 +66,8 @@ static int tps68470_gpio_get_direction(struct gpio_chip *gc,
|
||||
}
|
||||
|
||||
val &= TPS68470_GPIO_MODE_MASK;
|
||||
return val >= TPS68470_GPIO_MODE_OUT_CMOS ? 0 : 1;
|
||||
return val >= TPS68470_GPIO_MODE_OUT_CMOS ? GPIO_LINE_DIRECTION_OUT :
|
||||
GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
|
@ -101,7 +101,10 @@ static int tqmx86_gpio_direction_output(struct gpio_chip *chip,
|
||||
static int tqmx86_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
return !!(TQMX86_DIR_INPUT_MASK & BIT(offset));
|
||||
if (TQMX86_DIR_INPUT_MASK & BIT(offset))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void tqmx86_gpio_irq_mask(struct irq_data *data)
|
||||
|
@ -44,7 +44,10 @@ static int ts4900_gpio_get_direction(struct gpio_chip *chip,
|
||||
|
||||
regmap_read(priv->regmap, offset, ®);
|
||||
|
||||
return !(reg & TS4900_GPIO_OE);
|
||||
if (reg & TS4900_GPIO_OE)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int ts4900_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -165,10 +165,10 @@ static int twl4030_get_gpio_direction(int gpio)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* 1 = output, but gpiolib semantics are inverse so invert */
|
||||
ret = !(ret & d_msk);
|
||||
if (ret & d_msk)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return ret;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int twl4030_set_gpio_dataout(int gpio, int enable)
|
||||
@ -380,10 +380,10 @@ static int twl_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct gpio_twl4030_priv *priv = gpiochip_get_data(chip);
|
||||
/*
|
||||
* Default 0 = output
|
||||
* Default GPIO_LINE_DIRECTION_OUT
|
||||
* LED GPIOs >= TWL4030_GPIO_MAX are always output
|
||||
*/
|
||||
int ret = 0;
|
||||
int ret = GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (offset < TWL4030_GPIO_MAX) {
|
||||
|
@ -34,8 +34,7 @@ static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
static int twl6040gpo_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
/* This means "out" */
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int twl6040gpo_direction_out(struct gpio_chip *chip, unsigned offset,
|
||||
|
@ -113,7 +113,10 @@ static int uniphier_gpio_offset_read(struct gpio_chip *chip,
|
||||
static int uniphier_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
return uniphier_gpio_offset_read(chip, offset, UNIPHIER_GPIO_PORT_DIR);
|
||||
if (uniphier_gpio_offset_read(chip, offset, UNIPHIER_GPIO_PORT_DIR))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int uniphier_gpio_direction_input(struct gpio_chip *chip,
|
||||
|
@ -170,13 +170,16 @@ static int wcove_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
|
||||
int ret, reg = to_reg(gpio, CTRL_OUT);
|
||||
|
||||
if (reg < 0)
|
||||
return 0;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
ret = regmap_read(wg->regmap, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !(val & CTLO_DIR_OUT);
|
||||
if (val & CTLO_DIR_OUT)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int wcove_gpio_get(struct gpio_chip *chip, unsigned int gpio)
|
||||
|
@ -56,7 +56,10 @@ static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
const unsigned port = offset / 8;
|
||||
const unsigned mask = BIT(offset % 8);
|
||||
|
||||
return !!(ws16c48gpio->io_state[port] & mask);
|
||||
if (ws16c48gpio->io_state[port] & mask)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -80,7 +80,10 @@ static int xgene_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
|
||||
bit_offset = GPIO_BIT_OFFSET(offset);
|
||||
|
||||
return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset));
|
||||
if (ioread32(chip->base + bank_offset) & BIT(bit_offset))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
|
||||
|
321
drivers/gpio/gpio-xgs-iproc.c
Normal file
321
drivers/gpio/gpio-xgs-iproc.c
Normal file
@ -0,0 +1,321 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2017 Broadcom
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define IPROC_CCA_INT_F_GPIOINT BIT(0)
|
||||
#define IPROC_CCA_INT_STS 0x20
|
||||
#define IPROC_CCA_INT_MASK 0x24
|
||||
|
||||
#define IPROC_GPIO_CCA_DIN 0x0
|
||||
#define IPROC_GPIO_CCA_DOUT 0x4
|
||||
#define IPROC_GPIO_CCA_OUT_EN 0x8
|
||||
#define IPROC_GPIO_CCA_INT_LEVEL 0x10
|
||||
#define IPROC_GPIO_CCA_INT_LEVEL_MASK 0x14
|
||||
#define IPROC_GPIO_CCA_INT_EVENT 0x18
|
||||
#define IPROC_GPIO_CCA_INT_EVENT_MASK 0x1C
|
||||
#define IPROC_GPIO_CCA_INT_EDGE 0x24
|
||||
|
||||
struct iproc_gpio_chip {
|
||||
struct irq_chip irqchip;
|
||||
struct gpio_chip gc;
|
||||
spinlock_t lock;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
void __iomem *intr;
|
||||
};
|
||||
|
||||
static inline struct iproc_gpio_chip *
|
||||
to_iproc_gpio(struct gpio_chip *gc)
|
||||
{
|
||||
return container_of(gc, struct iproc_gpio_chip, gc);
|
||||
}
|
||||
|
||||
static void iproc_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
|
||||
int pin = d->hwirq;
|
||||
unsigned long flags;
|
||||
u32 irq = d->irq;
|
||||
u32 irq_type, event_status = 0;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
irq_type = irq_get_trigger_type(irq);
|
||||
if (irq_type & IRQ_TYPE_EDGE_BOTH) {
|
||||
event_status |= BIT(pin);
|
||||
writel_relaxed(event_status,
|
||||
chip->base + IPROC_GPIO_CCA_INT_EVENT);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
static void iproc_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
|
||||
int pin = d->hwirq;
|
||||
unsigned long flags;
|
||||
u32 irq = d->irq;
|
||||
u32 int_mask, irq_type, event_mask;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
irq_type = irq_get_trigger_type(irq);
|
||||
event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
|
||||
int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
|
||||
|
||||
if (irq_type & IRQ_TYPE_EDGE_BOTH) {
|
||||
event_mask |= 1 << pin;
|
||||
writel_relaxed(event_mask,
|
||||
chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
|
||||
} else {
|
||||
int_mask |= 1 << pin;
|
||||
writel_relaxed(int_mask,
|
||||
chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
static void iproc_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
|
||||
int pin = d->hwirq;
|
||||
unsigned long flags;
|
||||
u32 irq = d->irq;
|
||||
u32 irq_type, int_mask, event_mask;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
irq_type = irq_get_trigger_type(irq);
|
||||
event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
|
||||
int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
|
||||
|
||||
if (irq_type & IRQ_TYPE_EDGE_BOTH) {
|
||||
event_mask &= ~BIT(pin);
|
||||
writel_relaxed(event_mask,
|
||||
chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
|
||||
} else {
|
||||
int_mask &= ~BIT(pin);
|
||||
writel_relaxed(int_mask,
|
||||
chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
|
||||
}
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
static int iproc_gpio_irq_set_type(struct irq_data *d, u32 type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
|
||||
int pin = d->hwirq;
|
||||
unsigned long flags;
|
||||
u32 irq = d->irq;
|
||||
u32 event_pol, int_pol;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
switch (type & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
event_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EDGE);
|
||||
event_pol &= ~BIT(pin);
|
||||
writel_relaxed(event_pol, chip->base + IPROC_GPIO_CCA_INT_EDGE);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
event_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EDGE);
|
||||
event_pol |= BIT(pin);
|
||||
writel_relaxed(event_pol, chip->base + IPROC_GPIO_CCA_INT_EDGE);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
int_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);
|
||||
int_pol &= ~BIT(pin);
|
||||
writel_relaxed(int_pol, chip->base + IPROC_GPIO_CCA_INT_LEVEL);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
int_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);
|
||||
int_pol |= BIT(pin);
|
||||
writel_relaxed(int_pol, chip->base + IPROC_GPIO_CCA_INT_LEVEL);
|
||||
break;
|
||||
default:
|
||||
/* should not come here */
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq);
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t iproc_gpio_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct gpio_chip *gc = (struct gpio_chip *)data;
|
||||
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
|
||||
int bit;
|
||||
unsigned long int_bits = 0;
|
||||
u32 int_status;
|
||||
|
||||
/* go through the entire GPIOs and handle all interrupts */
|
||||
int_status = readl_relaxed(chip->intr + IPROC_CCA_INT_STS);
|
||||
if (int_status & IPROC_CCA_INT_F_GPIOINT) {
|
||||
u32 event, level;
|
||||
|
||||
/* Get level and edge interrupts */
|
||||
event =
|
||||
readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
|
||||
event &= readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT);
|
||||
level = readl_relaxed(chip->base + IPROC_GPIO_CCA_DIN);
|
||||
level ^= readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);
|
||||
level &=
|
||||
readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
|
||||
int_bits = level | event;
|
||||
|
||||
for_each_set_bit(bit, &int_bits, gc->ngpio)
|
||||
generic_handle_irq(irq_linear_revmap(gc->irq.domain, bit));
|
||||
}
|
||||
|
||||
return int_bits ? IRQ_HANDLED : IRQ_NONE;
|
||||
}
|
||||
|
||||
static int iproc_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
struct iproc_gpio_chip *chip;
|
||||
u32 num_gpios;
|
||||
int irq, ret;
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->dev = dev;
|
||||
platform_set_drvdata(pdev, chip);
|
||||
spin_lock_init(&chip->lock);
|
||||
|
||||
chip->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(chip->base))
|
||||
return PTR_ERR(chip->base);
|
||||
|
||||
ret = bgpio_init(&chip->gc, dev, 4,
|
||||
chip->base + IPROC_GPIO_CCA_DIN,
|
||||
chip->base + IPROC_GPIO_CCA_DOUT,
|
||||
NULL,
|
||||
chip->base + IPROC_GPIO_CCA_OUT_EN,
|
||||
NULL,
|
||||
0);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to init GPIO chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
chip->gc.label = dev_name(dev);
|
||||
if (of_property_read_u32(dn, "ngpios", &num_gpios))
|
||||
chip->gc.ngpio = num_gpios;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq > 0) {
|
||||
struct gpio_irq_chip *girq;
|
||||
struct irq_chip *irqc;
|
||||
u32 val;
|
||||
|
||||
irqc = &chip->irqchip;
|
||||
irqc->name = dev_name(dev);
|
||||
irqc->irq_ack = iproc_gpio_irq_ack;
|
||||
irqc->irq_mask = iproc_gpio_irq_mask;
|
||||
irqc->irq_unmask = iproc_gpio_irq_unmask;
|
||||
irqc->irq_set_type = iproc_gpio_irq_set_type;
|
||||
|
||||
chip->intr = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(chip->intr))
|
||||
return PTR_ERR(chip->intr);
|
||||
|
||||
/* Enable GPIO interrupts for CCA GPIO */
|
||||
val = readl_relaxed(chip->intr + IPROC_CCA_INT_MASK);
|
||||
val |= IPROC_CCA_INT_F_GPIOINT;
|
||||
writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK);
|
||||
|
||||
/*
|
||||
* Directly request the irq here instead of passing
|
||||
* a flow-handler to gpiochip_set_chained_irqchip,
|
||||
* because the irq is shared.
|
||||
*/
|
||||
ret = devm_request_irq(dev, irq, iproc_gpio_irq_handler,
|
||||
IRQF_SHARED, chip->gc.label, &chip->gc);
|
||||
if (ret) {
|
||||
dev_err(dev, "Fail to request IRQ%d: %d\n", irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
girq = &chip->gc.irq;
|
||||
girq->chip = irqc;
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
girq->parent_handler = NULL;
|
||||
girq->num_parents = 0;
|
||||
girq->parents = NULL;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_simple_irq;
|
||||
}
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &chip->gc, chip);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to add GPIO chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit iproc_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct iproc_gpio_chip *chip;
|
||||
|
||||
chip = platform_get_drvdata(pdev);
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
|
||||
if (chip->intr) {
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(chip->intr + IPROC_CCA_INT_MASK);
|
||||
val &= ~IPROC_CCA_INT_F_GPIOINT;
|
||||
writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm_iproc_gpio_of_match[] = {
|
||||
{ .compatible = "brcm,iproc-gpio-cca" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm_iproc_gpio_of_match);
|
||||
|
||||
static struct platform_driver bcm_iproc_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "iproc-xgs-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = bcm_iproc_gpio_of_match,
|
||||
},
|
||||
.probe = iproc_gpio_probe,
|
||||
.remove = iproc_gpio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(bcm_iproc_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("XGS IPROC GPIO driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -83,7 +83,10 @@ static int xra1403_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !!(val & BIT(offset % 8));
|
||||
if (val & BIT(offset % 8))
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int xra1403_get(struct gpio_chip *chip, unsigned int offset)
|
||||
|
@ -72,7 +72,7 @@ static inline void disable_cp(unsigned long flags, unsigned long cpenable)
|
||||
|
||||
static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
return 1; /* input only */
|
||||
return GPIO_LINE_DIRECTION_IN; /* input only */
|
||||
}
|
||||
|
||||
static int xtensa_impwire_get_value(struct gpio_chip *gc, unsigned offset)
|
||||
@ -95,7 +95,7 @@ static void xtensa_impwire_set_value(struct gpio_chip *gc, unsigned offset,
|
||||
|
||||
static int xtensa_expstate_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
return 0; /* output only */
|
||||
return GPIO_LINE_DIRECTION_OUT; /* output only */
|
||||
}
|
||||
|
||||
static int xtensa_expstate_get_value(struct gpio_chip *gc, unsigned offset)
|
||||
|
@ -360,7 +360,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
|
||||
*
|
||||
* This function returns the direction of the specified GPIO.
|
||||
*
|
||||
* Return: 0 for output, 1 for input
|
||||
* Return: GPIO_LINE_DIRECTION_OUT or GPIO_LINE_DIRECTION_IN
|
||||
*/
|
||||
static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
|
||||
{
|
||||
@ -372,7 +372,10 @@ static int zynq_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
|
||||
|
||||
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
|
||||
|
||||
return !(reg & BIT(bank_pin_num));
|
||||
if (reg & BIT(bank_pin_num))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,12 +185,11 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
|
||||
|
||||
/**
|
||||
* devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
|
||||
* device's child node
|
||||
* devm_fwnode_gpiod_get_index - get a GPIO descriptor from a given node
|
||||
* @dev: GPIO consumer
|
||||
* @fwnode: firmware node containing GPIO reference
|
||||
* @con_id: function within the GPIO consumer
|
||||
* @index: index of the GPIO to obtain in the consumer
|
||||
* @child: firmware node (child of @dev)
|
||||
* @flags: GPIO initialization flags
|
||||
* @label: label to attach to the requested GPIO
|
||||
*
|
||||
@ -200,35 +199,21 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
|
||||
* On successful request the GPIO pin is configured in accordance with
|
||||
* provided @flags.
|
||||
*/
|
||||
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
|
||||
const char *con_id, int index,
|
||||
struct fwnode_handle *child,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
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);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
|
||||
if (con_id)
|
||||
snprintf(prop_name, sizeof(prop_name), "%s-%s",
|
||||
con_id, gpio_suffixes[i]);
|
||||
else
|
||||
snprintf(prop_name, sizeof(prop_name), "%s",
|
||||
gpio_suffixes[i]);
|
||||
|
||||
desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
|
||||
label);
|
||||
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
|
||||
break;
|
||||
}
|
||||
desc = fwnode_gpiod_get_index(fwnode, con_id, index, flags, label);
|
||||
if (IS_ERR(desc)) {
|
||||
devres_free(dr);
|
||||
return desc;
|
||||
@ -239,7 +224,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
|
||||
|
||||
return desc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child);
|
||||
EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index);
|
||||
|
||||
/**
|
||||
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
|
||||
|
@ -84,8 +84,9 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
|
||||
/**
|
||||
* of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs
|
||||
* to set the .valid_mask
|
||||
* @dev: the device for the GPIO provider
|
||||
* @return: true if the valid mask needs to be set
|
||||
* @gc: the target gpio_chip
|
||||
*
|
||||
* Return: true if the valid mask needs to be set
|
||||
*/
|
||||
bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
|
||||
{
|
||||
@ -884,16 +885,13 @@ int of_gpiochip_add(struct gpio_chip *chip)
|
||||
of_node_get(chip->of_node);
|
||||
|
||||
ret = of_gpiochip_scan_gpios(chip);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
of_node_put(chip->of_node);
|
||||
gpiochip_remove_pin_ranges(chip);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void of_gpiochip_remove(struct gpio_chip *chip)
|
||||
{
|
||||
gpiochip_remove_pin_ranges(chip);
|
||||
of_node_put(chip->of_node);
|
||||
}
|
||||
|
@ -1401,11 +1401,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
|
||||
|
||||
machine_gpiochip_add(chip);
|
||||
|
||||
ret = gpiochip_irqchip_init_hw(chip);
|
||||
ret = gpiochip_irqchip_init_valid_mask(chip);
|
||||
if (ret)
|
||||
goto err_remove_acpi_chip;
|
||||
|
||||
ret = gpiochip_irqchip_init_valid_mask(chip);
|
||||
ret = gpiochip_irqchip_init_hw(chip);
|
||||
if (ret)
|
||||
goto err_remove_acpi_chip;
|
||||
|
||||
@ -1438,6 +1438,7 @@ err_remove_of_chip:
|
||||
gpiochip_free_hogs(chip);
|
||||
of_gpiochip_remove(chip);
|
||||
err_free_gpiochip_mask:
|
||||
gpiochip_remove_pin_ranges(chip);
|
||||
gpiochip_free_valid_mask(chip);
|
||||
err_remove_from_list:
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
@ -1493,8 +1494,8 @@ void gpiochip_remove(struct gpio_chip *chip)
|
||||
gdev->chip = NULL;
|
||||
gpiochip_irqchip_remove(chip);
|
||||
acpi_gpiochip_remove(chip);
|
||||
gpiochip_remove_pin_ranges(chip);
|
||||
of_gpiochip_remove(chip);
|
||||
gpiochip_remove_pin_ranges(chip);
|
||||
gpiochip_free_valid_mask(chip);
|
||||
/*
|
||||
* We accept no more calls into the driver from this point, so
|
||||
@ -4349,6 +4350,54 @@ static int platform_gpio_count(struct device *dev, const char *con_id)
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* fwnode_gpiod_get_index - obtain a GPIO from firmware node
|
||||
* @fwnode: handle of the firmware node
|
||||
* @con_id: function within the GPIO consumer
|
||||
* @index: index of the GPIO to obtain for the consumer
|
||||
* @flags: GPIO initialization flags
|
||||
* @label: label to attach to the requested GPIO
|
||||
*
|
||||
* This function can be used for drivers that get their configuration
|
||||
* from opaque firmware.
|
||||
*
|
||||
* The function properly finds the corresponding GPIO using whatever is the
|
||||
* underlying firmware interface and then makes sure that the GPIO
|
||||
* descriptor is requested before it is returned to the caller.
|
||||
*
|
||||
* Returns:
|
||||
* On successful request the GPIO pin is configured in accordance with
|
||||
* provided @flags.
|
||||
*
|
||||
* In case of error an ERR_PTR() is returned.
|
||||
*/
|
||||
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
char prop_name[32]; /* 32 is max size of property name */
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
|
||||
if (con_id)
|
||||
snprintf(prop_name, sizeof(prop_name), "%s-%s",
|
||||
con_id, gpio_suffixes[i]);
|
||||
else
|
||||
snprintf(prop_name, sizeof(prop_name), "%s",
|
||||
gpio_suffixes[i]);
|
||||
|
||||
desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags,
|
||||
label);
|
||||
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
|
||||
break;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index);
|
||||
|
||||
/**
|
||||
* gpiod_count - return the number of GPIOs associated with a device / function
|
||||
* or -ENOENT if no GPIO has been assigned to the requested function
|
||||
|
@ -176,11 +176,15 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label);
|
||||
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
|
||||
const char *con_id, int index,
|
||||
struct fwnode_handle *child,
|
||||
enum gpiod_flags flags,
|
||||
const char *label);
|
||||
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label);
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
|
||||
struct fwnode_handle *child,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label);
|
||||
|
||||
#else /* CONFIG_GPIOLIB */
|
||||
|
||||
@ -531,6 +535,38 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id, int index,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
|
||||
struct fwnode_handle *fwnode,
|
||||
const char *con_id,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return devm_fwnode_gpiod_get_index(dev, fwnode, con_id, 0,
|
||||
flags, label);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
|
||||
const char *con_id, int index,
|
||||
@ -538,11 +574,10 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return devm_fwnode_gpiod_get_index(dev, child, con_id, index,
|
||||
flags, label);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_GPIOLIB */
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
|
||||
const char *con_id,
|
||||
@ -550,8 +585,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
|
||||
enum gpiod_flags flags,
|
||||
const char *label)
|
||||
{
|
||||
return devm_fwnode_get_index_gpiod_from_child(dev, con_id, 0, child,
|
||||
flags, label);
|
||||
return devm_fwnode_gpiod_get_index(dev, child, con_id, 0, flags, label);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
|
||||
|
@ -22,6 +22,9 @@ enum gpio_lookup_flags;
|
||||
|
||||
struct gpio_chip;
|
||||
|
||||
#define GPIO_LINE_DIRECTION_IN 1
|
||||
#define GPIO_LINE_DIRECTION_OUT 0
|
||||
|
||||
/**
|
||||
* struct gpio_irq_chip - GPIO interrupt controller
|
||||
*/
|
||||
|
@ -3,7 +3,11 @@ include ../scripts/Makefile.include
|
||||
|
||||
bindir ?= /usr/bin
|
||||
|
||||
ifeq ($(srctree),)
|
||||
# This will work when gpio is built in tools env. where srctree
|
||||
# isn't set and when invoked from selftests build, where srctree
|
||||
# is set to ".". building_out_of_srctree is undefined for in srctree
|
||||
# builds
|
||||
ifndef building_out_of_srctree
|
||||
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
|
||||
srctree := $(patsubst %/,%,$(dir $(srctree)))
|
||||
endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user