Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148982
b: refs/heads/master
c: 910862e
h: refs/heads/master
v: v3
  • Loading branch information
Guennadi Liakhovetski authored and Sascha Hauer committed May 7, 2009
1 parent ebaab87 commit b8fdbbc
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fde364742a1afec9e71e705e863d029295282fe5
refs/heads/master: 910862ec092c156023b8a6e726e8c793da0a03f7
49 changes: 48 additions & 1 deletion trunk/arch/arm/plat-mxc/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ static void gpio_unmask_irq(u32 irq)
_set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
}

static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);

static int gpio_set_irq_type(u32 irq, u32 type)
{
u32 gpio = irq_to_gpio(irq);
Expand All @@ -72,20 +74,32 @@ static int gpio_set_irq_type(u32 irq, u32 type)
int edge;
void __iomem *reg = port->base;

port->both_edges &= ~(1 << (gpio & 31));
switch (type) {
case IRQ_TYPE_EDGE_RISING:
edge = GPIO_INT_RISE_EDGE;
break;
case IRQ_TYPE_EDGE_FALLING:
edge = GPIO_INT_FALL_EDGE;
break;
case IRQ_TYPE_EDGE_BOTH:
val = mxc_gpio_get(&port->chip, gpio & 31);
if (val) {
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
} else {
edge = GPIO_INT_HIGH_LEV;
pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
}
port->both_edges |= 1 << (gpio & 31);
break;
case IRQ_TYPE_LEVEL_LOW:
edge = GPIO_INT_LOW_LEV;
break;
case IRQ_TYPE_LEVEL_HIGH:
edge = GPIO_INT_HIGH_LEV;
break;
default: /* this includes IRQ_TYPE_EDGE_BOTH */
default:
return -EINVAL;
}

Expand All @@ -98,18 +112,51 @@ static int gpio_set_irq_type(u32 irq, u32 type)
return 0;
}

static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
{
void __iomem *reg = port->base;
u32 bit, val;
int edge;

reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
bit = gpio & 0xf;
val = __raw_readl(reg);
edge = (val >> (bit << 1)) & 3;
val &= ~(0x3 << (bit << 1));
switch (edge) {
case GPIO_INT_HIGH_LEV:
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
break;
case GPIO_INT_LOW_LEV:
edge = GPIO_INT_HIGH_LEV;
pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
break;
default:
pr_err("mxc: invalid configuration for GPIO %d: %x\n",
gpio, edge);
return;
}
__raw_writel(val | (edge << (bit << 1)), reg);
}

/* handle n interrupts in one status register */
static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
{
u32 gpio_irq_no;

gpio_irq_no = port->virtual_irq_start;
for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
u32 gpio = irq_to_gpio(gpio_irq_no);

if ((irq_stat & 1) == 0)
continue;

BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));

if (port->both_edges & (1 << (gpio & 31)))
mxc_flip_edge(port, gpio);

irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
&irq_desc[gpio_irq_no]);
}
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/plat-mxc/include/mach/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct mxc_gpio_port {
int irq;
int virtual_irq_start;
struct gpio_chip chip;
u32 both_edges;
};

int mxc_gpio_init(struct mxc_gpio_port*, int);
Expand Down

0 comments on commit b8fdbbc

Please sign in to comment.