Skip to content

Commit

Permalink
[Blackfin] arch: Allow concurrent use of GPIO and GPIO IRQ
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Hennerich authored and Bryan Wu committed Apr 24, 2008
1 parent a086ee2 commit affee2b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 67 deletions.
45 changes: 17 additions & 28 deletions arch/blackfin/kernel/bfin_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,32 +395,6 @@ inline void portmux_setup(unsigned short portno, unsigned short function)
# define portmux_setup(...) do { } while (0)
#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)
{
printk(KERN_INFO "Blackfin GPIO Controller\n");
Expand Down Expand Up @@ -1080,8 +1054,6 @@ void gpio_free(unsigned gpio)
return;
}

default_gpio(gpio);

reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);

set_label(gpio, "free");
Expand Down Expand Up @@ -1144,6 +1116,18 @@ int gpio_get_value(unsigned gpio)
}
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

int gpio_direction_input(unsigned gpio)
Expand Down Expand Up @@ -1210,6 +1194,11 @@ void bfin_gpio_reset_spi0_ssel1(void)
udelay(1);
}

void bfin_gpio_irq_prepare(unsigned gpio)
{
port_setup(gpio, GPIO_USAGE);
}

#endif /*BF548_FAMILY */

#if defined(CONFIG_PROC_FS)
Expand Down
52 changes: 13 additions & 39 deletions arch/blackfin/mach-common/ints-priority.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];

extern void bfin_gpio_irq_prepare(unsigned gpio);

static void bfin_gpio_ack_irq(unsigned int irq)
{
Expand Down Expand Up @@ -364,35 +365,25 @@ static void bfin_gpio_unmask_irq(unsigned int irq)

static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
unsigned int ret;
u16 gpionr = irq - IRQ_PF0;
char buf[8];

if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
snprintf(buf, sizeof buf, "IRQ %d", irq);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
bfin_gpio_irq_prepare(gpionr);

gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq);

return ret;
return 0;
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
bfin_gpio_mask_irq(irq);
gpio_free(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)
{

unsigned int ret;
char buf[8];
u16 gpionr = irq - IRQ_PF0;

if (type == IRQ_TYPE_PROBE) {
Expand All @@ -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 |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
snprintf(buf, sizeof buf, "IRQ %d", irq);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
bfin_gpio_irq_prepare(gpionr);

gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else {
Expand Down Expand Up @@ -595,6 +582,8 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
(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)
{

Expand Down Expand Up @@ -697,8 +686,6 @@ static void bfin_gpio_unmask_irq(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);
u8 pint_val = irq2pint_lut[irq - SYS_IRQS];

Expand All @@ -709,33 +696,26 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
return -ENODEV;
}

if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
snprintf(buf, sizeof buf, "IRQ %d", irq);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
bfin_gpio_irq_prepare(gpionr);

gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq);

return ret;
return 0;
}

static void bfin_gpio_irq_shutdown(unsigned int irq)
{
u16 gpionr = irq_to_gpio(irq);

bfin_gpio_mask_irq(irq);
gpio_free(gpionr);
gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
}

static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{

unsigned int ret;
char buf[8];
u16 gpionr = irq_to_gpio(irq);
u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val);
Expand All @@ -753,21 +733,15 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)

if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
snprintf(buf, sizeof buf, "IRQ %d", irq);
ret = gpio_request(gpionr, buf);
if (ret)
return ret;
}
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
bfin_gpio_irq_prepare(gpionr);

gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else {
gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
return 0;
}

gpio_direction_input(gpionr);

if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
else
Expand Down

0 comments on commit affee2b

Please sign in to comment.