summaryrefslogtreecommitdiff
path: root/drivers/net/mscc_eswitch/mscc_mac_table.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-02-02 10:11:12 -0500
committerTom Rini <trini@konsulko.com>2019-02-02 10:11:12 -0500
commit544d5e98f3657e4ac1966be8971586aa42dad8c4 (patch)
tree742ce50ddb331b05ea9a89db0faf1be4b35db8b5 /drivers/net/mscc_eswitch/mscc_mac_table.c
parent1b0769f2ed17ffc1cf9b32ad057bc8b160cbcbae (diff)
parent364e407f3cafd485db4d090430e3861c99858d42 (diff)
Merge tag 'mips-pull-2019-02-01' of git://git.denx.de/u-boot-mips
- MIPS: mscc: jr2: small fixes - MIPS: mscc: luton: add ethernet and switch driver - MIPS: mt76xx: fix timer frequency
Diffstat (limited to 'drivers/net/mscc_eswitch/mscc_mac_table.c')
-rw-r--r--drivers/net/mscc_eswitch/mscc_mac_table.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/net/mscc_eswitch/mscc_mac_table.c b/drivers/net/mscc_eswitch/mscc_mac_table.c
new file mode 100644
index 00000000000..833e233aa5a
--- /dev/null
+++ b/drivers/net/mscc_eswitch/mscc_mac_table.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <linux/io.h>
+#include "mscc_mac_table.h"
+
+#define ANA_TABLES_MACACCESS_VALID BIT(11)
+#define ANA_TABLES_MACACCESS_ENTRYTYPE(x) ((x) << 9)
+#define ANA_TABLES_MACACCESS_DEST_IDX(x) ((x) << 3)
+#define ANA_TABLES_MACACCESS_MAC_TABLE_CMD(x) (x)
+#define ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M GENMASK(2, 0)
+#define MACACCESS_CMD_IDLE 0
+#define MACACCESS_CMD_LEARN 1
+
+/* MAC table entry types.
+ * ENTRYTYPE_NORMAL is subject to aging.
+ * ENTRYTYPE_LOCKED is not subject to aging.
+ */
+enum macaccess_entry_type {
+ ENTRYTYPE_NORMAL = 0,
+ ENTRYTYPE_LOCKED,
+};
+
+static int vlan_wait_for_completion(void __iomem *regs,
+ const unsigned long *mscc_mac_table_offset)
+{
+ unsigned int val, timeout = 10;
+
+ /* Wait for the issued mac table command to be completed, or timeout.
+ * When the command read from ANA_TABLES_MACACCESS is
+ * MACACCESS_CMD_IDLE, the issued command completed successfully.
+ */
+ do {
+ val = readl(regs +
+ mscc_mac_table_offset[MSCC_ANA_TABLES_MACACCESS]);
+ val &= ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M;
+ } while (val != MACACCESS_CMD_IDLE && timeout--);
+
+ if (!timeout)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int mscc_mac_table_add(void __iomem *regs,
+ const unsigned long *mscc_mac_table_offset,
+ const unsigned char mac[ETH_LEN], int pgid)
+{
+ u32 macl = 0, mach = 0;
+
+ /* Set the MAC address to handle and the vlan associated in a format
+ * understood by the hardware.
+ */
+ mach |= MAC_VID << 16;
+ mach |= ((u32)mac[0]) << 8;
+ mach |= ((u32)mac[1]) << 0;
+ macl |= ((u32)mac[2]) << 24;
+ macl |= ((u32)mac[3]) << 16;
+ macl |= ((u32)mac[4]) << 8;
+ macl |= ((u32)mac[5]) << 0;
+
+ writel(macl, regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACLDATA]);
+ writel(mach, regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACHDATA]);
+
+ writel(ANA_TABLES_MACACCESS_VALID |
+ ANA_TABLES_MACACCESS_DEST_IDX(pgid) |
+ ANA_TABLES_MACACCESS_ENTRYTYPE(ENTRYTYPE_LOCKED) |
+ ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN),
+ regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACACCESS]);
+
+ return vlan_wait_for_completion(regs, mscc_mac_table_offset);
+}