Merge branch '2021-02-02-drop-asm_global_data-when-unused'
[platform/kernel/u-boot.git] / drivers / spi / fsl_qspi.c
index d9f531a..3f97730 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
 #include <log.h>
-#include <asm/io.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <asm/global_data.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/libfdt.h>
 #include <linux/sizes.h>
 #include <linux/iopoll.h>
-#include <dm.h>
 #include <linux/iopoll.h>
 #include <linux/sizes.h>
 #include <linux/err.h>
-#include <spi.h>
-#include <spi-mem.h>
+#include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -46,6 +48,7 @@ DECLARE_GLOBAL_DATA_PTR;
  * read operation, so let's use the last entry (15).
  */
 #define        SEQID_LUT                       15
+#define        SEQID_LUT_AHB           14
 
 /* Registers used by the driver */
 #define QUADSPI_MCR                    0x00
@@ -122,6 +125,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define QUADSPI_LUT_REG(idx) \
        (QUADSPI_LUT_BASE + QUADSPI_LUT_OFFSET + (idx) * 4)
 
+#define QUADSPI_AHB_LUT_OFFSET         (SEQID_LUT_AHB * 4 * 4)
+#define QUADSPI_AHB_LUT_REG(idx) \
+       (QUADSPI_LUT_BASE + QUADSPI_AHB_LUT_OFFSET + (idx) * 4)
+
 /* Instruction set for the LUT register */
 #define LUT_STOP               0
 #define LUT_CMD                        1
@@ -189,6 +196,11 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 #define QUADSPI_QUIRK_USE_TDH_SETTING  BIT(5)
 
+/*
+ * Controller only has Two CS on flash A, no flash B port
+ */
+#define QUADSPI_QUIRK_SINGLE_BUS               BIT(6)
+
 struct fsl_qspi_devtype_data {
        unsigned int rxfifo;
        unsigned int txfifo;
@@ -236,7 +248,7 @@ static const struct fsl_qspi_devtype_data imx7ulp_data = {
        .txfifo = SZ_64,
        .ahb_buf_size = SZ_128,
        .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK |
-                 QUADSPI_QUIRK_USE_TDH_SETTING,
+                 QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_SINGLE_BUS,
        .little_endian = true,
 };
 
@@ -248,14 +260,6 @@ static const struct fsl_qspi_devtype_data ls1021a_data = {
        .little_endian = false,
 };
 
-static const struct fsl_qspi_devtype_data ls1088a_data = {
-       .rxfifo = SZ_128,
-       .txfifo = SZ_128,
-       .ahb_buf_size = SZ_1K,
-       .quirks = QUADSPI_QUIRK_TKT253890,
-       .little_endian = true,
-};
-
 static const struct fsl_qspi_devtype_data ls2080a_data = {
        .rxfifo = SZ_128,
        .txfifo = SZ_64,
@@ -269,6 +273,7 @@ struct fsl_qspi {
        void __iomem *iobase;
        void __iomem *ahb_addr;
        u32 memmap_phy;
+       u32 memmap_size;
        const struct fsl_qspi_devtype_data *devtype_data;
        int selected;
 };
@@ -303,6 +308,11 @@ static inline int needs_tdh_setting(struct fsl_qspi *q)
        return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING;
 }
 
+static inline int needs_single_bus(struct fsl_qspi *q)
+{
+       return q->devtype_data->quirks & QUADSPI_QUIRK_SINGLE_BUS;
+}
+
 /*
  * An IC bug makes it necessary to rearrange the 32-bit data.
  * Later chips, such as IMX6SLX, have fixed this bug.
@@ -392,7 +402,7 @@ static bool fsl_qspi_supports_op(struct spi_slave *slave,
            op->data.nbytes > q->devtype_data->txfifo)
                return false;
 
-       return true;
+       return spi_mem_default_supports_op(slave, op);
 }
 
 static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
@@ -405,18 +415,27 @@ static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
        lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
                             op->cmd.opcode);
 
-       /*
-        * For some unknown reason, using LUT_ADDR doesn't work in some
-        * cases (at least with only one byte long addresses), so
-        * let's use LUT_MODE to write the address bytes one by one
-        */
-       for (i = 0; i < op->addr.nbytes; i++) {
-               u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
-
-               lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE,
-                                             LUT_PAD(op->addr.buswidth),
-                                             addrbyte);
-               lutidx++;
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+               if (op->addr.nbytes) {
+                       lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_ADDR,
+                                                     LUT_PAD(op->addr.buswidth),
+                                                     (op->addr.nbytes == 4) ? 0x20 : 0x18);
+                       lutidx++;
+               }
+       } else {
+               /*
+                * For some unknown reason, using LUT_ADDR doesn't work in some
+                * cases (at least with only one byte long addresses), so
+                * let's use LUT_MODE to write the address bytes one by one
+                */
+               for (i = 0; i < op->addr.nbytes; i++) {
+                       u8 addrbyte = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
+
+                       lutval[lutidx / 2] |= LUT_DEF(lutidx, LUT_MODE,
+                                                     LUT_PAD(op->addr.buswidth),
+                                                     addrbyte);
+                       lutidx++;
+               }
        }
 
        if (op->dummy.nbytes) {
@@ -449,6 +468,14 @@ static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
        for (i = 0; i < ARRAY_SIZE(lutval); i++)
                qspi_writel(q, lutval[i], base + QUADSPI_LUT_REG(i));
 
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+               if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN &&
+                   op->addr.nbytes) {
+                       for (i = 0; i < ARRAY_SIZE(lutval); i++)
+                               qspi_writel(q, lutval[i], base + QUADSPI_AHB_LUT_REG(i));
+               }
+       }
+
        /* lock LUT */
        qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
        qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
@@ -481,8 +508,8 @@ static void fsl_qspi_invalidate(struct fsl_qspi *q)
 
 static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_slave *slave)
 {
-       struct dm_spi_slave_platdata *plat =
-               dev_get_parent_platdata(slave->dev);
+       struct dm_spi_slave_plat *plat =
+               dev_get_parent_plat(slave->dev);
 
        if (q->selected == plat->cs)
                return;
@@ -491,10 +518,29 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_slave *slave)
        fsl_qspi_invalidate(q);
 }
 
+static u32 fsl_qspi_memsize_per_cs(struct fsl_qspi *q)
+{
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+               if (needs_single_bus(q))
+                       return q->memmap_size / 2;
+               else
+                       return q->memmap_size / 4;
+       } else {
+               return ALIGN(q->devtype_data->ahb_buf_size, 0x400);
+       }
+}
+
 static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
 {
+       void __iomem *ahb_read_addr = q->ahb_addr;
+
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+               if (op->addr.nbytes)
+                       ahb_read_addr += op->addr.val;
+       }
+
        memcpy_fromio(op->data.buf.in,
-                     q->ahb_addr + q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400),
+                     ahb_read_addr + q->selected * fsl_qspi_memsize_per_cs(q),
                      op->data.nbytes);
 }
 
@@ -597,8 +643,13 @@ static int fsl_qspi_exec_op(struct spi_slave *slave,
        if (needs_amba_base_offset(q))
                addr_offset = q->memmap_phy;
 
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP)) {
+               if (op->addr.nbytes)
+                       addr_offset += op->addr.val;
+       }
+
        qspi_writel(q,
-                   q->selected * ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
+                   q->selected * fsl_qspi_memsize_per_cs(q) + addr_offset,
                    base + QUADSPI_SFAR);
 
        qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
