net: mscc: Move ocelot_send and ocelot_recv in a different file.
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Thu, 31 Jan 2019 14:30:35 +0000 (15:30 +0100)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Fri, 1 Feb 2019 13:13:36 +0000 (14:13 +0100)
This functions can be reused by other MSCC SoCs therefore,
make them more generic and move them in separate files.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
drivers/net/mscc_eswitch/Makefile
drivers/net/mscc_eswitch/mscc_xfer.c [new file with mode: 0644]
drivers/net/mscc_eswitch/mscc_xfer.h [new file with mode: 0644]
drivers/net/mscc_eswitch/ocelot_switch.c

index 1ceb92a32e7c7cd50893e9e6b013ee620ca37aeb..20e8e4c32a5aa41018937c768f4eb6af658440a9 100644 (file)
@@ -1,2 +1,2 @@
 
-obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o
+obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o
diff --git a/drivers/net/mscc_eswitch/mscc_xfer.c b/drivers/net/mscc_eswitch/mscc_xfer.c
new file mode 100644 (file)
index 0000000..f412901
--- /dev/null
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#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);
+}
diff --git a/drivers/net/mscc_eswitch/mscc_xfer.h b/drivers/net/mscc_eswitch/mscc_xfer.h
new file mode 100644 (file)
index 0000000..c880a4e
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+
+enum mscc_regs_qs {
+       MSCC_QS_XTR_RD,
+       MSCC_QS_XTR_FLUSH,
+       MSCC_QS_XTR_DATA_PRESENT,
+       MSCC_QS_INJ_WR,
+       MSCC_QS_INJ_CTRL,
+};
+
+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 mscc_recv(void __iomem *regs, const unsigned long *mscc_qs_offset,
+             u32 *rxbuf, size_t ifh_len, bool byte_swap);
+void mscc_flush(void __iomem *regs, const unsigned long *mscc_qs_offset);
index a4361e81556760d54d68eb01546e6da2f7b576d6..c33ecd44a0f402df0c6465fb3c14012120cd877a 100644 (file)
@@ -16,6 +16,7 @@
 #include <wait_bit.h>
 
 #include "mscc_miim.h"
+#include "mscc_xfer.h"
 
 #define PHY_CFG                                0x0
 #define PHY_CFG_ENA                            0xF
 #define QS_XTR_GRP_CFG_MODE(x)                 ((x) << 2)
 #define                QS_XTR_GRP_CFG_STATUS_WORD_POS  BIT(1)
 #define                QS_XTR_GRP_CFG_BYTE_SWAP        BIT(0)
-#define QS_XTR_RD(x)                   (0x8 + 4 * (x))
-#define QS_XTR_FLUSH                   0x18
-#define                QS_XTR_FLUSH_FLUSH              GENMASK(1, 0)
-#define QS_XTR_DATA_PRESENT            0x1c
 #define QS_INJ_GRP_CFG(x)              (0x24 + (x) * 4)
 #define                QS_INJ_GRP_CFG_MODE(x)          ((x) << 2)
 #define                QS_INJ_GRP_CFG_BYTE_SWAP        BIT(0)
-#define QS_INJ_WR(x)                   (0x2c + 4 * (x))
-#define QS_INJ_CTRL(x)                 (0x34 + 4 * (x))
-#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 IFH_INJ_BYPASS         BIT(31)
 #define        IFH_TAG_TYPE_C          0
-#define XTR_VALID_BYTES(x)     (4 - ((x) & 3))
 #define        MAC_VID                 1
 #define CPU_PORT               11
 #define INTERNAL_PORT_MSK      0xF
 #define IFH_LEN                        4
-#define OCELOT_BUF_CELL_SZ     60
 #define ETH_ALEN               6
 #define        PGID_BROADCAST          13
 #define        PGID_UNICAST            14
@@ -181,6 +161,14 @@ struct ocelot_private {
        void *tx_adj_buf;
 };
 
+static const unsigned long ocelot_regs_qs[] = {
+       [MSCC_QS_XTR_RD] = 0x8,
+       [MSCC_QS_XTR_FLUSH] = 0x18,
+       [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
+       [MSCC_QS_INJ_WR] = 0x2c,
+       [MSCC_QS_INJ_CTRL] = 0x34,
+};
+
 struct mscc_miim_dev miim[NUM_PHY];
 
 static int mscc_miim_reset(struct mii_dev *bus)
@@ -367,16 +355,6 @@ static int ocelot_switch_init(struct ocelot_private *priv)
        return 0;
 }
 
