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
print_buffer(const char * string,void * buffer,int len)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
print_buffer(const char * string,void * buffer,int len)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
xor_20(unsigned char val)55 static unsigned char xor_20(unsigned char val)
56 {
57 return val^0x20;
58 }
59
reorder_phy_data(u8 bits_per_word,void * buf,unsigned int len)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
resp_find_sop_eop(unsigned char * resp,unsigned int len,int flags)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
phy_tx_pad(unsigned char * phy_buf,unsigned int phy_buf_len,unsigned int * aligned_len)112 static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len,
113 unsigned int *aligned_len)
114 {
115 unsigned char *p = &phy_buf[phy_buf_len - 1], *dst_p;
116
117 *aligned_len = IFPGA_ALIGN(phy_buf_len, 4);
118
119 if (*aligned_len == phy_buf_len)
120 return;
121
122 dst_p = &phy_buf[*aligned_len - 1];
123
124 /* move EOP and bytes after EOP to the end of aligned size */
125 while (p > phy_buf) {
126 *dst_p = *p;
127
128 if (*p == SPI_PACKET_EOP)
129 break;
130
131 p--;
132 dst_p--;
133 }
134
135 /* fill the hole with PHY_IDLE */
136 while (p < dst_p)
137 *p++ = SPI_BYTE_IDLE;
138 }
139
byte_to_core_convert(struct spi_transaction_dev * dev,unsigned int send_len,unsigned char * send_data,unsigned int resp_len,unsigned char * resp_data,unsigned int * valid_resp_len)140 static int byte_to_core_convert(struct spi_transaction_dev *dev,
141 unsigned int send_len, unsigned char *send_data,
142 unsigned int resp_len, unsigned char *resp_data,
143 unsigned int *valid_resp_len)
144 {
145 unsigned int i;
146 int ret = 0;
147 unsigned char *send_packet = dev->buffer->bytes_send;
148 unsigned char *resp_packet = dev->buffer->bytes_resp;
149 unsigned char *p;
150 unsigned char current_byte;
151 unsigned char *tx_buffer;
152 unsigned int tx_len = 0;
153 unsigned char *rx_buffer;
154 unsigned int rx_len = 0;
155 int retry = 0;
156 int spi_flags;
157 unsigned long timeout = msecs_to_timer_cycles(1000);
158 unsigned long ticks;
159 unsigned int resp_max_len = 2 * resp_len;
160
161 print_buffer("before bytes:", send_data, send_len);
162
163 p = send_packet;
164
165 for (i = 0; i < send_len; i++) {
166 current_byte = send_data[i];
167 switch (current_byte) {
168 case SPI_BYTE_IDLE:
169 *p++ = SPI_BYTE_ESC;
170 *p++ = xor_20(current_byte);
171 break;
172 case SPI_BYTE_ESC:
173 *p++ = SPI_BYTE_ESC;
174 *p++ = xor_20(current_byte);
175 break;
176 default:
177 *p++ = current_byte;
178 break;
179 }
180 }
181
182 tx_len = p - send_packet;
183
184 print_buffer("before spi:", send_packet, tx_len);
185
186 phy_tx_pad(send_packet, tx_len, &tx_len);
187 print_buffer("after pad:", send_packet, tx_len);
188
189 reorder_phy_data(32, send_packet, tx_len);
190
191 print_buffer("after order to spi:", send_packet, tx_len);
192
193 /* call spi */
194 tx_buffer = send_packet;
195 rx_buffer = resp_packet;
196 rx_len = resp_max_len;
197 spi_flags = SPI_NOT_FOUND;
198
199 read_again:
200 ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer,
201 rx_len, rx_buffer);
202 if (ret)
203 return -EBUSY;
204
205 print_buffer("read from spi:", rx_buffer, rx_len);
206
207 /* look for SOP firstly*/
208 ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags);
209 if (ret != SPI_FOUND_EOP) {
210 tx_buffer = NULL;
211 tx_len = 0;
212 ticks = rte_get_timer_cycles();
213 if (time_after(ticks, timeout) &&
214 retry++ > SPI_MAX_RETRY) {
215 dev_err(NULL, "Have retry %d, found invalid packet data\n",
216 retry);
217 return -EBUSY;
218 }
219
220 if (ret == SPI_FOUND_SOP) {
221 rx_buffer += rx_len;
222 resp_max_len += rx_len;
223 }
224
225 spi_flags = ret;
226 goto read_again;
227 }
228
229 print_buffer("found valid data:", resp_packet, resp_max_len);
230
231 /* analyze response packet */
232 i = 0;
233 p = resp_data;
234 while (i < resp_max_len) {
235 current_byte = resp_packet[i];
236 switch (current_byte) {
237 case SPI_BYTE_IDLE:
238 i++;
239 break;
240 case SPI_BYTE_ESC:
241 i++;
242 current_byte = resp_packet[i];
243 *p++ = xor_20(current_byte);
244 i++;
245 break;
246 default:
247 *p++ = current_byte;
248 i++;
249 break;
250 }
251 }
252
253 /* receive "4a" means the SPI is idle, not valid data */
254 *valid_resp_len = p - resp_data;
255 if (*valid_resp_len == 0) {
256 dev_err(NULL, "error: repond package without valid data\n");
257 return -EINVAL;
258 }
259
260 return 0;
261 }
262
packet_to_byte_conver(struct spi_transaction_dev * dev,unsigned int send_len,unsigned char * send_buf,unsigned int resp_len,unsigned char * resp_buf,unsigned int * valid)263 static int packet_to_byte_conver(struct spi_transaction_dev *dev,
264 unsigned int send_len, unsigned char *send_buf,
265 unsigned int resp_len, unsigned char *resp_buf,
266 unsigned int *valid)
267 {
268 int ret = 0;
269 unsigned int i;
270 unsigned char current_byte;
271 unsigned int resp_max_len;
272 unsigned char *send_packet = dev->buffer->packet_send;
273 unsigned char *resp_packet = dev->buffer->packet_resp;
274 unsigned char *p;
275 unsigned int valid_resp_len = 0;
276
277 print_buffer("before packet:", send_buf, send_len);
278
279 resp_max_len = 2 * resp_len + 4;
280
281 p = send_packet;
282
283 /* SOP header */
284 *p++ = SPI_PACKET_SOP;
285
286 *p++ = SPI_PACKET_CHANNEL;
287 *p++ = 0;
288
289 /* append the data into a packet */
290 for (i = 0; i < send_len; i++) {
291 current_byte = send_buf[i];
292
293 /* EOP for last byte */
294 if (i == send_len - 1)
295 *p++ = SPI_PACKET_EOP;
296
297 switch (current_byte) {
298 case SPI_PACKET_SOP:
299 case SPI_PACKET_EOP:
300 case SPI_PACKET_CHANNEL:
301 case SPI_PACKET_ESC:
302 *p++ = SPI_PACKET_ESC;
303 *p++ = xor_20(current_byte);
304 break;
305 default:
306 *p++ = current_byte;
307 }
308 }
309
310 ret = byte_to_core_convert(dev, p - send_packet,
311 send_packet, resp_max_len, resp_packet,
312 &valid_resp_len);
313 if (ret)
314 return -EBUSY;
315
316 print_buffer("after byte conver:", resp_packet, valid_resp_len);
317
318 /* analyze the response packet */
319 p = resp_buf;
320
321 /* look for SOP */
322 for (i = 0; i < valid_resp_len; i++) {
323 if (resp_packet[i] == SPI_PACKET_SOP)
324 break;
325 }
326
327 if (i == valid_resp_len) {
328 dev_err(NULL, "error on analyze response packet 0x%x\n",
329 resp_packet[i]);
330 return -EINVAL;
331 }
332
333 i++;
334
335 /* continue parsing data after SOP */
336 while (i < valid_resp_len) {
337 current_byte = resp_packet[i];
338
339 switch (current_byte) {
340 case SPI_PACKET_ESC:
341 case SPI_PACKET_CHANNEL:
342 case SPI_PACKET_SOP:
343 i++;
344 current_byte = resp_packet[i];
345 *p++ = xor_20(current_byte);
346 i++;
347 break;
348 case SPI_PACKET_EOP:
349 i++;
350 current_byte = resp_packet[i];
351 if (current_byte == SPI_PACKET_ESC ||
352 current_byte == SPI_PACKET_CHANNEL ||
353 current_byte == SPI_PACKET_SOP) {
354 i++;
355 current_byte = resp_packet[i];
356 *p++ = xor_20(current_byte);
357 } else
358 *p++ = current_byte;
359 i = valid_resp_len;
360 break;
361 default:
362 *p++ = current_byte;
363 i++;
364 }
365
366 }
367
368 *valid = p - resp_buf;
369
370 print_buffer("after packet:", resp_buf, *valid);
371
372 return ret;
373 }
374
do_transaction(struct spi_transaction_dev * dev,unsigned int addr,unsigned int size,unsigned char * data,unsigned int trans_type)375 static int do_transaction(struct spi_transaction_dev *dev, unsigned int addr,
376 unsigned int size, unsigned char *data,
377 unsigned int trans_type)
378 {
379
380 struct spi_tran_header header;
381 unsigned char *transaction = dev->buffer->tran_send;
382 unsigned char *response = dev->buffer->tran_resp;
383 unsigned char *p;
384 int ret = 0;
385 unsigned int i;
386 unsigned int valid_len = 0;
387
388 /* make transacation header */
389 INIT_SPI_TRAN_HEADER(trans_type, size, addr);
390
391 /* fill the header */
392 p = transaction;
393 opae_memcpy(p, &header, sizeof(struct spi_tran_header));
394 p = p + sizeof(struct spi_tran_header);
395
396 switch (trans_type) {
397 case SPI_TRAN_SEQ_WRITE:
398 case SPI_TRAN_NON_SEQ_WRITE:
399 for (i = 0; i < size; i++)
400 *p++ = *data++;
401
402 ret = packet_to_byte_conver(dev, size + HEADER_LEN,
403 transaction, RESPONSE_LEN, response,
404 &valid_len);
405 if (ret)
406 return -EBUSY;
407
408 /* check the result */
409 if (size != ((unsigned int)(response[2] & 0xff) << 8 |
410 (unsigned int)(response[3] & 0xff)))
411 ret = -EBUSY;
412
413 break;
414 case SPI_TRAN_SEQ_READ:
415 case SPI_TRAN_NON_SEQ_READ:
416 ret = packet_to_byte_conver(dev, HEADER_LEN,
417 transaction, size, response,
418 &valid_len);
419 if (ret || valid_len != size)
420 return -EBUSY;
421
422 for (i = 0; i < size; i++)
423 *data++ = *response++;
424
425 ret = 0;
426 break;
427 }
428
429 return ret;
430 }
431
spi_transaction_read(struct spi_transaction_dev * dev,unsigned int addr,unsigned int size,unsigned char * data)432 int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,
433 unsigned int size, unsigned char *data)
434 {
435 int ret;
436
437 pthread_mutex_lock(dev->mutex);
438 ret = do_transaction(dev, addr, size, data,
439 (size > SPI_REG_BYTES) ?
440 SPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);
441 pthread_mutex_unlock(dev->mutex);
442
443 return ret;
444 }
445
spi_transaction_write(struct spi_transaction_dev * dev,unsigned int addr,unsigned int size,unsigned char * data)446 int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,
447 unsigned int size, unsigned char *data)
448 {
449 int ret;
450
451 pthread_mutex_lock(dev->mutex);
452 ret = do_transaction(dev, addr, size, data,
453 (size > SPI_REG_BYTES) ?
454 SPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);
455 pthread_mutex_unlock(dev->mutex);
456
457 return ret;
458 }
459
spi_transaction_init(struct altera_spi_device * dev,int chipselect)460 struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,
461 int chipselect)
462 {
463 struct spi_transaction_dev *spi_tran_dev;
464 int ret;
465
466 spi_tran_dev = opae_malloc(sizeof(struct spi_transaction_dev));
467 if (!spi_tran_dev)
468 return NULL;
469
470 spi_tran_dev->dev = dev;
471 spi_tran_dev->chipselect = chipselect;
472
473 spi_tran_dev->buffer = opae_malloc(sizeof(struct spi_tran_buffer));
474 if (!spi_tran_dev->buffer)
475 goto err;
476
477 ret = pthread_mutex_init(&spi_tran_dev->lock, NULL);
478 if (ret) {
479 dev_err(spi_tran_dev, "fail to init mutex lock\n");
480 goto err;
481 }
482 if (dev->mutex) {
483 dev_info(NULL, "use multi-process mutex in spi\n");
484 spi_tran_dev->mutex = dev->mutex;
485 } else {
486 dev_info(NULL, "use multi-thread mutex in spi\n");
487 spi_tran_dev->mutex = &spi_tran_dev->lock;
488 }
489
490 return spi_tran_dev;
491
492 err:
493 opae_free(spi_tran_dev);
494 return NULL;
495 }
496
spi_transaction_remove(struct spi_transaction_dev * dev)497 void spi_transaction_remove(struct spi_transaction_dev *dev)
498 {
499 if (dev && dev->buffer)
500 opae_free(dev->buffer);
501 if (dev) {
502 pthread_mutex_destroy(&dev->lock);
503 opae_free(dev);
504 }
505 }
506