blob: 3f436c03361180bc42f43e06ceab60d1409883dd [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
86static inline struct gpio_bank *get_gpio_bank(int gpio)
87{
Tony Lindgren6e60e792006-04-02 17:46:23 +010088 if (cpu_is_omap15xx()) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010089 if (OMAP_GPIO_IS_MPUIO(gpio))
90 return &gpio_bank[0];
91 return &gpio_bank[1];
92 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010093 if (cpu_is_omap16xx()) {
94 if (OMAP_GPIO_IS_MPUIO(gpio))
95 return &gpio_bank[0];
96 return &gpio_bank[1 + (gpio >> 4)];
97 }
Zebediah C. McClure56739a62009-03-23 18:07:40 -070098 if (cpu_is_omap7xx()) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +010099 if (OMAP_GPIO_IS_MPUIO(gpio))
100 return &gpio_bank[0];
101 return &gpio_bank[1 + (gpio >> 5)];
102 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100103 if (cpu_is_omap24xx())
104 return &gpio_bank[gpio >> 5];
Santosh Shilimkar44169072009-05-28 14:16:04 -0700105 if (cpu_is_omap34xx() || cpu_is_omap44xx())
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800106 return &gpio_bank[gpio >> 5];
David Brownelle031ab22008-12-10 17:35:27 -0800107 BUG();
108 return NULL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100109}
110
111static inline int get_gpio_index(int gpio)
112{
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700113 if (cpu_is_omap7xx())
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100114 return gpio & 0x1f;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100115 if (cpu_is_omap24xx())
116 return gpio & 0x1f;
Santosh Shilimkar44169072009-05-28 14:16:04 -0700117 if (cpu_is_omap34xx() || cpu_is_omap44xx())
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800118 return gpio & 0x1f;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100119 return gpio & 0x0f;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100120}
121
122static inline int gpio_valid(int gpio)
123{
124 if (gpio < 0)
125 return -1;
Tony Lindgrend11ac972008-01-12 15:35:04 -0800126 if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
Jonathan McDowell193e68b2006-09-25 12:41:30 +0300127 if (gpio >= OMAP_MAX_GPIO_LINES + 16)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100128 return -1;
129 return 0;
130 }
Tony Lindgren6e60e792006-04-02 17:46:23 +0100131 if (cpu_is_omap15xx() && gpio < 16)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100132 return 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100133 if ((cpu_is_omap16xx()) && gpio < 64)
134 return 0;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700135 if (cpu_is_omap7xx() && gpio < 192)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100136 return 0;
Tony Lindgren25d6f632010-08-02 14:21:39 +0300137 if (cpu_is_omap2420() && gpio < 128)
138 return 0;
139 if (cpu_is_omap2430() && gpio < 160)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100140 return 0;
Santosh Shilimkar44169072009-05-28 14:16:04 -0700141 if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800142 return 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100143 return -1;
144}
145
146static int check_gpio(int gpio)
147{
Roel Kluind32b20f2009-11-17 14:39:03 -0800148 if (unlikely(gpio_valid(gpio) < 0)) {
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100149 printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
150 dump_stack();
151 return -1;
152 }
153 return 0;
154}
155
156static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
157{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100158 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100159 u32 l;
160
161 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800162#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100163 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800164 reg += OMAP_MPUIO_IO_CNTL / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100165 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800166#endif
167#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100168 case METHOD_GPIO_1510:
169 reg += OMAP1510_GPIO_DIR_CONTROL;
170 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800171#endif
172#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100173 case METHOD_GPIO_1610:
174 reg += OMAP1610_GPIO_DIRECTION;
175 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800176#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100177#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100178 case METHOD_GPIO_7XX:
179 reg += OMAP7XX_GPIO_DIR_CONTROL;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700180 break;
181#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800182#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100183 case METHOD_GPIO_24XX:
184 reg += OMAP24XX_GPIO_OE;
185 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800186#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530187#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800188 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530189 reg += OMAP4_GPIO_OE;
190 break;
191#endif
David Brownelle5c56ed2006-12-06 17:13:59 -0800192 default:
193 WARN_ON(1);
194 return;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100195 }
196 l = __raw_readl(reg);
197 if (is_input)
198 l |= 1 << gpio;
199 else
200 l &= ~(1 << gpio);
201 __raw_writel(l, reg);
202}
203
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100204static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
205{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100206 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100207 u32 l = 0;
208
209 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800210#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100211 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800212 reg += OMAP_MPUIO_OUTPUT / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100213 l = __raw_readl(reg);
214 if (enable)
215 l |= 1 << gpio;
216 else
217 l &= ~(1 << gpio);
218 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800219#endif
220#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100221 case METHOD_GPIO_1510:
222 reg += OMAP1510_GPIO_DATA_OUTPUT;
223 l = __raw_readl(reg);
224 if (enable)
225 l |= 1 << gpio;
226 else
227 l &= ~(1 << gpio);
228 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800229#endif
230#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100231 case METHOD_GPIO_1610:
232 if (enable)
233 reg += OMAP1610_GPIO_SET_DATAOUT;
234 else
235 reg += OMAP1610_GPIO_CLEAR_DATAOUT;
236 l = 1 << gpio;
237 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800238#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100239#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100240 case METHOD_GPIO_7XX:
241 reg += OMAP7XX_GPIO_DATA_OUTPUT;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700242 l = __raw_readl(reg);
243 if (enable)
244 l |= 1 << gpio;
245 else
246 l &= ~(1 << gpio);
247 break;
248#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800249#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100250 case METHOD_GPIO_24XX:
251 if (enable)
252 reg += OMAP24XX_GPIO_SETDATAOUT;
253 else
254 reg += OMAP24XX_GPIO_CLEARDATAOUT;
255 l = 1 << gpio;
256 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800257#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530258#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800259 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530260 if (enable)
261 reg += OMAP4_GPIO_SETDATAOUT;
262 else
263 reg += OMAP4_GPIO_CLEARDATAOUT;
264 l = 1 << gpio;
265 break;
266#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100267 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800268 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100269 return;
270 }
271 __raw_writel(l, reg);
272}
273
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300274static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100275{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100276 void __iomem *reg;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100277
278 if (check_gpio(gpio) < 0)
David Brownelle5c56ed2006-12-06 17:13:59 -0800279 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100280 reg = bank->base;
281 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800282#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100283 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800284 reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100285 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800286#endif
287#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100288 case METHOD_GPIO_1510:
289 reg += OMAP1510_GPIO_DATA_INPUT;
290 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800291#endif
292#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100293 case METHOD_GPIO_1610:
294 reg += OMAP1610_GPIO_DATAIN;
295 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800296#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100297#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100298 case METHOD_GPIO_7XX:
299 reg += OMAP7XX_GPIO_DATA_INPUT;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700300 break;
301#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800302#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100303 case METHOD_GPIO_24XX:
304 reg += OMAP24XX_GPIO_DATAIN;
305 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800306#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530307#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800308 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530309 reg += OMAP4_GPIO_DATAIN;
310 break;
311#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100312 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800313 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100314 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100315 return (__raw_readl(reg)
316 & (1 << get_gpio_index(gpio))) != 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100317}
318
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300319static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
320{
321 void __iomem *reg;
322
323 if (check_gpio(gpio) < 0)
324 return -EINVAL;
325 reg = bank->base;
326
327 switch (bank->method) {
328#ifdef CONFIG_ARCH_OMAP1
329 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800330 reg += OMAP_MPUIO_OUTPUT / bank->stride;
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300331 break;
332#endif
333#ifdef CONFIG_ARCH_OMAP15XX
334 case METHOD_GPIO_1510:
335 reg += OMAP1510_GPIO_DATA_OUTPUT;
336 break;
337#endif
338#ifdef CONFIG_ARCH_OMAP16XX
339 case METHOD_GPIO_1610:
340 reg += OMAP1610_GPIO_DATAOUT;
341 break;
342#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100343#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100344 case METHOD_GPIO_7XX:
345 reg += OMAP7XX_GPIO_DATA_OUTPUT;
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300346 break;
347#endif
Charulatha V9f096862010-05-14 12:05:27 -0700348#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300349 case METHOD_GPIO_24XX:
350 reg += OMAP24XX_GPIO_DATAOUT;
351 break;
352#endif
Charulatha V9f096862010-05-14 12:05:27 -0700353#ifdef CONFIG_ARCH_OMAP4
354 case METHOD_GPIO_44XX:
355 reg += OMAP4_GPIO_DATAOUT;
356 break;
357#endif
Roger Quadrosb37c45b2009-08-05 16:53:24 +0300358 default:
359 return -EINVAL;
360 }
361
362 return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
363}
364
Tony Lindgren92105bb2005-09-07 17:20:26 +0100365#define MOD_REG_BIT(reg, bit_mask, set) \
366do { \
367 int l = __raw_readl(base + reg); \
368 if (set) l |= bit_mask; \
369 else l &= ~bit_mask; \
370 __raw_writel(l, base + reg); \
371} while(0)
372
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700373/**
374 * _set_gpio_debounce - low level gpio debounce time
375 * @bank: the gpio bank we're acting upon
376 * @gpio: the gpio number on this @gpio
377 * @debounce: debounce time to use
378 *
379 * OMAP's debounce time is in 31us steps so we need
380 * to convert and round up to the closest unit.
381 */
382static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
383 unsigned debounce)
384{
385 void __iomem *reg = bank->base;
386 u32 val;
387 u32 l;
388
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800389 if (!bank->dbck_flag)
390 return;
391
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700392 if (debounce < 32)
393 debounce = 0x01;
394 else if (debounce > 7936)
395 debounce = 0xff;
396 else
397 debounce = (debounce / 0x1f) - 1;
398
399 l = 1 << get_gpio_index(gpio);
400
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_DEBOUNCINGTIME;
403 else
404 reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
405
406 __raw_writel(debounce, reg);
407
408 reg = bank->base;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800409 if (bank->method == METHOD_GPIO_44XX)
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700410 reg += OMAP4_GPIO_DEBOUNCENABLE;
411 else
412 reg += OMAP24XX_GPIO_DEBOUNCE_EN;
413
414 val = __raw_readl(reg);
415
416 if (debounce) {
417 val |= l;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800418 clk_enable(bank->dbck);
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700419 } else {
420 val &= ~l;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -0800421 clk_disable(bank->dbck);
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700422 }
Kevin Hilmanf7ec0b02010-06-09 13:53:07 +0300423 bank->dbck_enable_mask = val;
Felipe Balbi168ef3d2010-05-26 14:42:23 -0700424
425 __raw_writel(val, reg);
426}
427
Tony Lindgren140455f2010-02-12 12:26:48 -0800428#ifdef CONFIG_ARCH_OMAP2PLUS
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700429static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
430 int trigger)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100431{
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800432 void __iomem *base = bank->base;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100433 u32 gpio_bit = 1 << gpio;
434
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530435 if (cpu_is_omap44xx()) {
436 MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
437 trigger & IRQ_TYPE_LEVEL_LOW);
438 MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
439 trigger & IRQ_TYPE_LEVEL_HIGH);
440 MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
441 trigger & IRQ_TYPE_EDGE_RISING);
442 MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
443 trigger & IRQ_TYPE_EDGE_FALLING);
444 } else {
445 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
446 trigger & IRQ_TYPE_LEVEL_LOW);
447 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
448 trigger & IRQ_TYPE_LEVEL_HIGH);
449 MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
450 trigger & IRQ_TYPE_EDGE_RISING);
451 MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
452 trigger & IRQ_TYPE_EDGE_FALLING);
453 }
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800454 if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530455 if (cpu_is_omap44xx()) {
Colin Cross0622b252011-06-06 13:38:17 -0700456 MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
457 trigger != 0);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530458 } else {
Chunqiu Wang699117a2009-06-24 17:13:39 +0000459 /*
460 * GPIO wakeup request can only be generated on edge
461 * transitions
462 */
463 if (trigger & IRQ_TYPE_EDGE_BOTH)
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530464 __raw_writel(1 << gpio, bank->base
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700465 + OMAP24XX_GPIO_SETWKUENA);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530466 else
467 __raw_writel(1 << gpio, bank->base
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700468 + OMAP24XX_GPIO_CLEARWKUENA);
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530469 }
Tero Kristoa118b5f2008-12-22 14:27:12 +0200470 }
471 /* This part needs to be executed always for OMAP34xx */
472 if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
Chunqiu Wang699117a2009-06-24 17:13:39 +0000473 /*
474 * Log the edge gpio and manually trigger the IRQ
475 * after resume if the input level changes
476 * to avoid irq lost during PER RET/OFF mode
477 * Applies for omap2 non-wakeup gpio and all omap3 gpios
478 */
479 if (trigger & IRQ_TYPE_EDGE_BOTH)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800480 bank->enabled_non_wakeup_gpios |= gpio_bit;
481 else
482 bank->enabled_non_wakeup_gpios &= ~gpio_bit;
483 }
Kevin Hilman5eb3bb92007-05-05 11:40:29 -0700484
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530485 if (cpu_is_omap44xx()) {
486 bank->level_mask =
487 __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) |
488 __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1);
489 } else {
490 bank->level_mask =
491 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
492 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
493 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100494}
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800495#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +0100496
Uwe Kleine-König9198bcd2010-01-29 14:20:05 -0800497#ifdef CONFIG_ARCH_OMAP1
Cory Maccarrone4318f362010-01-08 10:29:04 -0800498/*
499 * This only applies to chips that can't do both rising and falling edge
500 * detection at once. For all other chips, this function is a noop.
501 */
502static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
503{
504 void __iomem *reg = bank->base;
505 u32 l = 0;
506
507 switch (bank->method) {
Cory Maccarrone4318f362010-01-08 10:29:04 -0800508 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800509 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
Cory Maccarrone4318f362010-01-08 10:29:04 -0800510 break;
Cory Maccarrone4318f362010-01-08 10:29:04 -0800511#ifdef CONFIG_ARCH_OMAP15XX
512 case METHOD_GPIO_1510:
513 reg += OMAP1510_GPIO_INT_CONTROL;
514 break;
515#endif
516#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
517 case METHOD_GPIO_7XX:
518 reg += OMAP7XX_GPIO_INT_CONTROL;
519 break;
520#endif
521 default:
522 return;
523 }
524
525 l = __raw_readl(reg);
526 if ((l >> gpio) & 1)
527 l &= ~(1 << gpio);
528 else
529 l |= 1 << gpio;
530
531 __raw_writel(l, reg);
532}
Uwe Kleine-König9198bcd2010-01-29 14:20:05 -0800533#endif
Cory Maccarrone4318f362010-01-08 10:29:04 -0800534
Tony Lindgren92105bb2005-09-07 17:20:26 +0100535static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
536{
537 void __iomem *reg = bank->base;
538 u32 l = 0;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100539
540 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800541#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100542 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800543 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100544 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000545 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800546 bank->toggle_mask |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100547 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100548 l |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100549 else if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100550 l &= ~(1 << gpio);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100551 else
552 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100553 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800554#endif
555#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100556 case METHOD_GPIO_1510:
557 reg += OMAP1510_GPIO_INT_CONTROL;
558 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000559 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800560 bank->toggle_mask |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100561 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100562 l |= 1 << gpio;
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100563 else if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100564 l &= ~(1 << gpio);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100565 else
566 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100567 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800568#endif
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800569#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100570 case METHOD_GPIO_1610:
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100571 if (gpio & 0x08)
572 reg += OMAP1610_GPIO_EDGE_CTRL2;
573 else
574 reg += OMAP1610_GPIO_EDGE_CTRL1;
575 gpio &= 0x07;
576 l = __raw_readl(reg);
577 l &= ~(3 << (gpio << 1));
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100578 if (trigger & IRQ_TYPE_EDGE_RISING)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100579 l |= 2 << (gpio << 1);
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100580 if (trigger & IRQ_TYPE_EDGE_FALLING)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100581 l |= 1 << (gpio << 1);
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800582 if (trigger)
583 /* Enable wake-up during idle for dynamic tick */
584 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);
585 else
586 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100587 break;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800588#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100589#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100590 case METHOD_GPIO_7XX:
591 reg += OMAP7XX_GPIO_INT_CONTROL;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700592 l = __raw_readl(reg);
Janusz Krzysztofik29501572010-04-05 11:38:06 +0000593 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
Cory Maccarrone4318f362010-01-08 10:29:04 -0800594 bank->toggle_mask |= 1 << gpio;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700595 if (trigger & IRQ_TYPE_EDGE_RISING)
596 l |= 1 << gpio;
597 else if (trigger & IRQ_TYPE_EDGE_FALLING)
598 l &= ~(1 << gpio);
599 else
600 goto bad;
601 break;
602#endif
Tony Lindgren140455f2010-02-12 12:26:48 -0800603#ifdef CONFIG_ARCH_OMAP2PLUS
Tony Lindgren92105bb2005-09-07 17:20:26 +0100604 case METHOD_GPIO_24XX:
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800605 case METHOD_GPIO_44XX:
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800606 set_24xx_gpio_triggering(bank, gpio, trigger);
Mika Westerbergf7c5cc42010-12-29 13:01:31 +0200607 return 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800608#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100609 default:
Tony Lindgren92105bb2005-09-07 17:20:26 +0100610 goto bad;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100611 }
Tony Lindgren92105bb2005-09-07 17:20:26 +0100612 __raw_writel(l, reg);
613 return 0;
614bad:
615 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100616}
617
Lennert Buytenheke9191022010-11-29 11:17:17 +0100618static int gpio_irq_type(struct irq_data *d, unsigned type)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100619{
620 struct gpio_bank *bank;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100621 unsigned gpio;
622 int retval;
David Brownella6472532008-03-03 04:33:30 -0800623 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100624
Lennert Buytenheke9191022010-11-29 11:17:17 +0100625 if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
626 gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100627 else
Lennert Buytenheke9191022010-11-29 11:17:17 +0100628 gpio = d->irq - IH_GPIO_BASE;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100629
630 if (check_gpio(gpio) < 0)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100631 return -EINVAL;
632
David Brownelle5c56ed2006-12-06 17:13:59 -0800633 if (type & ~IRQ_TYPE_SENSE_MASK)
Tony Lindgren6e60e792006-04-02 17:46:23 +0100634 return -EINVAL;
David Brownelle5c56ed2006-12-06 17:13:59 -0800635
636 /* OMAP1 allows only only edge triggering */
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -0800637 if (!cpu_class_is_omap2()
David Brownelle5c56ed2006-12-06 17:13:59 -0800638 && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
Tony Lindgren92105bb2005-09-07 17:20:26 +0100639 return -EINVAL;
640
Lennert Buytenheke9191022010-11-29 11:17:17 +0100641 bank = irq_data_get_irq_chip_data(d);
David Brownella6472532008-03-03 04:33:30 -0800642 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100643 retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
David Brownella6472532008-03-03 04:33:30 -0800644 spin_unlock_irqrestore(&bank->lock, flags);
Kevin Hilman672e3022008-01-16 21:56:16 -0800645
646 if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100647 __irq_set_handler_locked(d->irq, handle_level_irq);
Kevin Hilman672e3022008-01-16 21:56:16 -0800648 else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100649 __irq_set_handler_locked(d->irq, handle_edge_irq);
Kevin Hilman672e3022008-01-16 21:56:16 -0800650
Tony Lindgren92105bb2005-09-07 17:20:26 +0100651 return retval;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100652}
653
654static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
655{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100656 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100657
658 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800659#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100660 case METHOD_GPIO_1510:
661 reg += OMAP1510_GPIO_INT_STATUS;
662 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800663#endif
664#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100665 case METHOD_GPIO_1610:
666 reg += OMAP1610_GPIO_IRQSTATUS1;
667 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800668#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100669#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100670 case METHOD_GPIO_7XX:
671 reg += OMAP7XX_GPIO_INT_STATUS;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700672 break;
673#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800674#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100675 case METHOD_GPIO_24XX:
676 reg += OMAP24XX_GPIO_IRQSTATUS1;
677 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800678#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530679#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800680 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530681 reg += OMAP4_GPIO_IRQSTATUS0;
682 break;
683#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100684 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800685 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100686 return;
687 }
688 __raw_writel(gpio_mask, reg);
Hiroshi DOYUbee79302006-09-25 12:41:46 +0300689
690 /* Workaround for clearing DSP GPIO interrupts to allow retention */
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800691 if (cpu_is_omap24xx() || cpu_is_omap34xx())
692 reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
693 else if (cpu_is_omap44xx())
694 reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
695
Kevin Hilmandf3c8512011-04-21 09:08:15 -0700696 if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx())
Roger Quadrosbedfd152009-04-23 11:10:50 -0700697 __raw_writel(gpio_mask, reg);
698
699 /* Flush posted write for the irq status to avoid spurious interrupts */
700 __raw_readl(reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100701}
702
703static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
704{
705 _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
706}
707
Imre Deakea6dedd2006-06-26 16:16:00 -0700708static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
709{
710 void __iomem *reg = bank->base;
Imre Deak99c47702006-06-26 16:16:07 -0700711 int inv = 0;
712 u32 l;
713 u32 mask;
Imre Deakea6dedd2006-06-26 16:16:00 -0700714
715 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800716#ifdef CONFIG_ARCH_OMAP1
Imre Deakea6dedd2006-06-26 16:16:00 -0700717 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800718 reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
Imre Deak99c47702006-06-26 16:16:07 -0700719 mask = 0xffff;
720 inv = 1;
Imre Deakea6dedd2006-06-26 16:16:00 -0700721 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800722#endif
723#ifdef CONFIG_ARCH_OMAP15XX
Imre Deakea6dedd2006-06-26 16:16:00 -0700724 case METHOD_GPIO_1510:
725 reg += OMAP1510_GPIO_INT_MASK;
Imre Deak99c47702006-06-26 16:16:07 -0700726 mask = 0xffff;
727 inv = 1;
Imre Deakea6dedd2006-06-26 16:16:00 -0700728 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800729#endif
730#ifdef CONFIG_ARCH_OMAP16XX
Imre Deakea6dedd2006-06-26 16:16:00 -0700731 case METHOD_GPIO_1610:
732 reg += OMAP1610_GPIO_IRQENABLE1;
Imre Deak99c47702006-06-26 16:16:07 -0700733 mask = 0xffff;
Imre Deakea6dedd2006-06-26 16:16:00 -0700734 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800735#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100736#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100737 case METHOD_GPIO_7XX:
738 reg += OMAP7XX_GPIO_INT_MASK;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700739 mask = 0xffffffff;
740 inv = 1;
741 break;
742#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800743#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Imre Deakea6dedd2006-06-26 16:16:00 -0700744 case METHOD_GPIO_24XX:
745 reg += OMAP24XX_GPIO_IRQENABLE1;
Imre Deak99c47702006-06-26 16:16:07 -0700746 mask = 0xffffffff;
Imre Deakea6dedd2006-06-26 16:16:00 -0700747 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800748#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530749#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800750 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530751 reg += OMAP4_GPIO_IRQSTATUSSET0;
752 mask = 0xffffffff;
753 break;
754#endif
Imre Deakea6dedd2006-06-26 16:16:00 -0700755 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800756 WARN_ON(1);
Imre Deakea6dedd2006-06-26 16:16:00 -0700757 return 0;
758 }
759
Imre Deak99c47702006-06-26 16:16:07 -0700760 l = __raw_readl(reg);
761 if (inv)
762 l = ~l;
763 l &= mask;
764 return l;
Imre Deakea6dedd2006-06-26 16:16:00 -0700765}
766
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100767static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
768{
Tony Lindgren92105bb2005-09-07 17:20:26 +0100769 void __iomem *reg = bank->base;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100770 u32 l;
771
772 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -0800773#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100774 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -0800775 reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100776 l = __raw_readl(reg);
777 if (enable)
778 l &= ~(gpio_mask);
779 else
780 l |= gpio_mask;
781 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800782#endif
783#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100784 case METHOD_GPIO_1510:
785 reg += OMAP1510_GPIO_INT_MASK;
786 l = __raw_readl(reg);
787 if (enable)
788 l &= ~(gpio_mask);
789 else
790 l |= gpio_mask;
791 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800792#endif
793#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100794 case METHOD_GPIO_1610:
795 if (enable)
796 reg += OMAP1610_GPIO_SET_IRQENABLE1;
797 else
798 reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
799 l = gpio_mask;
800 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800801#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +0100802#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +0100803 case METHOD_GPIO_7XX:
804 reg += OMAP7XX_GPIO_INT_MASK;
Zebediah C. McClure56739a62009-03-23 18:07:40 -0700805 l = __raw_readl(reg);
806 if (enable)
807 l &= ~(gpio_mask);
808 else
809 l |= gpio_mask;
810 break;
811#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -0800812#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100813 case METHOD_GPIO_24XX:
814 if (enable)
815 reg += OMAP24XX_GPIO_SETIRQENABLE1;
816 else
817 reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
818 l = gpio_mask;
819 break;
David Brownelle5c56ed2006-12-06 17:13:59 -0800820#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530821#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800822 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +0530823 if (enable)
824 reg += OMAP4_GPIO_IRQSTATUSSET0;
825 else
826 reg += OMAP4_GPIO_IRQSTATUSCLR0;
827 l = gpio_mask;
828 break;
829#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100830 default:
David Brownelle5c56ed2006-12-06 17:13:59 -0800831 WARN_ON(1);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100832 return;
833 }
834 __raw_writel(l, reg);
835}
836
837static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
838{
839 _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
840}
841
Tony Lindgren92105bb2005-09-07 17:20:26 +0100842/*
843 * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
844 * 1510 does not seem to have a wake-up register. If JTAG is connected
845 * to the target, system will wake up always on GPIO events. While
846 * system is running all registered GPIO interrupts need to have wake-up
847 * enabled. When system is suspended, only selected GPIO interrupts need
848 * to have wake-up enabled.
849 */
850static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
851{
Tony Lindgren4cc64202010-01-08 10:29:05 -0800852 unsigned long uninitialized_var(flags);
David Brownella6472532008-03-03 04:33:30 -0800853
Tony Lindgren92105bb2005-09-07 17:20:26 +0100854 switch (bank->method) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800855#ifdef CONFIG_ARCH_OMAP16XX
David Brownell11a78b72006-12-06 17:14:11 -0800856 case METHOD_MPUIO:
Tony Lindgren92105bb2005-09-07 17:20:26 +0100857 case METHOD_GPIO_1610:
David Brownella6472532008-03-03 04:33:30 -0800858 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700859 if (enable)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100860 bank->suspend_wakeup |= (1 << gpio);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700861 else
Tony Lindgren92105bb2005-09-07 17:20:26 +0100862 bank->suspend_wakeup &= ~(1 << gpio);
David Brownella6472532008-03-03 04:33:30 -0800863 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100864 return 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800865#endif
Tony Lindgren140455f2010-02-12 12:26:48 -0800866#ifdef CONFIG_ARCH_OMAP2PLUS
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800867 case METHOD_GPIO_24XX:
Tony Lindgren3f1686a2010-02-15 09:27:25 -0800868 case METHOD_GPIO_44XX:
David Brownell11a78b72006-12-06 17:14:11 -0800869 if (bank->non_wakeup_gpios & (1 << gpio)) {
870 printk(KERN_ERR "Unable to modify wakeup on "
871 "non-wakeup GPIO%d\n",
Kevin Hilmand5f46242011-04-21 09:23:00 -0700872 (bank - gpio_bank) * bank->width + gpio);
David Brownell11a78b72006-12-06 17:14:11 -0800873 return -EINVAL;
874 }
David Brownella6472532008-03-03 04:33:30 -0800875 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700876 if (enable)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800877 bank->suspend_wakeup |= (1 << gpio);
Kevin Hilmanb3bb4f62009-04-23 11:10:49 -0700878 else
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800879 bank->suspend_wakeup &= ~(1 << gpio);
David Brownella6472532008-03-03 04:33:30 -0800880 spin_unlock_irqrestore(&bank->lock, flags);
Juha Yrjola3ac4fa92006-12-06 17:13:52 -0800881 return 0;
882#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +0100883 default:
884 printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
885 bank->method);
886 return -EINVAL;
887 }
888}
889
Tony Lindgren4196dd62006-09-25 12:41:38 +0300890static void _reset_gpio(struct gpio_bank *bank, int gpio)
891{
892 _set_gpio_direction(bank, get_gpio_index(gpio), 1);
893 _set_gpio_irqenable(bank, gpio, 0);
894 _clear_gpio_irqstatus(bank, gpio);
Dmitry Baryshkov6cab4862008-07-27 04:23:31 +0100895 _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
Tony Lindgren4196dd62006-09-25 12:41:38 +0300896}
897
Tony Lindgren92105bb2005-09-07 17:20:26 +0100898/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
Lennert Buytenheke9191022010-11-29 11:17:17 +0100899static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
Tony Lindgren92105bb2005-09-07 17:20:26 +0100900{
Lennert Buytenheke9191022010-11-29 11:17:17 +0100901 unsigned int gpio = d->irq - IH_GPIO_BASE;
Tony Lindgren92105bb2005-09-07 17:20:26 +0100902 struct gpio_bank *bank;
903 int retval;
904
905 if (check_gpio(gpio) < 0)
906 return -ENODEV;
Lennert Buytenheke9191022010-11-29 11:17:17 +0100907 bank = irq_data_get_irq_chip_data(d);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100908 retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100909
910 return retval;
911}
912
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800913static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100914{
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800915 struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
David Brownella6472532008-03-03 04:33:30 -0800916 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100917
David Brownella6472532008-03-03 04:33:30 -0800918 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100919
Tony Lindgren4196dd62006-09-25 12:41:38 +0300920 /* Set trigger to none. You need to enable the desired trigger with
921 * request_irq() or set_irq_type().
922 */
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800923 _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100924
Tony Lindgren1a8bfa12005-11-10 14:26:50 +0000925#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100926 if (bank->method == METHOD_GPIO_1510) {
Tony Lindgren92105bb2005-09-07 17:20:26 +0100927 void __iomem *reg;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100928
Tony Lindgren92105bb2005-09-07 17:20:26 +0100929 /* Claim the pin for MPU */
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100930 reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800931 __raw_writel(__raw_readl(reg) | (1 << offset), reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100932 }
933#endif
Charulatha V058af1e2009-11-22 10:11:25 -0800934 if (!cpu_class_is_omap1()) {
935 if (!bank->mod_usage) {
Charulatha V9f096862010-05-14 12:05:27 -0700936 void __iomem *reg = bank->base;
Charulatha V058af1e2009-11-22 10:11:25 -0800937 u32 ctrl;
Charulatha V9f096862010-05-14 12:05:27 -0700938
939 if (cpu_is_omap24xx() || cpu_is_omap34xx())
940 reg += OMAP24XX_GPIO_CTRL;
941 else if (cpu_is_omap44xx())
942 reg += OMAP4_GPIO_CTRL;
943 ctrl = __raw_readl(reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800944 /* Module is enabled, clocks are not gated */
Charulatha V9f096862010-05-14 12:05:27 -0700945 ctrl &= 0xFFFFFFFE;
946 __raw_writel(ctrl, reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800947 }
948 bank->mod_usage |= 1 << offset;
949 }
David Brownella6472532008-03-03 04:33:30 -0800950 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100951
952 return 0;
953}
954
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800955static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100956{
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800957 struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
David Brownella6472532008-03-03 04:33:30 -0800958 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +0100959
David Brownella6472532008-03-03 04:33:30 -0800960 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100961#ifdef CONFIG_ARCH_OMAP16XX
962 if (bank->method == METHOD_GPIO_1610) {
963 /* Disable wake-up during idle for dynamic tick */
964 void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800965 __raw_writel(1 << offset, reg);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100966 }
967#endif
Charulatha V9f096862010-05-14 12:05:27 -0700968#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
969 if (bank->method == METHOD_GPIO_24XX) {
Tony Lindgren92105bb2005-09-07 17:20:26 +0100970 /* Disable wake-up during idle for dynamic tick */
971 void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800972 __raw_writel(1 << offset, reg);
Tony Lindgren92105bb2005-09-07 17:20:26 +0100973 }
974#endif
Charulatha V9f096862010-05-14 12:05:27 -0700975#ifdef CONFIG_ARCH_OMAP4
976 if (bank->method == METHOD_GPIO_44XX) {
977 /* Disable wake-up during idle for dynamic tick */
978 void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
979 __raw_writel(1 << offset, reg);
980 }
981#endif
Charulatha V058af1e2009-11-22 10:11:25 -0800982 if (!cpu_class_is_omap1()) {
983 bank->mod_usage &= ~(1 << offset);
984 if (!bank->mod_usage) {
Charulatha V9f096862010-05-14 12:05:27 -0700985 void __iomem *reg = bank->base;
Charulatha V058af1e2009-11-22 10:11:25 -0800986 u32 ctrl;
Charulatha V9f096862010-05-14 12:05:27 -0700987
988 if (cpu_is_omap24xx() || cpu_is_omap34xx())
989 reg += OMAP24XX_GPIO_CTRL;
990 else if (cpu_is_omap44xx())
991 reg += OMAP4_GPIO_CTRL;
992 ctrl = __raw_readl(reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800993 /* Module is disabled, clocks are gated */
994 ctrl |= 1;
Charulatha V9f096862010-05-14 12:05:27 -0700995 __raw_writel(ctrl, reg);
Charulatha V058af1e2009-11-22 10:11:25 -0800996 }
997 }
Jarkko Nikula3ff164e2008-12-10 17:35:27 -0800998 _reset_gpio(bank, bank->chip.base + offset);
David Brownella6472532008-03-03 04:33:30 -0800999 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001000}
1001
1002/*
1003 * We need to unmask the GPIO bank interrupt as soon as possible to
1004 * avoid missing GPIO interrupts for other lines in the bank.
1005 * Then we need to mask-read-clear-unmask the triggered GPIO lines
1006 * in the bank to avoid missing nested interrupts for a GPIO line.
1007 * If we wait to unmask individual GPIO lines in the bank after the
1008 * line's interrupt handler has been run, we may miss some nested
1009 * interrupts.
1010 */
Russell King10dd5ce2006-11-23 11:41:32 +00001011static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001012{
Tony Lindgren92105bb2005-09-07 17:20:26 +01001013 void __iomem *isr_reg = NULL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001014 u32 isr;
Cory Maccarrone4318f362010-01-08 10:29:04 -08001015 unsigned int gpio_irq, gpio_index;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001016 struct gpio_bank *bank;
Imre Deakea6dedd2006-06-26 16:16:00 -07001017 u32 retrigger = 0;
1018 int unmasked = 0;
Will Deaconee144182011-02-21 13:46:08 +00001019 struct irq_chip *chip = irq_desc_get_chip(desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001020
Will Deaconee144182011-02-21 13:46:08 +00001021 chained_irq_enter(chip, desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001022
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001023 bank = irq_get_handler_data(irq);
David Brownelle5c56ed2006-12-06 17:13:59 -08001024#ifdef CONFIG_ARCH_OMAP1
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001025 if (bank->method == METHOD_MPUIO)
Tony Lindgren5de62b82010-12-07 16:26:58 -08001026 isr_reg = bank->base +
1027 OMAP_MPUIO_GPIO_INT / bank->stride;
David Brownelle5c56ed2006-12-06 17:13:59 -08001028#endif
Tony Lindgren1a8bfa12005-11-10 14:26:50 +00001029#ifdef CONFIG_ARCH_OMAP15XX
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001030 if (bank->method == METHOD_GPIO_1510)
1031 isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
1032#endif
1033#if defined(CONFIG_ARCH_OMAP16XX)
1034 if (bank->method == METHOD_GPIO_1610)
1035 isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
1036#endif
Alistair Buxtonb718aa82009-09-23 18:56:19 +01001037#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Alistair Buxton7c006922009-09-22 10:02:58 +01001038 if (bank->method == METHOD_GPIO_7XX)
1039 isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
Zebediah C. McClure56739a62009-03-23 18:07:40 -07001040#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001041#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001042 if (bank->method == METHOD_GPIO_24XX)
1043 isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
1044#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301045#if defined(CONFIG_ARCH_OMAP4)
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001046 if (bank->method == METHOD_GPIO_44XX)
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301047 isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
1048#endif
Evgeny Kuznetsovb1cc4c52010-12-07 16:25:40 -08001049
1050 if (WARN_ON(!isr_reg))
1051 goto exit;
1052
Tony Lindgren92105bb2005-09-07 17:20:26 +01001053 while(1) {
Tony Lindgren6e60e792006-04-02 17:46:23 +01001054 u32 isr_saved, level_mask = 0;
Imre Deakea6dedd2006-06-26 16:16:00 -07001055 u32 enabled;
Tony Lindgren6e60e792006-04-02 17:46:23 +01001056
Imre Deakea6dedd2006-06-26 16:16:00 -07001057 enabled = _get_gpio_irqbank_mask(bank);
1058 isr_saved = isr = __raw_readl(isr_reg) & enabled;
Tony Lindgren6e60e792006-04-02 17:46:23 +01001059
1060 if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
1061 isr &= 0x0000ffff;
1062
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001063 if (cpu_class_is_omap2()) {
Kevin Hilmanb144ff62008-01-16 21:56:15 -08001064 level_mask = bank->level_mask & enabled;
Imre Deakea6dedd2006-06-26 16:16:00 -07001065 }
Tony Lindgren6e60e792006-04-02 17:46:23 +01001066
1067 /* clear edge sensitive interrupts before handler(s) are
1068 called so that we don't miss any interrupt occurred while
1069 executing them */
1070 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
1071 _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
1072 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
1073
1074 /* if there is only edge sensitive GPIO pin interrupts
1075 configured, we could unmask GPIO bank interrupt immediately */
Imre Deakea6dedd2006-06-26 16:16:00 -07001076 if (!level_mask && !unmasked) {
1077 unmasked = 1;
Will Deaconee144182011-02-21 13:46:08 +00001078 chained_irq_exit(chip, desc);
Imre Deakea6dedd2006-06-26 16:16:00 -07001079 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001080
Imre Deakea6dedd2006-06-26 16:16:00 -07001081 isr |= retrigger;
1082 retrigger = 0;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001083 if (!isr)
1084 break;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001085
Tony Lindgren92105bb2005-09-07 17:20:26 +01001086 gpio_irq = bank->virtual_irq_start;
1087 for (; isr != 0; isr >>= 1, gpio_irq++) {
Cory Maccarrone4318f362010-01-08 10:29:04 -08001088 gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
1089
Tony Lindgren92105bb2005-09-07 17:20:26 +01001090 if (!(isr & 1))
1091 continue;
Thomas Gleixner29454dd2006-07-03 02:22:22 +02001092
Cory Maccarrone4318f362010-01-08 10:29:04 -08001093#ifdef CONFIG_ARCH_OMAP1
1094 /*
1095 * Some chips can't respond to both rising and falling
1096 * at the same time. If this irq was requested with
1097 * both flags, we need to flip the ICR data for the IRQ
1098 * to respond to the IRQ for the opposite direction.
1099 * This will be indicated in the bank toggle_mask.
1100 */
1101 if (bank->toggle_mask & (1 << gpio_index))
1102 _toggle_gpio_edge_triggering(bank, gpio_index);
1103#endif
1104
Dmitry Baryshkovd8aa0252008-10-09 13:36:24 +01001105 generic_handle_irq(gpio_irq);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001106 }
Tony Lindgren1a8bfa12005-11-10 14:26:50 +00001107 }
Imre Deakea6dedd2006-06-26 16:16:00 -07001108 /* if bank has any level sensitive GPIO pin interrupt
1109 configured, we must unmask the bank interrupt only after
1110 handler(s) are executed in order to avoid spurious bank
1111 interrupt */
Evgeny Kuznetsovb1cc4c52010-12-07 16:25:40 -08001112exit:
Imre Deakea6dedd2006-06-26 16:16:00 -07001113 if (!unmasked)
Will Deaconee144182011-02-21 13:46:08 +00001114 chained_irq_exit(chip, desc);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001115}
1116
Lennert Buytenheke9191022010-11-29 11:17:17 +01001117static void gpio_irq_shutdown(struct irq_data *d)
Tony Lindgren4196dd62006-09-25 12:41:38 +03001118{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001119 unsigned int gpio = d->irq - IH_GPIO_BASE;
1120 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001121 unsigned long flags;
Tony Lindgren4196dd62006-09-25 12:41:38 +03001122
Colin Cross85ec7b92011-06-06 13:38:18 -07001123 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren4196dd62006-09-25 12:41:38 +03001124 _reset_gpio(bank, gpio);
Colin Cross85ec7b92011-06-06 13:38:18 -07001125 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren4196dd62006-09-25 12:41:38 +03001126}
1127
Lennert Buytenheke9191022010-11-29 11:17:17 +01001128static void gpio_ack_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001129{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001130 unsigned int gpio = d->irq - IH_GPIO_BASE;
1131 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001132
1133 _clear_gpio_irqstatus(bank, gpio);
1134}
1135
Lennert Buytenheke9191022010-11-29 11:17:17 +01001136static void gpio_mask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001137{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001138 unsigned int gpio = d->irq - IH_GPIO_BASE;
1139 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001140 unsigned long flags;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001141
Colin Cross85ec7b92011-06-06 13:38:18 -07001142 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001143 _set_gpio_irqenable(bank, gpio, 0);
Kevin Hilman55b60192009-06-04 15:57:10 -07001144 _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
Colin Cross85ec7b92011-06-06 13:38:18 -07001145 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001146}
1147
Lennert Buytenheke9191022010-11-29 11:17:17 +01001148static void gpio_unmask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001149{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001150 unsigned int gpio = d->irq - IH_GPIO_BASE;
1151 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Kevin Hilmanb144ff62008-01-16 21:56:15 -08001152 unsigned int irq_mask = 1 << get_gpio_index(gpio);
Thomas Gleixner8c04a172011-03-24 12:40:15 +01001153 u32 trigger = irqd_get_trigger_type(d);
Colin Cross85ec7b92011-06-06 13:38:18 -07001154 unsigned long flags;
Kevin Hilman55b60192009-06-04 15:57:10 -07001155
Colin Cross85ec7b92011-06-06 13:38:18 -07001156 spin_lock_irqsave(&bank->lock, flags);
Kevin Hilman55b60192009-06-04 15:57:10 -07001157 if (trigger)
1158 _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
Kevin Hilmanb144ff62008-01-16 21:56:15 -08001159
1160 /* For level-triggered GPIOs, the clearing must be done after
1161 * the HW source is cleared, thus after the handler has run */
1162 if (bank->level_mask & irq_mask) {
1163 _set_gpio_irqenable(bank, gpio, 0);
1164 _clear_gpio_irqstatus(bank, gpio);
1165 }
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001166
Kevin Hilman4de8c752008-01-16 21:56:14 -08001167 _set_gpio_irqenable(bank, gpio, 1);
Colin Cross85ec7b92011-06-06 13:38:18 -07001168 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001169}
1170
David Brownelle5c56ed2006-12-06 17:13:59 -08001171static struct irq_chip gpio_irq_chip = {
1172 .name = "GPIO",
Lennert Buytenheke9191022010-11-29 11:17:17 +01001173 .irq_shutdown = gpio_irq_shutdown,
1174 .irq_ack = gpio_ack_irq,
1175 .irq_mask = gpio_mask_irq,
1176 .irq_unmask = gpio_unmask_irq,
1177 .irq_set_type = gpio_irq_type,
1178 .irq_set_wake = gpio_wake_enable,
David Brownelle5c56ed2006-12-06 17:13:59 -08001179};
1180
1181/*---------------------------------------------------------------------*/
1182
1183#ifdef CONFIG_ARCH_OMAP1
1184
1185/* MPUIO uses the always-on 32k clock */
1186
Lennert Buytenheke9191022010-11-29 11:17:17 +01001187static void mpuio_ack_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001188{
1189 /* The ISR is reset automatically, so do nothing here. */
1190}
1191
Lennert Buytenheke9191022010-11-29 11:17:17 +01001192static void mpuio_mask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001193{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001194 unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
1195 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001196
1197 _set_gpio_irqenable(bank, gpio, 0);
1198}
1199
Lennert Buytenheke9191022010-11-29 11:17:17 +01001200static void mpuio_unmask_irq(struct irq_data *d)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001201{
Lennert Buytenheke9191022010-11-29 11:17:17 +01001202 unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
1203 struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001204
1205 _set_gpio_irqenable(bank, gpio, 1);
1206}
1207
David Brownelle5c56ed2006-12-06 17:13:59 -08001208static struct irq_chip mpuio_irq_chip = {
1209 .name = "MPUIO",
Lennert Buytenheke9191022010-11-29 11:17:17 +01001210 .irq_ack = mpuio_ack_irq,
1211 .irq_mask = mpuio_mask_irq,
1212 .irq_unmask = mpuio_unmask_irq,
1213 .irq_set_type = gpio_irq_type,
David Brownell11a78b72006-12-06 17:14:11 -08001214#ifdef CONFIG_ARCH_OMAP16XX
1215 /* REVISIT: assuming only 16xx supports MPUIO wake events */
Lennert Buytenheke9191022010-11-29 11:17:17 +01001216 .irq_set_wake = gpio_wake_enable,
David Brownell11a78b72006-12-06 17:14:11 -08001217#endif
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001218};
1219
David Brownelle5c56ed2006-12-06 17:13:59 -08001220
1221#define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO)
1222
David Brownell11a78b72006-12-06 17:14:11 -08001223
1224#ifdef CONFIG_ARCH_OMAP16XX
1225
1226#include <linux/platform_device.h>
1227
Magnus Damm79ee0312009-07-08 13:22:04 +02001228static int omap_mpuio_suspend_noirq(struct device *dev)
David Brownell11a78b72006-12-06 17:14:11 -08001229{
Magnus Damm79ee0312009-07-08 13:22:04 +02001230 struct platform_device *pdev = to_platform_device(dev);
David Brownell11a78b72006-12-06 17:14:11 -08001231 struct gpio_bank *bank = platform_get_drvdata(pdev);
Tony Lindgren5de62b82010-12-07 16:26:58 -08001232 void __iomem *mask_reg = bank->base +
1233 OMAP_MPUIO_GPIO_MASKIT / bank->stride;
David Brownella6472532008-03-03 04:33:30 -08001234 unsigned long flags;
David Brownell11a78b72006-12-06 17:14:11 -08001235
David Brownella6472532008-03-03 04:33:30 -08001236 spin_lock_irqsave(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001237 bank->saved_wakeup = __raw_readl(mask_reg);
1238 __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
David Brownella6472532008-03-03 04:33:30 -08001239 spin_unlock_irqrestore(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001240
1241 return 0;
1242}
1243
Magnus Damm79ee0312009-07-08 13:22:04 +02001244static int omap_mpuio_resume_noirq(struct device *dev)
David Brownell11a78b72006-12-06 17:14:11 -08001245{
Magnus Damm79ee0312009-07-08 13:22:04 +02001246 struct platform_device *pdev = to_platform_device(dev);
David Brownell11a78b72006-12-06 17:14:11 -08001247 struct gpio_bank *bank = platform_get_drvdata(pdev);
Tony Lindgren5de62b82010-12-07 16:26:58 -08001248 void __iomem *mask_reg = bank->base +
1249 OMAP_MPUIO_GPIO_MASKIT / bank->stride;
David Brownella6472532008-03-03 04:33:30 -08001250 unsigned long flags;
David Brownell11a78b72006-12-06 17:14:11 -08001251
David Brownella6472532008-03-03 04:33:30 -08001252 spin_lock_irqsave(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001253 __raw_writel(bank->saved_wakeup, mask_reg);
David Brownella6472532008-03-03 04:33:30 -08001254 spin_unlock_irqrestore(&bank->lock, flags);
David Brownell11a78b72006-12-06 17:14:11 -08001255
1256 return 0;
1257}
1258
Alexey Dobriyan47145212009-12-14 18:00:08 -08001259static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
Magnus Damm79ee0312009-07-08 13:22:04 +02001260 .suspend_noirq = omap_mpuio_suspend_noirq,
1261 .resume_noirq = omap_mpuio_resume_noirq,
1262};
1263
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001264/* use platform_driver for this. */
David Brownell11a78b72006-12-06 17:14:11 -08001265static struct platform_driver omap_mpuio_driver = {
David Brownell11a78b72006-12-06 17:14:11 -08001266 .driver = {
1267 .name = "mpuio",
Magnus Damm79ee0312009-07-08 13:22:04 +02001268 .pm = &omap_mpuio_dev_pm_ops,
David Brownell11a78b72006-12-06 17:14:11 -08001269 },
1270};
1271
1272static struct platform_device omap_mpuio_device = {
1273 .name = "mpuio",
1274 .id = -1,
1275 .dev = {
1276 .driver = &omap_mpuio_driver.driver,
1277 }
1278 /* could list the /proc/iomem resources */
1279};
1280
1281static inline void mpuio_init(void)
1282{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001283 struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
1284 platform_set_drvdata(&omap_mpuio_device, bank);
David Brownellfcf126d2007-04-02 12:46:47 -07001285
David Brownell11a78b72006-12-06 17:14:11 -08001286 if (platform_driver_register(&omap_mpuio_driver) == 0)
1287 (void) platform_device_register(&omap_mpuio_device);
1288}
1289
1290#else
1291static inline void mpuio_init(void) {}
1292#endif /* 16xx */
1293
David Brownelle5c56ed2006-12-06 17:13:59 -08001294#else
1295
1296extern struct irq_chip mpuio_irq_chip;
1297
1298#define bank_is_mpuio(bank) 0
David Brownell11a78b72006-12-06 17:14:11 -08001299static inline void mpuio_init(void) {}
David Brownelle5c56ed2006-12-06 17:13:59 -08001300
1301#endif
1302
1303/*---------------------------------------------------------------------*/
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001304
David Brownell52e31342008-03-03 12:43:23 -08001305/* REVISIT these are stupid implementations! replace by ones that
1306 * don't switch on METHOD_* and which mostly avoid spinlocks
1307 */
1308
1309static int gpio_input(struct gpio_chip *chip, unsigned offset)
1310{
1311 struct gpio_bank *bank;
1312 unsigned long flags;
1313
1314 bank = container_of(chip, struct gpio_bank, chip);
1315 spin_lock_irqsave(&bank->lock, flags);
1316 _set_gpio_direction(bank, offset, 1);
1317 spin_unlock_irqrestore(&bank->lock, flags);
1318 return 0;
1319}
1320
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001321static int gpio_is_input(struct gpio_bank *bank, int mask)
1322{
1323 void __iomem *reg = bank->base;
1324
1325 switch (bank->method) {
1326 case METHOD_MPUIO:
Tony Lindgren5de62b82010-12-07 16:26:58 -08001327 reg += OMAP_MPUIO_IO_CNTL / bank->stride;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001328 break;
1329 case METHOD_GPIO_1510:
1330 reg += OMAP1510_GPIO_DIR_CONTROL;
1331 break;
1332 case METHOD_GPIO_1610:
1333 reg += OMAP1610_GPIO_DIRECTION;
1334 break;
Alistair Buxton7c006922009-09-22 10:02:58 +01001335 case METHOD_GPIO_7XX:
1336 reg += OMAP7XX_GPIO_DIR_CONTROL;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001337 break;
1338 case METHOD_GPIO_24XX:
1339 reg += OMAP24XX_GPIO_OE;
1340 break;
Charulatha V9f096862010-05-14 12:05:27 -07001341 case METHOD_GPIO_44XX:
1342 reg += OMAP4_GPIO_OE;
1343 break;
1344 default:
1345 WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
1346 return -EINVAL;
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001347 }
1348 return __raw_readl(reg) & mask;
1349}
1350
David Brownell52e31342008-03-03 12:43:23 -08001351static int gpio_get(struct gpio_chip *chip, unsigned offset)
1352{
Roger Quadrosb37c45b2009-08-05 16:53:24 +03001353 struct gpio_bank *bank;
1354 void __iomem *reg;
1355 int gpio;
1356 u32 mask;
1357
1358 gpio = chip->base + offset;
1359 bank = get_gpio_bank(gpio);
1360 reg = bank->base;
1361 mask = 1 << get_gpio_index(gpio);
1362
1363 if (gpio_is_input(bank, mask))
1364 return _get_gpio_datain(bank, gpio);
1365 else
1366 return _get_gpio_dataout(bank, gpio);
David Brownell52e31342008-03-03 12:43:23 -08001367}
1368
1369static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
1370{
1371 struct gpio_bank *bank;
1372 unsigned long flags;
1373
1374 bank = container_of(chip, struct gpio_bank, chip);
1375 spin_lock_irqsave(&bank->lock, flags);
1376 _set_gpio_dataout(bank, offset, value);
1377 _set_gpio_direction(bank, offset, 0);
1378 spin_unlock_irqrestore(&bank->lock, flags);
1379 return 0;
1380}
1381
Felipe Balbi168ef3d2010-05-26 14:42:23 -07001382static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
1383 unsigned debounce)
1384{
1385 struct gpio_bank *bank;
1386 unsigned long flags;
1387
1388 bank = container_of(chip, struct gpio_bank, chip);
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001389
1390 if (!bank->dbck) {
1391 bank->dbck = clk_get(bank->dev, "dbclk");
1392 if (IS_ERR(bank->dbck))
1393 dev_err(bank->dev, "Could not get gpio dbck\n");
1394 }
1395
Felipe Balbi168ef3d2010-05-26 14:42:23 -07001396 spin_lock_irqsave(&bank->lock, flags);
1397 _set_gpio_debounce(bank, offset, debounce);
1398 spin_unlock_irqrestore(&bank->lock, flags);
1399
1400 return 0;
1401}
1402
David Brownell52e31342008-03-03 12:43:23 -08001403static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1404{
1405 struct gpio_bank *bank;
1406 unsigned long flags;
1407
1408 bank = container_of(chip, struct gpio_bank, chip);
1409 spin_lock_irqsave(&bank->lock, flags);
1410 _set_gpio_dataout(bank, offset, value);
1411 spin_unlock_irqrestore(&bank->lock, flags);
1412}
1413
David Brownella007b702008-12-10 17:35:25 -08001414static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
1415{
1416 struct gpio_bank *bank;
1417
1418 bank = container_of(chip, struct gpio_bank, chip);
1419 return bank->virtual_irq_start + offset;
1420}
1421
David Brownell52e31342008-03-03 12:43:23 -08001422/*---------------------------------------------------------------------*/
1423
Tony Lindgren9a748052010-12-07 16:26:56 -08001424static void __init omap_gpio_show_rev(struct gpio_bank *bank)
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001425{
1426 u32 rev;
1427
Tony Lindgren9a748052010-12-07 16:26:56 -08001428 if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
1429 rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001430 else if (cpu_is_omap24xx() || cpu_is_omap34xx())
Tony Lindgren9a748052010-12-07 16:26:56 -08001431 rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001432 else if (cpu_is_omap44xx())
Tony Lindgren9a748052010-12-07 16:26:56 -08001433 rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001434 else
1435 return;
1436
1437 printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
1438 (rev >> 4) & 0x0f, rev & 0x0f);
1439}
1440
David Brownell8ba55c52008-02-26 11:10:50 -08001441/* This lock class tells lockdep that GPIO irqs are in a different
1442 * category than their parents, so it won't report false recursion.
1443 */
1444static struct lock_class_key gpio_lock_class;
1445
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001446static inline int init_gpio_info(struct platform_device *pdev)
1447{
1448 /* TODO: Analyze removing gpio_bank_count usage from driver code */
1449 gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank),
1450 GFP_KERNEL);
1451 if (!gpio_bank) {
1452 dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
1453 return -ENOMEM;
1454 }
1455 return 0;
1456}
1457
1458/* TODO: Cleanup cpu_is_* checks */
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001459static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
1460{
1461 if (cpu_class_is_omap2()) {
1462 if (cpu_is_omap44xx()) {
1463 __raw_writel(0xffffffff, bank->base +
1464 OMAP4_GPIO_IRQSTATUSCLR0);
1465 __raw_writel(0x00000000, bank->base +
1466 OMAP4_GPIO_DEBOUNCENABLE);
1467 /* Initialize interface clk ungated, module enabled */
1468 __raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
1469 } else if (cpu_is_omap34xx()) {
1470 __raw_writel(0x00000000, bank->base +
1471 OMAP24XX_GPIO_IRQENABLE1);
1472 __raw_writel(0xffffffff, bank->base +
1473 OMAP24XX_GPIO_IRQSTATUS1);
1474 __raw_writel(0x00000000, bank->base +
1475 OMAP24XX_GPIO_DEBOUNCE_EN);
1476
1477 /* Initialize interface clk ungated, module enabled */
1478 __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
1479 } else if (cpu_is_omap24xx()) {
1480 static const u32 non_wakeup_gpios[] = {
1481 0xe203ffc0, 0x08700040
1482 };
1483 if (id < ARRAY_SIZE(non_wakeup_gpios))
1484 bank->non_wakeup_gpios = non_wakeup_gpios[id];
1485 }
1486 } else if (cpu_class_is_omap1()) {
1487 if (bank_is_mpuio(bank))
Tony Lindgren5de62b82010-12-07 16:26:58 -08001488 __raw_writew(0xffff, bank->base +
1489 OMAP_MPUIO_GPIO_MASKIT / bank->stride);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001490 if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
1491 __raw_writew(0xffff, bank->base
1492 + OMAP1510_GPIO_INT_MASK);
1493 __raw_writew(0x0000, bank->base
1494 + OMAP1510_GPIO_INT_STATUS);
1495 }
1496 if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
1497 __raw_writew(0x0000, bank->base
1498 + OMAP1610_GPIO_IRQENABLE1);
1499 __raw_writew(0xffff, bank->base
1500 + OMAP1610_GPIO_IRQSTATUS1);
1501 __raw_writew(0x0014, bank->base
1502 + OMAP1610_GPIO_SYSCONFIG);
1503
1504 /*
1505 * Enable system clock for GPIO module.
1506 * The CAM_CLK_CTRL *is* really the right place.
1507 */
1508 omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
1509 ULPD_CAM_CLK_CTRL);
1510 }
1511 if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
1512 __raw_writel(0xffffffff, bank->base
1513 + OMAP7XX_GPIO_INT_MASK);
1514 __raw_writel(0x00000000, bank->base
1515 + OMAP7XX_GPIO_INT_STATUS);
1516 }
1517 }
1518}
1519
Russell Kingd52b31d2011-05-27 13:56:12 -07001520static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001521{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001522 int j;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001523 static int gpio;
1524
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001525 bank->mod_usage = 0;
1526 /*
1527 * REVISIT eventually switch from OMAP-specific gpio structs
1528 * over to the generic ones
1529 */
1530 bank->chip.request = omap_gpio_request;
1531 bank->chip.free = omap_gpio_free;
1532 bank->chip.direction_input = gpio_input;
1533 bank->chip.get = gpio_get;
1534 bank->chip.direction_output = gpio_output;
1535 bank->chip.set_debounce = gpio_debounce;
1536 bank->chip.set = gpio_set;
1537 bank->chip.to_irq = gpio_2irq;
1538 if (bank_is_mpuio(bank)) {
1539 bank->chip.label = "mpuio";
1540#ifdef CONFIG_ARCH_OMAP16XX
1541 bank->chip.dev = &omap_mpuio_device.dev;
1542#endif
1543 bank->chip.base = OMAP_MPUIO(0);
1544 } else {
1545 bank->chip.label = "gpio";
1546 bank->chip.base = gpio;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001547 gpio += bank->width;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001548 }
Kevin Hilmand5f46242011-04-21 09:23:00 -07001549 bank->chip.ngpio = bank->width;
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001550
1551 gpiochip_add(&bank->chip);
1552
1553 for (j = bank->virtual_irq_start;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001554 j < bank->virtual_irq_start + bank->width; j++) {
Thomas Gleixner1475b852011-03-22 17:11:09 +01001555 irq_set_lockdep_class(j, &gpio_lock_class);
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001556 irq_set_chip_data(j, bank);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001557 if (bank_is_mpuio(bank))
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001558 irq_set_chip(j, &mpuio_irq_chip);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001559 else
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001560 irq_set_chip(j, &gpio_irq_chip);
1561 irq_set_handler(j, handle_simple_irq);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001562 set_irq_flags(j, IRQF_VALID);
1563 }
Thomas Gleixner6845664a2011-03-24 13:25:22 +01001564 irq_set_chained_handler(bank->irq, gpio_irq_handler);
1565 irq_set_handler_data(bank->irq, bank);
Varadarajan, Charulatha2fae7fb2010-12-07 16:26:55 -08001566}
1567
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001568static int __devinit omap_gpio_probe(struct platform_device *pdev)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001569{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001570 static int gpio_init_done;
1571 struct omap_gpio_platform_data *pdata;
1572 struct resource *res;
1573 int id;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001574 struct gpio_bank *bank;
1575
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001576 if (!pdev->dev.platform_data)
1577 return -EINVAL;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001578
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001579 pdata = pdev->dev.platform_data;
Syed Mohammed Khasim56a25642006-12-06 17:14:08 -08001580
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001581 if (!gpio_init_done) {
1582 int ret;
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001583
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001584 ret = init_gpio_info(pdev);
1585 if (ret)
1586 return ret;
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001587 }
1588
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001589 id = pdev->id;
1590 bank = &gpio_bank[id];
1591
1592 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1593 if (unlikely(!res)) {
1594 dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
1595 return -ENODEV;
1596 }
1597
1598 bank->irq = res->start;
1599 bank->virtual_irq_start = pdata->virtual_irq_start;
1600 bank->method = pdata->bank_type;
1601 bank->dev = &pdev->dev;
1602 bank->dbck_flag = pdata->dbck_flag;
Tony Lindgren5de62b82010-12-07 16:26:58 -08001603 bank->stride = pdata->bank_stride;
Kevin Hilmand5f46242011-04-21 09:23:00 -07001604 bank->width = pdata->bank_width;
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001605
1606 spin_lock_init(&bank->lock);
1607
1608 /* Static mapping, never released */
1609 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1610 if (unlikely(!res)) {
1611 dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
1612 return -ENODEV;
1613 }
1614
1615 bank->base = ioremap(res->start, resource_size(res));
1616 if (!bank->base) {
1617 dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
1618 return -ENOMEM;
1619 }
1620
1621 pm_runtime_enable(bank->dev);
1622 pm_runtime_get_sync(bank->dev);
1623
1624 omap_gpio_mod_init(bank, id);
1625 omap_gpio_chip_init(bank);
Tony Lindgren9a748052010-12-07 16:26:56 -08001626 omap_gpio_show_rev(bank);
Tony Lindgren9f7065d2009-10-19 15:25:20 -07001627
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001628 if (!gpio_init_done)
1629 gpio_init_done = 1;
1630
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001631 return 0;
1632}
1633
Tony Lindgren140455f2010-02-12 12:26:48 -08001634#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001635static int omap_gpio_suspend(void)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001636{
1637 int i;
1638
Syed Mohammed, Khasim5492fb12007-11-29 16:15:11 -08001639 if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
Tony Lindgren92105bb2005-09-07 17:20:26 +01001640 return 0;
1641
1642 for (i = 0; i < gpio_bank_count; i++) {
1643 struct gpio_bank *bank = &gpio_bank[i];
1644 void __iomem *wake_status;
1645 void __iomem *wake_clear;
1646 void __iomem *wake_set;
David Brownella6472532008-03-03 04:33:30 -08001647 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001648
1649 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -08001650#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren92105bb2005-09-07 17:20:26 +01001651 case METHOD_GPIO_1610:
1652 wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
1653 wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
1654 wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
1655 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001656#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001657#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001658 case METHOD_GPIO_24XX:
Tero Kristo723fdb72008-11-26 14:35:16 -08001659 wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001660 wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
1661 wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
1662 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001663#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301664#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001665 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301666 wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
1667 wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
1668 wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
1669 break;
1670#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +01001671 default:
1672 continue;
1673 }
1674
David Brownella6472532008-03-03 04:33:30 -08001675 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001676 bank->saved_wakeup = __raw_readl(wake_status);
1677 __raw_writel(0xffffffff, wake_clear);
1678 __raw_writel(bank->suspend_wakeup, wake_set);
David Brownella6472532008-03-03 04:33:30 -08001679 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001680 }
1681
1682 return 0;
1683}
1684
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001685static void omap_gpio_resume(void)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001686{
1687 int i;
1688
Tero Kristo723fdb72008-11-26 14:35:16 -08001689 if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001690 return;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001691
1692 for (i = 0; i < gpio_bank_count; i++) {
1693 struct gpio_bank *bank = &gpio_bank[i];
1694 void __iomem *wake_clear;
1695 void __iomem *wake_set;
David Brownella6472532008-03-03 04:33:30 -08001696 unsigned long flags;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001697
1698 switch (bank->method) {
David Brownelle5c56ed2006-12-06 17:13:59 -08001699#ifdef CONFIG_ARCH_OMAP16XX
Tony Lindgren92105bb2005-09-07 17:20:26 +01001700 case METHOD_GPIO_1610:
1701 wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
1702 wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
1703 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001704#endif
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001705#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
Tony Lindgren92105bb2005-09-07 17:20:26 +01001706 case METHOD_GPIO_24XX:
Tony Lindgren0d9356c2006-09-25 12:41:45 +03001707 wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
1708 wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001709 break;
David Brownelle5c56ed2006-12-06 17:13:59 -08001710#endif
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301711#ifdef CONFIG_ARCH_OMAP4
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001712 case METHOD_GPIO_44XX:
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301713 wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
1714 wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
1715 break;
1716#endif
Tony Lindgren92105bb2005-09-07 17:20:26 +01001717 default:
1718 continue;
1719 }
1720
David Brownella6472532008-03-03 04:33:30 -08001721 spin_lock_irqsave(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001722 __raw_writel(0xffffffff, wake_clear);
1723 __raw_writel(bank->saved_wakeup, wake_set);
David Brownella6472532008-03-03 04:33:30 -08001724 spin_unlock_irqrestore(&bank->lock, flags);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001725 }
Tony Lindgren92105bb2005-09-07 17:20:26 +01001726}
1727
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001728static struct syscore_ops omap_gpio_syscore_ops = {
Tony Lindgren92105bb2005-09-07 17:20:26 +01001729 .suspend = omap_gpio_suspend,
1730 .resume = omap_gpio_resume,
1731};
1732
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001733#endif
1734
Tony Lindgren140455f2010-02-12 12:26:48 -08001735#ifdef CONFIG_ARCH_OMAP2PLUS
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001736
1737static int workaround_enabled;
1738
Paul Walmsley72e06d02010-12-21 21:05:16 -07001739void omap2_gpio_prepare_for_idle(int off_mode)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001740{
1741 int i, c = 0;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001742 int min = 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001743
Tero Kristoa118b5f2008-12-22 14:27:12 +02001744 if (cpu_is_omap34xx())
1745 min = 1;
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001746
Tero Kristoa118b5f2008-12-22 14:27:12 +02001747 for (i = min; i < gpio_bank_count; i++) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001748 struct gpio_bank *bank = &gpio_bank[i];
Sanjeev Premica828762010-09-23 18:27:18 -07001749 u32 l1 = 0, l2 = 0;
Kevin Hilman0aed04352010-09-22 16:06:27 -07001750 int j;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001751
Kevin Hilman0aed04352010-09-22 16:06:27 -07001752 for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
Kevin Hilman8865b9b2009-01-27 11:15:34 -08001753 clk_disable(bank->dbck);
1754
Paul Walmsley72e06d02010-12-21 21:05:16 -07001755 if (!off_mode)
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001756 continue;
1757
1758 /* If going to OFF, remove triggering for all
1759 * non-wakeup GPIOs. Otherwise spurious IRQs will be
1760 * generated. See OMAP2420 Errata item 1.101. */
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001761 if (!(bank->enabled_non_wakeup_gpios))
1762 continue;
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001763
1764 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1765 bank->saved_datain = __raw_readl(bank->base +
1766 OMAP24XX_GPIO_DATAIN);
1767 l1 = __raw_readl(bank->base +
1768 OMAP24XX_GPIO_FALLINGDETECT);
1769 l2 = __raw_readl(bank->base +
1770 OMAP24XX_GPIO_RISINGDETECT);
1771 }
1772
1773 if (cpu_is_omap44xx()) {
1774 bank->saved_datain = __raw_readl(bank->base +
1775 OMAP4_GPIO_DATAIN);
1776 l1 = __raw_readl(bank->base +
1777 OMAP4_GPIO_FALLINGDETECT);
1778 l2 = __raw_readl(bank->base +
1779 OMAP4_GPIO_RISINGDETECT);
1780 }
1781
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001782 bank->saved_fallingdetect = l1;
1783 bank->saved_risingdetect = l2;
1784 l1 &= ~bank->enabled_non_wakeup_gpios;
1785 l2 &= ~bank->enabled_non_wakeup_gpios;
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001786
1787 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1788 __raw_writel(l1, bank->base +
1789 OMAP24XX_GPIO_FALLINGDETECT);
1790 __raw_writel(l2, bank->base +
1791 OMAP24XX_GPIO_RISINGDETECT);
1792 }
1793
1794 if (cpu_is_omap44xx()) {
1795 __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
1796 __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
1797 }
1798
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001799 c++;
1800 }
1801 if (!c) {
1802 workaround_enabled = 0;
1803 return;
1804 }
1805 workaround_enabled = 1;
1806}
1807
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001808void omap2_gpio_resume_after_idle(void)
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001809{
1810 int i;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001811 int min = 0;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001812
Tero Kristoa118b5f2008-12-22 14:27:12 +02001813 if (cpu_is_omap34xx())
1814 min = 1;
1815 for (i = min; i < gpio_bank_count; i++) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001816 struct gpio_bank *bank = &gpio_bank[i];
Sanjeev Premica828762010-09-23 18:27:18 -07001817 u32 l = 0, gen, gen0, gen1;
Kevin Hilman0aed04352010-09-22 16:06:27 -07001818 int j;
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001819
Kevin Hilman0aed04352010-09-22 16:06:27 -07001820 for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
Kevin Hilman8865b9b2009-01-27 11:15:34 -08001821 clk_enable(bank->dbck);
1822
Kevin Hilman43ffcd92009-01-27 11:09:24 -08001823 if (!workaround_enabled)
1824 continue;
1825
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001826 if (!(bank->enabled_non_wakeup_gpios))
1827 continue;
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001828
1829 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1830 __raw_writel(bank->saved_fallingdetect,
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001831 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001832 __raw_writel(bank->saved_risingdetect,
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001833 bank->base + OMAP24XX_GPIO_RISINGDETECT);
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001834 l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
1835 }
1836
1837 if (cpu_is_omap44xx()) {
1838 __raw_writel(bank->saved_fallingdetect,
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301839 bank->base + OMAP4_GPIO_FALLINGDETECT);
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001840 __raw_writel(bank->saved_risingdetect,
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301841 bank->base + OMAP4_GPIO_RISINGDETECT);
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001842 l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
1843 }
1844
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001845 /* Check if any of the non-wakeup interrupt GPIOs have changed
1846 * state. If so, generate an IRQ by software. This is
1847 * horribly racy, but it's the best we can do to work around
1848 * this silicon bug. */
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001849 l ^= bank->saved_datain;
Tero Kristoa118b5f2008-12-22 14:27:12 +02001850 l &= bank->enabled_non_wakeup_gpios;
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001851
1852 /*
1853 * No need to generate IRQs for the rising edge for gpio IRQs
1854 * configured with falling edge only; and vice versa.
1855 */
1856 gen0 = l & bank->saved_fallingdetect;
1857 gen0 &= bank->saved_datain;
1858
1859 gen1 = l & bank->saved_risingdetect;
1860 gen1 &= ~(bank->saved_datain);
1861
1862 /* FIXME: Consider GPIO IRQs with level detections properly! */
1863 gen = l & (~(bank->saved_fallingdetect) &
1864 ~(bank->saved_risingdetect));
1865 /* Consider all GPIO IRQs needed to be updated */
1866 gen |= gen0 | gen1;
1867
1868 if (gen) {
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001869 u32 old0, old1;
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001870
Sergio Aguirref00d6492010-03-03 16:21:08 +00001871 if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001872 old0 = __raw_readl(bank->base +
1873 OMAP24XX_GPIO_LEVELDETECT0);
1874 old1 = __raw_readl(bank->base +
1875 OMAP24XX_GPIO_LEVELDETECT1);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001876 __raw_writel(old0 | gen, bank->base +
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001877 OMAP24XX_GPIO_LEVELDETECT0);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001878 __raw_writel(old1 | gen, bank->base +
Eero Nurkkala82dbb9d2009-08-28 10:51:36 -07001879 OMAP24XX_GPIO_LEVELDETECT1);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001880 __raw_writel(old0, bank->base +
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001881 OMAP24XX_GPIO_LEVELDETECT0);
Sergio Aguirref00d6492010-03-03 16:21:08 +00001882 __raw_writel(old1, bank->base +
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001883 OMAP24XX_GPIO_LEVELDETECT1);
1884 }
1885
1886 if (cpu_is_omap44xx()) {
1887 old0 = __raw_readl(bank->base +
1888 OMAP4_GPIO_LEVELDETECT0);
1889 old1 = __raw_readl(bank->base +
Syed Rafiuddin78a1a6d2009-07-28 18:57:30 +05301890 OMAP4_GPIO_LEVELDETECT1);
Tony Lindgren3f1686a2010-02-15 09:27:25 -08001891 __raw_writel(old0 | l, bank->base +
1892 OMAP4_GPIO_LEVELDETECT0);
1893 __raw_writel(old1 | l, bank->base +
1894 OMAP4_GPIO_LEVELDETECT1);
1895 __raw_writel(old0, bank->base +
1896 OMAP4_GPIO_LEVELDETECT0);
1897 __raw_writel(old1, bank->base +
1898 OMAP4_GPIO_LEVELDETECT1);
1899 }
Juha Yrjola3ac4fa92006-12-06 17:13:52 -08001900 }
1901 }
1902
1903}
1904
Tony Lindgren92105bb2005-09-07 17:20:26 +01001905#endif
1906
Tony Lindgrena8eb7ca2010-02-12 12:26:48 -08001907#ifdef CONFIG_ARCH_OMAP3
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301908/* save the registers of bank 2-6 */
1909void omap_gpio_save_context(void)
1910{
1911 int i;
1912
1913 /* saving banks from 2-6 only since GPIO1 is in WKUP */
1914 for (i = 1; i < gpio_bank_count; i++) {
1915 struct gpio_bank *bank = &gpio_bank[i];
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301916 gpio_context[i].irqenable1 =
1917 __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
1918 gpio_context[i].irqenable2 =
1919 __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
1920 gpio_context[i].wake_en =
1921 __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
1922 gpio_context[i].ctrl =
1923 __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
1924 gpio_context[i].oe =
1925 __raw_readl(bank->base + OMAP24XX_GPIO_OE);
1926 gpio_context[i].leveldetect0 =
1927 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
1928 gpio_context[i].leveldetect1 =
1929 __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
1930 gpio_context[i].risingdetect =
1931 __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
1932 gpio_context[i].fallingdetect =
1933 __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
1934 gpio_context[i].dataout =
1935 __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301936 }
1937}
1938
1939/* restore the required registers of bank 2-6 */
1940void omap_gpio_restore_context(void)
1941{
1942 int i;
1943
1944 for (i = 1; i < gpio_bank_count; i++) {
1945 struct gpio_bank *bank = &gpio_bank[i];
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301946 __raw_writel(gpio_context[i].irqenable1,
1947 bank->base + OMAP24XX_GPIO_IRQENABLE1);
1948 __raw_writel(gpio_context[i].irqenable2,
1949 bank->base + OMAP24XX_GPIO_IRQENABLE2);
1950 __raw_writel(gpio_context[i].wake_en,
1951 bank->base + OMAP24XX_GPIO_WAKE_EN);
1952 __raw_writel(gpio_context[i].ctrl,
1953 bank->base + OMAP24XX_GPIO_CTRL);
1954 __raw_writel(gpio_context[i].oe,
1955 bank->base + OMAP24XX_GPIO_OE);
1956 __raw_writel(gpio_context[i].leveldetect0,
1957 bank->base + OMAP24XX_GPIO_LEVELDETECT0);
1958 __raw_writel(gpio_context[i].leveldetect1,
1959 bank->base + OMAP24XX_GPIO_LEVELDETECT1);
1960 __raw_writel(gpio_context[i].risingdetect,
1961 bank->base + OMAP24XX_GPIO_RISINGDETECT);
1962 __raw_writel(gpio_context[i].fallingdetect,
1963 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
1964 __raw_writel(gpio_context[i].dataout,
1965 bank->base + OMAP24XX_GPIO_DATAOUT);
Rajendra Nayak40c670f2008-09-26 17:47:48 +05301966 }
1967}
1968#endif
1969
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001970static struct platform_driver omap_gpio_driver = {
1971 .probe = omap_gpio_probe,
1972 .driver = {
1973 .name = "omap_gpio",
1974 },
1975};
1976
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001977/*
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001978 * gpio driver register needs to be done before
1979 * machine_init functions access gpio APIs.
1980 * Hence omap_gpio_drv_reg() is a postcore_initcall.
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001981 */
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001982static int __init omap_gpio_drv_reg(void)
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001983{
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001984 return platform_driver_register(&omap_gpio_driver);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001985}
Varadarajan, Charulatha77640aa2010-12-07 16:26:57 -08001986postcore_initcall(omap_gpio_drv_reg);
Tony Lindgren5e1c5ff2005-07-10 19:58:15 +01001987
Tony Lindgren92105bb2005-09-07 17:20:26 +01001988static int __init omap_gpio_sysinit(void)
1989{
David Brownell11a78b72006-12-06 17:14:11 -08001990 mpuio_init();
1991
Tony Lindgren140455f2010-02-12 12:26:48 -08001992#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001993 if (cpu_is_omap16xx() || cpu_class_is_omap2())
1994 register_syscore_ops(&omap_gpio_syscore_ops);
Tony Lindgren92105bb2005-09-07 17:20:26 +01001995#endif
1996
Rafael J. Wysocki3c437ff2011-04-22 22:02:46 +02001997 return 0;
Tony Lindgren92105bb2005-09-07 17:20:26 +01001998}
1999
Tony Lindgren92105bb2005-09-07 17:20:26 +01002000arch_initcall(omap_gpio_sysinit);