iosm_ipc_flash.c (16066B)
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}