1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2 /* 3 * Copyright (c) 2018 Microsemi Corporation 4 */ 5 6 #include <linux/io.h> 7 #include "mscc_mac_table.h" 8 9 #define ANA_TABLES_MACACCESS_VALID BIT(11) 10 #define ANA_TABLES_MACACCESS_ENTRYTYPE(x) ((x) << 9) 11 #define ANA_TABLES_MACACCESS_DEST_IDX(x) ((x) << 3) 12 #define ANA_TABLES_MACACCESS_MAC_TABLE_CMD(x) (x) 13 #define ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M GENMASK(2, 0) 14 #define MACACCESS_CMD_IDLE 0 15 #define MACACCESS_CMD_LEARN 1 16 17 /* MAC table entry types. 18 * ENTRYTYPE_NORMAL is subject to aging. 19 * ENTRYTYPE_LOCKED is not subject to aging. 20 */ 21 enum macaccess_entry_type { 22 ENTRYTYPE_NORMAL = 0, 23 ENTRYTYPE_LOCKED, 24 }; 25 26 static int vlan_wait_for_completion(void __iomem *regs, 27 const unsigned long *mscc_mac_table_offset) 28 { 29 unsigned int val, timeout = 10; 30 31 /* Wait for the issued mac table command to be completed, or timeout. 32 * When the command read from ANA_TABLES_MACACCESS is 33 * MACACCESS_CMD_IDLE, the issued command completed successfully. 34 */ 35 do { 36 val = readl(regs + 37 mscc_mac_table_offset[MSCC_ANA_TABLES_MACACCESS]); 38 val &= ANA_TABLES_MACACCESS_MAC_TABLE_CMD_M; 39 } while (val != MACACCESS_CMD_IDLE && timeout--); 40 41 if (!timeout) 42 return -ETIMEDOUT; 43 44 return 0; 45 } 46 47 int mscc_mac_table_add(void __iomem *regs, 48 const unsigned long *mscc_mac_table_offset, 49 const unsigned char mac[ETH_LEN], int pgid) 50 { 51 u32 macl = 0, mach = 0; 52 53 /* Set the MAC address to handle and the vlan associated in a format 54 * understood by the hardware. 55 */ 56 mach |= MAC_VID << 16; 57 mach |= ((u32)mac[0]) << 8; 58 mach |= ((u32)mac[1]) << 0; 59 macl |= ((u32)mac[2]) << 24; 60 macl |= ((u32)mac[3]) << 16; 61 macl |= ((u32)mac[4]) << 8; 62 macl |= ((u32)mac[5]) << 0; 63 64 writel(macl, regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACLDATA]); 65 writel(mach, regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACHDATA]); 66 67 writel(ANA_TABLES_MACACCESS_VALID | 68 ANA_TABLES_MACACCESS_DEST_IDX(pgid) | 69 ANA_TABLES_MACACCESS_ENTRYTYPE(ENTRYTYPE_LOCKED) | 70 ANA_TABLES_MACACCESS_MAC_TABLE_CMD(MACACCESS_CMD_LEARN), 71 regs + mscc_mac_table_offset[MSCC_ANA_TABLES_MACACCESS]); 72 73 return vlan_wait_for_completion(regs, mscc_mac_table_offset); 74 } 75