Commit b38d950d3aedf90c8b15b3c7c799b5eb53c47c45

Authored by John Lenz
Committed by Russell King
1 parent caf39e87cc

[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 /*