Merge remote-tracking branches 'spi/topic/s3c64xx', 'spi/topic/sc18is602', 'spi/topic...
authorMark Brown <broonie@linaro.org>
Sun, 30 Mar 2014 00:51:34 +0000 (00:51 +0000)
committerMark Brown <broonie@linaro.org>
Sun, 30 Mar 2014 00:51:34 +0000 (00:51 +0000)
15 files changed:
Documentation/devicetree/bindings/spi/sh-hspi.txt
Documentation/devicetree/bindings/spi/sh-msiof.txt
Documentation/spi/spidev
Documentation/spi/spidev_fdx.c
Documentation/spi/spidev_test.c
drivers/spi/Kconfig
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-sh-hspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh-sci.c
drivers/spi/spi-sirf.c
drivers/spi/spidev.c
include/linux/platform_data/spi-s3c64xx.h
include/uapi/linux/spi/spidev.h

index 30b57b1..319bad4 100644 (file)
@@ -1,7 +1,29 @@
 Renesas HSPI.
 
 Required properties:
-- compatible :         "renesas,hspi"
-- reg : Offset and length of the register set for the device
-- interrupts : interrupt line used by HSPI
+- compatible       : "renesas,hspi-<soctype>", "renesas,hspi" as fallback.
+                    Examples with soctypes are:
+                      - "renesas,hspi-r8a7778" (R-Car M1)
+                      - "renesas,hspi-r8a7779" (R-Car H1)
+- reg              : Offset and length of the register set for the device
+- interrupt-parent : The phandle for the interrupt controller that
+                    services interrupts for this device
+- interrupts       : Interrupt specifier
+- #address-cells   : Must be <1>
+- #size-cells      : Must be <0>
+
+Pinctrl properties might be needed, too.  See
+Documentation/devicetree/bindings/pinctrl/renesas,*.
+
+Example:
+
+       hspi0: spi@fffc7000 {
+               compatible = "renesas,hspi-r8a7778", "renesas,hspi";
+               reg = <0xfffc7000 0x18>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
 
index e622210..f24baf3 100644 (file)
@@ -1,12 +1,40 @@
 Renesas MSIOF spi controller
 
 Required properties:
-- compatible :         "renesas,sh-msiof" for SuperH or
-               "renesas,sh-mobile-msiof" for SH Mobile series
-- reg : Offset and length of the register set for the device
-- interrupts : interrupt line used by MSIOF
+- compatible           : "renesas,msiof-<soctype>" for SoCs,
+                        "renesas,sh-msiof" for SuperH, or
+                        "renesas,sh-mobile-msiof" for SH Mobile series.
+                        Examples with soctypes are:
+                        "renesas,msiof-r8a7790" (R-Car H2)
+                        "renesas,msiof-r8a7791" (R-Car M2)
+- reg                  : Offset and length of the register set for the device
+- interrupt-parent     : The phandle for the interrupt controller that
+                        services interrupts for this device
+- interrupts           : Interrupt specifier
+- #address-cells       : Must be <1>
+- #size-cells          : Must be <0>
 
 Optional properties:
-- num-cs               : total number of chip-selects
-- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
-- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
+- clocks               : Must contain a reference to the functional clock.
+- num-cs               : Total number of chip-selects (default is 1)
+
+Optional properties, deprecated for soctype-specific bindings:
+- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
+                        (default is 64)
+- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
+                        (default is 64, or 256 on R-Car H2 and M2)
+
+Pinctrl properties might be needed, too.  See
+Documentation/devicetree/bindings/pinctrl/renesas,*.
+
+Example:
+
+       msiof0: spi@e6e20000 {
+               compatible = "renesas,msiof-r8a7791";
+               reg = <0 0xe6e20000 0 0x0064>;
+               interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
index ed2da5e..3d14035 100644 (file)
@@ -85,6 +85,12 @@ settings for data transfer parameters:
        SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
        (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
        sample on trailing edge iff this is set) flags.
+       Note that this request is limited to SPI mode flags that fit in a
+       single byte.
+
+    SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t
+       which will return (RD) or assign (WR) the full SPI transfer mode,
+       not limited to the bits that fit in one byte.
 
     SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
        which will return (RD) or assign (WR) the bit justification used to
index 36ec077..0ea3e51 100644 (file)
@@ -78,10 +78,10 @@ static void do_msg(int fd, int len)
 
 static void dumpstat(const char *name, int fd)
 {
-       __u8    mode, lsb, bits;
-       __u32   speed;
+       __u8    lsb, bits;
+       __u32   mode, speed;
 
-       if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) {
+       if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
                perror("SPI rd_mode");
                return;
        }
@@ -98,7 +98,7 @@ static void dumpstat(const char *name, int fd)
                return;
        }
 
-       printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+       printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
                name, mode, bits, lsb ? "(lsb first) " : "", speed);
 }
 
index 16feda9..3a2f9d5 100644 (file)
@@ -30,7 +30,7 @@ static void pabort(const char *s)
 }
 
 static const char *device = "/dev/spidev1.1";
-static uint8_t mode;
+static uint32_t mode;
 static uint8_t bits = 8;
 static uint32_t speed = 500000;
 static uint16_t delay;
@@ -57,6 +57,21 @@ static void transfer(int fd)
                .bits_per_word = bits,
        };
 
+       if (mode & SPI_TX_QUAD)
+               tr.tx_nbits = 4;
+       else if (mode & SPI_TX_DUAL)
+               tr.tx_nbits = 2;
+       if (mode & SPI_RX_QUAD)
+               tr.rx_nbits = 4;
+       else if (mode & SPI_RX_DUAL)
+               tr.rx_nbits = 2;
+       if (!(mode & SPI_LOOP)) {
+               if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
+                       tr.rx_buf = 0;
+               else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
+                       tr.tx_buf = 0;
+       }
+
        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (ret < 1)
                pabort("can't send spi message");
@@ -81,7 +96,11 @@ static void print_usage(const char *prog)
             "  -O --cpol     clock polarity\n"
             "  -L --lsb      least significant bit first\n"
             "  -C --cs-high  chip select active high\n"
-            "  -3 --3wire    SI/SO signals shared\n");
+            "  -3 --3wire    SI/SO signals shared\n"
+            "  -N --no-cs    no chip select\n"
+            "  -R --ready    slave pulls low to pause\n"
+            "  -2 --dual     dual transfer\n"
+            "  -4 --quad     quad transfer\n");
        exit(1);
 }
 
@@ -101,11 +120,13 @@ static void parse_opts(int argc, char *argv[])
                        { "3wire",   0, 0, '3' },
                        { "no-cs",   0, 0, 'N' },
                        { "ready",   0, 0, 'R' },
+                       { "dual",    0, 0, '2' },
+                       { "quad",    0, 0, '4' },
                        { NULL, 0, 0, 0 },
                };
                int c;
 
-               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
+               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24", lopts, NULL);
 
                if (c == -1)
                        break;
@@ -147,11 +168,23 @@ static void parse_opts(int argc, char *argv[])
                case 'R':
                        mode |= SPI_READY;
                        break;
+               case '2':
+                       mode |= SPI_TX_DUAL;
+                       break;
+               case '4':
+                       mode |= SPI_TX_QUAD;
+                       break;
                default:
                        print_usage(argv[0]);
                        break;
                }
        }
