diff options
author | Tom Rini <trini@konsulko.com> | 2019-02-02 10:11:12 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-02-02 10:11:12 -0500 |
commit | 544d5e98f3657e4ac1966be8971586aa42dad8c4 (patch) | |
tree | 742ce50ddb331b05ea9a89db0faf1be4b35db8b5 /drivers/net/mscc_eswitch/mscc_mac_table.c | |
parent | 1b0769f2ed17ffc1cf9b32ad057bc8b160cbcbae (diff) | |
parent | 364e407f3cafd485db4d090430e3861c99858d42 (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.c | 74 |
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); +} |