Merge remote-tracking branches 'spi/topic/acpi', 'spi/topic/axi-engine', 'spi/topic...
authorMark Brown <broonie@kernel.org>
Fri, 11 Mar 2016 07:28:25 +0000 (14:28 +0700)
committerMark Brown <broonie@kernel.org>
Fri, 11 Mar 2016 07:28:25 +0000 (14:28 +0700)
1  2  3  4  5 
drivers/spi/Kconfig
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi.c
include/linux/spi/spi.h

diff --combined drivers/spi/Kconfig
@@@@@@ -75,11 -75,11 -75,27 -75,10 -75,11 +75,26 @@@@@@ config SPI_ATME
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
     
++ ++config SPI_AU1550
++ ++   tristate "Au1550/Au1200/Au1300 SPI Controller"
++ ++   depends on MIPS_ALCHEMY
++ ++   select SPI_BITBANG
++ ++   help
++ ++     If you say yes to this option, support will be included for the
++ ++     PSC SPI controller found on Au1550, Au1200 and Au1300 series.
++ ++
++ ++config SPI_AXI_SPI_ENGINE
++ ++   tristate "Analog Devices AXI SPI Engine controller"
++ ++   depends on HAS_IOMEM
++ ++   help
++ ++     This enables support for the Analog Devices AXI SPI Engine SPI controller.
++ ++     It is part of the SPI Engine framework that is used in some Analog Devices
++ ++     reference designs for FPGAs.
++ ++
     config SPI_BCM2835
        tristate "BCM2835 SPI controller"
        depends on GPIOLIB
        depends on ARCH_BCM2835 || COMPILE_TEST
--- -   depends on GPIOLIB
        help
          This selects a driver for the Broadcom BCM2835 SPI master.
     
     
     config SPI_BCM2835AUX
        tristate "BCM2835 SPI auxiliary controller"
----    depends on ARCH_BCM2835 || COMPILE_TEST
----    depends on GPIOLIB
++++    depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST
        help
          This selects a driver for the Broadcom BCM2835 SPI aux master.
     
@@@@@@ -118,14 -118,14 -134,6 -117,14 -117,14 +132,6 @@@@@@ config SPI_BFIN_SPOR
        help
          Enable support for a SPI bus via the Blackfin SPORT peripheral.
     
-- --config SPI_AU1550
-- --   tristate "Au1550/Au1200/Au1300 SPI Controller"
-- --   depends on MIPS_ALCHEMY
-- --   select SPI_BITBANG
-- --   help
-- --     If you say yes to this option, support will be included for the
-- --     PSC SPI controller found on Au1550, Au1200 and Au1300 series.
-- --
     config SPI_BCM53XX
        tristate "Broadcom BCM53xx SPI controller"
        depends on ARCH_BCM_5301X
@@@@@@ -197,6 -197,6 -205,23 -196,6 -196,6 +203,23 @@@@@@ config SPI_DAVINC
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
     
++ ++config SPI_DESIGNWARE
++ ++   tristate "DesignWare SPI controller core support"
++ ++   help
++ ++     general driver for SPI controller core from DesignWare
++ ++
++ ++config SPI_DW_PCI
++ ++   tristate "PCI interface driver for DW SPI core"
++ ++   depends on SPI_DESIGNWARE && PCI
++ ++
++ ++config SPI_DW_MID_DMA
++ ++   bool "DMA support for DW SPI controller on Intel MID platform"
++ ++   depends on SPI_DW_PCI && DW_DMAC_PCI
++ ++
++ ++config SPI_DW_MMIO
++ ++   tristate "Memory-mapped io interface driver for DW SPI core"
++ ++   depends on SPI_DESIGNWARE
++ ++
     config SPI_DLN2
            tristate "Diolan DLN-2 USB SPI adapter"
            depends on MFD_DLN2
@@@@@@ -346,6 -346,6 -371,13 -345,6 -345,6 +369,13 @@@@@@ config SPI_MT65X
          say Y or M here.If you are not sure, say N.
          SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
     
