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 */
13static 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 */
39static 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 */
60static 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
88ipc_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 */
98int 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
119devlink_read_fail:
120	ipc_imem_sys_devlink_close(ipc_imem->ipc_devlink);
121chl_open_fail:
122	return -EIO;
123}
124
125/* Receive data from the modem */
126static 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
161ipc_flash_recv_err:
162	return ret;
163}
164
165/* Function to send command to modem and receive response */
166static 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
183ipc_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 */
194int 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 */
223int 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);
260ipc_swid_err:
261	return ret;
262}
263
264/* Function to check if full erase or conditional erase was successful */
265static 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
298ipc_erase_chk_err:
299	return ret;
300}
301
302/* Full erase function which will erase the nand flash through EBL command */
303static 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
325ipc_flash_erase_err:
326	return ret;
327}
328
329/* Logic for flashing all the Loadmaps available for individual fls file */
330static 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
387dl_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 */
399int 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
438ipc_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 */
449int 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
494ipc_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 */
506int 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
592ipc_flash_ebl_err:
593	return ret;
594}
595