static int fw_erase_stm(struct spi_device *spi) { struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int ret; char buff[EXT_ER_DATA_LEN] = {0xff, 0xff, 0x00}; ssp_dbgf(); cmd.cmd = EXT_ER_COMMAND; cmd.xor_cmd = XOR_EXT_ER_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = BL_DUMMY; ret = stm32fwu_spi_send_cmd(spi, &cmd); if (ret != BL_ACK) { ssp_err("fw_erase failed - %d", ret); return ret; } ret = stm32fwu_spi_write(spi, buff, EXT_ER_DATA_LEN); if (ret < EXT_ER_DATA_LEN) { ssp_err("fw_erase write failed"); return 0; } dummy_cmd.timeout = DEF_ACK_ERASE_NUMBER; ret = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK); if (ret == BL_ACK) return 0; else if (ret == BL_NACK) return -EPROTO; else return -ETIME; }
static int update_mcu_bin(struct ssp_data *data, int iBinType) { int retry = BLMODE_RETRYCOUNT; int iRet = SUCCESS; struct stm32fwu_spi_cmd cmd; cmd.cmd = GO_COMMAND; cmd.xor_cmd = XOR_GO_COMMAND; cmd.timeout = 1000; cmd.ack_pad = (u8)((STM_APP_ADDR >> 24) & 0xFF); // 1. Start system boot mode do { iRet = change_to_bootmode(data); pr_info("[ssp] bootmode %d retry: %d\n", iRet, 3 - retry); } while (retry-- > 0 && iRet != BL_ACK ); if(iRet != BL_ACK) { pr_err("[SSP]: %s - change_to_bootmode %d\n", __func__, iRet); return iRet; } // 2. Flash erase all iRet = fw_erase_stm(data->spi); if (iRet < 0) { pr_err("[SSP]: %s - fw_erase_stm %d\n", __func__, iRet); return iRet; } switch (iBinType) { case KERNEL_BINARY: /* HW request: I2C line is reversed */ #if defined(CONFIG_SEC_KSPORTS_PROJECT) iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME_TASMAN); #else iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME); #endif break; case KERNEL_CRASHED_BINARY: iRet = load_kernel_fw_bootmode(data->spi, BL_CRASHED_FW_NAME); break; case UMS_BINARY: iRet = load_ums_fw_bootmode(data->spi, BL_UMS_FW_NAME); break; default: pr_err("[SSP] binary type error!!\n"); } /* STM : GO USER ADDR */ stm32fwu_spi_send_cmd(data->spi, &cmd); send_addr(data->spi, STM_APP_ADDR, 0); data->spi->mode = SPI_MODE_1; if (spi_setup(data->spi)) pr_err("failed to setup spi mode for app\n"); usleep_range(1000, 1100); return iRet; }
static int update_mcu_bin(struct ssp_data *data, int iBinType) { int retry = BLMODE_RETRYCOUNT; int iRet = SUCCESS; struct stm32fwu_spi_cmd cmd; cmd.cmd = GO_COMMAND; cmd.xor_cmd = XOR_GO_COMMAND; cmd.timeout = 1000; cmd.ack_pad = (u8)((STM_APP_ADDR >> 24) & 0xFF); do { iRet = change_to_bootmode(data); pr_info("[ssp] bootmode %d retry: %d\n", iRet, 3 - retry); } while (retry-- > 0 && iRet != BL_ACK ); if(iRet != BL_ACK) { pr_err("[SSP]: %s - change_to_bootmode %d\n", __func__, iRet); return iRet; } iRet = fw_erase_stm(data->spi); if (iRet < 0) { pr_err("[SSP]: %s - fw_erase_stm %d\n", __func__, iRet); return iRet; } switch (iBinType) { case KERNEL_BINARY: /* HW request: I2C line is reversed */ iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME); break; case KERNEL_CRASHED_BINARY: iRet = load_kernel_fw_bootmode(data->spi, BL_CRASHED_FW_NAME); break; case UMS_BINARY: iRet = load_ums_fw_bootmode(data->spi, BL_UMS_FW_NAME); break; default: pr_err("[SSP] binary type error!!\n"); } /* STM : GO USER ADDR */ stm32fwu_spi_send_cmd(data->spi, &cmd); if (cmd.ack_loops > 0) send_addr(data->spi, STM_APP_ADDR, 1); else send_addr(data->spi, STM_APP_ADDR, 0); msleep(SSP_SW_RESET_TIME); return iRet; }
static int update_mcu_bin(struct ssp_data *data, int iBinType) { int retry = BLMODE_RETRYCOUNT; int iRet = SUCCESS; struct stm32fwu_spi_cmd cmd; cmd.cmd = GO_COMMAND; cmd.xor_cmd = XOR_GO_COMMAND; cmd.timeout = 1000; cmd.ack_pad = (u8)((STM_APP_ADDR >> 24) & 0xFF); pr_info("[SSP] update_mcu_bin\n"); // 1. Start system boot mode do { iRet = change_to_bootmode(data); pr_info("[SSP] bootmode %d, retry = %d\n", iRet, 3 - retry); } while (retry-- > 0 && iRet != BL_ACK); if(iRet != BL_ACK) { pr_err("[SSP] %s, change_to_bootmode failed %d\n", __func__, iRet); return iRet; } // 2. Flash erase all iRet = fw_erase_stm(data->spi); if (iRet < 0) { pr_err("[SSP] %s, fw_erase_stm failed %d\n", __func__, iRet); return iRet; } pr_info("======[SSP] SCHEDULE!!!!!\n"); schedule(); /*Defence for cpu schedule blocking watchdog*/ msleep(3); switch (iBinType) { case KERNEL_BINARY: /* HW request: I2C line is reversed */ iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME); break; case KERNEL_CRASHED_BINARY: iRet = load_kernel_fw_bootmode(data->spi, BL_CRASHED_FW_NAME); break; case UMS_BINARY: iRet = load_ums_fw_bootmode(data->spi, BL_UMS_FW_NAME); break; default: pr_err("[SSP] binary type error!!\n"); } pr_info("======[SSP] SCHEDULE!!!!!\n"); schedule(); /*Defence for cpu schedule blocking watchdog*/ msleep(3); /* STM : GO USER ADDR */ stm32fwu_spi_send_cmd(data->spi, &cmd); send_addr(data->spi, STM_APP_ADDR, 0); return iRet; }
static int update_mcu_bin(struct ssp_data *data, int iBinType) { int retry = BLMODE_RETRYCOUNT; int iRet = SUCCESS; struct stm32fwu_spi_cmd cmd; cmd.cmd = GO_COMMAND; cmd.xor_cmd = XOR_GO_COMMAND; cmd.timeout = 1000; cmd.ack_pad = (u8)((STM_APP_ADDR >> 24) & 0xFF); /* 1. Start system boot mode */ do { iRet = change_to_bootmode(data); ssp_info("bootmode %d retry: %d", iRet, 3 - retry); } while (retry-- > 0 && iRet != BL_ACK); if (iRet != BL_ACK) { ssp_errf("change_to_bootmode %d", iRet); return iRet; } /* 2. Flash erase all */ iRet = fw_erase_stm(data->spi); if (iRet < 0) { ssp_errf("fw_erase_stm %d", iRet); return iRet; } switch (iBinType) { case KERNEL_BINARY: /* HW request: I2C line is reversed */ iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME); break; case KERNEL_CRASHED_BINARY: iRet = load_kernel_fw_bootmode(data->spi, BL_CRASHED_FW_NAME); break; case UMS_BINARY: iRet = load_ums_fw_bootmode(data->spi, BL_UMS_FW_NAME); break; default: ssp_err("binary type error!!"); } /* STM : GO USER ADDR */ stm32fwu_spi_send_cmd(data->spi, &cmd); send_addr(data->spi, STM_APP_ADDR, 0); data->spi->mode = SPI_MODE_1; if (spi_setup(data->spi)) ssp_err("failed to setup spi mode for app"); usleep_range(1000, 1100); return iRet; }
static int fw_read_stm(struct spi_device *spi, u32 fw_addr, int len, const u8 *buffer) { int res; struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int i; u8 xor = 0; u8 send_buff[STM_MAX_BUFFER_SIZE] = {0,}; cmd.cmd = WMEM_COMMAND; cmd.xor_cmd = XOR_RMEM_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = (u8)((fw_addr >> 24) & 0xFF); res = stm32fwu_spi_send_cmd(spi, &cmd); if (res != BL_ACK) { pr_err("[SSP] Error %d sending read_mem cmd\n", res); return res; } res = send_addr(spi, fw_addr, 0); if (res != 0) { pr_err("[SSP] Error %d sending read_mem Address\n", res); return res; } res = send_byte_count(spi, len, 1); if (res != 0) { return -EPROTO; } // Add Read Syc stm32fwu_spi_send_ack(spi, BL_DUMMY); res = stm32fwu_spi_read(spi, buffer, len); if (res < len) { return -EIO; } return len; }
static int fw_erase_stm(struct spi_device *spi) { struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int ret; char buff[EXT_ER_DATA_LEN] = {0xff, 0xff, 0x00}; pr_debug("[SSP]%s\n", __func__); cmd.cmd = EXT_ER_COMMAND; cmd.xor_cmd = XOR_EXT_ER_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = BL_DUMMY; ret = stm32fwu_spi_send_cmd(spi, &cmd); if (ret < 0 || ret != BL_ACK) { pr_err("[SSP] fw_erase failed\n"); return ret; } ret = stm32fwu_spi_write(spi, buff, EXT_ER_DATA_LEN); if( ret < EXT_ER_DATA_LEN ) { pr_err("[SSP] fw_erase write failed\n"); return 0; } dummy_cmd.timeout = DEF_ACK_ERASE_NUMBER; ret = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK); #if SSP_STM_DEBUG pr_info("[SSP] %s: stm32fwu_spi_wait_for_ack returned %d (0x%x)\n", __func__, ret, ret); #endif if (ret == BL_ACK) return 0; else if (ret == BL_NACK) return -EPROTO; else return -ETIME; }
static int fw_erase_stm(struct spi_device *spi) { struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int ret; char buff[EXT_ER_DATA_LEN] = {0xff, 0xff, 0x00}; cmd.cmd = EXT_ER_COMMAND; cmd.xor_cmd = XOR_EXT_ER_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = 0xFF; ret = stm32fwu_spi_send_cmd(spi, &cmd); if (ret < 0 || ret != BL_ACK) { pr_err("[SSP] fw_erase failed\n"); return ret; } if (cmd.ack_loops == 0) ret = stm32fwu_spi_write(spi, buff, EXT_ER_DATA_LEN); else ret = stm32fwu_spi_write(spi, buff, EXT_ER_DATA_LEN-1); if (ret < (EXT_ER_DATA_LEN - cmd.ack_loops)) { return -EPROTO; } dummy_cmd.timeout = DEF_ACK_ERASE_NUMBER; ret = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK); if (ret == BL_ACK) return 0; else if (ret == BL_NACK) return -EPROTO; else return -ETIME; }
static int fw_write_stm(struct spi_device *spi, u32 fw_addr, int len, const u8 *buffer) { int res; struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int i; u8 xor = 0; u8 send_buff[STM_MAX_BUFFER_SIZE] = {0,}; cmd.cmd = WMEM_COMMAND; cmd.xor_cmd = XOR_WMEM_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = (u8)((fw_addr >> 24) & 0xFF); pr_debug("[SSP]%s\n", __func__); #if SSP_STM_DEBUG pr_info("[SSP] sending WMEM_COMMAND\n"); #endif if (len > STM_MAX_XFER_SIZE) { pr_err("[SSP] Can't send more than 256 bytes per transaction\n"); return -EINVAL; } send_buff[0] = len - 1; memcpy(&send_buff[1], buffer, len); for (i = 0; i < (len + 1); i++) xor ^= send_buff[i]; send_buff[len + 1] = xor; res = stm32fwu_spi_send_cmd(spi, &cmd); if (res != BL_ACK) { pr_err("[SSP] Error %d sending read_mem cmd\n", res); return res; } res = send_addr(spi, fw_addr, 0); if (res != 0) { pr_err("[SSP] Error %d sending write_mem Address\n", res); return res; } res = stm32fwu_spi_write(spi, send_buff, len + 2); if (res < len) { pr_err("[SSP] Error writing to flash. res = %d\n", res); return ((res > 0) ? -EIO : res); } pr_debug("[SSP]%s 2\n", __func__); dummy_cmd.timeout = DEF_ACKROOF_NUMBER; usleep_range(100, 150); /* Samsung added */ res = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK); if (res == BL_ACK) { return len; } if (res == BL_NACK) { pr_err("[SSP] Got NAK waiting for WRITE_MEM to complete\n"); return -EPROTO; } pr_err("[SSP] timeout waiting for ACK for WRITE_MEM command\n"); return -ETIME; }