xref: /dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c (revision d28809c27d2dae063231bee4e8332095476812f3)
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 __extension__ ({ \
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("%02x ", *(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 static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len,
76 		unsigned int *aligned_len)
77 {
78 	unsigned char *p = &phy_buf[phy_buf_len - 1], *dst_p;
79 
80 	*aligned_len = IFPGA_ALIGN(phy_buf_len, 4);
81 
82 	if (*aligned_len == phy_buf_len)
83 		return;
84 
85 	dst_p = &phy_buf[*aligned_len - 1];
86 
87 	/* move EOP and bytes after EOP to the end of aligned size */
88 	while (p > phy_buf) {
89 		*dst_p = *p;
90 
91 		if (*p == SPI_PACKET_EOP)
92 			break;
93 
94 		p--;
95 		dst_p--;
96 	}
97 
98 	/* fill the hole with PHY_IDLE */
99 	while (p < dst_p)
100 		*p++ = SPI_BYTE_IDLE;
101 }
102 
103 #define RX_ALL_IDLE_DATA (SPI_BYTE_IDLE << 24 | SPI_BYTE_IDLE << 16 |	\
104 			 SPI_BYTE_IDLE << 8 | SPI_BYTE_IDLE)
105 
106 static bool all_idle_data(u8 *rxbuf)
107 {
108 	return *(u32 *)rxbuf == RX_ALL_IDLE_DATA;
109 }
110 
111 static unsigned char *find_eop(u8 *rxbuf, u32 BPW)
112 {
113 	return memchr(rxbuf, SPI_PACKET_EOP, BPW);
114 }
115 
116 static int do_spi_txrx(struct spi_transaction_dev *dev,
117 		unsigned char *tx_buffer,
118 		unsigned int tx_len, unsigned char *rx_buffer,
119 		unsigned int rx_len,
120 		unsigned int *actual_rx)
121 {
122 	unsigned int rx_cnt = 0;
123 	int ret = 0;
124 	unsigned int BPW = 4;
125 	bool eop_found = false;
126 	unsigned char *eop;
127 	unsigned char *ptr;
128 	unsigned char *rxbuf = rx_buffer;
129 	int add_byte = 0;
130 	unsigned long ticks;
131 	unsigned long timeout;
132 
133 	/* send command */
134 	ret = spi_write(dev->dev, dev->chipselect, tx_len, tx_buffer);
135 	if (ret)
136 		return -EBUSY;
137 
138 	timeout = rte_get_timer_cycles() +
139 				msecs_to_timer_cycles(2000);
140 
141 	/* read out data */
142 	while (rx_cnt < rx_len) {
143 		ret = spi_read(dev->dev, dev->chipselect, BPW, rxbuf);
144 		if (ret)
145 			return -EBUSY;
146 
147 		/* skip all of invalid data */
148 		if (!eop_found && all_idle_data(rxbuf)) {
149 			ticks = rte_get_timer_cycles();
150 			if (!time_after(ticks, timeout)) {
151 				continue;
152 			} else {
153 				dev_err(dev, "read spi data timeout\n");
154 				return -ETIMEDOUT;
155 			}
156 		}
157 
158 		rx_cnt += BPW;
159 		if (!eop_found) {
160 			/* EOP is found, we read 2 more bytes and exit. */
161 			eop = find_eop(rxbuf, BPW);
162 			if (eop) {
163 				if ((BPW + rxbuf - eop) > 2) {
164 					/*
165 					 * check if the last 2 bytes are already
166 					 * received in current word.
167 					 */
168 					break;
169 				} else if ((BPW + rxbuf - eop) == 2) {
170 					/*
171 					 * skip if last byte is not SPI_BYTE_ESC
172 					 * or SPI_PACKET_ESC. this is the valid
173 					 * end of a response too.
174 					 */
175 					ptr = eop + 1;
176 
177 					if (*ptr != SPI_BYTE_ESC &&
178 							*ptr != SPI_PACKET_ESC)
179 						break;
180 
181 					add_byte = 1;
182 				} else {
183 					add_byte = 2;
184 				}
185 
186 				rx_len = min(rx_len,
187 						IFPGA_ALIGN(rx_cnt +
188 							add_byte, BPW));
189 				eop_found = true;
190 			}
191 		}
192 		rxbuf += BPW;
193 	}
194 
195 	*actual_rx = rx_cnt;
196 	print_buffer("found valid data:", rx_buffer, rx_cnt);
197 
198 	return ret;
199 }
200 
201 static int byte_to_core_convert(struct spi_transaction_dev *dev,
202 		unsigned int send_len, unsigned char *send_data,
203 		unsigned int resp_len, unsigned char *resp_data,
204 		unsigned int *valid_resp_len)
205 {
206 	unsigned int i;
207 	int ret = 0;
208 	unsigned char *send_packet = dev->buffer->bytes_send;
209 	unsigned char *resp_packet = dev->buffer->bytes_resp;
210 	unsigned char *p;
211 	unsigned char current_byte;
212 	unsigned int tx_len = 0;
213 	unsigned int resp_max_len = 2 * resp_len;
214 	unsigned int actual_rx;
215 
216 	print_buffer("before bytes:", send_data, send_len);
217 
218 	p = send_packet;
219 
220 	for (i = 0; i < send_len; i++) {
221 		current_byte = send_data[i];
222 		switch (current_byte) {
223 		case SPI_BYTE_IDLE:
224 			*p++ = SPI_BYTE_ESC;
225 			*p++ = xor_20(current_byte);
226 			break;
227 		case SPI_BYTE_ESC:
228 			*p++ = SPI_BYTE_ESC;
229 			*p++ = xor_20(current_byte);
230 			break;
231 		default:
232 			*p++ = current_byte;
233 			break;
234 		}
235 	}
236 
237 	tx_len = p - send_packet;
238 
239 	print_buffer("before spi:", send_packet, tx_len);
240 
241 	phy_tx_pad(send_packet, tx_len, &tx_len);
242 	print_buffer("after pad:", send_packet, tx_len);
243 
244 	reorder_phy_data(32, send_packet, tx_len);
245 
246 	print_buffer("after order to spi:", send_packet, tx_len);
247 
248 	ret = do_spi_txrx(dev, send_packet, tx_len, resp_packet,
249 			resp_max_len, &actual_rx);
250 	if (ret)
251 		return ret;
252 
253 	/* analyze response packet */
254 	i = 0;
255 	p = resp_data;
256 	while (i < actual_rx) {
257 		current_byte = resp_packet[i];
258 		switch (current_byte) {
259 		case SPI_BYTE_IDLE:
260 			i++;
261 			break;
262 		case SPI_BYTE_ESC:
263 			i++;
264 			current_byte = resp_packet[i];
265 			*p++ = xor_20(current_byte);
266 			i++;
267 			break;
268 		default:
269 			*p++ = current_byte;
270 			i++;
271 			break;
272 		}
273 	}
274 
275 	/* receive "4a" means the SPI is idle, not valid data */
276 	*valid_resp_len = p - resp_data;
277 	if (*valid_resp_len == 0) {
278 		dev_err(NULL, "error: repond package without valid data\n");
279 		return -EINVAL;
280 	}
281 
282 	return 0;
283 }
284 
285 static int packet_to_byte_conver(struct spi_transaction_dev *dev,
286 		unsigned int send_len, unsigned char *send_buf,
287 		unsigned int resp_len, unsigned char *resp_buf,
288 		unsigned int *valid)
289 {
290 	int ret = 0;
291 	unsigned int i;
292 	unsigned char current_byte;
293 	unsigned int resp_max_len;
294 	unsigned char *send_packet = dev->buffer->packet_send;
295 	unsigned char *resp_packet = dev->buffer->packet_resp;
296 	unsigned char *p;
297 	unsigned int valid_resp_len = 0;
298 
299 	print_buffer("before packet:", send_buf, send_len);
300 
301 	resp_max_len = 2 * resp_len + 4;
302 
303 	p = send_packet;
304 
305 	/* SOP header */
306 	*p++ = SPI_PACKET_SOP;
307 
308 	*p++ = SPI_PACKET_CHANNEL;
309 	*p++ = 0;
310 
311 	/* append the data into a packet */
312 	for (i = 0; i < send_len; i++) {
313 		current_byte = send_buf[i];
314 
315 		/* EOP for last byte */
316 		if (i == send_len - 1)
317 			*p++ = SPI_PACKET_EOP;
318 
319 		switch (current_byte) {
320 		case SPI_PACKET_SOP:
321 		case SPI_PACKET_EOP:
322 		case SPI_PACKET_CHANNEL:
323 		case SPI_PACKET_ESC:
324 			*p++ = SPI_PACKET_ESC;
325 			*p++ = xor_20(current_byte);
326 			break;
327 		default:
328 			*p++ = current_byte;
329 		}
330 	}
331 
332 	ret = byte_to_core_convert(dev, p - send_packet,
333 			send_packet, resp_max_len, resp_packet,
334 			&valid_resp_len);
335 	if (ret)
336 		return -EBUSY;
337 
338 	print_buffer("after byte conver:", resp_packet, valid_resp_len);
339 
340 	/* analyze the response packet */
341 	p = resp_buf;
342 
343 	/* look for SOP */
344 	for (i = 0; i < valid_resp_len; i++) {
345 		if (resp_packet[i] == SPI_PACKET_SOP)
346 			break;
347 	}
348 
349 	if (i == valid_resp_len) {
350 		dev_err(NULL, "error on analyze response packet 0x%x\n",
351 				resp_packet[i]);
352 		return -EINVAL;
353 	}
354 
355 	i++;
356 
357 	/* continue parsing data after SOP */
358 	while (i < valid_resp_len) {
359 		current_byte = resp_packet[i];
360 
361 		switch (current_byte) {
362 		case SPI_PACKET_SOP:
363 			dev_err(dev, "error on get SOP after SOP\n");
364 			return -EINVAL;
365 		case SPI_PACKET_CHANNEL:
366 			i += 2;
367 			break;
368 		case SPI_PACKET_ESC:
369 			i++;
370 			current_byte = resp_packet[i];
371 			*p++ = xor_20(current_byte);
372 			i++;
373 			break;
374 		case SPI_PACKET_EOP:
375 			i++;
376 			current_byte = resp_packet[i];
377 			switch (current_byte) {
378 			case SPI_PACKET_ESC:
379 				i++;
380 				current_byte = resp_packet[i];
381 				*p++ = xor_20(current_byte);
382 				break;
383 			case SPI_PACKET_CHANNEL:
384 			case SPI_PACKET_SOP:
385 			case SPI_PACKET_EOP:
386 				dev_err(dev, "error get SOP/EOP after EOP\n");
387 				return -EINVAL;
388 			default:
389 				*p++ = current_byte;
390 				break;
391 			}
392 			goto done;
393 
394 		default:
395 			*p++ = current_byte;
396 			i++;
397 		}
398 	}
399 
400 done:
401 	*valid = p - resp_buf;
402 
403 	print_buffer("after packet:", resp_buf, *valid);
404 
405 	return ret;
406 }
407 
408 static int do_transaction(struct spi_transaction_dev *dev, unsigned int addr,
409 		unsigned int size, unsigned char *data,
410 		unsigned int trans_type)
411 {
412 
413 	struct spi_tran_header header;
414 	unsigned char *transaction = dev->buffer->tran_send;
415 	unsigned char *response = dev->buffer->tran_resp;
416 	unsigned char *p;
417 	int ret = 0;
418 	unsigned int i;
419 	unsigned int valid_len = 0;
420 
421 	/* make transacation header */
422 	INIT_SPI_TRAN_HEADER(trans_type, size, addr);
423 
424 	/* fill the header */
425 	p = transaction;
426 	opae_memcpy(p, &header, sizeof(struct spi_tran_header));
427 	p = p + sizeof(struct spi_tran_header);
428 
429 	switch (trans_type) {
430 	case SPI_TRAN_SEQ_WRITE:
431 	case SPI_TRAN_NON_SEQ_WRITE:
432 		for (i = 0; i < size; i++)
433 			*p++ = *data++;
434 
435 		ret = packet_to_byte_conver(dev, size + HEADER_LEN,
436 				transaction, RESPONSE_LEN, response,
437 				&valid_len);
438 		if (ret)
439 			return -EBUSY;
440 
441 		/* check the result */
442 		if (size != ((unsigned int)(response[2] & 0xff) << 8 |
443 			(unsigned int)(response[3] & 0xff)))
444 			ret = -EBUSY;
445 
446 		break;
447 	case SPI_TRAN_SEQ_READ:
448 	case SPI_TRAN_NON_SEQ_READ:
449 		ret = packet_to_byte_conver(dev, HEADER_LEN,
450 				transaction, size, response,
451 				&valid_len);
452 		if (ret || valid_len != size)
453 			return -EBUSY;
454 
455 		for (i = 0; i < size; i++)
456 			*data++ = *response++;
457 
458 		ret = 0;
459 		break;
460 	}
461 
462 	return ret;
463 }
464 
465 int spi_transaction_read(struct spi_transaction_dev *dev, unsigned int addr,
466 		unsigned int size, unsigned char *data)
467 {
468 	int ret;
469 
470 	pthread_mutex_lock(dev->mutex);
471 	ret = do_transaction(dev, addr, size, data,
472 			(size > SPI_REG_BYTES) ?
473 			SPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);
474 	pthread_mutex_unlock(dev->mutex);
475 
476 	return ret;
477 }
478 
479 int spi_transaction_write(struct spi_transaction_dev *dev, unsigned int addr,
480 		unsigned int size, unsigned char *data)
481 {
482 	int ret;
483 
484 	pthread_mutex_lock(dev->mutex);
485 	ret = do_transaction(dev, addr, size, data,
486 			(size > SPI_REG_BYTES) ?
487 			SPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);
488 	pthread_mutex_unlock(dev->mutex);
489 
490 	return ret;
491 }
492 
493 struct spi_transaction_dev *spi_transaction_init(struct altera_spi_device *dev,
494 		int chipselect)
495 {
496 	struct spi_transaction_dev *spi_tran_dev;
497 
498 	spi_tran_dev = opae_malloc(sizeof(struct spi_transaction_dev));
499 	if (!spi_tran_dev)
500 		return NULL;
501 
502 	spi_tran_dev->dev = dev;
503 	spi_tran_dev->chipselect = chipselect;
504 
505 	spi_tran_dev->buffer = opae_malloc(sizeof(struct spi_tran_buffer));
506 	if (!spi_tran_dev->buffer)
507 		goto err;
508 
509 	pthread_mutex_init(&spi_tran_dev->lock, NULL);
510 	if (dev->mutex) {
511 		dev_info(NULL, "use multi-process mutex in spi\n");
512 		spi_tran_dev->mutex = dev->mutex;
513 	} else {
514 		dev_info(NULL, "use multi-thread mutex in spi\n");
515 		spi_tran_dev->mutex = &spi_tran_dev->lock;
516 	}
517 
518 	return spi_tran_dev;
519 
520 err:
521 	opae_free(spi_tran_dev);
522 	return NULL;
523 }
524 
525 void spi_transaction_remove(struct spi_transaction_dev *dev)
526 {
527 	if (dev && dev->buffer)
528 		opae_free(dev->buffer);
529 	if (dev) {
530 		pthread_mutex_destroy(&dev->lock);
531 		opae_free(dev);
532 	}
533 }
534