Commit 368d97d6 authored by Sergio Paracuellos's avatar Sergio Paracuellos Committed by Greg Kroah-Hartman

staging: mt7621-gpio: implement high level and low level irqs

This chip support high level and low level interrupts. Those
have to be implemented also to get a complete and clean driver.
Signed-off-by: default avatarSergio Paracuellos <sergio.paracuellos@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fe84f0c9
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
* @bank: gpio bank number for the chip * @bank: gpio bank number for the chip
* @rising: mask for rising irqs * @rising: mask for rising irqs
* @falling: mask for falling irqs * @falling: mask for falling irqs
* @hlevel: mask for high level irqs
* @llevel: mask for low level irqs
*/ */
struct mtk_gc { struct mtk_gc {
struct gpio_chip chip; struct gpio_chip chip;
...@@ -45,6 +47,8 @@ struct mtk_gc { ...@@ -45,6 +47,8 @@ struct mtk_gc {
int bank; int bank;
u32 rising; u32 rising;
u32 falling; u32 falling;
u32 hlevel;
u32 llevel;
}; };
/** /**
...@@ -184,7 +188,7 @@ mediatek_gpio_irq_unmask(struct irq_data *d) ...@@ -184,7 +188,7 @@ mediatek_gpio_irq_unmask(struct irq_data *d)
int bank = pin / MTK_BANK_WIDTH; int bank = pin / MTK_BANK_WIDTH;
struct mtk_gc *rg = &gpio_data->gc_map[bank]; struct mtk_gc *rg = &gpio_data->gc_map[bank];
unsigned long flags; unsigned long flags;
u32 rise, fall; u32 rise, fall, high, low;
if (!rg) if (!rg)
return; return;
...@@ -192,8 +196,12 @@ mediatek_gpio_irq_unmask(struct irq_data *d) ...@@ -192,8 +196,12 @@ mediatek_gpio_irq_unmask(struct irq_data *d)
spin_lock_irqsave(&rg->lock, flags); spin_lock_irqsave(&rg->lock, flags);
rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (PIN_MASK(pin) & rg->rising)); mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (PIN_MASK(pin) & rg->rising));
mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (PIN_MASK(pin) & rg->falling)); mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (PIN_MASK(pin) & rg->falling));
mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (PIN_MASK(pin) & rg->hlevel));
mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (PIN_MASK(pin) & rg->llevel));
spin_unlock_irqrestore(&rg->lock, flags); spin_unlock_irqrestore(&rg->lock, flags);
} }
...@@ -205,7 +213,7 @@ mediatek_gpio_irq_mask(struct irq_data *d) ...@@ -205,7 +213,7 @@ mediatek_gpio_irq_mask(struct irq_data *d)
int bank = pin / MTK_BANK_WIDTH; int bank = pin / MTK_BANK_WIDTH;
struct mtk_gc *rg = &gpio_data->gc_map[bank]; struct mtk_gc *rg = &gpio_data->gc_map[bank];
unsigned long flags; unsigned long flags;
u32 rise, fall; u32 rise, fall, high, low;
if (!rg) if (!rg)
return; return;
...@@ -213,8 +221,12 @@ mediatek_gpio_irq_mask(struct irq_data *d) ...@@ -213,8 +221,12 @@ mediatek_gpio_irq_mask(struct irq_data *d)
spin_lock_irqsave(&rg->lock, flags); spin_lock_irqsave(&rg->lock, flags);
rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
high = mtk_gpio_r32(rg, GPIO_REG_HLVL);
low = mtk_gpio_r32(rg, GPIO_REG_LLVL);
mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~PIN_MASK(pin)); mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~PIN_MASK(pin));
mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~PIN_MASK(pin)); mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~PIN_MASK(pin));
mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~PIN_MASK(pin));
mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~PIN_MASK(pin));
spin_unlock_irqrestore(&rg->lock, flags); spin_unlock_irqrestore(&rg->lock, flags);
} }
...@@ -231,21 +243,36 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) ...@@ -231,21 +243,36 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
return -1; return -1;
if (type == IRQ_TYPE_PROBE) { if (type == IRQ_TYPE_PROBE) {
if ((rg->rising | rg->falling) & mask) if ((rg->rising | rg->falling |
rg->hlevel | rg->llevel) & mask)
return 0; return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
} }
if (type & IRQ_TYPE_EDGE_RISING) rg->rising &= ~mask;
rg->rising |= mask; rg->falling &= ~mask;
else rg->hlevel &= ~mask;
rg->rising &= ~mask; rg->llevel &= ~mask;
if (type & IRQ_TYPE_EDGE_FALLING) switch (type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_BOTH:
rg->rising |= mask;
rg->falling |= mask; rg->falling |= mask;
else break;
rg->falling &= ~mask; case IRQ_TYPE_EDGE_RISING:
rg->rising |= mask;
break;
case IRQ_TYPE_EDGE_FALLING:
rg->falling |= mask;
break;
case IRQ_TYPE_LEVEL_HIGH:
rg->hlevel |= mask;
break;
case IRQ_TYPE_LEVEL_LOW:
rg->llevel |= mask;
break;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment