From: Vladimir Oltean <olteanv@gmail.com> To: broonie@kernel.org Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, shawnguo@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, devicetree@vger.kernel.org, eha@deif.com, angelo@sysam.it, andrew.smirnov@gmail.com, gustavo@embeddedor.com, weic@nvidia.com, mhosny@nvidia.com, michael@walle.cc, peng.ma@nxp.com Subject: [PATCH v2 2/6] spi: spi-fsl-dspi: Fix little endian access to PUSHR CMD and TXDATA Date: Mon, 9 Mar 2020 23:07:51 +0200 [thread overview] Message-ID: <20200309210755.6759-3-olteanv@gmail.com> (raw) In-Reply-To: <20200309210755.6759-1-olteanv@gmail.com> From: Vladimir Oltean <vladimir.oltean@nxp.com> In XSPI mode, the 32-bit PUSHR register can be written to separately: the higher 16 bits are for commands and the lower 16 bits are for data. This has nicely been hacked around, by defining a second regmap with a width of 16 bits, and effectively splitting a 32-bit register into 2 16-bit ones, from the perspective of this regmap_pushr. The problem is the assumption about the controller's endianness. If the controller is little endian (such as anything post-LS1046A), then the first 2 bytes, in the order imposed by memory layout, will actually hold the TXDATA, and the last 2 bytes will hold the CMD. So take the controller's endianness into account when performing split writes to PUSHR. The obvious and simple solution would have been to call regmap_get_val_endian(), but that is an internal regmap function and we don't want to change regmap just for this. Therefore, we just re-read the "big-endian" device tree property. Fixes: 58ba07ec79e6 ("spi: spi-fsl-dspi: Add support for XSPI mode registers") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- Changes in v2: Parse "big-endian" device tree bindings instead of taking the decision based on compatible SoC. drivers/spi/spi-fsl-dspi.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 0ce26c1cbf62..0483abd403a4 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -103,10 +103,6 @@ #define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) #define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) -/* Register offsets for regmap_pushr */ -#define PUSHR_CMD 0x0 -#define PUSHR_TX 0x2 - #define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { @@ -240,6 +236,13 @@ struct fsl_dspi { int words_in_flight; + /* + * Offsets for CMD and TXDATA within SPI_PUSHR when accessed + * individually (in XSPI mode) + */ + int pushr_cmd; + int pushr_tx; + void (*host_to_dev)(struct fsl_dspi *dspi, u32 *txdata); void (*dev_to_host)(struct fsl_dspi *dspi, u32 rxdata); }; @@ -670,12 +673,12 @@ static void dspi_pushr_cmd_write(struct fsl_dspi *dspi, u16 cmd) */ if (dspi->len > dspi->oper_word_size) cmd |= SPI_PUSHR_CMD_CONT; - regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); + regmap_write(dspi->regmap_pushr, dspi->pushr_cmd, cmd); } static void dspi_pushr_txdata_write(struct fsl_dspi *dspi, u16 txdata) { - regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); + regmap_write(dspi->regmap_pushr, dspi->pushr_tx, txdata); } static void dspi_xspi_write(struct fsl_dspi *dspi, int cnt, bool eoq) @@ -1256,6 +1259,7 @@ static int dspi_probe(struct platform_device *pdev) struct fsl_dspi *dspi; struct resource *res; void __iomem *base; + bool big_endian; ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); if (!ctlr) @@ -1281,6 +1285,7 @@ static int dspi_probe(struct platform_device *pdev) /* Only Coldfire uses platform data */ dspi->devtype_data = &devtype_data[MCF5441X]; + big_endian = true; } else { ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); @@ -1302,6 +1307,15 @@ static int dspi_probe(struct platform_device *pdev) ret = -EFAULT; goto out_ctlr_put; } + + big_endian = of_device_is_big_endian(np); + } + if (big_endian) { + dspi->pushr_cmd = 0; + dspi->pushr_tx = 2; + } else { + dspi->pushr_cmd = 2; + dspi->pushr_tx = 0; } if (dspi->devtype_data->trans_mode == DSPI_XSPI_MODE) -- 2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Vladimir Oltean <olteanv-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> To: broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, mark.rutland-5wv7dgnIgG8@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, eha-/iRVSOupHO4@public.gmane.org, angelo-BIYBQhTR83Y@public.gmane.org, andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, gustavo-L1vi/lXTdts+Va1GwOuvDg@public.gmane.org, weic-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org, mhosny-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org, michael-QKn5cuLxLXY@public.gmane.org, peng.ma-3arQi8VN3Tc@public.gmane.org Subject: [PATCH v2 2/6] spi: spi-fsl-dspi: Fix little endian access to PUSHR CMD and TXDATA Date: Mon, 9 Mar 2020 23:07:51 +0200 [thread overview] Message-ID: <20200309210755.6759-3-olteanv@gmail.com> (raw) In-Reply-To: <20200309210755.6759-1-olteanv-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> From: Vladimir Oltean <vladimir.oltean-3arQi8VN3Tc@public.gmane.org> In XSPI mode, the 32-bit PUSHR register can be written to separately: the higher 16 bits are for commands and the lower 16 bits are for data. This has nicely been hacked around, by defining a second regmap with a width of 16 bits, and effectively splitting a 32-bit register into 2 16-bit ones, from the perspective of this regmap_pushr. The problem is the assumption about the controller's endianness. If the controller is little endian (such as anything post-LS1046A), then the first 2 bytes, in the order imposed by memory layout, will actually hold the TXDATA, and the last 2 bytes will hold the CMD. So take the controller's endianness into account when performing split writes to PUSHR. The obvious and simple solution would have been to call regmap_get_val_endian(), but that is an internal regmap function and we don't want to change regmap just for this. Therefore, we just re-read the "big-endian" device tree property. Fixes: 58ba07ec79e6 ("spi: spi-fsl-dspi: Add support for XSPI mode registers") Signed-off-by: Vladimir Oltean <vladimir.oltean-3arQi8VN3Tc@public.gmane.org> --- Changes in v2: Parse "big-endian" device tree bindings instead of taking the decision based on compatible SoC. drivers/spi/spi-fsl-dspi.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 0ce26c1cbf62..0483abd403a4 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -103,10 +103,6 @@ #define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) #define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) -/* Register offsets for regmap_pushr */ -#define PUSHR_CMD 0x0 -#define PUSHR_TX 0x2 - #define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { @@ -240,6 +236,13 @@ struct fsl_dspi { int words_in_flight; + /* + * Offsets for CMD and TXDATA within SPI_PUSHR when accessed + * individually (in XSPI mode) + */ + int pushr_cmd; + int pushr_tx; + void (*host_to_dev)(struct fsl_dspi *dspi, u32 *txdata); void (*dev_to_host)(struct fsl_dspi *dspi, u32 rxdata); }; @@ -670,12 +673,12 @@ static void dspi_pushr_cmd_write(struct fsl_dspi *dspi, u16 cmd) */ if (dspi->len > dspi->oper_word_size) cmd |= SPI_PUSHR_CMD_CONT; - regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); + regmap_write(dspi->regmap_pushr, dspi->pushr_cmd, cmd); } static void dspi_pushr_txdata_write(struct fsl_dspi *dspi, u16 txdata) { - regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); + regmap_write(dspi->regmap_pushr, dspi->pushr_tx, txdata); } static void dspi_xspi_write(struct fsl_dspi *dspi, int cnt, bool eoq) @@ -1256,6 +1259,7 @@ static int dspi_probe(struct platform_device *pdev) struct fsl_dspi *dspi; struct resource *res; void __iomem *base; + bool big_endian; ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); if (!ctlr) @@ -1281,6 +1285,7 @@ static int dspi_probe(struct platform_device *pdev) /* Only Coldfire uses platform data */ dspi->devtype_data = &devtype_data[MCF5441X]; + big_endian = true; } else { ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); @@ -1302,6 +1307,15 @@ static int dspi_probe(struct platform_device *pdev) ret = -EFAULT; goto out_ctlr_put; } + + big_endian = of_device_is_big_endian(np); + } + if (big_endian) { + dspi->pushr_cmd = 0; + dspi->pushr_tx = 2; + } else { + dspi->pushr_cmd = 2; + dspi->pushr_tx = 0; } if (dspi->devtype_data->trans_mode == DSPI_XSPI_MODE) -- 2.17.1
next prev parent reply other threads:[~2020-03-09 21:08 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-03-09 21:07 [PATCH v2 0/6] NXP DSPI bugfixes and support for LS1028A Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean 2020-03-09 21:07 ` [PATCH v2 1/6] spi: spi-fsl-dspi: Don't access reserved fields in SPI_MCR Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean [this message] 2020-03-09 21:07 ` [PATCH v2 2/6] spi: spi-fsl-dspi: Fix little endian access to PUSHR CMD and TXDATA Vladimir Oltean 2020-03-09 21:07 ` [PATCH v2 3/6] spi: spi-fsl-dspi: Fix oper_word_size of zero for DMA mode Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean 2020-03-09 21:07 ` [PATCH v2 4/6] spi: spi-fsl-dspi: Add support for LS1028A Vladimir Oltean 2020-03-09 21:07 ` [PATCH v2 5/6] arm64: dts: ls1028a: Specify the DMA channels for the DSPI controllers Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean 2020-03-09 21:07 ` [PATCH v2 6/6] arm64: dts: ls1028a-rdb: Add a spidev node for the mikroBUS Vladimir Oltean 2020-03-09 21:07 ` Vladimir Oltean 2020-03-10 8:34 ` [PATCH v2 0/6] NXP DSPI bugfixes and support for LS1028A Michael Walle 2020-03-10 8:34 ` Michael Walle 2020-03-10 12:57 ` Vladimir Oltean 2020-03-10 12:57 ` Vladimir Oltean
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200309210755.6759-3-olteanv@gmail.com \ --to=olteanv@gmail.com \ --cc=andrew.smirnov@gmail.com \ --cc=angelo@sysam.it \ --cc=broonie@kernel.org \ --cc=devicetree@vger.kernel.org \ --cc=eha@deif.com \ --cc=gustavo@embeddedor.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-spi@vger.kernel.org \ --cc=mark.rutland@arm.com \ --cc=mhosny@nvidia.com \ --cc=michael@walle.cc \ --cc=peng.ma@nxp.com \ --cc=robh+dt@kernel.org \ --cc=shawnguo@kernel.org \ --cc=weic@nvidia.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.