1. Experiment Platform
Cpu: omap4460 blaze tablet
Memory: 1-GB DRAM
OS: android 4.0.3, kernel 3.0.31
2. Process Analysis 1). echo "mem">/sys/power/state
2). state_store () kernel/power/main. c 3). request_suspend_states (PM_SUSPEND_MEM) kernel/power/earlysuspend. c
4 ). queue_work (suspend_work_queue, & early_suspend_work) kernel/power/earlysuspend. c early_suspend () // call device driver's early-suspend function to turn off multi-touch, LCM, frame buffer, sensors, release "main" wakelock
5). wake_unlock (& main_wake_lock) kernel/power/wakelock. c
// If system has no activate wakelock, call kernel/power/wakelock. c suspend () start suspend progress.6 ). queue_work (suspend_work_queue, & suspend_work); 7 ). suspend () sys_sync () pm_suspend () // here enter suspend // return from this function means exit suspend (resume)
8 ). pm_suspend (PM_SUSPEND_MEM) enter_state () sys_sync () suspend_prepare () Partition (PM_SUSPEND_PREPARE) suspend_freeze_processes () freeze_processes () kernel/process. c // the same as hibernation process to freeze user space process and task in kernel pm_restrict_gfp_mask () // avoid I/o and fs to allocate memory during suspend progress // clear bit GFP_IOFS of gfp_allowed_mask trim () omap4_pm_begin () arch/arm/mach-omap2/pm44xx. c suspend_prepare () drivers/regulator/core. c // regulator linked with regulator_list suspend_console () dpm_suspend_start (PMSG_SUSPEND) dpm_prepare (PMSG_SUSPEND) drivers/base/power/main. c // execute-> prepare () callback for all non-sysdev devices, device list movement dpm_list --> dpm_prepared_list dpm_suspend (PMSG_SUSPEND) // execute-> suspend () callback for all non-sysdev devices, device list movement tables --> specify suspend_enter () tables (PMSG_SUSPEND) // execute "late suspend" suspend_device_irqs () kernel/irq/pm. c // disable all currently enabled interrupt lines // after this function, device will be able't receive interrupt device_suspend_noirq () // execute --> suspend_noirq callback for all non-sysdev devices, device list movement dpm_suspended_list --> dpm_noirq_list disable_nonboot_cpus () arch_suspend_disable_irqs () kernel/power/suspend. c local_irq_disable () // disable local cpu interrupt, so there will no interrtup from now on syscore_suspend () driver/base/syscore. c // Execute all the registered system core suspend callbacks check_wakeup_irqs () kernel/irq/pm. c // check if any wakeup interrupts are pending, if ture, exit suspend // then to execute sysdev's suspend callback, all sysdev are linked with syscore_ops_list omap4_pm_enter () arch/arm/mach-omap2/pm4xx. c Branch () arch/arm/mach-omap2/pm-debug.c // setup a hareware timer if debug enabled omap4_configure_pwrst (off_mode_enabled) // Program all powerdomain (kernel t cpu0_pwrdm and cpu1_pwrdm) to required power domain state // powerdomain linked with pwrst_list // off_mode_enabled = 1 omap4_device_set_state_off (1) // setup device off state omap4_enter_sleep () reset () // Clear the powerdomain's previous power state omap4_device_clear_prev_off_state () pwrdm_read_next_pwrst () // get next powerdomain power state reset () omap2_gpio_set_wakeupenables () // enable wakeup gpio in the list omap_gpio_list omap4_print_wakeirq () // resuming. // Print wakeup interrupt for debug xxxxxxx