void mstar_restore_context(void) { sleep_restore_neon_regs(&MStar_Suspend_Buffer[SLEEPSTATE_NEONREG/WORD_SIZE]); restore_a9_scu((appf_u32 *)a9_scu_save,PERI_ADDRESS(PERI_PHYS)); restore_pl310((appf_u32*)&pl310_context_save,L2_CACHE_ADDRESS(L2_CACHE_PHYS), 0); restore_mmu(mmu_data); restore_control_registers(control_data, 1); restore_gic_distributor_shared((appf_u32 *)gic_distributor_shared_save,(unsigned)_gic_dist_base_addr,1); gic_distributor_set_enabled(TRUE, (unsigned)_gic_dist_base_addr); restore_gic_distributor_private((appf_u32 *)gic_distributor_private_save,(unsigned)_gic_dist_base_addr,1); restore_gic_interface((appf_u32 *)gic_interface_save,(unsigned)_gic_cpu_base_addr,1); restore_a9_other((appf_u32 *)a9_other_save,1); restore_cp15((appf_u32 *)cp15_save); restore_a9_timers((appf_u32*)&a9_timer_save, PERI_ADDRESS(PERI_PHYS)); restore_a9_global_timer((appf_u32 *)a9_global_timer_save,PERI_ADDRESS(PERI_PHYS)); restore_performance_monitors((appf_u32 *)performance_monitor_save); mstar_restore_int_mask(); #if defined(CONFIG_SMP) platform_smp_boot_secondary_init(1); #endif #if defined(CONFIG_MP_PLATFORM_ARM) #ifdef CONFIG_ARM { extern int __init init_irq_fiq_merge(void); init_irq_fiq_merge(); } #endif #endif /* CONFIG_MP_PLATFORM_ARM */ mstar_sleep_cur_cpu_flush(); }
/** * This function restores all the context that was lost * when a CPU and cluster entered a low power state. It is called shortly after * reset, with the MMU and data cache off. * * This function is called with cluster->context->lock held */ int appf_platform_restore_context(struct appf_cluster *cluster, struct appf_cpu *cpu) { struct appf_cpu_context *context; struct appf_cluster_context *cluster_context; int cluster_init; appf_u32 saved_items, cluster_saved_items = 0; /* * At this point we may not write to any static data, and we may * only read the data that we explicitly cleaned from the L2 above. */ cluster_context = cluster->context; context = cpu->context; /* Should we initialize the cluster: are we the first CPU back on, and has the cluster been off? */ cluster_init = (cluster->active_cpus == 0 && cluster->power_state >= 2); saved_items = context->saved_items; /* First set up the SCU & L2, if necessary */ // if (cluster_init) { cluster_saved_items = cluster_context->saved_items; if(cluster->scu_address) restore_a9_scu(cluster_context->scu_data, cluster->scu_address); if (cluster_saved_items & SAVED_L2) { restore_pl310(cluster_context->l2_data, cluster->l2_address, cluster->power_state == 2); } } /* Next get the MMU back on */ restore_mmu(context->mmu_data); restore_control_registers(context); /* * MMU and L1 and L2 caches are on, we may now read/write any data. * Now we need to restore the rest of this CPU's context */ /* Get the debug registers restored, so we can debug most of the APPF code sensibly! */ if (saved_items & SAVED_DEBUG) { restore_a9_debug(context->debug_data); } /* Restore shared items if necessary */ // if (cluster_init) { restore_gic_distributor_shared(cluster_context->gic_dist_shared_data, cluster->ic_address); if (cluster_saved_items & SAVED_GLOBAL_TIMER) { restore_a9_global_timer(cluster_context->global_timer_data, cluster->scu_address); } } if(cluster->ic_address) restore_gic_distributor_private(context->gic_dist_private_data, cluster->ic_address); if(cluster->ic_address) restore_gic_interface(context->gic_interface_data, cluster->ic_address); if(context->other_data) restore_a9_other(context->other_data); if(context->cp15_data) restore_cp15(context->cp15_data); if(context->banked_registers) restore_banked_registers(context->banked_registers); if (saved_items & SAVED_VFP) { restore_vfp(context->vfp_data); } if (saved_items & SAVED_TIMERS) { restore_a9_timers(context->timer_data, cluster->scu_address); } if (saved_items & SAVED_PMU) { restore_performance_monitors(context->pmu_data); } /* Return to OS */ return APPF_OK; }
/*------------------------------------------------------------------------------ Function: mstar_pm_enter Description: Actually enter sleep state Input: (The arguments were used by caller to input data.) state - suspend state (not used) Output: (The arguments were used by caller to receive data.) None. Return: 0 Remark: None. -------------------------------------------------------------------------------*/ static int mstar_pm_enter(suspend_state_t state) { void *pWakeup=0; __asm__ volatile ( "ldr r1, =MSTAR_WAKEUP_ENTRY\n" "str r1, %0" :"=m"(pWakeup)::"r1" ); if(pre_str_max_cnt!=get_str_max_cnt()) { pre_str_max_cnt=get_str_max_cnt(); mstr_cnt=0; } mstr_cnt++; mstar_save_int_mask(); save_performance_monitors((appf_u32 *)performance_monitor_save); save_a9_timers((appf_u32*)&a9_timer_save, PERI_ADDRESS(PERI_PHYS)); save_a9_global_timer((appf_u32 *)a9_global_timer_save,PERI_ADDRESS(PERI_PHYS)); save_gic_interface((appf_u32 *)gic_interface_save,(unsigned)_gic_cpu_base_addr,1); save_gic_distributor_private((appf_u32 *)gic_distributor_private_save,(unsigned)_gic_dist_base_addr,1); save_cp15((appf_u32 *)cp15_save);// CSSELR //save_a9_other((appf_u32 *)a9_other_save,1); //save_v7_debug((appf_u32 *)&a9_dbg_data_save); save_gic_distributor_shared((appf_u32 *)gic_distributor_shared_save,(unsigned)_gic_dist_base_addr,1); //start add save_control_registers(control_data, 1); save_mmu(mmu_data); //end add save_a9_scu((appf_u32 *)a9_scu_save,PERI_ADDRESS(PERI_PHYS)); save_pl310((appf_u32*)&pl310_context_save,L2_CACHE_ADDRESS(L2_CACHE_PHYS)); sleep_save_neon_regs(&MStar_Suspend_Buffer[SLEEPSTATE_NEONREG/WORD_SIZE]); sleep_save_cpu_registers(MStar_Suspend_Buffer); sleep_set_wakeup_save_addr_phy(mstar_virt_to_phy((void*)WAKEUP_SAVE_ADDR),(void*)WAKEUP_SAVE_ADDR); sleep_prepare_last(mstar_virt_to_phy(pWakeup)); write_actlr(read_actlr() & ~A9_SMP_BIT);//add SerPrintf("\nMStar STR waiting power off...\n"); __asm__ volatile ( "nop\n" :::"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r12" ); //__asm__ volatile( // "SUSPEND_WAIT:\n" // "nop\n" // "nop\n" // "b SUSPEND_WAIT\n" // ); // pass different password to do ac onoff if(get_str_max_cnt()>0 &&mstr_cnt>=get_str_max_cnt()) { SerPrintf("Max Cnt Ac off...\n"); mstar_str_notifypmmaxcnt_off(); } else { #ifdef CONFIG_MSTAR_STR_CRC if(get_str_crc()) { MDrv_MBX_NotifyPMtoCrcCheck(false); MDrv_MBX_write_kernel_info(); MDrv_MBX_NotifyPMtoCrcCheck(true); while(!MDrv_MBX_recviceAck()); } #endif MDrv_MBX_NotifyPMtoSetPowerOff(); } __asm__ volatile( "WAIT_SLEEP:\n" "nop\n" "nop\n" "b WAIT_SLEEP\n" ); ////////////////////////////////////////////////////////////// __asm__ volatile( "MSTAR_WAKEUP_ENTRY:\n" "bl ensure_environment\n" "bl use_tmp_stack\n" "mov r0, #'K'\n" "bl __PUTCHAR\n" "ldr r1, =exit_addr\n" "sub r0, pc,#4 \n" "b sleep_wakeup_first\n" //sleep_wakeup_first(); "exit_addr: \n" "mov r0, #'L'\n" "bl PUTCHAR_VIRT\n" "ldr r0,=MStar_Suspend_Buffer\n" "bl sleep_restore_cpu_registers\n" //sleep_restore_cpu_registers(MStar_Suspend_Buffer) :::"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r12" ); SerPrintf("\nMStar STR Resuming...\n"); sleep_restore_neon_regs(&MStar_Suspend_Buffer[SLEEPSTATE_NEONREG/WORD_SIZE]); restore_a9_scu((appf_u32 *)a9_scu_save,PERI_ADDRESS(PERI_PHYS)); restore_pl310((appf_u32*)&pl310_context_save,L2_CACHE_ADDRESS(L2_CACHE_PHYS), 0); //means power off //start add restore_mmu(mmu_data); restore_control_registers(control_data, 1); //end add //restore_v7_debug((appf_u32 *)&a9_dbg_data_save); restore_gic_distributor_shared((appf_u32 *)gic_distributor_shared_save,(unsigned)_gic_dist_base_addr,1); gic_distributor_set_enabled(TRUE, (unsigned)_gic_dist_base_addr);//add restore_gic_distributor_private((appf_u32 *)gic_distributor_private_save,(unsigned)_gic_dist_base_addr,1); restore_gic_interface((appf_u32 *)gic_interface_save,(unsigned)_gic_cpu_base_addr,1); //restore_a9_other((appf_u32 *)a9_other_save,1); restore_cp15((appf_u32 *)cp15_save); restore_a9_timers((appf_u32*)&a9_timer_save, PERI_ADDRESS(PERI_PHYS)); restore_a9_global_timer((appf_u32 *)a9_global_timer_save,PERI_ADDRESS(PERI_PHYS)); restore_performance_monitors((appf_u32 *)performance_monitor_save); mstar_restore_int_mask(); sleep_clear_wakeup_save_addr_phy(mstar_virt_to_phy((void*)WAKEUP_SAVE_ADDR),(void*)WAKEUP_SAVE_ADDR); platform_smp_boot_secondary_init(1); mstar_sleep_cur_cpu_flush(); #if defined(CONFIG_MP_PLATFORM_ARM) { extern int __init init_irq_fiq_merge(void); init_irq_fiq_merge(); } #endif /* CONFIG_MP_PLATFORM_ARM */ return 0; }
/** * This function restores all the context that was lost * when a CPU and cluster entered a low power state. It is called shortly after * reset, with the MMU and data cache off. * */ static void platform_restore_context(struct cpu_cluster *cluster, struct cpu *pcpu) { struct cpu_context *context; struct cpu_cluster_context *cluster_context; #if MAX_CPUS != 1 int cluster_init; #endif int *chip_ver = (int *)__pa(&e1_chip); /* * At this point we may not write to any data, and we may * only read the data that we explicitly cleaned from the L2 above. */ cluster_context = &(cluster->context); context = &(pcpu->context); restore_cp15(context->cp15_data); /* Should we initialize the cluster: are we the first CPU back on, and has the cluster been off? */ #if MAX_CPUS != 1 cluster_init = (cluster->active_cpus == 0 && cluster->power_state >= STATUS_DORMANT); #endif /* First set up the SCU & L2, if necessary */ #if MAX_CPUS != 1 if (cluster_init) { #endif restore_a9_scu(cluster_context->scu_data, IO_VIRT_TO_PHYS(cluster->scu_address)); restore_pl310(cluster_context->l2_data, IO_VIRT_TO_PHYS(cluster->l2_address), cluster->power_state == STATUS_DORMANT); #if MAX_CPUS != 1 } #endif /* Next get the MMU back on */ restore_mmu(context->mmu_data); if (cluster->power_state == STATUS_SHUTDOWN) { invalidate_icache_v7(); invalidate_dcache_v7(); } else { //E2 L1 cache still has HW issue if (*chip_ver != 1) { invalidate_icache_v7(); invalidate_dcache_v7(); } } restore_control_registers(context); //now MMU is restored, welcome to virtual world isb(); dsb(); enable_pl310(cpu_cluster.l2_address); enable_cache_v7_l1(); /* * MMU and L1 and L2 caches are on, we may now read/write any data. * Now we need to restore the rest of this CPU's context */ #if 0 //wschen 2011-07-28 /* Get the debug registers restored, so we can debug most of the code sensibly! */ restore_a9_debug(cpu.context.debug_data); #endif /* Restore shared items if necessary */ #if MAX_CPUS != 1 if ((cpu_cluster.active_cpus == 0) && (cpu_cluster.power_state >= STATUS_DORMANT)) { #endif restore_gic_distributor_shared((u32 *)cpu_cluster.context.gic_dist_shared_data, cpu_cluster.ic_address); restore_a9_global_timer((u32 *)cpu_cluster.context.global_timer_data, cpu_cluster.scu_address); #if MAX_CPUS != 1 } #endif restore_gic_distributor_private((u32 *)cpu.context.gic_dist_private_data, cpu_cluster.ic_address); restore_gic_interface((u32 *)cpu.context.gic_interface_data, cpu.ic_address); restore_a9_other((u32 *)cpu.context.other_data); restore_vfp((u32 *)cpu.context.vfp_data); restore_a9_timers((u32 *)cpu.context.timer_data, cpu_cluster.scu_address); restore_performance_monitors((u32 *)cpu.context.pmu_data); dormant_ret_flag = 1; restore_banked_registers((u32 *)cpu.context.banked_registers); }