diff options
author | Graf Yang <graf.yang@analog.com> | 2009-01-07 15:14:38 (GMT) |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 15:14:38 (GMT) |
commit | 9570ff4af6920c5992eb91141d71fc94127d864b (patch) | |
tree | 8ab0887035ab00a655eb8f78b39ed0acbb0b3bed /arch/blackfin/kernel/bfin_gpio.c | |
parent | 94106e0fb6b863348a566617ca6bf431c37ddc5e (diff) | |
download | linux-9570ff4af6920c5992eb91141d71fc94127d864b.tar.xz |
Blackfin arch: Allow a gpio pin be requested both as gpio and irq.
[Mike Frysinger <vapier.adi@gmail.com>:
- use KERN_NOTICE when using gpios as both irq and non
rather than KERN_ERR
- embedded newlines in printk() does not fly]
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/kernel/bfin_gpio.c')
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index de235b8..2c72b15 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -179,6 +179,7 @@ static struct gpio_port_t *gpio_array[] = { static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; +static unsigned short reserved_gpio_irq_map[GPIO_BANK_NUM]; #define RESOURCE_LABEL_SIZE 16 @@ -1043,7 +1044,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { dump_stack(); printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", - gpio, get_label(gpio)); + gpio, get_label(gpio)); local_irq_restore(flags); return -EBUSY; } @@ -1055,13 +1056,16 @@ int bfin_gpio_request(unsigned gpio, const char *label) local_irq_restore(flags); return -EBUSY; } + if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) + printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" + " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); + set_label(gpio, label); local_irq_restore(flags); port_setup(gpio, GPIO_USAGE); - set_label(gpio, label); return 0; } @@ -1091,6 +1095,69 @@ void bfin_gpio_free(unsigned gpio) } EXPORT_SYMBOL(bfin_gpio_free); +int bfin_gpio_irq_request(unsigned gpio, const char *label) +{ + unsigned long flags; + + if (check_gpio(gpio) < 0) + return -EINVAL; + + local_irq_save(flags); + + if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + dump_stack(); + printk(KERN_ERR + "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n", + gpio); + local_irq_restore(flags); + return -EBUSY; + } + if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + dump_stack(); + printk(KERN_ERR + "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", + gpio, get_label(gpio)); + local_irq_restore(flags); + return -EBUSY; + } + if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) + printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! " + "(Documentation/blackfin/bfin-gpio-notes.txt)\n", + gpio, get_label(gpio)); + + reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio); + set_label(gpio, label); + + local_irq_restore(flags); + + port_setup(gpio, GPIO_USAGE); + + return 0; +} + +void bfin_gpio_irq_free(unsigned gpio) +{ + unsigned long flags; + + if (check_gpio(gpio) < 0) + return; + + local_irq_save(flags); + + if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { + dump_stack(); + gpio_error(gpio); + local_irq_restore(flags); + return; + } + + reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); + + set_label(gpio, "free"); + + local_irq_restore(flags); +} + #ifdef BF548_FAMILY int bfin_gpio_direction_input(unsigned gpio) @@ -1253,12 +1320,15 @@ void bfin_gpio_irq_prepare(unsigned gpio) static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int *unused_i, void *unused_v) { - int c, outlen = 0; + int c, irq, gpio, outlen = 0; for (c = 0; c < MAX_RESOURCES; c++) { - if (!check_gpio(c) && (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) - len = sprintf(buf, "GPIO_%d: \t%s \t\tGPIO %s\n", c, - get_label(c), get_gpio_dir(c) ? "OUTPUT" : "INPUT"); + irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c); + gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c); + if (!check_gpio(c) && (gpio || irq)) + len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, + get_label(c), (gpio && irq) ? " *" : "", + get_gpio_dir(c) ? "OUTPUT" : "INPUT"); else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c)) len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); else |