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