From b2888095feb3c651cba5904b0227622e82777b34 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 9 Dec 2011 16:56:08 -0600 Subject: gpio: pl061: drop extra check for NULL platform_data In adding DT binding support, the check for NULL platform_data got added back in inadvertently, so remove it. Signed-off-by: Rob Herring Signed-off-by: Grant Likely --- drivers/gpio/gpio-pl061.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpio/gpio-pl061.c') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 093c90bd3c1d..4102f63230fd 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -238,10 +238,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) int ret, irq, i; static DECLARE_BITMAP(init_irq, NR_IRQS); - pdata = dev->dev.platform_data; - if (pdata == NULL) - return -ENODEV; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; -- cgit v1.2.1 From dece904d74800d109f1bb06b55758169b1bcc140 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 9 Dec 2011 14:12:53 -0600 Subject: gpio: pl061: use chained_irq_* functions in irq handler Use chained_irq_enter/exit helper functions instead of direct pointer accesses. This is needed for generic irq chip conversion. Signed-off-by: Rob Herring Acked-by: Grant Likely Cc: Linus Walleij --- drivers/gpio/gpio-pl061.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpio/gpio-pl061.c') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 4102f63230fd..0f718f9bbd8c 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -23,6 +23,7 @@ #include #include #include +#include #define GPIODIR 0x400 #define GPIOIS 0x404 @@ -211,8 +212,9 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) struct list_head *chip_list = irq_get_handler_data(irq); struct list_head *ptr; struct pl061_gpio *chip; + struct irq_chip *irqchip = irq_desc_get_chip(desc); - desc->irq_data.chip->irq_ack(&desc->irq_data); + chained_irq_enter(irqchip, desc); list_for_each(ptr, chip_list) { unsigned long pending; int offset; @@ -227,7 +229,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) for_each_set_bit(offset, &pending, PL061_GPIO_NR) generic_handle_irq(pl061_to_irq(&chip->gc, offset)); } - desc->irq_data.chip->irq_unmask(&desc->irq_data); + chained_irq_exit(irqchip, desc); } static int pl061_probe(struct amba_device *dev, const struct amba_id *id) -- cgit v1.2.1 From f2ab2ba09e081fbce068c0adc205ad3f25a3b626 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 9 Dec 2011 14:11:41 -0600 Subject: gpio: pl061: convert to use 0 for no irq We don't want drivers using NO_IRQ, so remove its use. For now, 0 or -1 means no irq until platforms are converted to use 0. Signed-off-by: Rob Herring Acked-by: Grant Likely Cc: Linus Walleij --- drivers/gpio/gpio-pl061.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpio/gpio-pl061.c') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 0f718f9bbd8c..fe19dec4b117 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -53,7 +53,7 @@ struct pl061_gpio { spinlock_t irq_lock; /* IRQ registers */ void __iomem *base; - unsigned irq_base; + int irq_base; struct gpio_chip gc; }; @@ -119,7 +119,7 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) { struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - if (chip->irq_base == NO_IRQ) + if (chip->irq_base <= 0) return -EINVAL; return chip->irq_base + offset; @@ -250,7 +250,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) chip->irq_base = pdata->irq_base; } else if (dev->dev.of_node) { chip->gc.base = -1; - chip->irq_base = NO_IRQ; + chip->irq_base = 0; } else { ret = -ENODEV; goto free_mem; @@ -290,7 +290,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) * irq_chip support */ - if (chip->irq_base == NO_IRQ) + if (chip->irq_base <= 0) return 0; writeb(0, chip->base + GPIOIE); /* disable irqs */ -- cgit v1.2.1 From 3ab52475447641a6facf6ee5450bea24e477b811 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 21 Oct 2011 08:05:53 -0500 Subject: gpio: pl061: convert to use generic irq chip Convert the pl061 irq_chip code to use the generic irq chip code. This has the side effect of using 32-bit accesses rather than 8-bit accesses to interrupt registers. The h/w TRM and testing seem to indicate this is fine. Signed-off-by: Rob Herring Acked-by: Grant Likely Acked-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 74 +++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 48 deletions(-) (limited to 'drivers/gpio/gpio-pl061.c') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index fe19dec4b117..96ff6b28e9ad 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -50,10 +50,10 @@ struct pl061_gpio { * the IRQ code simpler. */ spinlock_t lock; /* GPIO registers */ - spinlock_t irq_lock; /* IRQ registers */ void __iomem *base; int irq_base; + struct irq_chip_generic *irq_gc; struct gpio_chip gc; }; @@ -125,40 +125,10 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) return chip->irq_base + offset; } -/* - * PL061 GPIO IRQ - */ -static void pl061_irq_disable(struct irq_data *d) -{ - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); - int offset = d->irq - chip->irq_base; - unsigned long flags; - u8 gpioie; - - spin_lock_irqsave(&chip->irq_lock, flags); - gpioie = readb(chip->base + GPIOIE); - gpioie &= ~(1 << offset); - writeb(gpioie, chip->base + GPIOIE); - spin_unlock_irqrestore(&chip->irq_lock, flags); -} - -static void pl061_irq_enable(struct irq_data *d) -{ - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); - int offset = d->irq - chip->irq_base; - unsigned long flags; - u8 gpioie; - - spin_lock_irqsave(&chip->irq_lock, flags); - gpioie = readb(chip->base + GPIOIE); - gpioie |= 1 << offset; - writeb(gpioie, chip->base + GPIOIE); - spin_unlock_irqrestore(&chip->irq_lock, flags); -} - static int pl061_irq_type(struct irq_data *d, unsigned trigger) { - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct pl061_gpio *chip = gc->private; int offset = d->irq - chip->irq_base; unsigned long flags; u8 gpiois, gpioibe, gpioiev; @@ -166,7 +136,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) if (offset < 0 || offset >= PL061_GPIO_NR) return -EINVAL; - spin_lock_irqsave(&chip->irq_lock, flags); + raw_spin_lock_irqsave(&gc->lock, flags); gpioiev = readb(chip->base + GPIOIEV); @@ -195,18 +165,11 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) writeb(gpioiev, chip->base + GPIOIEV); - spin_unlock_irqrestore(&chip->irq_lock, flags); + raw_spin_unlock_irqrestore(&gc->lock, flags); return 0; } -static struct irq_chip pl061_irqchip = { - .name = "GPIO", - .irq_enable = pl061_irq_enable, - .irq_disable = pl061_irq_disable, - .irq_set_type = pl061_irq_type, -}; - static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) { struct list_head *chip_list = irq_get_handler_data(irq); @@ -232,6 +195,25 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) chained_irq_exit(irqchip, desc); } +static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) +{ + struct irq_chip_type *ct; + + chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, + chip->base, handle_simple_irq); + chip->irq_gc->private = chip; + + ct = chip->irq_gc->chip_types; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = pl061_irq_type; + ct->chip.irq_set_wake = irq_gc_set_wake; + ct->regs.mask = GPIOIE; + + irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), + IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); +} + static int pl061_probe(struct amba_device *dev, const struct amba_id *id) { struct pl061_platform_data *pdata; @@ -269,7 +251,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) } spin_lock_init(&chip->lock); - spin_lock_init(&chip->irq_lock); INIT_LIST_HEAD(&chip->list); chip->gc.direction_input = pl061_direction_input; @@ -293,6 +274,8 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) if (chip->irq_base <= 0) return 0; + pl061_init_gc(chip, chip->irq_base); + writeb(0, chip->base + GPIOIE); /* disable irqs */ irq = dev->irq[0]; if (irq < 0) { @@ -321,11 +304,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) else pl061_direction_input(&chip->gc, i); } - - irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, - handle_simple_irq); - set_irq_flags(i+chip->irq_base, IRQF_VALID); - irq_set_chip_data(i + chip->irq_base, chip); } return 0; -- cgit v1.2.1 From 2de0dbc5f6830e7659083d1929f57cb88b16a3b6 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 4 Jan 2012 10:36:07 -0600 Subject: gpio: pl061: remove combined interrupt Drivers should not have a dependency on NR_IRQS. Doing so may break with SPARSE_IRQ enabled. As there are no in kernel users of the pl061 which have multiple instances with their interrupts combined to a single parent interrupt, remove this functionality. If this capability is needed later, it could be supported more cleanly by just using a devicetree property. Signed-off-by: Rob Herring Reviewed-by: Viresh Kumar Cc: Rajeev Kumar Acked-by: Baruch Siach Cc: Linus Walleij Cc: Grant Likely --- drivers/gpio/gpio-pl061.c | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) (limited to 'drivers/gpio/gpio-pl061.c') diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 96ff6b28e9ad..23065f6b3de1 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -37,13 +36,6 @@ #define PL061_GPIO_NR 8 struct pl061_gpio { - /* We use a list of pl061_gpio structs for each trigger IRQ in the main - * interrupts controller of the system. We need this to support systems - * in which more that one PL061s are connected to the same IRQ. The ISR - * interates through this list to find the source of the interrupt. - */ - struct list_head list; - /* Each of the two spinlocks protects a different set of hardware * regiters and data structurs. This decouples the code of the IRQ from * the GPIO code. This also makes the case of a GPIO routine call from @@ -172,26 +164,20 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) { - struct list_head *chip_list = irq_get_handler_data(irq); - struct list_head *ptr; - struct pl061_gpio *chip; + unsigned long pending; + int offset; + struct pl061_gpio *chip = irq_desc_get_handler_data(desc); struct irq_chip *irqchip = irq_desc_get_chip(desc); chained_irq_enter(irqchip, desc); - list_for_each(ptr, chip_list) { - unsigned long pending; - int offset; - - chip = list_entry(ptr, struct pl061_gpio, list); - pending = readb(chip->base + GPIOMIS); - writeb(pending, chip->base + GPIOIC); - - if (pending == 0) - continue; + pending = readb(chip->base + GPIOMIS); + writeb(pending, chip->base + GPIOIC); + if (pending) { for_each_set_bit(offset, &pending, PL061_GPIO_NR) generic_handle_irq(pl061_to_irq(&chip->gc, offset)); } + chained_irq_exit(irqchip, desc); } @@ -218,9 +204,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) { struct pl061_platform_data *pdata; struct pl061_gpio *chip; - struct list_head *chip_list; int ret, irq, i; - static DECLARE_BITMAP(init_irq, NR_IRQS); chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) @@ -251,7 +235,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) } spin_lock_init(&chip->lock); - INIT_LIST_HEAD(&chip->list); chip->gc.direction_input = pl061_direction_input; chip->gc.direction_output = pl061_direction_output; @@ -283,18 +266,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) goto iounmap; } irq_set_chained_handler(irq, pl061_irq_handler); - if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ - chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); - if (chip_list == NULL) { - clear_bit(irq, init_irq); - ret = -ENOMEM; - goto iounmap; - } - INIT_LIST_HEAD(chip_list); - irq_set_handler_data(irq, chip_list); - } else - chip_list = irq_get_handler_data(irq); - list_add(&chip->list, chip_list); + irq_set_handler_data(irq, chip); for (i = 0; i < PL061_GPIO_NR; i++) { if (pdata) { -- cgit v1.2.1