@@ -655,7 +706,7 @@ static int fsl_qspi_adjust_op_size(struct spi_slave *slave,
 static int fsl_qspi_default_setup(struct fsl_qspi *q)
 {
        void __iomem *base = q->iobase;
-       u32 reg, addr_offset = 0;
+       u32 reg, addr_offset = 0, memsize_cs;
 
        /* Reset the module */
        qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
@@ -687,8 +738,13 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
        qspi_writel(q, 0, base + QUADSPI_BUF1IND);
        qspi_writel(q, 0, base + QUADSPI_BUF2IND);
 
-       qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
-                   q->iobase + QUADSPI_BFGENCR);
+       if (IS_ENABLED(CONFIG_FSL_QSPI_AHB_FULL_MAP))
+               qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT_AHB),
+                           q->iobase + QUADSPI_BFGENCR);
+       else
+               qspi_writel(q, QUADSPI_BFGENCR_SEQID(SEQID_LUT),
+                           q->iobase + QUADSPI_BFGENCR);
+
        qspi_writel(q, QUADSPI_RBCT_WMRK_MASK, base + QUADSPI_RBCT);
        qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
                    QUADSPI_BUF3CR_ADATSZ(q->devtype_data->ahb_buf_size / 8),
@@ -704,14 +760,17 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
         * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
         * SFB2AD accordingly.
         */
-       qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) + addr_offset,
+       memsize_cs = fsl_qspi_memsize_per_cs(q);
+       qspi_writel(q, memsize_cs + addr_offset,
                    base + QUADSPI_SFA1AD);
-       qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 2 + addr_offset,
+       qspi_writel(q, memsize_cs * 2 + addr_offset,
                    base + QUADSPI_SFA2AD);
-       qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 3 + addr_offset,
-                   base + QUADSPI_SFB1AD);
-       qspi_writel(q, ALIGN(q->devtype_data->ahb_buf_size, 0x400) * 4 + addr_offset,
-                   base + QUADSPI_SFB2AD);
+       if (!needs_single_bus(q)) {
+               qspi_writel(q, memsize_cs * 3 + addr_offset,
+                           base + QUADSPI_SFB1AD);
+               qspi_writel(q, memsize_cs * 4 + addr_offset,
+                           base + QUADSPI_SFB2AD);
+       }
 
        q->selected = -1;
 
@@ -729,7 +788,7 @@ static const struct spi_controller_mem_ops fsl_qspi_mem_ops = {
 
 static int fsl_qspi_probe(struct udevice *bus)
 {
-       struct dm_spi_bus *dm_bus = bus->uclass_priv;
+       struct dm_spi_bus *dm_bus = dev_get_uclass_priv(bus);
        struct fsl_qspi *q = dev_get_priv(bus);
        const void *blob = gd->fdt_blob;
        int node = dev_of_offset(bus);
@@ -759,6 +818,7 @@ static int fsl_qspi_probe(struct udevice *bus)
 
        q->ahb_addr = map_physmem(res.start, res.end - res.start, MAP_NOCACHE);
        q->memmap_phy = res.start;
+       q->memmap_size = res.end - res.start;
 
        dm_bus->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
                                        66000000);
@@ -810,7 +870,7 @@ static const struct udevice_id fsl_qspi_ids[] = {
        { .compatible = "fsl,imx7d-qspi", .data = (ulong)&imx7d_data, },
        { .compatible = "fsl,imx7ulp-qspi", .data = (ulong)&imx7ulp_data, },
        { .compatible = "fsl,ls1021a-qspi", .data = (ulong)&ls1021a_data, },
-       { .compatible = "fsl,ls1088a-qspi", .data = (ulong)&ls1088a_data, },
+       { .compatible = "fsl,ls1088a-qspi", .data = (ulong)&ls2080a_data, },
        { .compatible = "fsl,ls2080a-qspi", .data = (ulong)&ls2080a_data, },
        { }
 };
@@ -820,6 +880,6 @@ U_BOOT_DRIVER(fsl_qspi) = {
        .id     = UCLASS_SPI,
        .of_match = fsl_qspi_ids,
        .ops    = &fsl_qspi_ops,
-       .priv_auto_alloc_size = sizeof(struct fsl_qspi),
+       .priv_auto      = sizeof(struct fsl_qspi),
        .probe  = fsl_qspi_probe,
 };