aboutsummaryrefslogtreecommitdiff
path: root/product/n1sdp/module/n1sdp_rom/src/mod_n1sdp_rom.c
blob: faf091b4e43278460743e6581d614ea92efbe3c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * Arm SCP/MCP Software
 * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <mod_fip.h>
#include <mod_n1sdp_rom.h>

#include <fwk_event.h>
#include <fwk_id.h>
#include <fwk_interrupt.h>
#include <fwk_log.h>
#include <fwk_module.h>
#include <fwk_module_idx.h>
#include <fwk_status.h>
#include <fwk_thread.h>

#include <fmw_cmsis.h>

#include <inttypes.h>
#include <stdint.h>
#include <string.h>

/*
 * Module context
 */
struct mod_n1sdp_rom_ctx {
    /* ROM configuration structure */
    const struct n1sdp_rom_config *rom_config;

    /* Pointer to FIP API */
    struct mod_fip_api *fip_api;
};

enum rom_event {
    ROM_EVENT_RUN,
    ROM_EVENT_COUNT
};

static struct mod_n1sdp_rom_ctx n1sdp_rom_ctx;

static void jump_to_ramfw(void)
{
    uintptr_t ramfw_base = n1sdp_rom_ctx.rom_config->ramfw_base;
    uintptr_t const *reset_base = (uintptr_t *)(ramfw_base + 0x4);
    void (*ramfw_reset_handler)(void);

    /*
     * Disable interrupts for the duration of the ROM firmware to RAM firmware
     * transition.
     */
    fwk_interrupt_global_disable();

    ramfw_reset_handler = (void (*)(void))*reset_base;

    /* Set the vector table offset register */
    SCB->VTOR = ramfw_base;

    /*
     * Execute the RAM firmware's reset handler to pass control from ROM
     * firmware to the RAM firmware.
     */
    ramfw_reset_handler();
}

/*
 * Framework handlers
 */
static int n1sdp_rom_init(fwk_id_t module_id, unsigned int element_count,
    const void *data)
{
    if ((data == NULL) || (element_count > 0))
        return FWK_E_PANIC;

    n1sdp_rom_ctx.rom_config = data;

    return FWK_SUCCESS;
}

static int n1sdp_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 n1sdp_flash component */
        status = fwk_module_bind(
            FWK_ID_MODULE(FWK_MODULE_IDX_FIP),
            FWK_ID_API(FWK_MODULE_IDX_FIP, 0),
            &n1sdp_rom_ctx.fip_api);
        if (status != FWK_SUCCESS)
            return FWK_E_PANIC;
    }

    return FWK_SUCCESS;
}

static int n1sdp_rom_start(fwk_id_t id)
{
    struct fwk_event event = {
        .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_N1SDP_ROM),
        .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_N1SDP_ROM),
        .id = FWK_ID_EVENT(FWK_MODULE_IDX_N1SDP_ROM, ROM_EVENT_RUN),
    };

    return fwk_thread_put_event(&event);
}

static const char *get_image_type_str(enum mod_fip_toc_entry_type type)
{
    if (type == MOD_FIP_TOC_ENTRY_MCP_BL2)
        return "MCP";
    if (type == MOD_FIP_TOC_ENTRY_SCP_BL2)
        return "SCP";
    return "???";
}

static int n1sdp_rom_process_event(const struct fwk_event *event,
    struct fwk_event *resp)
{
    struct mod_fip_entry_data entry;
    int status = n1sdp_rom_ctx.fip_api->get_entry(
        n1sdp_rom_ctx.rom_config->image_type, &entry);
    const char *image_type =
        get_image_type_str(n1sdp_rom_ctx.rom_config->image_type);

    if (status != FWK_SUCCESS) {
        FWK_LOG_INFO(
            "[ROM] Failed to locate %s_BL2, error: %d\n", image_type, status);
        return status;
    }

    FWK_LOG_INFO("[ROM] Located %s_BL2:\n", image_type);
    FWK_LOG_INFO("[ROM]   address: %p\n", entry.base);
    FWK_LOG_INFO("[ROM]   size   : %u\n", entry.size);
    FWK_LOG_INFO("[ROM]   flags  : 0x%08" PRIX32 "%08" PRIX32"\n",
        (uint32_t)(entry.flags >> 32),  (uint32_t)entry.flags);
    FWK_LOG_INFO("[ROM] Copying %s_BL2 to ITCRAM...!\n", image_type);

    memcpy(
        (void *)n1sdp_rom_ctx.rom_config->ramfw_base, entry.base, entry.size);
    FWK_LOG_INFO("[ROM] Done!");

    FWK_LOG_INFO("[ROM] Jumping to %s_BL2\n", image_type);

    jump_to_ramfw();
    return FWK_SUCCESS;
}

/* Module descriptor */
const struct fwk_module module_n1sdp_rom = {
    .name = "N1SDP SCP ROM",
    .type = FWK_MODULE_TYPE_SERVICE,
    .event_count = ROM_EVENT_COUNT,
    .init = n1sdp_rom_init,
    .bind = n1sdp_rom_bind,
    .start = n1sdp_rom_start,
    .process_event = n1sdp_rom_process_event,
};