1 /*
2 * Copyright (c) 2024, Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT altr_socfpga_agilex_bridge
8
9 #include <errno.h>
10 #include <zephyr/device.h>
11 #include <zephyr/sip_svc/sip_svc.h>
12 #include <zephyr/drivers/sip_svc/sip_svc_agilex_smc.h>
13 #include <zephyr/drivers/fpga.h>
14 #include <zephyr/logging/log.h>
15 #include "fpga_altera_agilex_bridge.h"
16
17 LOG_MODULE_REGISTER(fpga_altera, CONFIG_FPGA_LOG_LEVEL);
18
19 struct fpga_bridge_dev_data {
20 /* SiP SVC controller */
21 struct sip_svc_controller *mailbox_smc_dev;
22 /* SiP SVC client token id */
23 uint32_t mailbox_client_token;
24 };
25
26 #define MAX_TIMEOUT_MSECS (1 * 1000UL)
27
28 /**
29 * @brief Open SiP SVC client session
30 *
31 * @return 0 on success or negative value on failure
32 */
svc_client_open(const struct device * dev)33 static int32_t svc_client_open(const struct device *dev)
34 {
35 if (!dev) {
36 LOG_ERR("No such device found");
37 return -ENODEV;
38 }
39
40 struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);
41
42 if ((!data->mailbox_smc_dev) || (data->mailbox_client_token == 0)) {
43 LOG_ERR("Mailbox client is not registered");
44 return -ENODEV;
45 }
46
47 if (sip_svc_open(data->mailbox_smc_dev, data->mailbox_client_token,
48 K_MSEC(MAX_TIMEOUT_MSECS))) {
49 LOG_ERR("Mailbox client open fail");
50 return -ENODEV;
51 }
52
53 return 0;
54 }
55
56 /**
57 * @brief Close the svc client
58 *
59 * @return 0 on success or negative value on fail
60 */
svc_client_close(const struct device * dev)61 static int32_t svc_client_close(const struct device *dev)
62 {
63 int32_t err;
64 uint32_t cmd_size = sizeof(uint32_t);
65 struct sip_svc_request request;
66
67 if (!dev) {
68 LOG_ERR("No such device found");
69 return -ENODEV;
70 }
71
72 struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);
73
74 uint32_t *cmd_addr = (uint32_t *)k_malloc(cmd_size);
75
76 if (!cmd_addr) {
77 return -ENOMEM;
78 }
79
80 /* Fill the SiP SVC buffer with CANCEL request */
81 *cmd_addr = MAILBOX_CANCEL_COMMAND;
82
83 request.header = SIP_SVC_PROTO_HEADER(SIP_SVC_PROTO_CMD_ASYNC, 0);
84 request.a0 = SMC_FUNC_ID_MAILBOX_SEND_COMMAND;
85 request.a1 = 0;
86 request.a2 = (uint64_t)cmd_addr;
87 request.a3 = (uint64_t)cmd_size;
88 request.a4 = 0;
89 request.a5 = 0;
90 request.a6 = 0;
91 request.a7 = 0;
92 request.resp_data_addr = (uint64_t)NULL;
93 request.resp_data_size = 0;
94 request.priv_data = NULL;
95
96 err = sip_svc_close(data->mailbox_smc_dev, data->mailbox_client_token, &request);
97 if (err) {
98 k_free(cmd_addr);
99 LOG_ERR("Mailbox client close fail (%d)", err);
100 }
101
102 return err;
103 }
104
105 /**
106 * @brief Call back function which we receive when we send the data
107 * based on the current stage it will collect the data
108 *
109 * @param[in] c_token Token id for our svc services
110 * @param[in] response Buffer will contain the response
111 *
112 * @return void
113 */
smc_callback(uint32_t c_token,struct sip_svc_response * response)114 static void smc_callback(uint32_t c_token, struct sip_svc_response *response)
115 {
116 if (response == NULL) {
117 return;
118 }
119
120 uint32_t *resp_data = NULL;
121 uint32_t resp_len = 0;
122 uint32_t mbox_idx = 0;
123
124 struct sip_svc_private_data *private_data =
125 (struct sip_svc_private_data *)response->priv_data;
126 union mailbox_response_header response_header;
127
128 LOG_DBG("SiP SVC callback");
129
130 LOG_DBG("\tresponse data below:");
131 LOG_DBG("\theader=%08x", response->header);
132 LOG_DBG("\ta0=%016lx", response->a0);
133 LOG_DBG("\ta1=%016lx", response->a1);
134 LOG_DBG("\ta2=%016lx", response->a2);
135 LOG_DBG("\ta3=%016lx", response->a3);
136
137 private_data->response.header = response->header;
138 private_data->response.a0 = response->a0;
139 private_data->response.a1 = response->a1;
140 private_data->response.a2 = response->a2;
141 private_data->response.a3 = response->a3;
142 private_data->response.resp_data_size = response->resp_data_size;
143
144 /* Condition to check only for the mailbox command not for the non-mailbox command */
145 if (response->resp_data_size) {
146 resp_data = (uint32_t *)response->resp_data_addr;
147 resp_len = response->resp_data_size / 4;
148 private_data->mbox_response_len = resp_len;
149 if (resp_data && resp_len) {
150 response_header = (union mailbox_response_header)resp_data[0];
151 private_data->mbox_response_data =
152 (uint32_t *)k_malloc(sizeof(uint32_t) * resp_len);
153 for (mbox_idx = 0; mbox_idx < resp_len; mbox_idx++) {
154 LOG_DBG("\t\t[%4d] %08x", mbox_idx, resp_data[mbox_idx]);
155 private_data->mbox_response_data[mbox_idx] = resp_data[mbox_idx];
156 }
157 } else {
158 LOG_ERR("\t\tInvalid addr (%p) or len (%d)", resp_data, resp_len);
159 }
160 }
161 /* Condition for non-mailbox command*/
162 else {
163 LOG_DBG("Response Data size is zero !!");
164 }
165
166 /* Client only responsible to free the response data memory space,
167 * the command data memory space had been freed by SiP SVC service.
168 */
169 if (response->resp_data_addr) {
170 LOG_DBG("\tFree response memory %p", (char *)response->resp_data_addr);
171 k_free((char *)response->resp_data_addr);
172 }
173
174 k_sem_give(&(private_data->smc_sem));
175 }
176
177 /**
178 * @brief Send the data to SiP SVC service layer
179 * based on the command type further data will be send to SDM using mailbox
180 *
181 * @param[in] cmd_type Command type (Mailbox or Non-Mailbox)
182 * @param[in] function_identifier Function identifier for each command type
183 * @param[in] cmd_request
184 * @param[in] private_data
185 *
186 * @return 0 on success or negative value on fail
187 */
smc_send(const struct device * dev,uint32_t cmd_type,uint64_t function_identifier,uint32_t * cmd_request,struct sip_svc_private_data * private_data)188 static int32_t smc_send(const struct device *dev, uint32_t cmd_type, uint64_t function_identifier,
189 uint32_t *cmd_request, struct sip_svc_private_data *private_data)
190 {
191 int32_t trans_id = 0;
192 uint32_t *cmd_addr = NULL;
193 uint32_t *resp_addr = NULL;
194 struct sip_svc_request request;
195
196 if (!dev) {
197 LOG_ERR("No such device found");
198 return -ENODEV;
199 }
200
201 struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);
202
203 if (!data->mailbox_smc_dev) {
204 LOG_ERR("Mailbox client is not registered");
205 return -ENODEV;
206 }
207
208 if (cmd_type == SIP_SVC_PROTO_CMD_ASYNC) {
209 cmd_addr = (uint32_t *)k_malloc(FPGA_MB_CMD_ADDR_MEM_SIZE);
210 if (!cmd_addr) {
211 LOG_ERR("Failed to allocate command memory");
212 return -ENOMEM;
213 }
214 cmd_addr[MBOX_CMD_HEADER_INDEX] =
215 MBOX_REQUEST_HEADER(cmd_request[SMC_REQUEST_A2_INDEX], 0, 0);
216 resp_addr = (uint32_t *)k_malloc(FPGA_MB_RESPONSE_MEM_SIZE);
217 if (!resp_addr) {
218 k_free(cmd_addr);
219 return -ENOMEM;
220 }
221
222 request.a2 = (uint64_t)cmd_addr;
223 request.a3 = sizeof(uint32_t);
224 request.resp_data_addr = (uint64_t)resp_addr;
225 request.resp_data_size = FPGA_MB_RESPONSE_MEM_SIZE;
226
227 #if defined(CONFIG_LOG)
228 for (int32_t mbox_idx = 0; mbox_idx < request.a3 / 4; mbox_idx++) {
229 LOG_DBG("\t [%d ] %08x", mbox_idx, cmd_addr[mbox_idx]);
230 }
231 #endif
232
233 } else {
234 request.a2 = cmd_request[SMC_REQUEST_A2_INDEX];
235 request.a3 = cmd_request[SMC_REQUEST_A3_INDEX];
236 request.resp_data_addr = 0;
237 request.resp_data_size = 0;
238 }
239
240 /* Fill SiP SVC request buffer */
241 request.header = SIP_SVC_PROTO_HEADER(cmd_type, 0);
242 request.a0 = function_identifier;
243 request.a1 = 0;
244 request.a4 = 0;
245 request.a5 = 0;
246 request.a6 = 0;
247 request.a7 = 0;
248 request.priv_data = (void *)private_data;
249
250 /* Send SiP SVC request */
251 trans_id = sip_svc_send(data->mailbox_smc_dev, data->mailbox_client_token, &request,
252 smc_callback);
253
254 if (trans_id == SIP_SVC_ID_INVALID) {
255 LOG_ERR("SiP SVC send request fail");
256 return -EBUSY;
257 }
258
259 return 0;
260 }
261
262 /* Validate the Reconfig status response */
fpga_reconfig_status_validate(struct fpga_config_status * reconfig_status_resp)263 static int32_t fpga_reconfig_status_validate(struct fpga_config_status *reconfig_status_resp)
264 {
265 uint32_t ret = 0;
266
267 /* Check for any error */
268 ret = reconfig_status_resp->state;
269 if (ret == MBOX_CFGSTAT_VAB_BS_PREAUTH) {
270 return MBOX_CONFIG_STATUS_STATE_CONFIG;
271 }
272
273 if (ret && ret != MBOX_CONFIG_STATUS_STATE_CONFIG) {
274 return ret;
275 }
276
277 /* Make sure nStatus is not 0 */
278 ret = reconfig_status_resp->pin_status.pin_status;
279 if (!(ret & RECONFIG_PIN_STATUS_NSTATUS)) {
280 return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
281 }
282
283 ret = reconfig_status_resp->soft_function_status;
284 if ((ret & RECONFIG_SOFTFUNC_STATUS_CONF_DONE) &&
285 (ret & RECONFIG_SOFTFUNC_STATUS_INIT_DONE) && !reconfig_status_resp->state) {
286 return 0; /* Configuration success */
287 }
288
289 return MBOX_CONFIG_STATUS_STATE_CONFIG;
290 }
291
292 /* Will send the SMC command to check the status of the FPGA */
fpga_config_ready_check(const struct device * dev)293 static int32_t fpga_config_ready_check(const struct device *dev)
294 {
295 uint32_t smc_cmd[2] = {0};
296 int32_t ret = 0;
297 struct sip_svc_private_data priv_data;
298
299 /* Initialize the semaphore */
300 k_sem_init(&(priv_data.smc_sem), 0, 1);
301
302 smc_cmd[SMC_REQUEST_A2_INDEX] = FPGA_CONFIG_STATUS;
303 smc_cmd[SMC_REQUEST_A3_INDEX] = 0;
304
305 /* Sending the FPGA config status mailbox command */
306 ret = smc_send(dev, SIP_SVC_PROTO_CMD_ASYNC, SMC_FUNC_ID_MAILBOX_SEND_COMMAND, smc_cmd,
307 &priv_data);
308 if (ret) {
309 LOG_ERR("Failed to Send the Mailbox Command !!");
310 return -ECANCELED;
311 }
312
313 k_sem_take(&(priv_data.smc_sem), K_FOREVER);
314
315 /* Verify the SMC response */
316 if (!priv_data.response.resp_data_size &&
317 priv_data.mbox_response_len != FPGA_CONFIG_STATUS_RESPONSE_LEN) {
318 return -EINVAL;
319 }
320
321 /* Verify the FPGA config status response */
322 ret = fpga_reconfig_status_validate(
323 (struct fpga_config_status *)priv_data.mbox_response_data);
324
325 k_free(priv_data.mbox_response_data);
326
327 return ret;
328 }
329
socfpga_bridges_reset(const struct device * dev,uint32_t enable)330 static int32_t socfpga_bridges_reset(const struct device *dev, uint32_t enable)
331 {
332 uint32_t smc_cmd[2] = {0};
333 int ret = 0;
334 struct sip_svc_private_data priv_data;
335
336 if (!dev) {
337 LOG_ERR("No such device found");
338 return -ENODEV;
339 }
340
341 /* Initialize the semaphore */
342 k_sem_init(&(priv_data.smc_sem), 0, 1);
343
344 smc_cmd[SMC_REQUEST_A2_INDEX] = FIELD_GET(BIT(0), enable);
345
346 smc_cmd[SMC_REQUEST_A2_INDEX] |= BIT(1);
347 smc_cmd[SMC_REQUEST_A3_INDEX] = BRIDGE_MASK;
348
349 ret = smc_send(dev, SIP_SVC_PROTO_CMD_SYNC, SMC_FUNC_ID_SET_HPS_BRIDGES, smc_cmd,
350 &priv_data);
351 if (ret) {
352 LOG_ERR("Failed to send the smc Command !!");
353 return ret;
354 }
355
356 /* Wait for the SiP SVC callback */
357 k_sem_take(&(priv_data.smc_sem), K_FOREVER);
358
359 /* Check error code */
360 if (priv_data.response.a0) {
361 ret = -ENOMSG;
362 }
363
364 return ret;
365 }
366
altera_fpga_on(const struct device * dev)367 static int altera_fpga_on(const struct device *dev)
368 {
369 int32_t ret = 0;
370
371 if (!dev) {
372 LOG_ERR("No such device found");
373 return -ENODEV;
374 }
375
376 /* Opening SIP SVC session */
377 ret = svc_client_open(dev);
378 if (ret) {
379 LOG_ERR("Client open Failed!");
380 return ret;
381 }
382
383 /* Check FPGA status before bridge enable/disable */
384 ret = fpga_config_ready_check(dev);
385 if (ret) {
386 LOG_ERR("FPGA not ready. Bridge reset aborted!");
387 svc_client_close(dev);
388 return -EIO;
389 }
390
391 /* Bridge reset */
392 ret = socfpga_bridges_reset(dev, 0x01);
393 if (ret) {
394 LOG_ERR("Bridge reset failed");
395 }
396
397 /* Ignoring the return value to return bridge reset status */
398 if (svc_client_close(dev)) {
399 LOG_ERR("Unregistering & Closing failed");
400 }
401
402 return ret;
403 }
404
altera_fpga_off(const struct device * dev)405 static int altera_fpga_off(const struct device *dev)
406 {
407 int32_t ret = 0;
408
409 if (!dev) {
410 LOG_ERR("No such device found");
411 return -ENODEV;
412 }
413
414 /* Opening SIP SVC session */
415 ret = svc_client_open(dev);
416 if (ret) {
417 LOG_ERR("Client open Failed!");
418 return ret;
419 }
420
421 /* Check FPGA status before bridge enable/disable */
422 ret = fpga_config_ready_check(dev);
423 if (ret) {
424 LOG_ERR("FPGA not ready. Bridge reset aborted!");
425 svc_client_close(dev);
426 return -EIO;
427 }
428
429 /* Bridge reset */
430 ret = socfpga_bridges_reset(dev, 0x00);
431 if (ret) {
432 LOG_ERR("Bridge reset failed");
433 }
434
435 /* Ignoring the return value to return bridge reset status */
436 if (svc_client_close(dev)) {
437 LOG_ERR("Unregistering & Closing failed");
438 }
439
440 return ret;
441 }
442
altera_fpga_init(const struct device * dev)443 static int altera_fpga_init(const struct device *dev)
444 {
445 if (!dev) {
446 LOG_ERR("No such device found");
447 return -ENODEV;
448 }
449
450 struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);
451
452 data->mailbox_smc_dev = sip_svc_get_controller("smc");
453 if (!data->mailbox_smc_dev) {
454 LOG_ERR("Arm SiP service not found");
455 return -ENODEV;
456 }
457
458 data->mailbox_client_token = sip_svc_register(data->mailbox_smc_dev, NULL);
459 if (data->mailbox_client_token == SIP_SVC_ID_INVALID) {
460 data->mailbox_smc_dev = NULL;
461 LOG_ERR("Mailbox client register fail");
462 return -EINVAL;
463 }
464
465 return 0;
466 }
467
468 static DEVICE_API(fpga, altera_fpga_api) = {
469 .on = altera_fpga_on,
470 .off = altera_fpga_off,
471 };
472
473 #define CREATE_ALTERA_FPGA_BRIDGE_DEV(inst) \
474 static struct fpga_bridge_dev_data fpga_bridge_data_##inst; \
475 DEVICE_DT_INST_DEFINE(inst, \
476 altera_fpga_init, \
477 NULL, &fpga_bridge_data_##inst, \
478 NULL, POST_KERNEL, \
479 CONFIG_FPGA_INIT_PRIORITY, \
480 &altera_fpga_api); \
481
482 DT_INST_FOREACH_STATUS_OKAY(CREATE_ALTERA_FPGA_BRIDGE_DEV);
483