+       if (mode & SPI_LOOP) {
+               if (mode & SPI_TX_DUAL)
+                       mode |= SPI_RX_DUAL;
+               if (mode & SPI_TX_QUAD)
+                       mode |= SPI_RX_QUAD;
+       }
 }
 
 int main(int argc, char *argv[])
@@ -168,11 +201,11 @@ int main(int argc, char *argv[])
        /*
         * spi mode
         */
-       ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
+       ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
        if (ret == -1)
                pabort("can't set spi mode");
 
-       ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
+       ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
        if (ret == -1)
                pabort("can't get spi mode");
 
@@ -198,7 +231,7 @@ int main(int argc, char *argv[])
        if (ret == -1)
                pabort("can't get max speed hz");
 
-       printf("spi mode: %d\n", mode);
+       printf("spi mode: 0x%x\n", mode);
        printf("bits per word: %d\n", bits);
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
 
index 5dea67c..2a1b0a7 100644 (file)
@@ -429,7 +429,6 @@ config SPI_SH_MSIOF
        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.
 
index 25c9bd4..f19cd97 100644 (file)
 
 #include <linux/platform_data/spi-s3c64xx.h>
 
-#ifdef CONFIG_S3C_DMA
-#include <mach/dma.h>
-#endif
-
 #define MAX_SPI_PORTS          3
 #define S3C64XX_SPI_QUIRK_POLL         (1 << 0)
 
@@ -200,9 +196,6 @@ struct s3c64xx_spi_driver_data {
        unsigned                        cur_speed;
        struct s3c64xx_spi_dma_data     rx_dma;
        struct s3c64xx_spi_dma_data     tx_dma;
-#ifdef CONFIG_S3C_DMA
-       struct samsung_dma_ops          *ops;
-#endif
        struct s3c64xx_spi_port_config  *port_conf;
        unsigned int                    port_id;
        bool                            cs_gpio;
@@ -284,102 +277,6 @@ static void s3c64xx_spi_dmacb(void *data)
        spin_unlock_irqrestore(&sdd->lock, flags);
 }
 
-#ifdef CONFIG_S3C_DMA
-/* FIXME: remove this section once arch/arm/mach-s3c64xx uses dmaengine */
-
-static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
-       .name = "samsung-spi-dma",
-};
-
-static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
-                                       unsigned len, dma_addr_t buf)
-{
-       struct s3c64xx_spi_driver_data *sdd;
-       struct samsung_dma_prep info;
-       struct samsung_dma_config config;
-
-       if (dma->direction == DMA_DEV_TO_MEM) {
-               sdd = container_of((void *)dma,
-                       struct s3c64xx_spi_driver_data, rx_dma);
-               config.direction = sdd->rx_dma.direction;
-               config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
-               config.width = sdd->cur_bpw / 8;
-               sdd->ops->config((enum dma_ch)sdd->rx_dma.ch, &config);
-       } else {
-               sdd = container_of((void *)dma,
-                       struct s3c64xx_spi_driver_data, tx_dma);
-               config.direction =  sdd->tx_dma.direction;
-               config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-               config.width = sdd->cur_bpw / 8;
-               sdd->ops->config((enum dma_ch)sdd->tx_dma.ch, &config);
-       }
-
-       info.cap = DMA_SLAVE;
-       info.len = len;
-       info.fp = s3c64xx_spi_dmacb;
-       info.fp_param = dma;
-       info.direction = dma->direction;
-       info.buf = buf;
-
-       sdd->ops->prepare((enum dma_ch)dma->ch, &info);
-       sdd->ops->trigger((enum dma_ch)dma->ch);
-}
-
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-       struct samsung_dma_req req;
-       struct device *dev = &sdd->pdev->dev;
-
-       sdd->ops = samsung_dma_get_ops();
-
-       req.cap = DMA_SLAVE;
-       req.client = &s3c64xx_spi_dma_client;
-
-       sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
-                                       sdd->rx_dma.dmach, &req, dev, "rx");
-       sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request(
-                                       sdd->tx_dma.dmach, &req, dev, "tx");
-
-       return 1;
-}
-
-static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
-{
-       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
-       /*
-        * If DMA resource was not available during
-        * probe, no need to continue with dma requests
-        * else Acquire DMA channels
-        */
-       while (!is_polling(sdd) && !acquire_dma(sdd))
-               usleep_range(10000, 11000);
-
-       return 0;
-}
-
-static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
-{
-       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi);
-
-       /* Free DMA channels */
-       if (!is_polling(sdd)) {
-               sdd->ops->release((enum dma_ch)sdd->rx_dma.ch,
-                                       &s3c64xx_spi_dma_client);
-               sdd->ops->release((enum dma_ch)sdd->tx_dma.ch,
-                                       &s3c64xx_spi_dma_client);
-       }
-
-       return 0;
-}
-
-static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd,
-                                struct s3c64xx_spi_dma_data *dma)
-{
-       sdd->ops->stop((enum dma_ch)dma->ch);
-}
-#else
-
 static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
                        struct sg_table *sgt)
 {
@@ -437,6 +334,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
                        ret = -EBUSY;
                        goto out;
                }
+               spi->dma_rx = sdd->rx_dma.ch;
 
                sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter,
                                   (void *)sdd->tx_dma.dmach, dev, "tx");
@@ -445,6 +343,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
                        ret = -EBUSY;
                        goto out_rx;
                }
+               spi->dma_tx = sdd->tx_dma.ch;
        }
 
        ret = pm_runtime_get_sync(&sdd->pdev->dev);
@@ -477,12 +376,14 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
        return 0;
 }
 
-static void s3c64xx_spi_dma_stop(struct s3c64xx_spi_driver_data *sdd,
-                                struct s3c64xx_spi_dma_data *dma)
+static bool s3c64xx_spi_can_dma(struct spi_master *master,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer)
 {
-       dmaengine_terminate_all(dma->ch);
+       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+
+       return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1;
 }
-#endif
 
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_device *spi,
@@ -515,11 +416,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                chcfg |= S3C64XX_SPI_CH_TXCH_ON;
                if (dma_mode) {
                        modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-#ifndef CONFIG_S3C_DMA
                        prepare_dma(&sdd->tx_dma, &xfer->tx_sg);
-#else
-                       prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
-#endif
                } else {
                        switch (sdd->cur_bpw) {
                        case 32:
@@ -551,11 +448,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                        writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
                                        | S3C64XX_SPI_PACKET_CNT_EN,
                                        regs + S3C64XX_SPI_PACKET_CNT);
-#ifndef CONFIG_S3C_DMA
                        prepare_dma(&sdd->rx_dma, &xfer->rx_sg);
-#else
-                       prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
-#endif
                }
        }
 
