예제 #1
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.
 *
 * 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;
}
예제 #2
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);
}