Linux APM在ARM上的实现原理

欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入

  这就是实现三个状态转换的三个钩子函数.

  这个函数较为简单, 只是将/kerenel/power/main.c里的全局变量suspend_ops设置成

  s3c_pm_ops而已了.

  这就完成了这个全局变量的初始化.后续对suspend_ops的访问实质上都是访问s3c_pm_ops.

  void suspend_set_ops(struct platform_suspend_ops *ops)

  {

  mutex_lock(&pm_mutex);

  suspend_ops = ops;

  mutex_unlock(&pm_mutex);

  }

  最后看看函数实现:

  static int s3c_pm_prepare(void)

  {

  /* prepare check area if configured */

  s3c_pm_check_prepare();

  return 0;

  }

  static void s3c_pm_finish(void)

  {

  s3c_pm_check_cleanup();

  }

  这里主要是s3c_pm_nter函数:

  static int s3c_pm_enter(suspend_state_t state)

  {

  //用于保存16个通用寄存器的栈

  static unsigned long regs_save[16];

  /* ensure the debug is initialised (if enabled) */

  s3c_pm_debug_init();

  S3C_PMDBG(“%s(%d)\n”, __func__, state);

  if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {

  printk(KERN_ERR “%s: error: no cpu sleep function\n”, __func__);

  return -EINVAL;

  }

  /* check if we have anything to wake-up with… bad things seem

  * to happen if you suspend with no wakeup (system will often

  * require a full power-cycle)

  */

  //检查允许的唤醒中断

  if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&

  !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {

  printk(KERN_ERR “%s: No wake-up sources!\n”, __func__);

  printk(KERN_ERR “%s: Aborting sleep\n”, __func__);

  return -EINVAL;

  }

  /* store the physical address of the register recovery block */

  //寄存器的物理地址

  s3c_sleep_save_phys = virt_to_phys(regs_save);

  S3C_PMDBG(“s3c_sleep_save_phys=0x%08lx\n”, s3c_sleep_save_phys);

  //保存不属于driver的核心寄存器, driver的各自保存

  s3c_pm_save_gpios();

  s3c_pm_save_uarts();

  s3c_pm_save_core();

  /* set the irq configuration for wake */

  //设置外部中断用于唤醒

  s3c_pm_configure_extint();

  S3C_PMDBG(“sleep: irq wakeup masks: %08lx,%08lx\n”,

  s3c_irqwake_intmask, s3c_irqwake_eintmask);

  s3c_pm_arch_prepare_irqs();

  /* call cpu specific preparation */

  pm_cpu_prep();

  /* flush cache back to ram */

  flush_cache_all();

  s3c_pm_check_store();

  /* send the cpu to sleep… */

  s3c_pm_arch_stop_clocks();

  /* s3c_cpu_save will also act as our return point from when

  * we resume as it saves its own register state and restores it

  * during the resume. */

  s3c_cpu_save(regs_save);

  /* restore the cpu state using the kernel’s cpu init code. */

  //当接收到一个外部中断时,系统开始恢复

  cpu_init();

  /* restore the system state */

  s3c_pm_restore_core();

  s3c_pm_restore_uarts();

  s3c_pm_restore_gpios();

  s3c_pm_debug_init();

  /* check what irq (if any) restored the system */

  s3c_pm_arch_show_resume_irqs();

  S3C_PMDBG(“%s: post sleep, preparing to return\n”, __func__);

  s3c_pm_check_restore();

  /* ok, let’s return from sleep */

  S3C_PMDBG(“S3C PM Resume (post-restore)\n”);

  return 0;

  }

[1][2][3][4][5]

别人失去了信心,他却下决心实现自己的目标。

Linux APM在ARM上的实现原理

相关文章:

你感兴趣的文章:

标签云: