xref: /dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
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 }
439