[Blackfin] arch: Allow concurrent use of GPIO and GPIO IRQ

The irq setup code no longer calls gpio request and free.
This patch also changes the default gpio_free behavior on Blackfin.
A freed GPIO keeps it's last state, and is not defaulted back to
an input. This is also what all other architectures do.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
This commit is contained in:
Michael Hennerich 2008-04-24 08:10:10 +08:00 committed by Bryan Wu
parent a086ee2268
commit affee2b261
2 changed files with 30 additions and 67 deletions

View file

@ -395,32 +395,6 @@ inline void portmux_setup(unsigned short portno, unsigned short function)
# define portmux_setup(...) do { } while (0) # define portmux_setup(...) do { } while (0)
#endif #endif
#ifndef BF548_FAMILY
static void default_gpio(unsigned gpio)
{
unsigned short bank, bitmask;
unsigned long flags;
bank = gpio_bank(gpio);
bitmask = gpio_bit(gpio);
local_irq_save(flags);
gpio_bankb[bank]->maska_clear = bitmask;
gpio_bankb[bank]->maskb_clear = bitmask;
SSYNC();
gpio_bankb[bank]->inen &= ~bitmask;
gpio_bankb[bank]->dir &= ~bitmask;
gpio_bankb[bank]->polar &= ~bitmask;
gpio_bankb[bank]->both &= ~bitmask;
gpio_bankb[bank]->edge &= ~bitmask;
AWA_DUMMY_READ(edge);
local_irq_restore(flags);
}
#else
# define default_gpio(...) do { } while (0)
#endif
static int __init bfin_gpio_init(void) static int __init bfin_gpio_init(void)
{ {
printk(KERN_INFO "Blackfin GPIO Controller\n"); printk(KERN_INFO "Blackfin GPIO Controller\n");
@ -1080,8 +1054,6 @@ void gpio_free(unsigned gpio)
return; return;
} }
default_gpio(gpio);
reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
set_label(gpio, "free"); set_label(gpio, "free");
@ -1144,6 +1116,18 @@ int gpio_get_value(unsigned gpio)
} }
EXPORT_SYMBOL(gpio_get_value); EXPORT_SYMBOL(gpio_get_value);
void bfin_gpio_irq_prepare(unsigned gpio)
{
unsigned long flags;
port_setup(gpio, GPIO_USAGE);
local_irq_save(flags);
gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
local_irq_restore(flags);
}
#else #else
int gpio_direction_input(unsigned gpio) int gpio_direction_input(unsigned gpio)
@ -1210,6 +1194,11 @@ void bfin_gpio_reset_spi0_ssel1(void)
udelay(1); udelay(1);
} }
void bfin_gpio_irq_prepare(unsigned gpio)
{
port_setup(gpio, GPIO_USAGE);
}
#endif /*BF548_FAMILY */ #endif /*BF548_FAMILY */
#if defined(CONFIG_PROC_FS) #if defined(CONFIG_PROC_FS)

View file

@ -326,6 +326,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
extern void bfin_gpio_irq_prepare(unsigned gpio);
static void bfin_gpio_ack_irq(unsigned int irq) static void bfin_gpio_ack_irq(unsigned int irq)
{ {
@ -364,35 +365,25 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
static unsigned int bfin_gpio_irq_startup(unsigned int irq) static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{ {
unsigned int ret;
u16 gpionr = irq - IRQ_PF0; u16 gpionr = irq - IRQ_PF0;
char buf[8];
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
snprintf(buf, sizeof buf, "IRQ %d", irq); bfin_gpio_irq_prepare(gpionr);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq); bfin_gpio_unmask_irq(irq);
return ret; return 0;
} }
static void bfin_gpio_irq_shutdown(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq)
{ {
bfin_gpio_mask_irq(irq); bfin_gpio_mask_irq(irq);
gpio_free(irq - IRQ_PF0);
gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0); gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
} }
static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{ {
unsigned int ret;
char buf[8];
u16 gpionr = irq - IRQ_PF0; u16 gpionr = irq - IRQ_PF0;
if (type == IRQ_TYPE_PROBE) { if (type == IRQ_TYPE_PROBE) {
@ -404,12 +395,8 @@ 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)) {
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
snprintf(buf, sizeof buf, "IRQ %d", irq); bfin_gpio_irq_prepare(gpionr);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else { } else {
@ -595,6 +582,8 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
(struct pin_int_t *)PINT3_MASK_SET, (struct pin_int_t *)PINT3_MASK_SET,
}; };
extern void bfin_gpio_irq_prepare(unsigned gpio);
inline unsigned short get_irq_base(u8 bank, u8 bmap) inline unsigned short get_irq_base(u8 bank, u8 bmap)
{ {
@ -697,8 +686,6 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
static unsigned int bfin_gpio_irq_startup(unsigned int irq) static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{ {
unsigned int ret;
char buf[8];
u16 gpionr = irq_to_gpio(irq); u16 gpionr = irq_to_gpio(irq);
u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
@ -709,17 +696,13 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
return -ENODEV; return -ENODEV;
} }
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
snprintf(buf, sizeof buf, "IRQ %d", irq); bfin_gpio_irq_prepare(gpionr);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq); bfin_gpio_unmask_irq(irq);
return ret; return 0;
} }
static void bfin_gpio_irq_shutdown(unsigned int irq) static void bfin_gpio_irq_shutdown(unsigned int irq)
@ -727,15 +710,12 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
u16 gpionr = irq_to_gpio(irq); u16 gpionr = irq_to_gpio(irq);
bfin_gpio_mask_irq(irq); bfin_gpio_mask_irq(irq);
gpio_free(gpionr);
gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(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)
{ {
unsigned int ret;
char buf[8];
u16 gpionr = irq_to_gpio(irq); u16 gpionr = irq_to_gpio(irq);
u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val); u32 pintbit = PINT_BIT(pint_val);
@ -753,12 +733,8 @@ 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)) {
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
snprintf(buf, sizeof buf, "IRQ %d", irq); bfin_gpio_irq_prepare(gpionr);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else { } else {
@ -766,8 +742,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0; return 0;
} }
gpio_direction_input(gpionr);
if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
else else