aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap1/gpio15xx.c2
-rw-r--r--arch/arm/mach-omap1/gpio16xx.c3
-rw-r--r--arch/arm/mach-omap1/gpio7xx.c2
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h3
-rw-r--r--drivers/gpio/gpio-omap.c157
5 files changed, 53 insertions, 114 deletions
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index f8c15eabf06e..2adfece30ce6 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -42,6 +42,7 @@ static struct omap_gpio_reg_offs omap15xx_mpuio_regs = {
42 .irqstatus = OMAP_MPUIO_GPIO_INT, 42 .irqstatus = OMAP_MPUIO_GPIO_INT,
43 .irqenable = OMAP_MPUIO_GPIO_MASKIT, 43 .irqenable = OMAP_MPUIO_GPIO_MASKIT,
44 .irqenable_inv = true, 44 .irqenable_inv = true,
45 .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE,
45}; 46};
46 47
47static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { 48static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
@@ -83,6 +84,7 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = {
83 .irqstatus = OMAP1510_GPIO_INT_STATUS, 84 .irqstatus = OMAP1510_GPIO_INT_STATUS,
84 .irqenable = OMAP1510_GPIO_INT_MASK, 85 .irqenable = OMAP1510_GPIO_INT_MASK,
85 .irqenable_inv = true, 86 .irqenable_inv = true,
87 .irqctrl = OMAP1510_GPIO_INT_CONTROL,
86}; 88};
87 89
88static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { 90static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 1eb47e2760d8..46bb57a8cb7d 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -45,6 +45,7 @@ static struct omap_gpio_reg_offs omap16xx_mpuio_regs = {
45 .irqstatus = OMAP_MPUIO_GPIO_INT, 45 .irqstatus = OMAP_MPUIO_GPIO_INT,
46 .irqenable = OMAP_MPUIO_GPIO_MASKIT, 46 .irqenable = OMAP_MPUIO_GPIO_MASKIT,
47 .irqenable_inv = true, 47 .irqenable_inv = true,
48 .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE,
48}; 49};
49 50
50static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { 51static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
@@ -90,6 +91,8 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = {
90 .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1, 91 .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1,
91 .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1, 92 .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1,
92 .wkup_en = OMAP1610_GPIO_WAKEUPENABLE, 93 .wkup_en = OMAP1610_GPIO_WAKEUPENABLE,
94 .edgectrl1 = OMAP1610_GPIO_EDGE_CTRL1,
95 .edgectrl2 = OMAP1610_GPIO_EDGE_CTRL2,
93}; 96};
94 97
95static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { 98static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index 923eaa1df955..207a23cfa1a0 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -47,6 +47,7 @@ static struct omap_gpio_reg_offs omap7xx_mpuio_regs = {
47 .irqstatus = OMAP_MPUIO_GPIO_INT / 2, 47 .irqstatus = OMAP_MPUIO_GPIO_INT / 2,
48 .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2, 48 .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2,
49 .irqenable_inv = true, 49 .irqenable_inv = true,
50 .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE >> 1,
50}; 51};
51 52
52static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { 53static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
@@ -88,6 +89,7 @@ static struct omap_gpio_reg_offs omap7xx_gpio_regs = {
88 .irqstatus = OMAP7XX_GPIO_INT_STATUS, 89 .irqstatus = OMAP7XX_GPIO_INT_STATUS,
89 .irqenable = OMAP7XX_GPIO_INT_MASK, 90 .irqenable = OMAP7XX_GPIO_INT_MASK,
90 .irqenable_inv = true, 91 .irqenable_inv = true,
92 .irqctrl = OMAP7XX_GPIO_INT_CONTROL,
91}; 93};
92 94
93static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { 95static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 914c976b1de0..9e403e54f6f9 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -195,6 +195,9 @@ struct omap_gpio_reg_offs {
195 u16 leveldetect1; 195 u16 leveldetect1;
196 u16 risingdetect; 196 u16 risingdetect;
197 u16 fallingdetect; 197 u16 fallingdetect;
198 u16 irqctrl;
199 u16 edgectrl1;
200 u16 edgectrl2;
198 201
199 bool irqenable_inv; 202 bool irqenable_inv;
200}; 203};
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index ceb9edf16dab..f39d9e4967b2 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -199,52 +199,32 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
199 __raw_writel(val, reg); 199 __raw_writel(val, reg);
200} 200}
201 201
202#ifdef CONFIG_ARCH_OMAP2PLUS 202static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
203static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
204 int trigger) 203 int trigger)
205{ 204{
206 void __iomem *base = bank->base; 205 void __iomem *base = bank->base;
207 u32 gpio_bit = 1 << gpio; 206 u32 gpio_bit = 1 << gpio;
208 207
209 if (cpu_is_omap44xx()) { 208 _gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
210 _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit, 209 trigger & IRQ_TYPE_LEVEL_LOW);
211 trigger & IRQ_TYPE_LEVEL_LOW); 210 _gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
212 _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit, 211 trigger & IRQ_TYPE_LEVEL_HIGH);
213 trigger & IRQ_TYPE_LEVEL_HIGH); 212 _gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
214 _gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit, 213 trigger & IRQ_TYPE_EDGE_RISING);
215 trigger & IRQ_TYPE_EDGE_RISING); 214 _gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
216 _gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit, 215 trigger & IRQ_TYPE_EDGE_FALLING);
217 trigger & IRQ_TYPE_EDGE_FALLING); 216
218 } else { 217 if (likely(!(bank->non_wakeup_gpios & gpio_bit)))
219 _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, 218 _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
220 trigger & IRQ_TYPE_LEVEL_LOW); 219
221 _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
222 trigger & IRQ_TYPE_LEVEL_HIGH);
223 _gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
224 trigger & IRQ_TYPE_EDGE_RISING);
225 _gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
226 trigger & IRQ_TYPE_EDGE_FALLING);
227 }
228 if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
229 if (cpu_is_omap44xx()) {
230 _gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit,
231 trigger != 0);
232 } else {
233 /*
234 * GPIO wakeup request can only be generated on edge
235 * transitions
236 */
237 if (trigger & IRQ_TYPE_EDGE_BOTH)
238 __raw_writel(1 << gpio, bank->base
239 + OMAP24XX_GPIO_SETWKUENA);
240 else
241 __raw_writel(1 << gpio, bank->base
242 + OMAP24XX_GPIO_CLEARWKUENA);
243 }
244 }
245 /* This part needs to be executed always for OMAP{34xx, 44xx} */ 220 /* This part needs to be executed always for OMAP{34xx, 44xx} */
246 if (cpu_is_omap34xx() || cpu_is_omap44xx() || 221 if (!bank->regs->irqctrl) {
247 (bank->non_wakeup_gpios & gpio_bit)) { 222 /* On omap24xx proceed only when valid GPIO bit is set */
223 if (bank->non_wakeup_gpios) {
224 if (!(bank->non_wakeup_gpios & gpio_bit))
225 goto exit;
226 }
227
248 /* 228 /*
249 * Log the edge gpio and manually trigger the IRQ 229 * Log the edge gpio and manually trigger the IRQ
250 * after resume if the input level changes 230 * after resume if the input level changes
@@ -257,11 +237,11 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
257 bank->enabled_non_wakeup_gpios &= ~gpio_bit; 237 bank->enabled_non_wakeup_gpios &= ~gpio_bit;
258 } 238 }
259 239
240exit:
260 bank->level_mask = 241 bank->level_mask =
261 __raw_readl(bank->base + bank->regs->leveldetect0) | 242 __raw_readl(bank->base + bank->regs->leveldetect0) |
262 __raw_readl(bank->base + bank->regs->leveldetect1); 243 __raw_readl(bank->base + bank->regs->leveldetect1);
263} 244}
264#endif
265 245
266#ifdef CONFIG_ARCH_OMAP1 246#ifdef CONFIG_ARCH_OMAP1
267/* 247/*
@@ -273,23 +253,10 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
273 void __iomem *reg = bank->base; 253 void __iomem *reg = bank->base;
274 u32 l = 0; 254 u32 l = 0;
275 255
276 switch (bank->method) { 256 if (!bank->regs->irqctrl)
277 case METHOD_MPUIO:
278 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
279 break;
280#ifdef CONFIG_ARCH_OMAP15XX
281 case METHOD_GPIO_1510:
282 reg += OMAP1510_GPIO_INT_CONTROL;
283 break;
284#endif
285#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
286 case METHOD_GPIO_7XX:
287 reg += OMAP7XX_GPIO_INT_CONTROL;
288 break;
289#endif
290 default:
291 return; 257 return;
292 } 258
259 reg += bank->regs->irqctrl;
293 260
294 l = __raw_readl(reg); 261 l = __raw_readl(reg);
295 if ((l >> gpio) & 1) 262 if ((l >> gpio) & 1)
@@ -299,31 +266,21 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
299 266
300 __raw_writel(l, reg); 267 __raw_writel(l, reg);
301} 268}
269#else
270static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
302#endif 271#endif
303 272
304static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) 273static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
305{ 274{
306 void __iomem *reg = bank->base; 275 void __iomem *reg = bank->base;
276 void __iomem *base = bank->base;
307 u32 l = 0; 277 u32 l = 0;
308 278
309 switch (bank->method) { 279 if (bank->regs->leveldetect0 && bank->regs->wkup_en) {
310#ifdef CONFIG_ARCH_OMAP1 280 set_gpio_trigger(bank, gpio, trigger);
311 case METHOD_MPUIO: 281 } else if (bank->regs->irqctrl) {
312 reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; 282 reg += bank->regs->irqctrl;
313 l = __raw_readl(reg); 283
314 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
315 bank->toggle_mask |= 1 << gpio;
316 if (trigger & IRQ_TYPE_EDGE_RISING)
317 l |= 1 << gpio;
318 else if (trigger & IRQ_TYPE_EDGE_FALLING)
319 l &= ~(1 << gpio);
320 else
321 goto bad;
322 break;
323#endif
324#ifdef CONFIG_ARCH_OMAP15XX
325 case METHOD_GPIO_1510:
326 reg += OMAP1510_GPIO_INT_CONTROL;
327 l = __raw_readl(reg); 284 l = __raw_readl(reg);
328 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) 285 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
329 bank->toggle_mask |= 1 << gpio; 286 bank->toggle_mask |= 1 << gpio;
@@ -332,15 +289,15 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
332 else if (trigger & IRQ_TYPE_EDGE_FALLING) 289 else if (trigger & IRQ_TYPE_EDGE_FALLING)
333 l &= ~(1 << gpio); 290 l &= ~(1 << gpio);
334 else 291 else
335 goto bad; 292 return -EINVAL;
336 break; 293
337#endif 294 __raw_writel(l, reg);
338#ifdef CONFIG_ARCH_OMAP16XX 295 } else if (bank->regs->edgectrl1) {
339 case METHOD_GPIO_1610:
340 if (gpio & 0x08) 296 if (gpio & 0x08)
341 reg += OMAP1610_GPIO_EDGE_CTRL2; 297 reg += bank->regs->edgectrl2;
342 else 298 else
343 reg += OMAP1610_GPIO_EDGE_CTRL1; 299 reg += bank->regs->edgectrl1;
300
344 gpio &= 0x07; 301 gpio &= 0x07;
345 l = __raw_readl(reg); 302 l = __raw_readl(reg);
346 l &= ~(3 << (gpio << 1)); 303 l &= ~(3 << (gpio << 1));
@@ -348,40 +305,12 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
348 l |= 2 << (gpio << 1); 305 l |= 2 << (gpio << 1);
349 if (trigger & IRQ_TYPE_EDGE_FALLING) 306 if (trigger & IRQ_TYPE_EDGE_FALLING)
350 l |= 1 << (gpio << 1); 307 l |= 1 << (gpio << 1);
351 if (trigger) 308
352 /* Enable wake-up during idle for dynamic tick */ 309 /* Enable wake-up during idle for dynamic tick */
353 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA); 310 _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger);
354 else 311 __raw_writel(l, reg);
355 __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
356 break;
357#endif
358#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
359 case METHOD_GPIO_7XX:
360 reg += OMAP7XX_GPIO_INT_CONTROL;
361 l = __raw_readl(reg);
362 if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
363 bank->toggle_mask |= 1 << gpio;
364 if (trigger & IRQ_TYPE_EDGE_RISING)
365 l |= 1 << gpio;
366 else if (trigger & IRQ_TYPE_EDGE_FALLING)
367 l &= ~(1 << gpio);
368 else
369 goto bad;
370 break;
371#endif
372#ifdef CONFIG_ARCH_OMAP2PLUS
373 case METHOD_GPIO_24XX:
374 case METHOD_GPIO_44XX:
375 set_24xx_gpio_triggering(bank, gpio, trigger);
376 return 0;
377#endif
378 default:
379 goto bad;
380 } 312 }
381 __raw_writel(l, reg);
382 return 0; 313 return 0;
383bad:
384 return -EINVAL;
385} 314}
386 315
387static int gpio_irq_type(struct irq_data *d, unsigned type) 316static int gpio_irq_type(struct irq_data *d, unsigned type)