linux/arch/arm/mach-s3c24xx/pm-s3c2412.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s3c2412/pm.c
   2 *
   3 * Copyright (c) 2006 Simtec Electronics
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * http://armlinux.simtec.co.uk/.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11*/
  12
  13#include <linux/kernel.h>
  14#include <linux/types.h>
  15#include <linux/interrupt.h>
  16#include <linux/list.h>
  17#include <linux/timer.h>
  18#include <linux/init.h>
  19#include <linux/device.h>
  20#include <linux/syscore_ops.h>
  21#include <linux/platform_device.h>
  22#include <linux/io.h>
  23
  24#include <asm/cacheflush.h>
  25#include <asm/irq.h>
  26
  27#include <mach/hardware.h>
  28#include <mach/regs-gpio.h>
  29
  30#include <plat/cpu.h>
  31#include <plat/pm.h>
  32#include <plat/wakeup-mask.h>
  33
  34#include "regs-dsc.h"
  35#include "s3c2412-power.h"
  36
  37extern void s3c2412_sleep_enter(void);
  38
  39static int s3c2412_cpu_suspend(unsigned long arg)
  40{
  41        unsigned long tmp;
  42
  43        /* set our standby method to sleep */
  44
  45        tmp = __raw_readl(S3C2412_PWRCFG);
  46        tmp |= S3C2412_PWRCFG_STANDBYWFI_SLEEP;
  47        __raw_writel(tmp, S3C2412_PWRCFG);
  48
  49        s3c2412_sleep_enter();
  50
  51        pr_info("Failed to suspend the system\n");
  52        return 1; /* Aborting suspend */
  53}
  54
  55/* mapping of interrupts to parts of the wakeup mask */
  56static struct samsung_wakeup_mask wake_irqs[] = {
  57        { .irq = IRQ_RTC,       .bit = S3C2412_PWRCFG_RTC_MASKIRQ, },
  58};
  59
  60static void s3c2412_pm_prepare(void)
  61{
  62        samsung_sync_wakemask(S3C2412_PWRCFG,
  63                              wake_irqs, ARRAY_SIZE(wake_irqs));
  64}
  65
  66static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
  67{
  68        pm_cpu_prep = s3c2412_pm_prepare;
  69        pm_cpu_sleep = s3c2412_cpu_suspend;
  70
  71        return 0;
  72}
  73
  74static struct sleep_save s3c2412_sleep[] = {
  75        SAVE_ITEM(S3C2412_DSC0),
  76        SAVE_ITEM(S3C2412_DSC1),
  77        SAVE_ITEM(S3C2413_GPJDAT),
  78        SAVE_ITEM(S3C2413_GPJCON),
  79        SAVE_ITEM(S3C2413_GPJUP),
  80
  81        /* save the PWRCFG to get back to original sleep method */
  82
  83        SAVE_ITEM(S3C2412_PWRCFG),
  84
  85        /* save the sleep configuration anyway, just in case these
  86         * get damaged during wakeup */
  87
  88        SAVE_ITEM(S3C2412_GPBSLPCON),
  89        SAVE_ITEM(S3C2412_GPCSLPCON),
  90        SAVE_ITEM(S3C2412_GPDSLPCON),
  91        SAVE_ITEM(S3C2412_GPFSLPCON),
  92        SAVE_ITEM(S3C2412_GPGSLPCON),
  93        SAVE_ITEM(S3C2412_GPHSLPCON),
  94        SAVE_ITEM(S3C2413_GPJSLPCON),
  95};
  96
  97static struct subsys_interface s3c2412_pm_interface = {
  98        .name           = "s3c2412_pm",
  99        .subsys         = &s3c2412_subsys,
 100        .add_dev        = s3c2412_pm_add,
 101};
 102
 103static __init int s3c2412_pm_init(void)
 104{
 105        return subsys_interface_register(&s3c2412_pm_interface);
 106}
 107
 108arch_initcall(s3c2412_pm_init);
 109
 110static int s3c2412_pm_suspend(void)
 111{
 112        s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
 113        return 0;
 114}
 115
 116static void s3c2412_pm_resume(void)
 117{
 118        unsigned long tmp;
 119
 120        tmp = __raw_readl(S3C2412_PWRCFG);
 121        tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
 122        tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
 123        __raw_writel(tmp, S3C2412_PWRCFG);
 124
 125        s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
 126}
 127
 128struct syscore_ops s3c2412_pm_syscore_ops = {
 129        .suspend        = s3c2412_pm_suspend,
 130        .resume         = s3c2412_pm_resume,
 131};
 132