xref: /linux/drivers/net/wwan/iosm/iosm_ipc_flash.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2020-2021 Intel Corporation.
4  */
5 
6 #include "iosm_ipc_coredump.h"
7 #include "iosm_ipc_devlink.h"
8 #include "iosm_ipc_flash.h"
9 
10 /* This function will pack the data to be sent to the modem using the
11  * payload, payload length and pack id
12  */
ipc_flash_proc_format_ebl_pack(struct iosm_flash_data * flash_req,u32 pack_length,u16 pack_id,u8 * payload,u32 payload_length)13 static int ipc_flash_proc_format_ebl_pack(struct iosm_flash_data *flash_req,
14 					  u32 pack_length, u16 pack_id,
15 					  u8 *payload, u32 payload_length)
16 {
17 	u16 checksum = pack_id;
18 	u32 i;
19 
20 	if (payload_length + IOSM_EBL_HEAD_SIZE > pack_length)
21 		return -EINVAL;
22 
23 	flash_req->pack_id = cpu_to_le16(pack_id);
24 	flash_req->msg_length = cpu_to_le32(payload_length);
25 	checksum += (payload_length >> IOSM_EBL_PAYL_SHIFT) +
26 		     (payload_length & IOSM_EBL_CKSM);
27 
28 	for (i = 0; i < payload_length; i++)
29 		checksum += payload[i];
30 
31 	flash_req->checksum = cpu_to_le16(checksum);
32 
33 	return 0;
34 }
35 
36 /* validate the response received from modem and
37  * check the type of errors received
38  */
ipc_flash_proc_check_ebl_rsp(void * hdr_rsp,void * payload_rsp)39 static int ipc_flash_proc_check_ebl_rsp(void *hdr_rsp, void *payload_rsp)
40 {
41 	struct iosm_ebl_error  *err_info = payload_rsp;
42 	u16 *rsp_code = hdr_rsp;
43 	u32 i;
44 
45 	if (*rsp_code == IOSM_EBL_RSP_BUFF) {
46 		for (i = 0; i < IOSM_MAX_ERRORS; i++) {
47 			if (!err_info->error[i].error_code) {
48 				pr_err("EBL: error_class = %d, error_code = %d",
49 				       err_info->error[i].error_class,
50 				       err_info->error[i].error_code);
51 			}
52 		}
53 		return -EINVAL;
54 	}
55 
56 	return 0;
57 }
58 
59 /* Send data to the modem */
ipc_flash_send_data(struct iosm_devlink * ipc_devlink,u32 size,u16 pack_id,u8 * payload,u32 payload_length)60 static int ipc_flash_send_data(struct iosm_devlink *ipc_devlink, u32 size,
61 			       u16 pack_id, u8 *payload, u32 payload_length)
62 {
63 	struct iosm_flash_data flash_req;
64 	int ret;
65 
66 	ret = ipc_flash_proc_format_ebl_pack(&flash_req, size,
67 					     pack_id, payload, payload_length);
68 	if (ret) {
69 		dev_err(ipc_devlink->dev, "EBL2 pack failed for pack_id:%d",
70 			pack_id);
71 		goto ipc_free_payload;
72 	}
73 
74 	ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&flash_req,
75 					 IOSM_EBL_HEAD_SIZE);
76 	if (ret) {
77 		dev_err(ipc_devlink->dev, "EBL Header write failed for Id:%x",
78 			pack_id);
79 		goto ipc_free_payload;
80 	}
81 
82 	ret = ipc_imem_sys_devlink_write(ipc_devlink, payload, payload_length);
83 	if (ret) {
84 		dev_err(ipc_devlink->dev, "EBL Payload write failed for Id:%x",
85 			pack_id);
86 	}
87 
88 ipc_free_payload:
89 	return ret;
90 }
91 
92 /**
93  * ipc_flash_link_establish - Flash link establishment
94  * @ipc_imem:           Pointer to struct iosm_imem
95  *
96  * Returns:     0 on success and failure value on error
97  */
ipc_flash_link_establish(struct iosm_imem * ipc_imem)98 int ipc_flash_link_establish(struct iosm_imem *ipc_imem)
99 {
100 	u8 ler_data[IOSM_LER_RSP_SIZE];
101 	u32 bytes_read;
102 
103 	/* Allocate channel for flashing/cd collection */
104 	ipc_imem->ipc_devlink->devlink_sio.channel =
105 					ipc_imem_sys_devlink_open(ipc_imem);
106 
107 	if (!ipc_imem->ipc_devlink->devlink_sio.channel)
108 		goto chl_open_fail;
109 
110 	if (ipc_imem_sys_devlink_read(ipc_imem->ipc_devlink, ler_data,
111 				      IOSM_LER_RSP_SIZE, &bytes_read))
112 		goto devlink_read_fail;
113 
114 	if (bytes_read != IOSM_LER_RSP_SIZE)
115 		goto devlink_read_fail;
116 
117 	return 0;
118 
119 devlink_read_fail:
120 	ipc_imem_sys_devlink_close(ipc_imem->ipc_devlink);
121 chl_open_fail:
122 	return -EIO;
123 }
124 
125 /* Receive data from the modem */
ipc_flash_receive_data(struct iosm_devlink * ipc_devlink,u32 size,u8 * mdm_rsp)126 static int ipc_flash_receive_data(struct iosm_devlink *ipc_devlink, u32 size,
127 				  u8 *mdm_rsp)
128 {
129 	u8 mdm_rsp_hdr[IOSM_EBL_HEAD_SIZE];
130 	u32 bytes_read;
131 	int ret;
132 
133 	ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp_hdr,
134 					IOSM_EBL_HEAD_SIZE, &bytes_read);
135 	if (ret) {
136 		dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed",
137 			IOSM_EBL_HEAD_SIZE);
138 		goto ipc_flash_recv_err;
139 	}
140 
141 	if (bytes_read != IOSM_EBL_HEAD_SIZE) {
142 		ret = -EINVAL;
143 		goto ipc_flash_recv_err;
144 	}
145 
146 	ret = ipc_imem_sys_devlink_read(ipc_devlink, mdm_rsp, size,
147 					&bytes_read);
148 	if (ret) {
149 		dev_err(ipc_devlink->dev, "EBL rsp to read %d bytes failed",
150 			size);
151 		goto ipc_flash_recv_err;
152 	}
153 
154 	if (bytes_read != size) {
155 		ret = -EINVAL;
156 		goto ipc_flash_recv_err;
157 	}
158 
159 	ret = ipc_flash_proc_check_ebl_rsp(mdm_rsp_hdr + 2, mdm_rsp);
160 
161 ipc_flash_recv_err:
162 	return ret;
163 }
164 
165 /* Function to send command to modem and receive response */
ipc_flash_send_receive(struct iosm_devlink * ipc_devlink,u16 pack_id,u8 * payload,u32 payload_length,u8 * mdm_rsp)166 static int ipc_flash_send_receive(struct iosm_devlink *ipc_devlink, u16 pack_id,
167 				  u8 *payload, u32 payload_length, u8 *mdm_rsp)
168 {
169 	size_t frame_len = IOSM_EBL_DW_PACK_SIZE;
170 	int ret;
171 
172 	if (pack_id == FLASH_SET_PROT_CONF)
173 		frame_len = IOSM_EBL_W_PACK_SIZE;
174 
175 	ret = ipc_flash_send_data(ipc_devlink, frame_len, pack_id, payload,
176 				  payload_length);
177 	if (ret)
178 		goto ipc_flash_send_rcv;
179 
180 	ret = ipc_flash_receive_data(ipc_devlink,
181 				     frame_len - IOSM_EBL_HEAD_SIZE, mdm_rsp);
182 
183 ipc_flash_send_rcv:
184 	return ret;
185 }
186 
187 /**
188  * ipc_flash_boot_set_capabilities  - Set modem boot capabilities in flash
189  * @ipc_devlink:        Pointer to devlink structure
190  * @mdm_rsp:            Pointer to modem response buffer
191  *
192  * Returns:             0 on success and failure value on error
193  */
ipc_flash_boot_set_capabilities(struct iosm_devlink * ipc_devlink,u8 * mdm_rsp)194 int ipc_flash_boot_set_capabilities(struct iosm_devlink *ipc_devlink,
195 				    u8 *mdm_rsp)
196 {
197 	ipc_devlink->ebl_ctx.ebl_sw_info_version =
198 			ipc_devlink->ebl_ctx.m_ebl_resp[EBL_RSP_SW_INFO_VER];
199 	ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_ERASE] = IOSM_CAP_NOT_ENHANCED;
200 	ipc_devlink->ebl_ctx.m_ebl_resp[EBL_SKIP_CRC] = IOSM_CAP_NOT_ENHANCED;
201 
202 	if (ipc_devlink->ebl_ctx.m_ebl_resp[EBL_CAPS_FLAG] &
203 							IOSM_CAP_USE_EXT_CAP) {
204 		if (ipc_devlink->param.erase_full_flash)
205 			ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &=
206 				~((u8)IOSM_EXT_CAP_ERASE_ALL);
207 		else
208 			ipc_devlink->ebl_ctx.m_ebl_resp[EBL_OOS_CONFIG] &=
209 				~((u8)IOSM_EXT_CAP_COMMIT_ALL);
210 		ipc_devlink->ebl_ctx.m_ebl_resp[EBL_EXT_CAPS_HANDLED] =
211 				IOSM_CAP_USE_EXT_CAP;
212 	}
213 
214 	/* Write back the EBL capability to modem
215 	 * Request Set Protcnf command
216 	 */
217 	return ipc_flash_send_receive(ipc_devlink, FLASH_SET_PROT_CONF,
218 				     ipc_devlink->ebl_ctx.m_ebl_resp,
219 				     IOSM_EBL_RSP_SIZE, mdm_rsp);
220 }
221 
222 /* Read the SWID type and SWID value from the EBL */
ipc_flash_read_swid(struct iosm_devlink * ipc_devlink,u8 * mdm_rsp)223 int ipc_flash_read_swid(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
224 {
225 	struct iosm_flash_msg_control cmd_msg;
226 	struct iosm_swid_table *swid;
227 	char ebl_swid[IOSM_SWID_STR];
228 	int ret;
229 
230 	if (ipc_devlink->ebl_ctx.ebl_sw_info_version !=
231 			IOSM_EXT_CAP_SWID_OOS_PACK)
232 		return -EINVAL;
233 
234 	cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_READ);
235 	cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_SWID_TABLE);
236 	cmd_msg.length = cpu_to_le32(IOSM_MSG_LEN_ARG);
237 	cmd_msg.arguments = cpu_to_le32(IOSM_MSG_LEN_ARG);
238 
239 	ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL,
240 				     (u8 *)&cmd_msg, IOSM_MDM_SEND_16, mdm_rsp);
241 	if (ret)
242 		goto ipc_swid_err;
243 
244 	cmd_msg.action = cpu_to_le32(*((u32 *)mdm_rsp));
245 
246 	ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_DATA_READ,
247 				     (u8 *)&cmd_msg, IOSM_MDM_SEND_4, mdm_rsp);
248 	if (ret)
249 		goto ipc_swid_err;
250 
251 	swid = (struct iosm_swid_table *)mdm_rsp;
252 	dev_dbg(ipc_devlink->dev, "SWID %x RF_ENGINE_ID %x", swid->sw_id_val,
253 		swid->rf_engine_id_val);
254 
255 	snprintf(ebl_swid, sizeof(ebl_swid), "SWID: %x, RF_ENGINE_ID: %x",
256 		 swid->sw_id_val, swid->rf_engine_id_val);
257 
258 	devlink_flash_update_status_notify(ipc_devlink->devlink_ctx, ebl_swid,
259 					   NULL, 0, 0);
260 ipc_swid_err:
261 	return ret;
262 }
263 
264 /* Function to check if full erase or conditional erase was successful */
ipc_flash_erase_check(struct iosm_devlink * ipc_devlink,u8 * mdm_rsp)265 static int ipc_flash_erase_check(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
266 {
267 	int ret, count = 0;
268 	u16 mdm_rsp_data;
269 
270 	/* Request Flash Erase Check */
271 	do {
272 		mdm_rsp_data = IOSM_MDM_SEND_DATA;
273 		ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_CHECK,
274 					     (u8 *)&mdm_rsp_data,
275 					     IOSM_MDM_SEND_2, mdm_rsp);
276 		if (ret)
277 			goto ipc_erase_chk_err;
278 
279 		mdm_rsp_data = *((u16 *)mdm_rsp);
280 		if (mdm_rsp_data > IOSM_MDM_ERASE_RSP) {
281 			dev_err(ipc_devlink->dev,
282 				"Flash Erase Check resp wrong 0x%04X",
283 				mdm_rsp_data);
284 			ret = -EINVAL;
285 			goto ipc_erase_chk_err;
286 		}
287 		count++;
288 		msleep(IOSM_FLASH_ERASE_CHECK_INTERVAL);
289 	} while ((mdm_rsp_data != IOSM_MDM_ERASE_RSP) &&
290 		(count < (IOSM_FLASH_ERASE_CHECK_TIMEOUT /
291 		IOSM_FLASH_ERASE_CHECK_INTERVAL)));
292 
293 	if (mdm_rsp_data != IOSM_MDM_ERASE_RSP) {
294 		dev_err(ipc_devlink->dev, "Modem erase check timeout failure!");
295 		ret = -ETIMEDOUT;
296 	}
297 
298 ipc_erase_chk_err:
299 	return ret;
300 }
301 
302 /* Full erase function which will erase the nand flash through EBL command */
ipc_flash_full_erase(struct iosm_devlink * ipc_devlink,u8 * mdm_rsp)303 static int ipc_flash_full_erase(struct iosm_devlink *ipc_devlink, u8 *mdm_rsp)
304 {
305 	u32 erase_address = IOSM_ERASE_START_ADDR;
306 	struct iosm_flash_msg_control cmd_msg;
307 	u32 erase_length = IOSM_ERASE_LEN;
308 	int ret;
309 
310 	dev_dbg(ipc_devlink->dev, "Erase full nand flash");
311 	cmd_msg.action = cpu_to_le32(FLASH_OOSC_ACTION_ERASE);
312 	cmd_msg.type = cpu_to_le32(FLASH_OOSC_TYPE_ALL_FLASH);
313 	cmd_msg.length = cpu_to_le32(erase_length);
314 	cmd_msg.arguments = cpu_to_le32(erase_address);
315 
316 	ret = ipc_flash_send_receive(ipc_devlink, FLASH_OOS_CONTROL,
317 				     (unsigned char *)&cmd_msg,
318 				     IOSM_MDM_SEND_16, mdm_rsp);
319 	if (ret)
320 		goto ipc_flash_erase_err;
321 
322 	ipc_devlink->param.erase_full_flash_done = IOSM_SET_FLAG;
323 	ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp);
324 
325 ipc_flash_erase_err:
326 	return ret;
327 }
328 
329 /* Logic for flashing all the Loadmaps available for individual fls file */
ipc_flash_download_region(struct iosm_devlink * ipc_devlink,const struct firmware * fw,u8 * mdm_rsp)330 static int ipc_flash_download_region(struct iosm_devlink *ipc_devlink,
331 				     const struct firmware *fw, u8 *mdm_rsp)
332 {
333 	u32 raw_len, rest_len = fw->size - IOSM_DEVLINK_HDR_SIZE;
334 	struct iosm_devlink_image *fls_data;
335 	__le32 reg_info[2]; /* 0th position region address, 1st position size */
336 	u32 nand_address;
337 	char *file_ptr;
338 	int ret;
339 
340 	fls_data = (struct iosm_devlink_image *)fw->data;
341 	file_ptr = (void *)(fls_data + 1);
342 	nand_address = le32_to_cpu(fls_data->region_address);
343 	reg_info[0] = cpu_to_le32(nand_address);
344 
345 	if (!ipc_devlink->param.erase_full_flash_done) {
346 		reg_info[1] = cpu_to_le32(nand_address + rest_len - 2);
347 		ret = ipc_flash_send_receive(ipc_devlink, FLASH_ERASE_START,
348 					     (u8 *)reg_info, IOSM_MDM_SEND_8,
349 					     mdm_rsp);
350 		if (ret)
351 			goto dl_region_fail;
352 
353 		ret = ipc_flash_erase_check(ipc_devlink, mdm_rsp);
354 		if (ret)
355 			goto dl_region_fail;
356 	}
357 
358 	/* Request Flash Set Address */
359 	ret = ipc_flash_send_receive(ipc_devlink, FLASH_SET_ADDRESS,
360 				     (u8 *)reg_info, IOSM_MDM_SEND_4, mdm_rsp);
361 	if (ret)
362 		goto dl_region_fail;
363 
364 	/* Request Flash Write Raw Image */
365 	ret = ipc_flash_send_data(ipc_devlink, IOSM_EBL_DW_PACK_SIZE,
366 				  FLASH_WRITE_IMAGE_RAW, (u8 *)&rest_len,
367 				  IOSM_MDM_SEND_4);
368 	if (ret)
369 		goto dl_region_fail;
370 
371 	do {
372 		raw_len = (rest_len > IOSM_FLS_BUF_SIZE) ? IOSM_FLS_BUF_SIZE :
373 				rest_len;
374 		ret = ipc_imem_sys_devlink_write(ipc_devlink, file_ptr,
375 						 raw_len);
376 		if (ret) {
377 			dev_err(ipc_devlink->dev, "Image write failed");
378 			goto dl_region_fail;
379 		}
380 		file_ptr += raw_len;
381 		rest_len -= raw_len;
382 	} while (rest_len);
383 
384 	ret = ipc_flash_receive_data(ipc_devlink, IOSM_EBL_DW_PAYL_SIZE,
385 				     mdm_rsp);
386 
387 dl_region_fail:
388 	return ret;
389 }
390 
391 /**
392  * ipc_flash_send_fls  - Inject Modem subsystem fls file to device
393  * @ipc_devlink:        Pointer to devlink structure
394  * @fw:                 FW image
395  * @mdm_rsp:            Pointer to modem response buffer
396  *
397  * Returns:             0 on success and failure value on error
398  */
ipc_flash_send_fls(struct iosm_devlink * ipc_devlink,const struct firmware * fw,u8 * mdm_rsp)399 int ipc_flash_send_fls(struct iosm_devlink *ipc_devlink,
400 		       const struct firmware *fw, u8 *mdm_rsp)
401 {
402 	u32 fw_size = fw->size - IOSM_DEVLINK_HDR_SIZE;
403 	struct iosm_devlink_image *fls_data;
404 	u16 flash_cmd;
405 	int ret;
406 
407 	fls_data = (struct iosm_devlink_image *)fw->data;
408 	if (ipc_devlink->param.erase_full_flash) {
409 		ipc_devlink->param.erase_full_flash = false;
410 		ret = ipc_flash_full_erase(ipc_devlink, mdm_rsp);
411 		if (ret)
412 			goto ipc_flash_err;
413 	}
414 
415 	/* Request Sec Start */
416 	if (!fls_data->download_region) {
417 		ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_START,
418 					     (u8 *)fw->data +
419 					     IOSM_DEVLINK_HDR_SIZE, fw_size,
420 					     mdm_rsp);
421 		if (ret)
422 			goto ipc_flash_err;
423 	} else {
424 		/* Download regions */
425 		ret = ipc_flash_download_region(ipc_devlink, fw, mdm_rsp);
426 		if (ret)
427 			goto ipc_flash_err;
428 
429 		if (fls_data->last_region) {
430 			/* Request Sec End */
431 			flash_cmd = IOSM_MDM_SEND_DATA;
432 			ret = ipc_flash_send_receive(ipc_devlink, FLASH_SEC_END,
433 						     (u8 *)&flash_cmd,
434 						     IOSM_MDM_SEND_2, mdm_rsp);
435 		}
436 	}
437 
438 ipc_flash_err:
439 	return ret;
440 }
441 
442 /**
443  * ipc_flash_boot_psi - Inject PSI image
444  * @ipc_devlink:        Pointer to devlink structure
445  * @fw:                 FW image
446  *
447  * Returns:             0 on success and failure value on error
448  */
ipc_flash_boot_psi(struct iosm_devlink * ipc_devlink,const struct firmware * fw)449 int ipc_flash_boot_psi(struct iosm_devlink *ipc_devlink,
450 		       const struct firmware *fw)
451 {
452 	u32 bytes_read, psi_size = fw->size - IOSM_DEVLINK_HDR_SIZE;
453 	u8 psi_ack_byte[IOSM_PSI_ACK], read_data[2];
454 	u8 *psi_code;
455 	int ret;
456 
457 	dev_dbg(ipc_devlink->dev, "Boot transfer PSI");
458 	psi_code = kmemdup(fw->data + IOSM_DEVLINK_HDR_SIZE, psi_size,
459 			   GFP_KERNEL);
460 	if (!psi_code)
461 		return -ENOMEM;
462 
463 	ret = ipc_imem_sys_devlink_write(ipc_devlink, psi_code, psi_size);
464 	if (ret) {
465 		dev_err(ipc_devlink->dev, "RPSI Image write failed");
466 		goto ipc_flash_psi_free;
467 	}
468 
469 	ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data,
470 					IOSM_LER_ACK_SIZE, &bytes_read);
471 	if (ret) {
472 		dev_err(ipc_devlink->dev, "ipc_devlink_sio_read ACK failed");
473 		goto ipc_flash_psi_free;
474 	}
475 
476 	if (bytes_read != IOSM_LER_ACK_SIZE) {
477 		ret = -EINVAL;
478 		goto ipc_flash_psi_free;
479 	}
480 
481 	snprintf(psi_ack_byte, sizeof(psi_ack_byte), "%x%x", read_data[0],
482 		 read_data[1]);
483 	devlink_flash_update_status_notify(ipc_devlink->devlink_ctx,
484 					   psi_ack_byte, "PSI ACK", 0, 0);
485 
486 	if (read_data[0] == 0x00 && read_data[1] == 0xCD) {
487 		dev_dbg(ipc_devlink->dev, "Coredump detected");
488 		ret = ipc_coredump_get_list(ipc_devlink,
489 					    rpsi_cmd_coredump_start);
490 		if (ret)
491 			dev_err(ipc_devlink->dev, "Failed to get cd list");
492 	}
493 
494 ipc_flash_psi_free:
495 	kfree(psi_code);
496 	return ret;
497 }
498 
499 /**
500  * ipc_flash_boot_ebl  - Inject EBL image
501  * @ipc_devlink:        Pointer to devlink structure
502  * @fw:                 FW image
503  *
504  * Returns:             0 on success and failure value on error
505  */
ipc_flash_boot_ebl(struct iosm_devlink * ipc_devlink,const struct firmware * fw)506 int ipc_flash_boot_ebl(struct iosm_devlink *ipc_devlink,
507 		       const struct firmware *fw)
508 {
509 	u32 ebl_size = fw->size - IOSM_DEVLINK_HDR_SIZE;
510 	u8 read_data[2];
511 	u32 bytes_read;
512 	int ret;
513 
514 	if (ipc_mmio_get_exec_stage(ipc_devlink->pcie->imem->mmio) !=
515 				    IPC_MEM_EXEC_STAGE_PSI) {
516 		devlink_flash_update_status_notify(ipc_devlink->devlink_ctx,
517 						   "Invalid execution stage",
518 						   NULL, 0, 0);
519 		return -EINVAL;
520 	}
521 
522 	dev_dbg(ipc_devlink->dev, "Boot transfer EBL");
523 	ret = ipc_devlink_send_cmd(ipc_devlink, rpsi_cmd_code_ebl,
524 				   IOSM_RPSI_LOAD_SIZE);
525 	if (ret) {
526 		dev_err(ipc_devlink->dev, "Sending rpsi_cmd_code_ebl failed");
527 		goto ipc_flash_ebl_err;
528 	}
529 
530 	ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
531 					&bytes_read);
532 	if (ret) {
533 		dev_err(ipc_devlink->dev, "rpsi_cmd_code_ebl read failed");
534 		goto ipc_flash_ebl_err;
535 	}
536 
537 	if (bytes_read != IOSM_READ_SIZE) {
538 		ret = -EINVAL;
539 		goto ipc_flash_ebl_err;
540 	}
541 
542 	ret = ipc_imem_sys_devlink_write(ipc_devlink, (u8 *)&ebl_size,
543 					 sizeof(ebl_size));
544 	if (ret) {
545 		dev_err(ipc_devlink->dev, "EBL length write failed");
546 		goto ipc_flash_ebl_err;
547 	}
548 
549 	ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
550 					&bytes_read);
551 	if (ret) {
552 		dev_err(ipc_devlink->dev, "EBL read failed");
553 		goto ipc_flash_ebl_err;
554 	}
555 
556 	if (bytes_read != IOSM_READ_SIZE) {
557 		ret = -EINVAL;
558 		goto ipc_flash_ebl_err;
559 	}
560 
561 	ret = ipc_imem_sys_devlink_write(ipc_devlink,
562 					 (u8 *)fw->data + IOSM_DEVLINK_HDR_SIZE,
563 					 ebl_size);
564 	if (ret) {
565 		dev_err(ipc_devlink->dev, "EBL data transfer failed");
566 		goto ipc_flash_ebl_err;
567 	}
568 
569 	ret = ipc_imem_sys_devlink_read(ipc_devlink, read_data, IOSM_READ_SIZE,
570 					&bytes_read);
571 	if (ret) {
572 		dev_err(ipc_devlink->dev, "EBL read failed");
573 		goto ipc_flash_ebl_err;
574 	}
575 
576 	if (bytes_read != IOSM_READ_SIZE) {
577 		ret = -EINVAL;
578 		goto ipc_flash_ebl_err;
579 	}
580 
581 	ret = ipc_imem_sys_devlink_read(ipc_devlink,
582 					ipc_devlink->ebl_ctx.m_ebl_resp,
583 					IOSM_EBL_RSP_SIZE, &bytes_read);
584 	if (ret) {
585 		dev_err(ipc_devlink->dev, "EBL response read failed");
586 		goto ipc_flash_ebl_err;
587 	}
588 
589 	if (bytes_read != IOSM_EBL_RSP_SIZE)
590 		ret = -EINVAL;
591 
592 ipc_flash_ebl_err:
593 	return ret;
594 }
595