[U-Boot] [PATCH v2 3/8] net: mscc: Move ocelot_send and ocelot_recv in a different file.
Horatiu Vultur
horatiu.vultur at microchip.com
Wed Jan 30 12:29:36 UTC 2019
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 at microchip.com>
---
drivers/net/mscc_eswitch/Makefile | 2 +-
drivers/net/mscc_eswitch/mscc_xfer.c | 139 +++++++++++++++++++++++++++++++
drivers/net/mscc_eswitch/mscc_xfer.h | 20 +++++
drivers/net/mscc_eswitch/ocelot_switch.c | 130 ++++-------------------------
4 files changed, 175 insertions(+), 116 deletions(-)
create mode 100644 drivers/net/mscc_eswitch/mscc_xfer.c
create mode 100644 drivers/net/mscc_eswitch/mscc_xfer.h
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile
index 1ceb92a..20e8e4c 100644
--- a/drivers/net/mscc_eswitch/Makefile
+++ b/drivers/net/mscc_eswitch/Makefile
@@ -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
index 0000000..f412901
--- /dev/null
+++ b/drivers/net/mscc_eswitch/mscc_xfer.c
@@ -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
index 0000000..c880a4e
--- /dev/null
+++ b/drivers/net/mscc_eswitch/mscc_xfer.h
@@ -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);
diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c
index a4361e8..c33ecd4 100644
--- a/drivers/net/mscc_eswitch/ocelot_switch.c
+++ b/drivers/net/mscc_eswitch/ocelot_switch.c
@@ -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
@@ -87,37 +88,16 @@
#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];
--
2.7.4
More information about the U-Boot
mailing list