spi: ti_qspi: Convert to spi-mem ops
authorVignesh Raghavendra <vigneshr@ti.com>
Tue, 16 Apr 2019 16:02:00 +0000 (21:32 +0530)
committerJagan Teki <jagan@amarulasolutions.com>
Wed, 17 Apr 2019 12:13:54 +0000 (17:43 +0530)
Convert driver to use  spi-mem ops in order to support accelerated MMIO
flash interface in generic way and for better performance.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Acked-by: Jagan Teki <jagan@amarulasolutions.com>
drivers/spi/ti_qspi.c

index 731fb23022d2bff3a21d53d0dc217027942232f1..77fa17ee8ab1466c0ffd4e962611821b98295a54 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/arch/omap.h>
 #include <malloc.h>
 #include <spi.h>
+#include <spi-mem.h>
 #include <dm.h>
 #include <asm/gpio.h>
 #include <asm/omap_gpio.h>
@@ -40,7 +41,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define QSPI_INVAL                      (4 << 16)
 #define QSPI_RD_QUAD                    (7 << 16)
 /* device control */
-#define QSPI_DD(m, n)                   (m << (3 + n*8))
 #define QSPI_CKPHA(n)                   (1 << (2 + n*8))
 #define QSPI_CSPOL(n)                   (1 << (1 + n*8))
 #define QSPI_CKPOL(n)                   (1 << (n*8))
@@ -53,18 +53,11 @@ DECLARE_GLOBAL_DATA_PTR;
 #define MEM_CS(cs)                      ((cs + 1) << 8)
 #define MEM_CS_UNSELECT                 0xfffff8ff
 
-#define QSPI_CMD_READ                   (0x3 << 0)
-#define QSPI_CMD_READ_DUAL             (0x6b << 0)
-#define QSPI_CMD_READ_QUAD              (0x6c << 0)
-#define QSPI_CMD_READ_FAST              (0x0b << 0)
-#define QSPI_SETUP0_NUM_A_BYTES         (0x3 << 8)
-#define QSPI_SETUP0_NUM_D_BYTES_NO_BITS (0x0 << 10)
-#define QSPI_SETUP0_NUM_D_BYTES_8_BITS  (0x1 << 10)
 #define QSPI_SETUP0_READ_NORMAL         (0x0 << 12)
 #define QSPI_SETUP0_READ_DUAL           (0x1 << 12)
 #define QSPI_SETUP0_READ_QUAD           (0x3 << 12)
