Commit b38d950d3aedf90c8b15b3c7c799b5eb53c47c45
Committed by
Russell King
1 parent
caf39e87cc
Exists in
master
and in
4 other branches
[ARM] Add suspend/resume support to locomo.c
This adds low-level suspend/resume support to locomo.c. Signed-off-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Showing 1 changed file with 101 additions and 0 deletions Side-by-side Diff
arch/arm/common/locomo.c
| ... | ... | @@ -541,6 +541,103 @@ |
| 541 | 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 | 642 | * locomo_probe - probe for a single LoCoMo chip. |
| 546 | 643 | * @phys_addr: physical address of device. |
| ... | ... | @@ -707,6 +804,10 @@ |
| 707 | 804 | .bus = &platform_bus_type, |
| 708 | 805 | .probe = locomo_probe, |
| 709 | 806 | .remove = locomo_remove, |
| 807 | +#ifdef CONFIG_PM | |
| 808 | + .suspend = locomo_suspend, | |
| 809 | + .resume = locomo_resume, | |
| 810 | +#endif | |
| 710 | 811 | }; |
| 711 | 812 | |
| 712 | 813 | /* |