diff options
author | Mark Brown <broonie@kernel.org> | 2019-05-02 11:20:29 +0900 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-05-02 11:20:29 +0900 |
commit | 2e5f081003f033d37be3faf052aaccc8b6a44aa5 (patch) | |
tree | 6d07a9bfff47b20f997ecce96162b8ca9cf7b19c /drivers/spi | |
parent | 58b860ed4a77d9cb17b78e663a0341b79a12e240 (diff) | |
parent | d61ad23cb3be09ff4956e9b9794134456522817f (diff) |
Merge branch 'spi-5.2' into spi-next
Diffstat (limited to 'drivers/spi')
28 files changed, 2582 insertions, 550 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f761655e2a36..0fba8f400c59 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -426,6 +426,12 @@ config SPI_MT65XX say Y or M here.If you are not sure, say N. SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. +config SPI_MT7621 + tristate "MediaTek MT7621 SPI Controller" + depends on RALINK || COMPILE_TEST + help + This selects a driver for the MediaTek MT7621 SPI Controller. + config SPI_NPCM_PSPI tristate "Nuvoton NPCM PSPI Controller" depends on ARCH_NPCM || COMPILE_TEST @@ -842,9 +848,17 @@ config SPI_XTENSA_XTFPGA 16 bit words in SPI mode 0, automatically asserting CS on transfer start and deasserting on end. +config SPI_ZYNQ_QSPI + tristate "Xilinx Zynq QSPI controller" + depends on ARCH_ZYNQ || COMPILE_TEST + help + This enables support for the Zynq Quad SPI controller + in master mode. + This controller only supports SPI memory interface. + config SPI_ZYNQMP_GQSPI tristate "Xilinx ZynqMP GQSPI controller" - depends on SPI_MASTER && HAS_DMA + depends on (SPI_MASTER && HAS_DMA) || COMPILE_TEST help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index d8fc03c9faa2..f2f78d03dc28 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o +obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o @@ -118,6 +119,7 @@ obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o obj-$(CONFIG_SPI_XLP) += spi-xlp.o obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o +obj-$(CONFIG_SPI_ZYNQ_QSPI) += spi-zynq-qspi.o obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o # SPI slave protocol handlers diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index b3173ebddade..9f24d5f0b431 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -366,7 +366,7 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) return err; } -const char *atmel_qspi_get_name(struct spi_mem *spimem) +static const char *atmel_qspi_get_name(struct spi_mem *spimem) { return dev_name(spimem->spi->dev.parent); } diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a694d702e574..f763e14bdf12 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -178,12 +178,6 @@ static int at91_usart_spi_setup(struct spi_device *spi) struct at91_usart_spi *aus = spi_master_get_devdata(spi->controller); u32 *ausd = spi->controller_state; unsigned int mr = at91_usart_spi_readl(aus, MR); - u8 bits = spi->bits_per_word; - - if (bits != 8) { - dev_dbg(&spi->dev, "Only 8 bits per word are supported\n"); - return -EINVAL; - } if (spi->mode & SPI_CPOL) mr |= US_MR_CPOL; @@ -212,7 +206,7 @@ static int at91_usart_spi_setup(struct spi_device *spi) dev_dbg(&spi->dev, "setup: bpw %u mode 0x%x -> mr %d %08x\n", - bits, spi->mode, spi->chip_select, mr); + spi->bits_per_word, spi->mode, spi->chip_select, mr); return 0; } diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 35aebdfd3b4e..8aa22713c483 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -335,20 +335,6 @@ static int bcm2835_spi_transfer_one_irq(struct spi_master *master, return 1; } -/* - * DMA support - * - * this implementation has currently a few issues in so far as it does - * not work arrount limitations of the HW. - * - * the main one being that DMA transfers are limited to 16 bit - * (so 0 to 65535 bytes) by the SPI HW due to BCM2835_SPI_DLEN - * - * there may be a few more border-cases we may need to address as well - * but unfortunately this would mean splitting up the scatter-gather - * list making it slightly unpractical... - */ - /** * bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA * @master: SPI master @@ -630,19 +616,6 @@ static bool bcm2835_spi_can_dma(struct spi_master *master, if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH) return false; - /* BCM2835_SPI_DLEN has defined a max transfer size as - * 16 bit, so max is 65535 - * we can revisit this by using an alternative transfer - * method - ideally this would get done without any more - * interaction... - */ - if (tfr->len > 65535) { - dev_warn_once(&spi->dev, - "transfer size of %d too big for dma-transfer\n", - tfr->len); - return false; - } - /* return OK */ return true; } @@ -707,7 +680,6 @@ static void bcm2835_dma_init(struct spi_master *master, struct device *dev) /* all went well, so set can_dma */ master->can_dma = bcm2835_spi_can_dma; - master->max_dma_len = 65535; /* limitation by BCM2835_SPI_DLEN */ /* need to do TX AND RX DMA, so we need dummy buffers */ master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; @@ -844,6 +816,17 @@ static int bcm2835_spi_prepare_message(struct spi_master *master, struct spi_device *spi = msg->spi; struct bcm2835_spi *bs = spi_master_get_devdata(master); u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + int ret; + + /* + * DMA transfers are limited to 16 bit (0 to 65535 bytes) by the SPI HW + * due to DLEN. Split up transfers (32-bit FIFO aligned) if the limit is + * exceeded. + */ + ret = spi_split_transfers_maxsize(master, msg, 65532, + GFP_KERNEL | GFP_DMA); + if (ret) + return ret; cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index f7e054848ca5..bbf87adb3ff8 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/completion.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/interrupt.h> @@ -36,6 +37,12 @@ #include <linux/spi/spi.h> #include <linux/spinlock.h> +/* define polling limits */ +static unsigned int polling_limit_us = 30; +module_param(polling_limit_us, uint, 0664); +MODULE_PARM_DESC(polling_limit_us, + "time in us to run a transfer in polling mode - if zero no polling is used\n"); + /* * spi register defines * @@ -88,10 +95,6 @@ #define BCM2835_AUX_SPI_STAT_BUSY 0x00000040 #define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F -/* timeout values */ -#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30 -#define BCM2835_AUX_SPI_POLLING_JIFFIES 2 - struct bcm2835aux_spi { void __iomem *regs; struct clk *clk; @@ -102,8 +105,53 @@ struct bcm2835aux_spi { int tx_len; int rx_len; int pending; + + u64 count_transfer_polling; + u64 count_transfer_irq; + u64 count_transfer_irq_after_poll; + + struct dentry *debugfs_dir; }; +#if defined(CONFIG_DEBUG_FS) +static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs, + const char *dname) +{ + char name[64]; + struct dentry *dir; + + /* get full name */ + snprintf(name, sizeof(name), "spi-bcm2835aux-%s", dname); + + /* the base directory */ + dir = debugfs_create_dir(name, NULL); + bs->debugfs_dir = dir; + + /* the counters */ + debugfs_create_u64("count_transfer_polling", 0444, dir, + &bs->count_transfer_polling); + debugfs_create_u64("count_transfer_irq", 0444, dir, + &bs->count_transfer_irq); + debugfs_create_u64("count_transfer_irq_after_poll", 0444, dir, + &bs->count_transfer_irq_after_poll); +} + +static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs) +{ + debugfs_remove_recursive(bs->debugfs_dir); + bs->debugfs_dir = NULL; +} +#else +static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs, + const char *dname) +{ +} + +static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs) +{ +} +#endif /* CONFIG_DEBUG_FS */ + static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg) { return readl(bs->regs + reg); @@ -123,9 +171,6 @@ static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs) data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO); if (bs->rx_buf) { switch (count) { - case 4: - *bs->rx_buf++ = (data >> 24) & 0xff; - /* fallthrough */ case 3: *bs->rx_buf++ = (data >> 16) & 0xff; /* fallthrough */ @@ -178,24 +223,14 @@ static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs) BCM2835_AUX_SPI_CNTL0_CLEARFIFO); } -static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) +static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs) { - struct spi_master *master = dev_id; - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); - irqreturn_t ret = IRQ_NONE; - - /* IRQ may be shared, so return if our interrupts are disabled */ - if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & - (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) - return ret; + u32 stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT); /* check if we have data to read */ - while (bs->rx_len && - (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & - BCM2835_AUX_SPI_STAT_RX_EMPTY))) { + for (; bs->rx_len && (stat & BCM2835_AUX_SPI_STAT_RX_LVL); + stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT)) bcm2835aux_rd_fifo(bs); - ret = IRQ_HANDLED; - } /* check if we have data to write */ while (bs->tx_len && @@ -203,16 +238,21 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & BCM2835_AUX_SPI_STAT_TX_FULL))) { bcm2835aux_wr_fifo(bs); - ret = IRQ_HANDLED; } +} - /* and check if we have reached "done" */ - while (bs->rx_len && - (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & - BCM2835_AUX_SPI_STAT_BUSY))) { - bcm2835aux_rd_fifo(bs); - ret = IRQ_HANDLED; - } +static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) +{ + struct spi_master *master = dev_id; + struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + + /* IRQ may be shared, so return if our interrupts are disabled */ + if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & + (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) + return IRQ_NONE; + + /* do common fifo handling */ + bcm2835aux_spi_transfer_helper(bs); if (!bs->tx_len) { /* disable tx fifo empty interrupt */ @@ -226,8 +266,7 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) complete(&master->xfer_completion); } - /* and return */ - return ret; + return IRQ_HANDLED; } static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master, @@ -251,6 +290,9 @@ static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master, { struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + /* update statistics */ + bs->count_transfer_irq++; + /* fill in registers and fifos before enabling interrupts */ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); @@ -273,35 +315,22 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, { struct bcm2835aux_spi *bs = spi_master_get_devdata(master); unsigned long timeout; - u32 stat; + + /* update statistics */ + bs->count_transfer_polling++; /* configure spi */ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); - /* set the timeout */ - timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES; + /* set the timeout to at least 2 jiffies */ + timeout = jiffies + 2 + HZ * polling_limit_us / 1000000; /* loop until finished the transfer */ while (bs->rx_len) { - /* read status */ - stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT); - /* fill in tx fifo with remaining data */ - if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) { - bcm2835aux_wr_fifo(bs); - continue; - } - - /* read data from fifo for both cases */ - if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) { - bcm2835aux_rd_fifo(bs); - continue; - } - if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) { - bcm2835aux_rd_fifo(bs); - continue; - } + /* do common fifo handling */ + bcm2835aux_spi_transfer_helper(bs); /* there is still data pending to read check the timeout */ if (bs->rx_len && time_after(jiffies, timeout)) { @@ -310,6 +339,7 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, jiffies - timeout, bs->tx_len, bs->rx_len); /* forward to interrupt handler */ + bs->count_transfer_irq_after_poll++; return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr); } @@ -324,8 +354,8 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, struct spi_transfer *tfr) { struct bcm2835aux_spi *bs = spi_master_get_devdata(master); - unsigned long spi_hz, clk_hz, speed; - unsigned long spi_used_hz; + unsigned long spi_hz, clk_hz, speed, spi_used_hz; + unsigned long hz_per_byte, byte_limit; /* calculate the registers to handle * @@ -369,14 +399,15 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, * of Hz per byte per polling limit. E.g., we can transfer 1 byte in * 30 µs per 300,000 Hz of bus clock. */ -#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US) + hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0; + byte_limit = hz_per_byte ? spi_used_hz / hz_per_byte : 1; + /* run in polling mode for short transfers */ - if (tfr->len < spi_used_hz / HZ_PER_BYTE) + if (tfr->len < byte_limit) return bcm2835aux_spi_transfer_one_poll(master, spi, tfr); /* run in interrupt mode for all others */ return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); -#undef HZ_PER_BYTE } static int bcm2835aux_spi_prepare_message(struct spi_master *master, @@ -421,6 +452,50 @@ static void bcm2835aux_spi_handle_err(struct spi_master *master, bcm2835aux_spi_reset_hw(bs); } +static int bcm2835aux_spi_setup(struct spi_device *spi) +{ + int ret; + + /* sanity check for native cs */ + if (spi->mode & SPI_NO_CS) + return 0; + if (gpio_is_valid(spi->cs_gpio)) { + /* with gpio-cs set the GPIO to the correct level + * and as output (in case the dt has the gpio not configured + * as output but native cs) + */ + ret = gpio_direction_output(spi->cs_gpio, + (spi->mode & SPI_CS_HIGH) ? 0 : 1); + if (ret) + dev_err(&spi->dev, + "could not set gpio %i as output: %i\n", + spi->cs_gpio, ret); + + return ret; + } + + /* for dt-backwards compatibility: only support native on CS0 + * known things not supported with broken native CS: + * * multiple chip-selects: cs0-cs2 are all + * simultaniously asserted whenever there is a transfer + * this even includes SPI_NO_CS + * * SPI_CS_HIGH: cs are always asserted low + * * cs_change: cs is deasserted after each spi_transfer + * * cs_delay_usec: cs is always deasserted one SCK cycle + * after the last transfer + * probably more... + */ + dev_warn(&spi->dev, + "Native CS is not supported - please configure cs-gpio in device-tree\n"); + + if (spi->chip_select == 0) + return 0; + + dev_warn(&spi->dev, "Native CS is not working for cs > 0\n"); + + return -EINVAL; +} + static int bcm2835aux_spi_probe(struct platform_device *pdev) { struct spi_master *master; @@ -438,7 +513,19 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); master->bits_per_word_mask = SPI_BPW_MASK(8); - master->num_chipselect = -1; + /* even though the driver never officially supported native CS + * allow a single native CS for legacy DT support purposes when + * no cs-gpio is configured. + * Known limitations for native cs are: + * * multiple chip-selects: cs0-cs2 are all simultaniously asserted + * whenever there is a transfer - this even includes SPI_NO_CS + * * SPI_CS_HIGH: is ignores - cs are always asserted low + * * cs_change: cs is deasserted after each spi_transfer + * * cs_delay_usec: cs is always deasserted one SCK cycle after + * a spi_transfer + */ + master->num_chipselect = 1; + master->setup = bcm2835aux_spi_setup; master->transfer_one = bcm2835aux_spi_transfer_one; master->handle_err = bcm2835aux_spi_handle_err; master->prepare_message = bcm2835aux_spi_prepare_message; @@ -502,6 +589,8 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) goto out_clk_disable; } + bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev)); + return 0; out_clk_disable: @@ -516,6 +605,8 @@ static int bcm2835aux_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + bcm2835aux_debugfs_remove(bs); + bcm2835aux_spi_reset_hw(bs); /* disable the HW block by releasing the clock */ diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index dd9a8c54a693..4243e53f9f7b 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -335,6 +335,42 @@ static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) /*----------------------------------------------------------------------*/ +int spi_bitbang_init(struct spi_bitbang *bitbang) +{ + struct spi_master *master = bitbang->master; + + if (!master || !bitbang->chipselect) + return -EINVAL; + + mutex_init(&bitbang->lock); + + if (!master->mode_bits) + master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; + + if (master->transfer || master->transfer_one_message) + return -EINVAL; + + master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; + master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; + master->transfer_one = spi_bitbang_transfer_one; + master->set_cs = spi_bitbang_set_cs; + + if (!bitbang->txrx_bufs) { + bitbang->use_dma = 0; + bitbang->txrx_bufs = spi_bitbang_bufs; + if (!master->setup) { + if (!bitbang->setup_transfer) + bitbang->setup_transfer = + spi_bitbang_setup_transfer; + master->setup = spi_bitbang_setup; + master->cleanup = spi_bitbang_cleanup; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_bitbang_init); + /** * spi_bitbang_start - start up a polled/bitbanging SPI master driver * @bitbang: driver handle @@ -368,33 +404,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) struct spi_master *master = bitbang->master; int ret; - if (!master || !bitbang->chipselect) - return -EINVAL; - - mutex_init(&bitbang->lock); - - if (!master->mode_bits) - master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; - - if (master->transfer || master->transfer_one_message) - return -EINVAL; - - master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; - master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; - master->transfer_one = spi_bitbang_transfer_one; - master->set_cs = spi_bitbang_set_cs; - - if (!bitbang->txrx_bufs) { - bitbang->use_dma = 0; - bitbang->txrx_bufs = spi_bitbang_bufs; - if (!master->setup) { - if (!bitbang->setup_transfer) - bitbang->setup_transfer = - spi_bitbang_setup_transfer; - master->setup = spi_bitbang_setup; - master->cleanup = spi_bitbang_cleanup; - } - } + ret = spi_bitbang_init(bitbang); + if (ret) + return ret; /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 4bd59a93d988..de952b17bc10 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -30,6 +30,7 @@ struct dw_spi_mmio { struct dw_spi dws; struct clk *clk; + struct clk *pclk; void *priv; }; @@ -172,6 +173,14 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) if (ret) return ret; + /* Optional clock needed to access the registers */ + dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); + if (IS_ERR(dwsmmio->pclk)) + return PTR_ERR(dwsmmio->pclk); + ret = clk_prepare_enable(dwsmmio->pclk); + if (ret) + goto out_clk; + dws->bus_num = pdev->id; dws->max_freq = clk_get_rate(dwsmmio->clk); @@ -199,6 +208,8 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) return 0; out: + clk_disable_unprepare(dwsmmio->pclk); +out_clk: clk_disable_unprepare(dwsmmio->clk); return ret; } @@ -208,6 +219,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); dw_spi_remove_host(&dwsmmio->dws); + clk_disable_unprepare(dwsmmio->pclk); clk_disable_unprepare(dwsmmio->clk); return 0; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 79fc3940245a..47e39251bad9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -28,7 +28,6 @@ #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/scatterlist.h> -#include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/platform_data/dma-ep93xx.h> @@ -676,6 +675,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; + master->use_gpio_descriptors = true; master->prepare_transfer_hardware = ep93xx_spi_prepare_hardware; master->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware; master->prepare_message = ep93xx_spi_prepare_message; @@ -683,31 +683,11 @@ static int ep93xx_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); - - master->num_chipselect = info->num_chipselect; - master->cs_gpios = devm_kcalloc(&master->dev, - master->num_chipselect, sizeof(int), - GFP_KERNEL); - if (!master->cs_gpios) { - error = -ENOMEM; - goto fail_release_master; - } - - for (i = 0; i < master->num_chipselect; i++) { - master->cs_gpios[i] = info->chipselect[i]; - - if (!gpio_is_valid(master->cs_gpios[i])) - continue; - - error = devm_gpio_request_one(&pdev->dev, master->cs_gpios[i], - GPIOF_OUT_INIT_HIGH, - "ep93xx-spi"); - if (error) { - dev_err(&pdev->dev, "could not request cs gpio %d\n", - master->cs_gpios[i]); - goto fail_release_master; - } - } + /* + * The SPI core will count the number of GPIO descriptors to figure + * out the number of chip selects available on the platform. + */ + master->num_chipselect = 0; platform_set_drvdata(pdev, master); diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index f303f306b38e..483734bc1b1e 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -95,8 +95,10 @@ static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) struct mpc8xxx_spi_probe_info { struct fsl_spi_platform_data pdata; + int ngpios; int *gpios; bool *alow_flags; + __be32 __iomem *immr_spi_cs; }; extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi); diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 9e117c4635d8..d08e9324140e 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -8,7 +8,10 @@ #include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> #include <linux/err.h> +#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> @@ -16,7 +19,12 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> +#include <linux/platform_data/dma-imx.h> +#include <linux/platform_data/spi-imx.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> @@ -24,6 +32,11 @@ #define DRIVER_NAME "fsl_lpspi" +#define FSL_LPSPI_RPM_TIMEOUT 50 /* 50ms */ + +/* The maximum bytes that edma can transfer once.*/ +#define FSL_LPSPI_MAX_EDMA_BYTES ((1 << 15) - 1) + /* i.MX7ULP LPSPI registers */ #define IMX7ULP_VERID 0x0 #define IMX7ULP_PARAM 0x4 @@ -57,6 +70,8 @@ #define IER_FCIE BIT(9) #define IER_RDIE BIT(1) #define IER_TDIE BIT(0) +#define DER_RDDE BIT(1) +#define DER_TDDE BIT(0) #define CFGR1_PCSCFG BIT(27) #define CFGR1_PINCFG (BIT(24)|BIT(25)) #define CFGR1_PCSPOL BIT(8) @@ -84,8 +99,11 @@ struct lpspi_config { struct fsl_lpspi_data { struct device *dev; void __iomem *base; - struct clk *clk; + unsigned long base_phys; + struct clk *clk_ipg; + struct clk *clk_per; bool is_slave; + bool is_first_byte; void *rx_buf; const void *tx_buf; @@ -101,6 +119,13 @@ struct fsl_lpspi_data { struct completion xfer_done; bool slave_aborted; + + /* DMA */ + bool usedma; + struct completion dma_rx_completion; + struct completion dma_tx_completion; + + int chipselect[0]; }; static const struct of_device_id fsl_lpspi_dt_ids[] = { @@ -147,12 +172,48 @@ static void fsl_lpspi_intctrl(struct fsl_lpspi_data *fsl_lpspi, writel(enable, fsl_lpspi->base + IMX7ULP_IER); } +static int fsl_lpspi_bytes_per_word(const int bpw) +{ + return DIV_ROUND_UP(bpw, BITS_PER_BYTE); +} + +static bool fsl_lpspi_can_dma(struct spi_controller *controller, + struct spi_device *spi, + struct spi_transfer *transfer) +{ + unsigned int bytes_per_word; + + if (!controller->dma_rx) + return false; + + bytes_per_word = fsl_lpspi_bytes_per_word(transfer->bits_per_word); + + switch (bytes_per_word) + { + case 1: + case 2: + case 4: + break; + default: + return false; + } + + return true; +} + static int lpspi_prepare_xfer_hardware(struct spi_controller *controller) { struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(controller); + int ret; + + ret = pm_runtime_get_sync(fsl_lpspi->dev); + if (ret < 0) { + dev_err(fsl_lpspi->dev, "failed to enable clock\n"); + return ret; + } - return clk_prepare_enable(fsl_lpspi->clk); + return 0; } static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller) @@ -160,7 +221,22 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller) struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(controller); - clk_disable_unprepare(fsl_lpspi->clk); + pm_runtime_mark_last_busy(fsl_lpspi->dev); + pm_runtime_put_autosuspend(fsl_lpspi->dev); + + return 0; +} + +static int fsl_lpspi_prepare_message(struct spi_controller *controller, + struct spi_message |