aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-mxc/gpio.c49
-rw-r--r--arch/arm/plat-mxc/include/mach/gpio.h1
2 files changed, 49 insertions, 1 deletions
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 89e95798cc3b..7506d963be4b 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -64,6 +64,8 @@ static void gpio_unmask_irq(u32 irq)
64 _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1); 64 _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
65} 65}
66 66
67static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
68
67static int gpio_set_irq_type(u32 irq, u32 type) 69static int gpio_set_irq_type(u32 irq, u32 type)
68{ 70{
69 u32 gpio = irq_to_gpio(irq); 71 u32 gpio = irq_to_gpio(irq);
@@ -72,6 +74,7 @@ static int gpio_set_irq_type(u32 irq, u32 type)
72 int edge; 74 int edge;
73 void __iomem *reg = port->base; 75 void __iomem *reg = port->base;
74 76
77 port->both_edges &= ~(1 << (gpio & 31));
75 switch (type) { 78 switch (type) {
76 case IRQ_TYPE_EDGE_RISING: 79 case IRQ_TYPE_EDGE_RISING:
77 edge = GPIO_INT_RISE_EDGE; 80 edge = GPIO_INT_RISE_EDGE;
@@ -79,13 +82,24 @@ static int gpio_set_irq_type(u32 irq, u32 type)
79 case IRQ_TYPE_EDGE_FALLING: 82 case IRQ_TYPE_EDGE_FALLING:
80 edge = GPIO_INT_FALL_EDGE; 83 edge = GPIO_INT_FALL_EDGE;
81 break; 84 break;
85 case IRQ_TYPE_EDGE_BOTH:
86 val = mxc_gpio_get(&port->chip, gpio & 31);
87 if (val) {
88 edge = GPIO_INT_LOW_LEV;
89 pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
90 } else {
91 edge = GPIO_INT_HIGH_LEV;
92 pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
93 }
94 port->both_edges |= 1 << (gpio & 31);
95 break;
82 case IRQ_TYPE_LEVEL_LOW: 96 case IRQ_TYPE_LEVEL_LOW:
83 edge = GPIO_INT_LOW_LEV; 97 edge = GPIO_INT_LOW_LEV;
84 break; 98 break;
85 case IRQ_TYPE_LEVEL_HIGH: 99 case IRQ_TYPE_LEVEL_HIGH:
86 edge = GPIO_INT_HIGH_LEV; 100 edge = GPIO_INT_HIGH_LEV;
87 break; 101 break;
88 default: /* this includes IRQ_TYPE_EDGE_BOTH */ 102 default:
89 return -EINVAL; 103 return -EINVAL;
90 } 104 }
91 105
@@ -98,6 +112,34 @@ static int gpio_set_irq_type(u32 irq, u32 type)
98 return 0; 112 return 0;
99} 113}
100 114
115static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
116{
117 void __iomem *reg = port->base;
118 u32 bit, val;
119 int edge;
120
121 reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
122 bit = gpio & 0xf;
123 val = __raw_readl(reg);
124 edge = (val >> (bit << 1)) & 3;
125 val &= ~(0x3 << (bit << 1));
126 switch (edge) {
127 case GPIO_INT_HIGH_LEV:
128 edge = GPIO_INT_LOW_LEV;
129 pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
130 break;
131 case GPIO_INT_LOW_LEV:
132 edge = GPIO_INT_HIGH_LEV;
133 pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
134 break;
135 default:
136 pr_err("mxc: invalid configuration for GPIO %d: %x\n",
137 gpio, edge);
138 return;
139 }
140 __raw_writel(val | (edge << (bit << 1)), reg);
141}
142
101/* handle n interrupts in one status register */ 143/* handle n interrupts in one status register */
102static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) 144static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
103{ 145{
@@ -105,11 +147,16 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
105 147
106 gpio_irq_no = port->virtual_irq_start; 148 gpio_irq_no = port->virtual_irq_start;
107 for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) { 149 for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
150 u32 gpio = irq_to_gpio(gpio_irq_no);
108 151
109 if ((irq_stat & 1) == 0) 152 if ((irq_stat & 1) == 0)
110 continue; 153 continue;
111 154
112 BUG_ON(!(irq_desc[gpio_irq_no].handle_irq)); 155 BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
156
157 if (port->both_edges & (1 << (gpio & 31)))
158 mxc_flip_edge(port, gpio);
159
113 irq_desc[gpio_irq_no].handle_irq(gpio_irq_no, 160 irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
114 &irq_desc[gpio_irq_no]); 161 &irq_desc[gpio_irq_no]);
115 } 162 }
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index ea509f1090fb..894d2f87c856 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -35,6 +35,7 @@ struct mxc_gpio_port {
35 int irq; 35 int irq;
36 int virtual_irq_start; 36 int virtual_irq_start;
37 struct gpio_chip chip; 37 struct gpio_chip chip;
38 u32 both_edges;
38}; 39};
39 40
40int mxc_gpio_init(struct mxc_gpio_port*, int); 41int mxc_gpio_init(struct mxc_gpio_port*, int);