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