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);
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 	/* Make sure nStatus is not 0 */
277 	ret = reconfig_status_resp->pin_status.pin_status;
278 	if (!(ret & RECONFIG_PIN_STATUS_NSTATUS))
279 		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
280 
281 	ret = reconfig_status_resp->soft_function_status;
282 	if ((ret & RECONFIG_SOFTFUNC_STATUS_CONF_DONE) &&
283 		(ret & RECONFIG_SOFTFUNC_STATUS_INIT_DONE) && !reconfig_status_resp->state)
284 		return 0; /* Configuration success */
285 
286 	return MBOX_CONFIG_STATUS_STATE_CONFIG;
287 }
288 
289 /* Will send the SMC command to check the status of the FPGA */
fpga_config_ready_check(const struct device * dev)290 static int32_t fpga_config_ready_check(const struct device *dev)
291 {
292 	uint32_t smc_cmd[2] = {0};
293 	int32_t ret = 0;
294 	struct sip_svc_private_data priv_data;
295 
296 	/* Initialize the semaphore */
297 	k_sem_init(&(priv_data.smc_sem), 0, 1);
298 
299 	smc_cmd[SMC_REQUEST_A2_INDEX] = FPGA_CONFIG_STATUS;
300 	smc_cmd[SMC_REQUEST_A3_INDEX] = 0;
301 
302 	/* Sending the FPGA config status mailbox command */
303 	ret = smc_send(dev, SIP_SVC_PROTO_CMD_ASYNC, SMC_FUNC_ID_MAILBOX_SEND_COMMAND, smc_cmd,
304 				&priv_data);
305 	if (ret) {
306 		LOG_ERR("Failed to Send the Mailbox Command !!");
307 		return -ECANCELED;
308 	}
309 
310 	k_sem_take(&(priv_data.smc_sem), K_FOREVER);
311 
312 	/* Verify the SMC response */
313 	if (!priv_data.response.resp_data_size &&
314 		priv_data.mbox_response_len != FPGA_CONFIG_STATUS_RESPONSE_LEN) {
315 		return -EINVAL;
316 	}
317 
318 	/* Verify the FPGA config status response */
319 	ret = fpga_reconfig_status_validate(
320 		(struct fpga_config_status *)priv_data.mbox_response_data);
321 
322 	k_free(priv_data.mbox_response_data);
323 
324 	return ret;
325 }
326 
socfpga_bridges_reset(const struct device * dev,uint32_t enable)327 static int32_t socfpga_bridges_reset(const struct device *dev, uint32_t enable)
328 {
329 	uint32_t smc_cmd[2] = {0};
330 	int ret = 0;
331 	struct sip_svc_private_data priv_data;
332 
333 	if (!dev) {
334 		LOG_ERR("No such device found");
335 		return -ENODEV;
336 	}
337 
338 	/* Initialize the semaphore */
339 	k_sem_init(&(priv_data.smc_sem), 0, 1);
340 
341 	smc_cmd[SMC_REQUEST_A2_INDEX] = FIELD_GET(BIT(0), enable);
342 
343 	smc_cmd[SMC_REQUEST_A2_INDEX] |= BIT(1);
344 	smc_cmd[SMC_REQUEST_A3_INDEX] = BRIDGE_MASK;
345 
346 	ret = smc_send(dev, SIP_SVC_PROTO_CMD_SYNC, SMC_FUNC_ID_SET_HPS_BRIDGES, smc_cmd,
347 				&priv_data);
348 	if (ret) {
349 		LOG_ERR("Failed to send the smc Command !!");
350 		return ret;
351 	}
352 
353 	/* Wait for the SiP SVC callback */
354 	k_sem_take(&(priv_data.smc_sem), K_FOREVER);
355 
356 	/* Check error code */
357 	if (priv_data.response.a0) {
358 		ret = -ENOMSG;
359 	}
360 
361 	return ret;
362 }
363 
altera_fpga_on(const struct device * dev)364 static int altera_fpga_on(const struct device *dev)
365 {
366 	int32_t ret = 0;
367 
368 	if (!dev) {
369 		LOG_ERR("No such device found");
370 		return -ENODEV;
371 	}
372 
373 	/* Opening SIP SVC session */
374 	ret = svc_client_open(dev);
375 	if (ret) {
376 		LOG_ERR("Client open Failed!");
377 		return ret;
378 	}
379 
380 	/* Check FPGA status before bridge enable/disable */
381 	ret = fpga_config_ready_check(dev);
382 	if (ret) {
383 		LOG_ERR("FPGA not ready. Bridge reset aborted!");
384 		svc_client_close(dev);
385 		return -EIO;
386 	}
387 
388 	/* Bridge reset */
389 	ret = socfpga_bridges_reset(dev, 0x01);
390 	if (ret) {
391 		LOG_ERR("Bridge reset failed");
392 	}
393 
394 	/* Ignoring the return value to return bridge reset status */
395 	if (svc_client_close(dev)) {
396 		LOG_ERR("Unregistering & Closing failed");
397 	}
398 
399 	return ret;
400 }
401 
altera_fpga_off(const struct device * dev)402 static int altera_fpga_off(const struct device *dev)
403 {
404 	int32_t ret = 0;
405 
406 	if (!dev) {
407 		LOG_ERR("No such device found");
408 		return -ENODEV;
409 	}
410 
411 	/* Opening SIP SVC session */
412 	ret = svc_client_open(dev);
413 	if (ret) {
414 		LOG_ERR("Client open Failed!");
415 		return ret;
416 	}
417 
418 	/* Check FPGA status before bridge enable/disable */
419 	ret = fpga_config_ready_check(dev);
420 	if (ret) {
421 		LOG_ERR("FPGA not ready. Bridge reset aborted!");
422 		svc_client_close(dev);
423 		return -EIO;
424 	}
425 
426 	/* Bridge reset */
427 	ret = socfpga_bridges_reset(dev, 0x00);
428 	if (ret) {
429 		LOG_ERR("Bridge reset failed");
430 	}
431 
432 	/* Ignoring the return value to return bridge reset status */
433 	if (svc_client_close(dev)) {
434 		LOG_ERR("Unregistering & Closing failed");
435 	}
436 
437 	return ret;
438 }
439 
altera_fpga_init(const struct device * dev)440 static int altera_fpga_init(const struct device *dev)
441 {
442 	if (!dev) {
443 		LOG_ERR("No such device found");
444 		return -ENODEV;
445 	}
446 
447 	struct fpga_bridge_dev_data *const data = (struct fpga_bridge_dev_data *const)(dev->data);
448 
449 	data->mailbox_smc_dev = sip_svc_get_controller("smc");
450 	if (!data->mailbox_smc_dev) {
451 		LOG_ERR("Arm SiP service not found");
452 		return -ENODEV;
453 	}
454 
455 	data->mailbox_client_token = sip_svc_register(data->mailbox_smc_dev, NULL);
456 	if (data->mailbox_client_token == SIP_SVC_ID_INVALID) {
457 		data->mailbox_smc_dev = NULL;
458 		LOG_ERR("Mailbox client register fail");
459 		return -EINVAL;
460 	}
461 
462 	return 0;
463 }
464 
465 static const struct fpga_driver_api altera_fpga_api = {
466 	.on = altera_fpga_on,
467 	.off = altera_fpga_off,
468 };
469 
470 #define CREATE_ALTERA_FPGA_BRIDGE_DEV(inst)						\
471 	static struct fpga_bridge_dev_data fpga_bridge_data_##inst;		\
472 	DEVICE_DT_INST_DEFINE(inst,						\
473 			altera_fpga_init,					\
474 			NULL, &fpga_bridge_data_##inst,				\
475 			NULL, POST_KERNEL,			\
476 			CONFIG_FPGA_INIT_PRIORITY,				\
477 			&altera_fpga_api);					\
478 
479 DT_INST_FOREACH_STATUS_OKAY(CREATE_ALTERA_FPGA_BRIDGE_DEV);
480