1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * Reset domain HAL
9 */
10
11 #include <fwk_mm.h>
12 #include <fwk_module.h>
13 #include <fwk_module_idx.h>
14 #include <fwk_notification.h>
15 #include <mod_reset_domain.h>
16
17 /*
18 * Module and devices contexts for Reset Domain
19 */
20
21 /* Device context */
22 struct rd_dev_ctx {
23 const struct mod_reset_domain_dev_config *config;
24 struct mod_reset_domain_drv_api *driver_api;
25 };
26
27 /* Module context */
28 struct mod_rd_ctx {
29 const struct mod_reset_domain_config *config;
30 struct rd_dev_ctx *dev_ctx_table;
31 unsigned int dev_count;
32 };
33
34 /*
35 * Internal variables
36 */
37 static struct mod_rd_ctx module_reset_ctx;
38
39 /*
40 * API functions
41 */
set_reset_state(fwk_id_t reset_dev_id,enum mod_reset_domain_mode mode,uint32_t reset_state,uintptr_t cookie)42 static int set_reset_state(fwk_id_t reset_dev_id,
43 enum mod_reset_domain_mode mode,
44 uint32_t reset_state,
45 uintptr_t cookie)
46 {
47 struct rd_dev_ctx *reset_ctx;
48 unsigned int reset_domain_idx = fwk_id_get_element_idx(reset_dev_id);
49
50 reset_ctx = &module_reset_ctx.dev_ctx_table[reset_domain_idx];
51
52 return reset_ctx->driver_api->set_reset_state(reset_ctx->config->driver_id,
53 mode, reset_state, cookie);
54 }
55
56 /* HAL API */
57 static const struct mod_reset_domain_api reset_api = {
58 .set_reset_state = set_reset_state,
59 };
60
61 #ifdef BUILD_HAS_NOTIFICATION
reset_issued_notify(fwk_id_t dev_id,uint32_t reset_state,uintptr_t cookie)62 static int reset_issued_notify(fwk_id_t dev_id,
63 uint32_t reset_state,
64 uintptr_t cookie)
65 {
66 int domain_id = -1;
67 unsigned int i;
68 struct rd_dev_ctx *reset_ctx;
69 unsigned int notification_count;
70 struct fwk_event notification_event = {
71 .id = module_reset_ctx.config->notification_id,
72 .source_id = fwk_module_id_reset_domain,
73 };
74
75 struct mod_reset_domain_notification_event_params* params =
76 (struct mod_reset_domain_notification_event_params*)
77 notification_event.params;
78
79 /* Loop through device context table to get the associated domain_id */
80 for (i = 0; i < module_reset_ctx.dev_count; i++) {
81 reset_ctx = &module_reset_ctx.dev_ctx_table[i];
82 if (fwk_id_is_equal(reset_ctx->config->driver_id, dev_id)) {
83 domain_id = (int)i;
84 break;
85 }
86 }
87
88 if (domain_id < 0)
89 return FWK_E_PARAM;
90
91 params->domain_id = (uint32_t)domain_id;
92 params->reset_state = reset_state;
93 params->cookie = cookie;
94
95 return fwk_notification_notify(¬ification_event, ¬ification_count);
96 }
97 #endif /* BUILD_HAS_NOTIFICATION */
98
rd_process_event(const struct fwk_event * event,struct fwk_event * resp)99 static int rd_process_event(
100 const struct fwk_event *event,
101 struct fwk_event *resp)
102 {
103 #ifdef BUILD_HAS_NOTIFICATION
104 struct mod_reset_domain_autoreset_event_params* params =
105 (struct mod_reset_domain_autoreset_event_params*)event->params;
106 #endif
107
108 if (!fwk_id_is_equal(mod_reset_domain_autoreset_event_id,
109 event->id))
110 return FWK_E_SUPPORT;
111
112 #ifdef BUILD_HAS_NOTIFICATION
113 return reset_issued_notify(params->dev_id,
114 params->reset_state, params->cookie);
115 #else
116 return FWK_SUCCESS;
117 #endif
118 }
119
120 /*
121 * Framework handlers
122 */
rd_init(fwk_id_t module_id,unsigned int dev_count,const void * data)123 static int rd_init(fwk_id_t module_id,
124 unsigned int dev_count,
125 const void *data)
126 {
127 module_reset_ctx.config = (struct mod_reset_domain_config *)data;
128 module_reset_ctx.dev_ctx_table = fwk_mm_calloc(dev_count,
129 sizeof(struct rd_dev_ctx));
130 module_reset_ctx.dev_count = dev_count;
131
132 return FWK_SUCCESS;
133 }
134
rd_element_init(fwk_id_t element_id,unsigned int sub_dev_count,const void * data)135 static int rd_element_init(fwk_id_t element_id,
136 unsigned int sub_dev_count,
137 const void *data)
138 {
139 struct rd_dev_ctx *reset_ctx = NULL;
140
141 reset_ctx = &module_reset_ctx.dev_ctx_table[
142 fwk_id_get_element_idx(element_id)];
143
144 reset_ctx->config = (const struct mod_reset_domain_dev_config *)data;
145
146 return FWK_SUCCESS;
147 }
148
rd_bind(fwk_id_t id,unsigned int round)149 static int rd_bind(fwk_id_t id, unsigned int round)
150 {
151 struct rd_dev_ctx *reset_ctx = NULL;
152
153 /* Nothing to do during subsequent round of calls */
154 if (round != 0)
155 return FWK_SUCCESS;
156
157 if (!fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT))
158 return FWK_SUCCESS;
159
160 reset_ctx = module_reset_ctx.dev_ctx_table + fwk_id_get_element_idx(id);
161
162 return fwk_module_bind(reset_ctx->config->driver_id,
163 reset_ctx->config->driver_api_id,
164 &reset_ctx->driver_api);
165 }
166
rd_process_bind_request(fwk_id_t source_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)167 static int rd_process_bind_request(fwk_id_t source_id,
168 fwk_id_t target_id,
169 fwk_id_t api_id,
170 const void **api)
171 {
172 enum mod_reset_domain_api_type api_id_type =
173 (enum mod_reset_domain_api_type)fwk_id_get_api_idx(api_id);
174
175 switch (api_id_type) {
176 case MOD_RESET_DOMAIN_API_TYPE_HAL:
177 *api = &reset_api;
178 break;
179
180 default:
181 return FWK_E_ACCESS;
182 }
183
184 return FWK_SUCCESS;
185 }
186
187 const struct fwk_module module_reset_domain = {
188 .type = FWK_MODULE_TYPE_HAL,
189 .api_count = (unsigned int)MOD_RESET_DOMAIN_API_COUNT,
190 #ifdef BUILD_HAS_NOTIFICATION
191 .notification_count = (unsigned int)MOD_RESET_DOMAIN_NOTIFICATION_IDX_COUNT,
192 #endif
193 .event_count = (unsigned int)MOD_RESET_DOMAIN_EVENT_IDX_COUNT,
194 .init = rd_init,
195 .element_init = rd_element_init,
196 .bind = rd_bind,
197 .process_bind_request = rd_process_bind_request,
198 .process_event = rd_process_event,
199 };
200