diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-ath79.c | 11 | ||||
-rw-r--r-- | drivers/spi/spi-atmel.c | 26 | ||||
-rw-r--r-- | drivers/spi/spi-au1550.c | 11 | ||||
-rw-r--r-- | drivers/spi/spi-bcm2835.c | 20 | ||||
-rw-r--r-- | drivers/spi/spi-davinci.c | 22 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 7 | ||||
-rw-r--r-- | drivers/spi/spi-meson-spifc.c | 1 | ||||
-rw-r--r-- | drivers/spi/spi-mt65xx.c | 53 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 28 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi-ti-qspi.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-xilinx.c | 38 | ||||
-rw-r--r-- | drivers/spi/spi-xtensa-xtfpga.c | 4 | ||||
-rw-r--r-- | drivers/spi/spi.c | 132 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 3 |
15 files changed, 239 insertions, 124 deletions
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index bf1f9b32c597..6165bf21d427 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -240,14 +240,9 @@ static int ath79_spi_probe(struct platform_device *pdev) sp->bitbang.flags = SPI_CS_HIGH; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - ret = -ENOENT; - goto err_put_master; - } - - sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); - if (!sp->base) { - ret = -ENXIO; + sp->base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(sp->base)) { + ret = PTR_ERR(sp->base); goto err_put_master; } diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index bf9ed380bb1c..aebad36391c9 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -773,7 +773,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, *plen = len; - if (atmel_spi_dma_slave_config(as, &slave_config, 8)) + if (atmel_spi_dma_slave_config(as, &slave_config, + xfer->bits_per_word)) goto err_exit; /* Send both scatterlists */ @@ -871,14 +872,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, * Calculate the lowest divider that satisfies the * constraint, assuming div32/fdiv/mbz == 0. */ - if (xfer->speed_hz) - scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz); - else - /* - * This can happend if max_speed is null. - * In this case, we set the lowest possible speed - */ - scbr = 0xff; + scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz); /* * If the resulting divider doesn't fit into the @@ -1300,14 +1294,12 @@ static int atmel_spi_one_transfer(struct spi_master *master, return -EINVAL; } - if (xfer->bits_per_word) { - asd = spi->controller_state; - bits = (asd->csr >> 4) & 0xf; - if (bits != xfer->bits_per_word - 8) { - dev_dbg(&spi->dev, + asd = spi->controller_state; + bits = (asd->csr >> 4) & 0xf; + if (bits != xfer->bits_per_word - 8) { + dev_dbg(&spi->dev, "you can't yet change bits_per_word in transfers\n"); - return -ENOPROTOOPT; - } + return -ENOPROTOOPT; } /* @@ -1720,6 +1712,7 @@ static int atmel_spi_runtime_resume(struct device *dev) return clk_prepare_enable(as->clk); } +#ifdef CONFIG_PM_SLEEP static int atmel_spi_suspend(struct device *dev) { struct spi_master *master = dev_get_drvdata(dev); @@ -1756,6 +1749,7 @@ static int atmel_spi_resume(struct device *dev) return ret; } +#endif static const struct dev_pm_ops atmel_spi_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume) diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index f45e085c01a6..afd239d6dec1 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -233,13 +233,12 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) unsigned bpw, hz; u32 cfg, stat; - bpw = spi->bits_per_word; - hz = spi->max_speed_hz; if (t) { - if (t->bits_per_word) - bpw = t->bits_per_word; - if (t->speed_hz) - hz = t->speed_hz; + bpw = t->bits_per_word; + hz = t->speed_hz; + } else { + bpw = spi->bits_per_word; + hz = spi->max_speed_hz; } if (!hz) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index e7874a6171ec..cf04960cc3e6 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -386,14 +386,14 @@ static bool bcm2835_spi_can_dma(struct spi_master *master, /* otherwise we only allow transfers within the same page * to avoid wasting time on dma_mapping when it is not practical */ - if (((size_t)tfr->tx_buf & PAGE_MASK) + tfr->len > PAGE_SIZE) { + if (((size_t)tfr->tx_buf & (PAGE_SIZE - 1)) + tfr->len > PAGE_SIZE) { dev_warn_once(&spi->dev, "Unaligned spi tx-transfer bridging page\n"); return false; } - if (((size_t)tfr->rx_buf & PAGE_MASK) + tfr->len > PAGE_SIZE) { + if (((size_t)tfr->rx_buf & (PAGE_SIZE - 1)) + tfr->len > PAGE_SIZE) { dev_warn_once(&spi->dev, - "Unaligned spi tx-transfer bridging page\n"); + "Unaligned spi rx-transfer bridging page\n"); return false; } @@ -777,7 +777,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) goto out_master_put; } - bs->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; @@ -786,6 +786,12 @@ static int bcm2835_spi_probe(struct platform_device *pdev) clk_prepare_enable(bs->clk); + bcm2835_dma_init(master, &pdev->dev); + + /* initialise the hardware with the default polarities */ + bcm2835_wr(bs, BCM2835_SPI_CS, + BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); + err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, dev_name(&pdev->dev), master); if (err) { @@ -793,12 +799,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) goto out_clk_disable; } - bcm2835_dma_init(master, &pdev->dev); - - /* initialise the hardware with the default polarities */ - bcm2835_wr(bs, BCM2835_SPI_CS, - BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - err = devm_spi_register_master(&pdev->dev, master); if (err) { dev_err(&pdev->dev, "could not register SPI master: %d\n", err); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 3cf9faa6cc3f..7d3af3eacf57 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -215,18 +215,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) struct davinci_spi_config *spicfg = spi->controller_data; u8 chip_sel = spi->chip_select; u16 spidat1 = CS_DEFAULT; - bool gpio_chipsel = false; - int gpio; dspi = spi_master_get_devdata(spi->master); pdata = &dspi->pdata; - if (spi->cs_gpio >= 0) { - /* SPI core parse and update master->cs_gpio */ - gpio_chipsel = true; - gpio = spi->cs_gpio; - } - /* program delay transfers if tx_delay is non zero */ if (spicfg->wdelay) spidat1 |= SPIDAT1_WDEL; @@ -235,11 +227,12 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * Board specific chip select logic decides the polarity and cs * line for the controller */ - if (gpio_chipsel) { + if (spi->cs_gpio >= 0) { if (value == BITBANG_CS_ACTIVE) - gpio_set_value(gpio, spi->mode & SPI_CS_HIGH); + gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH); else - gpio_set_value(gpio, !(spi->mode & SPI_CS_HIGH)); + gpio_set_value(spi->cs_gpio, + !(spi->mode & SPI_CS_HIGH)); } else { if (value == BITBANG_CS_ACTIVE) { spidat1 |= SPIDAT1_CSHOLD_MASK; @@ -992,11 +985,12 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } - dspi->irq = platform_get_irq(pdev, 0); - if (dspi->irq <= 0) { + ret = platform_get_irq(pdev, 0); + if (ret == 0) ret = -EINVAL; + if (ret < 0) goto free_master; - } + dspi->irq = ret; ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq, dummy_thread_fn, 0, dev_name(&pdev->dev), dspi); diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index f9deb84e4e55..0e5723ab47f0 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -336,13 +336,20 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, if (config->mode & SPI_CPHA) cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs); + else + cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs); if (config->mode & SPI_CPOL) { cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs); + } else { + cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs); + cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs); } if (config->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); + else + cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c index 5468fc70dbf8..2465259f6241 100644 --- a/drivers/spi/spi-meson-spifc.c +++ b/drivers/spi/spi-meson-spifc.c @@ -444,6 +444,7 @@ static const struct of_device_id meson_spifc_dt_match[] = { { .compatible = "amlogic,meson6-spifc", }, { }, }; +MODULE_DEVICE_TABLE(of, meson_spifc_dt_match); static struct platform_driver meson_spifc_driver = { .probe = meson_spifc_probe, diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 5f6315c47920..ecb6c58238c4 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -85,7 +85,7 @@ struct mtk_spi { void __iomem *base; u32 state; u32 pad_sel; - struct clk *spi_clk, *parent_clk; + struct clk *parent_clk, *sel_clk, *spi_clk; struct spi_transfer *cur_transfer; u32 xfer_len; struct scatterlist *tx_sgl, *rx_sgl; @@ -173,22 +173,6 @@ static void mtk_spi_config(struct mtk_spi *mdata, writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG); } -static int mtk_spi_prepare_hardware(struct spi_master *master) -{ - struct spi_transfer *trans; - struct mtk_spi *mdata = spi_master_get_devdata(master); - struct spi_message *msg = master->cur_msg; - - trans = list_first_entry(&msg->transfers, struct spi_transfer, - transfer_list); - if (!trans->cs_change) { - mdata->state = MTK_SPI_IDLE; - mtk_spi_reset(mdata); - } - - return 0; -} - static int mtk_spi_prepare_message(struct spi_master *master, struct spi_message *msg) { @@ -228,11 +212,15 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) struct mtk_spi *mdata = spi_master_get_devdata(spi->master); reg_val = readl(mdata->base + SPI_CMD_REG); - if (!enable) + if (!enable) { reg_val |= SPI_CMD_PAUSE_EN; - else + writel(reg_val, mdata->base + SPI_CMD_REG); + } else { reg_val &= ~SPI_CMD_PAUSE_EN; - writel(reg_val, mdata->base + SPI_CMD_REG); + writel(reg_val, mdata->base + SPI_CMD_REG); + mdata->state = MTK_SPI_IDLE; + mtk_spi_reset(mdata); + } } static void mtk_spi_prepare_transfer(struct spi_master *master, @@ -509,7 +497,6 @@ static int mtk_spi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA; master->set_cs = mtk_spi_set_cs; - master->prepare_transfer_hardware = mtk_spi_prepare_hardware; master->prepare_message = mtk_spi_prepare_message; master->transfer_one = mtk_spi_transfer_one; master->can_dma = mtk_spi_can_dma; @@ -576,13 +563,6 @@ static int mtk_spi_probe(struct platform_device *pdev) goto err_put_master; } - mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk"); - if (IS_ERR(mdata->spi_clk)) { - ret = PTR_ERR(mdata->spi_clk); - dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret); - goto err_put_master; - } - mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk"); if (IS_ERR(mdata->parent_clk)) { ret = PTR_ERR(mdata->parent_clk); @@ -590,13 +570,27 @@ static int mtk_spi_probe(struct platform_device *pdev) goto err_put_master; } + mdata->sel_clk = devm_clk_get(&pdev->dev, "sel-clk"); + if (IS_ERR(mdata->sel_clk)) { + ret = PTR_ERR(mdata->sel_clk); + dev_err(&pdev->dev, "failed to get sel-clk: %d\n", ret); + goto err_put_master; + } + + mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk"); + if (IS_ERR(mdata->spi_clk)) { + ret = PTR_ERR(mdata->spi_clk); + dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret); + goto err_put_master; + } + ret = clk_prepare_enable(mdata->spi_clk); if (ret < 0) { dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret); goto err_put_master; } - ret = clk_set_parent(mdata->spi_clk, mdata->parent_clk); + ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); if (ret < 0) { dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); goto err_disable_clk; @@ -630,7 +624,6 @@ static int mtk_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); mtk_spi_reset(mdata); - clk_disable_unprepare(mdata->spi_clk); spi_master_put(master); return 0; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 3d09e0b69b73..1f8903d356e5 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1217,6 +1217,33 @@ out: return status; } +static int omap2_mcspi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi_regs *ctx = &mcspi->ctx; + struct omap2_mcspi_cs *cs; + + /* Only a single channel can have the FORCE bit enabled + * in its chconf0 register. + * Scan all channels and disable them except the current one. + * A FORCE can remain from a last transfer having cs_change enabled + */ + list_for_each_entry(cs, &ctx->cs, node) { + if (msg->spi->controller_state == cs) + continue; + + if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE)) { + cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; + writel_relaxed(cs->chconf0, + cs->base + OMAP2_MCSPI_CHCONF0); + readl_relaxed(cs->base + OMAP2_MCSPI_CHCONF0); + } + } + + return 0; +} + static int omap2_mcspi_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *t) { @@ -1344,6 +1371,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = omap2_mcspi_setup; master->auto_runtime_pm = true; + master->prepare_message = omap2_mcspi_prepare_message; master->transfer_one = omap2_mcspi_transfer_one; master->set_cs = omap2_mcspi_set_cs; master->cleanup = omap2_mcspi_cleanup; diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index fdd791977041..a8ef38ebb9c9 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -654,6 +654,10 @@ static irqreturn_t ssp_int(int irq, void *dev_id) if (!(sccr1_reg & SSCR1_TIE)) mask &= ~SSSR_TFS; + /* Ignore RX timeout interrupt if it is disabled */ + if (!(sccr1_reg & SSCR1_TINTE)) + mask &= ~SSSR_TINT; + if (!(status & mask)) return IRQ_NONE; diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index aa6d284131e0..81b84858cfee 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -410,11 +410,10 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, mutex_unlock(&qspi->list_lock); + ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); m->status = status; spi_finalize_current_message(master); - ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); - return status; } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index a339c1e9997a..3009121173cd 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -270,6 +270,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) while (remaining_words) { int n_words, tx_words, rx_words; + u32 sr; n_words = min(remaining_words, xspi->buffer_size); @@ -284,24 +285,33 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) if (use_irq) { xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); wait_for_completion(&xspi->done); - } else - while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) & - XSPI_SR_TX_EMPTY_MASK)) - ; - - /* A transmit has just completed. Process received data and - * check for more data to transmit. Always inhibit the - * transmitter while the Isr refills the transmit register/FIFO, - * or make sure it is stopped if we're done. - */ - if (use_irq) + /* A transmit has just completed. Process received data + * and check for more data to transmit. Always inhibit + * the transmitter while the Isr refills the transmit + * register/FIFO, or make sure it is stopped if we're + * done. + */ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, - xspi->regs + XSPI_CR_OFFSET); + xspi->regs + XSPI_CR_OFFSET); + sr = XSPI_SR_TX_EMPTY_MASK; + } else + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); /* Read out all the data from the Rx FIFO */ rx_words = n_words; - while (rx_words--) - xilinx_spi_rx(xspi); + while (rx_words) { + if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) { + xilinx_spi_rx(xspi); + rx_words--; + continue; + } + + sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); + if (!(sr & XSPI_SR_RX_EMPTY_MASK)) { + xilinx_spi_rx(xspi); + rx_words--; + } + } remaining_words -= n_words; } diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c index 2e32ea2f194f..be6155cba9de 100644 --- a/drivers/spi/spi-xtensa-xtfpga.c +++ b/drivers/spi/spi-xtensa-xtfpga.c @@ -34,13 +34,13 @@ struct xtfpga_spi { static inline void xtfpga_spi_write32(const struct xtfpga_spi *spi, unsigned addr, u32 val) { - iowrite32(val, spi->regs + addr); + __raw_writel(val, spi->regs + addr); } static inline unsigned int xtfpga_spi_read32(const struct xtfpga_spi *spi, unsigned addr) { - return ioread32(spi->regs + addr); + return __raw_readl(spi->regs + addr); } static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3abb3903f2ad..f9e92f535cbb 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -123,6 +123,28 @@ SPI_STATISTICS_SHOW(bytes, "%llu"); SPI_STATISTICS_SHOW(bytes_rx, "%llu"); SPI_STATISTICS_SHOW(bytes_tx, "%llu"); +#define SPI_STATISTICS_TRANSFER_BYTES_HISTO(index, number) \ + SPI_STATISTICS_SHOW_NAME(transfer_bytes_histo##index, \ + "transfer_bytes_histo_" number, \ + transfer_bytes_histo[index], "%lu") +SPI_STATISTICS_TRANSFER_BYTES_HISTO(0, "0-1"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(1, "2-3"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(2, "4-7"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(3, "8-15"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(4, "16-31"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(5, "32-63"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(6, "64-127"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(7, "128-255"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(8, "256-511"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(9, "512-1023"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(10, "1024-2047"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(11, "2048-4095"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(12, "4096-8191"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(13, "8192-16383"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535"); +SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+"); + static struct attribute *spi_dev_attrs[] = { &dev_attr_modalias.attr, NULL, @@ -143,6 +165,23 @@ static struct attribute *spi_device_statistics_attrs[] = { &dev_attr_spi_device_bytes.attr, &dev_attr_spi_device_bytes_rx.attr, &dev_attr_spi_device_bytes_tx.attr, + &dev_attr_spi_device_transfer_bytes_histo0.attr, + &dev_attr_spi_device_transfer_bytes_histo1.attr, + &dev_attr_spi_device_transfer_bytes_histo2.attr, + &dev_attr_spi_device_transfer_bytes_histo3.attr, + &dev_attr_spi_device_transfer_bytes_histo4.attr, + &dev_attr_spi_device_transfer_bytes_histo5.attr, + &dev_attr_spi_device_transfer_bytes_histo6.attr, + &dev_attr_spi_device_transfer_bytes_histo7.attr, + &dev_attr_spi_device_transfer_bytes_histo8.attr, + &dev_attr_spi_device_transfer_bytes_histo9.attr, + &dev_attr_spi_device_transfer_bytes_histo10.attr, + &dev_attr_spi_device_transfer_bytes_histo11.attr, + &dev_attr_spi_device_transfer_bytes_histo12.attr, + &dev_attr_spi_device_transfer_bytes_histo13.attr, + &dev_attr_spi_device_transfer_bytes_histo14.attr, + &dev_attr_spi_device_transfer_bytes_histo15.attr, + &dev_attr_spi_device_transfer_bytes_histo16.attr, NULL, }; @@ -168,6 +207,23 @@ static struct attribute *spi_master_statistics_attrs[] = { &dev_attr_spi_master_bytes.attr, &dev_attr_spi_master_bytes_rx.attr, &dev_attr_spi_master_bytes_tx.attr, + &dev_attr_spi_master_transfer_bytes_histo0.attr, + &dev_attr_spi_master_transfer_bytes_histo1.attr, + &dev_attr_spi_master_transfer_bytes_histo2.attr, + &dev_attr_spi_master_transfer_bytes_histo3.attr, + &dev_attr_spi_master_transfer_bytes_histo4.attr, + &dev_attr_spi_master_transfer_bytes_histo5.attr, + &dev_attr_spi_master_transfer_bytes_histo6.attr, + &dev_attr_spi_master_transfer_bytes_histo7.attr, + &dev_attr_spi_master_transfer_bytes_histo8.attr, + &dev_attr_spi_master_transfer_bytes_histo9.attr, + &dev_attr_spi_master_transfer_bytes_histo10.attr, + &dev_attr_spi_master_transfer_bytes_histo11.attr, + &dev_attr_spi_master_transfer_bytes_histo12.attr, + &dev_attr_spi_master_transfer_bytes_histo13.attr, + &dev_attr_spi_master_transfer_bytes_histo14.attr, + &dev_attr_spi_master_transfer_bytes_histo15.attr, + &dev_attr_spi_master_transfer_bytes_histo16.attr, NULL, }; @@ -186,10 +242,15 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, struct spi_master *master) { unsigned long flags; + int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1; + + if (l2len < 0) + l2len = 0; spin_lock_irqsave(&stats->lock, flags); stats->transfers++; + stats->transfer_bytes_histo[l2len]++; stats->bytes += xfer->len; if ((xfer->tx_buf) && @@ -270,15 +331,24 @@ EXPORT_SYMBOL_GPL(spi_bus_type); static int spi_drv_probe(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); + struct spi_device *spi = to_spi_device(dev); int ret; ret = of_clk_set_defaults(dev->of_node, false); if (ret) return ret; + if (dev->of_node) { + spi->irq = of_irq_get(dev->of_node, 0); + if (spi->irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (spi->irq < 0) + spi->irq = 0; + } + ret = dev_pm_domain_attach(dev, true); if (ret != -EPROBE_DEFER) { - ret = sdrv->probe(to_spi_device(dev)); + ret = sdrv->probe(spi); if (ret) dev_pm_domain_detach(dev, true); } @@ -308,6 +378,8 @@ static void spi_drv_shutdown(struct device *dev) * spi_register_driver - register a SPI driver * @sdrv: the driver to register * Context: can sleep + * + * Return: zero on success, else a negative error code. */ int spi_register_driver(struct spi_driver *sdrv) { @@ -359,7 +431,7 @@ static DEFINE_MUTEX(board_lock); * needs to discard the spi_device without adding it, then it should * call spi_dev_put() on it. * - * Returns a pointer to the new device, or NULL. + * Return: a pointer to the new device, or NULL. */ struct spi_device *spi_alloc_device(struct spi_master *master) { @@ -418,7 +490,7 @@ static int spi_dev_check(struct device *dev, void *data) * Companion function to spi_alloc_device. Devices allocated with * spi_alloc_device can be added onto the spi bus with this function. * - * Returns 0 on success; negative errno on failure + * Return: 0 on success; negative errno on failure */ int spi_add_device(struct spi_device *spi) { @@ -491,7 +563,7 @@ EXPORT_SYMBOL_GPL(spi_add_device); * this is exported so that for example a USB or parport based adapter * driver could add devices (which it would learn about out-of-band). * - * Returns the new device, or NULL. + * Return: the new device, or NULL. */ struct spi_device *spi_new_device(struct spi_master *master, struct spi_board_info *chip) @@ -563,6 +635,8 @@ static void spi_match_master_to_boardinfo(struct spi_master *master, * * The board info passed can safely be __initdata ... but be careful of * any embedded pointers (platform_data, etc), they're copied as-is. + * + * Return: zero on success, else a negative error code. */ int spi_register_board_info(struct spi_board_info const *info, unsigned n) { @@ -597,7 +671,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable) if (spi->mode & SPI_CS_HIGH) enable = !enable; - if (spi->cs_gpio >= 0) + if (gpio_is_valid(spi->cs_gpio)) gpio_set_value(spi->cs_gpio, !enable); else if (spi->master->set_cs) spi->master->set_cs(spi, !enable); @@ -1140,6 +1214,8 @@ static int spi_init_queue(struct spi_master *master) * * If there are more messages in the queue, the next message is returned from * this call. + * + * Return: the next message in the queue, else NULL if the queue is empty. */ struct spi_message *spi_get_next_queued_message(struct spi_master *master) { @@ -1303,6 +1379,8 @@ static int __spi_queued_transfer(struct spi_device *spi, * spi_queued_transfer - transfer function for queued transfers * @spi: spi device which is requesting transfer * @msg: spi message which is to handled is queued to driver queue + * + * Return: zero on success, else a negative error code. */ static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg) { @@ -1433,9 +1511,6 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc) } spi->max_speed_hz = value; - /* IRQ */ - spi->irq = irq_of_parse_and_map(nc, 0); - /* Store a pointer to the node in the device structure */ of_node_get(nc); spi->dev.of_node = nc; @@ -1605,13 +1680,13 @@ static struct class spi_master_class = { * only ones directly touching chip registers. It's how they allocate * an spi_master structure, prior to calling spi_register_master(). * - * This must be called from context that can sleep. It returns the SPI - * master structure on success, else NULL. + * This must be called from context that can sleep. * * The caller is responsible for assigning the bus number and initializing * the master's methods before calling spi_register_master(); and (after errors - * adding the device) calling spi_master_put() and kfree() to prevent a memory - * leak. + * adding the device) calling spi_master_put() to prevent a memory leak. + * + * Return: the SPI master structure on success, else NULL. */ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) { @@ -1695,6 +1770,8 @@ static int of_spi_register_master(struct spi_master *master) * success, else a negative error code (dropping the master's refcount). * After a successful return, the caller is responsible for calling * spi_unregister_master(). + * + * Return: zero on success, else a negative error code. */ int spi_register_master(struct spi_master *master) { @@ -1788,6 +1865,8 @@ static void devm_spi_unregister(struct device *dev, void *res) * * Register a SPI device as with spi_register_master() which will * automatically be unregister + * + * Return: zero on success, else a negative error code. */ int devm_spi_register_master(struct device *dev, struct spi_master *master) { @@ -1893,6 +1972,8 @@ static int __spi_master_match(struct device *dev, const void *data) * arch init time. It returns a refcounted pointer to the relevant * spi_master (which the caller must release), or NULL if there is * no such master registered. + * + * Return: the SPI master structure on success, else NULL. */ struct spi_master *spi_busnum_to_master(u16 bus_num) { @@ -1946,11 +2027,13 @@ static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_w * that the underlying controller or its driver does not support. For * example, not all hardware supports wire transfers using nine bit words, * LSB-first wire encoding, or active-high chipselects. + * + * Return: zero on success, else a negative error code. */ int spi_setup(struct spi_device *spi) { unsigned bad_bits, ugly_bits; - int status = 0; + int status; /* check mode to prevent that DUAL and QUAD set at the same time */ @@ -1987,17 +2070,18 @@ int spi_setup(struct spi_device *spi) if (!spi->bits_per_word) spi->bits_per_word = 8; - if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word)) - return -EINVAL; + status = __spi_validate_bits_per_word(spi->master, spi->bits_per_word); + if (status) + return status; if (!spi->max_speed_hz) spi->max_speed_hz = spi->master->max_speed_hz; - spi_set_cs(spi, false); - if (spi->master->setup) status = spi->master->setup(spi); + spi_set_cs(spi, false); + dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n", (int) (spi->mode & (SPI_CPOL | SPI_CPHA)), (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "", @@ -2163,6 +2247,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) * no other spi_message queued to that device will be processed. * (This rule applies equally to all the synchronous transfer calls, * which are wrappers around this core asynchronous primitive.) + * + * Return: zero on success, else a negative error code. */ int spi_async(struct spi_device *spi, struct spi_message *message) { @@ -2215,6 +2301,8 @@ EXPORT_SYMBOL_GPL(spi_async); * no other spi_message queued to that device will be processed. * (This rule applies equally to all the synchronous transfer calls, * which are wrappers around this core asynchronous primitive.) + * + * Return: zero on success, else a negative error code. */ int spi_async_locked(struct spi_device *spi, struct spi_message *message) { @@ -2330,7 +2418,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, * Also, the caller is guaranteeing that the memory associated with the * message will not be freed before this call returns. * - * It returns zero on success, else a negative error code. + * Return: zero on success, else a negative error code. */ int spi_sync(struct spi_device *spi, struct spi_message *message) { @@ -2352,7 +2440,7 @@ EXPORT_SYMBOL_GPL(spi_sync); * SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must * be released by a spi_bus_unlock call when the exclusive access is over. * - * It returns zero on success, else a negative error code. + * Return: zero on success, else a negative error code. */ int spi_sync_locked(struct spi_device *spi, struct spi_message *message) { @@ -2373,7 +2461,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked); * exclusive access is over. Data transfer must be done by spi_sync_locked * and spi_async_locked calls when the SPI bus lock is held. * - * It returns zero on success, else a negative error code. + * Return: always zero. */ int spi_bus_lock(struct spi_master *master) { @@ -2402,7 +2490,7 @@ EXPORT_SYMBOL_GPL(spi_bus_lock); * This call releases an SPI bus lock previously obtained by an spi_bus_lock * call. * - * It returns zero on success, else a negative error code. + * Return: always zero. */ int spi_bus_unlock(struct spi_master *master) { @@ -2437,6 +2525,8 @@ static u8 *buf; * portable code should never use this for more than 32 bytes. * Performance-sensitive or bulk transfer code should instead use * spi_{async,sync}() calls with dma-safe buffers. + * + * Return: zero on success, else a negative error code. */ int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx, diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index fba92a526531..ef008e52f953 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -651,7 +651,8 @@ static int spidev_release(struct inode *inode, struct file *filp) kfree(spidev->rx_buffer); spidev->rx_buffer = NULL; - spidev->speed_hz = spidev->spi->max_speed_hz; + if (spidev->spi) + spidev->speed_hz = spidev->spi->max_speed_hz; /* ... after we unbound from the underlying device? */ spin_lock_irq(&spidev->spi_lock); |