Message ID | 20240905094338.1986871-3-haibo.chen@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fix the flexspi error on imx8ulp | expand |
On Thu, Sep 05, 2024 at 05:43:36PM +0800, haibo.chen@nxp.com wrote: > From: Haibo Chen <haibo.chen@nxp.com> > > The flexspi on different SoCs may have different number of LUTs. > So involve lut_num in nxp_fspi_devtype_data to make distinguish. > This patch prepare for the adding of imx8ulp. > > Fixes: ef89fd56bdfc ("arm64: dts: imx8ulp: add flexspi node") > Cc: stable@kernel.org > Signed-off-by: Haibo Chen <haibo.chen@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> > --- > drivers/spi/spi-nxp-fspi.c | 44 ++++++++++++++++++++++---------------- > 1 file changed, 25 insertions(+), 19 deletions(-) > > diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c > index fd1816befcd8..f42c14d80289 100644 > --- a/drivers/spi/spi-nxp-fspi.c > +++ b/drivers/spi/spi-nxp-fspi.c > @@ -57,13 +57,6 @@ > #include <linux/spi/spi.h> > #include <linux/spi/spi-mem.h> > > -/* > - * The driver only uses one single LUT entry, that is updated on > - * each call of exec_op(). Index 0 is preset at boot with a basic > - * read operation, so let's use the last entry (31). > - */ > -#define SEQID_LUT 31 > - > /* Registers used by the driver */ > #define FSPI_MCR0 0x00 > #define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) > @@ -263,9 +256,6 @@ > #define FSPI_TFDR 0x180 > > #define FSPI_LUT_BASE 0x200 > -#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) > -#define FSPI_LUT_REG(idx) \ > - (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) > > /* register map end */ > > @@ -341,6 +331,7 @@ struct nxp_fspi_devtype_data { > unsigned int txfifo; > unsigned int ahb_buf_size; > unsigned int quirks; > + unsigned int lut_num; > bool little_endian; > }; > > @@ -349,6 +340,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { > .txfifo = SZ_1K, /* (128 * 64 bits) */ > .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ > .quirks = 0, > + .lut_num = 32, > .little_endian = true, /* little-endian */ > }; > > @@ -357,6 +349,7 @@ static struct nxp_fspi_devtype_data imx8mm_data = { > .txfifo = SZ_1K, /* (128 * 64 bits) */ > .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ > .quirks = 0, > + .lut_num = 32, > .little_endian = true, /* little-endian */ > }; > > @@ -365,6 +358,7 @@ static struct nxp_fspi_devtype_data imx8qxp_data = { > .txfifo = SZ_1K, /* (128 * 64 bits) */ > .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ > .quirks = 0, > + .lut_num = 32, > .little_endian = true, /* little-endian */ > }; > > @@ -373,6 +367,7 @@ static struct nxp_fspi_devtype_data imx8dxl_data = { > .txfifo = SZ_1K, /* (128 * 64 bits) */ > .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ > .quirks = FSPI_QUIRK_USE_IP_ONLY, > + .lut_num = 32, > .little_endian = true, /* little-endian */ > }; > > @@ -544,6 +539,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, > void __iomem *base = f->iobase; > u32 lutval[4] = {}; > int lutidx = 1, i; > + u32 lut_offset = (f->devtype_data->lut_num - 1) * 4 * 4; > + u32 target_lut_reg; > > /* cmd */ > lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), > @@ -588,8 +585,10 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, > fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR); > > /* fill LUT */ > - for (i = 0; i < ARRAY_SIZE(lutval); i++) > - fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); > + for (i = 0; i < ARRAY_SIZE(lutval); i++) { > + target_lut_reg = FSPI_LUT_BASE + lut_offset + i * 4; > + fspi_writel(f, lutval[i], base + target_lut_reg); > + } > > dev_dbg(f->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x], size: 0x%08x\n", > op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); > @@ -874,7 +873,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) > void __iomem *base = f->iobase; > int seqnum = 0; > int err = 0; > - u32 reg; > + u32 reg, seqid_lut; > > reg = fspi_readl(f, base + FSPI_IPRXFCR); > /* invalid RXFIFO first */ > @@ -890,8 +889,9 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) > * the LUT at each exec_op() call. And also specify the DATA > * length, since it's has not been specified in the LUT. > */ > + seqid_lut = f->devtype_data->lut_num - 1; > fspi_writel(f, op->data.nbytes | > - (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) | > + (seqid_lut << FSPI_IPCR1_SEQID_SHIFT) | > (seqnum << FSPI_IPCR1_SEQNUM_SHIFT), > base + FSPI_IPCR1); > > @@ -1015,7 +1015,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) > { > void __iomem *base = f->iobase; > int ret, i; > - u32 reg; > + u32 reg, seqid_lut; > > /* disable and unprepare clock to avoid glitch pass to controller */ > nxp_fspi_clk_disable_unprep(f); > @@ -1090,11 +1090,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) > fspi_writel(f, reg, base + FSPI_FLSHB1CR1); > fspi_writel(f, reg, base + FSPI_FLSHB2CR1); > > + /* > + * The driver only uses one single LUT entry, that is updated on > + * each call of exec_op(). Index 0 is preset at boot with a basic > + * read operation, so let's use the last entry. > + */ > + seqid_lut = f->devtype_data->lut_num - 1; > /* AHB Read - Set lut sequence ID for all CS. */ > - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2); > - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2); > - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2); > - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2); > + fspi_writel(f, seqid_lut, base + FSPI_FLSHA1CR2); > + fspi_writel(f, seqid_lut, base + FSPI_FLSHA2CR2); > + fspi_writel(f, seqid_lut, base + FSPI_FLSHB1CR2); > + fspi_writel(f, seqid_lut, base + FSPI_FLSHB2CR2); > > f->selected = -1; > > -- > 2.34.1 >
diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index fd1816befcd8..f42c14d80289 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -57,13 +57,6 @@ #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> -/* - * The driver only uses one single LUT entry, that is updated on - * each call of exec_op(). Index 0 is preset at boot with a basic - * read operation, so let's use the last entry (31). - */ -#define SEQID_LUT 31 - /* Registers used by the driver */ #define FSPI_MCR0 0x00 #define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) @@ -263,9 +256,6 @@ #define FSPI_TFDR 0x180 #define FSPI_LUT_BASE 0x200 -#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) -#define FSPI_LUT_REG(idx) \ - (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) /* register map end */ @@ -341,6 +331,7 @@ struct nxp_fspi_devtype_data { unsigned int txfifo; unsigned int ahb_buf_size; unsigned int quirks; + unsigned int lut_num; bool little_endian; }; @@ -349,6 +340,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = 0, + .lut_num = 32, .little_endian = true, /* little-endian */ }; @@ -357,6 +349,7 @@ static struct nxp_fspi_devtype_data imx8mm_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = 0, + .lut_num = 32, .little_endian = true, /* little-endian */ }; @@ -365,6 +358,7 @@ static struct nxp_fspi_devtype_data imx8qxp_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = 0, + .lut_num = 32, .little_endian = true, /* little-endian */ }; @@ -373,6 +367,7 @@ static struct nxp_fspi_devtype_data imx8dxl_data = { .txfifo = SZ_1K, /* (128 * 64 bits) */ .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ .quirks = FSPI_QUIRK_USE_IP_ONLY, + .lut_num = 32, .little_endian = true, /* little-endian */ }; @@ -544,6 +539,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, void __iomem *base = f->iobase; u32 lutval[4] = {}; int lutidx = 1, i; + u32 lut_offset = (f->devtype_data->lut_num - 1) * 4 * 4; + u32 target_lut_reg; /* cmd */ lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), @@ -588,8 +585,10 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f, fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR); /* fill LUT */ - for (i = 0; i < ARRAY_SIZE(lutval); i++) - fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i)); + for (i = 0; i < ARRAY_SIZE(lutval); i++) { + target_lut_reg = FSPI_LUT_BASE + lut_offset + i * 4; + fspi_writel(f, lutval[i], base + target_lut_reg); + } dev_dbg(f->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x], size: 0x%08x\n", op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes); @@ -874,7 +873,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) void __iomem *base = f->iobase; int seqnum = 0; int err = 0; - u32 reg; + u32 reg, seqid_lut; reg = fspi_readl(f, base + FSPI_IPRXFCR); /* invalid RXFIFO first */ @@ -890,8 +889,9 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op) * the LUT at each exec_op() call. And also specify the DATA * length, since it's has not been specified in the LUT. */ + seqid_lut = f->devtype_data->lut_num - 1; fspi_writel(f, op->data.nbytes | - (SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) | + (seqid_lut << FSPI_IPCR1_SEQID_SHIFT) | (seqnum << FSPI_IPCR1_SEQNUM_SHIFT), base + FSPI_IPCR1); @@ -1015,7 +1015,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) { void __iomem *base = f->iobase; int ret, i; - u32 reg; + u32 reg, seqid_lut; /* disable and unprepare clock to avoid glitch pass to controller */ nxp_fspi_clk_disable_unprep(f); @@ -1090,11 +1090,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f) fspi_writel(f, reg, base + FSPI_FLSHB1CR1); fspi_writel(f, reg, base + FSPI_FLSHB2CR1); + /* + * The driver only uses one single LUT entry, that is updated on + * each call of exec_op(). Index 0 is preset at boot with a basic + * read operation, so let's use the last entry. + */ + seqid_lut = f->devtype_data->lut_num - 1; /* AHB Read - Set lut sequence ID for all CS. */ - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2); - fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHA1CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHA2CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHB1CR2); + fspi_writel(f, seqid_lut, base + FSPI_FLSHB2CR2); f->selected = -1;