/******************************************************************************* * Configures access to the system counter timer module. ******************************************************************************/ void arm_configure_sys_timer(void) { unsigned int reg_val; #if ARM_CONFIG_CNTACR reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val); #endif /* ARM_CONFIG_CNTACR */ reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID)); mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val); }
/******************************************************************************* * Initialize the gic, configure the CLCD and zero out variables needed by the * secondaries to boot up correctly. ******************************************************************************/ void bl31_platform_setup() { // unsigned int reg_val; /* Initialize the gic cpu and distributor interfaces */ gic_setup(); #if 0 //do not init CLCD in ATF /* * TODO: Configure the CLCD before handing control to * linux. Need to see if a separate driver is needed * instead. */ mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGDATA, 0); mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, (1ull << 31) | (1 << 30) | (7 << 20) | (0 << 16)); #endif #if 0 //FIXME TIMER CTRL skip now /* Enable and initialize the System level generic timer */ mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN); /* Allow access to the System counter timer module */ reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(0), reg_val); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | (1 << CNTNSAR_NS_SHIFT(1)); mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); #endif /* Topologies are best known to the platform. */ mt_setup_topology(); }
/******************************************************************************* * MTK_platform handler called when an affinity instance has just been powered on after * being turned off earlier. The level and mpidr determine the affinity * instance. The 'state' arg. allows the platform to decide whether the cluster * was turned off prior to wakeup and do what's necessary to setup it up * correctly. ******************************************************************************/ int mt_affinst_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state) { int rc = PSCI_E_SUCCESS; unsigned long linear_id, cpu_setup; mailbox_t *mt_mboxes; unsigned int gicd_base, gicc_base, ectlr; switch (afflvl) { case MPIDR_AFFLVL2: if (state == PSCI_STATE_OFF) { // __asm__ __volatile__ ("1: b 1b \n\t"); } gicd_base = mt_get_cfgvar(CONFIG_GICD_ADDR); gic_pcpu_distif_setup(gicd_base); break; case MPIDR_AFFLVL1: /* Enable coherency if this cluster was off */ if (state == PSCI_STATE_OFF) { enable_scu(mpidr); mt_cci_setup(); trace_power_flow(mpidr, CLUSTER_UP); } break; case MPIDR_AFFLVL0: /* * Ignore the state passed for a cpu. It could only have * been off if we are here. */ workaround_836870(mpidr); /* * Turn on intra-cluster coherency if the MTK_platform flavour supports * it. */ cpu_setup = mt_get_cfgvar(CONFIG_CPU_SETUP); if (cpu_setup) { ectlr = read_cpuectlr(); ectlr |= CPUECTLR_SMP_BIT; write_cpuectlr(ectlr); } /* Zero the jump address in the mailbox for this cpu */ mt_mboxes = (mailbox_t *) (MBOX_OFF); linear_id = platform_get_core_pos(mpidr); mt_mboxes[linear_id].value = 0; flush_dcache_range((unsigned long) &mt_mboxes[linear_id], sizeof(unsigned long)); gicc_base = mt_get_cfgvar(CONFIG_GICC_ADDR); /* Enable the gic cpu interface */ gic_cpuif_setup(gicc_base); //gic_cpu_restore(); #if 0 //fixme, /* Allow access to the System counter timer module */ reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(0), reg_val); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | (1 << CNTNSAR_NS_SHIFT(1)); mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); #endif enable_ns_access_to_cpuectlr(); trace_power_flow(mpidr, CPU_UP); break; default: assert(0); } return rc; }
/******************************************************************************* * FVP handler called when an affinity instance has just been powered on after * being turned off earlier. The level and mpidr determine the affinity * instance. The 'state' arg. allows the platform to decide whether the cluster * was turned off prior to wakeup and do what's necessary to setup it up * correctly. ******************************************************************************/ int fvp_affinst_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state) { int rc = PSCI_E_SUCCESS; unsigned long linear_id, cpu_setup, cci_setup; mailbox *fvp_mboxes; unsigned int gicd_base, gicc_base, reg_val, ectlr; switch (afflvl) { case MPIDR_AFFLVL1: /* Enable coherency if this cluster was off */ if (state == PSCI_STATE_OFF) { /* * This CPU might have woken up whilst the * cluster was attempting to power down. In * this case the FVP power controller will * have a pending cluster power off request * which needs to be cleared by writing to the * PPONR register. This prevents the power * controller from interpreting a subsequent * entry of this cpu into a simple wfi as a * power down request. */ fvp_pwrc_write_pponr(mpidr); cci_setup = platform_get_cfgvar(CONFIG_HAS_CCI); if (cci_setup) { cci_enable_coherency(mpidr); } } break; case MPIDR_AFFLVL0: /* * Ignore the state passed for a cpu. It could only have * been off if we are here. */ /* * Turn on intra-cluster coherency if the FVP flavour supports * it. */ cpu_setup = platform_get_cfgvar(CONFIG_CPU_SETUP); if (cpu_setup) { ectlr = read_cpuectlr(); ectlr |= CPUECTLR_SMP_BIT; write_cpuectlr(ectlr); } /* * Clear PWKUPR.WEN bit to ensure interrupts do not interfere * with a cpu power down unless the bit is set again */ fvp_pwrc_clr_wen(mpidr); /* Zero the jump address in the mailbox for this cpu */ fvp_mboxes = (mailbox *) (TZDRAM_BASE + MBOX_OFF); linear_id = platform_get_core_pos(mpidr); fvp_mboxes[linear_id].value = 0; flush_dcache_range((unsigned long) &fvp_mboxes[linear_id], sizeof(unsigned long)); gicd_base = platform_get_cfgvar(CONFIG_GICD_ADDR); gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR); /* Enable the gic cpu interface */ gic_cpuif_setup(gicc_base); /* TODO: This setup is needed only after a cold boot */ gic_pcpu_distif_setup(gicd_base); /* Allow access to the System counter timer module */ reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(0), reg_val); mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); reg_val = (1 << CNTNSAR_NS_SHIFT(0)) | (1 << CNTNSAR_NS_SHIFT(1)); mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); break; default: assert(0); } return rc; }