summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index ea371b0f56ab..47f675098d63 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -41,6 +41,8 @@
#define QUADSPI_QUIRK_TKT253890 (1 << 2)
/* Controller cannot wake up from wait mode, TKT245618 */
#define QUADSPI_QUIRK_TKT245618 (1 << 3)
+/* Need low level code to control the clock */
+#define QUADSPI_QUIRK_LL_CLK (1 << 4)
/* The registers */
#define QUADSPI_MCR 0x00
@@ -220,7 +222,7 @@
#define SEQID_DYNAMIC_CMD0 14
#define SEQID_DYNAMIC_CMD1 15
-#define QUADSPI_MIN_IOMAP SZ_4M
+#define QUADSPI_MIN_IOMAP SZ_4M
/* dynamic lut configs */
#define MAX_LUT_REGS 4
@@ -255,6 +257,7 @@ enum fsl_qspi_devtype {
FSL_QUADSPI_IMX7D,
FSL_QUADSPI_IMX6UL,
FSL_QUADSPI_LS1021A,
+ FSL_QUADSPI_IMX7ULP,
};
struct fsl_qspi_devtype_data {
@@ -308,6 +311,15 @@ static struct fsl_qspi_devtype_data ls1021a_data = {
.driver_data = 0,
};
+static struct fsl_qspi_devtype_data imx7ulp_data = {
+ .devtype = FSL_QUADSPI_IMX7ULP,
+ .rxfifo = 64,
+ .txfifo = 64,
+ .ahb_buf_size = 128,
+ .driver_data = QUADSPI_QUIRK_LL_CLK
+ | QUADSPI_QUIRK_TKT253890
+};
+
#define FSL_QSPI_MAX_CHIP 4
struct fsl_qspi {
struct spi_nor nor[FSL_QSPI_MAX_CHIP];
@@ -351,6 +363,11 @@ static inline int needs_wakeup_wait_mode(struct fsl_qspi *q)
return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618;
}
+static inline int needs_ll_handle_clock(struct fsl_qspi *q)
+{
+ return q->devtype_data->driver_data & QUADSPI_QUIRK_LL_CLK;
+}
+
/*
* R/W functions for big- or little-endian registers:
* The qSPI controller's endian is independent of the CPU core's endian.
@@ -441,6 +458,11 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q)
} else {
dev_err(nor->dev, "Unsupported opcode : 0x%.2x\n", op);
}
+ } else if (nor->flash_read == SPI_NOR_NORMAL) {
+ writel(LUT0(CMD, PAD1, op) | LUT1(ADDR, PAD1, addrlen),
+ base + QUADSPI_LUT(lut_base));
+ writel(LUT0(FSL_READ, PAD1, rxfifo) | LUT1(JMP_ON_CS, PAD1, 0),
+ base + QUADSPI_LUT(lut_base + 1));
} else if (nor->flash_read == SPI_NOR_DDR_QUAD) {
if (op == SPINOR_OP_READ_1_4_4_D ||
op == SPINOR_OP_READ4_1_4_4_D) {
@@ -612,6 +634,7 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
case SPINOR_OP_READ4_1_4_4_D:
case SPINOR_OP_READ4_1_1_4:
case SPINOR_OP_READ_1_1_4:
+ case SPINOR_OP_READ:
return SEQID_QUAD_READ;
case SPINOR_OP_WREN:
return SEQID_WREN;
@@ -919,7 +942,7 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q)
/* the default frequency, we will change it in the future. */
ret = clk_set_rate(q->clk, 66000000);
- if (ret)
+ if (ret && !needs_ll_handle_clock(q))
return ret;
ret = fsl_qspi_clk_prep_enable(q);
@@ -977,7 +1000,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
fsl_qspi_clk_disable_unprep(q);
ret = clk_set_rate(q->clk, rate);
- if (ret)
+ if (ret && !needs_ll_handle_clock(q))
return ret;
ret = fsl_qspi_clk_prep_enable(q);
@@ -1001,6 +1024,7 @@ static const struct of_device_id fsl_qspi_dt_ids[] = {
{ .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, },
{ .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, },
{ .compatible = "fsl,imx6ull-qspi", .data = (void *)&imx6ul_data, },
+ { .compatible = "fsl,imx7ulp-qspi", .data = (void *)&imx7ulp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);