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_nor.h>
9 #include <mod_power_domain.h>
10 #include <mod_synquacer_system.h>
11 #include <mod_system_power.h>
12 
13 #include <fwk_core.h>
14 #include <fwk_event.h>
15 #include <fwk_id.h>
16 #include <fwk_log.h>
17 #include <fwk_module.h>
18 #include <fwk_module_idx.h>
19 #include <fwk_status.h>
20 
21 #include <stdbool.h>
22 
23 struct synquacer_system_ctx synquacer_system_ctx;
24 const struct fwk_module_config config_synquacer_system = { 0 };
25 
26 enum synquacer_system_event {
27     SYNQUACER_SYSTEM_EVENT_START,
28     SYNQUACER_SYSTEM_EVENT_COUNT
29 };
30 
31 int synquacer_reboot_chip(void);
32 int synquacer_shutdown(void);
33 void power_domain_reboot(void);
34 void main_initialize(void);
35 int synquacer_main(void);
36 
37 /*
38  * SYSTEM POWER driver API
39  */
40 
synquacer_system_shutdown(enum mod_pd_system_shutdown system_shutdown)41 static int synquacer_system_shutdown(
42     enum mod_pd_system_shutdown system_shutdown)
43 {
44     switch (system_shutdown) {
45     case MOD_PD_SYSTEM_SHUTDOWN:
46         FWK_LOG_INFO("[SYNQUACER SYSTEM] system is shutting down");
47         synquacer_shutdown();
48         break;
49     case MOD_PD_SYSTEM_COLD_RESET:
50         FWK_LOG_INFO("[SYNQUACER SYSTEM] system is cold reset");
51         synquacer_reboot_chip();
52         break;
53     default:
54         return FWK_E_SUPPORT;
55     }
56 
57     return FWK_E_DEVICE;
58 }
59 
60 static const struct mod_system_power_driver_api
61     synquacer_system_power_driver_api = {
62         .system_shutdown = synquacer_system_shutdown,
63     };
64 
65 /*
66  * Functions fulfilling the framework's module interface
67  */
68 
synquacer_system_mod_init(fwk_id_t module_id,unsigned int unused,const void * unused2)69 static int synquacer_system_mod_init(
70     fwk_id_t module_id,
71     unsigned int unused,
72     const void *unused2)
73 {
74     return FWK_SUCCESS;
75 }
76 
synquacer_system_bind(fwk_id_t id,unsigned int round)77 static int synquacer_system_bind(fwk_id_t id, unsigned int round)
78 {
79     int status;
80 
81     if (round == 0) {
82         status = fwk_module_bind(
83             FWK_ID_MODULE(FWK_MODULE_IDX_CCN512),
84             FWK_ID_API(FWK_MODULE_IDX_CCN512, 0),
85             &synquacer_system_ctx.ccn512_api);
86         if (status != FWK_SUCCESS)
87             return status;
88 
89         status = fwk_module_bind(
90             FWK_ID_MODULE(FWK_MODULE_IDX_F_I2C),
91             FWK_ID_API(FWK_MODULE_IDX_F_I2C, 0),
92             &synquacer_system_ctx.f_i2c_api);
93         if (status != FWK_SUCCESS)
94             return status;
95 
96         status = fwk_module_bind(
97             FWK_ID_MODULE(FWK_MODULE_IDX_HSSPI),
98             FWK_ID_API(FWK_MODULE_IDX_HSSPI, 0),
99             &synquacer_system_ctx.qspi_api);
100         if (status != FWK_SUCCESS)
101             return status;
102 
103         status = fwk_module_bind(
104             FWK_ID_MODULE(FWK_MODULE_IDX_NOR),
105             FWK_ID_API(FWK_MODULE_IDX_NOR, MOD_NOR_API_TYPE_DEFAULT),
106             &synquacer_system_ctx.nor_api);
107         if (status != FWK_SUCCESS)
108             return status;
109 
110         status = fwk_module_bind(
111             FWK_ID_MODULE(FWK_MODULE_IDX_POWER_DOMAIN),
112             FWK_ID_API(FWK_MODULE_IDX_POWER_DOMAIN, MOD_PD_API_IDX_RESTRICTED),
113             &synquacer_system_ctx.mod_pd_restricted_api);
114         if (status != FWK_SUCCESS)
115             return status;
116 
117         status = fwk_module_bind(
118             FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
119             FWK_ID_API(FWK_MODULE_IDX_TIMER, MOD_TIMER_API_IDX_TIMER),
120             &synquacer_system_ctx.timer_api);
121         if (status != FWK_SUCCESS) {
122             return status;
123         }
124     }
125 
126     FWK_LOG_INFO("[SYNQUACER SYSTEM] bind success\n");
127 
128     return FWK_SUCCESS;
129 }
130 
synquacer_system_process_bind_request(fwk_id_t requester_id,fwk_id_t pd_id,fwk_id_t api_id,const void ** api)131 static int synquacer_system_process_bind_request(
132     fwk_id_t requester_id,
133     fwk_id_t pd_id,
134     fwk_id_t api_id,
135     const void **api)
136 {
137     *api = &synquacer_system_power_driver_api;
138     return FWK_SUCCESS;
139 }
140 
synquacer_system_start(fwk_id_t id)141 static int synquacer_system_start(fwk_id_t id)
142 {
143     int status;
144     struct fwk_event req;
145 
146     main_initialize();
147 
148     FWK_LOG_INFO("[SYNQUACER SYSTEM] Request system initialization.");
149 
150     req = (struct fwk_event){
151         .id = FWK_ID_EVENT(
152             FWK_MODULE_IDX_SYNQUACER_SYSTEM, SYNQUACER_SYSTEM_EVENT_START),
153         .source_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_SYSTEM),
154         .target_id = FWK_ID_MODULE(FWK_MODULE_IDX_SYNQUACER_SYSTEM),
155         .response_requested = false,
156     };
157 
158     status = fwk_put_event(&req);
159     if (status != FWK_SUCCESS)
160         return status;
161 
162     return FWK_SUCCESS;
163 }
164 
synquacer_process_event(const struct fwk_event * event,struct fwk_event * resp)165 int synquacer_process_event(
166     const struct fwk_event *event,
167     struct fwk_event *resp)
168 {
169     if (fwk_id_get_event_idx(event->id) == SYNQUACER_SYSTEM_EVENT_START) {
170         FWK_LOG_INFO("[SYNQUACER SYSTEM] Process system start event.");
171         synquacer_main();
172     }
173 
174     return FWK_SUCCESS;
175 }
176 
177 const struct fwk_module module_synquacer_system = {
178     .type = FWK_MODULE_TYPE_DRIVER,
179     .api_count = 1,
180     .event_count = 1,
181     .init = synquacer_system_mod_init,
182     .bind = synquacer_system_bind,
183     .process_bind_request = synquacer_system_process_bind_request,
184     .start = synquacer_system_start,
185     .process_event = synquacer_process_event,
186 };
187