++ ++config SPI_NUC900
++ ++   tristate "Nuvoton NUC900 series SPI"
++ ++   depends on ARCH_W90X900
++ ++   select SPI_BITBANG
++ ++   help
++ ++     SPI driver for Nuvoton NUC900 series ARM SoCs
++ ++
     config SPI_OC_TINY
        tristate "OpenCores tiny SPI"
        depends on GPIOLIB || COMPILE_TEST
@@@@@@ -647,34 -647,34 -679,10 -646,34 -646,34 +677,10 @@@@@@ config SPI_ZYNQMP_GQSP
        help
          Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
     
-- --config SPI_NUC900
-- --   tristate "Nuvoton NUC900 series SPI"
-- --   depends on ARCH_W90X900
-- --   select SPI_BITBANG
-- --   help
-- --     SPI driver for Nuvoton NUC900 series ARM SoCs
-- --
     #
     # Add new SPI master controllers in alphabetical order above this line
     #
     
-- --config SPI_DESIGNWARE
-- --   tristate "DesignWare SPI controller core support"
-- --   help
-- --     general driver for SPI controller core from DesignWare
-- --
-- --config SPI_DW_PCI
-- --   tristate "PCI interface driver for DW SPI core"
-- --   depends on SPI_DESIGNWARE && PCI
-- --
-- --config SPI_DW_MID_DMA
-- --   bool "DMA support for DW SPI controller on Intel MID platform"
-- --   depends on SPI_DW_PCI && DW_DMAC_PCI
-- --
-- --config SPI_DW_MMIO
-- --   tristate "Memory-mapped io interface driver for DW SPI core"
-- --   depends on SPI_DESIGNWARE
-- --
     #
     # There are lots of SPI device types, with sensors and memory
     # being probably the most widely used ones.
     #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH    0x00004000
     #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD     0x00003000
     #define BCM2835_AUX_SPI_CNTL0_ENABLE       0x00000800
---- #define BCM2835_AUX_SPI_CNTL0_CPHA_IN      0x00000400
++++ #define BCM2835_AUX_SPI_CNTL0_IN_RISING    0x00000400
     #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO    0x00000200
---- #define BCM2835_AUX_SPI_CNTL0_CPHA_OUT     0x00000100
++++ #define BCM2835_AUX_SPI_CNTL0_OUT_RISING   0x00000100
     #define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
     #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT     0x00000040
     #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN     0x0000003F
     
     /* Bitfields in CNTL1 */
     #define BCM2835_AUX_SPI_CNTL1_CSHIGH       0x00000700
 ----#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000080
 ----#define BCM2835_AUX_SPI_CNTL1_TXEMPTY      0x00000040
 ++++#define BCM2835_AUX_SPI_CNTL1_TXEMPTY      0x00000080
 ++++#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040
     #define BCM2835_AUX_SPI_CNTL1_MSBF_IN      0x00000002
     #define BCM2835_AUX_SPI_CNTL1_KEEP_IN      0x00000001
     
     #define BCM2835_AUX_SPI_POLLING_LIMIT_US   30
     #define BCM2835_AUX_SPI_POLLING_JIFFIES            2
     
---- #define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
----                              | SPI_NO_CS)
---- 
     struct bcm2835aux_spi {
        void __iomem *regs;
        struct clk *clk;
@@@@@@ -212,9 -212,9 -212,9 -212,9 -209,15 +209,15 @@@@@@ static irqreturn_t bcm2835aux_spi_inter
                ret = IRQ_HANDLED;
        }
     
----    /* and if rx_len is 0 then wake up completion and disable spi */
++++    if (!bs->tx_len) {
++++            /* disable tx fifo empty interrupt */
++++            bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
++++                    BCM2835_AUX_SPI_CNTL1_IDLE);
++++    }
++++ 
++++    /* and if rx_len is 0 then disable interrupts and wake up completion */
        if (!bs->rx_len) {
----            bcm2835aux_spi_reset_hw(bs);
++++            bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
                complete(&master->xfer_completion);
        }
     
@@@@@@ -307,9 -307,9 -307,9 -307,9 -310,6 +310,6 @@@@@@ static int bcm2835aux_spi_transfer_one_
                }
        }
     
----    /* Transfer complete - reset SPI HW */
----    bcm2835aux_spi_reset_hw(bs);
---- 
        /* and return without waiting for completion */
        return 0;
     }
@@@@@@ -330,10 -330,10 -330,10 -330,10 -330,6 +330,6 @@@@@@ static int bcm2835aux_spi_transfer_one(
         * resulting (potentially) in more interrupts when transferring
         * more than 12 bytes
         */
----    bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
----                  BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
----                  BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
----    bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
     
        /* set clock */
        spi_hz = tfr->speed_hz;
        } else { /* the slowest we can go */
                speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
        }
++++    /* mask out old speed from previous spi_transfer */
++++    bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED);
++++    /* set the new speed */
        bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
     
        spi_used_hz = clk_hz / (2 * (speed + 1));
     
----    /* handle all the modes */
----    if (spi->mode & SPI_CPOL)
----            bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
----    if (spi->mode & SPI_CPHA)
----            bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
----                           BCM2835_AUX_SPI_CNTL0_CPHA_IN;
---- 
        /* set transmit buffers and length */
        bs->tx_buf = tfr->tx_buf;
        bs->rx_buf = tfr->rx_buf;
        return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
     }
     
++++ static int bcm2835aux_spi_prepare_message(struct spi_master *master,
++++                                      struct spi_message *msg)
++++ {
++++    struct spi_device *spi = msg->spi;
++++    struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
++++ 
++++    bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
++++                  BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
++++                  BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
++++    bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
++++ 
++++    /* handle all the modes */
++++    if (spi->mode & SPI_CPOL) {
++++            bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
++++            bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
++++    } else {
++++            bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
++++    }
++++    bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
++++    bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
++++ 
++++    return 0;
++++ }
++++ 
++++ static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
++++                                        struct spi_message *msg)
++++ {
++++    struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
++++ 
++++    bcm2835aux_spi_reset_hw(bs);
++++ 
++++    return 0;
++++ }
++++ 
     static void bcm2835aux_spi_handle_err(struct spi_master *master,
                                      struct spi_message *msg)
     {
@@@@@@ -405,11 -405,11 -405,11 -405,11 -431,13 +431,13 @@@@@@ static int bcm2835aux_spi_probe(struct 
        }
     
        platform_set_drvdata(pdev, master);
----    master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
++++    master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->num_chipselect = -1;
        master->transfer_one = bcm2835aux_spi_transfer_one;
        master->handle_err = bcm2835aux_spi_handle_err;
++++    master->prepare_message = bcm2835aux_spi_prepare_message;
++++    master->unprepare_message = bcm2835aux_spi_unprepare_message;
        master->dev.of_node = pdev->dev.of_node;
     
        bs = spi_master_get_devdata(master);
diff --combined drivers/spi/spi.c
@@@@@@ -702,7 -702,6 -702,6 -702,6 -702,6 +702,7 @@@@@@ static int spi_map_buf(struct spi_maste
                       enum dma_data_direction dir)
     {
        const bool vmalloced_buf = is_vmalloc_addr(buf);
 ++++   unsigned int max_seg_size = dma_get_max_seg_size(dev);
        int desc_len;
        int sgs;
        struct page *vm_page;
        int i, ret;
     
        if (vmalloced_buf) {
 ----           desc_len = PAGE_SIZE;
 ++++           desc_len = min_t(int, max_seg_size, PAGE_SIZE);
                sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
        } else {
 ----           desc_len = master->max_dma_len;
 ++++           desc_len = min_t(int, max_seg_size, master->max_dma_len);
                sgs = DIV_ROUND_UP(len, desc_len);
        }
     
                        sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }
     
 ----
                buf += min;
                len -= min;
        }
