/** * 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; }
/** * 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); }