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