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