Skip to content

Commit 260c41d

Browse files
committed
spi: 64 bytes long CS
1 parent 9ff7fb9 commit 260c41d

File tree

4 files changed

+267
-4
lines changed

4 files changed

+267
-4
lines changed

recipes-bsp/device-tree/lmp-device-tree/portenta-x8/arduino_portenta-x8.dts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@
238238

239239
pinctrl_ecspi3_cs: ecspi3cs {
240240
fsl,pins = <
241-
// MX8MM_IOMUXC_UART2_TXD_ECSPI3_SS0 0x40000
242-
MX8MM_IOMUXC_UART2_TXD_GPIO5_IO25 0x40000
241+
MX8MM_IOMUXC_UART2_TXD_ECSPI3_SS0 0x19
242+
// MX8MM_IOMUXC_UART2_TXD_GPIO5_IO25 0x19
243243
>;
244244
};
245245
};
@@ -265,7 +265,6 @@
265265
pinctrl-names = "default";
266266
pinctrl-0 = <&pinctrl_ecspi3 &pinctrl_ecspi3_cs>;
267267
num-cs = <1>;
268-
cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>;
269268
status = "disabled";
270269
};
271270

recipes-kernel/kernel-modules/x8h7/x8h7_drv.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
#define DRIVER_NAME "x8h7"
4848
#define X8H7_BUF_SIZE (64*1024)
49+
#define FIXED_PACKET_LEN 64
4950

5051
//#define DEBUG
5152
#include "debug.h"
@@ -371,7 +372,7 @@ static int x8h7_pkt_send(void)
371372

372373
DBG_PRINT("\n");
373374

374-
len = 1024;
375+
len = FIXED_PACKET_LEN;
375376

376377
pkt_dump("Send", spidev->x8h7_txb);
377378

@@ -449,6 +450,8 @@ static int x8h7_probe(struct spi_device *spi)
449450
spidev->spi = spi;
450451
mutex_init(&spidev->lock);
451452

