1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/drivers/spi/spi-loopback-test.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (c) Martin Sperl <kernel@martin.sperl.org>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Loopback test driver to test several typical spi_message conditions
8*4882a593Smuzhiyun * that a spi_master driver may encounter
9*4882a593Smuzhiyun * this can also get used for regression testing
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/ktime.h>
15*4882a593Smuzhiyun #include <linux/list.h>
16*4882a593Smuzhiyun #include <linux/list_sort.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/of_device.h>
19*4882a593Smuzhiyun #include <linux/printk.h>
20*4882a593Smuzhiyun #include <linux/vmalloc.h>
21*4882a593Smuzhiyun #include <linux/spi/spi.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "spi-test.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* flag to only simulate transfers */
26*4882a593Smuzhiyun static int simulate_only;
27*4882a593Smuzhiyun module_param(simulate_only, int, 0);
28*4882a593Smuzhiyun MODULE_PARM_DESC(simulate_only, "if not 0 do not execute the spi message");
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /* dump spi messages */
31*4882a593Smuzhiyun static int dump_messages;
32*4882a593Smuzhiyun module_param(dump_messages, int, 0);
33*4882a593Smuzhiyun MODULE_PARM_DESC(dump_messages,
34*4882a593Smuzhiyun "=1 dump the basic spi_message_structure, " \
35*4882a593Smuzhiyun "=2 dump the spi_message_structure including data, " \
36*4882a593Smuzhiyun "=3 dump the spi_message structure before and after execution");
37*4882a593Smuzhiyun /* the device is jumpered for loopback - enabling some rx_buf tests */
38*4882a593Smuzhiyun static int loopback;
39*4882a593Smuzhiyun module_param(loopback, int, 0);
40*4882a593Smuzhiyun MODULE_PARM_DESC(loopback,
41*4882a593Smuzhiyun "if set enable loopback mode, where the rx_buf " \
42*4882a593Smuzhiyun "is checked to match tx_buf after the spi_message " \
43*4882a593Smuzhiyun "is executed");
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun static int loop_req;
46*4882a593Smuzhiyun module_param(loop_req, int, 0);
47*4882a593Smuzhiyun MODULE_PARM_DESC(loop_req,
48*4882a593Smuzhiyun "if set controller will be asked to enable test loop mode. " \
49*4882a593Smuzhiyun "If controller supported it, MISO and MOSI will be connected");
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun static int no_cs;
52*4882a593Smuzhiyun module_param(no_cs, int, 0);
53*4882a593Smuzhiyun MODULE_PARM_DESC(no_cs,
54*4882a593Smuzhiyun "if set Chip Select (CS) will not be used");
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* run only a specific test */
57*4882a593Smuzhiyun static int run_only_test = -1;
58*4882a593Smuzhiyun module_param(run_only_test, int, 0);
59*4882a593Smuzhiyun MODULE_PARM_DESC(run_only_test,
60*4882a593Smuzhiyun "only run the test with this number (0-based !)");
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* use vmalloc'ed buffers */
63*4882a593Smuzhiyun static int use_vmalloc;
64*4882a593Smuzhiyun module_param(use_vmalloc, int, 0644);
65*4882a593Smuzhiyun MODULE_PARM_DESC(use_vmalloc,
66*4882a593Smuzhiyun "use vmalloc'ed buffers instead of kmalloc'ed");
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* check rx ranges */
69*4882a593Smuzhiyun static int check_ranges = 1;
70*4882a593Smuzhiyun module_param(check_ranges, int, 0644);
71*4882a593Smuzhiyun MODULE_PARM_DESC(check_ranges,
72*4882a593Smuzhiyun "checks rx_buffer pattern are valid");
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* the actual tests to execute */
75*4882a593Smuzhiyun static struct spi_test spi_tests[] = {
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun .description = "tx/rx-transfer - start of page",
78*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
79*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
80*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
81*4882a593Smuzhiyun .iterate_rx_align = ITERATE_ALIGN,
82*4882a593Smuzhiyun .transfer_count = 1,
83*4882a593Smuzhiyun .transfers = {
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun .tx_buf = TX(0),
86*4882a593Smuzhiyun .rx_buf = RX(0),
87*4882a593Smuzhiyun },
88*4882a593Smuzhiyun },
89*4882a593Smuzhiyun },
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun .description = "tx/rx-transfer - crossing PAGE_SIZE",
92*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
93*4882a593Smuzhiyun .iterate_len = { ITERATE_LEN },
94*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
95*4882a593Smuzhiyun .iterate_rx_align = ITERATE_ALIGN,
96*4882a593Smuzhiyun .transfer_count = 1,
97*4882a593Smuzhiyun .transfers = {
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun .tx_buf = TX(PAGE_SIZE - 4),
100*4882a593Smuzhiyun .rx_buf = RX(PAGE_SIZE - 4),
101*4882a593Smuzhiyun },
102*4882a593Smuzhiyun },
103*4882a593Smuzhiyun },
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun .description = "tx-transfer - only",
106*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
107*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
108*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
109*4882a593Smuzhiyun .transfer_count = 1,
110*4882a593Smuzhiyun .transfers = {
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun .tx_buf = TX(0),
113*4882a593Smuzhiyun },
114*4882a593Smuzhiyun },
115*4882a593Smuzhiyun },
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun .description = "rx-transfer - only",
118*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
119*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
120*4882a593Smuzhiyun .iterate_rx_align = ITERATE_ALIGN,
121*4882a593Smuzhiyun .transfer_count = 1,
122*4882a593Smuzhiyun .transfers = {
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun .rx_buf = RX(0),
125*4882a593Smuzhiyun },
126*4882a593Smuzhiyun },
127*4882a593Smuzhiyun },
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun .description = "two tx-transfers - alter both",
130*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
131*4882a593Smuzhiyun .iterate_len = { ITERATE_LEN },
132*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
133*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0) | BIT(1),
134*4882a593Smuzhiyun .transfer_count = 2,
135*4882a593Smuzhiyun .transfers = {
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun .tx_buf = TX(0),
138*4882a593Smuzhiyun },
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun /* this is why we cant use ITERATE_MAX_LEN */
141*4882a593Smuzhiyun .tx_buf = TX(SPI_TEST_MAX_SIZE_HALF),
142*4882a593Smuzhiyun },
143*4882a593Smuzhiyun },
144*4882a593Smuzhiyun },
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun .description = "two tx-transfers - alter first",
147*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
148*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
149*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
150*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0),
151*4882a593Smuzhiyun .transfer_count = 2,
152*4882a593Smuzhiyun .transfers = {
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun .tx_buf = TX(64),
155*4882a593Smuzhiyun },
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun .len = 1,
158*4882a593Smuzhiyun .tx_buf = TX(0),
159*4882a593Smuzhiyun },
160*4882a593Smuzhiyun },
161*4882a593Smuzhiyun },
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun .description = "two tx-transfers - alter second",
164*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
165*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
166*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
167*4882a593Smuzhiyun .iterate_transfer_mask = BIT(1),
168*4882a593Smuzhiyun .transfer_count = 2,
169*4882a593Smuzhiyun .transfers = {
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun .len = 16,
172*4882a593Smuzhiyun .tx_buf = TX(0),
173*4882a593Smuzhiyun },
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun .tx_buf = TX(64),
176*4882a593Smuzhiyun },
177*4882a593Smuzhiyun },
178*4882a593Smuzhiyun },
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun .description = "two transfers tx then rx - alter both",
181*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
182*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
183*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
184*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0) | BIT(1),
185*4882a593Smuzhiyun .transfer_count = 2,
186*4882a593Smuzhiyun .transfers = {
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun .tx_buf = TX(0),
189*4882a593Smuzhiyun },
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun .rx_buf = RX(0),
192*4882a593Smuzhiyun },
193*4882a593Smuzhiyun },
194*4882a593Smuzhiyun },
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun .description = "two transfers tx then rx - alter tx",
197*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
198*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
199*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
200*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0),
201*4882a593Smuzhiyun .transfer_count = 2,
202*4882a593Smuzhiyun .transfers = {
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun .tx_buf = TX(0),
205*4882a593Smuzhiyun },
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun .len = 1,
208*4882a593Smuzhiyun .rx_buf = RX(0),
209*4882a593Smuzhiyun },
210*4882a593Smuzhiyun },
211*4882a593Smuzhiyun },
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun .description = "two transfers tx then rx - alter rx",
214*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
215*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
216*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
217*4882a593Smuzhiyun .iterate_transfer_mask = BIT(1),
218*4882a593Smuzhiyun .transfer_count = 2,
219*4882a593Smuzhiyun .transfers = {
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun .len = 1,
222*4882a593Smuzhiyun .tx_buf = TX(0),
223*4882a593Smuzhiyun },
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun .rx_buf = RX(0),
226*4882a593Smuzhiyun },
227*4882a593Smuzhiyun },
228*4882a593Smuzhiyun },
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun .description = "two tx+rx transfers - alter both",
231*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
232*4882a593Smuzhiyun .iterate_len = { ITERATE_LEN },
233*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
234*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0) | BIT(1),
235*4882a593Smuzhiyun .transfer_count = 2,
236*4882a593Smuzhiyun .transfers = {
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun .tx_buf = TX(0),
239*4882a593Smuzhiyun .rx_buf = RX(0),
240*4882a593Smuzhiyun },
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun /* making sure we align without overwrite
243*4882a593Smuzhiyun * the reason we can not use ITERATE_MAX_LEN
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun .tx_buf = TX(SPI_TEST_MAX_SIZE_HALF),
246*4882a593Smuzhiyun .rx_buf = RX(SPI_TEST_MAX_SIZE_HALF),
247*4882a593Smuzhiyun },
248*4882a593Smuzhiyun },
249*4882a593Smuzhiyun },
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun .description = "two tx+rx transfers - alter first",
252*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
253*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
254*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
255*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0),
256*4882a593Smuzhiyun .transfer_count = 2,
257*4882a593Smuzhiyun .transfers = {
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun /* making sure we align without overwrite */
260*4882a593Smuzhiyun .tx_buf = TX(1024),
261*4882a593Smuzhiyun .rx_buf = RX(1024),
262*4882a593Smuzhiyun },
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun .len = 1,
265*4882a593Smuzhiyun /* making sure we align without overwrite */
266*4882a593Smuzhiyun .tx_buf = TX(0),
267*4882a593Smuzhiyun .rx_buf = RX(0),
268*4882a593Smuzhiyun },
269*4882a593Smuzhiyun },
270*4882a593Smuzhiyun },
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun .description = "two tx+rx transfers - alter second",
273*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
274*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
275*4882a593Smuzhiyun .iterate_tx_align = ITERATE_ALIGN,
276*4882a593Smuzhiyun .iterate_transfer_mask = BIT(1),
277*4882a593Smuzhiyun .transfer_count = 2,
278*4882a593Smuzhiyun .transfers = {
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun .len = 1,
281*4882a593Smuzhiyun .tx_buf = TX(0),
282*4882a593Smuzhiyun .rx_buf = RX(0),
283*4882a593Smuzhiyun },
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun /* making sure we align without overwrite */
286*4882a593Smuzhiyun .tx_buf = TX(1024),
287*4882a593Smuzhiyun .rx_buf = RX(1024),
288*4882a593Smuzhiyun },
289*4882a593Smuzhiyun },
290*4882a593Smuzhiyun },
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun .description = "two tx+rx transfers - delay after transfer",
293*4882a593Smuzhiyun .fill_option = FILL_COUNT_8,
294*4882a593Smuzhiyun .iterate_len = { ITERATE_MAX_LEN },
295*4882a593Smuzhiyun .iterate_transfer_mask = BIT(0) | BIT(1),
296*4882a593Smuzhiyun .transfer_count = 2,
297*4882a593Smuzhiyun .transfers = {
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun .tx_buf = TX(0),
300*4882a593Smuzhiyun .rx_buf = RX(0),
301*4882a593Smuzhiyun .delay = {
302*4882a593Smuzhiyun .value = 1000,
303*4882a593Smuzhiyun .unit = SPI_DELAY_UNIT_USECS,
304*4882a593Smuzhiyun },
305*4882a593Smuzhiyun },
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun .tx_buf = TX(0),
308*4882a593Smuzhiyun .rx_buf = RX(0),
309*4882a593Smuzhiyun .delay = {
310*4882a593Smuzhiyun .value = 1000,
311*4882a593Smuzhiyun .unit = SPI_DELAY_UNIT_USECS,
312*4882a593Smuzhiyun },
313*4882a593Smuzhiyun },
314*4882a593Smuzhiyun },
315*4882a593Smuzhiyun },
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun { /* end of tests sequence */ }
318*4882a593Smuzhiyun };
319*4882a593Smuzhiyun
spi_loopback_test_probe(struct spi_device * spi)320*4882a593Smuzhiyun static int spi_loopback_test_probe(struct spi_device *spi)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun int ret;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun if (loop_req || no_cs) {
325*4882a593Smuzhiyun spi->mode |= loop_req ? SPI_LOOP : 0;
326*4882a593Smuzhiyun spi->mode |= no_cs ? SPI_NO_CS : 0;
327*4882a593Smuzhiyun ret = spi_setup(spi);
328*4882a593Smuzhiyun if (ret) {
329*4882a593Smuzhiyun dev_err(&spi->dev, "SPI setup with SPI_LOOP or SPI_NO_CS failed (%d)\n",
330*4882a593Smuzhiyun ret);
331*4882a593Smuzhiyun return ret;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun dev_info(&spi->dev, "Executing spi-loopback-tests\n");
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun ret = spi_test_run_tests(spi, spi_tests);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun dev_info(&spi->dev, "Finished spi-loopback-tests with return: %i\n",
340*4882a593Smuzhiyun ret);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun return ret;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun /* non const match table to permit to change via a module parameter */
346*4882a593Smuzhiyun static struct of_device_id spi_loopback_test_of_match[] = {
347*4882a593Smuzhiyun { .compatible = "linux,spi-loopback-test", },
348*4882a593Smuzhiyun { }
349*4882a593Smuzhiyun };
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun /* allow to override the compatible string via a module_parameter */
352*4882a593Smuzhiyun module_param_string(compatible, spi_loopback_test_of_match[0].compatible,
353*4882a593Smuzhiyun sizeof(spi_loopback_test_of_match[0].compatible),
354*4882a593Smuzhiyun 0000);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, spi_loopback_test_of_match);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun static struct spi_driver spi_loopback_test_driver = {
359*4882a593Smuzhiyun .driver = {
360*4882a593Smuzhiyun .name = "spi-loopback-test",
361*4882a593Smuzhiyun .owner = THIS_MODULE,
362*4882a593Smuzhiyun .of_match_table = spi_loopback_test_of_match,
363*4882a593Smuzhiyun },
364*4882a593Smuzhiyun .probe = spi_loopback_test_probe,
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun module_spi_driver(spi_loopback_test_driver);
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
370*4882a593Smuzhiyun MODULE_DESCRIPTION("test spi_driver to check core functionality");
371*4882a593Smuzhiyun MODULE_LICENSE("GPL");
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /* spi_test implementation */
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun #define RANGE_CHECK(ptr, plen, start, slen) \
378*4882a593Smuzhiyun ((ptr >= start) && (ptr + plen <= start + slen))
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /* we allocate one page more, to allow for offsets */
381*4882a593Smuzhiyun #define SPI_TEST_MAX_SIZE_PLUS (SPI_TEST_MAX_SIZE + PAGE_SIZE)
382*4882a593Smuzhiyun
spi_test_print_hex_dump(char * pre,const void * ptr,size_t len)383*4882a593Smuzhiyun static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun /* limit the hex_dump */
386*4882a593Smuzhiyun if (len < 1024) {
387*4882a593Smuzhiyun print_hex_dump(KERN_INFO, pre,
388*4882a593Smuzhiyun DUMP_PREFIX_OFFSET, 16, 1,
389*4882a593Smuzhiyun ptr, len, 0);
390*4882a593Smuzhiyun return;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun /* print head */
393*4882a593Smuzhiyun print_hex_dump(KERN_INFO, pre,
394*4882a593Smuzhiyun DUMP_PREFIX_OFFSET, 16, 1,
395*4882a593Smuzhiyun ptr, 512, 0);
396*4882a593Smuzhiyun /* print tail */
397*4882a593Smuzhiyun pr_info("%s truncated - continuing at offset %04zx\n",
398*4882a593Smuzhiyun pre, len - 512);
399*4882a593Smuzhiyun print_hex_dump(KERN_INFO, pre,
400*4882a593Smuzhiyun DUMP_PREFIX_OFFSET, 16, 1,
401*4882a593Smuzhiyun ptr + (len - 512), 512, 0);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
spi_test_dump_message(struct spi_device * spi,struct spi_message * msg,bool dump_data)404*4882a593Smuzhiyun static void spi_test_dump_message(struct spi_device *spi,
405*4882a593Smuzhiyun struct spi_message *msg,
406*4882a593Smuzhiyun bool dump_data)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun struct spi_transfer *xfer;
409*4882a593Smuzhiyun int i;
410*4882a593Smuzhiyun u8 b;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun dev_info(&spi->dev, " spi_msg@%pK\n", msg);
413*4882a593Smuzhiyun if (msg->status)
414*4882a593Smuzhiyun dev_info(&spi->dev, " status: %i\n",
415*4882a593Smuzhiyun msg->status);
416*4882a593Smuzhiyun dev_info(&spi->dev, " frame_length: %i\n",
417*4882a593Smuzhiyun msg->frame_length);
418*4882a593Smuzhiyun dev_info(&spi->dev, " actual_length: %i\n",
419*4882a593Smuzhiyun msg->actual_length);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun list_for_each_entry(xfer, &msg->transfers, transfer_list) {
422*4882a593Smuzhiyun dev_info(&spi->dev, " spi_transfer@%pK\n", xfer);
423*4882a593Smuzhiyun dev_info(&spi->dev, " len: %i\n", xfer->len);
424*4882a593Smuzhiyun dev_info(&spi->dev, " tx_buf: %pK\n", xfer->tx_buf);
425*4882a593Smuzhiyun if (dump_data && xfer->tx_buf)
426*4882a593Smuzhiyun spi_test_print_hex_dump(" TX: ",
427*4882a593Smuzhiyun xfer->tx_buf,
428*4882a593Smuzhiyun xfer->len);
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun dev_info(&spi->dev, " rx_buf: %pK\n", xfer->rx_buf);
431*4882a593Smuzhiyun if (dump_data && xfer->rx_buf)
432*4882a593Smuzhiyun spi_test_print_hex_dump(" RX: ",
433*4882a593Smuzhiyun xfer->rx_buf,
434*4882a593Smuzhiyun xfer->len);
435*4882a593Smuzhiyun /* check for unwritten test pattern on rx_buf */
436*4882a593Smuzhiyun if (xfer->rx_buf) {
437*4882a593Smuzhiyun for (i = 0 ; i < xfer->len ; i++) {
438*4882a593Smuzhiyun b = ((u8 *)xfer->rx_buf)[xfer->len - 1 - i];
439*4882a593Smuzhiyun if (b != SPI_TEST_PATTERN_UNWRITTEN)
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun if (i)
443*4882a593Smuzhiyun dev_info(&spi->dev,
444*4882a593Smuzhiyun " rx_buf filled with %02x starts at offset: %i\n",
445*4882a593Smuzhiyun SPI_TEST_PATTERN_UNWRITTEN,
446*4882a593Smuzhiyun xfer->len - i);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun struct rx_ranges {
452*4882a593Smuzhiyun struct list_head list;
453*4882a593Smuzhiyun u8 *start;
454*4882a593Smuzhiyun u8 *end;
455*4882a593Smuzhiyun };
456*4882a593Smuzhiyun
rx_ranges_cmp(void * priv,struct list_head * a,struct list_head * b)457*4882a593Smuzhiyun static int rx_ranges_cmp(void *priv, struct list_head *a, struct list_head *b)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list);
460*4882a593Smuzhiyun struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list);
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun if (rx_a->start > rx_b->start)
463*4882a593Smuzhiyun return 1;
464*4882a593Smuzhiyun if (rx_a->start < rx_b->start)
465*4882a593Smuzhiyun return -1;
466*4882a593Smuzhiyun return 0;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
spi_check_rx_ranges(struct spi_device * spi,struct spi_message * msg,void * rx)469*4882a593Smuzhiyun static int spi_check_rx_ranges(struct spi_device *spi,
470*4882a593Smuzhiyun struct spi_message *msg,
471*4882a593Smuzhiyun void *rx)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun struct spi_transfer *xfer;
474*4882a593Smuzhiyun struct rx_ranges ranges[SPI_TEST_MAX_TRANSFERS], *r;
475*4882a593Smuzhiyun int i = 0;
476*4882a593Smuzhiyun LIST_HEAD(ranges_list);
477*4882a593Smuzhiyun u8 *addr;
478*4882a593Smuzhiyun int ret = 0;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun /* loop over all transfers to fill in the rx_ranges */
481*4882a593Smuzhiyun list_for_each_entry(xfer, &msg->transfers, transfer_list) {
482*4882a593Smuzhiyun /* if there is no rx, then no check is needed */
483*4882a593Smuzhiyun if (!xfer->rx_buf)
484*4882a593Smuzhiyun continue;
485*4882a593Smuzhiyun /* fill in the rx_range */
486*4882a593Smuzhiyun if (RANGE_CHECK(xfer->rx_buf, xfer->len,
487*4882a593Smuzhiyun rx, SPI_TEST_MAX_SIZE_PLUS)) {
488*4882a593Smuzhiyun ranges[i].start = xfer->rx_buf;
489*4882a593Smuzhiyun ranges[i].end = xfer->rx_buf + xfer->len;
490*4882a593Smuzhiyun list_add(&ranges[i].list, &ranges_list);
491*4882a593Smuzhiyun i++;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* if no ranges, then we can return and avoid the checks...*/
496*4882a593Smuzhiyun if (!i)
497*4882a593Smuzhiyun return 0;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* sort the list */
500*4882a593Smuzhiyun list_sort(NULL, &ranges_list, rx_ranges_cmp);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /* and iterate over all the rx addresses */
503*4882a593Smuzhiyun for (addr = rx; addr < (u8 *)rx + SPI_TEST_MAX_SIZE_PLUS; addr++) {
504*4882a593Smuzhiyun /* if we are the DO not write pattern,
505*4882a593Smuzhiyun * then continue with the loop...
506*4882a593Smuzhiyun */
507*4882a593Smuzhiyun if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE)
508*4882a593Smuzhiyun continue;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /* check if we are inside a range */
511*4882a593Smuzhiyun list_for_each_entry(r, &ranges_list, list) {
512*4882a593Smuzhiyun /* if so then set to end... */
513*4882a593Smuzhiyun if ((addr >= r->start) && (addr < r->end))
514*4882a593Smuzhiyun addr = r->end;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun /* second test after a (hopefull) translation */
517*4882a593Smuzhiyun if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE)
518*4882a593Smuzhiyun continue;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* if still not found then something has modified too much */
521*4882a593Smuzhiyun /* we could list the "closest" transfer here... */
522*4882a593Smuzhiyun dev_err(&spi->dev,
523*4882a593Smuzhiyun "loopback strangeness - rx changed outside of allowed range at: %pK\n",
524*4882a593Smuzhiyun addr);
525*4882a593Smuzhiyun /* do not return, only set ret,
526*4882a593Smuzhiyun * so that we list all addresses
527*4882a593Smuzhiyun */
528*4882a593Smuzhiyun ret = -ERANGE;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun return ret;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
spi_test_check_elapsed_time(struct spi_device * spi,struct spi_test * test)534*4882a593Smuzhiyun static int spi_test_check_elapsed_time(struct spi_device *spi,
535*4882a593Smuzhiyun struct spi_test *test)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun int i;
538*4882a593Smuzhiyun unsigned long long estimated_time = 0;
539*4882a593Smuzhiyun unsigned long long delay_usecs = 0;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun for (i = 0; i < test->transfer_count; i++) {
542*4882a593Smuzhiyun struct spi_transfer *xfer = test->transfers + i;
543*4882a593Smuzhiyun unsigned long long nbits = (unsigned long long)BITS_PER_BYTE *
544*4882a593Smuzhiyun xfer->len;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun delay_usecs += xfer->delay.value;
547*4882a593Smuzhiyun if (!xfer->speed_hz)
548*4882a593Smuzhiyun continue;
549*4882a593Smuzhiyun estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun estimated_time += delay_usecs * NSEC_PER_USEC;
553*4882a593Smuzhiyun if (test->elapsed_time < estimated_time) {
554*4882a593Smuzhiyun dev_err(&spi->dev,
555*4882a593Smuzhiyun "elapsed time %lld ns is shorter than minimum estimated time %lld ns\n",
556*4882a593Smuzhiyun test->elapsed_time, estimated_time);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun return -EINVAL;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun return 0;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
spi_test_check_loopback_result(struct spi_device * spi,struct spi_message * msg,void * tx,void * rx)564*4882a593Smuzhiyun static int spi_test_check_loopback_result(struct spi_device *spi,
565*4882a593Smuzhiyun struct spi_message *msg,
566*4882a593Smuzhiyun void *tx, void *rx)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun struct spi_transfer *xfer;
569*4882a593Smuzhiyun u8 rxb, txb;
570*4882a593Smuzhiyun size_t i;
571*4882a593Smuzhiyun int ret;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* checks rx_buffer pattern are valid with loopback or without */
574*4882a593Smuzhiyun if (check_ranges) {
575*4882a593Smuzhiyun ret = spi_check_rx_ranges(spi, msg, rx);
576*4882a593Smuzhiyun if (ret)
577*4882a593Smuzhiyun return ret;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* if we run without loopback, then return now */
581*4882a593Smuzhiyun if (!loopback)
582*4882a593Smuzhiyun return 0;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /* if applicable to transfer check that rx_buf is equal to tx_buf */
585*4882a593Smuzhiyun list_for_each_entry(xfer, &msg->transfers, transfer_list) {
586*4882a593Smuzhiyun /* if there is no rx, then no check is needed */
587*4882a593Smuzhiyun if (!xfer->len || !xfer->rx_buf)
588*4882a593Smuzhiyun continue;
589*4882a593Smuzhiyun /* so depending on tx_buf we need to handle things */
590*4882a593Smuzhiyun if (xfer->tx_buf) {
591*4882a593Smuzhiyun for (i = 0; i < xfer->len; i++) {
592*4882a593Smuzhiyun txb = ((u8 *)xfer->tx_buf)[i];
593*4882a593Smuzhiyun rxb = ((u8 *)xfer->rx_buf)[i];
594*4882a593Smuzhiyun if (txb != rxb)
595*4882a593Smuzhiyun goto mismatch_error;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun } else {
598*4882a593Smuzhiyun /* first byte received */
599*4882a593Smuzhiyun txb = ((u8 *)xfer->rx_buf)[0];
600*4882a593Smuzhiyun /* first byte may be 0 or xff */
601*4882a593Smuzhiyun if (!((txb == 0) || (txb == 0xff))) {
602*4882a593Smuzhiyun dev_err(&spi->dev,
603*4882a593Smuzhiyun "loopback strangeness - we expect 0x00 or 0xff, but not 0x%02x\n",
604*4882a593Smuzhiyun txb);
605*4882a593Smuzhiyun return -EINVAL;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun /* check that all bytes are identical */
608*4882a593Smuzhiyun for (i = 1; i < xfer->len; i++) {
609*4882a593Smuzhiyun rxb = ((u8 *)xfer->rx_buf)[i];
610*4882a593Smuzhiyun if (rxb != txb)
611*4882a593Smuzhiyun goto mismatch_error;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun return 0;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun mismatch_error:
619*4882a593Smuzhiyun dev_err(&spi->dev,
620*4882a593Smuzhiyun "loopback strangeness - transfer mismatch on byte %04zx - expected 0x%02x, but got 0x%02x\n",
621*4882a593Smuzhiyun i, txb, rxb);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun return -EINVAL;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
spi_test_translate(struct spi_device * spi,void ** ptr,size_t len,void * tx,void * rx)626*4882a593Smuzhiyun static int spi_test_translate(struct spi_device *spi,
627*4882a593Smuzhiyun void **ptr, size_t len,
628*4882a593Smuzhiyun void *tx, void *rx)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun size_t off;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun /* return on null */
633*4882a593Smuzhiyun if (!*ptr)
634*4882a593Smuzhiyun return 0;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun /* in the MAX_SIZE_HALF case modify the pointer */
637*4882a593Smuzhiyun if (((size_t)*ptr) & SPI_TEST_MAX_SIZE_HALF)
638*4882a593Smuzhiyun /* move the pointer to the correct range */
639*4882a593Smuzhiyun *ptr += (SPI_TEST_MAX_SIZE_PLUS / 2) -
640*4882a593Smuzhiyun SPI_TEST_MAX_SIZE_HALF;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /* RX range
643*4882a593Smuzhiyun * - we check against MAX_SIZE_PLUS to allow for automated alignment
644*4882a593Smuzhiyun */
645*4882a593Smuzhiyun if (RANGE_CHECK(*ptr, len, RX(0), SPI_TEST_MAX_SIZE_PLUS)) {
646*4882a593Smuzhiyun off = *ptr - RX(0);
647*4882a593Smuzhiyun *ptr = rx + off;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun return 0;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun /* TX range */
653*4882a593Smuzhiyun if (RANGE_CHECK(*ptr, len, TX(0), SPI_TEST_MAX_SIZE_PLUS)) {
654*4882a593Smuzhiyun off = *ptr - TX(0);
655*4882a593Smuzhiyun *ptr = tx + off;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun return 0;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun dev_err(&spi->dev,
661*4882a593Smuzhiyun "PointerRange [%pK:%pK[ not in range [%pK:%pK[ or [%pK:%pK[\n",
662*4882a593Smuzhiyun *ptr, *ptr + len,
663*4882a593Smuzhiyun RX(0), RX(SPI_TEST_MAX_SIZE),
664*4882a593Smuzhiyun TX(0), TX(SPI_TEST_MAX_SIZE));
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun return -EINVAL;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
spi_test_fill_pattern(struct spi_device * spi,struct spi_test * test)669*4882a593Smuzhiyun static int spi_test_fill_pattern(struct spi_device *spi,
670*4882a593Smuzhiyun struct spi_test *test)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun struct spi_transfer *xfers = test->transfers;
673*4882a593Smuzhiyun u8 *tx_buf;
674*4882a593Smuzhiyun size_t count = 0;
675*4882a593Smuzhiyun int i, j;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
678*4882a593Smuzhiyun #define GET_VALUE_BYTE(value, index, bytes) \
679*4882a593Smuzhiyun (value >> (8 * (bytes - 1 - count % bytes)))
680*4882a593Smuzhiyun #else
681*4882a593Smuzhiyun #define GET_VALUE_BYTE(value, index, bytes) \
682*4882a593Smuzhiyun (value >> (8 * (count % bytes)))
683*4882a593Smuzhiyun #endif
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /* fill all transfers with the pattern requested */
686*4882a593Smuzhiyun for (i = 0; i < test->transfer_count; i++) {
687*4882a593Smuzhiyun /* fill rx_buf with SPI_TEST_PATTERN_UNWRITTEN */
688*4882a593Smuzhiyun if (xfers[i].rx_buf)
689*4882a593Smuzhiyun memset(xfers[i].rx_buf, SPI_TEST_PATTERN_UNWRITTEN,
690*4882a593Smuzhiyun xfers[i].len);
691*4882a593Smuzhiyun /* if tx_buf is NULL then skip */
692*4882a593Smuzhiyun tx_buf = (u8 *)xfers[i].tx_buf;
693*4882a593Smuzhiyun if (!tx_buf)
694*4882a593Smuzhiyun continue;
695*4882a593Smuzhiyun /* modify all the transfers */
696*4882a593Smuzhiyun for (j = 0; j < xfers[i].len; j++, tx_buf++, count++) {
697*4882a593Smuzhiyun /* fill tx */
698*4882a593Smuzhiyun switch (test->fill_option) {
699*4882a593Smuzhiyun case FILL_MEMSET_8:
700*4882a593Smuzhiyun *tx_buf = test->fill_pattern;
701*4882a593Smuzhiyun break;
702*4882a593Smuzhiyun case FILL_MEMSET_16:
703*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(test->fill_pattern,
704*4882a593Smuzhiyun count, 2);
705*4882a593Smuzhiyun break;
706*4882a593Smuzhiyun case FILL_MEMSET_24:
707*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(test->fill_pattern,
708*4882a593Smuzhiyun count, 3);
709*4882a593Smuzhiyun break;
710*4882a593Smuzhiyun case FILL_MEMSET_32:
711*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(test->fill_pattern,
712*4882a593Smuzhiyun count, 4);
713*4882a593Smuzhiyun break;
714*4882a593Smuzhiyun case FILL_COUNT_8:
715*4882a593Smuzhiyun *tx_buf = count;
716*4882a593Smuzhiyun break;
717*4882a593Smuzhiyun case FILL_COUNT_16:
718*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(count, count, 2);
719*4882a593Smuzhiyun break;
720*4882a593Smuzhiyun case FILL_COUNT_24:
721*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(count, count, 3);
722*4882a593Smuzhiyun break;
723*4882a593Smuzhiyun case FILL_COUNT_32:
724*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(count, count, 4);
725*4882a593Smuzhiyun break;
726*4882a593Smuzhiyun case FILL_TRANSFER_BYTE_8:
727*4882a593Smuzhiyun *tx_buf = j;
728*4882a593Smuzhiyun break;
729*4882a593Smuzhiyun case FILL_TRANSFER_BYTE_16:
730*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(j, j, 2);
731*4882a593Smuzhiyun break;
732*4882a593Smuzhiyun case FILL_TRANSFER_BYTE_24:
733*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(j, j, 3);
734*4882a593Smuzhiyun break;
735*4882a593Smuzhiyun case FILL_TRANSFER_BYTE_32:
736*4882a593Smuzhiyun *tx_buf = GET_VALUE_BYTE(j, j, 4);
737*4882a593Smuzhiyun break;
738*4882a593Smuzhiyun case FILL_TRANSFER_NUM:
739*4882a593Smuzhiyun *tx_buf = i;
740*4882a593Smuzhiyun break;
741*4882a593Smuzhiyun default:
742*4882a593Smuzhiyun dev_err(&spi->dev,
743*4882a593Smuzhiyun "unsupported fill_option: %i\n",
744*4882a593Smuzhiyun test->fill_option);
745*4882a593Smuzhiyun return -EINVAL;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun return 0;
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
_spi_test_run_iter(struct spi_device * spi,struct spi_test * test,void * tx,void * rx)753*4882a593Smuzhiyun static int _spi_test_run_iter(struct spi_device *spi,
754*4882a593Smuzhiyun struct spi_test *test,
755*4882a593Smuzhiyun void *tx, void *rx)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun struct spi_message *msg = &test->msg;
758*4882a593Smuzhiyun struct spi_transfer *x;
759*4882a593Smuzhiyun int i, ret;
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun /* initialize message - zero-filled via static initialization */
762*4882a593Smuzhiyun spi_message_init_no_memset(msg);
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /* fill rx with the DO_NOT_WRITE pattern */
765*4882a593Smuzhiyun memset(rx, SPI_TEST_PATTERN_DO_NOT_WRITE, SPI_TEST_MAX_SIZE_PLUS);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /* add the individual transfers */
768*4882a593Smuzhiyun for (i = 0; i < test->transfer_count; i++) {
769*4882a593Smuzhiyun x = &test->transfers[i];
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun /* patch the values of tx_buf */
772*4882a593Smuzhiyun ret = spi_test_translate(spi, (void **)&x->tx_buf, x->len,
773*4882a593Smuzhiyun (void *)tx, rx);
774*4882a593Smuzhiyun if (ret)
775*4882a593Smuzhiyun return ret;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun /* patch the values of rx_buf */
778*4882a593Smuzhiyun ret = spi_test_translate(spi, &x->rx_buf, x->len,
779*4882a593Smuzhiyun (void *)tx, rx);
780*4882a593Smuzhiyun if (ret)
781*4882a593Smuzhiyun return ret;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun /* and add it to the list */
784*4882a593Smuzhiyun spi_message_add_tail(x, msg);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun /* fill in the transfer buffers with pattern */
788*4882a593Smuzhiyun ret = spi_test_fill_pattern(spi, test);
789*4882a593Smuzhiyun if (ret)
790*4882a593Smuzhiyun return ret;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun /* and execute */
793*4882a593Smuzhiyun if (test->execute_msg)
794*4882a593Smuzhiyun ret = test->execute_msg(spi, test, tx, rx);
795*4882a593Smuzhiyun else
796*4882a593Smuzhiyun ret = spi_test_execute_msg(spi, test, tx, rx);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* handle result */
799*4882a593Smuzhiyun if (ret == test->expected_return)
800*4882a593Smuzhiyun return 0;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun dev_err(&spi->dev,
803*4882a593Smuzhiyun "test failed - test returned %i, but we expect %i\n",
804*4882a593Smuzhiyun ret, test->expected_return);
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun if (ret)
807*4882a593Smuzhiyun return ret;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun /* if it is 0, as we expected something else,
810*4882a593Smuzhiyun * then return something special
811*4882a593Smuzhiyun */
812*4882a593Smuzhiyun return -EFAULT;
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun
spi_test_run_iter(struct spi_device * spi,const struct spi_test * testtemplate,void * tx,void * rx,size_t len,size_t tx_off,size_t rx_off)815*4882a593Smuzhiyun static int spi_test_run_iter(struct spi_device *spi,
816*4882a593Smuzhiyun const struct spi_test *testtemplate,
817*4882a593Smuzhiyun void *tx, void *rx,
818*4882a593Smuzhiyun size_t len,
819*4882a593Smuzhiyun size_t tx_off,
820*4882a593Smuzhiyun size_t rx_off
821*4882a593Smuzhiyun )
822*4882a593Smuzhiyun {
823*4882a593Smuzhiyun struct spi_test test;
824*4882a593Smuzhiyun int i, tx_count, rx_count;
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun /* copy the test template to test */
827*4882a593Smuzhiyun memcpy(&test, testtemplate, sizeof(test));
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun /* if iterate_transfer_mask is not set,
830*4882a593Smuzhiyun * then set it to first transfer only
831*4882a593Smuzhiyun */
832*4882a593Smuzhiyun if (!(test.iterate_transfer_mask & (BIT(test.transfer_count) - 1)))
833*4882a593Smuzhiyun test.iterate_transfer_mask = 1;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun /* count number of transfers with tx/rx_buf != NULL */
836*4882a593Smuzhiyun rx_count = tx_count = 0;
837*4882a593Smuzhiyun for (i = 0; i < test.transfer_count; i++) {
838*4882a593Smuzhiyun if (test.transfers[i].tx_buf)
839*4882a593Smuzhiyun tx_count++;
840*4882a593Smuzhiyun if (test.transfers[i].rx_buf)
841*4882a593Smuzhiyun rx_count++;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun /* in some iteration cases warn and exit early,
845*4882a593Smuzhiyun * as there is nothing to do, that has not been tested already...
846*4882a593Smuzhiyun */
847*4882a593Smuzhiyun if (tx_off && (!tx_count)) {
848*4882a593Smuzhiyun dev_warn_once(&spi->dev,
849*4882a593Smuzhiyun "%s: iterate_tx_off configured with tx_buf==NULL - ignoring\n",
850*4882a593Smuzhiyun test.description);
851*4882a593Smuzhiyun return 0;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun if (rx_off && (!rx_count)) {
854*4882a593Smuzhiyun dev_warn_once(&spi->dev,
855*4882a593Smuzhiyun "%s: iterate_rx_off configured with rx_buf==NULL - ignoring\n",
856*4882a593Smuzhiyun test.description);
857*4882a593Smuzhiyun return 0;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun /* write out info */
861*4882a593Smuzhiyun if (!(len || tx_off || rx_off)) {
862*4882a593Smuzhiyun dev_info(&spi->dev, "Running test %s\n", test.description);
863*4882a593Smuzhiyun } else {
864*4882a593Smuzhiyun dev_info(&spi->dev,
865*4882a593Smuzhiyun " with iteration values: len = %zu, tx_off = %zu, rx_off = %zu\n",
866*4882a593Smuzhiyun len, tx_off, rx_off);
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun /* update in the values from iteration values */
870*4882a593Smuzhiyun for (i = 0; i < test.transfer_count; i++) {
871*4882a593Smuzhiyun /* only when bit in transfer mask is set */
872*4882a593Smuzhiyun if (!(test.iterate_transfer_mask & BIT(i)))
873*4882a593Smuzhiyun continue;
874*4882a593Smuzhiyun test.transfers[i].len = len;
875*4882a593Smuzhiyun if (test.transfers[i].tx_buf)
876*4882a593Smuzhiyun test.transfers[i].tx_buf += tx_off;
877*4882a593Smuzhiyun if (test.transfers[i].rx_buf)
878*4882a593Smuzhiyun test.transfers[i].rx_buf += rx_off;
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun /* and execute */
882*4882a593Smuzhiyun return _spi_test_run_iter(spi, &test, tx, rx);
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun /**
886*4882a593Smuzhiyun * spi_test_execute_msg - default implementation to run a test
887*4882a593Smuzhiyun *
888*4882a593Smuzhiyun * @spi: @spi_device on which to run the @spi_message
889*4882a593Smuzhiyun * @test: the test to execute, which already contains @msg
890*4882a593Smuzhiyun * @tx: the tx buffer allocated for the test sequence
891*4882a593Smuzhiyun * @rx: the rx buffer allocated for the test sequence
892*4882a593Smuzhiyun *
893*4882a593Smuzhiyun * Returns: error code of spi_sync as well as basic error checking
894*4882a593Smuzhiyun */
spi_test_execute_msg(struct spi_device * spi,struct spi_test * test,void * tx,void * rx)895*4882a593Smuzhiyun int spi_test_execute_msg(struct spi_device *spi, struct spi_test *test,
896*4882a593Smuzhiyun void *tx, void *rx)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun struct spi_message *msg = &test->msg;
899*4882a593Smuzhiyun int ret = 0;
900*4882a593Smuzhiyun int i;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun /* only if we do not simulate */
903*4882a593Smuzhiyun if (!simulate_only) {
904*4882a593Smuzhiyun ktime_t start;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun /* dump the complete message before and after the transfer */
907*4882a593Smuzhiyun if (dump_messages == 3)
908*4882a593Smuzhiyun spi_test_dump_message(spi, msg, true);
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun start = ktime_get();
911*4882a593Smuzhiyun /* run spi message */
912*4882a593Smuzhiyun ret = spi_sync(spi, msg);
913*4882a593Smuzhiyun test->elapsed_time = ktime_to_ns(ktime_sub(ktime_get(), start));
914*4882a593Smuzhiyun if (ret == -ETIMEDOUT) {
915*4882a593Smuzhiyun dev_info(&spi->dev,
916*4882a593Smuzhiyun "spi-message timed out - rerunning...\n");
917*4882a593Smuzhiyun /* rerun after a few explicit schedules */
918*4882a593Smuzhiyun for (i = 0; i < 16; i++)
919*4882a593Smuzhiyun schedule();
920*4882a593Smuzhiyun ret = spi_sync(spi, msg);
921*4882a593Smuzhiyun }
922*4882a593Smuzhiyun if (ret) {
923*4882a593Smuzhiyun dev_err(&spi->dev,
924*4882a593Smuzhiyun "Failed to execute spi_message: %i\n",
925*4882a593Smuzhiyun ret);
926*4882a593Smuzhiyun goto exit;
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun /* do some extra error checks */
930*4882a593Smuzhiyun if (msg->frame_length != msg->actual_length) {
931*4882a593Smuzhiyun dev_err(&spi->dev,
932*4882a593Smuzhiyun "actual length differs from expected\n");
933*4882a593Smuzhiyun ret = -EIO;
934*4882a593Smuzhiyun goto exit;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun /* run rx-buffer tests */
938*4882a593Smuzhiyun ret = spi_test_check_loopback_result(spi, msg, tx, rx);
939*4882a593Smuzhiyun if (ret)
940*4882a593Smuzhiyun goto exit;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun ret = spi_test_check_elapsed_time(spi, test);
943*4882a593Smuzhiyun }
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun /* if requested or on error dump message (including data) */
946*4882a593Smuzhiyun exit:
947*4882a593Smuzhiyun if (dump_messages || ret)
948*4882a593Smuzhiyun spi_test_dump_message(spi, msg,
949*4882a593Smuzhiyun (dump_messages >= 2) || (ret));
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun return ret;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(spi_test_execute_msg);
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun /**
956*4882a593Smuzhiyun * spi_test_run_test - run an individual spi_test
957*4882a593Smuzhiyun * including all the relevant iterations on:
958*4882a593Smuzhiyun * length and buffer alignment
959*4882a593Smuzhiyun *
960*4882a593Smuzhiyun * @spi: the spi_device to send the messages to
961*4882a593Smuzhiyun * @test: the test which we need to execute
962*4882a593Smuzhiyun * @tx: the tx buffer allocated for the test sequence
963*4882a593Smuzhiyun * @rx: the rx buffer allocated for the test sequence
964*4882a593Smuzhiyun *
965*4882a593Smuzhiyun * Returns: status code of spi_sync or other failures
966*4882a593Smuzhiyun */
967*4882a593Smuzhiyun
spi_test_run_test(struct spi_device * spi,const struct spi_test * test,void * tx,void * rx)968*4882a593Smuzhiyun int spi_test_run_test(struct spi_device *spi, const struct spi_test *test,
969*4882a593Smuzhiyun void *tx, void *rx)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun int idx_len;
972*4882a593Smuzhiyun size_t len;
973*4882a593Smuzhiyun size_t tx_align, rx_align;
974*4882a593Smuzhiyun int ret;
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun /* test for transfer limits */
977*4882a593Smuzhiyun if (test->transfer_count >= SPI_TEST_MAX_TRANSFERS) {
978*4882a593Smuzhiyun dev_err(&spi->dev,
979*4882a593Smuzhiyun "%s: Exceeded max number of transfers with %i\n",
980*4882a593Smuzhiyun test->description, test->transfer_count);
981*4882a593Smuzhiyun return -E2BIG;
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun /* setting up some values in spi_message
985*4882a593Smuzhiyun * based on some settings in spi_master
986*4882a593Smuzhiyun * some of this can also get done in the run() method
987*4882a593Smuzhiyun */
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun /* iterate over all the iterable values using macros
990*4882a593Smuzhiyun * (to make it a bit more readable...
991*4882a593Smuzhiyun */
992*4882a593Smuzhiyun #define FOR_EACH_ALIGNMENT(var) \
993*4882a593Smuzhiyun for (var = 0; \
994*4882a593Smuzhiyun var < (test->iterate_##var ? \
995*4882a593Smuzhiyun (spi->master->dma_alignment ? \
996*4882a593Smuzhiyun spi->master->dma_alignment : \
997*4882a593Smuzhiyun test->iterate_##var) : \
998*4882a593Smuzhiyun 1); \
999*4882a593Smuzhiyun var++)
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun for (idx_len = 0; idx_len < SPI_TEST_MAX_ITERATE &&
1002*4882a593Smuzhiyun (len = test->iterate_len[idx_len]) != -1; idx_len++) {
1003*4882a593Smuzhiyun FOR_EACH_ALIGNMENT(tx_align) {
1004*4882a593Smuzhiyun FOR_EACH_ALIGNMENT(rx_align) {
1005*4882a593Smuzhiyun /* and run the iteration */
1006*4882a593Smuzhiyun ret = spi_test_run_iter(spi, test,
1007*4882a593Smuzhiyun tx, rx,
1008*4882a593Smuzhiyun len,
1009*4882a593Smuzhiyun tx_align,
1010*4882a593Smuzhiyun rx_align);
1011*4882a593Smuzhiyun if (ret)
1012*4882a593Smuzhiyun return ret;
1013*4882a593Smuzhiyun }
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun return 0;
1018*4882a593Smuzhiyun }
1019*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(spi_test_run_test);
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun /**
1022*4882a593Smuzhiyun * spi_test_run_tests - run an array of spi_messages tests
1023*4882a593Smuzhiyun * @spi: the spi device on which to run the tests
1024*4882a593Smuzhiyun * @tests: NULL-terminated array of @spi_test
1025*4882a593Smuzhiyun *
1026*4882a593Smuzhiyun * Returns: status errors as per @spi_test_run_test()
1027*4882a593Smuzhiyun */
1028*4882a593Smuzhiyun
spi_test_run_tests(struct spi_device * spi,struct spi_test * tests)1029*4882a593Smuzhiyun int spi_test_run_tests(struct spi_device *spi,
1030*4882a593Smuzhiyun struct spi_test *tests)
1031*4882a593Smuzhiyun {
1032*4882a593Smuzhiyun char *rx = NULL, *tx = NULL;
1033*4882a593Smuzhiyun int ret = 0, count = 0;
1034*4882a593Smuzhiyun struct spi_test *test;
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /* allocate rx/tx buffers of 128kB size without devm
1037*4882a593Smuzhiyun * in the hope that is on a page boundary
1038*4882a593Smuzhiyun */
1039*4882a593Smuzhiyun if (use_vmalloc)
1040*4882a593Smuzhiyun rx = vmalloc(SPI_TEST_MAX_SIZE_PLUS);
1041*4882a593Smuzhiyun else
1042*4882a593Smuzhiyun rx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
1043*4882a593Smuzhiyun if (!rx)
1044*4882a593Smuzhiyun return -ENOMEM;
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun if (use_vmalloc)
1048*4882a593Smuzhiyun tx = vmalloc(SPI_TEST_MAX_SIZE_PLUS);
1049*4882a593Smuzhiyun else
1050*4882a593Smuzhiyun tx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
1051*4882a593Smuzhiyun if (!tx) {
1052*4882a593Smuzhiyun ret = -ENOMEM;
1053*4882a593Smuzhiyun goto err_tx;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun /* now run the individual tests in the table */
1057*4882a593Smuzhiyun for (test = tests, count = 0; test->description[0];
1058*4882a593Smuzhiyun test++, count++) {
1059*4882a593Smuzhiyun /* only run test if requested */
1060*4882a593Smuzhiyun if ((run_only_test > -1) && (count != run_only_test))
1061*4882a593Smuzhiyun continue;
1062*4882a593Smuzhiyun /* run custom implementation */
1063*4882a593Smuzhiyun if (test->run_test)
1064*4882a593Smuzhiyun ret = test->run_test(spi, test, tx, rx);
1065*4882a593Smuzhiyun else
1066*4882a593Smuzhiyun ret = spi_test_run_test(spi, test, tx, rx);
1067*4882a593Smuzhiyun if (ret)
1068*4882a593Smuzhiyun goto out;
1069*4882a593Smuzhiyun /* add some delays so that we can easily
1070*4882a593Smuzhiyun * detect the individual tests when using a logic analyzer
1071*4882a593Smuzhiyun * we also add scheduling to avoid potential spi_timeouts...
1072*4882a593Smuzhiyun */
1073*4882a593Smuzhiyun mdelay(100);
1074*4882a593Smuzhiyun schedule();
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun out:
1078*4882a593Smuzhiyun kvfree(tx);
1079*4882a593Smuzhiyun err_tx:
1080*4882a593Smuzhiyun kvfree(rx);
1081*4882a593Smuzhiyun return ret;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(spi_test_run_tests);
1084