[PATCH] ARM: 2744/1: ixp2000 gpio irq support

Patch from Lennert Buytenhek

This patch cleans up the ixp2000 gpio irq code and implements the
set_irq_type method for gpio irqs so that users can select for which
events (falling edge/rising edge/level low/level high) on the gpio
pin they want the corresponding gpio irq to be triggered.

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

authored by Lennert Buytenhek and committed by Russell King c4982887 c6b56949

+82 -59
+67 -18
arch/arm/mach-ixp2000/core.c
··· 40 40 #include <asm/mach/time.h> 41 41 #include <asm/mach/irq.h> 42 42 43 + #include <asm/arch/gpio.h> 44 + 43 45 static DEFINE_SPINLOCK(ixp2000_slowport_lock); 44 46 static unsigned long ixp2000_slowport_irq_flags; 45 47 ··· 181 179 182 180 /* clear timer 1 */ 183 181 ixp2000_reg_write(IXP2000_T1_CLR, 1); 184 - 182 + 185 183 while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { 186 184 timer_tick(regs); 187 185 next_jiffy_time -= ticks_per_jiffy; ··· 240 238 /************************************************************************* 241 239 * GPIO helpers 242 240 *************************************************************************/ 243 - static unsigned long GPIO_IRQ_rising_edge; 244 241 static unsigned long GPIO_IRQ_falling_edge; 242 + static unsigned long GPIO_IRQ_rising_edge; 245 243 static unsigned long GPIO_IRQ_level_low; 246 244 static unsigned long GPIO_IRQ_level_high; 247 245 248 - void gpio_line_config(int line, int style) 246 + static void update_gpio_int_csrs(void) 247 + { 248 + ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge); 249 + ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge); 250 + ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low); 251 + ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high); 252 + } 253 + 254 + void gpio_line_config(int line, int direction) 249 255 { 250 256 unsigned long flags; 251 257 252 258 local_irq_save(flags); 259 + if (direction == GPIO_OUT) { 260 + irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0; 253 261 254 - if(style == GPIO_OUT) { 255 262 /* if it's an output, it ain't an interrupt anymore */ 256 - ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line)); 257 263 GPIO_IRQ_falling_edge &= ~(1 << line); 258 264 GPIO_IRQ_rising_edge &= ~(1 << line); 259 265 GPIO_IRQ_level_low &= ~(1 << line); 260 266 GPIO_IRQ_level_high &= ~(1 << line); 261 - ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge); 262 - ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge); 263 - ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high); 264 - ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low); 265 - irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0; 266 - } else if(style == GPIO_IN) { 267 - ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line)); 267 + update_gpio_int_csrs(); 268 + 269 + ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line); 270 + } else if (direction == GPIO_IN) { 271 + ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line); 268 272 } 269 - 270 273 local_irq_restore(flags); 271 - } 274 + } 272 275 273 276 274 277 /************************************************************************* ··· 292 285 } 293 286 } 294 287 288 + static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type) 289 + { 290 + int line = irq - IRQ_IXP2000_GPIO0; 291 + 292 + /* 293 + * First, configure this GPIO line as an input. 294 + */ 295 + ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line); 296 + 297 + /* 298 + * Then, set the proper trigger type. 299 + */ 300 + if (type & IRQT_FALLING) 301 + GPIO_IRQ_falling_edge |= 1 << line; 302 + else 303 + GPIO_IRQ_falling_edge &= ~(1 << line); 304 + if (type & IRQT_RISING) 305 + GPIO_IRQ_rising_edge |= 1 << line; 306 + else 307 + GPIO_IRQ_rising_edge &= ~(1 << line); 308 + if (type & IRQT_LOW) 309 + GPIO_IRQ_level_low |= 1 << line; 310 + else 311 + GPIO_IRQ_level_low &= ~(1 << line); 312 + if (type & IRQT_HIGH) 313 + GPIO_IRQ_level_high |= 1 << line; 314 + else 315 + GPIO_IRQ_level_high &= ~(1 << line); 316 + update_gpio_int_csrs(); 317 + 318 + /* 319 + * Finally, mark the corresponding IRQ as valid. 320 + */ 321 + irq_desc[irq].valid = 1; 322 + 323 + return 0; 324 + } 325 + 295 326 static void ixp2000_GPIO_irq_mask_ack(unsigned int irq) 296 327 { 297 328 ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0))); 329 + 330 + ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); 331 + ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0))); 298 332 ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0))); 299 333 } 300 334 ··· 350 302 } 351 303 352 304 static struct irqchip ixp2000_GPIO_irq_chip = { 305 + .type = ixp2000_GPIO_irq_type, 353 306 .ack = ixp2000_GPIO_irq_mask_ack, 354 307 .mask = ixp2000_GPIO_irq_mask, 355 308 .unmask = ixp2000_GPIO_irq_unmask ··· 387 338 388 339 static void ixp2000_irq_unmask(unsigned int irq) 389 340 { 390 - ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); 341 + ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); 391 342 } 392 343 393 344 static struct irqchip ixp2000_irq_chip = { ··· 424 375 * our mask/unmask code much simpler. 425 376 */ 426 377 for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { 427 - if((1 << irq) & IXP2000_VALID_IRQ_MASK) { 378 + if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { 428 379 set_irq_chip(irq, &ixp2000_irq_chip); 429 380 set_irq_handler(irq, do_level_IRQ); 430 381 set_irq_flags(irq, IRQF_VALID); 431 382 } else set_irq_flags(irq, 0); 432 383 } 433 - 384 + 434 385 /* 435 386 * GPIO IRQs are invalid until someone sets the interrupt mode 436 - * by calling gpio_line_set(); 387 + * by calling set_irq_type(). 437 388 */ 438 389 for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { 439 390 set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
+2 -1
drivers/i2c/busses/i2c-ixp2000.c
··· 33 33 #include <linux/i2c.h> 34 34 #include <linux/i2c-algo-bit.h> 35 35 36 - #include <asm/hardware.h> /* Pick up IXP42000-specific bits */ 36 + #include <asm/hardware.h> /* Pick up IXP2000-specific bits */ 37 + #include <asm/arch/gpio.h> 37 38 38 39 static inline int ixp2000_scl_pin(void *data) 39 40 {
+12 -19
include/asm-arm/arch-ixp2000/gpio.h
··· 1 1 /* 2 - * include/asm-arm/arch-ixp2000/ixp2000-gpio.h 2 + * include/asm-arm/arch-ixp2000/gpio.h 3 3 * 4 4 * Copyright (C) 2002 Intel Corporation. 5 5 * ··· 16 16 * Use this instead of directly setting the GPIO registers. 17 17 * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb) 18 18 */ 19 - #ifndef _ASM_ARCH_IXP2000_GPIO_H_ 20 - #define _ASM_ARCH_IXP2000_GPIO_H_ 19 + #ifndef __ASM_ARCH_GPIO_H 20 + #define __ASM_ARCH_GPIO_H 21 21 22 22 #ifndef __ASSEMBLY__ 23 - #define GPIO_OUT 0x0 24 - #define GPIO_IN 0x80 23 + 24 + #define GPIO_IN 0 25 + #define GPIO_OUT 1 25 26 26 27 #define IXP2000_GPIO_LOW 0 27 28 #define IXP2000_GPIO_HIGH 1 28 29 29 - #define GPIO_NO_EDGES 0 30 - #define GPIO_FALLING_EDGE 1 31 - #define GPIO_RISING_EDGE 2 32 - #define GPIO_BOTH_EDGES 3 33 - #define GPIO_LEVEL_LOW 4 34 - #define GPIO_LEVEL_HIGH 8 35 - 36 - extern void set_GPIO_IRQ_edge(int gpio_nr, int edge); 37 - extern void set_GPIO_IRQ_level(int gpio_nr, int level); 38 - extern void gpio_line_config(int line, int style); 30 + extern void gpio_line_config(int line, int direction); 39 31 40 32 static inline int gpio_line_get(int line) 41 33 { ··· 37 45 static inline void gpio_line_set(int line, int value) 38 46 { 39 47 if (value == IXP2000_GPIO_HIGH) { 40 - ixp_reg_write(IXP2000_GPIO_POSR, BIT(line)); 41 - } else if (value == IXP2000_GPIO_LOW) 42 - ixp_reg_write(IXP2000_GPIO_POCR, BIT(line)); 48 + ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line); 49 + } else if (value == IXP2000_GPIO_LOW) { 50 + ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line); 51 + } 43 52 } 44 53 45 54 #endif /* !__ASSEMBLY__ */ 46 - #endif /* ASM_ARCH_IXP2000_GPIO_H_ */ 47 55 56 + #endif /* ASM_ARCH_IXP2000_GPIO_H_ */
+1 -21
include/asm-arm/arch-ixp2000/platform.h
··· 138 138 unsigned long (*bank_setup)(unsigned long); 139 139 }; 140 140 141 - /* 142 - * GPIO helper functions 143 - */ 144 - #define GPIO_IN 0 145 - #define GPIO_OUT 1 146 - 147 - extern void gpio_line_config(int line, int style); 148 - 149 - static inline int gpio_line_get(int line) 150 - { 151 - return (((*IXP2000_GPIO_PLR) >> line) & 1); 152 - } 153 - 154 - static inline void gpio_line_set(int line, int value) 155 - { 156 - if (value) 157 - ixp2000_reg_write(IXP2000_GPIO_POSR, (1 << line)); 158 - else 159 - ixp2000_reg_write(IXP2000_GPIO_POCR, (1 << line)); 160 - } 161 - 162 141 struct ixp2000_i2c_pins { 163 142 unsigned long sda_pin; 164 143 unsigned long scl_pin; 165 144 }; 145 + 166 146 167 147 #endif /* !__ASSEMBLY__ */