xref: /openbmc/u-boot/drivers/net/mscc_eswitch/mscc_xfer.c (revision 544d5e98f3657e4ac1966be8971586aa42dad8c4)
1*36d04f52SHoratiu Vultur // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2*36d04f52SHoratiu Vultur /*
3*36d04f52SHoratiu Vultur  * Copyright (c) 2018 Microsemi Corporation
4*36d04f52SHoratiu Vultur  */
5*36d04f52SHoratiu Vultur 
6*36d04f52SHoratiu Vultur #include <linux/io.h>
7*36d04f52SHoratiu Vultur #include "mscc_xfer.h"
8*36d04f52SHoratiu Vultur 
9*36d04f52SHoratiu Vultur #define QS_XTR_FLUSH_FLUSH		GENMASK(1, 0)
10*36d04f52SHoratiu Vultur #define QS_INJ_CTRL_GAP_SIZE(x)		((x) << 21)
11*36d04f52SHoratiu Vultur #define QS_INJ_CTRL_EOF			BIT(19)
12*36d04f52SHoratiu Vultur #define QS_INJ_CTRL_SOF			BIT(18)
13*36d04f52SHoratiu Vultur #define QS_INJ_CTRL_VLD_BYTES(x)	((x) << 16)
14*36d04f52SHoratiu Vultur 
15*36d04f52SHoratiu Vultur #define XTR_EOF_0     ntohl(0x80000000u)
16*36d04f52SHoratiu Vultur #define XTR_EOF_1     ntohl(0x80000001u)
17*36d04f52SHoratiu Vultur #define XTR_EOF_2     ntohl(0x80000002u)
18*36d04f52SHoratiu Vultur #define XTR_EOF_3     ntohl(0x80000003u)
19*36d04f52SHoratiu Vultur #define XTR_PRUNED    ntohl(0x80000004u)
20*36d04f52SHoratiu Vultur #define XTR_ABORT     ntohl(0x80000005u)
21*36d04f52SHoratiu Vultur #define XTR_ESCAPE    ntohl(0x80000006u)
22*36d04f52SHoratiu Vultur #define XTR_NOT_READY ntohl(0x80000007u)
23*36d04f52SHoratiu Vultur 
24*36d04f52SHoratiu Vultur #define BUF_CELL_SZ		60
25*36d04f52SHoratiu Vultur #define XTR_VALID_BYTES(x)	(4 - ((x) & 3))
26*36d04f52SHoratiu Vultur 
mscc_send(void __iomem * regs,const unsigned long * mscc_qs_offset,u32 * ifh,size_t ifh_len,u32 * buff,size_t buff_len)27*36d04f52SHoratiu Vultur int mscc_send(void __iomem *regs, const unsigned long *mscc_qs_offset,
28*36d04f52SHoratiu Vultur 	      u32 *ifh, size_t ifh_len, u32 *buff, size_t buff_len)
29*36d04f52SHoratiu Vultur {
30*36d04f52SHoratiu Vultur 	int i, count = (buff_len + 3) / 4, last = buff_len % 4;
31*36d04f52SHoratiu Vultur 
32*36d04f52SHoratiu Vultur 	writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF,
33*36d04f52SHoratiu Vultur 	       regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
34*36d04f52SHoratiu Vultur 
35*36d04f52SHoratiu Vultur 	for (i = 0; i < ifh_len; i++)
36*36d04f52SHoratiu Vultur 		writel(ifh[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
37*36d04f52SHoratiu Vultur 
38*36d04f52SHoratiu Vultur 	for (i = 0; i < count; i++)
39*36d04f52SHoratiu Vultur 		writel(buff[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
40*36d04f52SHoratiu Vultur 
41*36d04f52SHoratiu Vultur 	/* Add padding */
42*36d04f52SHoratiu Vultur 	while (i < (BUF_CELL_SZ / 4)) {
43*36d04f52SHoratiu Vultur 		writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
44*36d04f52SHoratiu Vultur 		i++;
45*36d04f52SHoratiu Vultur 	}
46*36d04f52SHoratiu Vultur 
47*36d04f52SHoratiu Vultur 	/* Indicate EOF and valid bytes in last word */
48*36d04f52SHoratiu Vultur 	writel(QS_INJ_CTRL_GAP_SIZE(1) |
49*36d04f52SHoratiu Vultur 	       QS_INJ_CTRL_VLD_BYTES(buff_len < BUF_CELL_SZ ? 0 : last) |
50*36d04f52SHoratiu Vultur 	       QS_INJ_CTRL_EOF, regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
51*36d04f52SHoratiu Vultur 
52*36d04f52SHoratiu Vultur 	/* Add dummy CRC */
53*36d04f52SHoratiu Vultur 	writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
54*36d04f52SHoratiu Vultur 
55*36d04f52SHoratiu Vultur 	return 0;
56*36d04f52SHoratiu Vultur }
57*36d04f52SHoratiu Vultur 
mscc_recv(void __iomem * regs,const unsigned long * mscc_qs_offset,u32 * rxbuf,size_t ifh_len,bool byte_swap)58*36d04f52SHoratiu Vultur int mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset,
59*36d04f52SHoratiu Vultur 	      u32 *rxbuf, size_t ifh_len, bool byte_swap)
60*36d04f52SHoratiu Vultur {
61*36d04f52SHoratiu Vultur 	u8 grp = 0; /* Recv everything on CPU group 0 */
62*36d04f52SHoratiu Vultur 	int i, byte_cnt = 0;
63*36d04f52SHoratiu Vultur 	bool eof_flag = false, pruned_flag = false, abort_flag = false;
64*36d04f52SHoratiu Vultur 
65*36d04f52SHoratiu Vultur 	if (!(readl(regs + mscc_qs_offset[MSCC_QS_XTR_DATA_PRESENT]) &
66*36d04f52SHoratiu Vultur 	      BIT(grp)))
67*36d04f52SHoratiu Vultur 		return -EAGAIN;
68*36d04f52SHoratiu Vultur 
69*36d04f52SHoratiu Vultur 	/* skip IFH */
70*36d04f52SHoratiu Vultur 	for (i = 0; i < ifh_len; i++)
71*36d04f52SHoratiu Vultur 		readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
72*36d04f52SHoratiu Vultur 
73*36d04f52SHoratiu Vultur 	while (!eof_flag) {
74*36d04f52SHoratiu Vultur 		u32 val = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
75*36d04f52SHoratiu Vultur 		u32 cmp = val;
76*36d04f52SHoratiu Vultur 
77*36d04f52SHoratiu Vultur 		if (byte_swap)
78*36d04f52SHoratiu Vultur 			cmp = ntohl(val);
79*36d04f52SHoratiu Vultur 
80*36d04f52SHoratiu Vultur 		switch (cmp) {
81*36d04f52SHoratiu Vultur 		case XTR_NOT_READY:
82*36d04f52SHoratiu Vultur 			debug("%d NOT_READY...?\n", byte_cnt);
83*36d04f52SHoratiu Vultur 			break;
84*36d04f52SHoratiu Vultur 		case XTR_ABORT:
85*36d04f52SHoratiu Vultur 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
86*36d04f52SHoratiu Vultur 			abort_flag = true;
87*36d04f52SHoratiu Vultur 			eof_flag = true;
88*36d04f52SHoratiu Vultur 			debug("XTR_ABORT\n");
89*36d04f52SHoratiu Vultur 			break;
90*36d04f52SHoratiu Vultur 		case XTR_EOF_0:
91*36d04f52SHoratiu Vultur 		case XTR_EOF_1:
92*36d04f52SHoratiu Vultur 		case XTR_EOF_2:
93*36d04f52SHoratiu Vultur 		case XTR_EOF_3:
94*36d04f52SHoratiu Vultur 			byte_cnt += XTR_VALID_BYTES(val);
95*36d04f52SHoratiu Vultur 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
96*36d04f52SHoratiu Vultur 			eof_flag = true;
97*36d04f52SHoratiu Vultur 			debug("EOF\n");
98*36d04f52SHoratiu Vultur 			break;
99*36d04f52SHoratiu Vultur 		case XTR_PRUNED:
100*36d04f52SHoratiu Vultur 			/* But get the last 4 bytes as well */
101*36d04f52SHoratiu Vultur 			eof_flag = true;
102*36d04f52SHoratiu Vultur 			pruned_flag = true;
103*36d04f52SHoratiu Vultur 			debug("PRUNED\n");
104*36d04f52SHoratiu Vultur 			/* fallthrough */
105*36d04f52SHoratiu Vultur 		case XTR_ESCAPE:
106*36d04f52SHoratiu Vultur 			*rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
107*36d04f52SHoratiu Vultur 			byte_cnt += 4;
108*36d04f52SHoratiu Vultur 			rxbuf++;
109*36d04f52SHoratiu Vultur 			debug("ESCAPED\n");
110*36d04f52SHoratiu Vultur 			break;
111*36d04f52SHoratiu Vultur 		default:
112*36d04f52SHoratiu Vultur 			*rxbuf = val;
113*36d04f52SHoratiu Vultur 			byte_cnt += 4;
114*36d04f52SHoratiu Vultur 			rxbuf++;
115*36d04f52SHoratiu Vultur 		}
116*36d04f52SHoratiu Vultur 	}
117*36d04f52SHoratiu Vultur 
118*36d04f52SHoratiu Vultur 	if (abort_flag || pruned_flag || !eof_flag) {
119*36d04f52SHoratiu Vultur 		debug("Discarded frame: abort:%d pruned:%d eof:%d\n",
120*36d04f52SHoratiu Vultur 		      abort_flag, pruned_flag, eof_flag);
121*36d04f52SHoratiu Vultur 		return -EAGAIN;
122*36d04f52SHoratiu Vultur 	}
123*36d04f52SHoratiu Vultur 
124*36d04f52SHoratiu Vultur 	return byte_cnt;
125*36d04f52SHoratiu Vultur }
126*36d04f52SHoratiu Vultur 
mscc_flush(void __iomem * regs,const unsigned long * mscc_qs_offset)127*36d04f52SHoratiu Vultur void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset)
128*36d04f52SHoratiu Vultur {
129*36d04f52SHoratiu Vultur 	/* All Queues flush */
130*36d04f52SHoratiu Vultur 	setbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],
131*36d04f52SHoratiu Vultur 		     QS_XTR_FLUSH_FLUSH);
132*36d04f52SHoratiu Vultur 
133*36d04f52SHoratiu Vultur 	/* Allow to drain */
134*36d04f52SHoratiu Vultur 	mdelay(1);
135*36d04f52SHoratiu Vultur 
136*36d04f52SHoratiu Vultur 	/* All Queues normal */
137*36d04f52SHoratiu Vultur 	clrbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],
138*36d04f52SHoratiu Vultur 		     QS_XTR_FLUSH_FLUSH);
139*36d04f52SHoratiu Vultur }
140