@@ -764,81 +657,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
-static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
-                                               struct spi_message *msg)
-{
-       struct device *dev = &sdd->pdev->dev;
-       struct spi_transfer *xfer;
-
-       if (is_polling(sdd) || msg->is_dma_mapped)
-               return 0;
-
-       /* First mark all xfer unmapped */
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               xfer->rx_dma = XFER_DMAADDR_INVALID;
-               xfer->tx_dma = XFER_DMAADDR_INVALID;
-       }
-
-       /* Map until end or first fail */
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
-                       continue;
-
-               if (xfer->tx_buf != NULL) {
-                       xfer->tx_dma = dma_map_single(dev,
-                                       (void *)xfer->tx_buf, xfer->len,
-                                       DMA_TO_DEVICE);
-                       if (dma_mapping_error(dev, xfer->tx_dma)) {
-                               dev_err(dev, "dma_map_single Tx failed\n");
-                               xfer->tx_dma = XFER_DMAADDR_INVALID;
-                               return -ENOMEM;
-                       }
-               }
-
-               if (xfer->rx_buf != NULL) {
-                       xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
-                                               xfer->len, DMA_FROM_DEVICE);
-                       if (dma_mapping_error(dev, xfer->rx_dma)) {
-                               dev_err(dev, "dma_map_single Rx failed\n");
-                               dma_unmap_single(dev, xfer->tx_dma,
-                                               xfer->len, DMA_TO_DEVICE);
-                               xfer->tx_dma = XFER_DMAADDR_INVALID;
-                               xfer->rx_dma = XFER_DMAADDR_INVALID;
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
-                                               struct spi_message *msg)
-{
-       struct device *dev = &sdd->pdev->dev;
-       struct spi_transfer *xfer;
-
-       if (is_polling(sdd) || msg->is_dma_mapped)
-               return;
-
-       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-
-               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
-                       continue;
-
-               if (xfer->rx_buf != NULL
-                               && xfer->rx_dma != XFER_DMAADDR_INVALID)
-                       dma_unmap_single(dev, xfer->rx_dma,
-                                               xfer->len, DMA_FROM_DEVICE);
-
-               if (xfer->tx_buf != NULL
-                               && xfer->tx_dma != XFER_DMAADDR_INVALID)
-                       dma_unmap_single(dev, xfer->tx_dma,
-                                               xfer->len, DMA_TO_DEVICE);
-       }
-}
-
 static int s3c64xx_spi_prepare_message(struct spi_master *master,
                                       struct spi_message *msg)
 {
@@ -856,13 +674,6 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
                s3c64xx_spi_config(sdd);
        }
 
-       /* Map all the transfers if needed */
-       if (s3c64xx_spi_map_mssg(sdd, msg)) {
-               dev_err(&spi->dev,
-                       "Xfer: Unable to map message buffers!\n");
-               return -ENOMEM;
-       }
-
        /* Configure feedback delay */
        writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
 
@@ -886,13 +697,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        bpw = xfer->bits_per_word;
        speed = xfer->speed_hz ? : spi->max_speed_hz;
 
-       if (xfer->len % (bpw / 8)) {
-               dev_err(&spi->dev,
-                       "Xfer length(%u) not a multiple of word size(%u)\n",
-                       xfer->len, bpw / 8);
-               return -EIO;
-       }
-
        if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
                sdd->cur_bpw = bpw;
                sdd->cur_speed = speed;
@@ -934,10 +738,10 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
                if (use_dma) {
                        if (xfer->tx_buf != NULL
                            && (sdd->state & TXBUSY))
-                               s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
+                               dmaengine_terminate_all(sdd->tx_dma.ch);
                        if (xfer->rx_buf != NULL
                            && (sdd->state & RXBUSY))
-                               s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
+                               dmaengine_terminate_all(sdd->rx_dma.ch);
                }
        } else {
                flush_fifo(sdd);
@@ -946,16 +750,6 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
        return status;
 }
 