-#define QSPI_CMD_WRITE                  (0x12 << 16)
-#define QSPI_NUM_DUMMY_BITS             (0x0 << 24)
+#define QSPI_SETUP0_ADDR_SHIFT         (8)
+#define QSPI_SETUP0_DBITS_SHIFT                (10)
 
 /* ti qspi register set */
 struct ti_qspi_regs {
@@ -96,6 +89,7 @@ struct ti_qspi_regs {
 /* ti qspi priv */
 struct ti_qspi_priv {
        void *memory_map;
+       size_t mmap_size;
        uint max_hz;
        u32 num_cs;
        struct ti_qspi_regs *base;
@@ -171,19 +165,6 @@ static int ti_qspi_xfer(struct udevice *dev, unsigned int bitlen,
                return -EINVAL;
        }
 
-       /* Setup mmap flags */
-       if (flags & SPI_XFER_MMAP) {
-               writel(MM_SWITCH, &priv->base->memswitch);
-               if (priv->ctrl_mod_mmap)
-                       ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap, cs, true);
-               return 0;
-       } else if (flags & SPI_XFER_MMAP_END) {
-               writel(~MM_SWITCH, &priv->base->memswitch);
-               if (priv->ctrl_mod_mmap)
-                       ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap, cs, false);
-               return 0;
-       }
-
        if (bitlen == 0)
                return -1;
 
@@ -269,9 +250,9 @@ static int ti_qspi_xfer(struct udevice *dev, unsigned int bitlen,
 }
 
 /* TODO: control from sf layer to here through dm-spi */
-#if defined(CONFIG_TI_EDMA3) && !defined(CONFIG_DMA)
-void spi_flash_copy_mmap(void *data, void *offset, size_t len)
+static void ti_qspi_copy_mmap(void *data, void *offset, size_t len)
 {
+#if defined(CONFIG_TI_EDMA3) && !defined(CONFIG_DMA)
        unsigned int                    addr = (unsigned int) (data);
        unsigned int                    edma_slot_num = 1;
 
@@ -286,44 +267,34 @@ void spi_flash_copy_mmap(void *data, void *offset, size_t len)
 
        /* disable edma3 clocks */
        disable_edma3_clocks();
+#else
+       memcpy_fromio(data, offset, len);
+#endif
 
        *((unsigned int *)offset) += len;
 }
-#endif
 
-static void __ti_qspi_setup_memorymap(struct ti_qspi_priv *priv,
-                                     struct spi_slave *slave,
-                                     bool enable)
+static void ti_qspi_setup_mmap_read(struct ti_qspi_priv *priv, u8 opcode,
+                                   u8 data_nbits, u8 addr_width,
+                                   u8 dummy_bytes)
 {
-       u32 memval;
-       u32 mode = slave->mode & (SPI_RX_QUAD | SPI_RX_DUAL);
+       u32 memval = opcode;
 
-       if (!enable) {
-               writel(0, &priv->base->setup0);
-               return;
-       }
-
-       memval = QSPI_SETUP0_NUM_A_BYTES | QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS;
-
-       switch (mode) {
-       case SPI_RX_QUAD:
-               memval |= QSPI_CMD_READ_QUAD;
-               memval |= QSPI_SETUP0_NUM_D_BYTES_8_BITS;
+       switch (data_nbits) {
+       case 4:
                memval |= QSPI_SETUP0_READ_QUAD;
-               slave->mode |= SPI_RX_QUAD;
                break;
-       case SPI_RX_DUAL:
-               memval |= QSPI_CMD_READ_DUAL;
-               memval |= QSPI_SETUP0_NUM_D_BYTES_8_BITS;
+       case 2:
                memval |= QSPI_SETUP0_READ_DUAL;
                break;
        default:
-               memval |= QSPI_CMD_READ;
-               memval |= QSPI_SETUP0_NUM_D_BYTES_NO_BITS;
                memval |= QSPI_SETUP0_READ_NORMAL;
                break;
        }
 
+       memval |= ((addr_width - 1) << QSPI_SETUP0_ADDR_SHIFT |
+                  dummy_bytes << QSPI_SETUP0_DBITS_SHIFT);
+
        writel(memval, &priv->base->setup0);
 }
 
@@ -342,10 +313,39 @@ static int ti_qspi_set_mode(struct udevice *bus, uint mode)
        return 0;
 }
 
+static int ti_qspi_exec_mem_op(struct spi_slave *slave,
+                              const struct spi_mem_op *op)
+{
+       struct ti_qspi_priv *priv;
+       struct udevice *bus;
+
+       bus = slave->dev->parent;
+       priv = dev_get_priv(bus);
+       u32 from = 0;
+       int ret = 0;
+
+       /* Only optimize read path. */
+       if (!op->data.nbytes || op->data.dir != SPI_MEM_DATA_IN ||
+           !op->addr.nbytes || op->addr.nbytes > 4)
+               return -ENOTSUPP;
+
+       /* Address exceeds MMIO window size, fall back to regular mode. */
+       from = op->addr.val;
+       if (from + op->data.nbytes > priv->mmap_size)
+               return -ENOTSUPP;
+
+       ti_qspi_setup_mmap_read(priv, op->cmd.opcode, op->data.buswidth,
+                               op->addr.nbytes, op->dummy.nbytes);
+
+       ti_qspi_copy_mmap((void *)op->data.buf.in,
+                         (void *)priv->memory_map + from, op->data.nbytes);
+
+       return ret;
+}
+
 static int ti_qspi_claim_bus(struct udevice *dev)
 {
        struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
-       struct spi_slave *slave = dev_get_parent_priv(dev);
        struct ti_qspi_priv *priv;
        struct udevice *bus;
 
@@ -357,7 +357,10 @@ static int ti_qspi_claim_bus(struct udevice *dev)
                return -EINVAL;
        }
 
-       __ti_qspi_setup_memorymap(priv, slave, true);
+       writel(MM_SWITCH, &priv->base->memswitch);
+       if (priv->ctrl_mod_mmap)
+               ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap,
+                                      slave_plat->cs, true);
 
        writel(priv->dc, &priv->base->dc);
        writel(0, &priv->base->cmd);
