drivers: spi: esp32xx: Fix word size issue

This commit fixes the word size configuration issue
described in #54746 by considering the data frame size
when trasmitting in case the configuration is applied.

It also fixes an heap corruption problem when using
SPI DMA with a buffer that is not multiple of 32 bits
in lenght and GDMA instance in initialization.

Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>
diff --git a/drivers/spi/spi_esp32_spim.c b/drivers/spi/spi_esp32_spim.c
index 50e9ab5..e6a0eeb 100644
--- a/drivers/spi/spi_esp32_spim.c
+++ b/drivers/spi/spi_esp32_spim.c
@@ -70,29 +70,31 @@
 	size_t chunk_len = spi_context_max_continuous_chunk(&data->ctx);
 	size_t max_buf_sz =
 		cfg->dma_enabled ? SPI_DMA_MAX_BUFFER_SIZE : SOC_SPI_MAXIMUM_BUFFER_SIZE;
-	chunk_len = MIN(chunk_len, max_buf_sz);
-	size_t bit_len = chunk_len << 3;
+	size_t transfer_len = data->word_size ? data->dfs : MIN(chunk_len, max_buf_sz);
+	size_t bit_len =  transfer_len << 3;
 	uint8_t *rx_temp = NULL;
 	uint8_t *tx_temp = NULL;
+	uint8_t dma_len_tx = data->word_size ? data->dfs : ctx->tx_len;
+	uint8_t dma_len_rx = data->word_size ? data->dfs : ctx->rx_len;
 
 	if (cfg->dma_enabled) {
 		/* bit_len needs to be at least one byte long when using DMA */
 		bit_len = !bit_len ? 8 : bit_len;
 		if (ctx->tx_buf && !esp_ptr_dma_capable((uint32_t *)&ctx->tx_buf[0])) {
-			tx_temp = k_malloc(ctx->tx_len);
+			tx_temp = k_malloc(dma_len_tx);
 			if (!tx_temp) {
 				LOG_ERR("Error allocating temp buffer Tx");
 				return -ENOMEM;
 			}
-			memcpy(tx_temp, &ctx->tx_buf[0], ctx->tx_len);
+			memcpy(tx_temp, &ctx->tx_buf[0], dma_len_tx);
 		}
 		if (ctx->rx_buf && (!esp_ptr_dma_capable((uint32_t *)&ctx->rx_buf[0]) ||
-				    ((int)&ctx->rx_buf[0] % 4 != 0))) {
+				    ((int)&ctx->rx_buf[0] % 4 != 0) || (dma_len_tx % 4 != 0))) {
 			/* The rx buffer need to be length of
 			 * multiples of 32 bits to avoid heap
 			 * corruption.
 			 */
-			rx_temp = k_calloc(((ctx->rx_len << 3) + 31) / 8, sizeof(uint8_t));
+			rx_temp = k_calloc(((dma_len_rx << 3) + 31) / 8, sizeof(uint8_t));
 			if (!rx_temp) {
 				LOG_ERR("Error allocating temp buffer Rx");
 				k_free(tx_temp);
@@ -118,7 +120,7 @@
 
 	/* send data */
 	spi_hal_user_start(hal);
-	spi_context_update_tx(&data->ctx, data->dfs, chunk_len);
+	spi_context_update_tx(&data->ctx, data->dfs, transfer_len/data->dfs);
 
 	while (!spi_hal_usr_is_done(hal)) {
 		/* nop */
@@ -128,10 +130,10 @@
 	spi_hal_fetch_result(hal);
 
 	if (rx_temp) {
-		memcpy(&ctx->rx_buf[0], rx_temp, chunk_len);
+		memcpy(&ctx->rx_buf[0], rx_temp, transfer_len);
 	}
 
-	spi_context_update_rx(&data->ctx, data->dfs, chunk_len);
+	spi_context_update_rx(&data->ctx, data->dfs, transfer_len/data->dfs);
 
 	k_free(tx_temp);
 	k_free(rx_temp);
@@ -166,7 +168,7 @@
 	}
 
 #ifdef SOC_GDMA_SUPPORTED
-	gdma_hal_init(&data->hal_gdma, cfg->dma_host);
+	gdma_hal_init(&data->hal_gdma, 0);
 	gdma_ll_enable_clock(data->hal_gdma.dev, true);
 	gdma_ll_tx_reset_channel(data->hal_gdma.dev, cfg->dma_host);
 	gdma_ll_rx_reset_channel(data->hal_gdma.dev, cfg->dma_host);
@@ -324,8 +326,6 @@
 	data->trans_config.line_mode.addr_lines = 1;
 	data->trans_config.line_mode.cmd_lines = 1;
 
-	hal_dev->cs_setup = 1;
-
 	/* SPI mode */
 	hal_dev->mode = 0;
 	if (SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL) {
@@ -351,18 +351,14 @@
 	return 0;
 }
 
-static inline uint8_t spi_esp32_get_frame_size(const struct spi_config *spi_cfg)
+static inline uint8_t spi_esp32_get_frame_size(const struct device *dev,
+					       const struct spi_config *spi_cfg)
 {
-	uint8_t dfs = SPI_WORD_SIZE_GET(spi_cfg->operation);
+	struct spi_esp32_data *data = dev->data;
 
-	dfs /= 8;
+	data->word_size = SPI_WORD_SIZE_GET(spi_cfg->operation);
 
-	if ((dfs == 0) || (dfs > 4)) {
-		LOG_WRN("Unsupported dfs, 1-byte size will be used");
-		dfs = 1;
-	}
-
-	return dfs;
+	return data->word_size ? data->word_size >> 3 : 1;
 }
 
 static int transceive(const struct device *dev,
@@ -393,7 +389,7 @@
 		goto done;
 	}
 
-	data->dfs = spi_esp32_get_frame_size(spi_cfg);
+	data->dfs = spi_esp32_get_frame_size(dev, spi_cfg);
 
 	spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, data->dfs);
 
diff --git a/drivers/spi/spi_esp32_spim.h b/drivers/spi/spi_esp32_spim.h
index ecaf639..9a8ff98 100644
--- a/drivers/spi/spi_esp32_spim.h
+++ b/drivers/spi/spi_esp32_spim.h
@@ -52,6 +52,7 @@
 	int irq_line;
 	lldesc_t dma_desc_tx;
 	lldesc_t dma_desc_rx;
+	uint8_t word_size;
 };
 
 #endif /* ZEPHYR_DRIVERS_SPI_ESP32_SPIM_H_ */