-static int s3c64xx_spi_unprepare_message(struct spi_master *master,
-                                           struct spi_message *msg)
-{
-       struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-
-       s3c64xx_spi_unmap_mssg(sdd, msg);
-
-       return 0;
-}
-
 static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
                                struct spi_device *spi)
 {
@@ -1329,7 +1123,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
        master->prepare_message = s3c64xx_spi_prepare_message;
        master->transfer_one = s3c64xx_spi_transfer_one;
-       master->unprepare_message = s3c64xx_spi_unprepare_message;
        master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
        master->num_chipselect = sci->num_cs;
        master->dma_alignment = 8;
@@ -1338,6 +1131,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->auto_runtime_pm = true;
+       if (!is_polling(sdd))
+               master->can_dma = s3c64xx_spi_can_dma;
 
        sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
        if (IS_ERR(sdd->regs)) {
index 121c2e1..237f2e7 100644 (file)
@@ -183,17 +183,9 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
 static int sc18is602_check_transfer(struct spi_device *spi,
                                    struct spi_transfer *t, int tlen)
 {
-       uint32_t hz;
-
        if (t && t->len + tlen > SC18IS602_BUFSIZ)
                return -EINVAL;
 
-       hz = spi->max_speed_hz;
-       if (t && t->speed_hz)
-               hz = t->speed_hz;
-       if (hz == 0)
-               return -EINVAL;
-
        return 0;
 }
 
@@ -205,22 +197,15 @@ static int sc18is602_transfer_one(struct spi_master *master,
        struct spi_transfer *t;
        int status = 0;
 
-       /* SC18IS602 does not support CS2 */
-       if (hw->id == sc18is602 && spi->chip_select == 2) {
-               status = -ENXIO;
-               goto error;
-       }
-
        hw->tlen = 0;
        list_for_each_entry(t, &m->transfers, transfer_list) {
-               u32 hz = t->speed_hz ? : spi->max_speed_hz;
                bool do_transfer;
 
                status = sc18is602_check_transfer(spi, t, hw->tlen);
                if (status < 0)
                        break;
 
-               status = sc18is602_setup_transfer(hw, hz, spi->mode);
+               status = sc18is602_setup_transfer(hw, t->speed_hz, spi->mode);
                if (status < 0)
                        break;
 
@@ -238,7 +223,6 @@ static int sc18is602_transfer_one(struct spi_master *master,
                if (t->delay_usecs)
                        udelay(t->delay_usecs);
        }
-error:
        m->status = status;
        spi_finalize_current_message(master);
 
@@ -247,10 +231,13 @@ error:
 
 static int sc18is602_setup(struct spi_device *spi)
 {
-       if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
-               return -EINVAL;
+       struct sc18is602 *hw = spi_master_get_devdata(spi->master);
 
-       return sc18is602_check_transfer(spi, NULL, 0);
+       /* SC18IS602 does not support CS2 */
+       if (hw->id == sc18is602 && spi->chip_select == 2)
+               return -ENXIO;
+
+       return 0;
 }
 
 static int sc18is602_probe(struct i2c_client *client,
@@ -309,6 +296,8 @@ static int sc18is602_probe(struct i2c_client *client,
        master->setup = sc18is602_setup;
        master->transfer_one_message = sc18is602_transfer_one;
        master->dev.of_node = np;
+       master->min_speed_hz = hw->freq / 128;
+       master->max_speed_hz = hw->freq / 4;
 
        error = devm_spi_register_master(dev, master);
        if (error)
index 755d7cc..9009456 100644 (file)
@@ -46,8 +46,6 @@
 /* SPSR */
 #define RXFL   (1 << 2)
 
-#define hspi2info(h)   (h->dev->platform_data)
-
 struct hspi_priv {
        void __iomem *addr;
        struct spi_master *master;
@@ -113,14 +111,9 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
 {
        struct spi_device *spi = msg->spi;
        struct device *dev = hspi->dev;
-       u32 target_rate;
        u32 spcr, idiv_clk;
        u32 rate, best_rate, min, tmp;
 
-       target_rate = t ? t->speed_hz : 0;
-       if (!target_rate)
-               target_rate = spi->max_speed_hz;
-
        /*
         * find best IDIV/CLKCx settings
         */
@@ -140,7 +133,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
                rate /= (((idiv_clk & 0x1F) + 1) * 2);
 
                /* save best settings */
-               tmp = abs(target_rate - rate);
+               tmp = abs(t->speed_hz - rate);
                if (tmp < min) {
                        min = tmp;
                        spcr = idiv_clk;
@@ -153,7 +146,7 @@ static void hspi_hw_setup(struct hspi_priv *hspi,
        if (spi->mode & SPI_CPOL)
                spcr |= 1 << 6;
 
-       dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate);
+       dev_dbg(dev, "speed %d/%d\n", t->speed_hz, best_rate);
 
        hspi_write(hspi, SPCR, spcr);
        hspi_write(hspi, SPSR, 0x0);
@@ -230,29 +223,6 @@ static int hspi_transfer_one_message(struct spi_master *master,
        return ret;
 }
 
-static int hspi_setup(struct spi_device *spi)
-{
-       struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
-       struct device *dev = hspi->dev;
-
-       if (8 != spi->bits_per_word) {
-               dev_err(dev, "bits_per_word should be 8\n");
-               return -EIO;
-       }
-
-       dev_dbg(dev, "%s setup\n", spi->modalias);
-
-       return 0;
-}
-
-static void hspi_cleanup(struct spi_device *spi)
-{
-       struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
-       struct device *dev = hspi->dev;
-
-       dev_dbg(dev, "%s cleanup\n", spi->modalias);
-}
-
 static int hspi_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -299,20 +269,22 @@ static int hspi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
 
        master->bus_num         = pdev->id;
-       master->setup           = hspi_setup;
-       master->cleanup         = hspi_cleanup;
        master->mode_bits       = SPI_CPOL | SPI_CPHA;
        master->dev.of_node     = pdev->dev.of_node;
        master->auto_runtime_pm = true;
        master->transfer_one_message            = hspi_transfer_one_message;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+
        ret = devm_spi_register_master(&pdev->dev, master);
        if (ret < 0) {
                dev_err(&pdev->dev, "spi_register_master error.\n");
-               goto error1;
+               goto error2;
        }
 
        return 0;
 
+ error2:
+       pm_runtime_disable(&pdev->dev);
  error1:
        clk_put(clk);
  error0:
index 3347406..e850d03 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/spi/sh_msiof.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 
 #include <asm/unaligned.h>
 
+
+struct sh_msiof_chipdata {
+       u16 tx_fifo_size;
+       u16 rx_fifo_size;
+       u16 master_flags;
+};
+
 struct sh_msiof_spi_priv {
-       struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
        void __iomem *mapbase;
        struct clk *clk;
        struct platform_device *pdev;
+       const struct sh_msiof_chipdata *chipdata;
        struct sh_msiof_spi_info *info;
        struct completion done;
-       unsigned long flags;
        int tx_fifo_size;
        int rx_fifo_size;
 };
 
-#define TMDR1  0x00
-#define TMDR2  0x04
-#define TMDR3  0x08
-#define RMDR1  0x10
-#define RMDR2  0x14
-#define RMDR3  0x18
-#define TSCR   0x20
-#define RSCR   0x22
-#define CTR    0x28
-#define FCTR   0x30
-#define STR    0x40
-#define IER    0x44
-#define TDR1   0x48
-#define TDR2   0x4c
-#define TFDR   0x50
-#define RDR1   0x58
-#define RDR2   0x5c
-#define RFDR   0x60
-
-#define CTR_TSCKE (1 << 15)
-#define CTR_TFSE  (1 << 14)
-#define CTR_TXE   (1 << 9)
-#define CTR_RXE   (1 << 8)
-
-#define STR_TEOF  (1 << 23)
-#define STR_REOF  (1 << 7)
+#define TMDR1  0x00    /* Transmit Mode Register 1 */
+#define TMDR2  0x04    /* Transmit Mode Register 2 */
+#define TMDR3  0x08    /* Transmit Mode Register 3 */
+#define RMDR1  0x10    /* Receive Mode Register 1 */
+#define RMDR2  0x14    /* Receive Mode Register 2 */
+#define RMDR3  0x18    /* Receive Mode Register 3 */
+#define TSCR   0x20    /* Transmit Clock Select Register */
+#define RSCR   0x22    /* Receive Clock Select Register (SH, A1, APE6) */
+#define CTR    0x28    /* Control Register */
+#define FCTR   0x30    /* FIFO Control Register */
+#define STR    0x40    /* Status Register */
+#define IER    0x44    /* Interrupt Enable Register */
+#define TDR1   0x48    /* Transmit Control Data Register 1 (SH, A1) */
+#define TDR2   0x4c    /* Transmit Control Data Register 2 (SH, A1) */
+#define TFDR   0x50    /* Transmit FIFO Data Register */
+#define RDR1   0x58    /* Receive Control Data Register 1 (SH, A1) */
+#define RDR2   0x5c    /* Receive Control Data Register 2 (SH, A1) */
+#define RFDR   0x60    /* Receive FIFO Data Register */
+
+/* TMDR1 and RMDR1 */
+#define MDR1_TRMD       0x80000000 /* Transfer Mode (1 = Master mode) */
+#define MDR1_SYNCMD_MASK 0x30000000 /* SYNC Mode */
+#define MDR1_SYNCMD_SPI         0x20000000 /*   Level mode/SPI */
+#define MDR1_SYNCMD_LR  0x30000000 /*   L/R mode */
+#define MDR1_SYNCAC_SHIFT       25 /* Sync Polarity (1 = Active-low) */
+#define MDR1_BITLSB_SHIFT       24 /* MSB/LSB First (1 = LSB first) */
+#define MDR1_FLD_MASK   0x000000c0 /* Frame Sync Signal Interval (0-3) */
+#define MDR1_FLD_SHIFT           2
+#define MDR1_XXSTP      0x00000001 /* Transmission/Reception Stop on FIFO */
+/* TMDR1 */
+#define TMDR1_PCON      0x40000000 /* Transfer Signal Connection */
+
+/* TMDR2 and RMDR2 */
+#define MDR2_BITLEN1(i)        (((i) - 1) << 24) /* Data Size (8-32 bits) */
+#define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
+#define MDR2_GRPMASK1  0x00000001 /* Group Output Mask 1 (SH, A1) */
+
+/* TSCR and RSCR */
+#define SCR_BRPS_MASK      0x1f00 /* Prescaler Setting (1-32) */
+#define SCR_BRPS(i)    (((i) - 1) << 8)
+#define SCR_BRDV_MASK      0x0007 /* Baud Rate Generator's Division Ratio */
+#define SCR_BRDV_DIV_2     0x0000
+#define SCR_BRDV_DIV_4     0x0001
+#define SCR_BRDV_DIV_8     0x0002
+#define SCR_BRDV_DIV_16            0x0003
+#define SCR_BRDV_DIV_32            0x0004
+#define SCR_BRDV_DIV_1     0x0007
+
+/* CTR */
+#define CTR_TSCKIZ_MASK        0xc0000000 /* Transmit Clock I/O Polarity Select */
+#define CTR_TSCKIZ_SCK 0x80000000 /*   Disable SCK when TX disabled */
+#define CTR_TSCKIZ_POL_SHIFT   30 /*   Transmit Clock Polarity */
+#define CTR_RSCKIZ_MASK        0x30000000 /* Receive Clock Polarity Select */
+#define CTR_RSCKIZ_SCK 0x20000000 /*   Must match CTR_TSCKIZ_SCK */
+#define CTR_RSCKIZ_POL_SHIFT   28 /*   Receive Clock Polarity */
+#define CTR_TEDG_SHIFT         27 /* Transmit Timing (1 = falling edge) */
+#define CTR_REDG_SHIFT         26 /* Receive Timing (1 = falling edge) */
+#define CTR_TXDIZ_MASK 0x00c00000 /* Pin Output When TX is Disabled */
+#define CTR_TXDIZ_LOW  0x00000000 /*   0 */
+#define CTR_TXDIZ_HIGH 0x00400000 /*   1 */
+#define CTR_TXDIZ_HIZ  0x00800000 /*   High-impedance */
+#define CTR_TSCKE      0x00008000 /* Transmit Serial Clock Output Enable */
+#define CTR_TFSE       0x00004000 /* Transmit Frame Sync Signal Output Enable */
+#define CTR_TXE                0x00000200 /* Transmit Enable */
+#define CTR_RXE                0x00000100 /* Receive Enable */
+
+/* STR and IER */
+#define STR_TEOF       0x00800000 /* Frame Transmission End */
+#define STR_REOF       0x00000080 /* Frame Reception End */
+
 
 static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
 {
@@ -130,22 +180,21 @@ static struct {
        unsigned short div;
        unsigned short scr;
 } const sh_msiof_spi_clk_table[] = {
-       { 1, 0x0007 },
-       { 2, 0x0000 },
-       { 4, 0x0001 },
-       { 8, 0x0002 },
-       { 16, 0x0003 },
-       { 32, 0x0004 },
-       { 64, 0x1f00 },
-       { 128, 0x1f01 },
-       { 256, 0x1f02 },
-       { 512, 0x1f03 },
-       { 1024, 0x1f04 },
+       { 1,    SCR_BRPS( 1) | SCR_BRDV_DIV_1 },
+       { 2,    SCR_BRPS( 1) | SCR_BRDV_DIV_2 },
+       { 4,    SCR_BRPS( 1) | SCR_BRDV_DIV_4 },
+       { 8,    SCR_BRPS( 1) | SCR_BRDV_DIV_8 },
+       { 16,   SCR_BRPS( 1) | SCR_BRDV_DIV_16 },
+       { 32,   SCR_BRPS( 1) | SCR_BRDV_DIV_32 },
+       { 64,   SCR_BRPS(32) | SCR_BRDV_DIV_2 },
+       { 128,  SCR_BRPS(32) | SCR_BRDV_DIV_4 },
+       { 256,  SCR_BRPS(32) | SCR_BRDV_DIV_8 },
+       { 512,  SCR_BRPS(32) | SCR_BRDV_DIV_16 },
+       { 1024, SCR_BRPS(32) | SCR_BRDV_DIV_32 },
 };
 
 static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
-                                     unsigned long parent_rate,
-                                     unsigned long spi_hz)
+                                     unsigned long parent_rate, u32 spi_hz)
 {
        unsigned long div = 1024;
        size_t k;
@@ -163,7 +212,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
        k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_clk_table) - 1);
 
        sh_msiof_write(p, TSCR, sh_msiof_spi_clk_table[k].scr);
-       sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
+       if (!(p->chipdata->master_flags & SPI_MASTER_MUST_TX))
+               sh_msiof_write(p, RSCR, sh_msiof_spi_clk_table[k].scr);
 }
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
@@ -182,21 +232,25 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
         */
        sh_msiof_write(p, FCTR, 0);
 
-       tmp = 0;
-       tmp |= !cs_high << 25;
-       tmp |= lsb_first << 24;
-       sh_msiof_write(p, TMDR1, 0xe0000005 | tmp);
-       sh_msiof_write(p, RMDR1, 0x20000005 | tmp);
+       tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP;
+       tmp |= !cs_high << MDR1_SYNCAC_SHIFT;
+       tmp |= lsb_first << MDR1_BITLSB_SHIFT;
+       sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON);
+       if (p->chipdata->master_flags & SPI_MASTER_MUST_TX) {
+               /* These bits are reserved if RX needs TX */
+               tmp &= ~0x0000ffff;
+       }
+       sh_msiof_write(p, RMDR1, tmp);
 
-       tmp = 0xa0000000;
-       tmp |= cpol << 30; /* TSCKIZ */
-       tmp |= cpol << 28; /* RSCKIZ */
+       tmp = 0;
+       tmp |= CTR_TSCKIZ_SCK | cpol << CTR_TSCKIZ_POL_SHIFT;
+       tmp |= CTR_RSCKIZ_SCK | cpol << CTR_RSCKIZ_POL_SHIFT;
 
        edge = cpol ^ !cpha;
 
-       tmp |= edge << 27; /* TEDG */
-       tmp |= edge << 26; /* REDG */
-       tmp |= (tx_hi_z ? 2 : 0) << 22; /* TXDIZ */
+       tmp |= edge << CTR_TEDG_SHIFT;
+       tmp |= edge << CTR_REDG_SHIFT;
+       tmp |= tx_hi_z ? CTR_TXDIZ_HIZ : CTR_TXDIZ_LOW;
        sh_msiof_write(p, CTR, tmp);
 }
 
@@ -204,12 +258,12 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
                                       const void *tx_buf, void *rx_buf,
                                       u32 bits, u32 words)
 {
-       u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
+       u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words);
 
-       if (tx_buf)
+       if (tx_buf || (p->chipdata->master_flags & SPI_MASTER_MUST_TX))
                sh_msiof_write(p, TMDR2, dr2);
        else
-               sh_msiof_write(p, TMDR2, dr2 | 1);
+               sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1);
 
        if (rx_buf)
                sh_msiof_write(p, RMDR2, dr2);
@@ -362,77 +416,45 @@ static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
                put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
 }
 
-static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
+static int sh_msiof_spi_setup(struct spi_device *spi)
 {
-       int bits;
-
-       bits = t ? t->bits_per_word : 0;
-       if (!bits)
-               bits = spi->bits_per_word;
-       return bits;
-}
-
-static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
-                                    struct spi_transfer *t)
-{
-       unsigned long hz;
-
-       hz = t ? t->speed_hz : 0;
-       if (!hz)
-               hz = spi->max_speed_hz;
-       return hz;
-}
+       struct device_node      *np = spi->master->dev.of_node;
+       struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
 
-static int sh_msiof_spi_setup_transfer(struct spi_device *spi,
-                                      struct spi_transfer *t)
-{
-       int bits;
+       if (!np) {
+               /*
+                * Use spi->controller_data for CS (same strategy as spi_gpio),
+                * if any. otherwise let HW control CS
+                */
+               spi->cs_gpio = (uintptr_t)spi->controller_data;
+       }
 
-       /* noting to check hz values against since parent clock is disabled */
+       /* Configure pins before deasserting CS */
+       sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
+                                 !!(spi->mode & SPI_CPHA),
+                                 !!(spi->mode & SPI_3WIRE),
+                                 !!(spi->mode & SPI_LSB_FIRST),
+                                 !!(spi->mode & SPI_CS_HIGH));
 
-       bits = sh_msiof_spi_bits(spi, t);
-       if (bits < 8)
-               return -EINVAL;
-       if (bits > 32)
-               return -EINVAL;
+       if (spi->cs_gpio >= 0)
+               gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
 
-       return spi_bitbang_setup_transfer(spi, t);
+       return 0;
 }
 
-static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
+static int sh_msiof_prepare_message(struct spi_master *master,
+                                   struct spi_message *msg)
 {
-       struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
-       int value;
-
-       /* chip select is active low unless SPI_CS_HIGH is set */
-       if (spi->mode & SPI_CS_HIGH)
-               value = (is_on == BITBANG_CS_ACTIVE) ? 1 : 0;
-       else
-               value = (is_on == BITBANG_CS_ACTIVE) ? 0 : 1;
-
-       if (is_on == BITBANG_CS_ACTIVE) {
-               if (!test_and_set_bit(0, &p->flags)) {
-                       pm_runtime_get_sync(&p->pdev->dev);
-                       clk_enable(p->clk);
-               }
-
-               /* Configure pins before asserting CS */
-               sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
-                                         !!(spi->mode & SPI_CPHA),
-                                         !!(spi->mode & SPI_3WIRE),
-                                         !!(spi->mode & SPI_LSB_FIRST),
-                                         !!(spi->mode & SPI_CS_HIGH));
-       }
+       struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
+       const struct spi_device *spi = msg->spi;
 
