blob: 833e233aa5a4377b771471ef57cd812c7e1cafdb [file] [log] [blame]
Horatiu Vultur85653272019-01-31 15:30:36 +01001// 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 */
21enum macaccess_entry_type {
22 ENTRYTYPE_NORMAL = 0,
23 ENTRYTYPE_LOCKED,
24};
25
26static 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
47int 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}