-/* protect what irq_chip modifies through its helper task */
-static DEFINE_SPINLOCK(gpio_spinlock);
-
-/* shadow the imr register; updates are delayed */
-static u32 gpio_imr_shadow;
-static bool gpio_pending_mask;
-
-/* bitmask of requests to set gpio irq trigger type */
-static unsigned int gpio_pending_trigger;
-
-/* pointer to helper thread */
-static struct task_struct *gpio_helper_thread;
-
-/*
- * Helper functions to read and write the GPIO ISR and IMR registers as
- * 32-bit integers. Functions return 0 on success, non-zero otherwise.
- * The caller must hold gpio_lock.
- */
-
-/* NOTE: only the IRQ dispatcher may read ISR; reading it has
- * side effects, because of the clear-on-read mechanism (COR=1).
- */
-static int gpio_read_isr(unsigned int *isr)
-{
- int ret;
-
- *isr = 0;
- ret = twl4030_i2c_read(TWL4030_MODULE_GPIO, (u8 *) isr,
- REG_GPIO_ISR1A, 3);
- le32_to_cpup(isr);
- *isr &= GPIO_32_MASK;
-
- return ret;
-}
-
-/* IMR is written only during initialization and
- * by request of the irq_chip code.
- */
-static int gpio_write_imr(unsigned int imr)
-{
- imr &= GPIO_32_MASK;
- /*
- * The buffer passed to the twl4030_i2c_write() routine must have an
- * extra byte at the beginning reserved for its internal use.
- */
- imr <<= 8;
- imr = cpu_to_le32(imr);
- return twl4030_i2c_write(TWL4030_MODULE_GPIO, (u8 *) &imr,
- REG_GPIO_IMR1A, 3);
-}
-
-/*
- * These are the irqchip methods for the TWL4030 GPIO interrupts.
- * Our IRQ handle method doesn't call these, but they will be called by
- * other routines such as setup_irq() and enable_irq(). They are called
- * with cpu interrupts disabled and with a lock on the irq_desc.lock
- * spinlock. This complicates matters, because accessing the TWL4030 GPIO
- * interrupt controller requires I2C bus transactions that can't be initiated
- * in this context. Our solution is to defer accessing the interrupt
- * controller to a kernel thread.
- */
-
-static void twl4030_gpio_irq_ack(unsigned int irq)
-{
- /* NOP -- dispatcher acks when it reads ISR */
-}
-
-static void twl4030_gpio_irq_mask(unsigned int irq)
-{
- int gpio = irq - twl4030_gpio_irq_base;
- u32 mask = 1 << gpio;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_spinlock, flags);
- gpio_pending_mask = true;
- gpio_imr_shadow |= mask;
- if (gpio_helper_thread && gpio_helper_thread->state != TASK_RUNNING)
- wake_up_process(gpio_helper_thread);
- spin_unlock_irqrestore(&gpio_spinlock, flags);
-}
-
-static void twl4030_gpio_irq_unmask(unsigned int irq)
-{
- int gpio = irq - twl4030_gpio_irq_base;
- u32 mask = 1 << gpio;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_spinlock, flags);
- gpio_pending_mask = true;
- gpio_imr_shadow &= ~mask;
- if (gpio_helper_thread && gpio_helper_thread->state != TASK_RUNNING)
- wake_up_process(gpio_helper_thread);
- spin_unlock_irqrestore(&gpio_spinlock, flags);
-}
-
-static int twl4030_gpio_irq_set_type(unsigned int irq, unsigned trigger)
-{
- struct irq_desc *desc = irq_desc + irq;
- int gpio = irq - twl4030_gpio_irq_base;
- unsigned long flags;
-
- trigger &= IRQ_TYPE_SENSE_MASK;
- if (trigger & ~IRQ_TYPE_EDGE_BOTH)
- return -EINVAL;
- if ((desc->status & IRQ_TYPE_SENSE_MASK) == trigger)
- return 0;
-
- desc->status &= ~IRQ_TYPE_SENSE_MASK;
- desc->status |= trigger;
-
- spin_lock_irqsave(&gpio_spinlock, flags);
- gpio_pending_trigger |= (1 << gpio);
- if (gpio_helper_thread && gpio_helper_thread->state != TASK_RUNNING)
- wake_up_process(gpio_helper_thread);
- spin_unlock_irqrestore(&gpio_spinlock, flags);
-
- return 0;
-}
-
-static struct irq_chip twl4030_gpio_irq_chip = {
- .name = "twl4030",
- .ack = twl4030_gpio_irq_ack,
- .mask = twl4030_gpio_irq_mask,
- .unmask = twl4030_gpio_irq_unmask,
- .set_type = twl4030_gpio_irq_set_type,
-};
-