-       /* use spi->controller data for CS (same strategy as spi_gpio) */
-       gpio_set_value((uintptr_t)spi->controller_data, value);
-
-       if (is_on == BITBANG_CS_INACTIVE) {
-               if (test_and_clear_bit(0, &p->flags)) {
-                       clk_disable(p->clk);
-                       pm_runtime_put(&p->pdev->dev);
-               }
-       }
+       /* Configure pins before asserting CS */
+       sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
+                                 !!(spi->mode & SPI_CPHA),
+                                 !!(spi->mode & SPI_3WIRE),
+                                 !!(spi->mode & SPI_LSB_FIRST),
+                                 !!(spi->mode & SPI_CS_HIGH));
+       return 0;
 }
 
 static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
@@ -486,7 +508,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
        /* clear status bits */
        sh_msiof_reset_str(p);
 
-       /* shut down frame, tx/tx and clock signals */
+       /* shut down frame, rx/tx and clock signals */
        ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
        ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
        if (rx_buf)
@@ -504,9 +526,11 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
        return ret;
 }
 
-static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+static int sh_msiof_transfer_one(struct spi_master *master,
+                                struct spi_device *spi,
+                                struct spi_transfer *t)
 {
-       struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
+       struct sh_msiof_spi_priv *p = spi_master_get_devdata(master);
        void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int);
        void (*rx_fifo)(struct sh_msiof_spi_priv *, void *, int, int);
        int bits;
@@ -516,7 +540,7 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
        int n;
        bool swab;
 
-       bits = sh_msiof_spi_bits(spi, t);
+       bits = t->bits_per_word;
 
        if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
                bits = 32;
@@ -566,8 +590,7 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
        }
 
        /* setup clocks (clock already enabled in chipselect()) */
-       sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
-                                 sh_msiof_spi_hz(spi, t));
+       sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz);
 
        /* transfer in fifo sized chunks */
        words = t->len / bytes_per_word;
@@ -587,22 +610,36 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
                words -= n;
        }
 
-       return bytes_done;
-}
-
-static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
-                                 u32 word, u8 bits)
-{
-       BUG(); /* unused but needed by bitbang code */
        return 0;
 }
 
+static const struct sh_msiof_chipdata sh_data = {
+       .tx_fifo_size = 64,
+       .rx_fifo_size = 64,
+       .master_flags = 0,
+};
+
+static const struct sh_msiof_chipdata r8a779x_data = {
+       .tx_fifo_size = 64,
+       .rx_fifo_size = 256,
+       .master_flags = SPI_MASTER_MUST_TX,
+};
+
+static const struct of_device_id sh_msiof_match[] = {
+       { .compatible = "renesas,sh-msiof",        .data = &sh_data },
+       { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
+       { .compatible = "renesas,msiof-r8a7790",   .data = &r8a779x_data },
+       { .compatible = "renesas,msiof-r8a7791",   .data = &r8a779x_data },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sh_msiof_match);
+
 #ifdef CONFIG_OF
 static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
 {
        struct sh_msiof_spi_info *info;
        struct device_node *np = dev->of_node;
-       u32 num_cs = 0;
+       u32 num_cs = 1;
 
        info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL);
        if (!info) {
@@ -632,6 +669,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct spi_master *master;
+       const struct of_device_id *of_id;
        struct sh_msiof_spi_priv *p;
        int i;
        int ret;
@@ -645,10 +683,15 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        p = spi_master_get_devdata(master);
 
        platform_set_drvdata(pdev, p);
-       if (pdev->dev.of_node)
+
+       of_id = of_match_device(sh_msiof_match, &pdev->dev);
+       if (of_id) {
+               p->chipdata = of_id->data;
                p->info = sh_msiof_spi_parse_dt(&pdev->dev);
-       else
+       } else {
+               p->chipdata = (const void *)pdev->id_entry->driver_data;
                p->info = dev_get_platdata(&pdev->dev);
+       }
 
        if (!p->info) {
                dev_err(&pdev->dev, "failed to obtain device info\n");
@@ -686,49 +729,40 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       ret = clk_prepare(p->clk);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "unable to prepare clock\n");
-               goto err1;
-       }
-
        p->pdev = pdev;
        pm_runtime_enable(&pdev->dev);
 
-       /* The standard version of MSIOF use 64 word FIFOs */
-       p->tx_fifo_size = 64;
-       p->rx_fifo_size = 64;
-
        /* Platform data may override FIFO sizes */
+       p->tx_fifo_size = p->chipdata->tx_fifo_size;
+       p->rx_fifo_size = p->chipdata->rx_fifo_size;
        if (p->info->tx_fifo_override)
                p->tx_fifo_size = p->info->tx_fifo_override;
        if (p->info->rx_fifo_override)
                p->rx_fifo_size = p->info->rx_fifo_override;
 
-       /* init master and bitbang code */
+       /* init master code */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
-       master->flags = 0;
+       master->flags = p->chipdata->master_flags;
        master->bus_num = pdev->id;
+       master->dev.of_node = pdev->dev.of_node;
        master->num_chipselect = p->info->num_chipselect;
-       master->setup = spi_bitbang_setup;
-       master->cleanup = spi_bitbang_cleanup;
-
-       p->bitbang.master = master;
-       p->bitbang.chipselect = sh_msiof_spi_chipselect;
-       p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
-       p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
-       p->bitbang.txrx_word[SPI_MODE_0] = sh_msiof_spi_txrx_word;
-       p->bitbang.txrx_word[SPI_MODE_1] = sh_msiof_spi_txrx_word;
-       p->bitbang.txrx_word[SPI_MODE_2] = sh_msiof_spi_txrx_word;
-       p->bitbang.txrx_word[SPI_MODE_3] = sh_msiof_spi_txrx_word;
-
-       ret = spi_bitbang_start(&p->bitbang);
-       if (ret == 0)
-               return 0;
+       master->setup = sh_msiof_spi_setup;
+       master->prepare_message = sh_msiof_prepare_message;
+       master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
+       master->auto_runtime_pm = true;
+       master->transfer_one = sh_msiof_transfer_one;
+
+       ret = devm_spi_register_master(&pdev->dev, master);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "spi_register_master error.\n");
+               goto err2;
+       }
 
