lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251118065012.1418279-1-carlos.song@nxp.com>
Date: Tue, 18 Nov 2025 14:50:12 +0800
From: Carlos Song <carlos.song@....com>
To: broonie@...nel.org,
	shawnguo@...nel.org,
	s.hauer@...gutronix.de,
	kernel@...gutronix.de,
	festevam@...il.com,
	frank.li@....com
Cc: linux-spi@...r.kernel.org,
	imx@...ts.linux.dev,
	linux-arm-kernel@...ts.infradead.org,
	linux-kernel@...r.kernel.org,
	Carlos Song <carlos.song@....com>,
	Clark Wang <xiaoning.wang@....com>
Subject: [PATCH v3] spi: imx: add 16/32 bits per word support for target PIO mode

Enable 16/32 bits per word support for spi-imx target PIO mode.

Signed-off-by: Carlos Song <carlos.song@....com>
Signed-off-by: Clark Wang <xiaoning.wang@....com>
---
In SPI target mode, we write/read 32 bits word in 32 bits width TXFIFO and
RXFIFO. 32 bits point is used to get the logic value from memory. CPU only
handle the logic value with FIFO, logic value is the same with value in
FIFO. However, in different CPU endian, the logic value is different.

For example from TX:
SPI tx_buff bytes order in memory:
addr0 addr1 addr2 addr3
0x11  0x22  0x33  0x44

For little endian CPU:
Get a logic value by u32 point: 0x44332211, CPU send logic value to bus
following little endian, the bytes flow in AXI bus:
0x11 0x22 0x33 0x44
but when write 32 bits word to FIFO, all bytes are grouped to one 32
bits word following the little endian to 0x44332211.

so 0x44332211 is writed to TXFIFO:
bit31~24 bit23~16 bit15~bit8 bit7~bit0
0x44     0x33     0x22       0x11

For big endian CPU:
Get a logic value by u32 point: 0x11223344, CPU send logic value to bus
following big endian, the bytes flow in AXI bus:
0x11 0x22 0x33 0x44
but when write 32 bits word to FIFO, all bytes are grouped to one 32
bits word following the big endian to 0x11223344.

so 0x11223344 is writen to TXFIFO:
bit31~24 bit23~16 bit15~bit8 bit7~bit0
0x11     0x22     0x33       0x44

Because SPI spec is not ruled for bytes order, so SPI should keep bytes
order following the CPU endian.
The bytes order in memory is the same with logic value in big endian.
So don't need to handle data for big endian CPU.
But for little endian SOC, there is some diferences:
1. When bits per word = 8:
every word is byte, so bytes order should always keep the same with memory,
u32 word is 0x44332211, but CPU should send logic value 0x11223344.
So we should swap every bytes for the u32 word 0x44332211.
2. When bits per word = 16:
every word is two bytes, so every half word should be little endian:
u32 word is 0x44332211, but CPU should send logic value 0x22114433
so we should swap every half word for the u32 word 0x44332211.
3. When bits per word = 32:
every word is 4 bytes, so every 4 bytes word should be little endian:
u32 word is 0x44332211 CPU should send logic value 0x44332211,
so don't need to do any bytes swap for this word.
---
 drivers/spi/spi-imx.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 1dd20e9d9605..b8b79bb7fec3 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -425,8 +425,15 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
 
 static void mx53_ecspi_rx_target(struct spi_imx_data *spi_imx)
 {
-	u32 val = ioread32be(spi_imx->base + MXC_CSPIRXDATA);
+	u32 val = readl(spi_imx->base + MXC_CSPIRXDATA);
+#ifdef __LITTLE_ENDIAN
+	unsigned int bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 
+	if (bytes_per_word == 1)
+		swab32s(&val);
+	else if (bytes_per_word == 2)
+		swahw32s(&val);
+#endif
 	if (spi_imx->rx_buf) {
 		int n_bytes = spi_imx->target_burst % sizeof(val);
 
@@ -447,6 +454,9 @@ static void mx53_ecspi_tx_target(struct spi_imx_data *spi_imx)
 {
 	u32 val = 0;
 	int n_bytes = spi_imx->count % sizeof(val);
+#ifdef __LITTLE_ENDIAN
+	unsigned int bytes_per_word;
+#endif
 
 	if (!n_bytes)
 		n_bytes = sizeof(val);
@@ -459,7 +469,14 @@ static void mx53_ecspi_tx_target(struct spi_imx_data *spi_imx)
 
 	spi_imx->count -= n_bytes;
 
-	iowrite32be(val, spi_imx->base + MXC_CSPITXDATA);
+#ifdef __LITTLE_ENDIAN
+	bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
+	if (bytes_per_word == 1)
+		swab32s(&val);
+	else if (bytes_per_word == 2)
+		swahw32s(&val);
+#endif
+	writel(val, spi_imx->base + MXC_CSPITXDATA);
 }
 
 /* MX51 eCSPI */
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