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 stm32fwu_spi_wait_for_ack(struct spi_device *spi,
				     struct stm32fwu_spi_cmd *cmd, u8 dummy_bytes)
{
	static int check_spi_wait_cnt = 1;

	struct spi_message m;
	char tx_buf = 0x0;
	char rx_buf = 0x0;
	struct spi_transfer	t = {
		.tx_buf		= &tx_buf,
		.rx_buf		= &rx_buf,
		.len		= 1,
		.bits_per_word = 8,
	};
	int i = 0;
	int ret;
	dummy_bytes = BL_DUMMY;
#if SSP_STM_DEBUG
	pr_info("[SSP] %s: dummy byte = 0x%02hhx\n",
		__func__, dummy_bytes);
#endif
	while (i < cmd->timeout) {
		tx_buf = dummy_bytes;
		spi_message_init(&m);
		spi_message_add_tail(&t, &m);

		ret = spi_sync(spi, &m);

		if (ret < 0) {
			dev_err(&spi->dev, "%s: spi error %d\n", __func__, ret);
			return ret;
		} else if ((rx_buf == BL_ACK) || (rx_buf == BL_NACK)) {
			// ACK cmd set
			stm32fwu_spi_send_ack(spi, BL_ACK);
			return (int)rx_buf;
		} else {
			// Cross cmd set
			tx_buf = rx_buf;
		}
		if (check_spi_wait_cnt % 20 == 0)
			msleep(1);
		else
			usleep_range(1000, 1100);
		i++;
		check_spi_wait_cnt++;
	}
#if SSP_STM_DEBUG
	dev_err(&spi->dev, "%s: Timeout after %d loops\n", __func__, cmd->timeout);
#endif
	return -EIO;
}

static int stm32fwu_spi_send_cmd(struct spi_device *spi,
				 struct stm32fwu_spi_cmd *cmd)
{
	u8 tx_buf[3] = {0,};
	u8 rx_buf[3] = {0,};
	u8 dummy_byte = 0;
	struct spi_message m;
	int ret;
#if BYTETOBYTE_USED
	int i;
	struct spi_transfer t[STM_MAX_BUFFER_SIZE];
	memset(t, 0, STM_MAX_BUFFER_SIZE * sizeof(struct spi_transfer));
#else
	struct spi_transfer	t = {
		.tx_buf		= tx_buf,
		.rx_buf		= rx_buf,
		.len		= 3,
		.bits_per_word = 8,
	};
#endif
	pr_debug("[SSP]%s\n", __func__);

	spi_message_init(&m);
	tx_buf[0] = BL_SPI_SOF;
	tx_buf[1] = cmd->cmd;
	tx_buf[2] = cmd->xor_cmd;

#if BYTETOBYTE_USED
	for (i = 0; i < 3; i++) {
		t[i].tx_buf = &tx_buf[i];
		t[i].rx_buf = &rx_buf[i];
		t[i].len = 1;
		t[i].bits_per_word = 8;
		t[i].delay_usecs = BYTE_DELAY_WRITE;
		spi_message_add_tail(&t[i], &m);
        }
#else
	spi_message_add_tail(&t, &m);
#endif

	ret = spi_sync(spi, &m);
	if (ret < 0) {
		dev_err(&spi->dev, "%s: spi error %d\n", __func__, ret);
		return ret;
	}

	dummy_byte = cmd->ack_pad;

	/* check for ack/nack and loop until found */
	ret = stm32fwu_spi_wait_for_ack(spi, cmd, dummy_byte);
	cmd->status = ret;

	if (ret != BL_ACK) {
		pr_err("[SSP] %s: Got NAK or Error %d\n", __func__, ret);
		return ret;
	}

	return ret;
}
#if STM_SHOULD_BE_IMPLEMENT
static int stm32fwu_spi_read(struct spi_device *spi,
	u8 *buffer, ssize_t len)
{
	int ret;
	int i;
	u8 tx_buf[STM_MAX_BUFFER_SIZE] = {0,};
	struct spi_message m;
	struct spi_transfer	t[STM_MAX_BUFFER_SIZE];

	memset(t, 0, STM_MAX_BUFFER_SIZE * sizeof(struct spi_transfer));

	spi_message_init(&m);

	for (i = 0; i < len; i++) {
		t[i].tx_buf = tx_buf;
		t[i].rx_buf = &buffer[i];
		t[i].len = 1;
		t[i].bits_per_word = 8;
		t[i].delay_usecs = BYTE_DELAY_READ;
		spi_message_add_tail(&t[i], &m);
	}

	ret = spi_sync(spi, &m);

	if (ret < 0) {
		pr_err("[SSP] Error in %d spi_read()\n", ret);
		return ret;
	}

	return len;
}
static int stm32fwu_spi_wait_for_ack(struct spi_device *spi,
				struct stm32fwu_spi_cmd *cmd, u8 dummy_bytes)
{
	static int check_spi_wait_cnt = 1;

