]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
spi: mtk_snor: fix zeroed data in DMA read bounce path
authorMacpaul Lin <macpaul.lin@mediatek.com>
Mon, 6 Apr 2026 20:13:33 +0000 (15:13 -0500)
committerDavid Lechner <dlechner@baylibre.com>
Tue, 28 Apr 2026 18:11:19 +0000 (13:11 -0500)
Implement proper bounce buffer handling for the read path to fix zeroed
data when using DMA. In the bounce path, map the bounce buffer with
dma_map_single(), perform DMA using bounce_dma, then copy data from the
bounce buffer to the user buffer, and finally unmap with
dma_unmap_single().

Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
Reviewed-by: Julien Stephan <jstephan@baylibre.com>
Link: https://patch.msgid.link/20260406-mtk-spi-nor-improvements-v1-7-66f675cbbd3e@baylibre.com
Signed-off-by: David Lechner <dlechner@baylibre.com>
drivers/spi/mtk_snor.c

index 649bca5716c1f55b380fdd899d24fef6d9f31240..21ac115e3c3b4704872952b5e6923a91d7e4de95 100644 (file)
@@ -274,6 +274,7 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv,
 {
        unsigned int rdlen;
        int ret;
+       dma_addr_t bounce_dma;
 
        if (op->data.nbytes & MTK_NOR_DMA_ALIGN_MASK)
                rdlen = (op->data.nbytes + MTK_NOR_DMA_ALIGN) &
@@ -281,11 +282,21 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv,
        else
                rdlen = op->data.nbytes;
 
-       ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen,
-                               (dma_addr_t)priv->buffer);
+       /* Map bounce buffer for DMA */
+       bounce_dma = dma_map_single(priv->buffer, rdlen, DMA_FROM_DEVICE);
+       if (dma_mapping_error(priv->dev, bounce_dma)) {
+               dev_err(priv->dev, "bounce buffer dma map failed\n");
+               return -EINVAL;
+       }
 
-       if (!ret)
+       ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen, bounce_dma);
+       /* Ensure DMA writes are visible to CPU and copy the requested bytes */
+       if (!ret) {
+               /* Synchronize cached data to CPU visible memory if needed */
                memcpy(op->data.buf.in, priv->buffer, op->data.nbytes);
+       }
+       /* Unmap bounce buffer regardless of success/failure */
+       dma_unmap_single(bounce_dma, rdlen, DMA_FROM_DEVICE);
 
        return ret;
 }