config SPI_ATMEL
tristate "Atmel SPI Controller"
- depends on (ARCH_AT91 || AVR32)
+ depends on (ARCH_AT91 || AVR32 || COMPILE_TEST)
help
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_BCM2835
tristate "BCM2835 SPI controller"
- depends on ARCH_BCM2835
+ depends on ARCH_BCM2835 || COMPILE_TEST
help
This selects a driver for the Broadcom BCM2835 SPI master.
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
- depends on BLACKFIN
+ depends on BLACKFIN && !BF60x
help
This is the SPI controller master driver for Blackfin 5xx processor.
+config SPI_BFIN_V3
+ tristate "SPI controller v3 for Blackfin"
+ depends on BF60x
+ help
+ This is the SPI controller v3 master driver
+ found on Blackfin 60x processor.
+
config SPI_BFIN_SPORT
tristate "SPI bus via Blackfin SPORT"
depends on BLACKFIN
config SPI_DAVINCI
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
- depends on ARCH_DAVINCI
+ depends on ARCH_DAVINCI || ARCH_KEYSTONE
select SPI_BITBANG
select TI_EDMA
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
+config SPI_EFM32
+ tristate "EFM32 SPI controller"
+ depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+ select SPI_BITBANG
+ help
+ Driver for the spi controller found on Energy Micro's EFM32 SoCs.
+
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
- depends on ARCH_EP93XX
+ depends on ARCH_EP93XX || COMPILE_TEST
help
This enables using the Cirrus EP93xx SPI controller in master
mode.
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
- depends on ARCH_MXC
+ depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
default m if IMX_HAVE_PLATFORM_SPI_IMX
help
This also enables using the Aeroflex Gaisler GRLIB SPI controller in
master mode.
+config SPI_FSL_DSPI
+ tristate "Freescale DSPI controller"
+ select SPI_BITBANG
+ help
+ This enables support for the Freescale DSPI controller in master
+ mode. VF610 platform uses the controller.
+
config SPI_FSL_ESPI
bool "Freescale eSPI controller"
depends on FSL_SOC
config SPI_OMAP24XX
tristate "McSPI driver for OMAP"
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
SPI master controller for OMAP24XX and later Multichannel SPI
(McSPI) modules.
+ config SPI_TI_QSPI
+ tristate "DRA7xxx QSPI controller support"
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ help
+ QSPI master controller for DRA7xxx used for flash devices.
+ This device supports single, dual and quad read support, while
+ it only supports single write mode.
+
config SPI_OMAP_100K
tristate "OMAP SPI 100K"
- depends on ARCH_OMAP850 || ARCH_OMAP730
+ depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST
help
OMAP SPI 100K master controller for omap7xx boards.
config SPI_ORION
tristate "Orion SPI master"
- depends on PLAT_ORION
+ depends on PLAT_ORION || COMPILE_TEST
help
This enables using the SPI master controller on the Orion chips.
config SPI_RSPI
tristate "Renesas RSPI controller"
- depends on SUPERH
+ depends on SUPERH && SH_DMAE_BASE
help
SPI driver for Renesas RSPI blocks.
config SPI_SH
tristate "SuperH SPI controller"
- depends on SUPERH
+ depends on SUPERH || COMPILE_TEST
help
SPI driver for SuperH SPI blocks.
config SPI_SH_HSPI
tristate "SuperH HSPI controller"
- depends on ARCH_SHMOBILE
+ depends on ARCH_SHMOBILE || COMPILE_TEST
help
SPI driver for SuperH HSPI blocks.
config SPI_TEGRA114
tristate "NVIDIA Tegra114 SPI Controller"
- depends on ARCH_TEGRA && TEGRA20_APB_DMA
+ depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
help
SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller
is different than the older SoCs SPI controller and also register interface
config SPI_TEGRA20_SFLASH
tristate "Nvidia Tegra20 Serial flash Controller"
- depends on ARCH_TEGRA
+ depends on ARCH_TEGRA || COMPILE_TEST
help
SPI driver for Nvidia Tegra20 Serial flash Controller interface.
The main usecase of this controller is to use spi flash as boot
config SPI_TEGRA20_SLINK
tristate "Nvidia Tegra20/Tegra30 SLINK Controller"
- depends on ARCH_TEGRA && TEGRA20_APB_DMA
+ depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
help
SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface.
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
- depends on GPIOLIB && CPU_TX49XX
+ depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST)
help
SPI driver for Toshiba TXx9 MIPS SoCs
obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
+obj-$(CONFIG_SPI_EFM32) += spi-efm32.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o
+obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
+ obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
return 0;
}
- static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
- {
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(&bs->pdev->dev);
-
- return 0;
- }
-
- static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
- {
- struct bcm63xx_spi *bs = spi_master_get_devdata(master);
-
- pm_runtime_put(&bs->pdev->dev);
-
- return 0;
- }
-
static int bcm63xx_spi_transfer_one(struct spi_master *master,
struct spi_message *m)
{
{
struct resource *r;
struct device *dev = &pdev->dev;
- struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
+ struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
int irq;
struct spi_master *master;
struct clk *clk;
struct bcm63xx_spi *bs;
int ret;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(dev, "no iomem\n");
- ret = -ENXIO;
- goto out;
- }
-
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq\n");
platform_set_drvdata(pdev, master);
bs->pdev = pdev;
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bs->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(bs->regs)) {
ret = PTR_ERR(bs->regs);
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
- master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
- master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
master->transfer_one_message = bcm63xx_spi_transfer_one;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->auto_runtime_pm = true;
bs->msg_type_shift = pdata->msg_type_shift;
bs->msg_ctl_width = pdata->msg_ctl_width;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
#ifdef CONFIG_PM
static int bcm63xx_spi_suspend(struct device *dev)
{
- struct spi_master *master =
- platform_get_drvdata(to_platform_device(dev));
+ struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
spi_master_suspend(master);
static int bcm63xx_spi_resume(struct device *dev)
{
- struct spi_master *master =
- platform_get_drvdata(to_platform_device(dev));
+ struct spi_master *master = dev_get_drvdata(dev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
clk_prepare_enable(bs->clk);
}
- static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
- {
- struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(mcfqspi->dev);
-
- return 0;
- }
-
- static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
- {
- struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
-
- pm_runtime_put_sync(mcfqspi->dev);
-
- return 0;
- }
-
static int mcfqspi_setup(struct spi_device *spi)
{
if (spi->chip_select >= spi->master->num_chipselect) {
struct mcfqspi_platform_data *pdata;
int status;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_dbg(&pdev->dev, "platform data is missing\n");
return -ENOENT;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
master->setup = mcfqspi_setup;
master->transfer_one_message = mcfqspi_transfer_one_message;
- master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw;
- master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw;
+ master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master);
#ifdef CONFIG_PM_RUNTIME
static int mcfqspi_runtime_suspend(struct device *dev)
{
- struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+ struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
clk_disable(mcfqspi->clk);
static int mcfqspi_runtime_resume(struct device *dev)
{
- struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+ struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
clk_enable(mcfqspi->clk);
__raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
}
- static int omap2_prepare_transfer(struct spi_master *master)
- {
- struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(mcspi->dev);
- return 0;
- }
-
- static int omap2_unprepare_transfer(struct spi_master *master)
- {
- struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-
- pm_runtime_mark_last_busy(mcspi->dev);
- pm_runtime_put_autosuspend(mcspi->dev);
- return 0;
- }
-
static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
{
unsigned long timeout;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = omap2_mcspi_setup;
- master->prepare_transfer_hardware = omap2_prepare_transfer;
- master->unprepare_transfer_hardware = omap2_unprepare_transfer;
+ master->auto_runtime_pm = true;
master->transfer_one_message = omap2_mcspi_transfer_one_message;
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
} else {
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
master->num_chipselect = pdata->num_cs;
if (pdev->id != -1)
master->bus_num = pdev->id;
return 0;
}
- static int pl022_prepare_transfer_hardware(struct spi_master *master)
- {
- struct pl022 *pl022 = spi_master_get_devdata(master);
-
- /*
- * Just make sure we have all we need to run the transfer by syncing
- * with the runtime PM framework.
- */
- pm_runtime_get_sync(&pl022->adev->dev);
- return 0;
- }
-
static int pl022_unprepare_transfer_hardware(struct spi_master *master)
{
struct pl022 *pl022 = spi_master_get_devdata(master);
writew((readw(SSP_CR1(pl022->virtbase)) &
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
- if (pl022->master_info->autosuspend_delay > 0) {
- pm_runtime_mark_last_busy(&pl022->adev->dev);
- pm_runtime_put_autosuspend(&pl022->adev->dev);
- } else {
- pm_runtime_put(&pl022->adev->dev);
- }
-
return 0;
}
static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
- struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+ struct pl022_ssp_controller *platform_info =
+ dev_get_platdata(&adev->dev);
struct spi_master *master;
struct pl022 *pl022 = NULL; /*Data for this driver */
struct device_node *np = adev->dev.of_node;
master->num_chipselect = num_cs;
master->cleanup = pl022_cleanup;
master->setup = pl022_setup;
- master->prepare_transfer_hardware = pl022_prepare_transfer_hardware;
+ master->auto_runtime_pm = true;
master->transfer_one_message = pl022_transfer_one_message;
master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
master->rt = platform_info->rt;
status = -ENOMEM;
goto err_no_ioremap;
}
- printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
- adev->res.start, pl022->virtbase);
+ printk(KERN_INFO "pl022: mapped registers from %pa to %p\n",
+ &adev->res.start, pl022->virtbase);
pl022->clk = devm_clk_get(&adev->dev, NULL);
if (IS_ERR(pl022->clk)) {
#define LPSS_TX_HITHRESH_DFLT 224
/* Offset from drv_data->lpss_base */
+#define GENERAL_REG 0x08
+#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
#define SSP_REG 0x0c
#define SPI_CS_CONTROL 0x18
#define SPI_CS_CONTROL_SW_MODE BIT(0)
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
/* Enable multiblock DMA transfers */
- if (drv_data->master_info->enable_dma)
+ if (drv_data->master_info->enable_dma) {
__lpss_ssp_write_priv(drv_data, SSP_REG, 1);
+
+ value = __lpss_ssp_read_priv(drv_data, GENERAL_REG);
+ value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE;
+ __lpss_ssp_write_priv(drv_data, GENERAL_REG, value);
+ }
}
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
return 0;
}
- static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
- {
- struct driver_data *drv_data = spi_master_get_devdata(master);
-
- pm_runtime_get_sync(&drv_data->pdev->dev);
- return 0;
- }
-
static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
{
struct driver_data *drv_data = spi_master_get_devdata(master);
write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
drv_data->ioaddr);
- pm_runtime_mark_last_busy(&drv_data->pdev->dev);
- pm_runtime_put_autosuspend(&drv_data->pdev->dev);
return 0;
}
master->cleanup = cleanup;
master->setup = setup;
master->transfer_one_message = pxa2xx_spi_transfer_one_message;
- master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
+ master->auto_runtime_pm = true;
drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
while (!is_polling(sdd) && !acquire_dma(sdd))
usleep_range(10000, 11000);
- pm_runtime_get_sync(&sdd->pdev->dev);
-
return 0;
}
sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
&s3c64xx_spi_dma_client);
}
- pm_runtime_put(&sdd->pdev->dev);
return 0;
}
#else
static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
{
- return dev->platform_data;
+ return dev_get_platdata(dev);
}
#endif
struct resource *mem_res;
struct resource *res;
struct s3c64xx_spi_driver_data *sdd;
- struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
+ struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev);
struct spi_master *master;
int ret, irq;
char clk_name[16];
SPI_BPW_MASK(8);
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ master->auto_runtime_pm = true;
sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(sdd->regs)) {
master->unprepare_transfer_hardware(master))
dev_err(&master->dev,
"failed to unprepare transfer hardware\n");
+ if (master->auto_runtime_pm) {
+ pm_runtime_mark_last_busy(master->dev.parent);
+ pm_runtime_put_autosuspend(master->dev.parent);
+ }
return;
}
master->busy = true;
spin_unlock_irqrestore(&master->queue_lock, flags);
+ if (!was_busy && master->auto_runtime_pm) {
+ ret = pm_runtime_get_sync(master->dev.parent);
+ if (ret < 0) {
+ dev_err(&master->dev, "Failed to power device: %d\n",
+ ret);
+ return;
+ }
+ }
+
if (!was_busy && master->prepare_transfer_hardware) {
ret = master->prepare_transfer_hardware(master);
if (ret) {
dev_err(&master->dev,
"failed to prepare transfer hardware\n");
+
+ if (master->auto_runtime_pm)
+ pm_runtime_put(master->dev.parent);
return;
}
}
msg->status = -EINPROGRESS;
list_add_tail(&msg->queue, &master->queue);
- if (master->running && !master->busy)
+ if (!master->busy)
queue_kthread_work(&master->kworker, &master->pump_messages);
spin_unlock_irqrestore(&master->queue_lock, flags);
if (of_find_property(nc, "spi-3wire", NULL))
spi->mode |= SPI_3WIRE;
+ /* Device DUAL/QUAD mode */
+ prop = of_get_property(nc, "spi-tx-nbits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_err(&master->dev, "%s has no 'spi-tx-nbits' property\n",
+ nc->full_name);
+ spi_dev_put(spi);
+ continue;
+ }
+ switch (be32_to_cpup(prop)) {
+ case SPI_NBITS_SINGLE:
+ break;
+ case SPI_NBITS_DUAL:
+ spi->mode |= SPI_TX_DUAL;
+ break;
+ case SPI_NBITS_QUAD:
+ spi->mode |= SPI_TX_QUAD;
+ break;
+ default:
+ dev_err(&master->dev, "spi-tx-nbits value is not supported\n");
+ spi_dev_put(spi);
+ continue;
+ }
+
+ prop = of_get_property(nc, "spi-rx-nbits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_err(&master->dev, "%s has no 'spi-rx-nbits' property\n",
+ nc->full_name);
+ spi_dev_put(spi);
+ continue;
+ }
+ switch (be32_to_cpup(prop)) {
+ case SPI_NBITS_SINGLE:
+ break;
+ case SPI_NBITS_DUAL:
+ spi->mode |= SPI_RX_DUAL;
+ break;
+ case SPI_NBITS_QUAD:
+ spi->mode |= SPI_RX_QUAD;
+ break;
+ default:
+ dev_err(&master->dev, "spi-rx-nbits value is not supported\n");
+ spi_dev_put(spi);
+ continue;
+ }
+
/* Device speed */
prop = of_get_property(nc, "spi-max-frequency", &len);
if (!prop || len < sizeof(*prop)) {
else {
status = spi_master_initialize_queue(master);
if (status) {
- device_unregister(&master->dev);
+ device_del(&master->dev);
goto done;
}
}
unsigned bad_bits;
int status = 0;
+ /* check mode to prevent that DUAL and QUAD set at the same time
+ */
+ if (((spi->mode & SPI_TX_DUAL) && (spi->mode & SPI_TX_QUAD)) ||
+ ((spi->mode & SPI_RX_DUAL) && (spi->mode & SPI_RX_QUAD))) {
+ dev_err(&spi->dev,
+ "setup: can not select dual and quad at the same time\n");
+ return -EINVAL;
+ }
+ /* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden
+ */
+ if ((spi->mode & SPI_3WIRE) && (spi->mode &
+ (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)))
+ return -EINVAL;
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current master
*/
/**
* Set transfer bits_per_word and max speed as spi device default if
* it is not set for this transfer.
+ * Set transfer tx_nbits and rx_nbits as single transfer default
+ * (SPI_NBITS_SINGLE) if it is not set for this transfer.
*/
list_for_each_entry(xfer, &message->transfers, transfer_list) {
+ message->frame_length += xfer->len;
if (!xfer->bits_per_word)
xfer->bits_per_word = spi->bits_per_word;
if (!xfer->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;
+ if (xfer->rx_buf && !xfer->rx_nbits)
+ xfer->rx_nbits = SPI_NBITS_SINGLE;
+ /* check transfer tx/rx_nbits:
+ * 1. keep the value is not out of single, dual and quad
+ * 2. keep tx/rx_nbits is contained by mode in spi_device
+ * 3. if SPI_3WIRE, tx/rx_nbits should be in single
+ */
+ if (xfer->tx_buf) {
+ if (xfer->tx_nbits != SPI_NBITS_SINGLE &&
+ xfer->tx_nbits != SPI_NBITS_DUAL &&
+ xfer->tx_nbits != SPI_NBITS_QUAD)
+ return -EINVAL;
+ if ((xfer->tx_nbits == SPI_NBITS_DUAL) &&
+ !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD)))
+ return -EINVAL;
+ if ((xfer->tx_nbits == SPI_NBITS_QUAD) &&
+ !(spi->mode & SPI_TX_QUAD))
+ return -EINVAL;
+ if ((spi->mode & SPI_3WIRE) &&
+ (xfer->tx_nbits != SPI_NBITS_SINGLE))
+ return -EINVAL;
+ }
+ /* check transfer rx_nbits */
+ if (xfer->rx_buf) {
+ if (xfer->rx_nbits != SPI_NBITS_SINGLE &&
+ xfer->rx_nbits != SPI_NBITS_DUAL &&
+ xfer->rx_nbits != SPI_NBITS_QUAD)
+ return -EINVAL;
+ if ((xfer->rx_nbits == SPI_NBITS_DUAL) &&
+ !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD)))
+ return -EINVAL;
+ if ((xfer->rx_nbits == SPI_NBITS_QUAD) &&
+ !(spi->mode & SPI_RX_QUAD))
+ return -EINVAL;
+ if ((spi->mode & SPI_3WIRE) &&
+ (xfer->rx_nbits != SPI_NBITS_SINGLE))
+ return -EINVAL;
+ }
}
message->spi = spi;
struct spi_master *master;
u32 max_speed_hz;
u8 chip_select;
- u8 mode;
+ u16 mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
#define SPI_MODE_0 (0|0) /* (original MicroWire) */
#define SPI_LOOP 0x20 /* loopback mode */
#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
#define SPI_READY 0x80 /* slave pulls low to pause */
+ #define SPI_TX_DUAL 0x100 /* transmit with 2 wires */
+ #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
+ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */
+ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */
u8 bits_per_word;
int irq;
void *controller_state;
* @busy: message pump is busy
* @running: message pump is running
* @rt: whether this queue is set to run as a realtime task
+ * @auto_runtime_pm: the core should ensure a runtime PM reference is held
+ * while the hardware is prepared, using the parent
+ * device for the spidev
* @prepare_transfer_hardware: a message will soon arrive from the queue
* so the subsystem requests the driver to prepare the transfer hardware
* by issuing this call
/* bitmask of supported bits_per_word for transfers */
u32 bits_per_word_mask;
#define SPI_BPW_MASK(bits) BIT((bits) - 1)
-#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1))
+#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1))
#define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1))
/* limits on transfer speed */
bool busy;
bool running;
bool rt;
+ bool auto_runtime_pm;
int (*prepare_transfer_hardware)(struct spi_master *master);
int (*transfer_one_message)(struct spi_master *master,
struct spi_message *mesg);
int (*unprepare_transfer_hardware)(struct spi_master *master);
+
/* gpio chip select */
int *cs_gpios;
};
* @rx_buf: data to be read (dma-safe memory), or NULL
* @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
* @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
+ * @tx_nbits: number of bits used for writting. If 0 the default
+ * (SPI_NBITS_SINGLE) is used.
+ * @rx_nbits: number of bits used for reading. If 0 the default
+ * (SPI_NBITS_SINGLE) is used.
* @len: size of rx and tx buffers (in bytes)
* @speed_hz: Select a speed other than the device default for this
* transfer. If 0 the default (from @spi_device) is used.
* by the results of previous messages and where the whole transaction
* ends when the chipselect goes intactive.
*
+ * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
+ * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
+ * two should both be set. User can set transfer mode with SPI_NBITS_SINGLE(1x)
+ * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
+ *
* The code that submits an spi_message (and its spi_transfers)
* to the lower layers is responsible for managing its memory.
* Zero-initialize every field you don't set up explicitly, to
dma_addr_t rx_dma;
unsigned cs_change:1;
+ u8 tx_nbits;
+ u8 rx_nbits;
+ #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
+ #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
+ #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;
/* completion is reported through a callback */
void (*complete)(void *context);
void *context;
+ unsigned frame_length;
unsigned actual_length;
int status;
/* mode becomes spi_device.mode, and is essential for chips
* where the default of SPI_CS_HIGH = 0 is wrong.
*/
- u8 mode;
+ u16 mode;
/* ... may need additional spi_device chip config data here.
* avoid stuff protocol drivers can set; but include stuff