1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <mod_synquacer_rom.h>
9
10 #include <fwk_core.h>
11 #include <fwk_event.h>
12 #include <fwk_id.h>
13 #include <fwk_interrupt.h>
14 #include <fwk_log.h>
15 #include <fwk_module.h>
16 #include <fwk_module_idx.h>
17 #include <fwk_status.h>
18
19 #include <fmw_cmsis.h>
20
21 #include <stdint.h>
22 #include <string.h>
23
24 void synquacer_system_init(void);
25
26 static const struct synquacer_rom_config *rom_config;
27
28 enum rom_event { ROM_EVENT_RUN, ROM_EVENT_COUNT };
29
30 /*
31 * This function assumes that the RAM firmware image is located at the beginning
32 * of the SCP SRAM. The reset handler will be at offset 0x4 (the second entry of
33 * the vector table).
34 */
jump_to_ramfw(void)35 static void jump_to_ramfw(void)
36 {
37 uintptr_t const *reset_base = (uintptr_t *)(rom_config->ramfw_base + 0x4);
38 void (*ramfw_reset_handler)(void);
39
40 /*
41 * Disable interrupts for the duration of the ROM firmware to RAM firmware
42 * transition.
43 */
44 (void)fwk_interrupt_global_disable();
45
46 ramfw_reset_handler = (void (*)(void))(*reset_base);
47
48 /* Set the vector table offset register to ramfw vector table */
49 SCB->VTOR = rom_config->ramfw_base;
50
51 /*
52 * Execute the RAM firmware's reset handler to pass control from ROM
53 * firmware to the RAM firmware.
54 */
55 ramfw_reset_handler();
56 }
57
58 /*
59 * Framework API
60 */
synquacer_rom_init(fwk_id_t module_id,unsigned int element_count,const void * data)61 static int synquacer_rom_init(
62 fwk_id_t module_id,
63 unsigned int element_count,
64 const void *data)
65 {
66 rom_config = data;
67
68 synquacer_system_init();
69
70 return FWK_SUCCESS;
71 }
72
synquacer_rom_start(fwk_id_t id)73 static int synquacer_rom_start(fwk_id_t id)
74 {
75 int status;
76 struct fwk_event event = {
77 .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_ROM),
78 .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_ROM),
79 .id = FWK_ID_EVENT(FWK_MODULE_IDX_SYNQUACER_ROM, ROM_EVENT_RUN),
80 };
81
82 status = fwk_put_event(&event);
83
84 return status;
85 }
86
synquacer_rom_process_event(const struct fwk_event * event,struct fwk_event * resp)87 static int synquacer_rom_process_event(
88 const struct fwk_event *event,
89 struct fwk_event *resp)
90 {
91 FWK_LOG_INFO("[scp_romfw] Launch scp_ramfw");
92 FWK_LOG_FLUSH();
93
94 if (rom_config->load_ram_size != 0) {
95 memcpy(
96 (void *)rom_config->ramfw_base,
97 (uint8_t *)rom_config->nor_base,
98 rom_config->load_ram_size);
99 }
100
101 jump_to_ramfw();
102
103 return FWK_SUCCESS;
104 }
105
106 /* Module descriptor */
107 const struct fwk_module module_synquacer_rom = {
108 .type = FWK_MODULE_TYPE_SERVICE,
109 .event_count = ROM_EVENT_COUNT,
110 .init = synquacer_rom_init,
111 .start = synquacer_rom_start,
112 .process_event = synquacer_rom_process_event,
113 };
114