453+
//spi->bits_per_word = FIXED_PACKET_LEN * 8;
454+
452455
/* Device speed */
453456
if (!of_property_read_u32(spi->dev.of_node, "spi-max-frequency", &value))
454457
spidev->speed_hz = value;
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
From da6c942d6b5fa9fef6180c0b662d8989517cac55 Mon Sep 17 00:00:00 2001
2+
From: Martino Facchin <[email protected]>
3+
Date: Fri, 10 May 2024 08:13:08 +0000
4+
Subject: [PATCH] spi: test
5+
6+
---
7+
drivers/spi/spi-imx.c | 156 +++++++++++++++++++++++++++++++++++++-----
8+
1 file changed, 138 insertions(+), 18 deletions(-)
9+
10+
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
11+
index 5ab0ec63c4bd..e6ec0fa0b156 100644
12+
--- a/drivers/spi/spi-imx.c
13+
+++ b/drivers/spi/spi-imx.c
14+
@@ -24,6 +24,9 @@
15+
#include <linux/of_device.h>
16+
#include <linux/property.h>
17+
18+
+/* include for spi_map_buf defined in spi.c */
19+
+#include "internals.h"
20+
+
21+
#include <linux/platform_data/dma-imx.h>
22+
23+
#define DRIVER_NAME "spi_imx"
24+
@@ -118,6 +121,10 @@ struct spi_imx_data {
25+
struct completion dma_tx_completion;
26+
27+
const struct spi_imx_devtype_data *devtype_data;
28+
+
29+
+ /* temporary DMA buffers */
30+
+ u8 dmatxbuf[MAX_SDMA_BD_BYTES];
31+
+ u8 dmarxbuf[MAX_SDMA_BD_BYTES];
32+
};
33+
34+
static inline int is_imx27_cspi(struct spi_imx_data *d)
35+
@@ -223,7 +230,7 @@ static int spi_imx_bytes_per_word(const int bits_per_word)
36+
return 4;
37+
}
38+
39+
-static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
40+
+static bool __spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
41+
struct spi_transfer *transfer)
42+
{
43+
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
44+
@@ -245,6 +252,12 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
45+
return true;
46+
}
47+
48+
+static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
49+
+ struct spi_transfer *transfer)
50+
+{
51+
+ return false;
52+
+}
53+
+
54+
#define MX51_ECSPI_CTRL 0x08
55+
#define MX51_ECSPI_CTRL_ENABLE (1 << 0)
56+
#define MX51_ECSPI_CTRL_XCH (1 << 2)
57+
@@ -1216,25 +1229,29 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
58+
return IRQ_HANDLED;
59+
}
60+
61+
-static int spi_imx_dma_configure(struct spi_master *master)
62+
+static int spi_imx_dma_configure(struct spi_master *master, struct spi_transfer *transfer)
63+
{
64+
int ret;
65+
enum dma_slave_buswidth buswidth;
66+
struct dma_slave_config rx = {}, tx = {};
67+
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
68+
69+
- switch (spi_imx_bytes_per_word(spi_imx->bits_per_word)) {
70+
- case 4:
71+
+ if(transfer->len > MX51_ECSPI_CTRL_MAX_BURST) {
72+
+ switch (spi_imx_bytes_per_word(spi_imx->bits_per_word)) {
73+
+ case 4:
74+
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
75+
+ break;
76+
+ case 2:
77+
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
78+
+ break;
79+
+ case 1:
80+
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
81+
+ break;
82+
+ default:
83+
+ return -EINVAL;
84+
+ }
85+
+ } else {
86+
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
87+
- break;
88+
- case 2:
89+
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
90+
- break;
91+
- case 1:
92+
- buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
93+
- break;
94+
- default:
95+
- return -EINVAL;
96+
}
97+
98+
tx.direction = DMA_MEM_TO_DEV;
99+
@@ -1312,7 +1329,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
100+
spi_imx->dynamic_burst = 0;
101+
}
102+
103+
- if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
104+
+ if (__spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
105+
spi_imx->usedma = true;
106+
else
107+
spi_imx->usedma = false;
108+
@@ -1416,13 +1433,84 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
109+
unsigned long transfer_timeout;
110+
unsigned long timeout;
111+
struct spi_master *master = spi_imx->bitbang.master;
112+
- struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
113+
- struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
114+
+ struct sg_table *tx, *rx;
115+
+ struct scatterlist *last_sg;
116+
unsigned int bytes_per_word, i;
117+
int ret;
118+
119+
+ /* simple case (former DMA behaviour)
120+
+ either transfer size > 512 bytes (4kbits) or
121+
+ 32 bits per word and len % sizeof(u32) = 0 */
122+
+ int simple = 0;
123+
+ int offset = transfer->len % 4u;
124+
+ int numwords = (transfer->len + sizeof(u32)-1) / sizeof(u32);
125+
+
126+
+ /* in non simple case we need to right align message buffer to
127+
+ neareest u32 boundary. eCSPI first transfers odd byte count
128+
+ from the beginning of message */
129+
+ if(offset)
130+
+ offset = 4-offset;
131+
+
132+
+ if( transfer->len > MX51_ECSPI_CTRL_MAX_BURST
133+
+ || (transfer->bits_per_word > 16 && !offset) )
134+
+ {
135+
+ /* simple case, DMA directly to/from original message buffers */
136+
+ ret = spi_map_buf(master, spi_imx->dev, &transfer->tx_sg,
137+
+ (void *)transfer->tx_buf, transfer->len,
138+
+ DMA_TO_DEVICE);
139+
+ ret = spi_map_buf(master, spi_imx->dev, &transfer->rx_sg,
140+
+ transfer->rx_buf, transfer->len,
141+
+ DMA_FROM_DEVICE);
142+
+ simple = 1;
143+
+ }
144+
+ else
145+
+ {
146+
+ /* copy tx buffer to temporary location */
147+
+ memcpy(&spi_imx->dmatxbuf[offset], transfer->tx_buf, transfer->len);
148+
+
149+
+ /* 8 and 16 bits per word cases have to be byte shuffled a bit */
150+
+ if(transfer->bits_per_word == 8)
151+
+ {
152+
+ for(i = 0; i < numwords; i++)
153+
+ {
154+
+ swab32s((u32*) &spi_imx->dmatxbuf[i * sizeof(u32)]);
155+
+ }
156+
+ }
157+
+ else if(transfer->bits_per_word == 16)
158+
+ {
159+
+ for(i = 0; i < numwords; i++)
160+
+ {
161+
+ *(u32*)&spi_imx->dmatxbuf[i * sizeof(u32)] =
162+
+ swab32( swahb32(*(u32*)&spi_imx->dmatxbuf[i * sizeof(u32)] ));
163+
+ }
164+
+ }
165+
+ /* map temporary buffers, stretch DMA transfer length to
166+
+ nearest u32 boundary */
167+
+ ret = spi_map_buf(master, spi_imx->dev, &transfer->tx_sg,
168+
+ (void *)spi_imx->dmatxbuf, (transfer->len + 3) & ~3,
169+
+ DMA_TO_DEVICE);
170+
+ ret = spi_map_buf(master, spi_imx->dev, &transfer->rx_sg,
171+
+ spi_imx->dmarxbuf, (transfer->len + 3) & ~3,
172+
+ DMA_FROM_DEVICE);
173+
+ }
174+
+
175+
+ tx = &transfer->tx_sg;
176+
+ rx = &transfer->rx_sg;
177+
+ last_sg = sg_last(rx->sgl, rx->nents);
178+
+
179+
+ if (transfer->len > MX51_ECSPI_CTRL_MAX_BURST)
180+
+ {
181+
+ /* too long for proper HW CS */
182+
+ spi_imx_set_burst_len(spi_imx, transfer->bits_per_word);
183+
+ bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
184+
+ }
185+
+ else
186+
+ {
187+
+ spi_imx_set_burst_len(spi_imx, transfer->len * 8);
188+
+ bytes_per_word = 4;
189+
+ }
190+
+
191+
/* Get the right burst length from the last sg to ensure no tail data */
192+
- bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
193+
for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) {
194+
if (!(sg_dma_len(last_sg) % (i * bytes_per_word)))
195+
break;
196+
@@ -1433,7 +1521,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
197+
198+
spi_imx->wml = i;
199+
200+
- ret = spi_imx_dma_configure(master);
201+
+ ret = spi_imx_dma_configure(master, transfer);
202+
if (ret)
203+
goto dma_failure_no_start;
204+
205+
@@ -1500,6 +1588,30 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
206+
return -ETIMEDOUT;
207+
}
208+
209+
+ if(!simple)
210+
+ {
211+
+ /* shuffle rx bytes for 8 and 16 bits per word */
212+
+ if(transfer->bits_per_word == 8)
213+
+ {
214+
+ for(i = 0; i < numwords; i++)
215+
+ {
216+
+ swab32s((u32*) &spi_imx->dmarxbuf[i * sizeof(u32)]);
217+
+ }
218+
+ }
219+
+ else if(transfer->bits_per_word == 16)
220+
+ {
221+
+ for(i = 0; i < numwords; i++)
222+
+ {
223+
+ *(u32*)&spi_imx->dmarxbuf[i * sizeof(u32)] =
224+
+ swab32( swahb32(*(u32*)&spi_imx->dmarxbuf[i * sizeof(u32)] ));
225+
+ }
226+
+ }
227+
+ memcpy(transfer->rx_buf, &spi_imx->dmarxbuf[offset], transfer->len);
228+
+ }
229+
+ spi_unmap_buf(master, spi_imx->dev, &transfer->rx_sg, DMA_FROM_DEVICE);
230+
+ spi_unmap_buf(master, spi_imx->dev, &transfer->tx_sg, DMA_TO_DEVICE);
231+
+
232+
+
233+
return transfer->len;
234+
/* fallback to pio */
235+
dma_failure_no_start:
236+
@@ -1657,6 +1769,13 @@ static int spi_imx_slave_abort(struct spi_master *master)
237+
return 0;
238+
}
239+
240+
+/* override set_cs from spi-bitbang.c for native CS.
241+
+ * spi-bitbang.c tries to toggle CS itself when CS GPIO is not valid,
242+
+ * introducing unneeded delay and CPU usage with two ndelay() calls */
243+
+static void spi_imx_dummy_set_cs(struct spi_device *spi, bool enable)
244+
+{
245+
+}
246+
+
247+
static int spi_imx_probe(struct platform_device *pdev)
248+
{
249+
struct device_node *np = pdev->dev.of_node;
250+
@@ -1720,6 +1839,7 @@ static int spi_imx_probe(struct platform_device *pdev)
251+
spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
252+
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
253+
spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
254+
+ spi_imx->bitbang.master->set_cs = spi_imx_dummy_set_cs;
255+
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
256+
| SPI_NO_CS;
257+
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
258+
--
259+
2.25.1
260+

recipes-kernel/linux/linux-lmp-fslc-imx_%.bbappend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ SRC_URI:append:portenta-x8 = " \
2727
file://0002-NXP-V4L2-patch-2-3-courtesy-of-weiping.liu-nxp.com.patch \
2828
file://0003-NXP-V4L2-patch-3-3-courtesy-of-weiping.liu-nxp.com.patch \
2929
file://QUECTEL-0001-support-ec200a.patch \
30+
file://0001-spi-test.patch \
3031
"
3132

3233
# file://rtc-pcf8563-remove-workaround.patch

0 commit comments

Comments
 (0)