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; }