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 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 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 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