Commit 9570ff4a authored by Graf Yang's avatar Graf Yang Committed by Bryan Wu

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: default avatarGraf Yang <graf.yang@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier.adi@gmail.com>
Signed-off-by: default avatarBryan Wu <cooloney@kernel.org>
parent 94106e0f
...@@ -548,6 +548,8 @@ struct gpio_port_s { ...@@ -548,6 +548,8 @@ struct gpio_port_s {
int bfin_gpio_request(unsigned gpio, const char *label); int bfin_gpio_request(unsigned gpio, const char *label);
void bfin_gpio_free(unsigned gpio); void bfin_gpio_free(unsigned gpio);
int bfin_gpio_irq_request(unsigned gpio, const char *label);
void bfin_gpio_irq_free(unsigned gpio);
int bfin_gpio_direction_input(unsigned gpio); int bfin_gpio_direction_input(unsigned gpio);
int bfin_gpio_direction_output(unsigned gpio, int value); int bfin_gpio_direction_output(unsigned gpio, int value);
int bfin_gpio_get_value(unsigned gpio); int bfin_gpio_get_value(unsigned gpio);
......
...@@ -179,6 +179,7 @@ static struct gpio_port_t *gpio_array[] = { ...@@ -179,6 +179,7 @@ static struct gpio_port_t *gpio_array[] = {
static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; 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 #define RESOURCE_LABEL_SIZE 16
...@@ -1055,13 +1056,16 @@ int bfin_gpio_request(unsigned gpio, const char *label) ...@@ -1055,13 +1056,16 @@ int bfin_gpio_request(unsigned gpio, const char *label)
local_irq_restore(flags); local_irq_restore(flags);
return -EBUSY; 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); reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
set_label(gpio, label);
local_irq_restore(flags); local_irq_restore(flags);
port_setup(gpio, GPIO_USAGE); port_setup(gpio, GPIO_USAGE);
set_label(gpio, label);
return 0; return 0;
} }
...@@ -1091,6 +1095,69 @@ void bfin_gpio_free(unsigned gpio) ...@@ -1091,6 +1095,69 @@ void bfin_gpio_free(unsigned gpio)
} }
EXPORT_SYMBOL(bfin_gpio_free); 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 #ifdef BF548_FAMILY
int bfin_gpio_direction_input(unsigned gpio) int bfin_gpio_direction_input(unsigned gpio)
...@@ -1253,12 +1320,15 @@ void bfin_gpio_irq_prepare(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, static int gpio_proc_read(char *buf, char **start, off_t offset,
int len, int *unused_i, void *unused_v) 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++) { for (c = 0; c < MAX_RESOURCES; c++) {
if (!check_gpio(c) && (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c);
len = sprintf(buf, "GPIO_%d: \t%s \t\tGPIO %s\n", c, gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c);
get_label(c), get_gpio_dir(c) ? "OUTPUT" : "INPUT"); 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)) 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)); len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
else else
......
...@@ -432,7 +432,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) ...@@ -432,7 +432,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
bfin_gpio_mask_irq(irq); bfin_gpio_mask_irq(irq);
__clear_bit(gpionr, gpio_enabled); __clear_bit(gpionr, gpio_enabled);
bfin_gpio_free(gpionr); bfin_gpio_irq_free(gpionr);
} }
static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
...@@ -441,11 +441,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -441,11 +441,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
char buf[16]; char buf[16];
u32 gpionr = irq_to_gpio(irq); u32 gpionr = irq_to_gpio(irq);
snprintf(buf, 16, "gpio-irq%d", irq);
ret = bfin_gpio_request(gpionr, buf);
if (ret)
return ret;
if (type == IRQ_TYPE_PROBE) { if (type == IRQ_TYPE_PROBE) {
/* only probe unenabled GPIO interrupt lines */ /* only probe unenabled GPIO interrupt lines */
if (__test_bit(gpionr, gpio_enabled)) if (__test_bit(gpionr, gpio_enabled))
...@@ -456,6 +451,11 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -456,6 +451,11 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
snprintf(buf, 16, "gpio-irq%d", irq);
ret = bfin_gpio_irq_request(gpionr, buf);
if (ret)
return ret;
if (__test_and_set_bit(gpionr, gpio_enabled)) if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr); bfin_gpio_irq_prepare(gpionr);
...@@ -740,7 +740,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) ...@@ -740,7 +740,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
bfin_gpio_mask_irq(irq); bfin_gpio_mask_irq(irq);
__clear_bit(gpionr, gpio_enabled); __clear_bit(gpionr, gpio_enabled);
bfin_gpio_free(gpionr); bfin_gpio_irq_free(gpionr);
} }
static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
...@@ -755,11 +755,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -755,11 +755,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
if (pint_val == IRQ_NOT_AVAIL) if (pint_val == IRQ_NOT_AVAIL)
return -ENODEV; return -ENODEV;
snprintf(buf, 16, "gpio-irq%d", irq);
ret = bfin_gpio_request(gpionr, buf);
if (ret)
return ret;
if (type == IRQ_TYPE_PROBE) { if (type == IRQ_TYPE_PROBE) {
/* only probe unenabled GPIO interrupt lines */ /* only probe unenabled GPIO interrupt lines */
if (__test_bit(gpionr, gpio_enabled)) if (__test_bit(gpionr, gpio_enabled))
...@@ -769,6 +764,12 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) ...@@ -769,6 +764,12 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
snprintf(buf, 16, "gpio-irq%d", irq);
ret = bfin_gpio_irq_request(gpionr, buf);
if (ret)
return ret;
if (__test_and_set_bit(gpionr, gpio_enabled)) if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr); bfin_gpio_irq_prepare(gpionr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment