#include <linux/platform_data/spi-mt65xx.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
+#include <linux/dma-mapping.h>
 
 #define SPI_CFG0_REG                      0x0000
 #define SPI_CFG1_REG                      0x0004
 #define SPI_STATUS0_REG                   0x001c
 #define SPI_PAD_SEL_REG                   0x0024
 #define SPI_CFG2_REG                      0x0028
+#define SPI_TX_SRC_REG_64                 0x002c
+#define SPI_RX_DST_REG_64                 0x0030
 
 #define SPI_CFG0_SCK_HIGH_OFFSET          0
 #define SPI_CFG0_SCK_LOW_OFFSET           8
 
 #define MTK_SPI_MAX_FIFO_SIZE 32U
 #define MTK_SPI_PACKET_SIZE 1024
+#define MTK_SPI_32BITS_MASK  (0xffffffff)
+
+#define DMA_ADDR_EXT_BITS (36)
+#define DMA_ADDR_DEF_BITS (32)
 
 struct mtk_spi_compatible {
        bool need_pad_sel;
        bool must_tx;
        /* some IC design adjust cfg register to enhance time accuracy */
        bool enhance_timing;
+       /* some IC support DMA addr extension */
+       bool dma_ext;
 };
 
 struct mtk_spi {
        .need_pad_sel = true,
        .must_tx = true,
        .enhance_timing = true,
+       .dma_ext = true,
 };
 
 static const struct mtk_spi_compatible mt7622_compat = {
 {
        struct mtk_spi *mdata = spi_master_get_devdata(master);
 
-       if (mdata->tx_sgl)
-               writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG);
-       if (mdata->rx_sgl)
-               writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG);
+       if (mdata->tx_sgl) {
+               writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK),
+                      mdata->base + SPI_TX_SRC_REG);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+               if (mdata->dev_comp->dma_ext)
+                       writel((u32)(xfer->tx_dma >> 32),
+                              mdata->base + SPI_TX_SRC_REG_64);
+#endif
+       }
+
+       if (mdata->rx_sgl) {
+               writel((u32)(xfer->rx_dma & MTK_SPI_32BITS_MASK),
+                      mdata->base + SPI_RX_DST_REG);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+               if (mdata->dev_comp->dma_ext)
+                       writel((u32)(xfer->rx_dma >> 32),
+                              mdata->base + SPI_RX_DST_REG_64);
+#endif
+       }
 }
 
 static int mtk_spi_fifo_transfer(struct spi_master *master,
        struct mtk_spi *mdata;
        const struct of_device_id *of_id;
        struct resource *res;
-       int i, irq, ret;
+       int i, irq, ret, addr_bits;
 
        master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
        if (!master) {
                }
        }
 
+       if (mdata->dev_comp->dma_ext)
+               addr_bits = DMA_ADDR_EXT_BITS;
+       else
+               addr_bits = DMA_ADDR_DEF_BITS;
+       ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(addr_bits));
+       if (ret)
+               dev_notice(&pdev->dev, "SPI dma_set_mask(%d) failed, ret:%d\n",
+                          addr_bits, ret);
+
        return 0;
 
 err_disable_runtime_pm: