From: akpm@linux-foundation.org
To: baruch@tkos.co.il, david-b@pacbell.net, rmk@arm.linux.org.uk,
mm-commits@vger.kernel.org
Subject: [folded] gpio-driver-for-primecell-pl061-gpio-controller-v4.patch removed from -mm tree
Date: Wed, 17 Jun 2009 15:45:37 -0700 [thread overview]
Message-ID: <200906172245.n5HMjbsF005924@imap1.linux-foundation.org> (raw)
The patch titled
gpio-driver-for-primecell-pl061-gpio-controller-v4
has been removed from the -mm tree. Its filename was
gpio-driver-for-primecell-pl061-gpio-controller-v4.patch
This patch was dropped because it was folded into gpio-driver-for-primecell-pl061-gpio-controller.patch
The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/
------------------------------------------------------
Subject: gpio-driver-for-primecell-pl061-gpio-controller-v4
From: Baruch Siach <baruch@tkos.co.il>
- Depend on CONFIG_ARM_AMBA
- Do not request the gpio for IRQ automatically, just warn if it's not
requested
- Remove SZ_4K
- Iterate through a linked list find the source of interrupt when
multiple PL061s are connected to the same IRQ trigger
- Move hardware register defines into the .c file
Cc: David Brownell <david-b@pacbell.net>
Cc: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/gpio/Kconfig | 1
drivers/gpio/pl061.c | 92 ++++++++++++++++-------------------
include/linux/amba/pl061.h | 19 +++----
3 files changed, 54 insertions(+), 58 deletions(-)
diff -puN drivers/gpio/Kconfig~gpio-driver-for-primecell-pl061-gpio-controller-v4 drivers/gpio/Kconfig
--- a/drivers/gpio/Kconfig~gpio-driver-for-primecell-pl061-gpio-controller-v4
+++ a/drivers/gpio/Kconfig
@@ -69,6 +69,7 @@ comment "Memory mapped GPIO expanders:"
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
+ depends on ARM_AMBA
help
Say yes here to support the PrimeCell PL061 GPIO device
diff -puN drivers/gpio/pl061.c~gpio-driver-for-primecell-pl061-gpio-controller-v4 drivers/gpio/pl061.c
--- a/drivers/gpio/pl061.c~gpio-driver-for-primecell-pl061-gpio-controller-v4
+++ a/drivers/gpio/pl061.c
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/list.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
@@ -24,9 +25,22 @@
#include <linux/amba/bus.h>
#include <linux/amba/pl061.h>
+#define GPIODIR 0x400
+#define GPIOIS 0x404
+#define GPIOIBE 0x408
+#define GPIOIEV 0x40C
+#define GPIOIE 0x410
+#define GPIORIS 0x414
+#define GPIOMIS 0x418
+#define GPIOIC 0x41C
+
#define PL061_GPIO_NR 8
+#define PL061_REG_SIZE (4*1024)
+
struct pl061_gpio {
+ 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
@@ -37,12 +51,8 @@ struct pl061_gpio {
void __iomem *base;
struct gpio_chip gc;
- struct work_struct gpio_free_work;
- DECLARE_BITMAP(gpios_to_free, PL061_GPIO_NR);
};
-static u32 (*pl061_pending_irq)(int irq);
-
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -112,16 +122,6 @@ static void pl061_irq_disable(unsigned i
spin_unlock_irqrestore(&chip->irq_lock, flags);
}
-static void pl061_irq_shutdown(unsigned irq)
-{
- struct pl061_gpio *chip = get_irq_chip_data(irq);
- int offset = irq_to_gpio(irq) - chip->gc.base;
-
- pl061_irq_disable(irq);
- set_bit(offset, chip->gpios_to_free);
- schedule_work(&chip->gpio_free_work);
-}
-
static void pl061_irq_enable(unsigned irq)
{
struct pl061_gpio *chip = get_irq_chip_data(irq);
@@ -138,16 +138,10 @@ static void pl061_irq_enable(unsigned ir
static unsigned int pl061_irq_startup(unsigned irq)
{
- int ret;
-
- ret = gpio_request(irq_to_gpio(irq), "IRQ");
- if (ret < 0) {
- pr_warning("%s: warning: gpio_request(%d) returned %d\n",
- __func__, irq_to_gpio(irq), ret);
- return 0;
- }
+ if (gpio_request(irq_to_gpio(irq), "IRQ") == 0)
+ pr_warning("%s: warning: GPIO%d has not been requested\n",
+ __func__, irq_to_gpio(irq));
- gpio_direction_input(irq_to_gpio(irq));
pl061_irq_enable(irq);
return 0;
@@ -202,45 +196,38 @@ static struct irq_chip pl061_irqchip = {
.startup = pl061_irq_startup,
.enable = pl061_irq_enable,
.disable = pl061_irq_disable,
- .shutdown = pl061_irq_shutdown,
.set_type = pl061_irq_type,
};
static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
{
+ struct list_head *chip_list = get_irq_chip_data(irq);
+ struct list_head *ptr;
+ struct pl061_gpio *chip;
+
desc->chip->ack(irq);
- while (1) {
+ list_for_each(ptr, chip_list) {
unsigned long pending;
int gpio;
- pending = pl061_pending_irq(irq);
+ chip = list_entry(ptr, struct pl061_gpio, list);
+ pending = readb(chip->base + GPIOMIS);
+ writeb(pending, chip->base + GPIOIC);
+
if (pending == 0)
- break;
+ continue;
- for_each_bit(gpio, &pending, BITS_PER_LONG)
+ for_each_bit(gpio, &pending, PL061_GPIO_NR)
generic_handle_irq(gpio_to_irq(gpio));
}
desc->chip->unmask(irq);
}
-static void pl061_gpio_free(struct work_struct *work)
-{
- struct pl061_gpio *chip = container_of(work, struct pl061_gpio,
- gpio_free_work);
- int offset;
-
- for_each_bit(offset, chip->gpios_to_free, PL061_GPIO_NR) {
- int gpio = offset + chip->gc.base;
-
- if (test_and_clear_bit(offset, chip->gpios_to_free))
- gpio_free(gpio);
- }
-}
-
static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
{
struct pl061_platform_data *pdata;
struct pl061_gpio *chip;
+ struct list_head *chip_list;
int ret, irq, i;
pdata = dev->dev.platform_data;
@@ -251,12 +238,12 @@ static int __init pl061_probe(struct amb
if (chip == NULL)
return -ENOMEM;
- if (request_mem_region(dev->res.start, SZ_4K, "pl061") == NULL) {
+ if (!request_mem_region(dev->res.start, PL061_REG_SIZE, "pl061")) {
ret = -EBUSY;
goto free_mem;
}
- chip->base = ioremap(dev->res.start, SZ_4K);
+ chip->base = ioremap(dev->res.start, PL061_REG_SIZE);
if (chip->base == NULL) {
ret = -ENOMEM;
goto release_region;
@@ -264,8 +251,7 @@ static int __init pl061_probe(struct amb
spin_lock_init(&chip->lock);
spin_lock_init(&chip->irq_lock);
-
- INIT_WORK(&chip->gpio_free_work, pl061_gpio_free);
+ INIT_LIST_HEAD(&chip->list);
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
@@ -291,7 +277,17 @@ static int __init pl061_probe(struct amb
goto iounmap;
}
set_irq_chained_handler(irq, pl061_irq_handler);
- pl061_pending_irq = pdata->pending_irqs;
+ if (!pdata->is_irq_initialized || !pdata->is_irq_initialized(irq)) {
+ chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
+ if (chip_list == NULL) {
+ ret = -ENOMEM;
+ goto iounmap;
+ }
+ INIT_LIST_HEAD(chip_list);
+ set_irq_chip_data(irq, chip_list);
+ } else
+ chip_list = get_irq_chip_data(irq);
+ list_add(&chip->list, chip_list);
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata->directions & (1 << i))
@@ -312,7 +308,7 @@ static int __init pl061_probe(struct amb
iounmap:
iounmap(chip->base);
release_region:
- release_mem_region(dev->res.start, SZ_4K);
+ release_mem_region(dev->res.start, PL061_REG_SIZE);
free_mem:
kfree(chip);
diff -puN include/linux/amba/pl061.h~gpio-driver-for-primecell-pl061-gpio-controller-v4 include/linux/amba/pl061.h
--- a/include/linux/amba/pl061.h~gpio-driver-for-primecell-pl061-gpio-controller-v4
+++ a/include/linux/amba/pl061.h
@@ -1,18 +1,17 @@
/* platform data for the PL061 GPIO driver */
-#define GPIODIR 0x400
-#define GPIOIS 0x404
-#define GPIOIBE 0x408
-#define GPIOIEV 0x40C
-#define GPIOIE 0x410
-#define GPIORIS 0x414
-#define GPIOMIS 0x418
-#define GPIOIC 0x41C
-
struct pl061_platform_data {
/* number of the first GPIO */
unsigned gpio_base;
- u32 (*pending_irqs)(int irq);
+
u8 directions; /* startup directions, 1: out, 0: in */
u8 values; /* startup values */
+
+ /* This callback may be used when you have more than one PL061
+ * connected to the same IRQ trigger. This callback must return 0 on
+ * the first time it is called for each irq, and 1 on any other call.
+ * In case you are not unfortunate enough to have this setup, this
+ * pointer must be set to NULL.
+ */
+ int (*is_irq_initialized)(int irq);
};
_
Patches currently in -mm which might be from baruch@tkos.co.il are
origin.patch
gpio-driver-for-primecell-pl061-gpio-controller.patch
gpio-driver-for-primecell-pl061-gpio-controller-v4.patch
gpio-driver-for-primecell-pl061-gpio-controller-v5.patch
reply other threads:[~2009-06-17 22:47 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200906172245.n5HMjbsF005924@imap1.linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=baruch@tkos.co.il \
--cc=david-b@pacbell.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mm-commits@vger.kernel.org \
--cc=rmk@arm.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.