]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge remote-tracking branch 'spi/topic/qspi' into spi-next
authorMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:49:06 +0000 (13:49 +0100)
committerMark Brown <broonie@linaro.org>
Sun, 1 Sep 2013 12:49:06 +0000 (13:49 +0100)
1  2 
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi.c
include/linux/spi/spi.h

diff --combined drivers/spi/Kconfig
index 8aad2c1dc33d64d6eed10b550fab5b184532a290,72dee132b6cbbdc5777afa6dddd7a6828fd49917..f552c89abdd466da510b472fd613c47b2c1aefe1
@@@ -70,14 -70,14 +70,14 @@@ config SPI_ATH7
  
  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
@@@ -158,22 -151,15 +158,22 @@@ config SPI_COLDFIRE_QSP
  
  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.
@@@ -205,7 -191,7 +205,7 @@@ config SPI_GPI
  
  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
@@@ -262,13 -248,6 +262,13 @@@ config SPI_FSL_SP
          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
@@@ -301,20 -280,28 +301,28 @@@ config SPI_OMAP_UWIR
  
  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.
  
@@@ -362,7 -349,7 +370,7 @@@ config SPI_PXA2XX_PC
  
  config SPI_RSPI
        tristate "Renesas RSPI controller"
 -      depends on SUPERH
 +      depends on SUPERH && SH_DMAE_BASE
        help
          SPI driver for Renesas RSPI blocks.
  
@@@ -406,7 -393,7 +414,7 @@@ config SPI_SH_MSIO
  
  config SPI_SH
        tristate "SuperH SPI controller"
 -      depends on SUPERH
 +      depends on SUPERH || COMPILE_TEST
        help
          SPI driver for SuperH SPI blocks.
  
@@@ -419,7 -406,7 +427,7 @@@ config SPI_SH_SC
  
  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.
  
@@@ -439,7 -426,7 +447,7 @@@ config SPI_MX
  
  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.
  
@@@ -478,7 -465,7 +486,7 @@@ config SPI_TOPCLIFF_PC
  
  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
  
diff --combined drivers/spi/Makefile
index 985d7bad7932a1a1d670aa017a54d56ea23e10be,a174030a0833bd3902502f0e2c4ee94d40bd8b75..ab8d8644af0e9e97e66d082c472f2a83793dfbd7
@@@ -17,7 -17,6 +17,7 @@@ obj-$(CONFIG_SPI_AU1550)              += spi-au1550
  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
@@@ -28,11 -27,9 +28,11 @@@ obj-$(CONFIG_SPI_DESIGNWARE)                += spi-dw
  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
@@@ -49,6 -46,7 +49,7 @@@ obj-$(CONFIG_SPI_OCTEON)              += spi-octeon
  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
index de197f72e082dd200455fe5f0eb39d811c5f91a5,4ac028d6b2d840538175fb4aead2f0f4bfb491b1..536b0e363826164f3421765f21e32913c071ec8f
@@@ -231,24 -231,6 +231,6 @@@ static int bcm63xx_txrx_bufs(struct spi
        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)
  {
@@@ -353,13 -335,20 +335,13 @@@ static int bcm63xx_spi_probe(struct pla
  {
        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));
@@@ -474,7 -461,8 +455,7 @@@ static int bcm63xx_spi_remove(struct pl
  #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);
index 8e07928cadb33f7a2ae325d2e00ca0e00cce381c,e4265eaf054856cc05600d8f4b0ac6c8bdad689f..cc5b75d10c386145dad24ac595c5495e4b7564f0
@@@ -354,24 -354,6 +354,6 @@@ static int mcfqspi_transfer_one_message
  
  }
  
- 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) {
@@@ -400,7 -382,7 +382,7 @@@ static int mcfqspi_probe(struct platfor
        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);
  
@@@ -558,7 -539,7 +539,7 @@@ static int mcfqspi_resume(struct devic
  #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);
  
index fc190a5a0badd03d9037bd04986f247c500049fe,973c1cb42c9c67d6b1a8e1fd070602e0f05e11fb..ed4af4708d9aa2374c444915aa81345b9684b518
@@@ -335,23 -335,6 +335,6 @@@ static void omap2_mcspi_restore_ctx(str
                __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;
@@@ -1318,8 -1301,7 +1301,7 @@@ static int omap2_mcspi_probe(struct pla
        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;
diff --combined drivers/spi/spi-pl022.c
index 5a9e05e20bb5b4e0e61231e35cf538b565ddc550,07e6db6c810fb5bcb8b2e1201ff18f74b9d4c3cc..9c511a954d213cfec829ebcc0431b80cf93541f9
@@@ -1555,18 -1555,6 +1555,6 @@@ static int pl022_transfer_one_message(s
        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;
  }
  
@@@ -2091,8 -2072,7 +2072,8 @@@ pl022_platform_data_dt_get(struct devic
  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)) {
diff --combined drivers/spi/spi-pxa2xx.c
index e0fd6f63c93ef457c5b4a5c9437fc8cc314f28c9,a8c85424eb8d0ac2522faf2c2626b522d22d990b..2eb06ee0b3264020d040c2b1ea8bd6745656c372
@@@ -69,8 -69,6 +69,8 @@@ MODULE_ALIAS("platform:pxa2xx-spi")
  #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)
@@@ -144,13 -142,8 +144,13 @@@ detection_done
        __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)
@@@ -811,14 -804,6 +811,6 @@@ static int pxa2xx_spi_transfer_one_mess
        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;
  }
  
@@@ -1141,8 -1124,8 +1131,8 @@@ static int pxa2xx_spi_probe(struct plat
        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);
index 2465d6d35b068fa5158073a515ca562973ffc239,a73d0a3a35dfbf6ea5eeb7cd81b63aa73657d215..c5bc96123c1ba2d0d5525525d3c09deef58a80b0
@@@ -356,8 -356,6 +356,6 @@@ static int s3c64xx_spi_prepare_transfer
        while (!is_polling(sdd) && !acquire_dma(sdd))
                usleep_range(10000, 11000);
  
-       pm_runtime_get_sync(&sdd->pdev->dev);
        return 0;
  }
  
@@@ -372,7 -370,6 +370,6 @@@ static int s3c64xx_spi_unprepare_transf
                sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
                                        &s3c64xx_spi_dma_client);
        }
