[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 #include <asm/mach/time.h> 41 #include <asm/mach/irq.h> 42 43 static DEFINE_SPINLOCK(ixp2000_slowport_lock); 44 static unsigned long ixp2000_slowport_irq_flags; 45 ··· 181 182 /* clear timer 1 */ 183 ixp2000_reg_write(IXP2000_T1_CLR, 1); 184 - 185 while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { 186 timer_tick(regs); 187 next_jiffy_time -= ticks_per_jiffy; ··· 240 /************************************************************************* 241 * GPIO helpers 242 *************************************************************************/ 243 - static unsigned long GPIO_IRQ_rising_edge; 244 static unsigned long GPIO_IRQ_falling_edge; 245 static unsigned long GPIO_IRQ_level_low; 246 static unsigned long GPIO_IRQ_level_high; 247 248 - void gpio_line_config(int line, int style) 249 { 250 unsigned long flags; 251 252 local_irq_save(flags); 253 254 - if(style == GPIO_OUT) { 255 /* if it's an output, it ain't an interrupt anymore */ 256 - ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line)); 257 GPIO_IRQ_falling_edge &= ~(1 << line); 258 GPIO_IRQ_rising_edge &= ~(1 << line); 259 GPIO_IRQ_level_low &= ~(1 << line); 260 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)); 268 } 269 - 270 local_irq_restore(flags); 271 - } 272 273 274 /************************************************************************* ··· 292 } 293 } 294 295 static void ixp2000_GPIO_irq_mask_ack(unsigned int irq) 296 { 297 ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0))); 298 ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0))); 299 } 300 ··· 350 } 351 352 static struct irqchip ixp2000_GPIO_irq_chip = { 353 .ack = ixp2000_GPIO_irq_mask_ack, 354 .mask = ixp2000_GPIO_irq_mask, 355 .unmask = ixp2000_GPIO_irq_unmask ··· 387 388 static void ixp2000_irq_unmask(unsigned int irq) 389 { 390 - ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); 391 } 392 393 static struct irqchip ixp2000_irq_chip = { ··· 424 * our mask/unmask code much simpler. 425 */ 426 for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { 427 - if((1 << irq) & IXP2000_VALID_IRQ_MASK) { 428 set_irq_chip(irq, &ixp2000_irq_chip); 429 set_irq_handler(irq, do_level_IRQ); 430 set_irq_flags(irq, IRQF_VALID); 431 } else set_irq_flags(irq, 0); 432 } 433 - 434 /* 435 * GPIO IRQs are invalid until someone sets the interrupt mode 436 - * by calling gpio_line_set(); 437 */ 438 for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { 439 set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
··· 40 #include <asm/mach/time.h> 41 #include <asm/mach/irq.h> 42 43 + #include <asm/arch/gpio.h> 44 + 45 static DEFINE_SPINLOCK(ixp2000_slowport_lock); 46 static unsigned long ixp2000_slowport_irq_flags; 47 ··· 179 180 /* clear timer 1 */ 181 ixp2000_reg_write(IXP2000_T1_CLR, 1); 182 + 183 while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { 184 timer_tick(regs); 185 next_jiffy_time -= ticks_per_jiffy; ··· 238 /************************************************************************* 239 * GPIO helpers 240 *************************************************************************/ 241 static unsigned long GPIO_IRQ_falling_edge; 242 + static unsigned long GPIO_IRQ_rising_edge; 243 static unsigned long GPIO_IRQ_level_low; 244 static unsigned long GPIO_IRQ_level_high; 245 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) 255 { 256 unsigned long flags; 257 258 local_irq_save(flags); 259 + if (direction == GPIO_OUT) { 260 + irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0; 261 262 /* if it's an output, it ain't an interrupt anymore */ 263 GPIO_IRQ_falling_edge &= ~(1 << line); 264 GPIO_IRQ_rising_edge &= ~(1 << line); 265 GPIO_IRQ_level_low &= ~(1 << line); 266 GPIO_IRQ_level_high &= ~(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); 272 } 273 local_irq_restore(flags); 274 + } 275 276 277 /************************************************************************* ··· 285 } 286 } 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 + 326 static void ixp2000_GPIO_irq_mask_ack(unsigned int irq) 327 { 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))); 332 ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0))); 333 } 334 ··· 302 } 303 304 static struct irqchip ixp2000_GPIO_irq_chip = { 305 + .type = ixp2000_GPIO_irq_type, 306 .ack = ixp2000_GPIO_irq_mask_ack, 307 .mask = ixp2000_GPIO_irq_mask, 308 .unmask = ixp2000_GPIO_irq_unmask ··· 338 339 static void ixp2000_irq_unmask(unsigned int irq) 340 { 341 + ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); 342 } 343 344 static struct irqchip ixp2000_irq_chip = { ··· 375 * our mask/unmask code much simpler. 376 */ 377 for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { 378 + if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { 379 set_irq_chip(irq, &ixp2000_irq_chip); 380 set_irq_handler(irq, do_level_IRQ); 381 set_irq_flags(irq, IRQF_VALID); 382 } else set_irq_flags(irq, 0); 383 } 384 + 385 /* 386 * GPIO IRQs are invalid until someone sets the interrupt mode 387 + * by calling set_irq_type(). 388 */ 389 for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { 390 set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
+2 -1
drivers/i2c/busses/i2c-ixp2000.c
··· 33 #include <linux/i2c.h> 34 #include <linux/i2c-algo-bit.h> 35 36 - #include <asm/hardware.h> /* Pick up IXP42000-specific bits */ 37 38 static inline int ixp2000_scl_pin(void *data) 39 {
··· 33 #include <linux/i2c.h> 34 #include <linux/i2c-algo-bit.h> 35 36 + #include <asm/hardware.h> /* Pick up IXP2000-specific bits */ 37 + #include <asm/arch/gpio.h> 38 39 static inline int ixp2000_scl_pin(void *data) 40 {
+12 -19
include/asm-arm/arch-ixp2000/gpio.h
··· 1 /* 2 - * include/asm-arm/arch-ixp2000/ixp2000-gpio.h 3 * 4 * Copyright (C) 2002 Intel Corporation. 5 * ··· 16 * Use this instead of directly setting the GPIO registers. 17 * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb) 18 */ 19 - #ifndef _ASM_ARCH_IXP2000_GPIO_H_ 20 - #define _ASM_ARCH_IXP2000_GPIO_H_ 21 22 #ifndef __ASSEMBLY__ 23 - #define GPIO_OUT 0x0 24 - #define GPIO_IN 0x80 25 26 #define IXP2000_GPIO_LOW 0 27 #define IXP2000_GPIO_HIGH 1 28 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); 39 40 static inline int gpio_line_get(int line) 41 { ··· 37 static inline void gpio_line_set(int line, int value) 38 { 39 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)); 43 } 44 45 #endif /* !__ASSEMBLY__ */ 46 - #endif /* ASM_ARCH_IXP2000_GPIO_H_ */ 47
··· 1 /* 2 + * include/asm-arm/arch-ixp2000/gpio.h 3 * 4 * Copyright (C) 2002 Intel Corporation. 5 * ··· 16 * Use this instead of directly setting the GPIO registers. 17 * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb) 18 */ 19 + #ifndef __ASM_ARCH_GPIO_H 20 + #define __ASM_ARCH_GPIO_H 21 22 #ifndef __ASSEMBLY__ 23 + 24 + #define GPIO_IN 0 25 + #define GPIO_OUT 1 26 27 #define IXP2000_GPIO_LOW 0 28 #define IXP2000_GPIO_HIGH 1 29 30 + extern void gpio_line_config(int line, int direction); 31 32 static inline int gpio_line_get(int line) 33 { ··· 45 static inline void gpio_line_set(int line, int value) 46 { 47 if (value == IXP2000_GPIO_HIGH) { 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 + } 52 } 53 54 #endif /* !__ASSEMBLY__ */ 55 56 + #endif /* ASM_ARCH_IXP2000_GPIO_H_ */
+1 -21
include/asm-arm/arch-ixp2000/platform.h
··· 138 unsigned long (*bank_setup)(unsigned long); 139 }; 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 struct ixp2000_i2c_pins { 163 unsigned long sda_pin; 164 unsigned long scl_pin; 165 }; 166 167 #endif /* !__ASSEMBLY__ */
··· 138 unsigned long (*bank_setup)(unsigned long); 139 }; 140 141 struct ixp2000_i2c_pins { 142 unsigned long sda_pin; 143 unsigned long scl_pin; 144 }; 145 + 146 147 #endif /* !__ASSEMBLY__ */