diff options
Diffstat (limited to 'drivers/spi/spi-mt65xx.c')
-rw-r--r-- | drivers/spi/spi-mt65xx.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 45d8a7048b6c..6888a4dcff6d 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -17,6 +17,7 @@ #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 @@ -28,6 +29,8 @@ #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 @@ -73,6 +76,10 @@ #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; @@ -80,6 +87,8 @@ struct mtk_spi_compatible { 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 { @@ -102,6 +111,13 @@ static const struct mtk_spi_compatible mt2712_compat = { .must_tx = true, }; +static const struct mtk_spi_compatible mt6765_compat = { + .need_pad_sel = true, + .must_tx = true, + .enhance_timing = true, + .dma_ext = true, +}; + static const struct mtk_spi_compatible mt7622_compat = { .must_tx = true, .enhance_timing = true, @@ -137,6 +153,9 @@ static const struct of_device_id mtk_spi_of_match[] = { { .compatible = "mediatek,mt6589-spi", .data = (void *)&mtk_common_compat, }, + { .compatible = "mediatek,mt6765-spi", + .data = (void *)&mt6765_compat, + }, { .compatible = "mediatek,mt7622-spi", .data = (void *)&mt7622_compat, }, @@ -371,10 +390,25 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master, { 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, @@ -586,7 +620,7 @@ static int mtk_spi_probe(struct platform_device *pdev) 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) { @@ -664,7 +698,6 @@ static int mtk_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_master; } @@ -753,6 +786,15 @@ static int mtk_spi_probe(struct platform_device *pdev) } } + 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: |