+       return 0;
+
+ err2:
        pm_runtime_disable(&pdev->dev);
-       clk_unprepare(p->clk);
  err1:
        spi_master_put(master);
        return ret;
@@ -736,30 +770,22 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 
 static int sh_msiof_spi_remove(struct platform_device *pdev)
 {
-       struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = spi_bitbang_stop(&p->bitbang);
-       if (!ret) {
-               pm_runtime_disable(&pdev->dev);
-               clk_unprepare(p->clk);
-               spi_master_put(p->bitbang.master);
-       }
-       return ret;
+       pm_runtime_disable(&pdev->dev);
+       return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id sh_msiof_match[] = {
-       { .compatible = "renesas,sh-msiof", },
-       { .compatible = "renesas,sh-mobile-msiof", },
+static struct platform_device_id spi_driver_ids[] = {
+       { "spi_sh_msiof",       (kernel_ulong_t)&sh_data },
+       { "spi_r8a7790_msiof",  (kernel_ulong_t)&r8a779x_data },
+       { "spi_r8a7791_msiof",  (kernel_ulong_t)&r8a779x_data },
        {},
 };
-MODULE_DEVICE_TABLE(of, sh_msiof_match);
-#endif
+MODULE_DEVICE_TABLE(platform, spi_driver_ids);
 
 static struct platform_driver sh_msiof_spi_drv = {
        .probe          = sh_msiof_spi_probe,
        .remove         = sh_msiof_spi_remove,
+       .id_table       = spi_driver_ids,
        .driver         = {
                .name           = "spi_sh_msiof",
                .owner          = THIS_MODULE,
index 85c2efd..8b44b71 100644 (file)
@@ -108,7 +108,7 @@ static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
 {
        struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
 
-       if (sp->info && sp->info->chip_select)
+       if (sp->info->chip_select)
                (sp->info->chip_select)(sp->info, dev->chip_select, value);
 }
 
@@ -130,6 +130,11 @@ static int sh_sci_spi_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, sp);
        sp->info = dev_get_platdata(&dev->dev);
+       if (!sp->info) {
+               dev_err(&dev->dev, "platform data is missing\n");
+               ret = -ENOENT;
+               goto err1;
+       }
 
        /* setup spi bitbang adaptor */
        sp->bitbang.master = master;
index e430689..1a77ad5 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-direction.h>
 #include <linux/dma-mapping.h>
-#include <linux/sirfsoc_dma.h>
 
 #define DRIVER_NAME "sirfsoc_spi"
 
 #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
        ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
 
+#define SIRFSOC_MAX_CMD_BYTES  4
+
 struct sirfsoc_spi {
        struct spi_bitbang bitbang;
        struct completion rx_done;
@@ -162,6 +163,12 @@ struct sirfsoc_spi {
        void *dummypage;
        int word_width; /* in bytes */
 
+       /*
+        * if tx size is not more than 4 and rx size is NULL, use
+        * command model
+        */
+       bool    tx_by_cmd;
+
        int chipselect[0];
 };
 
@@ -260,6 +267,12 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
 
        writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
+       if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) {
+               complete(&sspi->tx_done);
+               writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN);
+               return IRQ_HANDLED;
+       }
+
        /* Error Conditions */
        if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
                        spi_stat & SIRFSOC_SPI_TX_UFLOW) {
@@ -310,6 +323,34 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
 
        writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS);
 
+       /*
+        * fill tx_buf into command register and wait for its completion
+        */
+       if (sspi->tx_by_cmd) {
+               u32 cmd;
+               memcpy(&cmd, sspi->tx, t->len);
+
+               if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
+                       cmd = cpu_to_be32(cmd) >>
+                               ((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
+               if (sspi->word_width == 2 && t->len == 4 &&
+                               (!(spi->mode & SPI_LSB_FIRST)))
+                       cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
+
+               writel(cmd, sspi->base + SIRFSOC_SPI_CMD);
+               writel(SIRFSOC_SPI_FRM_END_INT_EN,
+                       sspi->base + SIRFSOC_SPI_INT_EN);
+               writel(SIRFSOC_SPI_CMD_TX_EN,
+                       sspi->base + SIRFSOC_SPI_TX_RX_EN);
+
+               if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
+                       dev_err(&spi->dev, "transfer timeout\n");
+                       return 0;
+               }
+
+               return t->len;
+       }
+
        if (sspi->left_tx_word == 1) {
                writel(readl(sspi->base + SIRFSOC_SPI_CTRL) |
                        SIRFSOC_SPI_ENA_AUTO_CLR,
@@ -459,11 +500,6 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8;
                sspi->rx_word = spi_sirfsoc_rx_word_u8;
                sspi->tx_word = spi_sirfsoc_tx_word_u8;
-               txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_BYTE;
-               rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_BYTE;
-               sspi->word_width = 1;
                break;
        case 12:
        case 16:
@@ -471,26 +507,22 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
                        SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
                sspi->rx_word = spi_sirfsoc_rx_word_u16;
                sspi->tx_word = spi_sirfsoc_tx_word_u16;
-               txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_WORD;
-               rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_WORD;
-               sspi->word_width = 2;
                break;
        case 32:
                regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
                sspi->rx_word = spi_sirfsoc_rx_word_u32;
                sspi->tx_word = spi_sirfsoc_tx_word_u32;
-               txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_DWORD;
-               rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                       SIRFSOC_SPI_FIFO_WIDTH_DWORD;
-               sspi->word_width = 4;
                break;
        default:
                BUG();
        }
 
+       sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
+       txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
+                                          sspi->word_width;
+       rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
+                                          sspi->word_width;
+
        if (!(spi->mode & SPI_CS_HIGH))
                regval |= SIRFSOC_SPI_CS_IDLE_STAT;
        if (!(spi->mode & SPI_LSB_FIRST))
@@ -519,6 +551,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL);
        writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL);
 
+       if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) {
+               regval |= (SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) |
+                               SIRFSOC_SPI_CMD_MODE);
+               sspi->tx_by_cmd = true;
+       } else {
+               regval &= ~SIRFSOC_SPI_CMD_MODE;
+               sspi->tx_by_cmd = false;
+       }
        writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
 
        if (IS_DMA_VALID(t)) {
@@ -548,8 +588,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct resource *mem_res;
        int num_cs, cs_gpio, irq;
-       u32 rx_dma_ch, tx_dma_ch;
-       dma_cap_mask_t dma_cap_mask;
        int i;
        int ret;
 
@@ -560,20 +598,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
                goto err_cs;
        }
 
