Beispiel #1
0
/**
 * create_image - Create a hibernation image.
 * @platform_mode: Whether or not to use the platform driver.
 *
 * Execute device drivers' "late" and "noirq" freeze callbacks, create a
 * hibernation image and run the drivers' "noirq" and "early" thaw callbacks.
 *
 * Control reappears in this routine after the subsequent restore.
 */
static int create_image(int platform_mode)
{
	int error;

	error = dpm_suspend_end(PMSG_FREEZE);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to power down, "
			"aborting hibernation\n");
		return error;
	}

	error = platform_pre_snapshot(platform_mode);
	if (error || hibernation_test(TEST_PLATFORM))
		goto Platform_finish;

	error = disable_nonboot_cpus();
	if (error || hibernation_test(TEST_CPUS))
		goto Enable_cpus;

	local_irq_disable();

	error = syscore_suspend();
	if (error) {
		printk(KERN_ERR "PM: Some system devices failed to power down, "
			"aborting hibernation\n");
		goto Enable_irqs;
	}

	if (hibernation_test(TEST_CORE) || pm_wakeup_pending())
		goto Power_up;

	in_suspend = 1;
	save_processor_state();
	error = swsusp_arch_suspend();
	if (error)
		printk(KERN_ERR "PM: Error %d creating hibernation image\n",
			error);
	/* Restore control flow magically appears here */
	restore_processor_state();
	if (!in_suspend) {
		events_check_enabled = false;
		platform_leave(platform_mode);
	}

 Power_up:
	syscore_resume();

 Enable_irqs:
	local_irq_enable();

 Enable_cpus:
	enable_nonboot_cpus();

 Platform_finish:
	platform_finish(platform_mode);

	dpm_resume_start(in_suspend ?
		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);

	return error;
}
static int resume_target_kernel(bool platform_mode)
{
	int error;

	error = dpm_suspend_noirq(PMSG_QUIESCE);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to power down, "
			"aborting resume\n");
		return error;
	}

	error = platform_pre_restore(platform_mode);
	if (error)
		goto Cleanup;

	error = disable_nonboot_cpus();
	if (error)
		goto Enable_cpus;

	local_irq_disable();

	error = sysdev_suspend(PMSG_QUIESCE);
	if (error)
		goto Enable_irqs;

	/* We'll ignore saved state, but this gets preempt count (etc) right */
	save_processor_state();
	error = restore_highmem();
	if (!error) {
		error = swsusp_arch_resume();
		/*
		 * The code below is only ever reached in case of a failure.
		 * Otherwise execution continues at place where
		 * swsusp_arch_suspend() was called
		 */
		BUG_ON(!error);
		/* This call to restore_highmem() undos the previous one */
		restore_highmem();
	}
	/*
	 * The only reason why swsusp_arch_resume() can fail is memory being
	 * very tight, so we have to free it as soon as we can to avoid
	 * subsequent failures
	 */
	swsusp_free();
	restore_processor_state();
	touch_softlockup_watchdog();

	sysdev_resume();

 Enable_irqs:
	local_irq_enable();

 Enable_cpus:
	enable_nonboot_cpus();

 Cleanup:
	platform_restore_cleanup(platform_mode);

	dpm_resume_noirq(PMSG_RECOVER);

	return error;
}
/*
*********************************************************************************************************
*                           aw_early_suspend
*
*Description: prepare necessary info for suspend&resume;
*
*Return     : return 0 is process successed;
*
*Notes      : 
*********************************************************************************************************
*/
static int aw_super_standby(suspend_state_t state)
{
    int result = 0;
    suspend_status_flag = 0;
    mem_para_info.axp_enable = standby_axp_enable;
    
mem_enter:
    if( 1 == mem_para_info.mem_flag){
        invalidate_branch_predictor();
        //must be called to invalidate I-cache inner shareable?
        // I+BTB cache invalidate
        __cpuc_flush_icache_all();
        //disable 0x0000 <---> 0x0000 mapping
        restore_processor_state();
        mem_flush_tlb();
        //destroy 0x0000 <---> 0x0000 mapping
        //restore_mapping(MEM_SW_VA_SRAM_BASE);
        mem_arch_resume();
        goto resume;
    }

    save_runtime_context(mem_para_info.saved_runtime_context_svc);
    mem_para_info.mem_flag = 1;
    standby_level = STANDBY_WITH_POWER_OFF;
    mem_para_info.resume_pointer = (void *)&&mem_enter;
    mem_para_info.debug_mask = debug_mask;
    mem_para_info.suspend_delay_ms = suspend_delay_ms;
    //busy_waiting();
    if(unlikely(debug_mask&PM_STANDBY_PRINT_STANDBY)){
        pr_info("resume_pointer = 0x%x. \n", (unsigned int)(mem_para_info.resume_pointer));
    }
    
    
#if 1
    /* config system wakeup evetn type */
    if(PM_SUSPEND_MEM == state || PM_SUSPEND_STANDBY == state){
        mem_para_info.axp_event = AXP_MEM_WAKEUP | AXP_WAKEUP_PIO_ANY;
    }else if(PM_SUSPEND_BOOTFAST == state){
        mem_para_info.axp_event = AXP_BOOTFAST_WAKEUP;
    }
#endif  

    result = aw_early_suspend();
    if(-2 == result){
        //mem_para_info.mem_flag = 1;
        //busy_waiting();
        suspend_status_flag = 2;
        goto mem_enter;
    }else if(-1 == result){
        suspend_status_flag = 1;
        mem_para_info.mem_flag = 0;
        goto suspend_err;
    }
    
resume:
    aw_late_resume();
    //have been disable dcache in resume1
    //enable_cache();
    
suspend_err:
    if(unlikely(debug_mask&PM_STANDBY_PRINT_RESUME)){
        pr_info("suspend_status_flag = %d. \n", suspend_status_flag);
    }

    return 0;

}
static int create_image(int platform_mode)
{
	int error;

	error = arch_prepare_suspend();
	if (error)
		return error;

	/* At this point, dpm_suspend_start() has been called, but *not*
	 * dpm_suspend_noirq(). We *must* call dpm_suspend_noirq() now.
	 * Otherwise, drivers for some devices (e.g. interrupt controllers)
	 * become desynchronized with the actual state of the hardware
	 * at resume time, and evil weirdness ensues.
	 */
	error = dpm_suspend_noirq(PMSG_FREEZE);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to power down, "
			"aborting hibernation\n");
		return error;
	}

	error = platform_pre_snapshot(platform_mode);
	if (error || hibernation_test(TEST_PLATFORM))
		goto Platform_finish;

	error = disable_nonboot_cpus();
	if (error || hibernation_test(TEST_CPUS)
	    || hibernation_testmode(HIBERNATION_TEST))
		goto Enable_cpus;

	local_irq_disable();

	error = sysdev_suspend(PMSG_FREEZE);
	if (error) {
		printk(KERN_ERR "PM: Some system devices failed to power down, "
			"aborting hibernation\n");
		goto Enable_irqs;
	}

	if (hibernation_test(TEST_CORE) || !pm_check_wakeup_events())
		goto Power_up;

	in_suspend = 1;
	save_processor_state();
	error = swsusp_arch_suspend();
	if (error)
		printk(KERN_ERR "PM: Error %d creating hibernation image\n",
			error);
	/* Restore control flow magically appears here */
	restore_processor_state();
	if (!in_suspend) {
    		events_check_enabled = false;
		platform_leave(platform_mode);
	}

 Power_up:
	sysdev_resume();
	/* NOTE:  dpm_resume_noirq() is just a resume() for devices
	 * that suspended with irqs off ... no overall powerup.
	 */

 Enable_irqs:
	local_irq_enable();

 Enable_cpus:
	enable_nonboot_cpus();

 Platform_finish:
	platform_finish(platform_mode);

	dpm_resume_noirq(in_suspend ?
		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);

	return error;
}