diff options
Diffstat (limited to 'drivers/spi/spi-mt65xx.c')
-rw-r--r-- | drivers/spi/spi-mt65xx.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 45d8a7048b6c..6783e12c40c2 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, @@ -123,7 +139,6 @@ static const struct mtk_spi_compatible mt8183_compat = { * supplies it. */ static const struct mtk_chip_config mtk_default_chip_info = { - .cs_pol = 0, .sample_sel = 0, }; @@ -137,6 +152,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, }, @@ -211,10 +229,12 @@ static int mtk_spi_prepare_message(struct spi_master *master, #endif if (mdata->dev_comp->enhance_timing) { - if (chip_config->cs_pol) + /* set CS polarity */ + if (spi->mode & SPI_CS_HIGH) reg_val |= SPI_CMD_CS_POL; else reg_val &= ~SPI_CMD_CS_POL; + if (chip_config->sample_sel) reg_val |= SPI_CMD_SAMPLE_SEL; else @@ -245,6 +265,9 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) u32 reg_val; struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + if (spi->mode & SPI_CS_HIGH) + enable = !enable; + reg_val = readl(mdata->base + SPI_CMD_REG); if (!enable) { reg_val |= SPI_CMD_PAUSE_EN; @@ -371,10 +394,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, @@ -585,8 +623,7 @@ static int mtk_spi_probe(struct platform_device *pdev) 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) { @@ -613,6 +650,10 @@ static int mtk_spi_probe(struct platform_device *pdev) mdata = spi_master_get_devdata(master); mdata->dev_comp = of_id->data; + + if (mdata->dev_comp->enhance_timing) + master->mode_bits |= SPI_CS_HIGH; + if (mdata->dev_comp->must_tx) master->flags = SPI_MASTER_MUST_TX; @@ -648,15 +689,7 @@ static int mtk_spi_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, master); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to determine base address\n"); - goto err_put_master; - } - - mdata->base = devm_ioremap_resource(&pdev->dev, res); + mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) { ret = PTR_ERR(mdata->base); goto err_put_master; @@ -664,7 +697,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 +785,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: |