summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bcma/driver_gpio.c3
-rw-r--r--drivers/gpio/Kconfig14
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-adnp.c155
-rw-r--r--drivers/gpio/gpio-bcm-kona.c2
-rw-r--r--drivers/gpio/gpio-crystalcove.c28
-rw-r--r--drivers/gpio/gpio-cs5535.c9
-rw-r--r--drivers/gpio/gpio-dwapb.c410
-rw-r--r--drivers/gpio/gpio-ks8695.c30
-rw-r--r--drivers/gpio/gpio-mcp23s08.c64
-rw-r--r--drivers/gpio/gpio-omap.c33
-rw-r--r--drivers/gpio/gpio-pca953x.c54
-rw-r--r--drivers/gpio/gpio-pch.c2
-rw-r--r--drivers/gpio/gpio-samsung.c50
-rw-r--r--drivers/gpio/gpio-stmpe.c99
-rw-r--r--drivers/gpio/gpio-stp-xway.c2
-rw-r--r--drivers/gpio/gpio-syscon.c94
-rw-r--r--drivers/gpio/gpio-tc3589x.c5
-rw-r--r--drivers/gpio/gpio-xgene.c244
-rw-r--r--drivers/gpio/gpio-xilinx.c27
-rw-r--r--drivers/gpio/gpio-zynq.c89
-rw-r--r--drivers/gpio/gpiolib-acpi.c30
-rw-r--r--drivers/gpio/gpiolib.c90
-rw-r--r--drivers/hid/hid-cp2112.c6
-rw-r--r--drivers/input/keyboard/adp5588-keys.c4
-rw-r--r--drivers/input/keyboard/adp5589-keys.c4
-rw-r--r--drivers/input/touchscreen/ad7879.c10
-rw-r--r--drivers/leds/leds-pca9532.c10
-rw-r--r--drivers/leds/leds-tca6507.c7
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c10
-rw-r--r--drivers/mfd/asic3.c3
-rw-r--r--drivers/mfd/htc-i2cpld.c8
-rw-r--r--drivers/mfd/sm501.c17
-rw-r--r--drivers/mfd/tc6393xb.c13
-rw-r--r--drivers/mfd/ucb1x00-core.c8
-rw-r--r--drivers/pinctrl/Kconfig2
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c16
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c8
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos5440.c6
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c15
-rw-r--r--drivers/pinctrl/sirf/pinctrl-sirf.c3
-rw-r--r--drivers/platform/x86/intel_pmic_gpio.c3
-rw-r--r--drivers/ssb/driver_gpio.c3
-rw-r--r--drivers/staging/vme/devices/vme_pio2_gpio.c4
-rw-r--r--drivers/tty/serial/max310x.c10
-rw-r--r--drivers/tty/serial/sc16is7xx.c13
-rw-r--r--drivers/video/fbdev/via/via-gpio.c10
48 files changed, 1110 insertions, 620 deletions
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 57ce5fe65364..706b9ae0dcfb 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -255,5 +255,6 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
int bcma_gpio_unregister(struct bcma_drv_cc *cc)
{
bcma_gpio_irq_domain_exit(cc);
- return gpiochip_remove(&cc->gpio);
+ gpiochip_remove(&cc->gpio);
+ return 0;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 9de1515e5808..0959ca9b6b27 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -136,7 +136,6 @@ config GPIO_DWAPB
tristate "Synopsys DesignWare APB GPIO driver"
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
- depends on OF_GPIO
help
Say Y or M here to build support for the Synopsys DesignWare APB
GPIO block.
@@ -334,6 +333,15 @@ config GPIO_TZ1090_PDC
help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
+config GPIO_XGENE
+ bool "APM X-Gene GPIO controller support"
+ depends on ARM64 && OF_GPIO
+ help
+ This driver is to support the GPIO block within the APM X-Gene SoC
+ platform's generic flash controller. The GPIO pins are muxed with
+ the generic flash controller's address and data pins. Say yes
+ here to enable the GFC GPIO functionality.
+
config GPIO_XILINX
bool "Xilinx GPIO support"
depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ
@@ -681,6 +689,7 @@ config GPIO_ADP5588_IRQ
config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
depends on I2C && OF_GPIO
+ select GPIOLIB_IRQCHIP
help
This option enables support for N GPIOs found on Avionic Design
I2C GPIO expanders. The register space will be extended by powers
@@ -796,7 +805,6 @@ config GPIO_MAX7301
config GPIO_MCP23S08
tristate "Microchip MCP23xxx I/O expander"
- depends on OF_GPIO
depends on (SPI_MASTER && !I2C) || I2C
help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
@@ -880,7 +888,7 @@ config GPIO_MSIC
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
- depends on OF_GPIO
+ depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
help
Turn on GPIO support for Broadcom "Kona" chips.
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 5d024e396622..e5d346cf3b6e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
+obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 416b2200d4f1..d3d0a90fe542 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -6,10 +6,9 @@
* published by the Free Software Foundation.
*/
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/seq_file.h>
@@ -27,8 +26,6 @@ struct adnp {
unsigned int reg_shift;
struct mutex i2c_lock;
-
- struct irq_domain *domain;
struct mutex irq_lock;
u8 *irq_enable;
@@ -253,6 +250,7 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
{
struct gpio_chip *chip = &adnp->gpio;
+ int err;
adnp->reg_shift = get_count_order(num_gpios) - 3;
@@ -272,6 +270,10 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
chip->of_node = chip->dev->of_node;
chip->owner = THIS_MODULE;
+ err = gpiochip_add(chip);
+ if (err)
+ return err;
+
return 0;
}
@@ -326,7 +328,8 @@ static irqreturn_t adnp_irq(int irq, void *data)
for_each_set_bit(bit, &pending, 8) {
unsigned int child_irq;
- child_irq = irq_find_mapping(adnp->domain, base + bit);
+ child_irq = irq_find_mapping(adnp->gpio.irqdomain,
+ base + bit);
handle_nested_irq(child_irq);
}
}
@@ -334,35 +337,32 @@ static irqreturn_t adnp_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct adnp *adnp = to_adnp(chip);
- return irq_create_mapping(adnp->domain, offset);
-}
-
-static void adnp_irq_mask(struct irq_data *data)
+static void adnp_irq_mask(struct irq_data *d)
{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
- unsigned int reg = data->hwirq >> adnp->reg_shift;
- unsigned int pos = data->hwirq & 7;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct adnp *adnp = to_adnp(gc);
+ unsigned int reg = d->hwirq >> adnp->reg_shift;
+ unsigned int pos = d->hwirq & 7;
adnp->irq_enable[reg] &= ~BIT(pos);
}
-static void adnp_irq_unmask(struct irq_data *data)
+static void adnp_irq_unmask(struct irq_data *d)
{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
- unsigned int reg = data->hwirq >> adnp->reg_shift;
- unsigned int pos = data->hwirq & 7;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct adnp *adnp = to_adnp(gc);
+ unsigned int reg = d->hwirq >> adnp->reg_shift;
+ unsigned int pos = d->hwirq & 7;
adnp->irq_enable[reg] |= BIT(pos);
}
-static int adnp_irq_set_type(struct irq_data *data, unsigned int type)
+static int adnp_irq_set_type(struct irq_data *d, unsigned int type)
{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
- unsigned int reg = data->hwirq >> adnp->reg_shift;
- unsigned int pos = data->hwirq & 7;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct adnp *adnp = to_adnp(gc);
+ unsigned int reg = d->hwirq >> adnp->reg_shift;
+ unsigned int pos = d->hwirq & 7;
if (type & IRQ_TYPE_EDGE_RISING)
adnp->irq_rise[reg] |= BIT(pos);
@@ -387,16 +387,18 @@ static int adnp_irq_set_type(struct irq_data *data, unsigned int type)
return 0;
}
-static void adnp_irq_bus_lock(struct irq_data *data)
+static void adnp_irq_bus_lock(struct irq_data *d)
{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct adnp *adnp = to_adnp(gc);
mutex_lock(&adnp->irq_lock);
}
-static void adnp_irq_bus_unlock(struct irq_data *data)
+static void adnp_irq_bus_unlock(struct irq_data *d)
{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct adnp *adnp = to_adnp(gc);
unsigned int num_regs = 1 << adnp->reg_shift, i;
mutex_lock(&adnp->i2c_lock);
@@ -408,26 +410,6 @@ static void adnp_irq_bus_unlock(struct irq_data *data)
mutex_unlock(&adnp->irq_lock);
}
-static int adnp_irq_reqres(struct irq_data *data)
-{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
-
- if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) {
- dev_err(adnp->gpio.dev,
- "unable to lock HW IRQ %lu for IRQ\n",
- data->hwirq);
- return -EINVAL;
- }
- return 0;
-}
-
-static void adnp_irq_relres(struct irq_data *data)
-{
- struct adnp *adnp = irq_data_get_irq_chip_data(data);
-
- gpio_unlock_as_irq(&adnp->gpio, data->hwirq);
-}
-
static struct irq_chip adnp_irq_chip = {
.name = "gpio-adnp",
.irq_mask = adnp_irq_mask,
@@ -435,29 +417,6 @@ static struct irq_chip adnp_irq_chip = {
.irq_set_type = adnp_irq_set_type,
.irq_bus_lock = adnp_irq_bus_lock,
.irq_bus_sync_unlock = adnp_irq_bus_unlock,
- .irq_request_resources = adnp_irq_reqres,
- .irq_release_resources = adnp_irq_relres,
-};
-
-static int adnp_irq_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_data(irq, domain->host_data);
- irq_set_chip(irq, &adnp_irq_chip);
- irq_set_nested_thread(irq, true);
-
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
-
- return 0;
-}
-
-static const struct irq_domain_ops adnp_irq_domain_ops = {
- .map = adnp_irq_map,
- .xlate = irq_domain_xlate_twocell,
};
static int adnp_irq_setup(struct adnp *adnp)
@@ -503,35 +462,28 @@ static int adnp_irq_setup(struct adnp *adnp)
adnp->irq_enable[i] = 0x00;
}
- adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio,
- &adnp_irq_domain_ops, adnp);
-
- err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- dev_name(chip->dev), adnp);
+ err = devm_request_threaded_irq(chip->dev, adnp->client->irq,
+ NULL, adnp_irq,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ dev_name(chip->dev), adnp);
if (err != 0) {
dev_err(chip->dev, "can't request IRQ#%d: %d\n",
adnp->client->irq, err);
return err;
}
- chip->to_irq = adnp_gpio_to_irq;
- return 0;
-}
-
-static void adnp_irq_teardown(struct adnp *adnp)
-{
- unsigned int irq, i;
-
- free_irq(adnp->client->irq, adnp);
-
- for (i = 0; i < adnp->gpio.ngpio; i++) {
- irq = irq_find_mapping(adnp->domain, i);
- if (irq > 0)
- irq_dispose_mapping(irq);
+ err = gpiochip_irqchip_add(chip,
+ &adnp_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (err) {
+ dev_err(chip->dev,
+ "could not connect irqchip to gpiochip\n");
+ return err;
}
- irq_domain_remove(adnp->domain);
+ return 0;
}
static int adnp_i2c_probe(struct i2c_client *client,
@@ -558,38 +510,25 @@ static int adnp_i2c_probe(struct i2c_client *client,
adnp->client = client;
err = adnp_gpio_setup(adnp, num_gpios);
- if (err < 0)
+ if (err)
return err;
if (of_find_property(np, "interrupt-controller", NULL)) {
err = adnp_irq_setup(adnp);
- if (err < 0)
- goto teardown;
+ if (err)
+ return err;
}
- err = gpiochip_add(&adnp->gpio);
- if (err < 0)
- goto teardown;
-
i2c_set_clientdata(client, adnp);
- return 0;
-teardown:
- if (of_find_property(np, "interrupt-controller", NULL))
- adnp_irq_teardown(adnp);
-
- return err;
+ return 0;
}
static int adnp_i2c_remove(struct i2c_client *client)
{
struct adnp *adnp = i2c_get_clientdata(client);
- struct device_node *np = client->dev.of_node;
gpiochip_remove(&adnp->gpio);
- if (of_find_property(np, "interrupt-controller", NULL))
- adnp_irq_teardown(adnp);
-
return 0;
}
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 3f6b33ce9bd4..de0801e9767a 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -496,7 +496,7 @@ static struct irq_chip bcm_gpio_irq_chip = {
.irq_release_resources = bcm_kona_gpio_irq_relres,
};
-static struct __initconst of_device_id bcm_kona_gpio_of_match[] = {
+static struct of_device_id const bcm_kona_gpio_of_match[] = {
{ .compatible = "brcm,kona-gpio" },
{}
};
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
index 934462f5bd22..bbfe7f508502 100644
--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -24,6 +24,7 @@
#include <linux/mfd/intel_soc_pmic.h>
#define CRYSTALCOVE_GPIO_NUM 16
+#define CRYSTALCOVE_VGPIO_NUM 94
#define UPDATE_IRQ_TYPE BIT(0)
#define UPDATE_IRQ_MASK BIT(1)
@@ -130,6 +131,9 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
{
struct crystalcove_gpio *cg = to_cg(chip);
+ if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ return 0;
+
return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_INPUT_SET);
}
@@ -139,6 +143,9 @@ static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
{
struct crystalcove_gpio *cg = to_cg(chip);
+ if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ return 0;
+
return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_OUTPUT_SET | value);
}
@@ -149,6 +156,9 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
int ret;
unsigned int val;
+ if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ return 0;
+
ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
if (ret)
return ret;
@@ -161,6 +171,9 @@ static void crystalcove_gpio_set(struct gpio_chip *chip,
{
struct crystalcove_gpio *cg = to_cg(chip);
+ if (gpio > CRYSTALCOVE_VGPIO_NUM)
+ return;
+
if (value)
regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
else
@@ -256,7 +269,7 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
pending = p0 | p1 << 8;
- for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) {
if (pending & BIT(gpio)) {
virq = irq_find_mapping(cg->chip.irqdomain, gpio);
generic_handle_irq(virq);
@@ -273,7 +286,7 @@ static void crystalcove_gpio_dbg_show(struct seq_file *s,
int gpio, offset;
unsigned int ctlo, ctli, mirqs0, mirqsx, irq;
- for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) {
regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli);
regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0,
@@ -320,7 +333,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
cg->chip.get = crystalcove_gpio_get;
cg->chip.set = crystalcove_gpio_set;
cg->chip.base = -1;
- cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM;
+ cg->chip.ngpio = CRYSTALCOVE_VGPIO_NUM;
cg->chip.can_sleep = true;
cg->chip.dev = dev;
cg->chip.dbg_show = crystalcove_gpio_dbg_show;
@@ -346,7 +359,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
return 0;
out_remove_gpio:
- WARN_ON(gpiochip_remove(&cg->chip));
+ gpiochip_remove(&cg->chip);
return retval;
}
@@ -354,14 +367,11 @@ static int crystalcove_gpio_remove(struct platform_device *pdev)
{
struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
- int err;
-
- err = gpiochip_remove(&cg->chip);
+ gpiochip_remove(&cg->chip);
if (irq >= 0)
free_irq(irq, cg);
-
- return err;
+ return 0;
}
static struct platform_driver crystalcove_gpio_driver = {
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index 92ec58fa9236..668127fe90ef 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -201,7 +201,8 @@ EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event);
static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
{
- struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+ struct cs5535_gpio_chip *chip =
+ container_of(c, struct cs5535_gpio_chip, chip);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -241,7 +242,8 @@ static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
static int chip_direction_input(struct gpio_chip *c, unsigned offset)
{
- struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+ struct cs5535_gpio_chip *chip =
+ container_of(c, struct cs5535_gpio_chip, chip);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -254,7 +256,8 @@ static int chip_direction_input(struct gpio_chip *c, unsigned offset)
static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
{
- struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
+ struct cs5535_gpio_chip *chip =
+ container_of(c, struct cs5535_gpio_chip, chip);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index d6618a6e2399..b43cd84b61f1 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -21,6 +21,8 @@
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
+#include <linux/platform_data/gpio-dwapb.h>
+#include <linux/slab.h>
#define GPIO_SWPORTA_DR 0x00
#define GPIO_SWPORTA_DDR 0x04
@@ -35,6 +37,7 @@
#define GPIO_INTTYPE_LEVEL 0x38
#define GPIO_INT_POLARITY 0x3c
#define GPIO_INTSTATUS 0x40
+#define GPIO_PORTA_DEBOUNCE 0x48
#define GPIO_PORTA_EOI 0x4c
#define GPIO_EXT_PORTA 0x50
#define GPIO_EXT_PORTB 0x54
@@ -48,10 +51,28 @@
struct dwapb_gpio;
+#ifdef CONFIG_PM_SLEEP
+/* Store GPIO context across system-wide suspend/resume transitions */
+struct dwapb_context {
+ u32 data;
+ u32 dir;
+ u32 ext;
+ u32 int_en;
+ u32 int_mask;
+ u32 int_type;
+ u32 int_pol;
+ u32 int_deb;
+};
+#endif
+
struct dwapb_gpio_port {
struct bgpio_chip bgc;
bool is_registered;
struct dwapb_gpio *gpio;
+#ifdef CONFIG_PM_SLEEP
+ struct dwapb_context *ctx;
+#endif
+ unsigned int idx;
};
struct dwapb_gpio {
@@ -62,11 +83,33 @@ struct dwapb_gpio {
struct irq_domain *domain;
};
+static inline struct dwapb_gpio_port *
+to_dwapb_gpio_port(struct bgpio_chip *bgc)
+{
+ return container_of(bgc, struct dwapb_gpio_port, bgc);
+}
+
+static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset)
+{
+ struct bgpio_chip *bgc = &gpio->ports[0].bgc;
+ void __iomem *reg_base = gpio->regs;
+
+ return bgc->read_reg(reg_base + offset);
+}
+
+static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
+ u32 val)
+{
+ struct bgpio_chip *bgc = &gpio->ports[0].bgc;
+ void __iomem *reg_base = gpio->regs;
+
+ bgc->write_reg(reg_base + offset, val);
+}
+
static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
- struct dwapb_gpio_port *port = container_of(bgc, struct
- dwapb_gpio_port, bgc);
+ struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc);
struct dwapb_gpio *gpio = port->gpio;
return irq_find_mapping(gpio->domain, offset);
@@ -74,21 +117,20 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
{
- u32 v = readl(gpio->regs + GPIO_INT_POLARITY);
+ u32 v = dwapb_read(gpio, GPIO_INT_POLARITY);
if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs))
v &= ~BIT(offs);
else
v |= BIT(offs);
- writel(v, gpio->regs + GPIO_INT_POLARITY);
+ dwapb_write(gpio, GPIO_INT_POLARITY, v);
}
-static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
+static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
{
- struct dwapb_gpio *gpio = irq_get_handler_data(irq);
- struct irq_chip *chip = irq_desc_get_chip(desc);
u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS);
+ u32 ret = irq_status;
while (irq_status) {
int hwirq = fls(irq_status) - 1;
@@ -102,6 +144,16 @@ static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
dwapb_toggle_trigger(gpio, hwirq);
}
+ return ret;
+}
+
+static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ struct dwapb_gpio *gpio = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ dwapb_do_irq(gpio);
+
if (chip->irq_eoi)
chip->irq_eoi(irq_desc_get_irq_data(desc));
}
@@ -115,9 +167,9 @@ static void dwapb_irq_enable(struct irq_data *d)
u32 val;
spin_lock_irqsave(&bgc->lock, flags);
- val = readl(gpio->regs + GPIO_INTEN);
+ val = dwapb_read(gpio, GPIO_INTEN);
val |= BIT(d->hwirq);
- writel(val, gpio->regs + GPIO_INTEN);
+ dwapb_write(gpio, GPIO_INTEN, val);
spin_unlock_irqrestore(&bgc->lock, flags);
}
@@ -130,9 +182,9 @@ static void dwapb_irq_disable(struct irq_data *d)
u32 val;
spin_lock_irqsave(&bgc->lock, flags);
- val = readl(gpio->regs + GPIO_INTEN);
+ val = dwapb_read(gpio, GPIO_INTEN);
val &= ~BIT(d->hwirq);
- writel(val, gpio->regs + GPIO_INTEN);
+ dwapb_write(gpio, GPIO_INTEN, val);
spin_unlock_irqrestore(&bgc->lock, flags);
}
@@ -172,8 +224,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
return -EINVAL;
spin_lock_irqsave(&bgc->lock, flags);
- level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
- polarity = readl(gpio->regs + GPIO_INT_POLARITY);
+ level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL);
+ polarity = dwapb_read(gpio, GPIO_INT_POLARITY);
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
@@ -200,29 +252,55 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
irq_setup_alt_chip(d, type);
- writel(level, gpio->regs + GPIO_INTTYPE_LEVEL);
- writel(polarity, gpio->regs + GPIO_INT_POLARITY);
+ dwapb_write(gpio, GPIO_INTTYPE_LEVEL, level);
+ dwapb_write(gpio, GPIO_INT_POLARITY, polarity);
+ spin_unlock_irqrestore(&bgc->lock, flags);
+
+ return 0;
+}
+
+static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
+ unsigned offset, unsigned debounce)
+{
+ struct bgpio_chip *bgc = to_bgpio_chip(gc);
+ struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc);
+ struct dwapb_gpio *gpio = port->gpio;
+ unsigned long flags, val_deb;
+ unsigned long mask = bgc->pin2mask(bgc, offset);
+
+ spin_lock_irqsave(&bgc->lock, flags);
+
+ val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE);
+ if (debounce)
+ dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb | mask);
+ else
+ dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb & ~mask);
+
spin_unlock_irqrestore(&bgc->lock, flags);
return 0;
}