aboutsummaryrefslogtreecommitdiff
path: root/product/rdn1e1/module/rdn1e1_rom/src/mod_rdn1e1_rom.c
blob: 86f51f5b87dcf0d88fc651a8f581409f48a9a87d (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
/*
 * Arm SCP/MCP Software
 * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdint.h>
#include <string.h>
#include <fwk_errno.h>
#include <fwk_interrupt.h>
#include <fwk_module.h>
#include <fwk_module_idx.h>
#include <fwk_thread.h>
#include <mod_log.h>
#include <mod_rdn1e1_rom.h>

static const struct rdn1e1_rom_config *rom_config;
static struct mod_log_api *log_api;

enum rom_event {
    ROM_EVENT_RUN,
    ROM_EVENT_COUNT
};

/*
 * This function assumes that the RAM firmware image is located at the beginning
 * of the SCP SRAM. The reset handler will be at offset 0x4 (the second entry of
 * the vector table).
 */
static void jump_to_ramfw(void)
{
    uintptr_t const *reset_base = (uintptr_t *)(rom_config->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;

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

/*
 * Framework API
 */
static int rdn1e1_rom_init(fwk_id_t module_id, unsigned int element_count,
    const void *data)
{
    rom_config = data;

    return FWK_SUCCESS;
}

static int rdn1e1_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 log component */
        status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_LOG),
                                 FWK_ID_API(FWK_MODULE_IDX_LOG, 0),
                                 &log_api);

        if (status != FWK_SUCCESS)
            return FWK_E_PANIC;
    }

    return FWK_SUCCESS;
}

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

    status = fwk_thread_put_event(&event);

    return status;
}

static int rdn1e1_rom_process_event(const struct fwk_event *event,
    struct fwk_event *resp)
{
    log_api->log(MOD_LOG_GROUP_INFO, "[ROM] Launch RAM\n");

    if (rom_config->load_ram_size != 0) {
        memcpy((void *)rom_config->ramfw_base,
            (uint8_t *)rom_config->nor_base, rom_config->load_ram_size);
    }

    jump_to_ramfw();

    return FWK_SUCCESS;
}

/* Module descriptor */
const struct fwk_module module_rdn1e1_rom = {
    .name = "RDN1E1_ROM",
    .type = FWK_MODULE_TYPE_SERVICE,
    .event_count = ROM_EVENT_COUNT,
    .init = rdn1e1_rom_init,
    .bind = rdn1e1_rom_bind,
    .start = rdn1e1_rom_start,
    .process_event = rdn1e1_rom_process_event,
};