diff options
-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) return ret; } +#ifdef CONFIG_PM + +struct locomo_save_data { + u16 LCM_GPO; + u16 LCM_SPICT; + u16 LCM_GPE; + u16 LCM_ASD; + u16 LCM_SPIMD; +}; + +static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) +{ + struct locomo *lchip = dev_get_drvdata(dev); + struct locomo_save_data *save; + unsigned long flags; + + if (level != SUSPEND_DISABLE) + return 0; + + save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); + if (!save) + return -ENOMEM; + + dev->power.saved_state = (void *) save; + + spin_lock_irqsave(&lchip->lock, flags); + + save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ + locomo_writel(0x00, lchip->base + LOCOMO_GPO); + save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPICT); /* SPI */ + locomo_writel(0x40, lchip->base + LOCOMO_SPICT); + save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ + locomo_writel(0x00, lchip->base + LOCOMO_GPE); + save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ + locomo_writel(0x00, lchip->base + LOCOMO_ASD); + save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPIMD); /* SPI */ + locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD); + + locomo_writel(0x00, lchip->base + LOCOMO_PAIF); + locomo_writel(0x00, lchip->base + LOCOMO_DAC); + locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); + + if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) ) + locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ + else + /* 18MHz already enabled, so no wait */ + locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */ + + locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/ + locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */ + locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */ + + spin_unlock_irqrestore(&lchip->lock, flags); + + return 0; +} + +static int locomo_resume(struct device *dev, u32 level) +{ + struct locomo *lchip = dev_get_drvdata(dev); + struct locomo_save_data *save; + unsigned long r; + unsigned long flags; + + if (level != RESUME_ENABLE) + return 0; + + save = (struct locomo_save_data *) dev->power.saved_state; + if (!save) + return 0; + + spin_lock_irqsave(&lchip->lock, flags); + + locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); + locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT); + locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); + locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); + locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD); + + locomo_writel(0x00, lchip->base + LOCOMO_C32K); + locomo_writel(0x90, lchip->base + LOCOMO_TADC); + + locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC); + r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); + r &= 0xFEFF; + locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); + locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); + + spin_unlock_irqrestore(&lchip->lock, flags); + + dev->power.saved_state = NULL; + kfree(save); + + return 0; +} +#endif + /** * locomo_probe - probe for a single LoCoMo chip. * @phys_addr: physical address of device. @@ -707,6 +804,10 @@ static struct device_driver locomo_device_driver = { .bus = &platform_bus_type, .probe = locomo_probe, .remove = locomo_remove, +#ifdef CONFIG_PM + .suspend = locomo_suspend, + .resume = locomo_resume, +#endif }; /* |