-       ret = of_property_read_u32(pdev->dev.of_node,
-                       "sirf,spi-dma-rx-channel", &rx_dma_ch);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Unable to get rx dma channel\n");
-               goto err_cs;
-       }
-
-       ret = of_property_read_u32(pdev->dev.of_node,
-                       "sirf,spi-dma-tx-channel", &tx_dma_ch);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Unable to get tx dma channel\n");
-               goto err_cs;
-       }
-
        master = spi_alloc_master(&pdev->dev, sizeof(*sspi) + sizeof(int) * num_cs);
        if (!master) {
                dev_err(&pdev->dev, "Unable to allocate SPI master\n");
@@ -637,18 +661,13 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
        sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
 
        /* request DMA channels */
-       dma_cap_zero(dma_cap_mask);
-       dma_cap_set(DMA_INTERLEAVE, dma_cap_mask);
-
-       sspi->rx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
-               (void *)rx_dma_ch);
+       sspi->rx_chan = dma_request_slave_channel(&pdev->dev, "rx");
        if (!sspi->rx_chan) {
                dev_err(&pdev->dev, "can not allocate rx dma channel\n");
                ret = -ENODEV;
                goto free_master;
        }
-       sspi->tx_chan = dma_request_channel(dma_cap_mask, (dma_filter_fn)sirfsoc_dma_filter_id,
-               (void *)tx_dma_ch);
+       sspi->tx_chan = dma_request_slave_channel(&pdev->dev, "tx");
        if (!sspi->tx_chan) {
                dev_err(&pdev->dev, "can not allocate tx dma channel\n");
                ret = -ENODEV;
@@ -724,11 +743,16 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int spi_sirfsoc_suspend(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
        struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
+       int ret;
+
+       ret = spi_master_suspend(master);
+       if (ret)
+               return ret;
 
        clk_disable(sspi->clk);
        return 0;
@@ -745,15 +769,13 @@ static int spi_sirfsoc_resume(struct device *dev)
        writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_RXFIFO_OP);
        writel(SIRFSOC_SPI_FIFO_START, sspi->base + SIRFSOC_SPI_TXFIFO_OP);
 
-       return 0;
+       return spi_master_resume(master);
 }
-
-static const struct dev_pm_ops spi_sirfsoc_pm_ops = {
-       .suspend = spi_sirfsoc_suspend,
-       .resume = spi_sirfsoc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend,
+                        spi_sirfsoc_resume);
+
 static const struct of_device_id spi_sirfsoc_of_match[] = {
        { .compatible = "sirf,prima2-spi", },
        { .compatible = "sirf,marco-spi", },
@@ -765,9 +787,7 @@ static struct platform_driver spi_sirfsoc_driver = {
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &spi_sirfsoc_pm_ops,
-#endif
                .of_match_table = spi_sirfsoc_of_match,
        },
        .probe = spi_sirfsoc_probe,
index d7c6e36..e3bc23b 100644 (file)
@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
  */
 #define SPI_MODE_MASK          (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
                                | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
-                               | SPI_NO_CS | SPI_READY)
+                               | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
+                               | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
 
 struct spidev_data {
        dev_t                   devt;
@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev,
                buf += k_tmp->len;
 
                k_tmp->cs_change = !!u_tmp->cs_change;
+               k_tmp->tx_nbits = u_tmp->tx_nbits;
+               k_tmp->rx_nbits = u_tmp->rx_nbits;
                k_tmp->bits_per_word = u_tmp->bits_per_word;
                k_tmp->delay_usecs = u_tmp->delay_usecs;
                k_tmp->speed_hz = u_tmp->speed_hz;
@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                retval = __put_user(spi->mode & SPI_MODE_MASK,
                                        (__u8 __user *)arg);
                break;
+       case SPI_IOC_RD_MODE32:
+               retval = __put_user(spi->mode & SPI_MODE_MASK,
+                                       (__u32 __user *)arg);
+               break;
        case SPI_IOC_RD_LSB_FIRST:
                retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
                                        (__u8 __user *)arg);
@@ -372,9 +379,13 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
        /* write requests */
        case SPI_IOC_WR_MODE:
-               retval = __get_user(tmp, (u8 __user *)arg);
+       case SPI_IOC_WR_MODE32:
+               if (cmd == SPI_IOC_WR_MODE)
+                       retval = __get_user(tmp, (u8 __user *)arg);
+               else
+                       retval = __get_user(tmp, (u32 __user *)arg);
                if (retval == 0) {
-                       u     save = spi->mode;
+                       u32     save = spi->mode;
 
                        if (tmp & ~SPI_MODE_MASK) {
                                retval = -EINVAL;
@@ -382,18 +393,18 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        }
 
                        tmp |= spi->mode & ~SPI_MODE_MASK;
-                       spi->mode = (u8)tmp;
+                       spi->mode = (u16)tmp;
                        retval = spi_setup(spi);
                        if (retval < 0)
                                spi->mode = save;
                        else
-                               dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
+                               dev_dbg(&spi->dev, "spi mode %x\n", tmp);
                }
                break;
        case SPI_IOC_WR_LSB_FIRST:
                retval = __get_user(tmp, (__u8 __user *)arg);
                if (retval == 0) {
-                       u     save = spi->mode;
+                       u32     save = spi->mode;
 
                        if (tmp)
                                spi->mode |= SPI_LSB_FIRST;
index 8447f63..d3889b9 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
- *
+/*
  * Copyright (C) 2009 Samsung Electronics Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -8,8 +7,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __S3C64XX_PLAT_SPI_H
-#define __S3C64XX_PLAT_SPI_H
+#ifndef __SPI_S3C64XX_H
+#define __SPI_S3C64XX_H
 
 #include <linux/dmaengine.h>
 
@@ -68,4 +67,4 @@ extern int s3c64xx_spi2_cfg_gpio(void);
 extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
-#endif /* __S3C64XX_PLAT_SPI_H */
+#endif /*__SPI_S3C64XX_H */
index 52d9ed0..dd5f21e 100644 (file)
 #define SPI_LOOP               0x20
 #define SPI_NO_CS              0x40
 #define SPI_READY              0x80
+#define SPI_TX_DUAL            0x100
+#define SPI_TX_QUAD            0x200
+#define SPI_RX_DUAL            0x400
+#define SPI_RX_QUAD            0x800
 
 /*---------------------------------------------------------------------------*/
 
@@ -92,7 +96,9 @@ struct spi_ioc_transfer {
        __u16           delay_usecs;
        __u8            bits_per_word;
        __u8            cs_change;
-       __u32           pad;
+       __u8            tx_nbits;
+       __u8            rx_nbits;
+       __u16           pad;
 
        /* If the contents of 'struct spi_ioc_transfer' ever change
         * incompatibly, then the ioctl number (currently 0) must change;
@@ -110,7 +116,7 @@ struct spi_ioc_transfer {
 #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
 
 
-/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
+/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
 #define SPI_IOC_RD_MODE                        _IOR(SPI_IOC_MAGIC, 1, __u8)
 #define SPI_IOC_WR_MODE                        _IOW(SPI_IOC_MAGIC, 1, __u8)
 
@@ -126,6 +132,10 @@ struct spi_ioc_transfer {
 #define SPI_IOC_RD_MAX_SPEED_HZ                _IOR(SPI_IOC_MAGIC, 4, __u32)
 #define SPI_IOC_WR_MAX_SPEED_HZ                _IOW(SPI_IOC_MAGIC, 4, __u32)
 
+/* Read / Write of the SPI mode field */
+#define SPI_IOC_RD_MODE32              _IOR(SPI_IOC_MAGIC, 5, __u32)
+#define SPI_IOC_WR_MODE32              _IOW(SPI_IOC_MAGIC, 5, __u32)
+
 
 
 #endif /* SPIDEV_H */