@@@@@@ -1152,7 -1152,6 -1152,6 -1152,6 -1152,6 +1152,7 @@@@@@ static void __spi_pump_messages(struct 
                }
        }
     
 ++++   mutex_lock(&master->bus_lock_mutex);
        trace_spi_message_start(master->cur_msg);
     
        if (master->prepare_message) {
                                "failed to prepare message: %d\n", ret);
                        master->cur_msg->status = ret;
                        spi_finalize_current_message(master);
 ++++                   mutex_unlock(&master->bus_lock_mutex);
                        return;
                }
                master->cur_msg_prepared = true;
        if (ret) {
                master->cur_msg->status = ret;
                spi_finalize_current_message(master);
 ++++           mutex_unlock(&master->bus_lock_mutex);
                return;
        }
     
        if (ret) {
                dev_err(&master->dev,
                        "failed to transfer one message from queue\n");
 ++++           mutex_unlock(&master->bus_lock_mutex);
                return;
        }
 ++++   mutex_unlock(&master->bus_lock_mutex);
 ++++
 ++++   /* Prod the scheduler in case transfer_one() was busy waiting */
 ++++   cond_resched();
     }
     
     /**
@@@@@@ -1589,13 -1581,30 -1581,13 -1581,13 -1581,13 +1589,30 @@@@@@ static void of_register_spi_devices(str
     static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
     {
        struct spi_device *spi = data;
+ +++   struct spi_master *master = spi->master;
     
        if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
                struct acpi_resource_spi_serialbus *sb;
     
                sb = &ares->data.spi_serial_bus;
                if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
- ---                   spi->chip_select = sb->device_selection;
+ +++                   /*
+ +++                    * ACPI DeviceSelection numbering is handled by the
+ +++                    * host controller driver in Windows and can vary
+ +++                    * from driver to driver. In Linux we always expect
+ +++                    * 0 .. max - 1 so we need to ask the driver to
+ +++                    * translate between the two schemes.
+ +++                    */
+ +++                   if (master->fw_translate_cs) {
+ +++                           int cs = master->fw_translate_cs(master,
+ +++                                           sb->device_selection);
+ +++                           if (cs < 0)
+ +++                                   return cs;
+ +++                           spi->chip_select = cs;
+ +++                   } else {
+ +++                           spi->chip_select = sb->device_selection;
+ +++                   }
+ +++
                        spi->max_speed_hz = sb->connection_speed;
     
                        if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
