forked from Minki/linux
gpio: pcf857x: call the gpio user handler iff gpio_to_irq is done
For pcf857x driver if the initial state is not set properly (proper n_latch is not passed), we get bad irq prints on console. We get this only for the first interrupt and doesnot repeat for further interrupts unles and until there are other gpio pins which are not flipping continously. following prints are seen on console. [ 40.983924] irq 0, desc: ce004080, depth: 1, count: 0, unhandled: 0 [ 40.990511] ->handle_irq(): c00aa538, handle_bad_irq+0x0/0x260 [ 40.996768] ->irq_data.chip(): c080b6ec, no_irq_chip+0x0/0x60 [ 41.002842] ->action(): (null) [ 41.006242] IRQ_NOPROBE set [ 41.009465] IRQ_NOREQUEST set Signed-off-by: George Cherian <george.cherian@ti.com> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
98ff449090
commit
21fd3cd187
@ -69,6 +69,7 @@ struct pcf857x {
|
|||||||
spinlock_t slock; /* protect irq demux */
|
spinlock_t slock; /* protect irq demux */
|
||||||
unsigned out; /* software latch */
|
unsigned out; /* software latch */
|
||||||
unsigned status; /* current status */
|
unsigned status; /* current status */
|
||||||
|
unsigned irq_mapped; /* mapped gpio irqs */
|
||||||
|
|
||||||
int (*write)(struct i2c_client *client, unsigned data);
|
int (*write)(struct i2c_client *client, unsigned data);
|
||||||
int (*read)(struct i2c_client *client);
|
int (*read)(struct i2c_client *client);
|
||||||
@ -161,8 +162,13 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||||||
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
|
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||||
{
|
{
|
||||||
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
|
||||||
|
int ret;
|
||||||
|
|
||||||
return irq_create_mapping(gpio->irq_domain, offset);
|
ret = irq_create_mapping(gpio->irq_domain, offset);
|
||||||
|
if (ret > 0)
|
||||||
|
gpio->irq_mapped |= (1 << offset);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t pcf857x_irq(int irq, void *data)
|
static irqreturn_t pcf857x_irq(int irq, void *data)
|
||||||
@ -174,7 +180,12 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
|
|||||||
|
|
||||||
spin_lock_irqsave(&gpio->slock, flags);
|
spin_lock_irqsave(&gpio->slock, flags);
|
||||||
|
|
||||||
change = gpio->status ^ status;
|
/*
|
||||||
|
* call the interrupt handler iff gpio is used as
|
||||||
|
* interrupt source, just to avoid bad irqs
|
||||||
|
*/
|
||||||
|
|
||||||
|
change = ((gpio->status ^ status) & gpio->irq_mapped);
|
||||||
for_each_set_bit(i, &change, gpio->chip.ngpio)
|
for_each_set_bit(i, &change, gpio->chip.ngpio)
|
||||||
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
|
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
|
||||||
gpio->status = status;
|
gpio->status = status;
|
||||||
@ -187,9 +198,14 @@ static irqreturn_t pcf857x_irq(int irq, void *data)
|
|||||||
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
|
static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
|
||||||
irq_hw_number_t hw)
|
irq_hw_number_t hw)
|
||||||
{
|
{
|
||||||
|
struct pcf857x *gpio = domain->host_data;
|
||||||
|
|
||||||
irq_set_chip_and_handler(virq,
|
irq_set_chip_and_handler(virq,
|
||||||
&dummy_irq_chip,
|
&dummy_irq_chip,
|
||||||
handle_level_irq);
|
handle_level_irq);
|
||||||
|
set_irq_flags(virq, IRQF_VALID);
|
||||||
|
gpio->irq_mapped |= (1 << hw);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +228,7 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
|
|||||||
gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
|
gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
|
||||||
gpio->chip.ngpio,
|
gpio->chip.ngpio,
|
||||||
&pcf857x_irq_domain_ops,
|
&pcf857x_irq_domain_ops,
|
||||||
NULL);
|
gpio);
|
||||||
if (!gpio->irq_domain)
|
if (!gpio->irq_domain)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user