[PATCH v4 1/3] ARM: bcm281xx: Add GPIO driver
Markus Mayer
markus.mayer at linaro.org
Fri Aug 23 15:30:57 EDT 2013
>>> +static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
>>> +{
>>> + void __iomem *reg_base;
>>> + int bit, bank_id;
>>> + unsigned long sta;
>>> + struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq);
>>> + struct irq_chip *chip = irq_desc_get_chip(desc);
>>> +
>>> + chained_irq_enter(chip, desc);
>>> +
>>> + /*
>>> + * For bank interrupts, we can't use chip_data to store the kona_gpio
>>> + * pointer, since GIC needs it for its own purposes. Therefore, we get
>>> + * our pointer from the bank structure.
>>> + */
>>> + reg_base = bank->reg_base;
>>> + bank_id = bank->id;
>>> + bcm_kona_gpio_unlock_bank(reg_base, bank_id);
>>> +
>>> + sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
>>> + (~(readl(reg_base + GPIO_INT_MASK(bank_id))));
>>> +
>>> + for_each_set_bit(bit, &sta, 32) {
>>> + /*
>>> + * Clear interrupt before handler is called so we don't
>>> + * miss any interrupt occurred during executing them.
>>> + */
>>> + writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
>>> + (1 << bit),
>>
>> Use BIT(bit)
>>
>>> + reg_base + GPIO_INT_STATUS(bank_id));
>>> + /* Invoke interrupt handler */
>>> + generic_handle_irq(gpio_to_irq(GPIO_PER_BANK * bank_id + bit));
>>> + }
>>
>> Usually you may want to re-read thet status for each iteration
>> of this loop, if IRQs appear as you are processing.
>
> Will do.
I have a follow-up question regarding status reads for each iteration.
Is this what you are looking for?
for (;;) {
sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
(~(readl(reg_base + GPIO_INT_MASK(bank_id))));
if (sta == 0)
break;
for_each_set_bit(bit, &sta, 32) {
int gpio = GPIO_PER_BANK * bank_id + bit;
int virq = irq_find_mapping(bank->kona_gpio->irq_domain,
gpio);
/*
* Clear interrupt before handler is called so
we don't
* miss any interrupt occurred during
executing them.
*/
writel(readl(reg_base +
GPIO_INT_STATUS(bank_id)) |
BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
/* Invoke interrupt handler */
generic_handle_irq(virq);
}
}
It's an extra loop, since I am not sure it would work to modify "sta"
within the for_each_set_bit loop. Say an interrupt occurred whose bit
we already checked, we'd still miss that.
Thanks,
-Markus
More information about the linux-arm-kernel
mailing list