@@@@@@ -2359,46 -2368,6 -2351,6 -2351,6 -2351,6 +2376,46 @@@@@@ int spi_async_locked(struct spi_device 
     EXPORT_SYMBOL_GPL(spi_async_locked);
     
     
 ++++int spi_flash_read(struct spi_device *spi,
 ++++              struct spi_flash_read_message *msg)
 ++++
 ++++{
 ++++   struct spi_master *master = spi->master;
 ++++   int ret;
 ++++
 ++++   if ((msg->opcode_nbits == SPI_NBITS_DUAL ||
 ++++        msg->addr_nbits == SPI_NBITS_DUAL) &&
 ++++       !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD)))
 ++++           return -EINVAL;
 ++++   if ((msg->opcode_nbits == SPI_NBITS_QUAD ||
 ++++        msg->addr_nbits == SPI_NBITS_QUAD) &&
 ++++       !(spi->mode & SPI_TX_QUAD))
 ++++           return -EINVAL;
 ++++   if (msg->data_nbits == SPI_NBITS_DUAL &&
 ++++       !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD)))
 ++++           return -EINVAL;
 ++++   if (msg->data_nbits == SPI_NBITS_QUAD &&
 ++++       !(spi->mode &  SPI_RX_QUAD))
 ++++           return -EINVAL;
 ++++
 ++++   if (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 ret;
 ++++           }
 ++++   }
 ++++   mutex_lock(&master->bus_lock_mutex);
 ++++   ret = master->spi_flash_read(spi, msg);
 ++++   mutex_unlock(&master->bus_lock_mutex);
 ++++   if (master->auto_runtime_pm)
 ++++           pm_runtime_put(master->dev.parent);
 ++++
 ++++   return ret;
 ++++}
 ++++EXPORT_SYMBOL_GPL(spi_flash_read);
 ++++
     /*-------------------------------------------------------------------------*/
     
     /* Utility methods for SPI master protocol drivers, layered on
diff --combined include/linux/spi/spi.h
     struct dma_chan;
     struct spi_master;
     struct spi_transfer;
 ++++struct spi_flash_read_message;
     
     /*
      * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@@@@@ -362,8 -361,6 -361,6 -361,6 -361,6 +362,8 @@@@@@ static inline void spi_unregister_drive
      * @handle_err: the subsystem calls the driver to handle an error that occurs
      *         in the generic implementation of transfer_one_message().
      * @unprepare_message: undo any work done by prepare_message().
 ++++ * @spi_flash_read: to support spi-controller hardwares that provide
 ++++ *                  accelerated interface to read from flash devices.
      * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
      * number. Any individual value may be -ENOENT for CS lines that
      * are not GPIOs (driven by the SPI controller itself).
      * @dma_rx: DMA receive channel
      * @dummy_rx: dummy receive buffer for full-duplex devices
      * @dummy_tx: dummy transmit buffer for full-duplex devices
+ +++ * @fw_translate_cs: If the boot firmware uses different numbering scheme
+ +++ * what Linux expects, this optional hook can be used to translate
+ +++ * between the two.
      *
      * Each SPI master controller can communicate with one or more @spi_device
      * children.  These make a small bus, sharing MOSI, MISO and SCK signals
@@@@@@ -516,8 -516,6 -513,6 -513,6 -513,6 +519,8 @@@@@@ struct spi_master 
                               struct spi_message *message);
        int (*unprepare_message)(struct spi_master *master,
                                 struct spi_message *message);
 ++++   int (*spi_flash_read)(struct  spi_device *spi,
 ++++                         struct spi_flash_read_message *msg);
     
        /*
         * These hooks are for drivers that use a generic implementation
        /* dummy data for full duplex devices */
        void                    *dummy_rx;
        void                    *dummy_tx;
+ +++
+ +++   int (*fw_translate_cs)(struct spi_master *master, unsigned cs);
     };
     
     static inline void *spi_master_get_devdata(struct spi_master *master)
@@@@@@ -1024,42 -1024,6 -1019,6 -1019,6 -1019,6 +1029,42 @@@@@@ static inline ssize_t spi_w8r16be(struc
        return be16_to_cpu(result);
     }
     
 ++++/**
 ++++ * struct spi_flash_read_message - flash specific information for
 ++++ * spi-masters that provide accelerated flash read interfaces
 ++++ * @buf: buffer to read data
 ++++ * @from: offset within the flash from where data is to be read
 ++++ * @len: length of data to be read
 ++++ * @retlen: actual length of data read
 ++++ * @read_opcode: read_opcode to be used to communicate with flash
 ++++ * @addr_width: number of address bytes
 ++++ * @dummy_bytes: number of dummy bytes
 ++++ * @opcode_nbits: number of lines to send opcode
 ++++ * @addr_nbits: number of lines to send address
 ++++ * @data_nbits: number of lines for data
 ++++ */
 ++++struct spi_flash_read_message {
 ++++   void *buf;
 ++++   loff_t from;
 ++++   size_t len;
 ++++   size_t retlen;
 ++++   u8 read_opcode;
 ++++   u8 addr_width;
 ++++   u8 dummy_bytes;
 ++++   u8 opcode_nbits;
 ++++   u8 addr_nbits;
 ++++   u8 data_nbits;
 ++++};
 ++++
 ++++/* SPI core interface for flash read support */
 ++++static inline bool spi_flash_read_supported(struct spi_device *spi)
 ++++{
 ++++   return spi->master->spi_flash_read ? true : false;
 ++++}
 ++++
 ++++int spi_flash_read(struct spi_device *spi,
 ++++              struct spi_flash_read_message *msg);
 ++++
     /*---------------------------------------------------------------------------*/
     
     /*