static void msm_gpio_irq_ack(unsigned int irq) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); spin_lock_irqsave(&msm_chip->chip.lock, irq_flags); msm_gpio_clear_detect_status(&msm_chip->chip, irq - FIRST_GPIO_IRQ); spin_unlock_irqrestore(&msm_chip->chip.lock, irq_flags); }
static void msm_gpio_irq_ack(struct irq_data *d) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = irq_get_chip_data(d->irq); spin_lock_irqsave(&msm_chip->lock, irq_flags); msm_gpio_clear_detect_status(msm_chip, d->irq - gpio_to_irq(msm_chip->chip.base)); spin_unlock_irqrestore(&msm_chip->lock, irq_flags); }
static void msm_gpio_irq_unmask(unsigned int irq) { unsigned long irq_flags; struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq); unsigned offset = irq - gpio_to_irq(msm_chip->chip.base); spin_lock_irqsave(&msm_chip->lock, irq_flags); /* level triggered interrupts are also latched */ if (!(readl(msm_chip->regs.int_edge) & BIT(offset))) msm_gpio_clear_detect_status(msm_chip, offset); msm_chip->int_enable[0] |= BIT(offset); writel(msm_chip->int_enable[0], msm_chip->regs.int_en); spin_unlock_irqrestore(&msm_chip->lock, irq_flags); }
int msm_gpio_configure(struct gpio_chip *chip, unsigned int gpio, unsigned long flags) { struct msm_gpio_chip *msm_chip = container_of(chip, struct msm_gpio_chip, chip); unsigned b = 1U << (gpio - chip->start); unsigned v; if (flags & (GPIOF_OUTPUT_LOW | GPIOF_OUTPUT_HIGH)) msm_gpio_write(chip, gpio, flags & GPIOF_OUTPUT_HIGH); if (flags & (GPIOF_INPUT | GPIOF_DRIVE_OUTPUT)) { v = readl(msm_chip->regs.oe); if (flags & GPIOF_DRIVE_OUTPUT) { writel(v | b, msm_chip->regs.oe); } else { writel(v & (~b), msm_chip->regs.oe); } } if (flags & (IRQF_TRIGGER_MASK | GPIOF_IRQF_TRIGGER_NONE)) { v = readl(msm_chip->regs.int_edge); if (flags & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) { writel(v | b, msm_chip->regs.int_edge); irq_desc[MSM_GPIO_TO_INT(gpio)].handle_irq = handle_edge_irq; } else { writel(v & (~b), msm_chip->regs.int_edge); irq_desc[MSM_GPIO_TO_INT(gpio)].handle_irq = handle_level_irq; } if ((flags & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) == (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) { msm_chip->both_edge_detect |= b; msm_gpio_update_both_edge_detect(msm_chip); } else { msm_chip->both_edge_detect &= ~b; v = readl(msm_chip->regs.int_pos); if (flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) { writel(v | b, msm_chip->regs.int_pos); } else { writel(v & (~b), msm_chip->regs.int_pos); } } } /* used by msm_gpio_irq_mask and msm_gpio_irq_unmask */ if (flags & (MSM_GPIOF_ENABLE_INTERRUPT | MSM_GPIOF_DISABLE_INTERRUPT)) { v = readl(msm_chip->regs.int_edge); /* level triggered interrupts are also latched */ if (!(v & b)) msm_gpio_clear_detect_status(chip, gpio); if (flags & MSM_GPIOF_ENABLE_INTERRUPT) { msm_chip->int_enable[0] |= b; } else { msm_chip->int_enable[0] &= ~b; } writel(msm_chip->int_enable[0], msm_chip->regs.int_en); } if (flags & (MSM_GPIOF_ENABLE_WAKE | MSM_GPIOF_DISABLE_WAKE)) { if (flags & MSM_GPIOF_ENABLE_WAKE) msm_chip->int_enable[1] |= b; else msm_chip->int_enable[1] &= ~b; } return 0; }