diff options
Diffstat (limited to 'arch/arm/common/locomo.c')
| -rw-r--r-- | arch/arm/common/locomo.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 51f430cc2fbf..2786f7c34b3f 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
| @@ -541,6 +541,103 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) | |||
| 541 | return ret; | 541 | return ret; |
| 542 | } | 542 | } |
| 543 | 543 | ||
| 544 | #ifdef CONFIG_PM | ||
| 545 | |||
| 546 | struct locomo_save_data { | ||
| 547 | u16 LCM_GPO; | ||
| 548 | u16 LCM_SPICT; | ||
| 549 | u16 LCM_GPE; | ||
| 550 | u16 LCM_ASD; | ||
| 551 | u16 LCM_SPIMD; | ||
| 552 | }; | ||
| 553 | |||
| 554 | static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) | ||
| 555 | { | ||
| 556 | struct locomo *lchip = dev_get_drvdata(dev); | ||
| 557 | struct locomo_save_data *save; | ||
| 558 | unsigned long flags; | ||
| 559 | |||
| 560 | if (level != SUSPEND_DISABLE) | ||
| 561 | return 0; | ||
| 562 | |||
| 563 | save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); | ||
| 564 | if (!save) | ||
| 565 | return -ENOMEM; | ||
| 566 | |||
| 567 | dev->power.saved_state = (void *) save; | ||
| 568 | |||
| 569 | spin_lock_irqsave(&lchip->lock, flags); | ||
| 570 | |||
| 571 | save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ | ||
| 572 | locomo_writel(0x00, lchip->base + LOCOMO_GPO); | ||
| 573 | save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPICT); /* SPI */ | ||
| 574 | locomo_writel(0x40, lchip->base + LOCOMO_SPICT); | ||
| 575 | save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ | ||
| 576 | locomo_writel(0x00, lchip->base + LOCOMO_GPE); | ||
| 577 | save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ | ||
| 578 | locomo_writel(0x00, lchip->base + LOCOMO_ASD); | ||
| 579 | save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPIMD); /* SPI */ | ||
| 580 | locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD); | ||
| 581 | |||
| 582 | locomo_writel(0x00, lchip->base + LOCOMO_PAIF); | ||
| 583 | locomo_writel(0x00, lchip->base + LOCOMO_DAC); | ||
| 584 | locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); | ||
| 585 | |||
| 586 | if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) ) | ||
| 587 | locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ | ||
| 588 | else | ||
| 589 | /* 18MHz already enabled, so no wait */ | ||
| 590 | locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */ | ||
| 591 | |||
| 592 | locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/ | ||
| 593 | locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */ | ||
| 594 | locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */ | ||
| 595 | |||
| 596 | spin_unlock_irqrestore(&lchip->lock, flags); | ||
| 597 | |||
| 598 | return 0; | ||
| 599 | } | ||
| 600 | |||
| 601 | static int locomo_resume(struct device *dev, u32 level) | ||
| 602 | { | ||
| 603 | struct locomo *lchip = dev_get_drvdata(dev); | ||
| 604 | struct locomo_save_data *save; | ||
| 605 | unsigned long r; | ||
| 606 | unsigned long flags; | ||
| 607 | |||
| 608 | if (level != RESUME_ENABLE) | ||
| 609 | return 0; | ||
| 610 | |||
| 611 | save = (struct locomo_save_data *) dev->power.saved_state; | ||
| 612 | if (!save) | ||
| 613 | return 0; | ||
| 614 | |||
| 615 | spin_lock_irqsave(&lchip->lock, flags); | ||
| 616 | |||
| 617 | locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); | ||
| 618 | locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT); | ||
| 619 | locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); | ||
| 620 | locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); | ||
| 621 | locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD); | ||
| 622 | |||
| 623 | locomo_writel(0x00, lchip->base + LOCOMO_C32K); | ||
| 624 | locomo_writel(0x90, lchip->base + LOCOMO_TADC); | ||
| 625 | |||
| 626 | locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC); | ||
| 627 | r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
| 628 | r &= 0xFEFF; | ||
| 629 | locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
| 630 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | ||
| 631 | |||
| 632 | spin_unlock_irqrestore(&lchip->lock, flags); | ||
| 633 | |||
| 634 | dev->power.saved_state = NULL; | ||
| 635 | kfree(save); | ||
| 636 | |||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | #endif | ||
| 640 | |||
| 544 | /** | 641 | /** |
| 545 | * locomo_probe - probe for a single LoCoMo chip. | 642 | * locomo_probe - probe for a single LoCoMo chip. |
| 546 | * @phys_addr: physical address of device. | 643 | * @phys_addr: physical address of device. |
| @@ -707,6 +804,10 @@ static struct device_driver locomo_device_driver = { | |||
| 707 | .bus = &platform_bus_type, | 804 | .bus = &platform_bus_type, |
| 708 | .probe = locomo_probe, | 805 | .probe = locomo_probe, |
| 709 | .remove = locomo_remove, | 806 | .remove = locomo_remove, |
| 807 | #ifdef CONFIG_PM | ||
| 808 | .suspend = locomo_suspend, | ||
| 809 | .resume = locomo_resume, | ||
| 810 | #endif | ||
| 710 | }; | 811 | }; |
| 711 | 812 | ||
| 712 | /* | 813 | /* |
