diff options
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | 7 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/mfp-pxa2xx.c | 21 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 6 | ||||
| -rw-r--r-- | arch/arm/mach-sa1100/generic.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pxa.c | 21 | ||||
| -rw-r--r-- | include/linux/gpio-pxa.h | 4 |
6 files changed, 55 insertions, 6 deletions
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index c54cef25895c..cbf51ae81855 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * | 17 | * |
| 18 | * bit 23 - Input/Output (PXA2xx specific) | 18 | * bit 23 - Input/Output (PXA2xx specific) |
| 19 | * bit 24 - Wakeup Enable(PXA2xx specific) | 19 | * bit 24 - Wakeup Enable(PXA2xx specific) |
| 20 | * bit 25 - Keep Output (PXA2xx specific) | ||
| 20 | */ | 21 | */ |
| 21 | 22 | ||
| 22 | #define MFP_DIR_IN (0x0 << 23) | 23 | #define MFP_DIR_IN (0x0 << 23) |
| @@ -25,6 +26,12 @@ | |||
| 25 | #define MFP_DIR(x) (((x) >> 23) & 0x1) | 26 | #define MFP_DIR(x) (((x) >> 23) & 0x1) |
| 26 | 27 | ||
| 27 | #define MFP_LPM_CAN_WAKEUP (0x1 << 24) | 28 | #define MFP_LPM_CAN_WAKEUP (0x1 << 24) |
| 29 | |||
| 30 | /* | ||
| 31 | * MFP_LPM_KEEP_OUTPUT must be specified for pins that need to | ||
| 32 | * retain their last output level (low or high). | ||
| 33 | * Note: MFP_LPM_KEEP_OUTPUT has no effect on pins configured for input. | ||
| 34 | */ | ||
| 28 | #define MFP_LPM_KEEP_OUTPUT (0x1 << 25) | 35 | #define MFP_LPM_KEEP_OUTPUT (0x1 << 25) |
| 29 | 36 | ||
| 30 | #define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) | 37 | #define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) |
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index b0a842887780..ef0426a159d4 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) | 33 | #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) |
| 34 | #define GPLR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5)) | 34 | #define GPLR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5)) |
| 35 | #define GPDR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c) | 35 | #define GPDR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c) |
| 36 | #define GPSR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x18) | ||
| 37 | #define GPCR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x24) | ||
| 36 | 38 | ||
| 37 | #define PWER_WE35 (1 << 24) | 39 | #define PWER_WE35 (1 << 24) |
| 38 | 40 | ||
| @@ -348,6 +350,7 @@ static inline void pxa27x_mfp_init(void) {} | |||
| 348 | #ifdef CONFIG_PM | 350 | #ifdef CONFIG_PM |
| 349 | static unsigned long saved_gafr[2][4]; | 351 | static unsigned long saved_gafr[2][4]; |
| 350 | static unsigned long saved_gpdr[4]; | 352 | static unsigned long saved_gpdr[4]; |
| 353 | static unsigned long saved_gplr[4]; | ||
| 351 | static unsigned long saved_pgsr[4]; | 354 | static unsigned long saved_pgsr[4]; |
| 352 | 355 | ||
| 353 | static int pxa2xx_mfp_suspend(void) | 356 | static int pxa2xx_mfp_suspend(void) |
| @@ -366,14 +369,26 @@ static int pxa2xx_mfp_suspend(void) | |||
| 366 | } | 369 | } |
| 367 | 370 | ||
| 368 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { | 371 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { |
| 369 | |||
| 370 | saved_gafr[0][i] = GAFR_L(i); | 372 | saved_gafr[0][i] = GAFR_L(i); |
| 371 | saved_gafr[1][i] = GAFR_U(i); | 373 | saved_gafr[1][i] = GAFR_U(i); |
| 372 | saved_gpdr[i] = GPDR(i * 32); | 374 | saved_gpdr[i] = GPDR(i * 32); |
| 375 | saved_gplr[i] = GPLR(i * 32); | ||
| 373 | saved_pgsr[i] = PGSR(i); | 376 | saved_pgsr[i] = PGSR(i); |
| 374 | 377 | ||
| 375 | GPDR(i * 32) = gpdr_lpm[i]; | 378 | GPSR(i * 32) = PGSR(i); |
| 379 | GPCR(i * 32) = ~PGSR(i); | ||
| 380 | } | ||
| 381 | |||
| 382 | /* set GPDR bits taking into account MFP_LPM_KEEP_OUTPUT */ | ||
| 383 | for (i = 0; i < pxa_last_gpio; i++) { | ||
| 384 | if ((gpdr_lpm[gpio_to_bank(i)] & GPIO_bit(i)) || | ||
| 385 | ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) && | ||
| 386 | (saved_gpdr[gpio_to_bank(i)] & GPIO_bit(i)))) | ||
| 387 | GPDR(i) |= GPIO_bit(i); | ||
| 388 | else | ||
| 389 | GPDR(i) &= ~GPIO_bit(i); | ||
| 376 | } | 390 | } |
| 391 | |||
| 377 | return 0; | 392 | return 0; |
| 378 | } | 393 | } |
| 379 | 394 | ||
| @@ -384,6 +399,8 @@ static void pxa2xx_mfp_resume(void) | |||
| 384 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { | 399 | for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { |
| 385 | GAFR_L(i) = saved_gafr[0][i]; | 400 | GAFR_L(i) = saved_gafr[0][i]; |
| 386 | GAFR_U(i) = saved_gafr[1][i]; | 401 | GAFR_U(i) = saved_gafr[1][i]; |
| 402 | GPSR(i * 32) = saved_gplr[i]; | ||
| 403 | GPCR(i * 32) = ~saved_gplr[i]; | ||
| 387 | GPDR(i * 32) = saved_gpdr[i]; | 404 | GPDR(i * 32) = saved_gpdr[i]; |
| 388 | PGSR(i) = saved_pgsr[i]; | 405 | PGSR(i) = saved_pgsr[i]; |
| 389 | } | 406 | } |
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 6bce78edce7a..4726c246dcdc 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
| @@ -421,8 +421,11 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) | |||
| 421 | pxa_register_device(&pxa27x_device_i2c_power, info); | 421 | pxa_register_device(&pxa27x_device_i2c_power, info); |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = { | ||
| 425 | .gpio_set_wake = gpio_set_wake, | ||
| 426 | }; | ||
| 427 | |||
| 424 | static struct platform_device *devices[] __initdata = { | 428 | static struct platform_device *devices[] __initdata = { |
| 425 | &pxa_device_gpio, | ||
| 426 | &pxa27x_device_udc, | 429 | &pxa27x_device_udc, |
| 427 | &pxa_device_pmu, | 430 | &pxa_device_pmu, |
| 428 | &pxa_device_i2s, | 431 | &pxa_device_i2s, |
| @@ -458,6 +461,7 @@ static int __init pxa27x_init(void) | |||
| 458 | register_syscore_ops(&pxa2xx_mfp_syscore_ops); | 461 | register_syscore_ops(&pxa2xx_mfp_syscore_ops); |
| 459 | register_syscore_ops(&pxa2xx_clock_syscore_ops); | 462 | register_syscore_ops(&pxa2xx_clock_syscore_ops); |
| 460 | 463 | ||
| 464 | pxa_register_device(&pxa_device_gpio, &pxa27x_gpio_info); | ||
| 461 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 465 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
| 462 | } | 466 | } |
| 463 | 467 | ||
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 7c524b4e415d..16be4c56abe3 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c | |||
| @@ -306,7 +306,7 @@ void sa11x0_register_irda(struct irda_platform_data *irda) | |||
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | static struct resource sa1100_rtc_resources[] = { | 308 | static struct resource sa1100_rtc_resources[] = { |
| 309 | DEFINE_RES_MEM(0x90010000, 0x9001003f), | 309 | DEFINE_RES_MEM(0x90010000, 0x40), |
| 310 | DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"), | 310 | DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"), |
| 311 | DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"), | 311 | DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"), |
| 312 | }; | 312 | }; |
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 5689ce62fd81..fc3ace3fd4cb 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c | |||
| @@ -64,6 +64,7 @@ struct pxa_gpio_chip { | |||
| 64 | unsigned long irq_mask; | 64 | unsigned long irq_mask; |
| 65 | unsigned long irq_edge_rise; | 65 | unsigned long irq_edge_rise; |
| 66 | unsigned long irq_edge_fall; | 66 | unsigned long irq_edge_fall; |
| 67 | int (*set_wake)(unsigned int gpio, unsigned int on); | ||
| 67 | 68 | ||
| 68 | #ifdef CONFIG_PM | 69 | #ifdef CONFIG_PM |
| 69 | unsigned long saved_gplr; | 70 | unsigned long saved_gplr; |
| @@ -269,7 +270,8 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
| 269 | (value ? GPSR_OFFSET : GPCR_OFFSET)); | 270 | (value ? GPSR_OFFSET : GPCR_OFFSET)); |
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | static int __devinit pxa_init_gpio_chip(int gpio_end) | 273 | static int __devinit pxa_init_gpio_chip(int gpio_end, |
| 274 | int (*set_wake)(unsigned int, unsigned int)) | ||
| 273 | { | 275 | { |
| 274 | int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; | 276 | int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; |
| 275 | struct pxa_gpio_chip *chips; | 277 | struct pxa_gpio_chip *chips; |
| @@ -285,6 +287,7 @@ static int __devinit pxa_init_gpio_chip(int gpio_end) | |||
| 285 | 287 | ||
| 286 | sprintf(chips[i].label, "gpio-%d", i); | 288 | sprintf(chips[i].label, "gpio-%d", i); |
| 287 | chips[i].regbase = gpio_reg_base + BANK_OFF(i); | 289 | chips[i].regbase = gpio_reg_base + BANK_OFF(i); |
| 290 | chips[i].set_wake = set_wake; | ||
| 288 | 291 | ||
| 289 | c->base = gpio; | 292 | c->base = gpio; |
| 290 | c->label = chips[i].label; | 293 | c->label = chips[i].label; |
| @@ -412,6 +415,17 @@ static void pxa_mask_muxed_gpio(struct irq_data *d) | |||
| 412 | writel_relaxed(gfer, c->regbase + GFER_OFFSET); | 415 | writel_relaxed(gfer, c->regbase + GFER_OFFSET); |
| 413 | } | 416 | } |
| 414 | 417 | ||
| 418 | static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on) | ||
| 419 | { | ||
| 420 | int gpio = pxa_irq_to_gpio(d->irq); | ||
| 421 | struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); | ||
| 422 | |||
| 423 | if (c->set_wake) | ||
| 424 | return c->set_wake(gpio, on); | ||
| 425 | else | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 415 | static void pxa_unmask_muxed_gpio(struct irq_data *d) | 429 | static void pxa_unmask_muxed_gpio(struct irq_data *d) |
| 416 | { | 430 | { |
| 417 | int gpio = pxa_irq_to_gpio(d->irq); | 431 | int gpio = pxa_irq_to_gpio(d->irq); |
| @@ -427,6 +441,7 @@ static struct irq_chip pxa_muxed_gpio_chip = { | |||
| 427 | .irq_mask = pxa_mask_muxed_gpio, | 441 | .irq_mask = pxa_mask_muxed_gpio, |
| 428 | .irq_unmask = pxa_unmask_muxed_gpio, | 442 | .irq_unmask = pxa_unmask_muxed_gpio, |
| 429 | .irq_set_type = pxa_gpio_irq_type, | 443 | .irq_set_type = pxa_gpio_irq_type, |
| 444 | .irq_set_wake = pxa_gpio_set_wake, | ||
| 430 | }; | 445 | }; |
| 431 | 446 | ||
| 432 | static int pxa_gpio_nums(void) | 447 | static int pxa_gpio_nums(void) |
| @@ -471,6 +486,7 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) | |||
| 471 | struct pxa_gpio_chip *c; | 486 | struct pxa_gpio_chip *c; |
| 472 | struct resource *res; | 487 | struct resource *res; |
| 473 | struct clk *clk; | 488 | struct clk *clk; |
| 489 | struct pxa_gpio_platform_data *info; | ||
| 474 | int gpio, irq, ret; | 490 | int gpio, irq, ret; |
| 475 | int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; | 491 | int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; |
| 476 | 492 | ||
| @@ -516,7 +532,8 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) | |||
| 516 | } | 532 | } |
| 517 | 533 | ||
| 518 | /* Initialize GPIO chips */ | 534 | /* Initialize GPIO chips */ |
| 519 | pxa_init_gpio_chip(pxa_last_gpio); | 535 | info = dev_get_platdata(&pdev->dev); |
| 536 | pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL); | ||
| 520 | 537 | ||
| 521 | /* clear all GPIO edge detects */ | 538 | /* clear all GPIO edge detects */ |
| 522 | for_each_gpio_chip(gpio, c) { | 539 | for_each_gpio_chip(gpio, c) { |
diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h index 05071ee34c3f..d755b28ba635 100644 --- a/include/linux/gpio-pxa.h +++ b/include/linux/gpio-pxa.h | |||
| @@ -13,4 +13,8 @@ extern int pxa_last_gpio; | |||
| 13 | 13 | ||
| 14 | extern int pxa_irq_to_gpio(int irq); | 14 | extern int pxa_irq_to_gpio(int irq); |
| 15 | 15 | ||
| 16 | struct pxa_gpio_platform_data { | ||
| 17 | int (*gpio_set_wake)(unsigned int gpio, unsigned int on); | ||
| 18 | }; | ||
| 19 | |||
| 16 | #endif /* __GPIO_PXA_H */ | 20 | #endif /* __GPIO_PXA_H */ |
