diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/spi-bcm2835.c | 38 | ||||
-rw-r--r-- | drivers/spi/spi-bitbang-txrx.h | 4 | ||||
-rw-r--r-- | drivers/spi/spi-img-spfi.c | 61 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi-xilinx.c | 20 | ||||
-rw-r--r-- | drivers/spi/spi-zynqmp-gqspi.c | 1 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 1 |
9 files changed, 108 insertions, 34 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0cae1694014d..b0f30fb68914 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -612,7 +612,7 @@ config SPI_XTENSA_XTFPGA config SPI_ZYNQMP_GQSPI tristate "Xilinx ZynqMP GQSPI controller" - depends on SPI_MASTER + depends on SPI_MASTER && HAS_DMA help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 59705ab23577..e7874a6171ec 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master, struct spi_device *spi, struct spi_transfer *tfr, u32 cs, - unsigned long xfer_time_us) + unsigned long long xfer_time_us) { struct bcm2835_spi *bs = spi_master_get_devdata(master); unsigned long timeout; @@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, { struct bcm2835_spi *bs = spi_master_get_devdata(master); unsigned long spi_hz, clk_hz, cdiv; - unsigned long spi_used_hz, xfer_time_us; + unsigned long spi_used_hz; + unsigned long long xfer_time_us; u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); /* set clock */ @@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536); bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); - /* handle all the modes */ + /* handle all the 3-wire mode */ if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf)) cs |= BCM2835_SPI_CS_REN; - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; + else + cs &= ~BCM2835_SPI_CS_REN; /* for gpio_cs set dummy CS so that no HW-CS get changed * we can not run this in bcm2835_spi_set_cs, as it does @@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, bs->rx_len = tfr->len; /* calculate the estimated time in us the transfer runs */ - xfer_time_us = tfr->len + xfer_time_us = (unsigned long long)tfr->len * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */ - * 1000000 / spi_used_hz; + * 1000000; + do_div(xfer_time_us, spi_used_hz); /* for short requests run polling*/ if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US) @@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master, return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs); } +static int bcm2835_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_device *spi = msg->spi; + struct bcm2835_spi *bs = spi_master_get_devdata(master); + u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + + cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); + + if (spi->mode & SPI_CPOL) + cs |= BCM2835_SPI_CS_CPOL; + if (spi->mode & SPI_CPHA) + cs |= BCM2835_SPI_CS_CPHA; + + bcm2835_wr(bs, BCM2835_SPI_CS, cs); + + return 0; +} + static void bcm2835_spi_handle_err(struct spi_master *master, struct spi_message *msg) { @@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) master->set_cs = bcm2835_spi_set_cs; master->transfer_one = bcm2835_spi_transfer_one; master->handle_err = bcm2835_spi_handle_err; + master->prepare_message = bcm2835_spi_prepare_message; master->dev.of_node = pdev->dev.of_node; bs = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h index 06b34e5bcfa3..47bb9b898dfd 100644 --- a/drivers/spi/spi-bitbang-txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h @@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, { /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ - bool oldbit = !(word & 1); + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { @@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, { /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ - bool oldbit = !(word & (1 << 31)); + u32 oldbit = (!(word & (1<<(bits-1)))) << 31; /* clock starts at inactive polarity */ for (word <<= (32 - bits); likely(bits); bits--) { diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b176a4f..bb916c8d40db 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESET BIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SE BIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK 0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -104,6 +105,10 @@ struct img_spfi { bool rx_dma_busy; }; +struct img_spfi_device_data { + bool gpio_requested; +}; + static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg) { return readl(spfi->regs + reg); @@ -266,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master, cpu_relax(); } - ret = spfi_wait_all_done(spfi); - if (ret < 0) - return ret; - if (rx_bytes > 0 || tx_bytes > 0) { dev_err(spfi->dev, "PIO transfer timed out\n"); return -ETIMEDOUT; } + ret = spfi_wait_all_done(spfi); + if (ret < 0) + return ret; + return 0; } @@ -439,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master, static int img_spfi_setup(struct spi_device *spi) { - int ret; - - ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? - GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, - dev_name(&spi->dev)); - if (ret) - dev_err(&spi->dev, "can't request chipselect gpio %d\n", + int ret = -EINVAL; + struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi); + + if (!spfi_data) { + spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL); + if (!spfi_data) + return -ENOMEM; + spfi_data->gpio_requested = false; + spi_set_ctldata(spi, spfi_data); + } + if (!spfi_data->gpio_requested) { + ret = gpio_request_one(spi->cs_gpio, + (spi->mode & SPI_CS_HIGH) ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, + dev_name(&spi->dev)); + if (ret) + dev_err(&spi->dev, "can't request chipselect gpio %d\n", spi->cs_gpio); - + else + spfi_data->gpio_requested = true; + } else { + if (gpio_is_valid(spi->cs_gpio)) { + int mode = ((spi->mode & SPI_CS_HIGH) ? + GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH); + + ret = gpio_direction_output(spi->cs_gpio, mode); + if (ret) + dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n", + spi->cs_gpio, ret); + } + } return ret; } static void img_spfi_cleanup(struct spi_device *spi) { - gpio_free(spi->cs_gpio); + struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi); + + if (spfi_data) { + if (spfi_data->gpio_requested) + gpio_free(spi->cs_gpio); + kfree(spfi_data); + spi_set_ctldata(spi, NULL); + } } static void img_spfi_config(struct spi_master *master, struct spi_device *spi, @@ -491,6 +525,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index eb7d3a6fb14c..f9deb84e4e55 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -201,8 +201,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); - if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml) - && (transfer->len > spi_imx->tx_wml)) + if (spi_imx->dma_is_inited + && transfer->len > spi_imx->rx_wml * sizeof(u32) + && transfer->len > spi_imx->tx_wml * sizeof(u32)) return true; return false; } diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 58673841286c..3d09e0b69b73 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) { + struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); u32 l; /* The controller handles the inverted chip selects @@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) enable = !enable; if (spi->controller_state) { + int err = pm_runtime_get_sync(mcspi->dev); + if (err < 0) { + dev_err(mcspi->dev, "failed to get sync: %d\n", err); + return; + } + l = mcspi_cached_chconf0(spi); if (enable) @@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable) l |= OMAP2_MCSPI_CHCONF_FORCE; mcspi_write_chconf0(spi, l); + + pm_runtime_mark_last_busy(mcspi->dev); + pm_runtime_put_autosuspend(mcspi->dev); } } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 133f53a9c1d4..a339c1e9997a 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) xspi->tx_ptr = t->tx_buf; xspi->rx_ptr = t->rx_buf; remaining_words = t->len / xspi->bytes_per_word; - reinit_completion(&xspi->done); if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { + u32 isr; use_irq = true; - xspi->write_fn(XSPI_INTR_TX_EMPTY, - xspi->regs + XIPIF_V123B_IISR_OFFSET); - /* Enable the global IPIF interrupt */ - xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, - xspi->regs + XIPIF_V123B_DGIER_OFFSET); /* Inhibit irq to avoid spurious irqs on tx_empty*/ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, xspi->regs + XSPI_CR_OFFSET); + /* ACK old irqs (if any) */ + isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); + if (isr) + xspi->write_fn(isr, + xspi->regs + XIPIF_V123B_IISR_OFFSET); + /* Enable the global IPIF interrupt */ + xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, + xspi->regs + XIPIF_V123B_DGIER_OFFSET); + reinit_completion(&xspi->done); } while (remaining_words) { @@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) remaining_words -= n_words; } - if (use_irq) + if (use_irq) { xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); + xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); + } return t->len; } diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 87b20a511a6b..f23f36ebaf3d 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -214,6 +214,7 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr, case GQSPI_SELECT_FLASH_CS_BOTH: instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER | GQSPI_GENFIFO_CS_UPPER; + break; case GQSPI_SELECT_FLASH_CS_UPPER: instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER; break; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index dd616ff0ffc5..c7de64171c45 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -693,6 +693,7 @@ static struct class *spidev_class; #ifdef CONFIG_OF static const struct of_device_id spidev_dt_ids[] = { { .compatible = "rohm,dh2228fv" }, + { .compatible = "lineartechnology,ltc2488" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); |