config SPI_CLPS711X
tristate "CLPS711X host SPI controller"
-------- depends on ARCH_CLPS711X
++++++++ depends on ARCH_CLPS711X || COMPILE_TEST
help
This enables dedicated general purpose SPI/Microwire1-compatible
master mode interface (SSI1) for CLPS711X-based CPUs.
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
-------- default m if IMX_HAVE_PLATFORM_SPI_IMX
help
This enables using the Freescale i.MX SPI controllers in master
mode.
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select SPI_BITBANG
++++++++ select REGMAP_MMIO
depends on SOC_VF610 || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
config SPI_OMAP24XX
tristate "McSPI driver for OMAP"
-------- depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
++++++++ depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SUPERH
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
SPI master controller for OMAP24XX and later Multichannel SPI
def_tristate SPI_PXA2XX && PCI
config SPI_RSPI
-------- tristate "Renesas RSPI controller"
++++++++ tristate "Renesas RSPI/QSPI controller"
depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
help
-------- SPI driver for Renesas RSPI blocks.
++++++++ SPI driver for Renesas RSPI and QSPI blocks.
++++++++
++++++++config SPI_QUP
++++++++ tristate "Qualcomm SPI controller with QUP interface"
++++++++ depends on ARCH_MSM_DT || (ARM && COMPILE_TEST)
++++++++ help
++++++++ Qualcomm Universal Peripheral (QUP) core is an AHB slave that
++++++++ provides a common data path (an output FIFO and an input FIFO)
++++++++ for serial peripheral interface (SPI) mini-core. SPI in master
++++++++ mode supports up to 50MHz, up to four chip selects, programmable
++++++++ data path from 4 bits to 32 bits and numerous protocol variants.
++++++++
++++++++ This driver can also be built as a module. If so, the module
++++++++ will be called spi_qup.
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
tristate "SuperH MSIOF SPI controller"
depends on HAVE_CLK
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
-------- select SPI_BITBANG
help
SPI driver for SuperH and SH Mobile MSIOF blocks.
help
SPI driver for CSR SiRFprimaII SoCs
+ +++++++config SPI_SUN4I
+ +++++++ tristate "Allwinner A10 SoCs SPI controller"
+ +++++++ depends on ARCH_SUNXI || COMPILE_TEST
+ +++++++ help
+ +++++++ SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+ +++++++
+ +++++++config SPI_SUN6I
+ +++++++ tristate "Allwinner A31 SPI controller"
+ +++++++ depends on ARCH_SUNXI || COMPILE_TEST
+ +++++++ depends on RESET_CONTROLLER
+ +++++++ help
+ +++++++ This enables using the SPI controller on the Allwinner A31 SoCs.
+ +++++++
config SPI_MXS
tristate "Freescale MXS SPI controller"
depends on ARCH_MXS
help
SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
---- ----config SPI_TI_SSP
---- ---- tristate "TI Sequencer Serial Port - SPI Support"
---- ---- depends on MFD_TI_SSP
---- ---- help
---- ---- This selects an SPI master implementation using a TI sequencer
---- ---- serial port.
---- ----
config SPI_TOPCLIFF_PCH
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
depends on PCI
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
-------- depends on SPI_DESIGNWARE && HAVE_CLK
++++++++ depends on SPI_DESIGNWARE
#
# There are lots of SPI device types, with sensors and memory
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
++++++++obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
+ +++++++obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
+ +++++++obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
---- ----obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o
obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/err.h>
--------#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
void __iomem *base;
phys_addr_t phys;
unsigned irq;
-------- u32 spi_max_frequency;
u32 cur_speed;
struct spi_device *cur_spi;
spi->mode & SPI_CPHA ? "" : "~",
spi->max_speed_hz);
-------- BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
--------
-------- /* Set speed to the spi max fequency if spi device has not set */
-------- spi->max_speed_hz = spi->max_speed_hz ? : tspi->spi_max_frequency;
--------
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs);
goto exit;
-- ------ } else if (msg->transfers.prev == &xfer->transfer_list) {
-- ------ /* This is the last transfer in message */
++ ++++++ } else if (list_is_last(&xfer->transfer_list,
++ ++++++ &msg->transfers)) {
if (xfer->cs_change)
tspi->cs_control = spi;
else {
return IRQ_WAKE_THREAD;
}
--------static void tegra_spi_parse_dt(struct platform_device *pdev,
-------- struct tegra_spi_data *tspi)
--------{
-------- struct device_node *np = pdev->dev.of_node;
--------
-------- if (of_property_read_u32(np, "spi-max-frequency",
-------- &tspi->spi_max_frequency))
-------- tspi->spi_max_frequency = 25000000; /* 25MHz */
--------}
--------
static struct of_device_id tegra_spi_of_match[] = {
{ .compatible = "nvidia,tegra114-spi", },
{}
platform_set_drvdata(pdev, master);
tspi = spi_master_get_devdata(master);
-------- /* Parse DT */
-------- tegra_spi_parse_dt(pdev, tspi);
++++++++ if (of_property_read_u32(pdev->dev.of_node, "spi-max-frequency",
++++++++ &master->max_speed_hz))
++++++++ master->max_speed_hz = 25000000; /* 25MHz */
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->setup = tegra_spi_setup;
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
-------- master->bus_num = -1;
master->auto_runtime_pm = true;
tspi->master = master;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD;
-------- master->bus_num = -1;
master->flags = SPI_MASTER_HALF_DUPLEX;
master->setup = ti_qspi_setup;
master->auto_runtime_pm = true;
master->transfer_one_message = ti_qspi_start_transfer_one;
master->dev.of_node = pdev->dev.of_node;
-------- master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
++++++++ master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
++++++++ SPI_BPW_MASK(8);
if (!of_property_read_u32(np, "num-cs", &num_cs))
master->num_chipselect = num_cs;
if (res_mmap == NULL) {
dev_err(&pdev->dev,
"memory mapped resource not required\n");
--- ----- return -ENODEV;
}
}
data->transfer_active = false;
wake_up(&data->wait);
} else {
----- --- dev_err(&data->master->dev,
+++++ +++ dev_vdbg(&data->master->dev,
"%s : Transfer is not completed",
__func__);
}
pch_spi_writereg(master, PCH_SRST, 0x0);
}
----- ---static int pch_spi_setup(struct spi_device *pspi)
----- ---{
----- --- /* Check baud rate setting */
----- --- /* if baud rate of chip is greater than
----- --- max we can support,return error */
----- --- if ((pspi->max_speed_hz) > PCH_MAX_BAUDRATE)
----- --- pspi->max_speed_hz = PCH_MAX_BAUDRATE;
----- ---
----- --- dev_dbg(&pspi->dev, "%s MODE = %x\n", __func__,
----- --- (pspi->mode) & (SPI_CPOL | SPI_CPHA));
----- ---
----- --- return 0;
----- ---}
----- ---
static int pch_spi_transfer(struct spi_device *pspi, struct spi_message *pmsg)
{
int retval;
unsigned long flags;
----- --- /* validate spi message and baud rate */
----- --- if (unlikely(list_empty(&pmsg->transfers) == 1)) {
----- --- dev_err(&pspi->dev, "%s list empty\n", __func__);
----- --- retval = -EINVAL;
----- --- goto err_out;
----- --- }
----- ---
----- --- if (unlikely(pspi->max_speed_hz == 0)) {
----- --- dev_err(&pspi->dev, "%s pch_spi_transfer maxspeed=%d\n",
----- --- __func__, pspi->max_speed_hz);
----- --- retval = -EINVAL;
----- --- goto err_out;
----- --- }
----- ---
----- --- dev_dbg(&pspi->dev,
----- --- "%s Transfer List not empty. Transfer Speed is set.\n", __func__);
----- ---
spin_lock_irqsave(&data->lock, flags);
/* validate Tx/Rx buffers and Transfer length */
list_for_each_entry(transfer, &pmsg->transfers, transfer_list) {
dev_dbg(&pspi->dev,
"%s Tx/Rx buffer valid. Transfer length valid\n",
__func__);
----- ---
----- --- /* if baud rate has been specified validate the same */
----- --- if (transfer->speed_hz > PCH_MAX_BAUDRATE)
----- --- transfer->speed_hz = PCH_MAX_BAUDRATE;
}
spin_unlock_irqrestore(&data->lock, flags);
/* Set Tx DMA */
param = &dma->param_tx;
param->dma_dev = &dma_dev->dev;
-------- param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
++++++++ param->chan_id = data->ch * 2; /* Tx = 0, 2 */;
param->tx_reg = data->io_base_addr + PCH_SPDWR;
param->width = width;
chan = dma_request_channel(mask, pch_spi_filter, param);
/* Set Rx DMA */
param = &dma->param_rx;
param->dma_dev = &dma_dev->dev;
-------- param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
++++++++ param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */;
param->rx_reg = data->io_base_addr + PCH_SPDRR;
param->width = width;
chan = dma_request_channel(mask, pch_spi_filter, param);
dma->nent = num;
dma->desc_tx = desc_tx;
----- --- dev_dbg(&data->master->dev, "\n%s:Pulling down SSN low - writing "
----- --- "0x2 to SSNXCR\n", __func__);
+++++ +++ dev_dbg(&data->master->dev, "%s:Pulling down SSN low - writing 0x2 to SSNXCR\n", __func__);
spin_lock_irqsave(&data->lock, flags);
pch_spi_writereg(data->master, PCH_SSNXCR, SSN_LOW);
/* initialize members of SPI master */
master->num_chipselect = PCH_MAX_CS;
----- --- master->setup = pch_spi_setup;
master->transfer = pch_spi_transfer;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
+++++ +++ master->max_speed_hz = PCH_MAX_BAUDRATE;
data->board_dat = board_dat;
data->plat_dev = plat_dev;
pch_spi_set_master_mode(master);
++++++++ if (use_dma) {
++++++++ dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
++++++++ pch_alloc_dma_buf(board_dat, data);
++++++++ }
++++++++
ret = spi_register_master(master);
if (ret != 0) {
dev_err(&plat_dev->dev,
goto err_spi_register_master;
}
-------- if (use_dma) {
-------- dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
-------- pch_alloc_dma_buf(board_dat, data);
-------- }
--------
return 0;
err_spi_register_master:
++++++++ pch_free_dma_buf(board_dat, data);
free_irq(board_dat->pdev->irq, data);
err_request_irq:
pch_spi_free_resources(board_dat, data);
.resume = pch_spi_pd_resume
};
----- ---static int pch_spi_probe(struct pci_dev *pdev,
----- --- const struct pci_device_id *id)
+++++ +++static int pch_spi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct pch_spi_board_data *board_dat;
struct platform_device *pd_dev = NULL;
return 0;
err_platform_device:
+++++ +++ while (--i >= 0)
+++++ +++ platform_device_unregister(pd_dev_save->pd_save[i]);
pci_disable_device(pdev);
pci_enable_device:
pci_release_regions(pdev);
*/
#include <linux/kernel.h>
--------#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm,
struct spi_device *spi, struct spi_transfer *t, unsigned int *settings)
{
------- - unsigned int speed;
------- -
if (t->len > 62)
return -EINVAL;
------- - speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+++++++ + if (t->speed_hz != spi_xcomm->current_speed) {
+++++++ + unsigned int divider;
------- - if (speed != spi_xcomm->current_speed) {
------- - unsigned int divider = DIV_ROUND_UP(SPI_XCOMM_CLOCK, speed);
+++++++ + divider = DIV_ROUND_UP(SPI_XCOMM_CLOCK, t->speed_hz);
if (divider >= 64)
*settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_64;
else if (divider >= 16)
else
*settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_4;
------- - spi_xcomm->current_speed = speed;
+++++++ + spi_xcomm->current_speed = t->speed_hz;
}
if (spi->mode & SPI_CPOL)
int status = 0;
bool is_last;
------- - is_first = true;
------- -
spi_xcomm_chipselect(spi_xcomm, spi, true);
list_for_each_entry(t, &msg->transfers, transfer_list) {
#include <linux/device.h>
#include <linux/init.h>
#include <linux/cache.h>
++++++++#include <linux/dma-mapping.h>
++++++++#include <linux/dmaengine.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
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;
-------- acpi_dev_pm_attach(&spi->dev, true);
-------- ret = sdrv->probe(spi);
++++++++ acpi_dev_pm_attach(dev, true);
++++++++ ret = sdrv->probe(to_spi_device(dev));
if (ret)
-------- acpi_dev_pm_detach(&spi->dev, true);
++++++++ acpi_dev_pm_detach(dev, true);
return ret;
}
static int spi_drv_remove(struct device *dev)
{
const struct spi_driver *sdrv = to_spi_driver(dev->driver);
-------- struct spi_device *spi = to_spi_device(dev);
int ret;
-------- ret = sdrv->remove(spi);
-------- acpi_dev_pm_detach(&spi->dev, true);
++++++++ ret = sdrv->remove(to_spi_device(dev));
++++++++ acpi_dev_pm_detach(dev, true);
return ret;
}
spi->master->set_cs(spi, !enable);
}
++++++++static int spi_map_buf(struct spi_master *master, struct device *dev,
++++++++ struct sg_table *sgt, void *buf, size_t len,
++++++++ enum dma_data_direction dir)
++++++++{
++++++++ const bool vmalloced_buf = is_vmalloc_addr(buf);
++++++++ const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len;
++++++++ const int sgs = DIV_ROUND_UP(len, desc_len);
++++++++ struct page *vm_page;
++++++++ void *sg_buf;
++++++++ size_t min;
++++++++ int i, ret;
++++++++
++++++++ ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
++++++++ if (ret != 0)
++++++++ return ret;
++++++++
++++++++ for (i = 0; i < sgs; i++) {
++++++++ min = min_t(size_t, len, desc_len);
++++++++
++++++++ if (vmalloced_buf) {
++++++++ vm_page = vmalloc_to_page(buf);
++++++++ if (!vm_page) {
++++++++ sg_free_table(sgt);
++++++++ return -ENOMEM;
++++++++ }
++++++++ sg_buf = page_address(vm_page) +
++++++++ ((size_t)buf & ~PAGE_MASK);
++++++++ } else {
++++++++ sg_buf = buf;
++++++++ }
++++++++
++++++++ sg_set_buf(&sgt->sgl[i], sg_buf, min);
++++++++
++++++++ buf += min;
++++++++ len -= min;
++++++++ }
++++++++
++++++++ ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
++++++++ if (ret < 0) {
++++++++ sg_free_table(sgt);
++++++++ return ret;
++++++++ }
++++++++
++++++++ sgt->nents = ret;
++++++++
++++++++ return 0;
++++++++}
++++++++
++++++++static void spi_unmap_buf(struct spi_master *master, struct device *dev,
++++++++ struct sg_table *sgt, enum dma_data_direction dir)
++++++++{
++++++++ if (sgt->orig_nents) {
++++++++ dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
++++++++ sg_free_table(sgt);
++++++++ }
++++++++}
++++++++
++++++++static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
++++++++{
++++++++ struct device *tx_dev, *rx_dev;
++++++++ struct spi_transfer *xfer;
++++++++ void *tmp;
++++++++ unsigned int max_tx, max_rx;
++++++++ int ret;
++++++++
++++++++ if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) {
++++++++ max_tx = 0;
++++++++ max_rx = 0;
++++++++
++++++++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++++++++ if ((master->flags & SPI_MASTER_MUST_TX) &&
++++++++ !xfer->tx_buf)
++++++++ max_tx = max(xfer->len, max_tx);
++++++++ if ((master->flags & SPI_MASTER_MUST_RX) &&
++++++++ !xfer->rx_buf)
++++++++ max_rx = max(xfer->len, max_rx);
++++++++ }
++++++++
++++++++ if (max_tx) {
++++++++ tmp = krealloc(master->dummy_tx, max_tx,
++++++++ GFP_KERNEL | GFP_DMA);
++++++++ if (!tmp)
++++++++ return -ENOMEM;
++++++++ master->dummy_tx = tmp;
++++++++ memset(tmp, 0, max_tx);
++++++++ }
++++++++
++++++++ if (max_rx) {
++++++++ tmp = krealloc(master->dummy_rx, max_rx,
++++++++ GFP_KERNEL | GFP_DMA);
++++++++ if (!tmp)
++++++++ return -ENOMEM;
++++++++ master->dummy_rx = tmp;
++++++++ }
++++++++
++++++++ if (max_tx || max_rx) {
++++++++ list_for_each_entry(xfer, &msg->transfers,
++++++++ transfer_list) {
++++++++ if (!xfer->tx_buf)
++++++++ xfer->tx_buf = master->dummy_tx;
++++++++ if (!xfer->rx_buf)
++++++++ xfer->rx_buf = master->dummy_rx;
++++++++ }
++++++++ }
++++++++ }
++++++++
++++++++ if (!master->can_dma)
++++++++ return 0;
++++++++
++++++++ tx_dev = &master->dma_tx->dev->device;
++++++++ rx_dev = &master->dma_rx->dev->device;
++++++++
++++++++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++++++++ if (!master->can_dma(master, msg->spi, xfer))
++++++++ continue;
++++++++
++++++++ if (xfer->tx_buf != NULL) {
++++++++ ret = spi_map_buf(master, tx_dev, &xfer->tx_sg,
++++++++ (void *)xfer->tx_buf, xfer->len,
++++++++ DMA_TO_DEVICE);
++++++++ if (ret != 0)
++++++++ return ret;
++++++++ }
++++++++
++++++++ if (xfer->rx_buf != NULL) {
++++++++ ret = spi_map_buf(master, rx_dev, &xfer->rx_sg,
++++++++ xfer->rx_buf, xfer->len,
++++++++ DMA_FROM_DEVICE);
++++++++ if (ret != 0) {
++++++++ spi_unmap_buf(master, tx_dev, &xfer->tx_sg,
++++++++ DMA_TO_DEVICE);
++++++++ return ret;
++++++++ }
++++++++ }
++++++++ }
++++++++
++++++++ master->cur_msg_mapped = true;
++++++++
++++++++ return 0;
++++++++}
++++++++
++++++++static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
++++++++{
++++++++ struct spi_transfer *xfer;
++++++++ struct device *tx_dev, *rx_dev;
++++++++
++++++++ if (!master->cur_msg_mapped || !master->can_dma)
++++++++ return 0;
++++++++
++++++++ tx_dev = &master->dma_tx->dev->device;
++++++++ rx_dev = &master->dma_rx->dev->device;
++++++++
++++++++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++++++++ if (!master->can_dma(master, msg->spi, xfer))
++++++++ continue;
++++++++
++++++++ spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
++++++++ spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
++++++++ }
++++++++
++++++++ return 0;
++++++++}
++++++++
/*
* spi_transfer_one_message - Default implementation of transfer_one_message()
*
struct spi_message *msg)
{
struct spi_transfer *xfer;
-------- bool cur_cs = true;
bool keep_cs = false;
int ret = 0;
++++++++ int ms = 1;
spi_set_cs(msg->spi, true);
if (ret > 0) {
ret = 0;
-------- wait_for_completion(&master->xfer_completion);
++++++++ ms = xfer->len * 8 * 1000 / xfer->speed_hz;
++++++++ ms += 10; /* some tolerance */
++++++++
++++++++ ms = wait_for_completion_timeout(&master->xfer_completion,
++++++++ msecs_to_jiffies(ms));
++++++++ }
++++++++
++++++++ if (ms == 0) {
++++++++ dev_err(&msg->spi->dev, "SPI transfer timed out\n");
++++++++ msg->status = -ETIMEDOUT;
}
trace_spi_transfer_stop(msg, xfer);
&msg->transfers)) {
keep_cs = true;
} else {
-------- cur_cs = !cur_cs;
-------- spi_set_cs(msg->spi, cur_cs);
++++++++ spi_set_cs(msg->spi, false);
++++++++ udelay(10);
++++++++ spi_set_cs(msg->spi, true);
}
}
}
master->busy = false;
spin_unlock_irqrestore(&master->queue_lock, flags);
++++++++ kfree(master->dummy_rx);
++++++++ master->dummy_rx = NULL;
++++++++ kfree(master->dummy_tx);
++++++++ master->dummy_tx = NULL;
if (master->unprepare_transfer_hardware &&
master->unprepare_transfer_hardware(master))
dev_err(&master->dev,
master->cur_msg_prepared = true;
}
-------- ret = master->transfer_one_message(master, master->cur_msg);
++++++++ ret = spi_map_msg(master, master->cur_msg);
if (ret) {
-------- dev_err(&master->dev,
-------- "failed to transfer one message from queue: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
return;
}
++++++++
++++++++ ret = master->transfer_one_message(master, master->cur_msg);
++++++++ if (ret) {
++++++++ dev_err(&master->dev,
++++++++ "failed to transfer one message from queue\n");
++++++++ return;
++++++++ }
}
static int spi_init_queue(struct spi_master *master)
queue_kthread_work(&master->kworker, &master->pump_messages);
spin_unlock_irqrestore(&master->queue_lock, flags);
++++++++ spi_unmap_msg(master, mesg);
++++++++
if (master->cur_msg_prepared && master->unprepare_message) {
ret = master->unprepare_message(master, mesg);
if (ret) {
*/
while ((!list_empty(&master->queue) || master->busy) && limit--) {
spin_unlock_irqrestore(&master->queue_lock, flags);
-------- msleep(10);
++++++++ usleep_range(10000, 11000);
spin_lock_irqsave(&master->queue_lock, flags);
}
mutex_init(&master->bus_lock_mutex);
master->bus_lock_flag = 0;
init_completion(&master->xfer_completion);
++++++++ if (!master->max_dma_len)
++++++++ master->max_dma_len = INT_MAX;
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
if (!spi->bits_per_word)
spi->bits_per_word = 8;
++++++++ if (!spi->max_speed_hz)
++++++++ spi->max_speed_hz = spi->master->max_speed_hz;
++++++++
if (spi->master->setup)
status = spi->master->setup(spi);
{
struct spi_master *master = spi->master;
struct spi_transfer *xfer;
++++++++ int w_size;
if (list_empty(&message->transfers))
return -EINVAL;
-------- if (!message->complete)
-------- return -EINVAL;
/* Half-duplex links include original MicroWire, and ones with
* only one data pin like SPI_3WIRE (switches direction) or where
message->frame_length += xfer->len;
if (!xfer->bits_per_word)
xfer->bits_per_word = spi->bits_per_word;
-------- if (!xfer->speed_hz) {
++++++++
++++++++ if (!xfer->speed_hz)
xfer->speed_hz = spi->max_speed_hz;
-------- if (master->max_speed_hz &&
-------- xfer->speed_hz > master->max_speed_hz)
-------- xfer->speed_hz = master->max_speed_hz;
-------- }
++++++++
++++++++ if (master->max_speed_hz &&
++++++++ xfer->speed_hz > master->max_speed_hz)
++++++++ xfer->speed_hz = master->max_speed_hz;
if (master->bits_per_word_mask) {
/* Only 32 bits fit in the mask */
return -EINVAL;
}
++++++++ /*
++++++++ * SPI transfer length should be multiple of SPI word size
++++++++ * where SPI word size should be power-of-two multiple
++++++++ */
++++++++ if (xfer->bits_per_word <= 8)
++++++++ w_size = 1;
++++++++ else if (xfer->bits_per_word <= 16)
++++++++ w_size = 2;
++++++++ else
++++++++ w_size = 4;
++++++++
++++++++ /* No partial transfers accepted */
++++++++ if (xfer->len % w_size)
++++++++ return -EINVAL;
++++++++
if (xfer->speed_hz && master->min_speed_hz &&
xfer->speed_hz < master->min_speed_hz)
return -EINVAL;
-------- if (xfer->speed_hz && master->max_speed_hz &&
-------- xfer->speed_hz > master->max_speed_hz)
-------- return -EINVAL;
if (xfer->tx_buf && !xfer->tx_nbits)
xfer->tx_nbits = SPI_NBITS_SINGLE;