	struct spi_message m;
	char tx_buf = 0x0;
	char rx_buf = 0x0;
	struct spi_transfer	t = {
		.tx_buf		= &tx_buf,
		.rx_buf		= &rx_buf,
		.len		= 1,
		.bits_per_word = 8,
	};
	int i = 0;
	int ret;
	dummy_bytes = BL_DUMMY;
#if SSP_STM_DEBUG
	ssp_infof("dummy byte = 0x%02hhx", dummy_bytes);
#endif
	while (i < cmd->timeout) {
		tx_buf = dummy_bytes;
		spi_message_init(&m);
		spi_message_add_tail(&t, &m);

		ret = spi_sync(spi, &m);

		if (ret < 0) {
			dev_err(&spi->dev, "%s: spi error %d\n", __func__, ret);
			return ret;
		} else if ((rx_buf == BL_ACK) || (rx_buf == BL_NACK)) {
			/* ACK cmd set */
			stm32fwu_spi_send_ack(spi, BL_ACK);
			return (int)rx_buf;
		} else {
			/* Cross cmd set */
			tx_buf = rx_buf;
		}
		if (check_spi_wait_cnt % 20 == 0)
			usleep_range(1000, 1100);
		else
			usleep_range(1000, 1100);
		i++;
		check_spi_wait_cnt++;
	}
#if SSP_STM_DEBUG
	dev_err(&spi->dev, "%s: Timeout after %d loops\n",
			__func__, cmd->timeout);
#endif
	return -EIO;
}

static int stm32fwu_spi_send_cmd(struct spi_device *spi,
				 struct stm32fwu_spi_cmd *cmd)
{
	u8 tx_buf[3] = {0,};
	u8 rx_buf[3] = {0,};
	u8 dummy_byte = 0;
	struct spi_message m;
	int ret;
#if BYTETOBYTE_USED
	int i;
	struct spi_transfer t[STM_MAX_BUFFER_SIZE];
	memset(t, 0, STM_MAX_BUFFER_SIZE * sizeof(struct spi_transfer));
#else
	struct spi_transfer	t = {
		.tx_buf		= tx_buf,
		.rx_buf		= rx_buf,
		.len		= 3,
		.bits_per_word = 8,
	};
#endif
	ssp_dbgf();

	spi_message_init(&m);
	tx_buf[0] = BL_SPI_SOF;
	tx_buf[1] = cmd->cmd;
	tx_buf[2] = cmd->xor_cmd;

#if BYTETOBYTE_USED
	for (i = 0; i < 3; i++) {
		t[i].tx_buf = &tx_buf[i];
		t[i].rx_buf = &rx_buf[i];
		t[i].len = 1;
		t[i].bits_per_word = 8;
		t[i].delay_usecs = BYTE_DELAY_WRITE;
		spi_message_add_tail(&t[i], &m);
	}
#else
	spi_message_add_tail(&t, &m);
#endif

	ret = spi_sync(spi, &m);
	if (ret < 0) {
		dev_err(&spi->dev, "%s: spi error %d\n", __func__, ret);
		return ret;
	}

	dummy_byte = cmd->ack_pad;

	/* check for ack/nack and loop until found */
	ret = stm32fwu_spi_wait_for_ack(spi, cmd, dummy_byte);
	cmd->status = ret;

	if (ret != BL_ACK) {
		ssp_errf("Got NAK or Error %d", ret);
		return ret;
	}

	return ret;
}

static int stm32fwu_spi_write(struct spi_device *spi,
	const u8 *buffer, ssize_t len)
{
	int ret;
	u8 rx_buf[STM_MAX_BUFFER_SIZE] = {0,};
	struct spi_message m;
#if BYTETOBYTE_USED
	struct spi_transfer t[STM_MAX_BUFFER_SIZE];
	memset(t, 0, STM_MAX_BUFFER_SIZE * sizeof(struct spi_transfer));
	int i;
#else
	struct spi_transfer	t = {
		.tx_buf		= buffer,
		.rx_buf		= rx_buf,
		.len		= (unsigned int)len,
		.bits_per_word = 8,
	};
#endif
	spi_message_init(&m);
#if BYTETOBYTE_USED
	for (i = 0; i < len; i++) {
		t[i].tx_buf = &buffer[i];
		t[i].rx_buf = &rx_buf[i];
		t[i].len = 1;
		t[i].bits_per_word = 8;
		t[i].delay_usecs = BYTE_DELAY_WRITE;
		spi_message_add_tail(&t[i], &m);
	}
#else
	spi_message_add_tail(&t, &m);
#endif
	ret = spi_sync(spi, &m);

	if (ret < 0) {
		ssp_err("Error in %d spi_write()", ret);
		return ret;
	}

	return len;
}

static int send_addr(struct spi_device *spi, u32 fw_addr, int send_short)
{
	int res;
	int i = send_short;
	int len = SEND_ADDR_LEN - send_short;
	u8 header[SEND_ADDR_LEN];
	struct stm32fwu_spi_cmd dummy_cmd;
	dummy_cmd.timeout = DEF_ACKROOF_NUMBER;
	ssp_dbgf();

	header[0] = (u8)((fw_addr >> 24) & 0xFF);
	header[1] = (u8)((fw_addr >> 16) & 0xFF);
	header[2] = (u8)((fw_addr >> 8) & 0xFF);
	header[3] = (u8)(fw_addr & 0xFF);
	header[4] = header[0] ^ header[1] ^ header[2] ^ header[3];

	res = stm32fwu_spi_write(spi, &header[i], len);

	if (res < len) {
		ssp_err("Error in sending address. Res %d", res);
		return (res > 0) ? -EIO : res;
	}

	res = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK);
	if (res != BL_ACK) {
		ssp_err("send_addr(): rcv_ack returned 0x%x", res);
		return res;
	}
	return 0;
}