/* * Arm SCP/MCP Software * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * * Description: Module dedicated to the ROM firmware of the mobile platforms to * initiate the boot of the primary AP core and then to jump to the SCP RAM * firmware. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct msys_rom_ctx { const struct msys_rom_config *rom_config; struct ppu_v1_boot_api *ppu_boot_api; struct mod_bootloader_api *bootloader_api; unsigned int notification_count; /* Notifications awaiting a response */ } ctx; enum rom_event { ROM_EVENT_RUN, ROM_EVENT_COUNT }; static int msys_deferred_setup(void) { int status; /* Initialize the AP context area by zeroing it */ memset((void *)ctx.rom_config->ap_context_base, 0, ctx.rom_config->ap_context_size); /* Power on the primary cluster and cpu */ ctx.ppu_boot_api->power_mode_on(ctx.rom_config->id_primary_cluster); ctx.ppu_boot_api->power_mode_on(ctx.rom_config->id_primary_core); status = ctx.bootloader_api->load_image(); FWK_LOG_CRIT( "[MSYS-ROM] Failed to load RAM firmware image: %s", fwk_status_str(status)); return FWK_E_DATA; } /* * Functions fulfilling the framework's module interface */ static int msys_rom_init(fwk_id_t module_id, unsigned int element_count, const void *data) { ctx.rom_config = data; if ((ctx.rom_config->ap_context_base == 0) || (ctx.rom_config->ap_context_size == 0)) return FWK_E_RANGE; return FWK_SUCCESS; } static int msys_rom_bind(fwk_id_t id, unsigned int round) { int status; /* Use second round only (round numbering is zero-indexed) */ if (round == 1) { /* Bind to the PPU module */ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_PPU_V1), FWK_ID_API(FWK_MODULE_IDX_PPU_V1, MOD_PPU_V1_API_IDX_BOOT), &ctx.ppu_boot_api); if (status != FWK_SUCCESS) return FWK_E_PANIC; /* Bind to the bootloader module */ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_BOOTLOADER), FWK_ID_API(FWK_MODULE_IDX_BOOTLOADER, 0), &ctx.bootloader_api); if (status != FWK_SUCCESS) return FWK_E_PANIC; } return FWK_SUCCESS; } static int msys_rom_start(fwk_id_t id) { struct fwk_event event = { .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_MSYS_ROM), .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_MSYS_ROM), .id = FWK_ID_EVENT(FWK_MODULE_IDX_MSYS_ROM, ROM_EVENT_RUN), }; return fwk_put_event(&event); } static int msys_rom_process_event(const struct fwk_event *event, struct fwk_event *resp) { int status; struct mod_pd_power_state_transition_notification_params *notification_params; struct fwk_event systop_on_event = { .response_requested = true, .id = mod_msys_rom_notification_id_systop, .source_id = FWK_ID_NONE }; /* Notify any subscribers of the SYSTOP power domain state change */ notification_params = (struct mod_pd_power_state_transition_notification_params *) systop_on_event.params; notification_params->state = MOD_PD_STATE_ON; status = fwk_notification_notify(&systop_on_event, &ctx.notification_count); if (status != FWK_SUCCESS) return status; /* Complete remaining setup now if there are no subscribers to respond */ if (ctx.notification_count == 0) return msys_deferred_setup(); return FWK_SUCCESS; } static int msys_rom_process_notification( const struct fwk_event *event, struct fwk_event *resp_event) { fwk_assert( fwk_id_is_equal(event->id, mod_msys_rom_notification_id_systop)); fwk_assert(event->is_response == true); /* At least one notification response must be outstanding */ if (ctx.notification_count == 0) { fwk_unexpected(); return FWK_E_PANIC; } /* Complete remaining setup now that all subscribers have responded */ if ((--ctx.notification_count) == 0) return msys_deferred_setup(); return FWK_SUCCESS; } /* Module descriptor */ const struct fwk_module module_msys_rom = { .type = FWK_MODULE_TYPE_SERVICE, .event_count = ROM_EVENT_COUNT, .notification_count = MOD_MSYS_ROM_NOTIFICATION_COUNT, .init = msys_rom_init, .bind = msys_rom_bind, .start = msys_rom_start, .process_event = msys_rom_process_event, .process_notification = msys_rom_process_notification, };