mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 02:15:45 +01:00 
			
		
		
		
	Move this uncommon header out of the common header. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			143 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 | |
| /*
 | |
|  * Copyright (c) 2018 Microsemi Corporation
 | |
|  */
 | |
| 
 | |
| #include <log.h>
 | |
| #include <linux/bitops.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/io.h>
 | |
| #include "mscc_xfer.h"
 | |
| 
 | |
| #define QS_XTR_FLUSH_FLUSH		GENMASK(1, 0)
 | |
| #define QS_INJ_CTRL_GAP_SIZE(x)		((x) << 21)
 | |
| #define QS_INJ_CTRL_EOF			BIT(19)
 | |
| #define QS_INJ_CTRL_SOF			BIT(18)
 | |
| #define QS_INJ_CTRL_VLD_BYTES(x)	((x) << 16)
 | |
| 
 | |
| #define XTR_EOF_0     ntohl(0x80000000u)
 | |
| #define XTR_EOF_1     ntohl(0x80000001u)
 | |
| #define XTR_EOF_2     ntohl(0x80000002u)
 | |
| #define XTR_EOF_3     ntohl(0x80000003u)
 | |
| #define XTR_PRUNED    ntohl(0x80000004u)
 | |
| #define XTR_ABORT     ntohl(0x80000005u)
 | |
| #define XTR_ESCAPE    ntohl(0x80000006u)
 | |
| #define XTR_NOT_READY ntohl(0x80000007u)
 | |
| 
 | |
| #define BUF_CELL_SZ		60
 | |
| #define XTR_VALID_BYTES(x)	(4 - ((x) & 3))
 | |
| 
 | |
| int mscc_send(void __iomem *regs, const unsigned long *mscc_qs_offset,
 | |
| 	      u32 *ifh, size_t ifh_len, u32 *buff, size_t buff_len)
 | |
| {
 | |
| 	int i, count = (buff_len + 3) / 4, last = buff_len % 4;
 | |
| 
 | |
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF,
 | |
| 	       regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
 | |
| 
 | |
| 	for (i = 0; i < ifh_len; i++)
 | |
| 		writel(ifh[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
 | |
| 
 | |
| 	for (i = 0; i < count; i++)
 | |
| 		writel(buff[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
 | |
| 
 | |
| 	/* Add padding */
 | |
| 	while (i < (BUF_CELL_SZ / 4)) {
 | |
| 		writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
 | |
| 		i++;
 | |
| 	}
 | |
| 
 | |
| 	/* Indicate EOF and valid bytes in last word */
 | |
| 	writel(QS_INJ_CTRL_GAP_SIZE(1) |
 | |
| 	       QS_INJ_CTRL_VLD_BYTES(buff_len < BUF_CELL_SZ ? 0 : last) |
 | |
| 	       QS_INJ_CTRL_EOF, regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
 | |
| 
 | |
| 	/* Add dummy CRC */
 | |
| 	writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset,
 | |
| 	      u32 *rxbuf, size_t ifh_len, bool byte_swap)
 | |
| {
 | |
| 	u8 grp = 0; /* Recv everything on CPU group 0 */
 | |
| 	int i, byte_cnt = 0;
 | |
| 	bool eof_flag = false, pruned_flag = false, abort_flag = false;
 | |
| 
 | |
| 	if (!(readl(regs + mscc_qs_offset[MSCC_QS_XTR_DATA_PRESENT]) &
 | |
| 	      BIT(grp)))
 | |
| 		return -EAGAIN;
 | |
| 
 | |
| 	/* skip IFH */
 | |
| 	for (i = 0; i < ifh_len; i++)
 | |
| 		readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
 | |
| 
 | |
| 	while (!eof_flag) {
 | |
| 		u32 val = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
 | |
| 		u32 cmp = val;
 | |
| 
 | |
| 		if (byte_swap)
 | |
| 			cmp = ntohl(val);
 | |
| 
 | |
| 		switch (cmp) {
 | |
| 		case XTR_NOT_READY:
 | |
| 			debug("%d NOT_READY...?\n", byte_cnt);
 | |
| 			break;
 | |
| 		case XTR_ABORT:
 | |
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
 | |
| 			abort_flag = true;
 | |
| 			eof_flag = true;
 | |
| 			debug("XTR_ABORT\n");
 | |
| 			break;
 | |
| 		case XTR_EOF_0:
 | |
| 		case XTR_EOF_1:
 | |
| 		case XTR_EOF_2:
 | |
| 		case XTR_EOF_3:
 | |
| 			byte_cnt += XTR_VALID_BYTES(val);
 | |
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
 | |
| 			eof_flag = true;
 | |
| 			debug("EOF\n");
 | |
| 			break;
 | |
| 		case XTR_PRUNED:
 | |
| 			/* But get the last 4 bytes as well */
 | |
| 			eof_flag = true;
 | |
| 			pruned_flag = true;
 | |
| 			debug("PRUNED\n");
 | |
| 			/* fallthrough */
 | |
| 		case XTR_ESCAPE:
 | |
| 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
 | |
| 			byte_cnt += 4;
 | |
| 			rxbuf++;
 | |
| 			debug("ESCAPED\n");
 | |
| 			break;
 | |
| 		default:
 | |
| 			*rxbuf = val;
 | |
| 			byte_cnt += 4;
 | |
| 			rxbuf++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (abort_flag || pruned_flag || !eof_flag) {
 | |
| 		debug("Discarded frame: abort:%d pruned:%d eof:%d\n",
 | |
| 		      abort_flag, pruned_flag, eof_flag);
 | |
| 		return -EAGAIN;
 | |
| 	}
 | |
| 
 | |
| 	return byte_cnt;
 | |
| }
 | |
| 
 | |
| void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset)
 | |
| {
 | |
| 	/* All Queues flush */
 | |
| 	setbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],
 | |
| 		     QS_XTR_FLUSH_FLUSH);
 | |
| 
 | |
| 	/* Allow to drain */
 | |
| 	mdelay(1);
 | |
| 
 | |
| 	/* All Queues normal */
 | |
| 	clrbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],
 | |
| 		     QS_XTR_FLUSH_FLUSH);
 | |
| }
 |