[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:
parent
a086ee2268
commit
affee2b261
2 changed files with 30 additions and 67 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue