static int tps25751_download_patch_bundle(const msdk_device_t *dev, const uint8_t *patch_data, size_t patch_size) { int ret; uint8_t buf[64] = {0}; int retry = 10; // Retry up to 10 times // Step 1: Check ReadyForPatch bit (INT_EVENT1, Reg 0x14, Byte 11, Bit 1 = 0x02) while (retry--) { memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x14, buf, 12); if (ret != MSDK_STATUS__OK) { MSDK_LOG_ERR("Failed to read INT_EVENT1"); return MSDK_STATUS__ERROR; } if ((buf[11] & 0x02) != 0) { MSDK_LOG_DBG("INT_EVENT1 ReadyForPatch bit is ready for patching."); break; } msdk_time_delay_ms(10); // Delay 10ms between reads } MSDK_LOG_DBG("Step 1: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); // Step 2: Check current mode == 'PTCH' retry = 10; while (retry--) { memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x03, buf, 5); if (ret != MSDK_STATUS__OK) { MSDK_LOG_ERR("Failed to read PTCH mode"); return MSDK_STATUS__ERROR; } if (strncmp((char *)&buf[1], "PTCH", 4) == 0) { MSDK_LOG_DBG("PD controller is ready for patching."); break; } msdk_time_delay_ms(10); // Delay 10ms between reads } MSDK_LOG_DBG("Step 2: %02X %02X %02X %02X %02X ", buf[0], buf[1], buf[2], buf[3], buf[4]); // Step 3: Write DATA1 = [size_LSB...MSB][target][timeout] memset(buf, 0, sizeof(buf)); buf[0] = 0x06; buf[1] = (uint8_t)(patch_size & 0xFF); buf[2] = (uint8_t)((patch_size >> 8) & 0xFF); buf[3] = (uint8_t)((patch_size >> 16) & 0xFF); buf[4] = (uint8_t)((patch_size >> 24) & 0xFF); buf[5] = 0x35; // Patch I2C target address buf[6] = 0x32; // Timeout = 5s = 0x32 * 100ms ret = write_reg(dev, 0x09, buf, 7); if (ret != MSDK_STATUS__OK) return ret; MSDK_LOG_DBG(" Step 3: %02X %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); // Step 4: Write CMD1 = 'PBMs' uint8_t pbms_cmd[5] = {0x04, 'P', 'B', 'M', 's'}; ret = write_reg(dev, 0x08, pbms_cmd, 5); if (ret != MSDK_STATUS__OK) return ret; MSDK_LOG_DBG("Step 4: %02X %02X %02X %02X %02X", pbms_cmd[0], pbms_cmd[1], pbms_cmd[2], pbms_cmd[3], pbms_cmd[4]); // Step 5: Poll CMD1 (0x08) until cleared memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x08, buf, 5); if (ret != MSDK_STATUS__OK) return ret; MSDK_LOG_DBG("Step 5: %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); // Step 6: Check if DATA1 status is 0 memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x09, buf, 5); MSDK_LOG_DBG("Step 6: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],buf[16], buf[17]); if (ret != MSDK_STATUS__OK) return ret; // Step 7: Write Patch Data to I2C addr 0x30 register 0x01 (burst) tps25751_write_patch(&nina_tps25751_device_patch, patch_data, patch_size); msdk_time_delay_ms(1); // Step 8: Write CMD1 = 'PBMc' to complete uint8_t pbmc_cmd[5] = {0x04, 'P', 'B', 'M', 'c'}; ret = write_reg(dev, 0x08, pbmc_cmd, 5); if (ret != MSDK_STATUS__OK) return ret; MSDK_LOG_DBG("Step 8: %02X %02X %02X %02X %02X %02X", pbmc_cmd[0], pbmc_cmd[1], pbmc_cmd[2], pbmc_cmd[3], pbmc_cmd[4], pbmc_cmd[5]); // Step 9: Confirm CMD1 is cleared retry = 10; while (retry--) { memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x08, buf, 5); if (ret != MSDK_STATUS__OK) { MSDK_LOG_ERR("Failed to read CMD1 mode"); return MSDK_STATUS__ERROR; } if (buf[1]==0 && buf[2]==0 && buf[3]==0 && buf[4]==0) { MSDK_LOG_DBG("Confirm CMD1 is cleared."); break; } msdk_time_delay_ms(10); // Delay 10ms between reads } MSDK_LOG_DBG(" Step 9 :%02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); msdk_time_delay_ms(20); // Step 10: Confirm DATA1 status is 0 memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x09, buf, 5); if (ret != MSDK_STATUS__OK) return MSDK_STATUS__ERROR; MSDK_LOG_DBG("Step 10: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],buf[16], buf[17]); MSDK_LOG_DBG("Step 10: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31], buf[32], buf[33],buf[34], buf[35]); MSDK_LOG_DBG("Step 10 :%02X %02X %02X %02X", buf[36], buf[37], buf[38], buf[39]); // Step 11: Read Interrupt Event for I2C1 (Offset = 0x14), check bit[80] memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x14, buf, 6); if (ret != MSDK_STATUS__OK) return MSDK_STATUS__ERROR; MSDK_LOG_DBG("Step 11: %02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); msdk_time_delay_ms(10); /*uint8_t pbme_cmd[5] = {0x04, 'P', 'B', 'M', 'e'}; ret = write_reg(dev, 0x08, pbme_cmd, 5); if (ret != MSDK_STATUS__OK) return ret; MSDK_LOG_DBG("Step 11: %02X %02X %02X %02X %02X %02X", pbme_cmd[0], pbme_cmd[1], pbme_cmd[2], pbme_cmd[3], pbme_cmd[4], pbme_cmd[5]); */ msdk_time_delay_ms(10); // Step 12: Check Mode = 'APP ' memset(buf, 0, sizeof(buf)); ret = read_reg(dev, 0x03, buf, 6); if (ret != MSDK_STATUS__OK || strncmp((char *)&buf[1], "APP ", 4) != 0) { MSDK_LOG_DBG("Step 12:%02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); MSDK_LOG_ERR("Patch success but still not in APP mode, got: %.4s", &buf[1]); return MSDK_STATUS__ERROR; } MSDK_LOG_DBG("Step 12:%02X %02X %02X %02X %02X %02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); MSDK_LOG_INF("TPS25751 patch bundle loaded successfully, device is in APP mode"); return MSDK_STATUS__OK; }