raw/ifpga/base: add SPI and MAX10 device driver
[dpdk.git] / drivers / raw / ifpga_rawdev / base / opae_spi_transaction.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2019 Intel Corporation
3  */
4
5 #include "opae_spi.h"
6 #include "ifpga_compat.h"
7
8 /*transaction opcodes*/
9 #define SPI_TRAN_SEQ_WRITE 0x04 /* SPI transaction sequential write */
10 #define SPI_TRAN_SEQ_READ  0x14 /* SPI transaction sequential read */
11 #define SPI_TRAN_NON_SEQ_WRITE 0x00 /* SPI transaction non-sequential write */
12 #define SPI_TRAN_NON_SEQ_READ  0x10 /* SPI transaction non-sequential read*/
13
14 /*specail packet characters*/
15 #define SPI_PACKET_SOP     0x7a
16 #define SPI_PACKET_EOP     0x7b
17 #define SPI_PACKET_CHANNEL 0x7c
18 #define SPI_PACKET_ESC     0x7d
19
20 /*special byte characters*/
21 #define SPI_BYTE_IDLE 0x4a
22 #define SPI_BYTE_ESC  0x4d
23
24 #define SPI_REG_BYTES 4
25
26 #define INIT_SPI_TRAN_HEADER(trans_type, size, address) \
27 ({ \
28         header.trans_type = trans_type; \
29         header.reserve = 0; \
30         header.size = cpu_to_be16(size); \
31         header.addr = cpu_to_be32(addr); \
32 })
33
34 #ifdef OPAE_SPI_DEBUG
35 static void print_buffer(const char *string, void *buffer, int len)
36 {
37         int i;
38         unsigned char *p = buffer;
39
40         printf("%s print buffer, len=%d\n", string, len);
41
42         for (i = 0; i < len; i++)
43                 printf("%x ", *(p+i));
44         printf("\n");
45 }
46 #else
47 static void print_buffer(const char *string, void *buffer, int len)
48 {
49         UNUSED(string);
50         UNUSED(buffer);
51         UNUSED(len);
52 }
53 #endif
54
55 static unsigned char xor_20(unsigned char val)
56 {
57         return val^0x20;
58 }
59
60 static void reorder_phy_data(u8 bits_per_word,
61                 void *buf, unsigned int len)
62 {
63         unsigned int count = len / (bits_per_word/8);
64         u32 *p;
65
66         if (bits_per_word == 32) {
67                 p = (u32 *)buf;
68                 while (count--) {
69                         *p = cpu_to_be32(*p);
70                         p++;
71                 }
72         }
73 }
74
75 enum {
76         SPI_FOUND_SOP,
77         SPI_FOUND_EOP,
78         SPI_NOT_FOUND,
79 };
80
81 static int resp_find_sop_eop(unsigned char *resp, unsigned int len,
82                 int flags)
83 {
84         int ret = SPI_NOT_FOUND;
85
86         unsigned char *b = resp;
87
88         /* find SOP */
89         if (flags != SPI_FOUND_SOP) {
90                 while (b < resp + len && *b != SPI_PACKET_SOP)
91                         b++;
92
93                 if (*b != SPI_PACKET_SOP)
94                         goto done;
95
96                 ret = SPI_FOUND_SOP;
97         }
98
99         /* find EOP */
100         while (b < resp + len && *b != SPI_PACKET_EOP)
101                 b++;
102
103         if (*b != SPI_PACKET_EOP)
104                 goto done;
105
106         ret = SPI_FOUND_EOP;
107
108 done:
109         return ret;
110 }
111
112 static int byte_to_core_convert(struct spi_transaction_dev *dev,
113                 unsigned int send_len, unsigned char *send_data,
114                 unsigned int resp_len, unsigned char *resp_data,
115                 unsigned int *valid_resp_len)
116 {
117         unsigned int i;
118         int ret = 0;
119         unsigned char *send_packet = dev->buffer->bytes_send;
120         unsigned char *resp_packet = dev->buffer->bytes_resp;
121         unsigned char *p;
122         unsigned char current_byte;
123         unsigned char *tx_buffer;
124         unsigned int tx_len = 0;
125         unsigned char *rx_buffer;
126         unsigned int rx_len = 0;
127         int retry = 0;
128         int spi_flags;
129         unsigned int resp_max_len = 2 * resp_len;
130
131         print_buffer("before bytes:", send_data, send_len);
132
133         p = send_packet;
134
135         for (i = 0; i < send_len; i++) {
136                 current_byte = send_data[i];
137                 switch (current_byte) {
138                 case SPI_BYTE_IDLE:
139                         *p++ = SPI_BYTE_IDLE;
140                         *p++ = xor_20(current_byte);
141                         break;
142                 case SPI_BYTE_ESC:
143                         *p++ = SPI_BYTE_ESC;
144                         *p++ = xor_20(current_byte);
145                         break;
146                 default:
147                         *p++ = current_byte;
148                         break;
149                 }
150         }
151
152         print_buffer("before spi:", send_packet, p-send_packet);
153
154         reorder_phy_data(32, send_packet, p - send_packet);
155
156         print_buffer("after order to spi:", send_packet, p-send_packet);
157
158         /* call spi */
159         tx_buffer = send_packet;
160         tx_len = p - send_packet;
161         rx_buffer = resp_packet;
162         rx_len = resp_max_len;
163         spi_flags = SPI_NOT_FOUND;
164
165 read_again:
166         ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer,
167                         rx_len, rx_buffer);
168         if (ret)
169                 return -EBUSY;
170
171         print_buffer("read from spi:", rx_buffer, rx_len);
172
173         /* look for SOP firstly*/
174         ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags);
175         if (ret != SPI_FOUND_EOP) {
176                 tx_buffer = NULL;
177                 tx_len = 0;
178                 if (retry++ > 10) {
179                         dev_err(NULL, "cannot found valid data from SPI\n");
180                         return -EBUSY;
181                 }
182
183                 if (ret == SPI_FOUND_SOP) {
184                         rx_buffer += rx_len;
185                         resp_max_len += rx_len;
186                 }
187
188                 spi_flags = ret;
189                 goto read_again;
190         }
191
192         print_buffer("found valid data:", resp_packet, resp_max_len);
193
194         /* analyze response packet */
195         i = 0;
196         p = resp_data;
197         while (i < resp_max_len) {
198                 current_byte = resp_packet[i];
199                 switch (current_byte) {
200                 case SPI_BYTE_IDLE:
201                         i++;
202                         break;
203                 case SPI_BYTE_ESC:
204                         i++;
205                         current_byte = resp_packet[i];
206                         *p++ = xor_20(current_byte);
207                         i++;
208                         break;
209                 default:
210                         *p++ = current_byte;
211                         i++;
212                         break;
213                 }
214         }
215
216         /* receive "4a" means the SPI is idle, not valid data */
217         *valid_resp_len = p - resp_data;
218         if (*valid_resp_len == 0) {
219                 dev_err(NULL, "error: repond package without valid data\n");
220                 return -EINVAL;
221         }
222
223         return 0;
224 }
225
226 static int packet_to_byte_conver(struct spi_transaction_dev *dev,
227                 unsigned int send_len, unsigned char *send_buf,
228                 unsigned int resp_len, unsigned char *resp_buf,
229                 unsigned int *valid)
230 {
231         int ret = 0;
232         unsigned int i;
233         unsigned char current_byte;
234         unsigned int resp_max_len;
235         unsigned char *send_packet = dev->buffer->packet_send;
236         unsigned char *resp_packet = dev->buffer->packet_resp;
237         unsigned char *p;
238         unsigned int valid_resp_len = 0;
239
240         print_buffer("before packet:", send_buf, send_len);
241
242         resp_max_len = 2 * resp_len + 4;
243
244         p = send_packet;
245
246         /* SOP header */
247         *p++ = SPI_PACKET_SOP;
248
249         *p++ = SPI_PACKET_CHANNEL;
250         *p++ = 0;
251
252         /* append the data into a packet */
253         for (i = 0; i < send_len; i++) {
254                 current_byte = send_buf[i];
255
256                 /* EOP for last byte */
257                 if (i == send_len - 1)
258                         *p++ = SPI_PACKET_EOP;
259
260                 switch (current_byte) {
261                 case SPI_PACKET_SOP:
262                 case SPI_PACKET_EOP:
263                 case SPI_PACKET_CHANNEL:
264                 case SPI_PACKET_ESC:
265                         *p++ = SPI_PACKET_ESC;
266                         *p++ = xor_20(current_byte);
267                         break;
268                 default:
269                         *p++ = current_byte;
270                 }
271         }
272
273         ret = byte_to_core_convert(dev, p - send_packet,
274                         send_packet, resp_max_len, resp_packet,
275                         &valid_resp_len);
276         if (ret)
277                 return -EBUSY;
278
279         print_buffer("after byte conver:", resp_packet, valid_resp_len);
280
281         /* analyze the response packet */
282         p = resp_buf;
283
284         /* look for SOP */
285         for (i = 0; i < valid_resp_len; i++) {
286                 if (resp_packet[i] == SPI_PACKET_SOP)
287                         break;
288         }
289
290         if (i == valid_resp_len) {
291                 dev_err(NULL, "error on analyze response packet 0x%x\n",
292                                 resp_packet[i]);
293                 return -EINVAL;
294         }
295
296         i++;
297
298         /* continue parsing data after SOP */
299         while (i < valid_resp_len) {
300                 current_byte = resp_packet[i];
301
302                 switch (current_byte) {
303                 case SPI_PACKET_ESC:
304                 case SPI_PACKET_CHANNEL:
305                 case SPI_PACKET_SOP:
306                         i++;
307                         current_byte = resp_packet[i];
308                         *p++ = xor_20(current_byte);
309                         i++;
310                         break;
311                 case SPI_PACKET_EOP:
312                         i++;
313                         current_byte = resp_packet[i];
314                         if (current_byte == SPI_PACKET_ESC ||
315                                         current_byte == SPI_PACKET_CHANNEL ||
316                                         current_byte == SPI_PACKET_SOP) {
317                                 i++;
318                                 current_byte = resp_packet[i];
319                                 *p++ = xor_20(current_byte);
320                         } else
321                                 *p++ = current_byte;
322                         i = valid_resp_len;
323                         break;
324                 default:
325                         *p++ = current_byte;
326                         i++;
327                 }
328
329         }
330
331         *valid = p - resp_buf;
332
333         print_buffer("after packet:", resp_buf, *valid);
334
335         return ret;
336 }
337
338 static int do_transaction(struct spi_transaction_dev *dev, unsigned int addr,
339                 unsigned int size, unsigned char *data,
340                 unsigned int trans_type)
341 {
342
343         struct spi_tran_header header;
344         unsigned char *transaction = dev->buffer->tran_send;
345         unsigned char *response = dev->buffer->tran_resp;
346         unsigned char *p;
347         int ret = 0;
348         unsigned int i;
349         unsigned int valid_len = 0;
350
351         /* make transacation header */
352         INIT_SPI_TRAN_HEADER(trans_type, size, addr);
353
354         /* fill the header */
355         p = transaction;
356         opae_memcpy(p, &header, sizeof(struct spi_tran_header));
357         p = p + sizeof(struct spi_tran_header);
358
359         switch (trans_type) {
360         case SPI_TRAN_SEQ_WRITE:
361         case SPI_TRAN_NON_SEQ_WRITE:
362                 for (i = 0; i < size; i++)
363                         *p++ = *data++;
364
365                 ret = packet_to_byte_conver(dev, size + HEADER_LEN,
366                                 transaction, RESPONSE_LEN, response,
367                                 &valid_len);
368                 if (ret)
369                         return -EBUSY;
370
371                 /* check the result */
372                 if (size != ((unsigned int)(response[2] & 0xff) << 8 |
373                         (unsigned int)(response[3] & 0xff)))
374                         ret = -EBUSY;
375
376                 break;
377         case SPI_TRAN_SEQ_READ:
378         case SPI_TRAN_NON_SEQ_READ:
379                 ret = packet_to_byte_conver(dev, HEADER_LEN,
380                                 transaction, size, response,
381                                 &valid_len);
382                 if (ret || valid_len != size)
383                         return -EBUSY;
384
385                 for (i = 0; i < size; i++)
386                         *data++ = *response++;
387
388                 ret = 0;
389                 break;
390         }
391
392         return ret;
393 }
394
395 int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,
396                 unsigned int size, unsigned char *data)
397 {
398         return do_transaction(dev, addr, size, data,
399                         (size > SPI_REG_BYTES) ?
400                         SPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);
401 }
402
403 int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,
404                 unsigned int size, unsigned char *data)
405 {
406         return do_transaction(dev, addr, size, data,
407                         (size > SPI_REG_BYTES) ?
408                         SPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);
409 }
410
411 struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,
412                 int chipselect)
413 {
414         struct spi_transaction_dev *spi_tran_dev;
415
416         spi_tran_dev = opae_malloc(sizeof(struct spi_transaction_dev));
417         if (!spi_tran_dev)
418                 return NULL;
419
420         spi_tran_dev->dev = dev;
421         spi_tran_dev->chipselect = chipselect;
422
423         spi_tran_dev->buffer = opae_malloc(sizeof(struct spi_tran_buffer));
424         if (!spi_tran_dev->buffer) {
425                 opae_free(spi_tran_dev);
426                 return NULL;
427         }
428
429         return spi_tran_dev;
430 }
431
432 void spi_transaction_remove(struct spi_transaction_dev *dev)
433 {
434         if (dev && dev->buffer)
435                 opae_free(dev->buffer);
436         if (dev)
437                 opae_free(dev);
438 }