blob: 72811a3b915837652c246ce0b0f0c390129eae43 [file] [log] [blame]
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001/*
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01002 * Support functions for OMAP GPIO
3 *
Tony Lindgren92105bb2005-09-07 17:20:26 +01004 * Copyright (C) 2003-2005 Nokia Corporation
Jan Engelhardt96de0e22007-10-19 23:21:04 +02005 * Written by Juha Yrjölä <juha.yrjola@nokia.com>
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01006 *
Santosh Shilimkar44169072009-05-28 14:16:04 -07007 * Copyright (C) 2009 Texas Instruments
8 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
9 *
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010015#include <linux/init.h>
16#include <linux/module.h>
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010017#include <linux/interrupt.h>
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +020018#include <linux/syscore_ops.h>
Tony Lindgren92105bb2005-09-07 17:20:26 +010019#include <linux/err.h>
Russell Kingf8ce2542006-01-07 16:15:52 +000020#include <linux/clk.h>
Russell Kingfced80c2008-09-06 12:10:45 +010021#include <linux/io.h>
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -080022#include <linux/slab.h>
23#include <linux/pm_runtime.h>
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010024
Russell Kinga09e64f2008-08-05 16:14:15 +010025#include <mach/hardware.h>
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010026#include <asm/irq.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010027#include <mach/irqs.h>
28#include <mach/gpio.h>
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010029#include <asm/mach/irq.h>
30
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010031struct gpio_bank {
Tony Lindgren9f7065d2009-10-19 15:25:20 -070032 unsigned long pbase;
Tony Lindgren92105bb2005-09-07 17:20:26 +010033 void __iomem *base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010034 u16 irq;
35 u16 virtual_irq_start;
Tony Lindgren92105bb2005-09-07 17:20:26 +010036 int method;
Tony Lindgren140455f2010-02-12 12:26:48 -080037#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
Tony Lindgren92105bb2005-09-07 17:20:26 +010038 u32 suspend_wakeup;
39 u32 saved_wakeup;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -080040#endif
Juha Yrjola3ac4fa92006-12-06 17:13:52 -080041 u32 non_wakeup_gpios;
42 u32 enabled_non_wakeup_gpios;
43
44 u32 saved_datain;
45 u32 saved_fallingdetect;
46 u32 saved_risingdetect;
Kevin Hilmanb144ff62008-01-16 21:56:15 -080047 u32 level_mask;
Cory Maccarrone4318f362010-01-08 10:29:04 -080048 u32 toggle_mask;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010049 spinlock_t lock;
David Brownell52e31342008-03-03 12:43:23 -080050 struct gpio_chip chip;
Jouni Hogander89db9482008-12-10 17:35:24 -080051 struct clk *dbck;
Charulatha V058af1e2009-11-22 10:11:25 -080052 u32 mod_usage;
Kevin Hilman8865b9b2009-01-27 11:15:34 -080053 u32 dbck_enable_mask;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -080054 struct device *dev;
55 bool dbck_flag;
Tony Lindgren5de62b82010-12-07 16:26:58 -080056 int stride;
Kevin Hilmand5f46242011-04-21 09:23:00 -070057 u32 width;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010058};
59
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -080060#ifdef CONFIG_ARCH_OMAP3
Rajendra Nayak40c670f2008-09-26 17:47:48 +053061struct omap3_gpio_regs {
Rajendra Nayak40c670f2008-09-26 17:47:48 +053062 u32 irqenable1;
63 u32 irqenable2;
64 u32 wake_en;
65 u32 ctrl;
66 u32 oe;
67 u32 leveldetect0;
68 u32 leveldetect1;
69 u32 risingdetect;
70 u32 fallingdetect;
71 u32 dataout;
Rajendra Nayak40c670f2008-09-26 17:47:48 +053072};
73
74static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -080075#endif
76
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -080077/*
78 * TODO: Cleanup gpio_bank usage as it is having information
79 * related to all instances of the device
80 */
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010081static struct gpio_bank *gpio_bank;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -080082
Varadarajan, Charulathac95d10b2010-12-07 16:26:56 -080083/* TODO: Analyze removing gpio_bank_count usage from driver code */
84int gpio_bank_count;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010085
Kevin Hilman129fd222011-04-22 07:59:07 -070086#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
87#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
88
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010089static inline struct gpio_bank *get_gpio_bank(int gpio)
90{
Tony Lindgren6e60e792006-04-02 17:46:23 +010091 if (cpu_is_omap15xx()) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010092 if (OMAP_GPIO_IS_MPUIO(gpio))
93 return &gpio_bank[0];
94 return &gpio_bank[1];
95 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010096 if (cpu_is_omap16xx()) {
97 if (OMAP_GPIO_IS_MPUIO(gpio))
98 return &gpio_bank[0];
99 return &gpio_bank[1 + (gpio >> 4)];
100 }
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700101 if (cpu_is_omap7xx()) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100102 if (OMAP_GPIO_IS_MPUIO(gpio))
103 return &gpio_bank[0];
104 return &gpio_bank[1 + (gpio >> 5)];
105 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100106 if (cpu_is_omap24xx())
107 return &gpio_bank[gpio >> 5];
Santosh Shilimkar44169072009-05-28 14:16:04 -0700108 if (cpu_is_omap34xx() || cpu_is_omap44xx())
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800109 return &gpio_bank[gpio >> 5];
David Brownelle031ab22008-12-10 17:35:27 -0800110 BUG();
111 return NULL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100112}
113
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100114static inline int gpio_valid(int gpio)
115{
116 if (gpio < 0)
117 return -1;
Tony Lindgrend11ac972008-01-12 15:35:04 -0800118 if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
Jonathan McDowell193e68b2006-09-25 12:41:30 +0300119 if (gpio >= OMAP_MAX_GPIO_LINES + 16)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100120 return -1;
121 return 0;
122 }
Tony Lindgren6e60e792006-04-02 17:46:23 +0100123 if (cpu_is_omap15xx() && gpio < 16)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100124 return 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100125 if ((cpu_is_omap16xx()) && gpio < 64)
126 return 0;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700127 if (cpu_is_omap7xx() && gpio < 192)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100128 return 0;
Tony Lindgren25d6f632010-08-02 14:21:39 +0300129 if (cpu_is_omap2420() && gpio < 128)
130 return 0;
131 if (cpu_is_omap2430() && gpio < 160)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100132 return 0;
Santosh Shilimkar44169072009-05-28 14:16:04 -0700133 if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800134 return 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100135 return -1;
136}
137
138static int check_gpio(int gpio)
139{
Roel Kluind32b20f2009-11-17 14:39:03 -0800140 if (unlikely(gpio_valid(gpio) < 0)) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100141 printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
142 dump_stack();
143 return -1;
144 }
145 return 0;
146}
147
148static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
149{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100150 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100151 u32 l;
152
153 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800154#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100155 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800156 reg += OMAP_MPUIO_IO_CNTL / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100157 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800158#endif
159#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100160 case METHOD_GPIO_1510:
161 reg += OMAP1510_GPIO_DIR_CONTROL;
162 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800163#endif
164#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100165 case METHOD_GPIO_1610:
166 reg += OMAP1610_GPIO_DIRECTION;
167 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800168#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100169#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100170 case METHOD_GPIO_7XX:
171 reg += OMAP7XX_GPIO_DIR_CONTROL;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700172 break;
173#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800174#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100175 case METHOD_GPIO_24XX:
176 reg += OMAP24XX_GPIO_OE;
177 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800178#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530179#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800180 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530181 reg += OMAP4_GPIO_OE;
182 break;
183#endif
David Brownelle5c56ed2006-12-06 17:13:59 -0800184 default:
185 WARN_ON(1);
186 return;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100187 }
188 l = __raw_readl(reg);
189 if (is_input)
190 l |= 1 << gpio;
191 else
192 l &= ~(1 << gpio);
193 __raw_writel(l, reg);
194}
195
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100196static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
197{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100198 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100199 u32 l = 0;
200
201 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800202#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100203 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800204 reg += OMAP_MPUIO_OUTPUT / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100205 l = __raw_readl(reg);
206 if (enable)
207 l |= 1 << gpio;
208 else
209 l &= ~(1 << gpio);
210 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800211#endif
212#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100213 case METHOD_GPIO_1510:
214 reg += OMAP1510_GPIO_DATA_OUTPUT;
215 l = __raw_readl(reg);
216 if (enable)
217 l |= 1 << gpio;
218 else
219 l &= ~(1 << gpio);
220 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800221#endif
222#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100223 case METHOD_GPIO_1610:
224 if (enable)
225 reg += OMAP1610_GPIO_SET_DATAOUT;
226 else
227 reg += OMAP1610_GPIO_CLEAR_DATAOUT;
228 l = 1 << gpio;
229 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800230#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100231#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100232 case METHOD_GPIO_7XX:
233 reg += OMAP7XX_GPIO_DATA_OUTPUT;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700234 l = __raw_readl(reg);
235 if (enable)
236 l |= 1 << gpio;
237 else
238 l &= ~(1 << gpio);
239 break;
240#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800241#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100242 case METHOD_GPIO_24XX:
243 if (enable)
244 reg += OMAP24XX_GPIO_SETDATAOUT;
245 else
246 reg += OMAP24XX_GPIO_CLEARDATAOUT;
247 l = 1 << gpio;
248 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800249#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530250#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800251 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530252 if (enable)
253 reg += OMAP4_GPIO_SETDATAOUT;
254 else
255 reg += OMAP4_GPIO_CLEARDATAOUT;
256 l = 1 << gpio;
257 break;
258#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100259 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800260 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100261 return;
262 }
263 __raw_writel(l, reg);
264}
265
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300266static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100267{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100268 void __iomem *reg;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100269
270 if (check_gpio(gpio) < 0)
David Brownelle5c56ed2006-12-06 17:13:59 -0800271 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100272 reg = bank->base;
273 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800274#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100275 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800276 reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100277 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800278#endif
279#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100280 case METHOD_GPIO_1510:
281 reg += OMAP1510_GPIO_DATA_INPUT;
282 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800283#endif
284#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100285 case METHOD_GPIO_1610:
286 reg += OMAP1610_GPIO_DATAIN;
287 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800288#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100289#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100290 case METHOD_GPIO_7XX:
291 reg += OMAP7XX_GPIO_DATA_INPUT;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700292 break;
293#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800294#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100295 case METHOD_GPIO_24XX:
296 reg += OMAP24XX_GPIO_DATAIN;
297 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800298#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530299#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800300 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530301 reg += OMAP4_GPIO_DATAIN;
302 break;
303#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100304 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800305 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100306 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100307 return (__raw_readl(reg)
Kevin Hilman129fd222011-04-22 07:59:07 -0700308 & (GPIO_BIT(bank, gpio))) != 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100309}
310
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300311static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
312{
313 void __iomem *reg;
314
315 if (check_gpio(gpio) < 0)
316 return -EINVAL;
317 reg = bank->base;
318
319 switch (bank->method) {
320#ifdef CONFIG_ARCH_OMAP1
321 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800322 reg += OMAP_MPUIO_OUTPUT / bank->stride;
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300323 break;
324#endif
325#ifdef CONFIG_ARCH_OMAP15XX
326 case METHOD_GPIO_1510:
327 reg += OMAP1510_GPIO_DATA_OUTPUT;
328 break;
329#endif
330#ifdef CONFIG_ARCH_OMAP16XX
331 case METHOD_GPIO_1610:
332 reg += OMAP1610_GPIO_DATAOUT;
333 break;
334#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100335#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100336 case METHOD_GPIO_7XX:
337 reg += OMAP7XX_GPIO_DATA_OUTPUT;
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300338 break;
339#endif
Charulatha V9f096862010-05-14 12:05:27 -0700340#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300341 case METHOD_GPIO_24XX:
342 reg += OMAP24XX_GPIO_DATAOUT;
343 break;
344#endif
Charulatha V9f096862010-05-14 12:05:27 -0700345#ifdef CONFIG_ARCH_OMAP4
346 case METHOD_GPIO_44XX:
347 reg += OMAP4_GPIO_DATAOUT;
348 break;
349#endif
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300350 default:
351 return -EINVAL;
352 }
353
Kevin Hilman129fd222011-04-22 07:59:07 -0700354 return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300355}
356
Tony Lindgren92105bb2005-09-07 17:20:26 +0100357#define MOD_REG_BIT(reg, bit_mask, set) \
358do { \
359 int l = __raw_readl(base + reg); \
360 if (set) l |= bit_mask; \
361 else l &= ~bit_mask; \
362 __raw_writel(l, base + reg); \
363} while(0)
364
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700365/**
366 * _set_gpio_debounce - low level gpio debounce time
367 * @bank: the gpio bank we're acting upon
368 * @gpio: the gpio number on this @gpio
369 * @debounce: debounce time to use
370 *
371 * OMAP's debounce time is in 31us steps so we need
372 * to convert and round up to the closest unit.
373 */
374static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
375 unsigned debounce)
376{
377 void __iomem *reg = bank->base;
378 u32 val;
379 u32 l;
380
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800381 if (!bank->dbck_flag)
382 return;
383
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700384 if (debounce < 32)
385 debounce = 0x01;
386 else if (debounce > 7936)
387 debounce = 0xff;
388 else
389 debounce = (debounce / 0x1f) - 1;
390
Kevin Hilman129fd222011-04-22 07:59:07 -0700391 l = GPIO_BIT(bank, gpio);
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700392
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800393 if (bank->method == METHOD_GPIO_44XX)
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700394 reg += OMAP4_GPIO_DEBOUNCINGTIME;
395 else
396 reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
397
398 __raw_writel(debounce, reg);
399
400 reg = bank->base;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800401 if (bank->method == METHOD_GPIO_44XX)
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700402 reg += OMAP4_GPIO_DEBOUNCENABLE;
403 else
404 reg += OMAP24XX_GPIO_DEBOUNCE_EN;
405
406 val = __raw_readl(reg);
407
408 if (debounce) {
409 val |= l;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800410 clk_enable(bank->dbck);
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700411 } else {
412 val &= ~l;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800413 clk_disable(bank->dbck);
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700414 }
Kevin Hilmanf7ec0b02010-06-09 13:53:07 +0300415 bank->dbck_enable_mask = val;
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700416
417 __raw_writel(val, reg);
418}
419
Tony Lindgren140455f2010-02-12 12:26:48 -0800420#ifdef CONFIG_ARCH_OMAP2PLUS
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700421static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
422 int trigger)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100423{
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800424 void __iomem *base = bank->base;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100425 u32 gpio_bit = 1 << gpio;
426
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530427 if (cpu_is_omap44xx()) {
428 MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
429 trigger & IRQ_TYPE_LEVEL_LOW);
430 MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
431 trigger & IRQ_TYPE_LEVEL_HIGH);
432 MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
433 trigger & IRQ_TYPE_EDGE_RISING);
434 MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
435 trigger & IRQ_TYPE_EDGE_FALLING);
436 } else {
437 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
438 trigger & IRQ_TYPE_LEVEL_LOW);
439 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
440 trigger & IRQ_TYPE_LEVEL_HIGH);
441 MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
442 trigger & IRQ_TYPE_EDGE_RISING);
443 MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
444 trigger & IRQ_TYPE_EDGE_FALLING);
445 }
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800446 if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530447 if (cpu_is_omap44xx()) {
Colin Cross0622b252011-06-06 13:38:17 -0700448 MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
449 trigger != 0);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530450 } else {
Chunqiu Wang699117a62009-06-24 17:13:39 +0000451 /*
452 * GPIO wakeup request can only be generated on edge
453 * transitions
454 */
455 if (trigger & IRQ_TYPE_EDGE_BOTH)
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530456 __raw_writel(1 << gpio, bank->base
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700457 + OMAP24XX_GPIO_SETWKUENA);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530458 else
459 __raw_writel(1 << gpio, bank->base
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700460 + OMAP24XX_GPIO_CLEARWKUENA);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530461 }
Tero Kristoa118b5f2008-12-22 14:27:12 +0200462 }
463 /* This part needs to be executed always for OMAP34xx */
464 if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
Chunqiu Wang699117a62009-06-24 17:13:39 +0000465 /*
466 * Log the edge gpio and manually trigger the IRQ
467 * after resume if the input level changes
468 * to avoid irq lost during PER RET/OFF mode
469 * Applies for omap2 non-wakeup gpio and all omap3 gpios
470 */
471 if (trigger & IRQ_TYPE_EDGE_BOTH)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800472 bank->enabled_non_wakeup_gpios |= gpio_bit;
473 else
474 bank->enabled_non_wakeup_gpios &= ~gpio_bit;
475 }
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700476
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530477 if (cpu_is_omap44xx()) {
478 bank->level_mask =
479 __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) |
480 __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1);
481 } else {
482 bank->level_mask =
483 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
484 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
485 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100486}
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800487#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +0100488
Uwe Kleine-König9198bcd2010-01-29 14:20:05 -0800489#ifdef CONFIG_ARCH_OMAP1
Cory Maccarrone4318f362010-01-08 10:29:04 -0800490/*
491 * This only applies to chips that can't do both rising and falling edge
492 * detection at once. For all other chips, this function is a noop.
493 */
494static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
495{
496 void __iomem *reg = bank->base;
497 u32 l = 0;
498
499 switch (bank->method) {
Cory Maccarrone4318f362010-01-08 10:29:04 -0800500 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800501 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
Cory Maccarrone4318f362010-01-08 10:29:04 -0800502 break;
Cory Maccarrone4318f362010-01-08 10:29:04 -0800503#ifdef CONFIG_ARCH_OMAP15XX
504 case METHOD_GPIO_1510:
505 reg += OMAP1510_GPIO_INT_CONTROL;
506 break;
507#endif
508#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
509 case METHOD_GPIO_7XX:
510 reg += OMAP7XX_GPIO_INT_CONTROL;
511 break;
512#endif
513 default:
514 return;
515 }
516
517 l = __raw_readl(reg);
518 if ((l >> gpio) & 1)
519 l &= ~(1 << gpio);
520 else
521 l |= 1 << gpio;
522
523 __raw_writel(l, reg);
524}
Uwe Kleine-König9198bcd2010-01-29 14:20:05 -0800525#endif
Cory Maccarrone4318f362010-01-08 10:29:04 -0800526
Tony Lindgren92105bb2005-09-07 17:20:26 +0100527static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
528{
529 void __iomem *reg = bank->base;
530 u32 l = 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100531
532 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800533#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100534 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800535 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100536 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000537 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800538 bank->toggle_mask |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100539 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100540 l |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100541 else if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100542 l &= ~(1 << gpio);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100543 else
544 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100545 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800546#endif
547#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100548 case METHOD_GPIO_1510:
549 reg += OMAP1510_GPIO_INT_CONTROL;
550 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000551 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800552 bank->toggle_mask |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100553 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100554 l |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100555 else if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100556 l &= ~(1 << gpio);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100557 else
558 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100559 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800560#endif
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800561#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100562 case METHOD_GPIO_1610:
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100563 if (gpio & 0x08)
564 reg += OMAP1610_GPIO_EDGE_CTRL2;
565 else
566 reg += OMAP1610_GPIO_EDGE_CTRL1;
567 gpio &= 0x07;
568 l = __raw_readl(reg);
569 l &= ~(3 << (gpio << 1));
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100570 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100571 l |= 2 << (gpio << 1);
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100572 if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100573 l |= 1 << (gpio << 1);
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800574 if (trigger)
575 /* Enable wake-up during idle for dynamic tick */
576 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);
577 else
578 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100579 break;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800580#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100581#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100582 case METHOD_GPIO_7XX:
583 reg += OMAP7XX_GPIO_INT_CONTROL;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700584 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000585 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800586 bank->toggle_mask |= 1 << gpio;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700587 if (trigger & IRQ_TYPE_EDGE_RISING)
588 l |= 1 << gpio;
589 else if (trigger & IRQ_TYPE_EDGE_FALLING)
590 l &= ~(1 << gpio);
591 else
592 goto bad;
593 break;
594#endif
Tony Lindgren140455f2010-02-12 12:26:48 -0800595#ifdef CONFIG_ARCH_OMAP2PLUS
Tony Lindgren92105bb2005-09-07 17:20:26 +0100596 case METHOD_GPIO_24XX:
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800597 case METHOD_GPIO_44XX:
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800598 set_24xx_gpio_triggering(bank, gpio, trigger);
Mika Westerbergf7c5cc42010-12-29 13:01:31 +0200599 return 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800600#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100601 default:
Tony Lindgren92105bb2005-09-07 17:20:26 +0100602 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100603 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100604 __raw_writel(l, reg);
605 return 0;
606bad:
607 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100608}
609
Lennert Buytenheke9191022010-11-29 11:17:17 +0100610static int gpio_irq_type(struct irq_data *d, unsigned type)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100611{
612 struct gpio_bank *bank;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100613 unsigned gpio;
614 int retval;
David Brownella6472532008-03-03 04:33:30 -0800615 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100616
Lennert Buytenheke9191022010-11-29 11:17:17 +0100617 if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
618 gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100619 else
Lennert Buytenheke9191022010-11-29 11:17:17 +0100620 gpio = d->irq - IH_GPIO_BASE;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100621
622 if (check_gpio(gpio) < 0)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100623 return -EINVAL;
624
David Brownelle5c56ed2006-12-06 17:13:59 -0800625 if (type & ~IRQ_TYPE_SENSE_MASK)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100626 return -EINVAL;
David Brownelle5c56ed2006-12-06 17:13:59 -0800627
628 /* OMAP1 allows only only edge triggering */
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800629 if (!cpu_class_is_omap2()
David Brownelle5c56ed2006-12-06 17:13:59 -0800630 && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
Tony Lindgren92105bb2005-09-07 17:20:26 +0100631 return -EINVAL;
632
Lennert Buytenheke9191022010-11-29 11:17:17 +0100633 bank = irq_data_get_irq_chip_data(d);
David Brownella6472532008-03-03 04:33:30 -0800634 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilman129fd222011-04-22 07:59:07 -0700635 retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
David Brownella6472532008-03-03 04:33:30 -0800636 spin_unlock_irqrestore(&bank->lock, flags);
Kevin Hilman672e3022008-01-16 21:56:16 -0800637
638 if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100639 __irq_set_handler_locked(d->irq, handle_level_irq);
Kevin Hilman672e3022008-01-16 21:56:16 -0800640 else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100641 __irq_set_handler_locked(d->irq, handle_edge_irq);
Kevin Hilman672e3022008-01-16 21:56:16 -0800642
Tony Lindgren92105bb2005-09-07 17:20:26 +0100643 return retval;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100644}
645
646static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
647{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100648 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100649
650 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800651#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100652 case METHOD_GPIO_1510:
653 reg += OMAP1510_GPIO_INT_STATUS;
654 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800655#endif
656#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100657 case METHOD_GPIO_1610:
658 reg += OMAP1610_GPIO_IRQSTATUS1;
659 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800660#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100661#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100662 case METHOD_GPIO_7XX:
663 reg += OMAP7XX_GPIO_INT_STATUS;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700664 break;
665#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800666#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100667 case METHOD_GPIO_24XX:
668 reg += OMAP24XX_GPIO_IRQSTATUS1;
669 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800670#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530671#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800672 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530673 reg += OMAP4_GPIO_IRQSTATUS0;
674 break;
675#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100676 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800677 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100678 return;
679 }
680 __raw_writel(gpio_mask, reg);
Hiroshi DOYUbee79302006-09-25 12:41:46 +0300681
682 /* Workaround for clearing DSP GPIO interrupts to allow retention */
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800683 if (cpu_is_omap24xx() || cpu_is_omap34xx())
684 reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
685 else if (cpu_is_omap44xx())
686 reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
687
Kevin Hilmandf3c8512011-04-21 09:08:15 -0700688 if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx())
Roger Quadrosbedfd152009-04-23 11:10:50 -0700689 __raw_writel(gpio_mask, reg);
690
691 /* Flush posted write for the irq status to avoid spurious interrupts */
692 __raw_readl(reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100693}
694
695static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
696{
Kevin Hilman129fd222011-04-22 07:59:07 -0700697 _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100698}
699
Imre Deakea6dedd2006-06-26 16:16:00 -0700700static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
701{
702 void __iomem *reg = bank->base;
Imre Deak99c47702006-06-26 16:16:07 -0700703 int inv = 0;
704 u32 l;
Kevin Hilmanc390aad02011-04-21 09:33:36 -0700705 u32 mask = (1 << bank->width) - 1;
Imre Deakea6dedd2006-06-26 16:16:00 -0700706
707 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800708#ifdef CONFIG_ARCH_OMAP1
Imre Deakea6dedd2006-06-26 16:16:00 -0700709 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800710 reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
Imre Deak99c47702006-06-26 16:16:07 -0700711 inv = 1;
Imre Deakea6dedd2006-06-26 16:16:00 -0700712 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800713#endif
714#ifdef CONFIG_ARCH_OMAP15XX
Imre Deakea6dedd2006-06-26 16:16:00 -0700715 case METHOD_GPIO_1510:
716 reg += OMAP1510_GPIO_INT_MASK;
Imre Deak99c47702006-06-26 16:16:07 -0700717 inv = 1;
Imre Deakea6dedd2006-06-26 16:16:00 -0700718 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800719#endif
720#ifdef CONFIG_ARCH_OMAP16XX
Imre Deakea6dedd2006-06-26 16:16:00 -0700721 case METHOD_GPIO_1610:
722 reg += OMAP1610_GPIO_IRQENABLE1;
723 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800724#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100725#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100726 case METHOD_GPIO_7XX:
727 reg += OMAP7XX_GPIO_INT_MASK;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700728 inv = 1;
729 break;
730#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800731#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Imre Deakea6dedd2006-06-26 16:16:00 -0700732 case METHOD_GPIO_24XX:
733 reg += OMAP24XX_GPIO_IRQENABLE1;
734 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800735#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530736#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800737 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530738 reg += OMAP4_GPIO_IRQSTATUSSET0;
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530739 break;
740#endif
Imre Deakea6dedd2006-06-26 16:16:00 -0700741 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800742 WARN_ON(1);
Imre Deakea6dedd2006-06-26 16:16:00 -0700743 return 0;
744 }
745
Imre Deak99c47702006-06-26 16:16:07 -0700746 l = __raw_readl(reg);
747 if (inv)
748 l = ~l;
749 l &= mask;
750 return l;
Imre Deakea6dedd2006-06-26 16:16:00 -0700751}
752
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100753static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
754{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100755 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100756 u32 l;
757
758 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800759#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100760 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800761 reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100762 l = __raw_readl(reg);
763 if (enable)
764 l &= ~(gpio_mask);
765 else
766 l |= gpio_mask;
767 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800768#endif
769#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100770 case METHOD_GPIO_1510:
771 reg += OMAP1510_GPIO_INT_MASK;
772 l = __raw_readl(reg);
773 if (enable)
774 l &= ~(gpio_mask);
775 else
776 l |= gpio_mask;
777 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800778#endif
779#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100780 case METHOD_GPIO_1610:
781 if (enable)
782 reg += OMAP1610_GPIO_SET_IRQENABLE1;
783 else
784 reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
785 l = gpio_mask;
786 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800787#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100788#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100789 case METHOD_GPIO_7XX:
790 reg += OMAP7XX_GPIO_INT_MASK;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700791 l = __raw_readl(reg);
792 if (enable)
793 l &= ~(gpio_mask);
794 else
795 l |= gpio_mask;
796 break;
797#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800798#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100799 case METHOD_GPIO_24XX:
800 if (enable)
801 reg += OMAP24XX_GPIO_SETIRQENABLE1;
802 else
803 reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
804 l = gpio_mask;
805 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800806#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530807#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800808 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530809 if (enable)
810 reg += OMAP4_GPIO_IRQSTATUSSET0;
811 else
812 reg += OMAP4_GPIO_IRQSTATUSCLR0;
813 l = gpio_mask;
814 break;
815#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100816 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800817 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100818 return;
819 }
820 __raw_writel(l, reg);
821}
822
823static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
824{
Kevin Hilman129fd222011-04-22 07:59:07 -0700825 _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio), enable);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100826}
827
Tony Lindgren92105bb2005-09-07 17:20:26 +0100828/*
829 * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
830 * 1510 does not seem to have a wake-up register. If JTAG is connected
831 * to the target, system will wake up always on GPIO events. While
832 * system is running all registered GPIO interrupts need to have wake-up
833 * enabled. When system is suspended, only selected GPIO interrupts need
834 * to have wake-up enabled.
835 */
836static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
837{
Tony Lindgren4cc64202010-01-08 10:29:05 -0800838 unsigned long uninitialized_var(flags);
David Brownella6472532008-03-03 04:33:30 -0800839
Tony Lindgren92105bb2005-09-07 17:20:26 +0100840 switch (bank->method) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800841#ifdef CONFIG_ARCH_OMAP16XX
David Brownell11a78b72006-12-06 17:14:11 -0800842 case METHOD_MPUIO:
Tony Lindgren92105bb2005-09-07 17:20:26 +0100843 case METHOD_GPIO_1610:
David Brownella6472532008-03-03 04:33:30 -0800844 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700845 if (enable)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100846 bank->suspend_wakeup |= (1 << gpio);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700847 else
Tony Lindgren92105bb2005-09-07 17:20:26 +0100848 bank->suspend_wakeup &= ~(1 << gpio);
David Brownella6472532008-03-03 04:33:30 -0800849 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100850 return 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800851#endif
Tony Lindgren140455f2010-02-12 12:26:48 -0800852#ifdef CONFIG_ARCH_OMAP2PLUS
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800853 case METHOD_GPIO_24XX:
Tony Lindgren3f1686a92010-02-15 09:27:25 -0800854 case METHOD_GPIO_44XX:
David Brownell11a78b72006-12-06 17:14:11 -0800855 if (bank->non_wakeup_gpios & (1 << gpio)) {
856 printk(KERN_ERR "Unable to modify wakeup on "
857 "non-wakeup GPIO%d\n",
Kevin Hilmand5f46242011-04-21 09:23:00 -0700858 (bank - gpio_bank) * bank->width + gpio);
David Brownell11a78b72006-12-06 17:14:11 -0800859 return -EINVAL;
860 }
David Brownella6472532008-03-03 04:33:30 -0800861 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700862 if (enable)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800863 bank->suspend_wakeup |= (1 << gpio);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700864 else
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800865 bank->suspend_wakeup &= ~(1 << gpio);
David Brownella6472532008-03-03 04:33:30 -0800866 spin_unlock_irqrestore(&bank->lock, flags);
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800867 return 0;
868#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +0100869 default:
870 printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
871 bank->method);
872 return -EINVAL;
873 }
874}
875
Tony Lindgren4196dd62006-09-25 12:41:38 +0300876static void _reset_gpio(struct gpio_bank *bank, int gpio)
877{
Kevin Hilman129fd222011-04-22 07:59:07 -0700878 _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
Tony Lindgren4196dd62006-09-25 12:41:38 +0300879 _set_gpio_irqenable(bank, gpio, 0);
880 _clear_gpio_irqstatus(bank, gpio);
Kevin Hilman129fd222011-04-22 07:59:07 -0700881 _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
Tony Lindgren4196dd62006-09-25 12:41:38 +0300882}
883
Tony Lindgren92105bb2005-09-07 17:20:26 +0100884/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
Lennert Buytenheke9191022010-11-29 11:17:17 +0100885static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100886{
Lennert Buytenheke9191022010-11-29 11:17:17 +0100887 unsigned int gpio = d->irq - IH_GPIO_BASE;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100888 struct gpio_bank *bank;
889 int retval;
890
891 if (check_gpio(gpio) < 0)
892 return -ENODEV;
Lennert Buytenheke9191022010-11-29 11:17:17 +0100893 bank = irq_data_get_irq_chip_data(d);
Kevin Hilman129fd222011-04-22 07:59:07 -0700894 retval = _set_gpio_wakeup(bank, GPIO_INDEX(bank, gpio), enable);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100895
896 return retval;
897}
898
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800899static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100900{
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800901 struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
David Brownella6472532008-03-03 04:33:30 -0800902 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100903
David Brownella6472532008-03-03 04:33:30 -0800904 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100905
Tony Lindgren4196dd62006-09-25 12:41:38 +0300906 /* Set trigger to none. You need to enable the desired trigger with
907 * request_irq() or set_irq_type().
908 */
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800909 _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100910
Tony Lindgren1a8bfa12005-11-10 14:26:50 +0000911#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100912 if (bank->method == METHOD_GPIO_1510) {
Tony Lindgren92105bb2005-09-07 17:20:26 +0100913 void __iomem *reg;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100914
Tony Lindgren92105bb2005-09-07 17:20:26 +0100915 /* Claim the pin for MPU */
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100916 reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800917 __raw_writel(__raw_readl(reg) | (1 << offset), reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100918 }
919#endif
Charulatha V058af1e2009-11-22 10:11:25 -0800920 if (!cpu_class_is_omap1()) {
921 if (!bank->mod_usage) {
Charulatha V9f096862010-05-14 12:05:27 -0700922 void __iomem *reg = bank->base;
Charulatha V058af1e2009-11-22 10:11:25 -0800923 u32 ctrl;
Charulatha V9f096862010-05-14 12:05:27 -0700924
925 if (cpu_is_omap24xx() || cpu_is_omap34xx())
926 reg += OMAP24XX_GPIO_CTRL;
927 else if (cpu_is_omap44xx())
928 reg += OMAP4_GPIO_CTRL;
929 ctrl = __raw_readl(reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800930 /* Module is enabled, clocks are not gated */
Charulatha V9f096862010-05-14 12:05:27 -0700931 ctrl &= 0xFFFFFFFE;
932 __raw_writel(ctrl, reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800933 }
934 bank->mod_usage |= 1 << offset;
935 }
David Brownella6472532008-03-03 04:33:30 -0800936 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100937
938 return 0;
939}
940
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800941static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100942{
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800943 struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
David Brownella6472532008-03-03 04:33:30 -0800944 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100945
David Brownella6472532008-03-03 04:33:30 -0800946 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100947#ifdef CONFIG_ARCH_OMAP16XX
948 if (bank->method == METHOD_GPIO_1610) {
949 /* Disable wake-up during idle for dynamic tick */
950 void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800951 __raw_writel(1 << offset, reg);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100952 }
953#endif
Charulatha V9f096862010-05-14 12:05:27 -0700954#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
955 if (bank->method == METHOD_GPIO_24XX) {
Tony Lindgren92105bb2005-09-07 17:20:26 +0100956 /* Disable wake-up during idle for dynamic tick */
957 void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800958 __raw_writel(1 << offset, reg);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100959 }
960#endif
Charulatha V9f096862010-05-14 12:05:27 -0700961#ifdef CONFIG_ARCH_OMAP4
962 if (bank->method == METHOD_GPIO_44XX) {
963 /* Disable wake-up during idle for dynamic tick */
964 void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
965 __raw_writel(1 << offset, reg);
966 }
967#endif
Charulatha V058af1e2009-11-22 10:11:25 -0800968 if (!cpu_class_is_omap1()) {
969 bank->mod_usage &= ~(1 << offset);
970 if (!bank->mod_usage) {
Charulatha V9f096862010-05-14 12:05:27 -0700971 void __iomem *reg = bank->base;
Charulatha V058af1e2009-11-22 10:11:25 -0800972 u32 ctrl;
Charulatha V9f096862010-05-14 12:05:27 -0700973
974 if (cpu_is_omap24xx() || cpu_is_omap34xx())
975 reg += OMAP24XX_GPIO_CTRL;
976 else if (cpu_is_omap44xx())
977 reg += OMAP4_GPIO_CTRL;
978 ctrl = __raw_readl(reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800979 /* Module is disabled, clocks are gated */
980 ctrl |= 1;
Charulatha V9f096862010-05-14 12:05:27 -0700981 __raw_writel(ctrl, reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800982 }
983 }
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800984 _reset_gpio(bank, bank->chip.base + offset);
David Brownella6472532008-03-03 04:33:30 -0800985 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100986}
987
988/*
989 * We need to unmask the GPIO bank interrupt as soon as possible to
990 * avoid missing GPIO interrupts for other lines in the bank.
991 * Then we need to mask-read-clear-unmask the triggered GPIO lines
992 * in the bank to avoid missing nested interrupts for a GPIO line.
993 * If we wait to unmask individual GPIO lines in the bank after the
994 * line's interrupt handler has been run, we may miss some nested
995 * interrupts.
996 */
Russell King10dd5ce2006-11-23 11:41:32 +0000997static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100998{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100999 void __iomem *isr_reg = NULL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001000 u32 isr;
Cory Maccarrone4318f362010-01-08 10:29:04 -08001001 unsigned int gpio_irq, gpio_index;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001002 struct gpio_bank *bank;
Imre Deakea6dedd2006-06-26 16:16:00 -07001003 u32 retrigger = 0;
1004 int unmasked = 0;
Will Deaconee144182011-02-21 13:46:08 +00001005 struct irq_chip *chip = irq_desc_get_chip(desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001006
Will Deaconee144182011-02-21 13:46:08 +00001007 chained_irq_enter(chip, desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001008
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001009 bank = irq_get_handler_data(irq);
David Brownelle5c56ed2006-12-06 17:13:59 -08001010#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001011 if (bank->method == METHOD_MPUIO)
Tony Lindgren5de62b82010-12-07 16:26:58 -08001012 isr_reg = bank->base +
1013 OMAP_MPUIO_GPIO_INT / bank->stride;
David Brownelle5c56ed2006-12-06 17:13:59 -08001014#endif
Tony Lindgren1a8bfa12005-11-10 14:26:50 +00001015#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001016 if (bank->method == METHOD_GPIO_1510)
1017 isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
1018#endif
1019#if defined(CONFIG_ARCH_OMAP16XX)
1020 if (bank->method == METHOD_GPIO_1610)
1021 isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
1022#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +01001023#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +01001024 if (bank->method == METHOD_GPIO_7XX)
1025 isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
Zebediah C. McClure56739a62009-03-23 18:07:40 -07001026#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001027#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001028 if (bank->method == METHOD_GPIO_24XX)
1029 isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
1030#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301031#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001032 if (bank->method == METHOD_GPIO_44XX)
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301033 isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
1034#endif
Evgeny Kuznetsovb1cc4c52010-12-07 16:25:40 -08001035
1036 if (WARN_ON(!isr_reg))
1037 goto exit;
1038
Tony Lindgren92105bb2005-09-07 17:20:26 +01001039 while(1) {
Tony Lindgren6e60e792006-04-02 17:46:23 +01001040 u32 isr_saved, level_mask = 0;
Imre Deakea6dedd2006-06-26 16:16:00 -07001041 u32 enabled;
Tony Lindgren6e60e792006-04-02 17:46:23 +01001042
Imre Deakea6dedd2006-06-26 16:16:00 -07001043 enabled = _get_gpio_irqbank_mask(bank);
1044 isr_saved = isr = __raw_readl(isr_reg) & enabled;
Tony Lindgren6e60e792006-04-02 17:46:23 +01001045
1046 if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
1047 isr &= 0x0000ffff;
1048
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001049 if (cpu_class_is_omap2()) {
Kevin Hilmanb144ff62008-01-16 21:56:15 -08001050 level_mask = bank->level_mask & enabled;
Imre Deakea6dedd2006-06-26 16:16:00 -07001051 }
Tony Lindgren6e60e792006-04-02 17:46:23 +01001052
1053 /* clear edge sensitive interrupts before handler(s) are
1054 called so that we don't miss any interrupt occurred while
1055 executing them */
1056 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
1057 _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
1058 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
1059
1060 /* if there is only edge sensitive GPIO pin interrupts
1061 configured, we could unmask GPIO bank interrupt immediately */
Imre Deakea6dedd2006-06-26 16:16:00 -07001062 if (!level_mask && !unmasked) {
1063 unmasked = 1;
Will Deaconee144182011-02-21 13:46:08 +00001064 chained_irq_exit(chip, desc);
Imre Deakea6dedd2006-06-26 16:16:00 -07001065 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001066
Imre Deakea6dedd2006-06-26 16:16:00 -07001067 isr |= retrigger;
1068 retrigger = 0;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001069 if (!isr)
1070 break;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001071
Tony Lindgren92105bb2005-09-07 17:20:26 +01001072 gpio_irq = bank->virtual_irq_start;
1073 for (; isr != 0; isr >>= 1, gpio_irq++) {
Kevin Hilman129fd222011-04-22 07:59:07 -07001074 gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
Cory Maccarrone4318f362010-01-08 10:29:04 -08001075
Tony Lindgren92105bb2005-09-07 17:20:26 +01001076 if (!(isr & 1))
1077 continue;
Thomas Gleixner29454dd2006-07-03 02:22:22 +02001078
Cory Maccarrone4318f362010-01-08 10:29:04 -08001079#ifdef CONFIG_ARCH_OMAP1
1080 /*
1081 * Some chips can't respond to both rising and falling
1082 * at the same time. If this irq was requested with
1083 * both flags, we need to flip the ICR data for the IRQ
1084 * to respond to the IRQ for the opposite direction.
1085 * This will be indicated in the bank toggle_mask.
1086 */
1087 if (bank->toggle_mask & (1 << gpio_index))
1088 _toggle_gpio_edge_triggering(bank, gpio_index);
1089#endif
1090
Dmitry Baryshkovd8aa0252008-10-09 13:36:24 +01001091 generic_handle_irq(gpio_irq);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001092 }
Tony Lindgren1a8bfa12005-11-10 14:26:50 +00001093 }
Imre Deakea6dedd2006-06-26 16:16:00 -07001094 /* if bank has any level sensitive GPIO pin interrupt
1095 configured, we must unmask the bank interrupt only after
1096 handler(s) are executed in order to avoid spurious bank
1097 interrupt */
Evgeny Kuznetsovb1cc4c52010-12-07 16:25:40 -08001098exit:
Imre Deakea6dedd2006-06-26 16:16:00 -07001099 if (!unmasked)
Will Deaconee144182011-02-21 13:46:08 +00001100 chained_irq_exit(chip, desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001101}
1102
Lennert Buytenheke9191022010-11-29 11:17:17 +01001103static void gpio_irq_shutdown(struct irq_data *d)
Tony Lindgren4196dd62006-09-25 12:41:38 +03001104{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001105 unsigned int gpio = d->irq - IH_GPIO_BASE;
1106 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001107 unsigned long flags;
Tony Lindgren4196dd62006-09-25 12:41:38 +03001108
Colin Cross85ec7b92011-06-06 13:38:18 -07001109 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren4196dd62006-09-25 12:41:38 +03001110 _reset_gpio(bank, gpio);
Colin Cross85ec7b92011-06-06 13:38:18 -07001111 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren4196dd62006-09-25 12:41:38 +03001112}
1113
Lennert Buytenheke9191022010-11-29 11:17:17 +01001114static void gpio_ack_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001115{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001116 unsigned int gpio = d->irq - IH_GPIO_BASE;
1117 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001118
1119 _clear_gpio_irqstatus(bank, gpio);
1120}
1121
Lennert Buytenheke9191022010-11-29 11:17:17 +01001122static void gpio_mask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001123{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001124 unsigned int gpio = d->irq - IH_GPIO_BASE;
1125 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001126 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001127
Colin Cross85ec7b92011-06-06 13:38:18 -07001128 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001129 _set_gpio_irqenable(bank, gpio, 0);
Kevin Hilman129fd222011-04-22 07:59:07 -07001130 _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
Colin Cross85ec7b92011-06-06 13:38:18 -07001131 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001132}
1133
Lennert Buytenheke9191022010-11-29 11:17:17 +01001134static void gpio_unmask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001135{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001136 unsigned int gpio = d->irq - IH_GPIO_BASE;
1137 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Kevin Hilman129fd222011-04-22 07:59:07 -07001138 unsigned int irq_mask = GPIO_BIT(bank, gpio);
Thomas Gleixner8c04a172011-03-24 12:40:15 +01001139 u32 trigger = irqd_get_trigger_type(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001140 unsigned long flags;
Kevin Hilman55b60192009-06-04 15:57:10 -07001141
Colin Cross85ec7b92011-06-06 13:38:18 -07001142 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilman55b60192009-06-04 15:57:10 -07001143 if (trigger)
Kevin Hilman129fd222011-04-22 07:59:07 -07001144 _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
Kevin Hilmanb144ff62008-01-16 21:56:15 -08001145
1146 /* For level-triggered GPIOs, the clearing must be done after
1147 * the HW source is cleared, thus after the handler has run */
1148 if (bank->level_mask & irq_mask) {
1149 _set_gpio_irqenable(bank, gpio, 0);
1150 _clear_gpio_irqstatus(bank, gpio);
1151 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001152
Kevin Hilman4de8c752008-01-16 21:56:14 -08001153 _set_gpio_irqenable(bank, gpio, 1);
Colin Cross85ec7b92011-06-06 13:38:18 -07001154 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001155}
1156
David Brownelle5c56ed2006-12-06 17:13:59 -08001157static struct irq_chip gpio_irq_chip = {
1158 .name = "GPIO",
Lennert Buytenheke9191022010-11-29 11:17:17 +01001159 .irq_shutdown = gpio_irq_shutdown,
1160 .irq_ack = gpio_ack_irq,
1161 .irq_mask = gpio_mask_irq,
1162 .irq_unmask = gpio_unmask_irq,
1163 .irq_set_type = gpio_irq_type,
1164 .irq_set_wake = gpio_wake_enable,
David Brownelle5c56ed2006-12-06 17:13:59 -08001165};
1166
1167/*---------------------------------------------------------------------*/
1168
1169#ifdef CONFIG_ARCH_OMAP1
1170
1171/* MPUIO uses the always-on 32k clock */
1172
Lennert Buytenheke9191022010-11-29 11:17:17 +01001173static void mpuio_ack_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001174{
1175 /* The ISR is reset automatically, so do nothing here. */
1176}
1177
Lennert Buytenheke9191022010-11-29 11:17:17 +01001178static void mpuio_mask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001179{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001180 unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
1181 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001182
1183 _set_gpio_irqenable(bank, gpio, 0);
1184}
1185
Lennert Buytenheke9191022010-11-29 11:17:17 +01001186static void mpuio_unmask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001187{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001188 unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
1189 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001190
1191 _set_gpio_irqenable(bank, gpio, 1);
1192}
1193
David Brownelle5c56ed2006-12-06 17:13:59 -08001194static struct irq_chip mpuio_irq_chip = {
1195 .name = "MPUIO",
Lennert Buytenheke9191022010-11-29 11:17:17 +01001196 .irq_ack = mpuio_ack_irq,
1197 .irq_mask = mpuio_mask_irq,
1198 .irq_unmask = mpuio_unmask_irq,
1199 .irq_set_type = gpio_irq_type,
David Brownell11a78b72006-12-06 17:14:11 -08001200#ifdef CONFIG_ARCH_OMAP16XX
1201 /* REVISIT: assuming only 16xx supports MPUIO wake events */
Lennert Buytenheke9191022010-11-29 11:17:17 +01001202 .irq_set_wake = gpio_wake_enable,
David Brownell11a78b72006-12-06 17:14:11 -08001203#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001204};
1205
David Brownelle5c56ed2006-12-06 17:13:59 -08001206
1207#define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO)
1208
David Brownell11a78b72006-12-06 17:14:11 -08001209
1210#ifdef CONFIG_ARCH_OMAP16XX
1211
1212#include <linux/platform_device.h>
1213
Magnus Damm79ee0312009-07-08 13:22:04 +02001214static int omap_mpuio_suspend_noirq(struct device *dev)
David Brownell11a78b72006-12-06 17:14:11 -08001215{
Magnus Damm79ee0312009-07-08 13:22:04 +02001216 struct platform_device *pdev = to_platform_device(dev);
David Brownell11a78b72006-12-06 17:14:11 -08001217 struct gpio_bank *bank = platform_get_drvdata(pdev);
Tony Lindgren5de62b82010-12-07 16:26:58 -08001218 void __iomem *mask_reg = bank->base +
1219 OMAP_MPUIO_GPIO_MASKIT / bank->stride;
David Brownella6472532008-03-03 04:33:30 -08001220 unsigned long flags;
David Brownell11a78b72006-12-06 17:14:11 -08001221
David Brownella6472532008-03-03 04:33:30 -08001222 spin_lock_irqsave(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001223 bank->saved_wakeup = __raw_readl(mask_reg);
1224 __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
David Brownella6472532008-03-03 04:33:30 -08001225 spin_unlock_irqrestore(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001226
1227 return 0;
1228}
1229
Magnus Damm79ee0312009-07-08 13:22:04 +02001230static int omap_mpuio_resume_noirq(struct device *dev)
David Brownell11a78b72006-12-06 17:14:11 -08001231{
Magnus Damm79ee0312009-07-08 13:22:04 +02001232 struct platform_device *pdev = to_platform_device(dev);
David Brownell11a78b72006-12-06 17:14:11 -08001233 struct gpio_bank *bank = platform_get_drvdata(pdev);
Tony Lindgren5de62b82010-12-07 16:26:58 -08001234 void __iomem *mask_reg = bank->base +
1235 OMAP_MPUIO_GPIO_MASKIT / bank->stride;
David Brownella6472532008-03-03 04:33:30 -08001236 unsigned long flags;
David Brownell11a78b72006-12-06 17:14:11 -08001237
David Brownella6472532008-03-03 04:33:30 -08001238 spin_lock_irqsave(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001239 __raw_writel(bank->saved_wakeup, mask_reg);
David Brownella6472532008-03-03 04:33:30 -08001240 spin_unlock_irqrestore(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001241
1242 return 0;
1243}
1244
Alexey Dobriyan47145212009-12-14 18:00:08 -08001245static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
Magnus Damm79ee0312009-07-08 13:22:04 +02001246 .suspend_noirq = omap_mpuio_suspend_noirq,
1247 .resume_noirq = omap_mpuio_resume_noirq,
1248};
1249
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001250/* use platform_driver for this. */
David Brownell11a78b72006-12-06 17:14:11 -08001251static struct platform_driver omap_mpuio_driver = {
David Brownell11a78b72006-12-06 17:14:11 -08001252 .driver = {
1253 .name = "mpuio",
Magnus Damm79ee0312009-07-08 13:22:04 +02001254 .pm = &omap_mpuio_dev_pm_ops,
David Brownell11a78b72006-12-06 17:14:11 -08001255 },
1256};
1257
1258static struct platform_device omap_mpuio_device = {
1259 .name = "mpuio",
1260 .id = -1,
1261 .dev = {
1262 .driver = &omap_mpuio_driver.driver,
1263 }
1264 /* could list the /proc/iomem resources */
1265};
1266
1267static inline void mpuio_init(void)
1268{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001269 struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
1270 platform_set_drvdata(&omap_mpuio_device, bank);
David Brownellfcf126d2007-04-02 12:46:47 -07001271
David Brownell11a78b72006-12-06 17:14:11 -08001272 if (platform_driver_register(&omap_mpuio_driver) == 0)
1273 (void) platform_device_register(&omap_mpuio_device);
1274}
1275
1276#else
1277static inline void mpuio_init(void) {}
1278#endif /* 16xx */
1279
David Brownelle5c56ed2006-12-06 17:13:59 -08001280#else
1281
1282extern struct irq_chip mpuio_irq_chip;
1283
1284#define bank_is_mpuio(bank) 0
David Brownell11a78b72006-12-06 17:14:11 -08001285static inline void mpuio_init(void) {}
David Brownelle5c56ed2006-12-06 17:13:59 -08001286
1287#endif
1288
1289/*---------------------------------------------------------------------*/
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001290
David Brownell52e31342008-03-03 12:43:23 -08001291/* REVISIT these are stupid implementations! replace by ones that
1292 * don't switch on METHOD_* and which mostly avoid spinlocks
1293 */
1294
1295static int gpio_input(struct gpio_chip *chip, unsigned offset)
1296{
1297 struct gpio_bank *bank;
1298 unsigned long flags;
1299
1300 bank = container_of(chip, struct gpio_bank, chip);
1301 spin_lock_irqsave(&bank->lock, flags);
1302 _set_gpio_direction(bank, offset, 1);
1303 spin_unlock_irqrestore(&bank->lock, flags);
1304 return 0;
1305}
1306
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001307static int gpio_is_input(struct gpio_bank *bank, int mask)
1308{
1309 void __iomem *reg = bank->base;
1310
1311 switch (bank->method) {
1312 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -08001313 reg += OMAP_MPUIO_IO_CNTL / bank->stride;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001314 break;
1315 case METHOD_GPIO_1510:
1316 reg += OMAP1510_GPIO_DIR_CONTROL;
1317 break;
1318 case METHOD_GPIO_1610:
1319 reg += OMAP1610_GPIO_DIRECTION;
1320 break;
Alistair Buxton7c006922009-09-22 10:02:58 +01001321 case METHOD_GPIO_7XX:
1322 reg += OMAP7XX_GPIO_DIR_CONTROL;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001323 break;
1324 case METHOD_GPIO_24XX:
1325 reg += OMAP24XX_GPIO_OE;
1326 break;
Charulatha V9f096862010-05-14 12:05:27 -07001327 case METHOD_GPIO_44XX:
1328 reg += OMAP4_GPIO_OE;
1329 break;
1330 default:
1331 WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
1332 return -EINVAL;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001333 }
1334 return __raw_readl(reg) & mask;
1335}
1336
David Brownell52e31342008-03-03 12:43:23 -08001337static int gpio_get(struct gpio_chip *chip, unsigned offset)
1338{
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001339 struct gpio_bank *bank;
1340 void __iomem *reg;
1341 int gpio;
1342 u32 mask;
1343
1344 gpio = chip->base + offset;
1345 bank = get_gpio_bank(gpio);
1346 reg = bank->base;
Kevin Hilman129fd222011-04-22 07:59:07 -07001347 mask = GPIO_BIT(bank, gpio);
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001348
1349 if (gpio_is_input(bank, mask))
1350 return _get_gpio_datain(bank, gpio);
1351 else
1352 return _get_gpio_dataout(bank, gpio);
David Brownell52e31342008-03-03 12:43:23 -08001353}
1354
1355static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
1356{
1357 struct gpio_bank *bank;
1358 unsigned long flags;
1359
1360 bank = container_of(chip, struct gpio_bank, chip);
1361 spin_lock_irqsave(&bank->lock, flags);
1362 _set_gpio_dataout(bank, offset, value);
1363 _set_gpio_direction(bank, offset, 0);
1364 spin_unlock_irqrestore(&bank->lock, flags);
1365 return 0;
1366}
1367
Felipe Balbi168ef3d2010-05-26 14:42:23 -07001368static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
1369 unsigned debounce)
1370{
1371 struct gpio_bank *bank;
1372 unsigned long flags;
1373
1374 bank = container_of(chip, struct gpio_bank, chip);
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001375
1376 if (!bank->dbck) {
1377 bank->dbck = clk_get(bank->dev, "dbclk");
1378 if (IS_ERR(bank->dbck))
1379 dev_err(bank->dev, "Could not get gpio dbck\n");
1380 }
1381
Felipe Balbi168ef3d2010-05-26 14:42:23 -07001382 spin_lock_irqsave(&bank->lock, flags);
1383 _set_gpio_debounce(bank, offset, debounce);
1384 spin_unlock_irqrestore(&bank->lock, flags);
1385
1386 return 0;
1387}
1388
David Brownell52e31342008-03-03 12:43:23 -08001389static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1390{
1391 struct gpio_bank *bank;
1392 unsigned long flags;
1393
1394 bank = container_of(chip, struct gpio_bank, chip);
1395 spin_lock_irqsave(&bank->lock, flags);
1396 _set_gpio_dataout(bank, offset, value);
1397 spin_unlock_irqrestore(&bank->lock, flags);
1398}
1399
David Brownella007b702008-12-10 17:35:25 -08001400static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
1401{
1402 struct gpio_bank *bank;
1403
1404 bank = container_of(chip, struct gpio_bank, chip);
1405 return bank->virtual_irq_start + offset;
1406}
1407
David Brownell52e31342008-03-03 12:43:23 -08001408/*---------------------------------------------------------------------*/
1409
Tony Lindgren9a748052010-12-07 16:26:56 -08001410static void __init omap_gpio_show_rev(struct gpio_bank *bank)
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001411{
1412 u32 rev;
1413
Tony Lindgren9a748052010-12-07 16:26:56 -08001414 if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
1415 rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001416 else if (cpu_is_omap24xx() || cpu_is_omap34xx())
Tony Lindgren9a748052010-12-07 16:26:56 -08001417 rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001418 else if (cpu_is_omap44xx())
Tony Lindgren9a748052010-12-07 16:26:56 -08001419 rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001420 else
1421 return;
1422
1423 printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
1424 (rev >> 4) & 0x0f, rev & 0x0f);
1425}
1426
David Brownell8ba55c52008-02-26 11:10:50 -08001427/* This lock class tells lockdep that GPIO irqs are in a different
1428 * category than their parents, so it won't report false recursion.
1429 */
1430static struct lock_class_key gpio_lock_class;
1431
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001432static inline int init_gpio_info(struct platform_device *pdev)
1433{
1434 /* TODO: Analyze removing gpio_bank_count usage from driver code */
1435 gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank),
1436 GFP_KERNEL);
1437 if (!gpio_bank) {
1438 dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
1439 return -ENOMEM;
1440 }
1441 return 0;
1442}
1443
1444/* TODO: Cleanup cpu_is_* checks */
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001445static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
1446{
1447 if (cpu_class_is_omap2()) {
1448 if (cpu_is_omap44xx()) {
1449 __raw_writel(0xffffffff, bank->base +
1450 OMAP4_GPIO_IRQSTATUSCLR0);
1451 __raw_writel(0x00000000, bank->base +
1452 OMAP4_GPIO_DEBOUNCENABLE);
1453 /* Initialize interface clk ungated, module enabled */
1454 __raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
1455 } else if (cpu_is_omap34xx()) {
1456 __raw_writel(0x00000000, bank->base +
1457 OMAP24XX_GPIO_IRQENABLE1);
1458 __raw_writel(0xffffffff, bank->base +
1459 OMAP24XX_GPIO_IRQSTATUS1);
1460 __raw_writel(0x00000000, bank->base +
1461 OMAP24XX_GPIO_DEBOUNCE_EN);
1462
1463 /* Initialize interface clk ungated, module enabled */
1464 __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
1465 } else if (cpu_is_omap24xx()) {
1466 static const u32 non_wakeup_gpios[] = {
1467 0xe203ffc0, 0x08700040
1468 };
1469 if (id < ARRAY_SIZE(non_wakeup_gpios))
1470 bank->non_wakeup_gpios = non_wakeup_gpios[id];
1471 }
1472 } else if (cpu_class_is_omap1()) {
1473 if (bank_is_mpuio(bank))
Tony Lindgren5de62b82010-12-07 16:26:58 -08001474 __raw_writew(0xffff, bank->base +
1475 OMAP_MPUIO_GPIO_MASKIT / bank->stride);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001476 if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
1477 __raw_writew(0xffff, bank->base
1478 + OMAP1510_GPIO_INT_MASK);
1479 __raw_writew(0x0000, bank->base
1480 + OMAP1510_GPIO_INT_STATUS);
1481 }
1482 if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
1483 __raw_writew(0x0000, bank->base
1484 + OMAP1610_GPIO_IRQENABLE1);
1485 __raw_writew(0xffff, bank->base
1486 + OMAP1610_GPIO_IRQSTATUS1);
1487 __raw_writew(0x0014, bank->base
1488 + OMAP1610_GPIO_SYSCONFIG);
1489
1490 /*
1491 * Enable system clock for GPIO module.
1492 * The CAM_CLK_CTRL *is* really the right place.
1493 */
1494 omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
1495 ULPD_CAM_CLK_CTRL);
1496 }
1497 if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
1498 __raw_writel(0xffffffff, bank->base
1499 + OMAP7XX_GPIO_INT_MASK);
1500 __raw_writel(0x00000000, bank->base
1501 + OMAP7XX_GPIO_INT_STATUS);
1502 }
1503 }
1504}
1505
Russell Kingd52b31d2011-05-27 13:56:12 -07001506static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001507{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001508 int j;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001509 static int gpio;
1510
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001511 bank->mod_usage = 0;
1512 /*
1513 * REVISIT eventually switch from OMAP-specific gpio structs
1514 * over to the generic ones
1515 */
1516 bank->chip.request = omap_gpio_request;
1517 bank->chip.free = omap_gpio_free;
1518 bank->chip.direction_input = gpio_input;
1519 bank->chip.get = gpio_get;
1520 bank->chip.direction_output = gpio_output;
1521 bank->chip.set_debounce = gpio_debounce;
1522 bank->chip.set = gpio_set;
1523 bank->chip.to_irq = gpio_2irq;
1524 if (bank_is_mpuio(bank)) {
1525 bank->chip.label = "mpuio";
1526#ifdef CONFIG_ARCH_OMAP16XX
1527 bank->chip.dev = &omap_mpuio_device.dev;
1528#endif
1529 bank->chip.base = OMAP_MPUIO(0);
1530 } else {
1531 bank->chip.label = "gpio";
1532 bank->chip.base = gpio;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001533 gpio += bank->width;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001534 }
Kevin Hilmand5f46242011-04-21 09:23:00 -07001535 bank->chip.ngpio = bank->width;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001536
1537 gpiochip_add(&bank->chip);
1538
1539 for (j = bank->virtual_irq_start;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001540 j < bank->virtual_irq_start + bank->width; j++) {
Thomas Gleixner1475b852011-03-22 17:11:09 +01001541 irq_set_lockdep_class(j, &gpio_lock_class);
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001542 irq_set_chip_data(j, bank);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001543 if (bank_is_mpuio(bank))
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001544 irq_set_chip(j, &mpuio_irq_chip);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001545 else
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001546 irq_set_chip(j, &gpio_irq_chip);
1547 irq_set_handler(j, handle_simple_irq);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001548 set_irq_flags(j, IRQF_VALID);
1549 }
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001550 irq_set_chained_handler(bank->irq, gpio_irq_handler);
1551 irq_set_handler_data(bank->irq, bank);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001552}
1553
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001554static int __devinit omap_gpio_probe(struct platform_device *pdev)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001555{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001556 static int gpio_init_done;
1557 struct omap_gpio_platform_data *pdata;
1558 struct resource *res;
1559 int id;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001560 struct gpio_bank *bank;
1561
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001562 if (!pdev->dev.platform_data)
1563 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001564
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001565 pdata = pdev->dev.platform_data;
Syed Mohammed Khasim56a25642006-12-06 17:14:08 -08001566
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001567 if (!gpio_init_done) {
1568 int ret;
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001569
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001570 ret = init_gpio_info(pdev);
1571 if (ret)
1572 return ret;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001573 }
1574
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001575 id = pdev->id;
1576 bank = &gpio_bank[id];
1577
1578 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1579 if (unlikely(!res)) {
1580 dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
1581 return -ENODEV;
1582 }
1583
1584 bank->irq = res->start;
1585 bank->virtual_irq_start = pdata->virtual_irq_start;
1586 bank->method = pdata->bank_type;
1587 bank->dev = &pdev->dev;
1588 bank->dbck_flag = pdata->dbck_flag;
Tony Lindgren5de62b82010-12-07 16:26:58 -08001589 bank->stride = pdata->bank_stride;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001590 bank->width = pdata->bank_width;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001591
1592 spin_lock_init(&bank->lock);
1593
1594 /* Static mapping, never released */
1595 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1596 if (unlikely(!res)) {
1597 dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
1598 return -ENODEV;
1599 }
1600
1601 bank->base = ioremap(res->start, resource_size(res));
1602 if (!bank->base) {
1603 dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
1604 return -ENOMEM;
1605 }
1606
1607 pm_runtime_enable(bank->dev);
1608 pm_runtime_get_sync(bank->dev);
1609
1610 omap_gpio_mod_init(bank, id);
1611 omap_gpio_chip_init(bank);
Tony Lindgren9a748052010-12-07 16:26:56 -08001612 omap_gpio_show_rev(bank);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001613
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001614 if (!gpio_init_done)
1615 gpio_init_done = 1;
1616
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001617 return 0;
1618}
1619
Tony Lindgren140455f2010-02-12 12:26:48 -08001620#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001621static int omap_gpio_suspend(void)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001622{
1623 int i;
1624
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001625 if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
Tony Lindgren92105bb2005-09-07 17:20:26 +01001626 return 0;
1627
1628 for (i = 0; i < gpio_bank_count; i++) {
1629 struct gpio_bank *bank = &gpio_bank[i];
1630 void __iomem *wake_status;
1631 void __iomem *wake_clear;
1632 void __iomem *wake_set;
David Brownella6472532008-03-03 04:33:30 -08001633 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001634
1635 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -08001636#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren92105bb2005-09-07 17:20:26 +01001637 case METHOD_GPIO_1610:
1638 wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
1639 wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
1640 wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
1641 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001642#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001643#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001644 case METHOD_GPIO_24XX:
Tero Kristo723fdb72008-11-26 14:35:16 -08001645 wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001646 wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
1647 wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
1648 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001649#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301650#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001651 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301652 wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
1653 wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
1654 wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
1655 break;
1656#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +01001657 default:
1658 continue;
1659 }
1660
David Brownella6472532008-03-03 04:33:30 -08001661 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001662 bank->saved_wakeup = __raw_readl(wake_status);
1663 __raw_writel(0xffffffff, wake_clear);
1664 __raw_writel(bank->suspend_wakeup, wake_set);
David Brownella6472532008-03-03 04:33:30 -08001665 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001666 }
1667
1668 return 0;
1669}
1670
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001671static void omap_gpio_resume(void)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001672{
1673 int i;
1674
Tero Kristo723fdb72008-11-26 14:35:16 -08001675 if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001676 return;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001677
1678 for (i = 0; i < gpio_bank_count; i++) {
1679 struct gpio_bank *bank = &gpio_bank[i];
1680 void __iomem *wake_clear;
1681 void __iomem *wake_set;
David Brownella6472532008-03-03 04:33:30 -08001682 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001683
1684 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -08001685#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren92105bb2005-09-07 17:20:26 +01001686 case METHOD_GPIO_1610:
1687 wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
1688 wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
1689 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001690#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001691#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001692 case METHOD_GPIO_24XX:
Tony Lindgren0d9356c2006-09-25 12:41:45 +03001693 wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
1694 wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001695 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001696#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301697#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001698 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301699 wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
1700 wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
1701 break;
1702#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +01001703 default:
1704 continue;
1705 }
1706
David Brownella6472532008-03-03 04:33:30 -08001707 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001708 __raw_writel(0xffffffff, wake_clear);
1709 __raw_writel(bank->saved_wakeup, wake_set);
David Brownella6472532008-03-03 04:33:30 -08001710 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001711 }
Tony Lindgren92105bb2005-09-07 17:20:26 +01001712}
1713
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001714static struct syscore_ops omap_gpio_syscore_ops = {
Tony Lindgren92105bb2005-09-07 17:20:26 +01001715 .suspend = omap_gpio_suspend,
1716 .resume = omap_gpio_resume,
1717};
1718
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001719#endif
1720
Tony Lindgren140455f2010-02-12 12:26:48 -08001721#ifdef CONFIG_ARCH_OMAP2PLUS
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001722
1723static int workaround_enabled;
1724
Paul Walmsley72e06d02010-12-21 21:05:16 -07001725void omap2_gpio_prepare_for_idle(int off_mode)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001726{
1727 int i, c = 0;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001728 int min = 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001729
Tero Kristoa118b5f2008-12-22 14:27:12 +02001730 if (cpu_is_omap34xx())
1731 min = 1;
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001732
Tero Kristoa118b5f2008-12-22 14:27:12 +02001733 for (i = min; i < gpio_bank_count; i++) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001734 struct gpio_bank *bank = &gpio_bank[i];
Sanjeev Premica828762010-09-23 18:27:18 -07001735 u32 l1 = 0, l2 = 0;
Kevin Hilman0aed04352010-09-22 16:06:27 -07001736 int j;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001737
Kevin Hilman0aed04352010-09-22 16:06:27 -07001738 for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
Kevin Hilman8865b9b2009-01-27 11:15:34 -08001739 clk_disable(bank->dbck);
1740
Paul Walmsley72e06d02010-12-21 21:05:16 -07001741 if (!off_mode)
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001742 continue;
1743
1744 /* If going to OFF, remove triggering for all
1745 * non-wakeup GPIOs. Otherwise spurious IRQs will be
1746 * generated. See OMAP2420 Errata item 1.101. */
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001747 if (!(bank->enabled_non_wakeup_gpios))
1748 continue;
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001749
1750 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1751 bank->saved_datain = __raw_readl(bank->base +
1752 OMAP24XX_GPIO_DATAIN);
1753 l1 = __raw_readl(bank->base +
1754 OMAP24XX_GPIO_FALLINGDETECT);
1755 l2 = __raw_readl(bank->base +
1756 OMAP24XX_GPIO_RISINGDETECT);
1757 }
1758
1759 if (cpu_is_omap44xx()) {
1760 bank->saved_datain = __raw_readl(bank->base +
1761 OMAP4_GPIO_DATAIN);
1762 l1 = __raw_readl(bank->base +
1763 OMAP4_GPIO_FALLINGDETECT);
1764 l2 = __raw_readl(bank->base +
1765 OMAP4_GPIO_RISINGDETECT);
1766 }
1767
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001768 bank->saved_fallingdetect = l1;
1769 bank->saved_risingdetect = l2;
1770 l1 &= ~bank->enabled_non_wakeup_gpios;
1771 l2 &= ~bank->enabled_non_wakeup_gpios;
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001772
1773 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1774 __raw_writel(l1, bank->base +
1775 OMAP24XX_GPIO_FALLINGDETECT);
1776 __raw_writel(l2, bank->base +
1777 OMAP24XX_GPIO_RISINGDETECT);
1778 }
1779
1780 if (cpu_is_omap44xx()) {
1781 __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
1782 __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
1783 }
1784
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001785 c++;
1786 }
1787 if (!c) {
1788 workaround_enabled = 0;
1789 return;
1790 }
1791 workaround_enabled = 1;
1792}
1793
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001794void omap2_gpio_resume_after_idle(void)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001795{
1796 int i;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001797 int min = 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001798
Tero Kristoa118b5f2008-12-22 14:27:12 +02001799 if (cpu_is_omap34xx())
1800 min = 1;
1801 for (i = min; i < gpio_bank_count; i++) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001802 struct gpio_bank *bank = &gpio_bank[i];
Sanjeev Premica828762010-09-23 18:27:18 -07001803 u32 l = 0, gen, gen0, gen1;
Kevin Hilman0aed04352010-09-22 16:06:27 -07001804 int j;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001805
Kevin Hilman0aed04352010-09-22 16:06:27 -07001806 for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
Kevin Hilman8865b9b2009-01-27 11:15:34 -08001807 clk_enable(bank->dbck);
1808
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001809 if (!workaround_enabled)
1810 continue;
1811
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001812 if (!(bank->enabled_non_wakeup_gpios))
1813 continue;
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001814
1815 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1816 __raw_writel(bank->saved_fallingdetect,
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001817 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001818 __raw_writel(bank->saved_risingdetect,
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001819 bank->base + OMAP24XX_GPIO_RISINGDETECT);
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001820 l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
1821 }
1822
1823 if (cpu_is_omap44xx()) {
1824 __raw_writel(bank->saved_fallingdetect,
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301825 bank->base + OMAP4_GPIO_FALLINGDETECT);
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001826 __raw_writel(bank->saved_risingdetect,
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301827 bank->base + OMAP4_GPIO_RISINGDETECT);
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001828 l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
1829 }
1830
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001831 /* Check if any of the non-wakeup interrupt GPIOs have changed
1832 * state. If so, generate an IRQ by software. This is
1833 * horribly racy, but it's the best we can do to work around
1834 * this silicon bug. */
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001835 l ^= bank->saved_datain;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001836 l &= bank->enabled_non_wakeup_gpios;
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001837
1838 /*
1839 * No need to generate IRQs for the rising edge for gpio IRQs
1840 * configured with falling edge only; and vice versa.
1841 */
1842 gen0 = l & bank->saved_fallingdetect;
1843 gen0 &= bank->saved_datain;
1844
1845 gen1 = l & bank->saved_risingdetect;
1846 gen1 &= ~(bank->saved_datain);
1847
1848 /* FIXME: Consider GPIO IRQs with level detections properly! */
1849 gen = l & (~(bank->saved_fallingdetect) &
1850 ~(bank->saved_risingdetect));
1851 /* Consider all GPIO IRQs needed to be updated */
1852 gen |= gen0 | gen1;
1853
1854 if (gen) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001855 u32 old0, old1;
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001856
Sergio Aguirref00d6492010-03-03 16:21:08 +00001857 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001858 old0 = __raw_readl(bank->base +
1859 OMAP24XX_GPIO_LEVELDETECT0);
1860 old1 = __raw_readl(bank->base +
1861 OMAP24XX_GPIO_LEVELDETECT1);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001862 __raw_writel(old0 | gen, bank->base +
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001863 OMAP24XX_GPIO_LEVELDETECT0);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001864 __raw_writel(old1 | gen, bank->base +
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001865 OMAP24XX_GPIO_LEVELDETECT1);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001866 __raw_writel(old0, bank->base +
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001867 OMAP24XX_GPIO_LEVELDETECT0);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001868 __raw_writel(old1, bank->base +
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001869 OMAP24XX_GPIO_LEVELDETECT1);
1870 }
1871
1872 if (cpu_is_omap44xx()) {
1873 old0 = __raw_readl(bank->base +
1874 OMAP4_GPIO_LEVELDETECT0);
1875 old1 = __raw_readl(bank->base +
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301876 OMAP4_GPIO_LEVELDETECT1);
Tony Lindgren3f1686a92010-02-15 09:27:25 -08001877 __raw_writel(old0 | l, bank->base +
1878 OMAP4_GPIO_LEVELDETECT0);
1879 __raw_writel(old1 | l, bank->base +
1880 OMAP4_GPIO_LEVELDETECT1);
1881 __raw_writel(old0, bank->base +
1882 OMAP4_GPIO_LEVELDETECT0);
1883 __raw_writel(old1, bank->base +
1884 OMAP4_GPIO_LEVELDETECT1);
1885 }
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001886 }
1887 }
1888
1889}
1890
Tony Lindgren92105bb2005-09-07 17:20:26 +01001891#endif
1892
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001893#ifdef CONFIG_ARCH_OMAP3
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301894/* save the registers of bank 2-6 */
1895void omap_gpio_save_context(void)
1896{
1897 int i;
1898
1899 /* saving banks from 2-6 only since GPIO1 is in WKUP */
1900 for (i = 1; i < gpio_bank_count; i++) {
1901 struct gpio_bank *bank = &gpio_bank[i];
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301902 gpio_context[i].irqenable1 =
1903 __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
1904 gpio_context[i].irqenable2 =
1905 __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
1906 gpio_context[i].wake_en =
1907 __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
1908 gpio_context[i].ctrl =
1909 __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
1910 gpio_context[i].oe =
1911 __raw_readl(bank->base + OMAP24XX_GPIO_OE);
1912 gpio_context[i].leveldetect0 =
1913 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
1914 gpio_context[i].leveldetect1 =
1915 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
1916 gpio_context[i].risingdetect =
1917 __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
1918 gpio_context[i].fallingdetect =
1919 __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
1920 gpio_context[i].dataout =
1921 __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301922 }
1923}
1924
1925/* restore the required registers of bank 2-6 */
1926void omap_gpio_restore_context(void)
1927{
1928 int i;
1929
1930 for (i = 1; i < gpio_bank_count; i++) {
1931 struct gpio_bank *bank = &gpio_bank[i];
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301932 __raw_writel(gpio_context[i].irqenable1,
1933 bank->base + OMAP24XX_GPIO_IRQENABLE1);
1934 __raw_writel(gpio_context[i].irqenable2,
1935 bank->base + OMAP24XX_GPIO_IRQENABLE2);
1936 __raw_writel(gpio_context[i].wake_en,
1937 bank->base + OMAP24XX_GPIO_WAKE_EN);
1938 __raw_writel(gpio_context[i].ctrl,
1939 bank->base + OMAP24XX_GPIO_CTRL);
1940 __raw_writel(gpio_context[i].oe,
1941 bank->base + OMAP24XX_GPIO_OE);
1942 __raw_writel(gpio_context[i].leveldetect0,
1943 bank->base + OMAP24XX_GPIO_LEVELDETECT0);
1944 __raw_writel(gpio_context[i].leveldetect1,
1945 bank->base + OMAP24XX_GPIO_LEVELDETECT1);
1946 __raw_writel(gpio_context[i].risingdetect,
1947 bank->base + OMAP24XX_GPIO_RISINGDETECT);
1948 __raw_writel(gpio_context[i].fallingdetect,
1949 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
1950 __raw_writel(gpio_context[i].dataout,
1951 bank->base + OMAP24XX_GPIO_DATAOUT);
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301952 }
1953}
1954#endif
1955
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001956static struct platform_driver omap_gpio_driver = {
1957 .probe = omap_gpio_probe,
1958 .driver = {
1959 .name = "omap_gpio",
1960 },
1961};
1962
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001963/*
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001964 * gpio driver register needs to be done before
1965 * machine_init functions access gpio APIs.
1966 * Hence omap_gpio_drv_reg() is a postcore_initcall.
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001967 */
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001968static int __init omap_gpio_drv_reg(void)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001969{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001970 return platform_driver_register(&omap_gpio_driver);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001971}
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001972postcore_initcall(omap_gpio_drv_reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001973
Tony Lindgren92105bb2005-09-07 17:20:26 +01001974static int __init omap_gpio_sysinit(void)
1975{
David Brownell11a78b72006-12-06 17:14:11 -08001976 mpuio_init();
1977
Tony Lindgren140455f2010-02-12 12:26:48 -08001978#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001979 if (cpu_is_omap16xx() || cpu_class_is_omap2())
1980 register_syscore_ops(&omap_gpio_syscore_ops);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001981#endif
1982
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001983 return 0;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001984}
1985
Tony Lindgren92105bb2005-09-07 17:20:26 +01001986arch_initcall(omap_gpio_sysinit);