void bl1_plat_set_ep_info(unsigned int image_id, entry_point_info_t *ep_info) { unsigned int data = 0; uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; if (image_id != NS_BL1U_IMAGE_ID) panic(); /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, NS_BL1U_SIZE); memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); /* Initialize the GIC driver, cpu and distributor interfaces */ gicv2_driver_init(&hikey960_gic_data); gicv2_distif_init(); gicv2_pcpu_distif_init(); gicv2_cpuif_enable(); /* CNTFRQ is read-only in EL1 */ write_cntfrq_el0(plat_get_syscnt_freq2()); data = read_cpacr_el1(); do { data |= 3 << 20; write_cpacr_el1(data); data = read_cpacr_el1(); } while ((data & (3 << 20)) != (3 << 20)); INFO("cpacr_el1:0x%x\n", data); ep_info->args.arg0 = 0xffff & read_mpidr(); ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); }
/******************************************************************************* * This duplicates what the primary cpu did after a cold boot in BL1. The same * needs to be done when a cpu is hotplugged in. This function could also over- * ride any EL3 setup done by BL1 as this code resides in rw memory. ******************************************************************************/ void psci_arch_setup(void) { #if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) /* Program the counter frequency */ write_cntfrq_el0(plat_get_syscnt_freq2()); #endif /* Initialize the cpu_ops pointer. */ init_cpu_ops(); /* Having initialized cpu_ops, we can now print errata status */ print_errata_status(); }
/******************************************************************************* * The following functions finish an earlier affinity suspend request. They * are called by the common finisher routine in psci_common.c. ******************************************************************************/ static unsigned int psci_afflvl0_suspend_finish(aff_map_node_t *cpu_node) { unsigned int plat_state, state, rc; int32_t suspend_level; uint64_t counter_freq; assert(cpu_node->level == MPIDR_AFFLVL0); /* Ensure we have been woken up from a suspended state */ state = psci_get_state(cpu_node); assert(state == PSCI_STATE_SUSPEND); /* * Plat. management: Perform the platform specific actions * before we change the state of the cpu e.g. enabling the * gic or zeroing the mailbox register. If anything goes * wrong then assert as there is no way to recover from this * situation. */ if (psci_plat_pm_ops->affinst_suspend_finish) { /* Get the physical state of this cpu */ plat_state = get_phys_state(state); rc = psci_plat_pm_ops->affinst_suspend_finish(read_mpidr_el1(), cpu_node->level, plat_state); assert(rc == PSCI_E_SUCCESS); } /* Get the index for restoring the re-entry information */ /* * Arch. management: Enable the data cache, manage stack memory and * restore the stashed EL3 architectural context from the 'cpu_context' * structure for this cpu. */ psci_do_pwrup_cache_maintenance(); /* Re-init the cntfrq_el0 register */ counter_freq = plat_get_syscnt_freq(); write_cntfrq_el0(counter_freq); /* * Call the cpu suspend finish handler registered by the Secure Payload * Dispatcher to let it do any bookeeping. If the handler encounters an * error, it's expected to assert within */ if (psci_spd_pm && psci_spd_pm->svc_suspend) { suspend_level = psci_get_suspend_afflvl(); assert (suspend_level != PSCI_INVALID_DATA); psci_spd_pm->svc_suspend_finish(suspend_level); } /* Invalidate the suspend context for the node */ psci_set_suspend_power_state(PSCI_INVALID_DATA); /* * Generic management: Now we just need to retrieve the * information that we had stashed away during the suspend * call to set this cpu on its way. */ cm_prepare_el3_exit(NON_SECURE); /* Clean caches before re-entering normal world */ dcsw_op_louis(DCCSW); rc = PSCI_E_SUCCESS; return rc; }
/******************************************************************************* * STM32MP1 handler called when a power domain has just been powered on after * being turned off earlier. The target_state encodes the low power state that * each level has woken up from. * call by core 1 just after wake up ******************************************************************************/ static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) { stm32mp1_gic_pcpu_init(); write_cntfrq_el0(cntfrq_core0); }