-       pm_runtime_put(&sdd->pdev->dev);
  
        return 0;
  }
@@@ -1275,7 -1272,7 +1272,7 @@@ static struct s3c64xx_spi_info *s3c64xx
  #else
  static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
  {
 -      return dev->platform_data;
 +      return dev_get_platdata(dev);
  }
  #endif
  
@@@ -1300,7 -1297,7 +1297,7 @@@ static int s3c64xx_spi_probe(struct pla
        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)) {
diff --combined drivers/spi/spi.c
index 7ed5c147c073c7c7fbcbfef1fb15529727999598,76e6ddf00ccc4b90f0a7001f5ce78ca1c7282413..6ef349f82b5f3624db4c9511b29c1ea125227a70
@@@ -553,6 -553,10 +553,10 @@@ static void spi_pump_messages(struct kt
                    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;
                }
        }
@@@ -774,7 -790,7 +790,7 @@@ static int spi_queued_transfer(struct s
        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);
@@@ -869,6 -885,51 +885,51 @@@ static void of_register_spi_devices(str
                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)) {
@@@ -1169,7 -1230,7 +1230,7 @@@ int spi_register_master(struct spi_mast
        else {
                status = spi_master_initialize_queue(master);
                if (status) {
 -                      device_unregister(&master->dev);
 +                      device_del(&master->dev);
                        goto done;
                }
        }
@@@ -1316,6 -1377,19 +1377,19 @@@ int spi_setup(struct spi_device *spi
        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
         */
@@@ -1378,9 -1452,10 +1452,11 @@@ static int __spi_async(struct spi_devic
        /**
         * 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;
diff --combined include/linux/spi/spi.h
index e1b3e69aeddc4c739144f619bac29275abe7dddd,d4a16a68b9cf896afada9265995386d9ae1b9f05..887116dbce2c8504fb7d56cf13565f47dd8c3c2a
@@@ -74,7 -74,7 +74,7 @@@ struct spi_device 
        struct spi_master       *master;
        u32                     max_speed_hz;
        u8                      chip_select;
-       u                     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;
@@@ -256,6 -260,9 +260,9 @@@ static inline void spi_unregister_drive
   * @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
@@@ -311,7 -318,7 +318,7 @@@ struct spi_master 
        /* 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;
  };
@@@ -454,6 -463,10 +463,10 @@@ extern struct spi_master *spi_busnum_to
   * @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
@@@ -528,6 -546,11 +546,11 @@@ struct spi_transfer 
        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;
@@@ -584,7 -607,6 +607,7 @@@ struct spi_message 
        /* completion is reported through a callback */
        void                    (*complete)(void *context);
        void                    *context;
 +      unsigned                frame_length;
        unsigned                actual_length;
        int                     status;
  
@@@ -876,7 -898,7 +899,7 @@@ struct spi_board_info 
        /* mode becomes spi_device.mode, and is essential for chips
         * where the default of SPI_CS_HIGH = 0 is wrong.
         */
-       u             mode;
+       u16             mode;
  
        /* ... may need additional spi_device chip config data here.
         * avoid stuff protocol drivers can set; but include stuff