mscc_mac_table.c 2.2 KB

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