Commit 4932e397be71370b95f555f87d3b424d2b5ca57b

Authored by Lennert Buytenhek
Committed by Russell King
1 parent fac105d05e

[ARM] 4122/1: ep93xx: add support for GPIO port F interrupts

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Showing 3 changed files with 73 additions and 30 deletions Side-by-side Diff

arch/arm/mach-ep93xx/core.c
... ... @@ -152,22 +152,29 @@
152 152 /*************************************************************************
153 153 * GPIO handling for EP93xx
154 154 *************************************************************************/
155   -static unsigned char gpio_int_enable[2];
156   -static unsigned char gpio_int_type1[2];
157   -static unsigned char gpio_int_type2[2];
  155 +static unsigned char gpio_int_enable[3];
  156 +static unsigned char gpio_int_type1[3];
  157 +static unsigned char gpio_int_type2[3];
158 158  
159   -static void update_gpio_ab_int_params(int port)
  159 +static void update_gpio_int_params(int abf)
160 160 {
161   - if (port == 0) {
  161 + if (abf == 0) {
162 162 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
163 163 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
164 164 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
165 165 __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
166   - } else if (port == 1) {
  166 + } else if (abf == 1) {
167 167 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
168 168 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
169 169 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
170 170 __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
  171 + } else if (abf == 2) {
  172 + __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
  173 + __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
  174 + __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
  175 + __raw_writeb(gpio_int_enable[2], EP93XX_GPIO_F_INT_ENABLE);
  176 + } else {
  177 + BUG();
171 178 }
172 179 }
173 180  
174 181  
... ... @@ -192,8 +199,13 @@
192 199 local_irq_save(flags);
193 200 if (direction == GPIO_OUT) {
194 201 if (line >= 0 && line < 16) {
  202 + /* Port A/B. */
195 203 gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
196   - update_gpio_ab_int_params(line >> 3);
  204 + update_gpio_int_params(line >> 3);
  205 + } else if (line >= 40 && line < 48) {
  206 + /* Port F. */
  207 + gpio_int_enable[2] &= ~(1 << (line & 7));
  208 + update_gpio_int_params(2);
197 209 }
198 210  
199 211 v = __raw_readb(data_direction_register);
... ... @@ -244,8 +256,7 @@
244 256 /*************************************************************************
245 257 * EP93xx IRQ handling
246 258 *************************************************************************/
247   -static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
248   - struct irq_desc *desc)
  259 +static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
249 260 {
250 261 unsigned char status;
251 262 int i;
252 263  
253 264  
254 265  
255 266  
256 267  
257 268  
258 269  
259 270  
... ... @@ -267,37 +278,46 @@
267 278 }
268 279 }
269 280  
270   -static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq)
  281 +static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
271 282 {
  283 + int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
  284 +
  285 + desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
  286 +}
  287 +
  288 +static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
  289 +{
272 290 int line = irq - IRQ_EP93XX_GPIO(0);
273 291 int port = line >> 3;
274 292  
275 293 gpio_int_enable[port] &= ~(1 << (line & 7));
276   - update_gpio_ab_int_params(port);
  294 + update_gpio_int_params(port);
277 295  
278   - if (line >> 3) {
279   - __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
280   - } else {
  296 + if (port == 0) {
281 297 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
  298 + } else if (port == 1) {
  299 + __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
  300 + } else if (port == 2) {
  301 + __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
282 302 }
283 303 }
284 304  
285   -static void ep93xx_gpio_ab_irq_mask(unsigned int irq)
  305 +static void ep93xx_gpio_irq_mask(unsigned int irq)
286 306 {
287 307 int line = irq - IRQ_EP93XX_GPIO(0);
288 308 int port = line >> 3;
289 309  
290 310 gpio_int_enable[port] &= ~(1 << (line & 7));
291   - update_gpio_ab_int_params(port);
  311 + update_gpio_int_params(port);
292 312 }
293 313  
294   -static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
  314 +static void ep93xx_gpio_irq_unmask(unsigned int irq)
295 315 {
296 316 int line = irq - IRQ_EP93XX_GPIO(0);
297 317 int port = line >> 3;
298 318  
299 319 gpio_int_enable[port] |= 1 << (line & 7);
300   - update_gpio_ab_int_params(port);
  320 + update_gpio_int_params(port);
301 321 }
302 322  
303 323  
304 324  
... ... @@ -306,13 +326,17 @@
306 326 * edge (1) triggered, while gpio_int_type2 controls whether it
307 327 * triggers on low/falling (0) or high/rising (1).
308 328 */
309   -static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
  329 +static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
310 330 {
311 331 int port;
312 332 int line;
313 333  
314 334 line = irq - IRQ_EP93XX_GPIO(0);
315   - gpio_line_config(line, GPIO_IN);
  335 + if (line >= 0 && line < 16) {
  336 + gpio_line_config(line, GPIO_IN);
  337 + } else {
  338 + gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
  339 + }
316 340  
317 341 port = line >> 3;
318 342 line &= 7;
319 343  
... ... @@ -330,16 +354,17 @@
330 354 gpio_int_type1[port] &= ~(1 << line);
331 355 gpio_int_type2[port] &= ~(1 << line);
332 356 }
333   - update_gpio_ab_int_params(port);
  357 + update_gpio_int_params(port);
334 358  
335 359 return 0;
336 360 }
337 361  
338   -static struct irq_chip ep93xx_gpio_ab_irq_chip = {
339   - .ack = ep93xx_gpio_ab_irq_mask_ack,
340   - .mask = ep93xx_gpio_ab_irq_mask,
341   - .unmask = ep93xx_gpio_ab_irq_unmask,
342   - .set_type = ep93xx_gpio_ab_irq_type,
  362 +static struct irq_chip ep93xx_gpio_irq_chip = {
  363 + .name = "GPIO",
  364 + .ack = ep93xx_gpio_irq_mask_ack,
  365 + .mask = ep93xx_gpio_irq_mask,
  366 + .unmask = ep93xx_gpio_irq_unmask,
  367 + .set_type = ep93xx_gpio_irq_type,
343 368 };
344 369  
345 370  
346 371  
347 372  
... ... @@ -350,12 +375,21 @@
350 375 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
351 376 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
352 377  
353   - for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) {
354   - set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip);
  378 + for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
  379 + set_irq_chip(irq, &ep93xx_gpio_irq_chip);
355 380 set_irq_handler(irq, handle_level_irq);
356 381 set_irq_flags(irq, IRQF_VALID);
357 382 }
  383 +
358 384 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
  385 + set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
  386 + set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
  387 + set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
  388 + set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
  389 + set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
  390 + set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
  391 + set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
  392 + set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
359 393 }
360 394  
361 395  
include/asm-arm/arch-ep93xx/ep93xx-regs.h
... ... @@ -73,6 +73,11 @@
73 73  
74 74 #define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000)
75 75 #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
  76 +#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c)
  77 +#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50)
  78 +#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54)
  79 +#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58)
  80 +#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
76 81 #define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90)
77 82 #define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94)
78 83 #define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98)
include/asm-arm/arch-ep93xx/irqs.h
... ... @@ -67,9 +67,13 @@
67 67 #define IRQ_EP93XX_SAI 60
68 68 #define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
69 69  
70   -#define IRQ_EP93XX_GPIO(x) (64 + (x))
  70 +/*
  71 + * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
  72 + * F0..F7 to 80..87.
  73 + */
  74 +#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
71 75  
72   -#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16)
  76 +#define NR_EP93XX_IRQS (64 + 24)
73 77  
74 78 #define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
75 79 #define EP93XX_BOARD_IRQS 32