@@ -371,18 +374,22 @@ static int ti_qspi_claim_bus(struct udevice *dev)
 
 static int ti_qspi_release_bus(struct udevice *dev)
 {
-       struct spi_slave *slave = dev_get_parent_priv(dev);
+       struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
        struct ti_qspi_priv *priv;
        struct udevice *bus;
 
        bus = dev->parent;
        priv = dev_get_priv(bus);
 
-       __ti_qspi_setup_memorymap(priv, slave, false);
+       writel(~MM_SWITCH, &priv->base->memswitch);
+       if (priv->ctrl_mod_mmap)
+               ti_qspi_ctrl_mode_mmap(priv->ctrl_mod_mmap,
+                                      slave_plat->cs, false);
 
        writel(0, &priv->base->dc);
        writel(0, &priv->base->cmd);
        writel(0, &priv->base->data);
+       writel(0, &priv->base->setup0);
 
        return 0;
 }
@@ -440,12 +447,15 @@ static int ti_qspi_ofdata_to_platdata(struct udevice *bus)
        struct ti_qspi_priv *priv = dev_get_priv(bus);
        const void *blob = gd->fdt_blob;
        int node = dev_of_offset(bus);
+       fdt_addr_t mmap_addr;
+       fdt_addr_t mmap_size;
 
        priv->ctrl_mod_mmap = map_syscon_chipselects(bus);
        priv->base = map_physmem(devfdt_get_addr(bus),
                                 sizeof(struct ti_qspi_regs), MAP_NOCACHE);
-       priv->memory_map = map_physmem(devfdt_get_addr_index(bus, 1), 0,
-                                      MAP_NOCACHE);
+       mmap_addr = devfdt_get_addr_size_index(bus, 1, &mmap_size);
+       priv->memory_map = map_physmem(mmap_addr, mmap_size, MAP_NOCACHE);
+       priv->mmap_size = mmap_size;
 
        priv->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", -1);
        if (priv->max_hz < 0) {
@@ -460,15 +470,9 @@ static int ti_qspi_ofdata_to_platdata(struct udevice *bus)
        return 0;
 }
 
-static int ti_qspi_child_pre_probe(struct udevice *dev)
-{
-       struct spi_slave *slave = dev_get_parent_priv(dev);
-       struct udevice *bus = dev_get_parent(dev);
-       struct ti_qspi_priv *priv = dev_get_priv(bus);
-
-       slave->memory_map = priv->memory_map;
-       return 0;
-}
+static const struct spi_controller_mem_ops ti_qspi_mem_ops = {
+       .exec_op = ti_qspi_exec_mem_op,
+};
 
 static const struct dm_spi_ops ti_qspi_ops = {
        .claim_bus      = ti_qspi_claim_bus,
@@ -476,6 +480,7 @@ static const struct dm_spi_ops ti_qspi_ops = {
        .xfer           = ti_qspi_xfer,
        .set_speed      = ti_qspi_set_speed,
        .set_mode       = ti_qspi_set_mode,
+       .mem_ops        = &ti_qspi_mem_ops,
 };
 
 static const struct udevice_id ti_qspi_ids[] = {
@@ -492,5 +497,4 @@ U_BOOT_DRIVER(ti_qspi) = {
        .ofdata_to_platdata = ti_qspi_ofdata_to_platdata,
        .priv_auto_alloc_size = sizeof(struct ti_qspi_priv),
        .probe  = ti_qspi_probe,
-       .child_pre_probe = ti_qspi_child_pre_probe,
 };