summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-12 17:24:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-12 17:24:29 -0700
commit1bc4a5be0acbd16de4df6e4fb73a76fa92e9a521 (patch)
tree207efb416a3704ef6b13cb9eb2cd0a001983876b /drivers
parentcf00c55e3d30b242d6f6530e61a7bc828124f0a3 (diff)
parent2760f7adbb6c4e39bd3ae733f56d4ac8fb5e3521 (diff)
downloadlinux-stable-1bc4a5be0acbd16de4df6e4fb73a76fa92e9a521.tar.gz
linux-stable-1bc4a5be0acbd16de4df6e4fb73a76fa92e9a521.tar.bz2
linux-stable-1bc4a5be0acbd16de4df6e4fb73a76fa92e9a521.zip
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6
Pull a few more GPIO bug fixes from Grant Likely: "Oops, missed a couple. Here's an updated pull req for GPIO" A set of PCH bug fixes, and one patch to fix up compile warnings * tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6: gpio/exynos: Fix compiler warnings when non-exynos machines are selected gpio: pch9: Use proper flow type handlers
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-pch.c57
-rw-r--r--drivers/gpio/gpio-samsung.c18
2 files changed, 40 insertions, 35 deletions
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index e8729cc2ba2b..2cd958e0b822 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-samsung.c b/drivers/gpio/gpio-samsung.c
index 19d6fc0229c3..e991d9171961 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);