1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
3 * Copyright (c) 2018 Microsemi Corporation
10 #define QS_XTR_FLUSH_FLUSH GENMASK(1, 0)
11 #define QS_INJ_CTRL_GAP_SIZE(x) ((x) << 21)
12 #define QS_INJ_CTRL_EOF BIT(19)
13 #define QS_INJ_CTRL_SOF BIT(18)
14 #define QS_INJ_CTRL_VLD_BYTES(x) ((x) << 16)
16 #define XTR_EOF_0 ntohl(0x80000000u)
17 #define XTR_EOF_1 ntohl(0x80000001u)
18 #define XTR_EOF_2 ntohl(0x80000002u)
19 #define XTR_EOF_3 ntohl(0x80000003u)
20 #define XTR_PRUNED ntohl(0x80000004u)
21 #define XTR_ABORT ntohl(0x80000005u)
22 #define XTR_ESCAPE ntohl(0x80000006u)
23 #define XTR_NOT_READY ntohl(0x80000007u)
25 #define BUF_CELL_SZ 60
26 #define XTR_VALID_BYTES(x) (4 - ((x) & 3))
28 int mscc_send(void __iomem *regs, const unsigned long *mscc_qs_offset,
29 u32 *ifh, size_t ifh_len, u32 *buff, size_t buff_len)
31 int i, count = (buff_len + 3) / 4, last = buff_len % 4;
33 writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF,
34 regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
36 for (i = 0; i < ifh_len; i++)
37 writel(ifh[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
39 for (i = 0; i < count; i++)
40 writel(buff[i], regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
43 while (i < (BUF_CELL_SZ / 4)) {
44 writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
48 /* Indicate EOF and valid bytes in last word */
49 writel(QS_INJ_CTRL_GAP_SIZE(1) |
50 QS_INJ_CTRL_VLD_BYTES(buff_len < BUF_CELL_SZ ? 0 : last) |
51 QS_INJ_CTRL_EOF, regs + mscc_qs_offset[MSCC_QS_INJ_CTRL]);
54 writel(0, regs + mscc_qs_offset[MSCC_QS_INJ_WR]);
59 int mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset,
60 u32 *rxbuf, size_t ifh_len, bool byte_swap)
62 u8 grp = 0; /* Recv everything on CPU group 0 */
64 bool eof_flag = false, pruned_flag = false, abort_flag = false;
66 if (!(readl(regs + mscc_qs_offset[MSCC_QS_XTR_DATA_PRESENT]) &
71 for (i = 0; i < ifh_len; i++)
72 readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
75 u32 val = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
83 debug("%d NOT_READY...?\n", byte_cnt);
86 *rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
95 byte_cnt += XTR_VALID_BYTES(val);
96 *rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
101 /* But get the last 4 bytes as well */
107 *rxbuf = readl(regs + mscc_qs_offset[MSCC_QS_XTR_RD]);
119 if (abort_flag || pruned_flag || !eof_flag) {
120 debug("Discarded frame: abort:%d pruned:%d eof:%d\n",
121 abort_flag, pruned_flag, eof_flag);
128 void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset)
130 /* All Queues flush */
131 setbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],
137 /* All Queues normal */
138 clrbits_le32(regs + mscc_qs_offset[MSCC_QS_XTR_FLUSH],