summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig2
-rw-r--r--drivers/gpio/gpio-adp5588.c2
-rw-r--r--drivers/gpio/gpio-pxa.c21
-rw-r--r--drivers/gpio/gpio-samsung.c16
-rw-r--r--drivers/gpio/gpio-sodaville.c23
-rw-r--r--drivers/gpio/gpio-tegra.c59
-rw-r--r--drivers/gpio/gpiolib-of.c2
7 files changed, 84 insertions, 41 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1042c3f..7875c3f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -435,7 +435,7 @@ config GPIO_ML_IOH
config GPIO_SODAVILLE
bool "Intel Sodaville GPIO support"
- depends on X86 && PCI && OF && BROKEN
+ depends on X86 && PCI && OF
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
help
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index 9ad1703..ae5d7f1 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -252,7 +252,7 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid)
if (ret < 0)
memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
- for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
+ for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
bank++, bit = 0) {
pending = dev->irq_stat[bank] & dev->irq_mask[bank];
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 5689ce6..fc3ace3 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -64,6 +64,7 @@ struct pxa_gpio_chip {
unsigned long irq_mask;
unsigned long irq_edge_rise;
unsigned long irq_edge_fall;
+ int (*set_wake)(unsigned int gpio, unsigned int on);
#ifdef CONFIG_PM
unsigned long saved_gplr;
@@ -269,7 +270,8 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
(value ? GPSR_OFFSET : GPCR_OFFSET));
}
-static int __devinit pxa_init_gpio_chip(int gpio_end)
+static int __devinit pxa_init_gpio_chip(int gpio_end,
+ int (*set_wake)(unsigned int, unsigned int))
{
int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
struct pxa_gpio_chip *chips;
@@ -285,6 +287,7 @@ static int __devinit pxa_init_gpio_chip(int gpio_end)
sprintf(chips[i].label, "gpio-%d", i);
chips[i].regbase = gpio_reg_base + BANK_OFF(i);
+ chips[i].set_wake = set_wake;
c->base = gpio;
c->label = chips[i].label;
@@ -412,6 +415,17 @@ static void pxa_mask_muxed_gpio(struct irq_data *d)
writel_relaxed(gfer, c->regbase + GFER_OFFSET);
}
+static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
+{
+ int gpio = pxa_irq_to_gpio(d->irq);
+ struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+ if (c->set_wake)
+ return c->set_wake(gpio, on);
+ else
+ return 0;
+}
+
static void pxa_unmask_muxed_gpio(struct irq_data *d)
{
int gpio = pxa_irq_to_gpio(d->irq);
@@ -427,6 +441,7 @@ static struct irq_chip pxa_muxed_gpio_chip = {
.irq_mask = pxa_mask_muxed_gpio,
.irq_unmask = pxa_unmask_muxed_gpio,
.irq_set_type = pxa_gpio_irq_type,
+ .irq_set_wake = pxa_gpio_set_wake,
};
static int pxa_gpio_nums(void)
@@ -471,6 +486,7 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
struct pxa_gpio_chip *c;
struct resource *res;
struct clk *clk;
+ struct pxa_gpio_platform_data *info;
int gpio, irq, ret;
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
@@ -516,7 +532,8 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
}
/* Initialize GPIO chips */
- pxa_init_gpio_chip(pxa_last_gpio);
+ info = dev_get_platdata(&pdev->dev);
+ pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL);
/* clear all GPIO edge detects */
for_each_gpio_chip(gpio, c) {
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 4627787..19d6fc0 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2382,8 +2382,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
#endif
};
-static struct samsung_gpio_chip exynos5_gpios_1[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_1[] = {
{
.chip = {
.base = EXYNOS5_GPA0(0),
@@ -2541,11 +2541,11 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {
.to_irq = samsung_gpiolib_to_irq,
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_2[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_2[] = {
{
.chip = {
.base = EXYNOS5_GPE0(0),
@@ -2602,11 +2602,11 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = {
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_3[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_3[] = {
{
.chip = {
.base = EXYNOS5_GPV0(0),
@@ -2638,11 +2638,11 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = {
.label = "GPV4",
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_4[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_4[] = {
{
.chip = {
.base = EXYNOS5_GPZ(0),
@@ -2650,8 +2650,8 @@ static struct samsung_gpio_chip exynos5_gpios_4[] = {
.label = "GPZ",
},
},
-#endif
};
+#endif
#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index e20dc73..820209c 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -41,7 +41,7 @@
struct sdv_gpio_chip_data {
int irq_base;
void __iomem *gpio_pub_base;
- struct irq_domain id;
+ struct irq_domain *id;
struct irq_chip_generic *gc;
struct bgpio_chip bgpio;
};
@@ -51,10 +51,9 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct sdv_gpio_chip_data *sd = gc->private;
void __iomem *type_reg;
- u32 irq_offs = d->irq - sd->irq_base;
u32 reg;
- if (irq_offs < 8)
+ if (d->hwirq < 8)
type_reg = sd->gpio_pub_base + GPIT1R0;
else
type_reg = sd->gpio_pub_base + GPIT1R1;
@@ -63,11 +62,11 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
- reg &= ~BIT(4 * (irq_offs % 8));
+ reg &= ~BIT(4 * (d->hwirq % 8));
break;
case IRQ_TYPE_LEVEL_LOW:
- reg |= BIT(4 * (irq_offs % 8));
+ reg |= BIT(4 * (d->hwirq % 8));
break;
default:
@@ -91,7 +90,7 @@ static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
u32 irq_bit = __fls(irq_stat);
irq_stat &= ~BIT(irq_bit);
- generic_handle_irq(sd->irq_base + irq_bit);
+ generic_handle_irq(irq_find_mapping(sd->id, irq_bit));
}
return IRQ_HANDLED;
@@ -127,7 +126,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
}
static struct irq_domain_ops irq_domain_sdv_ops = {
- .dt_translate = sdv_xlate,
+ .xlate = sdv_xlate,
};
static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
@@ -149,10 +148,6 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
if (ret)
goto out_free_desc;
- sd->id.irq_base = sd->irq_base;
- sd->id.of_node = of_node_get(pdev->dev.of_node);
- sd->id.ops = &irq_domain_sdv_ops;
-
/*
* This gpio irq controller latches level irqs. Testing shows that if
* we unmask & ACK the IRQ before the source of the interrupt is gone
@@ -179,7 +174,10 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST,
IRQ_LEVEL | IRQ_NOPROBE);
- irq_domain_add(&sd->id);
+ sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
+ sd->irq_base, 0, &irq_domain_sdv_ops, sd);
+ if (!sd->id)
+ goto out_free_irq;
return 0;
out_free_irq:
free_irq(pdev->irq, sd);
@@ -260,7 +258,6 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
{
struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
- irq_domain_del(&sd->id);
free_irq(pdev->irq, sd);
irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 32de670..12f349b3 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -22,7 +22,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
@@ -37,7 +37,8 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
+#define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \
+ GPIO_PORT(x) * 4)
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
@@ -48,12 +49,12 @@
#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
-#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800)
-#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810)
-#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820)
-#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840)
-#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850)
-#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860)
+#define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00)
+#define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10)
+#define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20)
+#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40)
+#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50)
+#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60)
#define GPIO_INT_LVL_MASK 0x010101
#define GPIO_INT_LVL_EDGE_RISING 0x000101
@@ -78,6 +79,8 @@ struct tegra_gpio_bank {
static struct irq_domain *irq_domain;
static void __iomem *regs;
static u32 tegra_gpio_bank_count;
+static u32 tegra_gpio_bank_stride;
+static u32 tegra_gpio_upper_offset;
static struct tegra_gpio_bank *tegra_gpio_banks;
static inline void tegra_gpio_writel(u32 val, u32 reg)
@@ -333,6 +336,26 @@ static struct irq_chip tegra_gpio_irq_chip = {
#endif
};
+struct tegra_gpio_soc_config {
+ u32 bank_stride;
+ u32 upper_offset;
+};
+
+static struct tegra_gpio_soc_config tegra20_gpio_config = {
+ .bank_stride = 0x80,
+ .upper_offset = 0x800,
+};
+
+static struct tegra_gpio_soc_config tegra30_gpio_config = {
+ .bank_stride = 0x100,
+ .upper_offset = 0x80,
+};
+
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
+ { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
+ { },
+};
/* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
@@ -341,6 +364,8 @@ static struct lock_class_key gpio_lock_class;
static int __devinit tegra_gpio_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
+ struct tegra_gpio_soc_config *config;
int irq_base;
struct resource *res;
struct tegra_gpio_bank *bank;
@@ -348,6 +373,15 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
int i;
int j;
+ match = of_match_device(tegra_gpio_of_match, &pdev->dev);
+ if (match)
+ config = (struct tegra_gpio_soc_config *)match->data;
+ else
+ config = &tegra20_gpio_config;
+
+ tegra_gpio_bank_stride = config->bank_stride;
+ tegra_gpio_upper_offset = config->upper_offset;
+
for (;;) {
res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count);
if (!res)
@@ -402,7 +436,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
@@ -441,11 +475,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
return 0;
}
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
- { .compatible = "nvidia,tegra20-gpio", },
- { },
-};
-
static struct platform_driver tegra_gpio_driver = {
.driver = {
.name = "tegra-gpio",
@@ -485,7 +514,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
int i;
int j;
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
seq_printf(s,
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index bba8121..bf984b6 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -140,7 +140,7 @@ int of_gpio_simple_xlate(struct gpio_chip *gc,
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
- if (gpiospec->args[0] > gc->ngpio)
+ if (gpiospec->args[0] >= gc->ngpio)
return -EINVAL;
if (flags)
OpenPOWER on IntegriCloud