-static void ocelot_switch_flush(struct ocelot_private *priv)
-{
-       /* All Queues flush */
-       setbits_le32(priv->regs[QS] + QS_XTR_FLUSH, QS_XTR_FLUSH_FLUSH);
-       /* Allow to drain */
-       mdelay(1);
-       /* All Queues normal */
-       clrbits_le32(priv->regs[QS] + QS_XTR_FLUSH, QS_XTR_FLUSH_FLUSH);
-}
-
 static int ocelot_initialize(struct ocelot_private *priv)
 {
        int ret, i;
@@ -394,7 +372,7 @@ static int ocelot_initialize(struct ocelot_private *priv)
                writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
 
        /* Flush queues */
-       ocelot_switch_flush(priv);
+       mscc_flush(priv->regs[QS], ocelot_regs_qs);
 
        /* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */
        writel(SYS_FRM_AGING_ENA | (20000000 / 65),
@@ -503,13 +481,8 @@ static int ocelot_send(struct udevice *dev, void *packet, int length)
        struct ocelot_private *priv = dev_get_priv(dev);
        u32 ifh[IFH_LEN];
        int port = BIT(0);      /* use port 0 */
-       u8 grp = 0;             /* Send everything on CPU group 0 */
-       int i, count = (length + 3) / 4, last = length % 4;
        u32 *buf = packet;
 
-       writel(QS_INJ_CTRL_GAP_SIZE(1) | QS_INJ_CTRL_SOF,
-              priv->regs[QS] + QS_INJ_CTRL(grp));
-
        /*
         * Generate the IFH for frame injection
         *
@@ -526,91 +499,18 @@ static int ocelot_send(struct udevice *dev, void *packet, int length)
        ifh[2] = (0xff & port) << 24;
        ifh[3] = (IFH_TAG_TYPE_C << 16);
 
-       for (i = 0; i < IFH_LEN; i++)
-               writel(ifh[i], priv->regs[QS] + QS_INJ_WR(grp));
-
-       for (i = 0; i < count; i++)
-               writel(buf[i], priv->regs[QS] + QS_INJ_WR(grp));
-
-       /* Add padding */
-       while (i < (OCELOT_BUF_CELL_SZ / 4)) {
-               writel(0, priv->regs[QS] + QS_INJ_WR(grp));
-               i++;
-       }
-
-       /* Indicate EOF and valid bytes in last word */
-       writel(QS_INJ_CTRL_GAP_SIZE(1) |
-              QS_INJ_CTRL_VLD_BYTES(length < OCELOT_BUF_CELL_SZ ? 0 : last) |
-              QS_INJ_CTRL_EOF, priv->regs[QS] + QS_INJ_CTRL(grp));
-
-       /* Add dummy CRC */
-       writel(0, priv->regs[QS] + QS_INJ_WR(grp));
-
-       return 0;
+       return mscc_send(priv->regs[QS], ocelot_regs_qs,
+                        ifh, IFH_LEN, buf, length);
 }
 
 static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct ocelot_private *priv = dev_get_priv(dev);
-       u8 grp = 0;             /* Send everything on CPU group 0 */
        u32 *rxbuf = (u32 *)net_rx_packets[0];
-       int i, byte_cnt = 0;
-       bool eof_flag = false, pruned_flag = false, abort_flag = false;
-
-       if (!(readl(priv->regs[QS] + QS_XTR_DATA_PRESENT) & BIT(grp)))
-               return -EAGAIN;
-
-       /* skip IFH */
-       for (i = 0; i < IFH_LEN; i++)
-               readl(priv->regs[QS] + QS_XTR_RD(grp));
-
-       while (!eof_flag) {
-               u32 val = readl(priv->regs[QS] + QS_XTR_RD(grp));
-
-               switch (val) {
-               case XTR_NOT_READY:
-                       debug("%d NOT_READY...?\n", byte_cnt);
-                       break;
-               case XTR_ABORT:
-                       /* really nedeed?? not done in linux */
-                       *rxbuf = readl(priv->regs[QS] + QS_XTR_RD(grp));
-                       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(priv->regs[QS] + QS_XTR_RD(grp));
-                       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(priv->regs[QS] + QS_XTR_RD(grp));
-                       byte_cnt += 4;
-                       rxbuf++;
-                       debug("ESCAPED\n");
-                       break;
-               default:
-                       *rxbuf = val;
-                       byte_cnt += 4;
-                       rxbuf++;
-               }
-       }
+       int byte_cnt;
 
-       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;
-       }
+       byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN,
+                            false);
 
        *packetp = net_rx_packets[0];