summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-omap.c9
-rw-r--r--drivers/gpio/gpio-pch.c57
-rw-r--r--drivers/gpio/gpio-pxa.c116
-rw-r--r--drivers/gpio/gpio-samsung.c18
4 files changed, 141 insertions, 59 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 1adc2ec1e38..4461540653a 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -965,18 +965,15 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
}
_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv);
- _gpio_rmw(base, bank->regs->irqstatus, l,
- bank->regs->irqenable_inv == false);
- _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->debounce_en != 0);
- _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->ctrl != 0);
+ _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv);
if (bank->regs->debounce_en)
- _gpio_rmw(base, bank->regs->debounce_en, 0, 1);
+ __raw_writel(0, base + bank->regs->debounce_en);
/* Save OE default value (0xffffffff) in the context */
bank->context.oe = __raw_readl(bank->base + bank->regs->direction);
/* Initialize interface clk ungated, module enabled */
if (bank->regs->ctrl)
- _gpio_rmw(base, bank->regs->ctrl, 0, 1);
+ __raw_writel(0, base + bank->regs->ctrl);
}
static __devinit void
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index e8729cc2ba2..2cd958e0b82 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -230,16 +230,12 @@ static void pch_gpio_setup(struct pch_gpio *chip)
static int pch_irq_type(struct irq_data *d, unsigned int type)
{
- u32 im;
- u32 __iomem *im_reg;
- u32 ien;
- u32 im_pos;
- int ch;
- unsigned long flags;
- u32 val;
- int irq = d->irq;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct pch_gpio *chip = gc->private;
+ u32 im, im_pos, val;
+ u32 __iomem *im_reg;
+ unsigned long flags;
+ int ch, irq = d->irq;
ch = irq - chip->irq_base;
if (irq <= chip->irq_base + 7) {
@@ -270,30 +266,22 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
case IRQ_TYPE_LEVEL_LOW:
val = PCH_LEVEL_L;
break;
- case IRQ_TYPE_PROBE:
- goto end;
default:
- dev_warn(chip->dev, "%s: unknown type(%dd)",
- __func__, type);
- goto end;
+ goto unlock;
}
/* Set interrupt mode */
im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
iowrite32(im | (val << (im_pos * 4)), im_reg);
- /* iclr */
- iowrite32(BIT(ch), &chip->reg->iclr);
+ /* And the handler */
+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ __irq_set_handler_locked(d->irq, handle_level_irq);
+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
- /* IMASKCLR */
- iowrite32(BIT(ch), &chip->reg->imaskclr);
-
- /* Enable interrupt */
- ien = ioread32(&chip->reg->ien);
- iowrite32(ien | BIT(ch), &chip->reg->ien);
-end:
+unlock:
spin_unlock_irqrestore(&chip->spinlock, flags);
-
return 0;
}
@@ -313,18 +301,24 @@ static void pch_irq_mask(struct irq_data *d)
iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
}
+static void pch_irq_ack(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct pch_gpio *chip = gc->private;
+
+ iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->iclr);
+}
+
static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
{
struct pch_gpio *chip = dev_id;
u32 reg_val = ioread32(&chip->reg->istatus);
- int i;
- int ret = IRQ_NONE;
+ int i, ret = IRQ_NONE;
for (i = 0; i < gpio_pins[chip->ioh]; i++) {
if (reg_val & BIT(i)) {
dev_dbg(chip->dev, "%s:[%d]:irq=%d status=0x%x\n",
__func__, i, irq, reg_val);
- iowrite32(BIT(i), &chip->reg->iclr);
generic_handle_irq(chip->irq_base + i);
ret = IRQ_HANDLED;
}
@@ -343,6 +337,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
gc->private = chip;
ct = gc->chip_types;
+ ct->chip.irq_ack = pch_irq_ack;
ct->chip.irq_mask = pch_irq_mask;
ct->chip.irq_unmask = pch_irq_unmask;
ct->chip.irq_set_type = pch_irq_type;
@@ -357,6 +352,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
s32 ret;
struct pch_gpio *chip;
int irq_base;
+ u32 msk;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -408,8 +404,13 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
}
chip->irq_base = irq_base;
+ /* Mask all interrupts, but enable them */
+ msk = (1 << gpio_pins[chip->ioh]) - 1;
+ iowrite32(msk, &chip->reg->imask);
+ iowrite32(msk, &chip->reg->ien);
+
ret = request_irq(pdev->irq, pch_gpio_handler,
- IRQF_SHARED, KBUILD_MODNAME, chip);
+ IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
@@ -418,8 +419,6 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
- /* Initialize interrupt ien register */
- iowrite32(0, &chip->reg->ien);
end:
return 0;
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index fc3ace3fd4c..58a6a63a6ec 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -11,13 +11,17 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
#include <linux/slab.h>
@@ -56,6 +60,10 @@
int pxa_last_gpio;
+#ifdef CONFIG_OF
+static struct irq_domain *domain;
+#endif
+
struct pxa_gpio_chip {
struct gpio_chip chip;
void __iomem *regbase;
@@ -81,7 +89,6 @@ enum {
PXA3XX_GPIO,
PXA93X_GPIO,
MMP_GPIO = 0x10,
- MMP2_GPIO,
};
static DEFINE_SPINLOCK(gpio_lock);
@@ -475,22 +482,92 @@ static int pxa_gpio_nums(void)
gpio_type = MMP_GPIO;
} else if (cpu_is_mmp2()) {
count = 191;
- gpio_type = MMP2_GPIO;
+ gpio_type = MMP_GPIO;
}
#endif /* CONFIG_ARCH_MMP */
return count;
}
+static struct of_device_id pxa_gpio_dt_ids[] = {
+ { .compatible = "mrvl,pxa-gpio" },
+ { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO },
+ {}
+};
+
+static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ return 0;
+}
+
+const struct irq_domain_ops pxa_irq_domain_ops = {
+ .map = pxa_irq_domain_map,
+};
+
+#ifdef CONFIG_OF
+static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+{
+ int ret, nr_banks, nr_gpios, irq_base;
+ struct device_node *prev, *next, *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(pxa_gpio_dt_ids, &pdev->dev);
+
+ if (!of_id) {
+ dev_err(&pdev->dev, "Failed to find gpio controller\n");
+ return -EFAULT;
+ }
+ gpio_type = (int)of_id->data;
+
+ next = of_get_next_child(np, NULL);
+ prev = next;
+ if (!next) {
+ dev_err(&pdev->dev, "Failed to find child gpio node\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ for (nr_banks = 1; ; nr_banks++) {
+ next = of_get_next_child(np, prev);
+ if (!next)
+ break;
+ prev = next;
+ }
+ of_node_put(prev);
+ nr_gpios = nr_banks << 5;
+ pxa_last_gpio = nr_gpios - 1;
+
+ irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
+ if (irq_base < 0) {
+ dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
+ goto err;
+ }
+ domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,
+ &pxa_irq_domain_ops, NULL);
+ return 0;
+err:
+ iounmap(gpio_reg_base);
+ return ret;
+}
+#else
+#define pxa_gpio_probe_dt(pdev) (-1)
+#endif
+
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 gpio, irq, ret, use_of = 0;
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
- pxa_last_gpio = pxa_gpio_nums();
+ ret = pxa_gpio_probe_dt(pdev);
+ if (ret < 0)
+ pxa_last_gpio = pxa_gpio_nums();
+ else
+ use_of = 1;
if (!pxa_last_gpio)
return -EINVAL;
@@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
writel_relaxed(~0, c->regbase + ED_MASK_OFFSET);
}
+ if (!use_of) {
#ifdef CONFIG_ARCH_PXA
- irq = gpio_to_irq(0);
- irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
- handle_edge_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
- irq = gpio_to_irq(1);
- irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
- handle_edge_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
+ irq = gpio_to_irq(0);
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
- for (irq = gpio_to_irq(gpio_offset);
- irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+ irq = gpio_to_irq(1);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
+#endif
+
+ for (irq = gpio_to_irq(gpio_offset);
+ irq <= gpio_to_irq(pxa_last_gpio); irq++) {
+ irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+ handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
}
irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
@@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = {
.probe = pxa_gpio_probe,
.driver = {
.name = "pxa-gpio",
+ .of_match_table = pxa_gpio_dt_ids,
},
};
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 19d6fc0229c..e991d917196 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -452,12 +452,14 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
};
#endif
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
static struct samsung_gpio_cfg exynos_gpio_cfg = {
.set_pull = exynos_gpio_setpull,
.get_pull = exynos_gpio_getpull,
.set_config = samsung_gpio_setcfg_4bit,
.get_config = samsung_gpio_getcfg_4bit,
};
+#endif
#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
@@ -2123,8 +2125,8 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
* uses the above macro and depends on the banks being listed in order here.
*/
-static struct samsung_gpio_chip exynos4_gpios_1[] = {
#ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
{
.chip = {
.base = EXYNOS4_GPA0(0),
@@ -2222,11 +2224,11 @@ static struct samsung_gpio_chip exynos4_gpios_1[] = {
.label = "GPF3",
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos4_gpios_2[] = {
#ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
{
.chip = {
.base = EXYNOS4_GPJ0(0),
@@ -2367,11 +2369,11 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
.to_irq = samsung_gpiolib_to_irq,
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos4_gpios_3[] = {
#ifdef CONFIG_ARCH_EXYNOS4
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
{
.chip = {
.base = EXYNOS4_GPZ(0),
@@ -2379,8 +2381,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
.label = "GPZ",
},
},
-#endif
};
+#endif
#ifdef CONFIG_ARCH_EXYNOS5
static struct samsung_gpio_chip exynos5_gpios_1[] = {
@@ -2719,7 +2721,9 @@ static __init int samsung_gpiolib_init(void)
{
struct samsung_gpio_chip *chip;
int i, nr_chips;
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250)
void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
+#endif
int group = 0;
samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
@@ -2971,6 +2975,7 @@ static __init int samsung_gpiolib_init(void)
return 0;
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS5250)
err_ioremap4:
iounmap(gpio_base3);
err_ioremap3:
@@ -2979,6 +2984,7 @@ err_ioremap2:
iounmap(gpio_base1);
err_ioremap1:
return -ENOMEM;
+#endif
}
core_initcall(samsung_gpiolib_init);