[rdkb][common][bsp][Refactor and sync kernel from openwrt]
[Description]
9627c280 [CRITICAL][kernel][mt7988][eth][Fix issue of PSE hanging when the internal 2.5G PHY connection is disconnected]
ef2c790d [openwrt][common][config][Add AN8855 dsa and gsw config in alphabetical order]
97f46542 [MAC80211][hnat][Improve ETH to ETH performace in an unbalanced PHY rate test for mt7981/7986]
ab061242 [openwrt][common][bsp][Add support to reset boot count of dual image booting]
dff562ec [openwrt][common][bsp][Refactor dual image related patches]
4041ddc5 [CRITICAL][kernel][mt7988][eth][Increase CDM2 guard band settings to 4KB]
d8bd64af [kernel][mt7981][eth][Fix issue of GMAC RX hanging when internal GPHY connect to a legacy 10M/Half hub]
f8e2de72 [CRITICAL][kernel][mt7988][eth][Fix issue of transmitting abnormal data for SGMII]
84c34a72 [openwrt][mt7988][crypto][Fix 3 PPE issue for IPSec]
2f5b874e [MAC80211][hnat][Fix issue of multiple PPEs unbind for ETH in mt7981/7986]
15456702 [openwrt][common][network][Upgrade lldpd from 1.0.17 release 2 to release 3]
3d01da2e [openwrt][common][app][Fix switch cmd netlink issue on mt7988]
8d49660c [kernel][common][dts][Fix the mt7981 with an8855 syntax error dts]
88339b3b [kernel][common][hnat][Fix HNAT BIND issue with entry index 0x3fff]
9c805693 [openwrt][common][app][Add an8855 switch command support]
4cadd12b [openwrt][common][app][Refactor switch command to support switches with different design]
ba8a98e4 [kernel][common][net][Add AN8855 dsa and gsw driver]
6adb18b9 [kernel][common][hnat][Add PPE config to compare source PSE port as hit condition]
99170889 [kernel][common][eth][Add the new firmware for Aquantia AQR113C and CUX3410]
f634629e [kernel][mt7988][eth][macsec: Remove CK_TOP_NETSYS_TOPS_400M_SEL since it's not relevant]
f868325b [kernel][common][eth][Add Aquantia CUX3410 support]
6f2ddbf0 [openwrt][mt7988][tops][fix 3 PPE feature issue]
ff49cc9f [kernel][common][Refactor network backport patch path]
2c9fda11 [kernel][mtd/spi/nmbm/phy/][Change pending-5.4 & backport-5.4 files to correct folder]
[Release-log]
Change-Id: I793a18f2f96f185687080a0fb6b55379995b0398
diff --git a/recipes-devtools/switch/files/src/Makefile b/recipes-devtools/switch/files/src/Makefile
index 81ae127..1d88a8c 100644
--- a/recipes-devtools/switch/files/src/Makefile
+++ b/recipes-devtools/switch/files/src/Makefile
@@ -1,6 +1,10 @@
EXEC = switch
SRC=switch_fun.c switch_753x.c switch_ioctl.c switch_netlink.c
+SRC+=switch_fun_an8855.c an8855_sdk/api/src/*.c
+
+CFLAGS+=-I./an8855_sdk/api/inc
+CFLAGS+=-DCOMPAT_MODE
all: $(EXEC)
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air.h
new file mode 100644
index 0000000..c62174f
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air.h
@@ -0,0 +1,216 @@
+/* FILE NAME: air.h
+ * PURPOSE:
+ * Define the initialization in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_H
+#define AIR_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include <stdio.h>
+#include <string.h>
+#include "air_types.h"
+#include "air_error.h"
+#include "air_reg.h"
+#include "air_aml.h"
+#include "air_port.h"
+#include "air_vlan.h"
+#include "air_lag.h"
+#include "air_l2.h"
+#include "air_stp.h"
+#include "air_mirror.h"
+#include "air_mib.h"
+#include "air_diag.h"
+#include "air_led.h"
+#include "air_cmd.h"
+#include "air_qos.h"
+#include "air_switch.h"
+#include "air_ver.h"
+#include "air_sec.h"
+#include "air_acl.h"
+#include "air_sptag.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+#define AIR_CHECK_PTR(__ptr__) do \
+{ \
+ if (NULL == (__ptr__)) \
+ { \
+ return AIR_E_BAD_PARAMETER; \
+ } \
+} while (0)
+
+#define AIR_PARAM_CHK(expr, errCode) do \
+{ \
+ if ((I32_T)(expr)) \
+ { \
+ return errCode; \
+ } \
+} while (0)
+
+#define AIR_PRINT(fmt,...) do \
+{ \
+ if (_ext_printf) \
+ { \
+ _ext_printf(fmt, ##__VA_ARGS__); \
+ } \
+}while (0)
+
+#define AIR_UDELAY(us) do \
+{ \
+ if (_ext_udelay) \
+ { \
+ _ext_udelay(us); \
+ } \
+}while (0)
+
+#define AIR_MALLOC(size) (_ext_malloc ? _ext_malloc(size) : NULL)
+
+#define AIR_FREE(ptr) do \
+ { \
+ if (ptr && _ext_free) \
+ { \
+ _ext_free(ptr); \
+ } \
+ }while (0)
+
+#ifndef BIT
+#define BIT(nr) (1UL << (nr))
+#endif /* End of BIT */
+
+/* bits range: for example BITS(16,23) = 0xFF0000*/
+#ifndef BITS
+#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
+#endif /* End of BITS */
+
+/* bits range: for example BITS_RANGE(16,4) = 0x0F0000*/
+#ifndef BITS_RANGE
+#define BITS_RANGE(offset, range) BITS(offset, ((offset)+(range)-1))
+#endif /* End of BITS_RANGE */
+
+/* bits offset right: for example BITS_OFF_R(0x1234, 8, 4) = 0x2 */
+#ifndef BITS_OFF_R
+#define BITS_OFF_R(val, offset, range) ((val >> offset) & (BIT(range) - 1))
+#endif /* End of BITS_OFF_R */
+
+/* bits offset left: for example BITS_OFF_L(0x1234, 8, 4) = 0x400 */
+#ifndef BITS_OFF_L
+#define BITS_OFF_L(val, offset, range) ((val & (BIT(range) - 1)) << offset)
+#endif /* End of BITS_OFF_L */
+
+#ifndef MAX
+#define MAX(a, b) (((a)>(b))?(a):(b))
+#endif /* End of MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a)<(b))?(a):(b))
+#endif /* End of MIN */
+
+/* DATA TYPE DECLARATIONS
+ */
+typedef AIR_ERROR_NO_T
+(*AIR_PRINTF)(
+ C8_T* fmt,
+ ...);
+
+typedef void
+(*AIR_UDELAY)(
+ UI32_T us);
+
+typedef void*
+(*AIR_MALLOC)(
+ UI32_T size);
+
+typedef void
+(*AIR_FREE)(
+ void *ptr);
+
+typedef struct
+{
+ AML_DEV_ACCESS_T dev_access;
+ AIR_PRINTF printf;
+ AIR_UDELAY udelay;
+ AIR_MALLOC malloc;
+ AIR_FREE free;
+}AIR_INIT_PARAM_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+extern AIR_PRINTF _ext_printf;
+extern AIR_UDELAY _ext_udelay;
+extern AIR_MALLOC _ext_malloc;
+extern AIR_FREE _ext_free;
+
+
+/* FUNCTION NAME: air_init
+ * PURPOSE:
+ * This API is used to initialize the SDK.
+ *
+ * INPUT:
+ * unit -- The device unit
+ * ptr_init_param -- The sdk callback functions.
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_init(
+ const UI32_T unit,
+ AIR_INIT_PARAM_T *ptr_init_param);
+
+/* FUNCTION NAME: air_hw_reset
+ * PURPOSE:
+ * This API is used to reset hardware.
+ *
+ * INPUT:
+ * unit -- The device unit
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_hw_reset(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_set_gpio_pin_mux
+ * PURPOSE:
+ * This API is used to set gpio pin mux.
+ *
+ * INPUT:
+ * unit -- The device unit
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_set_gpio_pin_mux(
+ const UI32_T unit);
+
+#endif /* AIR_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_acl.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_acl.h
new file mode 100644
index 0000000..f4ea6c9
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_acl.h
@@ -0,0 +1,1245 @@
+/* FILE NAME: air_acl.h
+ * PURPOSE:
+ * Define the ACL function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_ACL_H
+#define AIR_ACL_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define ACL_MAX_BUSY_TIME (20)
+#define ACL_MAX_RULE_NUM (128)
+#define ACL_MAX_ACTION_NUM (128)
+#define ACL_MAX_TRTCM_NUM (32)
+#define ACL_MAX_MIB_NUM (64)
+#define ACL_MAX_UDF_NUM (16)
+#define ACL_MAX_METER_NUM (32)
+#define ACL_MAX_MIR_SESSION_NUM (2)
+#define ACL_MAX_TOKEN_NUM (0xffff)
+#define ACL_MAX_VLAN_NUM (4096)
+#define ACL_MAX_DROP_PCD_NUM (8)
+#define ACL_MAX_CLASS_SLR_NUM (8)
+#define ACL_MAX_ATTACK_RATE_NUM (96)
+#define ACL_MAX_WORD_OFST_NUM (128)
+#define ACL_MAX_CMP_PAT_NUM (0xffff)
+#define ACL_MAX_CMP_BIT_NUM (0xffff)
+#define ACL_MAX_CBS_NUM (0xffff)
+#define ACL_MAX_CIR_NUM (0xffff)
+#define ACL_MAX_PBS_NUM (0xffff)
+#define ACL_MAX_PIR_NUM (0xffff)
+
+#define ACL_EN_MASK (0x1)
+#define ACL_MEM_CFG_DONE_OFFSET (31)
+#define ACL_MEM_CFG_RULE_ID_OFFSET (16)
+#define ACL_MEM_CFG_TCAM_CELL_OFFSET (12)
+#define ACL_MEM_CFG_DATA_BN_OFFSET (8)
+#define ACL_MEM_CFG_MEM_SEL_OFFSET (4)
+#define ACL_MEM_CFG_FUNC_SEL_OFFSET (1)
+#define ACL_MEM_CFG_EN (1)
+
+#define ACL_MIB_SEL_OFFSET (4)
+#define ACL_MIB_CLEAR (1)
+#define ACL_MIB_SEL_MASK (0x3f)
+#define ACL_TRTCM_EN_OFFSET (31)
+#define ACL_TRTCM_BUSY_OFFSET (31)
+#define ACL_TRTCM_WRITE (1U << 27)
+#define ACL_TRTCM_READ (0U << 27)
+#define ACL_TRTCM_ID_OFFSET (0)
+#define ACL_TRTCM_ID_MASK (0x1f)
+#define ACL_TRTCM_CBS_MASK (0xffff)
+#define ACL_TRTCM_EBS_MASK (0xffff)
+#define ACL_TRTCM_CIR_MASK (0xffff)
+#define ACL_TRTCM_EIR_MASK (0xffff)
+#define ACL_RATE_BUSY_OFFSET (31)
+#define ACL_RATE_WRITE (1U << 30)
+#define ACL_RATE_READ (0U << 30)
+#define ACL_RATE_ID_OFFSET (20)
+#define ACL_RATE_ID_MASK (0x1f)
+#define ACL_RATE_EN_OFFSET (19)
+#define ACL_RATE_EN (1U << 19)
+#define ACL_RATE_DIS (0U << 19)
+#define ACL_RATE_TOKEN_MASK (0xffff)
+
+/*ACL rule field offset and width*/
+#define RULE_TYPE0_OFFSET (0)
+#define DMAC_OFFSET (1)
+#define SMAC_OFFSET (49)
+#define STAG_OFFSET (97)
+#define CTAG_OFFSET (113)
+#define ETYPE_OFFSET (129)
+#define DIP_OFFSET (145)
+#define SIP_OFFSET (177)
+#define DSCP_OFFSET (209)
+#define PROTOCOL_OFFSET (217)
+#define DPORT_OFFSET (225)
+#define SPORT_OFFSET (241)
+#define UDF_OFFSET (257)
+#define FIELDMAP_OFFSET (273)
+#define IS_IPV6_OFFSET (286)
+#define PORTMAP_OFFSET (287)
+
+#define RULE_TYPE1_OFFSET (0)
+#define DIP_IPV6_OFFSET (1)
+#define SIP_IPV6_OFFSET (97)
+#define FLOW_LABEL_OFFSET (193)
+
+#define RULE_TYPE0_WIDTH (1)
+#define DMAC_WIDTH (8)
+#define SMAC_WIDTH (8)
+#define STAG_WIDTH (16)
+#define CTAG_WIDTH (16)
+#define ETYPE_WIDTH (16)
+#define DIP_WIDTH (32)
+#define SIP_WIDTH (32)
+#define DSCP_WIDTH (8)
+#define PROTOCOL_WIDTH (8)
+#define DPORT_WIDTH (16)
+#define SPORT_WIDTH (16)
+#define UDF_WIDTH (16)
+#define FIELDMAP_WIDTH (13)
+#define IS_IPV6_WIDTH (1)
+#define PORTMAP_WIDTH (7)
+
+#define RULE_TYPE1_WIDTH (1)
+#define DIP_IPV6_WIDTH (32)
+#define SIP_IPV6_WIDTH (32)
+#define FLOW_LABEL_WIDTH (20)
+
+/*ACL action offset and width*/
+#define ACL_VLAN_VID_OFFSET (0)
+#define ACL_VLAN_HIT_OFFSET (12)
+#define ACL_CLASS_IDX_OFFSET (13)
+#define ACL_TCM_OFFSET (18)
+#define ACL_TCM_SEL_OFFSET (20)
+#define ACL_DROP_PCD_G_OFFSET (21)
+#define ACL_DROP_PCD_Y_OFFSET (24)
+#define ACL_DROP_PCD_R_OFFSET (27)
+#define CLASS_SLR_OFFSET (30)
+#define CLASS_SLR_SEL_OFFSET (33)
+#define DROP_PCD_SEL_OFFSET (34)
+#define TRTCM_EN_OFFSET (35)
+#define ACL_MANG_OFFSET (36)
+#define LKY_VLAN_OFFSET (37)
+#define LKY_VLAN_EN_OFFSET (38)
+#define EG_TAG_OFFSET (39)
+#define EG_TAG_EN_OFFSET (42)
+#define PRI_USER_OFFSET (43)
+#define PRI_USER_EN_OFFSET (46)
+#define MIRROR_OFFSET (47)
+#define FW_PORT_OFFSET (49)
+#define PORT_FW_EN_OFFSET (52)
+#define RATE_INDEX_OFFSET (53)
+#define RATE_EN_OFFSET (58)
+#define ATTACK_RATE_ID_OFFSET (59)
+#define ATTACK_RATE_EN_OFFSET (66)
+#define ACL_MIB_ID_OFFSET (67)
+#define ACL_MIB_EN_OFFSET (73)
+#define VLAN_PORT_SWAP_OFFSET (74)
+#define DST_PORT_SWAP_OFFSET (75)
+#define BPDU_OFFSET (76)
+#define PORT_OFFSET (77)
+#define PORT_FORCE_OFFSET (84)
+
+#define ACL_VLAN_VID_WIDTH (12)
+#define ACL_VLAN_HIT_WIDTH (1)
+#define ACL_CLASS_IDX_WIDTH (5)
+#define ACL_TCM_WIDTH (2)
+#define ACL_TCM_SEL_WIDTH (1)
+#define ACL_DROP_PCD_G_WIDTH (3)
+#define ACL_DROP_PCD_Y_WIDTH (3)
+#define ACL_DROP_PCD_R_WIDTH (3)
+#define CLASS_SLR_WIDTH (3)
+#define CLASS_SLR_SEL_WIDTH (1)
+#define DROP_PCD_SEL_WIDTH (1)
+#define TRTCM_EN_WIDTH (1)
+#define ACL_MANG_WIDTH (1)
+#define LKY_VLAN_WIDTH (1)
+#define LKY_VLAN_EN_WIDTH (1)
+#define EG_TAG_WIDTH (3)
+#define EG_TAG_EN_WIDTH (1)
+#define PRI_USER_WIDTH (3)
+#define PRI_USER_EN_WIDTH (1)
+#define MIRROR_WIDTH (2)
+#define FW_PORT_WIDTH (3)
+#define PORT_FW_EN_WIDTH (1)
+#define RATE_INDEX_WIDTH (5)
+#define RATE_EN_WIDTH (1)
+#define ATTACK_RATE_ID_WIDTH (7)
+#define ATTACK_RATE_EN_WIDTH (1)
+#define ACL_MIB_ID_WIDTH (6)
+#define ACL_MIB_EN_WIDTH (1)
+#define VLAN_PORT_SWAP_WIDTH (1)
+#define DST_PORT_SWAP_WIDTH (1)
+#define BPDU_WIDTH (1)
+#define PORT_WIDTH (7)
+#define PORT_FORCE_WIDTH (1)
+
+/*ACL UDF table offset and width*/
+#define UDF_RULE_EN_OFFSET (0)
+#define UDF_PKT_TYPE_OFFSET (1)
+#define WORD_OFST_OFFSET (4)
+#define CMP_SEL_OFFSET (11)
+#define CMP_PAT_OFFSET (32)
+#define CMP_MASK_OFFSET (48)
+#define PORT_BITMAP_OFFSET (64)
+
+#define UDF_RULE_EN_WIDTH (1)
+#define UDF_PKT_TYPE_WIDTH (3)
+#define WORD_OFST_WIDTH (7)
+#define CMP_SEL_WIDTH (1)
+#define CMP_PAT_WIDTH (16)
+#define CMP_MASK_WIDTH (16)
+#define PORT_BITMAP_WIDTH (29)
+
+#define ACL_UDF_ACC_OFFSET (31)
+#define ACL_UDF_READ_MASK (0x0)
+#define ACL_UDF_WRITE_MASK (0x1)
+#define ACL_UDF_CLEAR_MASK (0x2)
+#define ACL_UDF_CMD_OFFSET (28)
+#define ACL_UDF_READ (ACL_UDF_READ_MASK << ACL_UDF_CMD_OFFSET)
+#define ACL_UDF_WRITE (ACL_UDF_WRITE_MASK << ACL_UDF_CMD_OFFSET)
+#define ACL_UDF_CLEAR (ACL_UDF_CLEAR_MASK << ACL_UDF_CMD_OFFSET)
+#define ACL_UDF_ADDR_MASK (0xf)
+
+#define DPCR_HIGH_THRSH_OFFSET (11)
+#define DPCR_PBB_OFFSET (22)
+#define DPCR_LOW_THRSH_WIDTH (11)
+#define DPCR_LOW_THRSH_MASK (0x7ff)
+#define DPCR_HIGH_THRSH_WIDTH (11)
+#define DPCR_HIGH_THRSH_MASK (0x7ff)
+#define DPCR_PBB_WIDTH (10)
+#define DPCR_PBB_MASK (0x3ff)
+#define DP_MFRM_EX_OFFSET (24)
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef enum
+{
+ AIR_ACL_RULE_OFS_FMT_MAC_HEADER = 0,
+ AIR_ACL_RULE_OFS_FMT_L2_PAYLOAD,
+ AIR_ACL_RULE_OFS_FMT_IPV4_HEADER,
+ AIR_ACL_RULE_OFS_FMT_IPV6_HEADER,
+ AIR_ACL_RULE_OFS_FMT_L3_PAYLOAD,
+ AIR_ACL_RULE_OFS_FMT_TCP_HEADER,
+ AIR_ACL_RULE_OFS_FMT_UDP_HEADER,
+ AIR_ACL_RULE_OFS_FMT_L4_PAYLOAD,
+ AIR_ACL_RULE_OFS_FMT_LAST
+} AIR_ACL_RULE_OFS_FMT_T;
+
+typedef enum
+{
+ AIR_ACL_RULE_CMP_SEL_PATTERN, /* Pattern hit by data pattern and bit mask */
+ AIR_ACL_RULE_CMP_SEL_THRESHOLD, /* Pattern hit by low and high threshold */
+ AIR_ACL_RULE_CMP_SEL_LAST
+}AIR_ACL_RULE_CMP_SEL_T;
+
+typedef enum
+{
+ AIR_ACL_ACT_FWD_DIS, /* Don't change forwarding behaviour by ACL */
+ AIR_ACL_ACT_FWD_CPU_EX = 4, /* Forward by system default & CPU port is excluded */
+ AIR_ACL_ACT_FWD_CPU_IN, /* Forward by system default & CPU port is included */
+ AIR_ACL_ACT_FWD_CPU, /* Forward to CPU port only */
+ AIR_ACL_ACT_FWD_DROP, /* Frame dropped */
+ AIR_ACL_ACT_FWD_LAST
+}AIR_ACL_ACT_FWD_T;
+
+typedef enum
+{
+ AIR_ACL_ACT_EGTAG_DIS,
+ AIR_ACL_ACT_EGTAG_CONSISTENT,
+ AIR_ACL_ACT_EGTAG_UNTAG = 4,
+ AIR_ACL_ACT_EGTAG_SWAP,
+ AIR_ACL_ACT_EGTAG_TAG,
+ AIR_ACL_ACT_EGTAG_STACK,
+ AIR_ACL_ACT_EGTAG_LAST
+}AIR_ACL_ACT_EGTAG_T;
+
+typedef enum
+{
+ AIR_ACL_ACT_USR_TCM_DEFAULT, /* Normal packets, don't work based on color */
+ AIR_ACL_ACT_USR_TCM_GREEN, /* Green */
+ AIR_ACL_ACT_USR_TCM_YELLOW, /* Yellow */
+ AIR_ACL_ACT_USR_TCM_RED, /* Red */
+ AIR_ACL_ACT_USR_TCM_LAST
+}AIR_ACL_ACT_USR_TCM_T;
+
+typedef enum
+{
+ AIR_ACL_DP_COLOR_GREEN,
+ AIR_ACL_DP_COLOR_YELLOW,
+ AIR_ACL_DP_COLOR_RED,
+ AIR_ACL_DP_COLOR_LAST
+}AIR_ACL_DP_COLOR_T;
+
+typedef enum
+{
+ AIR_ACL_RULE_TYPE_0,
+ AIR_ACL_RULE_TYPE_1,
+ AIR_ACL_RULE_TYPE_LAST
+}AIR_ACL_RULE_TYPE_T;
+
+typedef enum
+{
+ AIR_ACL_RULE_T_CELL,
+ AIR_ACL_RULE_C_CELL,
+ AIR_ACL_RULE_TCAM_LAST
+}AIR_ACL_RULE_TCAM_T;
+
+typedef enum
+{
+ AIR_ACL_MEM_SEL_RULE,
+ AIR_ACL_MEM_SEL_ACTION,
+ AIR_ACL_MEM_SEL_LAST
+}AIR_ACL_MEM_SEL_T;
+
+typedef enum
+{
+ AIR_ACL_MEM_FUNC_READ = 0,
+ AIR_ACL_MEM_FUNC_WRITE,
+ AIR_ACL_MEM_FUNC_CLEAR,
+ AIR_ACL_MEM_FUNC_CONFIG_READ = 4,
+ AIR_ACL_MEM_FUNC_CONFIG_WRITE,
+ AIR_ACL_MEM_FUNC_LAST
+}AIR_ACL_MEM_FUNC_T;
+
+typedef enum
+{
+ AIR_ACL_RULE_CONFIG_ENABLE,
+ AIR_ACL_RULE_CONFIG_END,
+ AIR_ACL_RULE_CONFIG_REVERSE,
+ AIR_ACL_RULE_CONFIG_LAST
+}AIR_ACL_RULE_CONFIG_T;
+
+typedef enum
+{
+ AIR_ACL_CHECK_ACL,
+ AIR_ACL_CHECK_UDF,
+ AIR_ACL_CHECK_TRTCM,
+ AIR_ACL_CHECK_METER,
+ AIR_ACL_CHECK_TYPE_LAST
+}AIR_ACL_CHECK_TYPE_T;
+
+typedef enum
+{
+ AIR_ACL_DMAC,
+ AIR_ACL_SMAC,
+ AIR_ACL_STAG,
+ AIR_ACL_CTAG,
+ AIR_ACL_ETYPE,
+ AIR_ACL_DIP,
+ AIR_ACL_SIP,
+ AIR_ACL_DSCP,
+ AIR_ACL_PROTOCOL,
+ AIR_ACL_DPORT,
+ AIR_ACL_SPORT,
+ AIR_ACL_UDF,
+ AIR_ACL_FLOW_LABEL,
+ AIR_ACL_FIELD_TYPE_LAST
+}AIR_ACL_FIELD_TYPE_T;
+
+typedef struct AIR_ACL_FIELD_S
+{
+ UI8_T dmac[6];
+ UI8_T smac[6];
+ UI16_T stag;
+ UI16_T ctag;
+ UI16_T etype;
+ UI32_T dip[4];
+ UI32_T sip[4];
+ UI8_T dscp;
+ UI8_T protocol;
+ UI32_T flow_label;
+ UI16_T dport;
+ UI16_T sport;
+ UI16_T udf;
+ BOOL_T isipv6;
+ UI16_T fieldmap;
+ UI32_T portmap;
+} AIR_ACL_FIELD_T;
+
+typedef struct AIR_ACL_CTRL_S
+{
+ BOOL_T rule_en;
+ BOOL_T reverse;
+ BOOL_T end;
+}AIR_ACL_CTRL_T;
+
+typedef struct AIR_ACL_RULE_S
+{
+ AIR_ACL_FIELD_T key;
+ AIR_ACL_FIELD_T mask;
+ AIR_ACL_CTRL_T ctrl;
+} AIR_ACL_RULE_T;
+
+typedef struct AIR_ACL_UDF_RULE_S
+{
+ BOOL_T valid; /* Valid bit */
+ AIR_ACL_RULE_OFS_FMT_T offset_format; /* Format Type for Word Offset Range */
+ UI32_T offset; /* Word Offset */
+ UI32_T portmap; /* Physical Source Port Bit-map */
+ AIR_ACL_RULE_CMP_SEL_T cmp_sel; /* Comparison mode selection */
+ UI16_T pattern; /* Comparison Pattern when cmp_sel=AIR_ACL_RULE_CMP_SEL_PATTERN */
+ UI16_T mask; /* Comparison Pattern Mask when cmp_sel=AIR_ACL_RULE_CMP_SEL_PATTERN */
+ UI16_T low_threshold; /* Low Threshold when cmp_sel=AIR_ACL_RULE_CMP_SEL_THRESHOLD */
+ UI16_T high_threshold; /* High Threshold when cmp_sel=AIR_ACL_RULE_CMP_SEL_THRESHOLD */
+}AIR_ACL_UDF_RULE_T;
+
+typedef struct AIR_ACL_ACT_TRTCM_S
+{
+ BOOL_T cls_slr_sel; /* FALSE: Select original class selector value
+ TRUE: Select ACL control table defined class selector value */
+ UI8_T cls_slr; /* User defined class selector */
+ BOOL_T drop_pcd_sel; /* FALSE: Select original drop precedence value
+ TRUE: Select ACL control table defined drop precedence value */
+ UI8_T drop_pcd_r; /* User defined drop precedence for red packets */
+ UI8_T drop_pcd_y; /* User defined drop precedence for yellow packets */
+ UI8_T drop_pcd_g; /* User defined drop precedence for green packets */
+ BOOL_T tcm_sel; /* FALSE: Select user defined color value
+ TRUE: Select color remark by trtcm table */
+ AIR_ACL_ACT_USR_TCM_T usr_tcm; /* User defined color remark */
+ UI8_T tcm_idx; /* Index for the 32-entries trtcm table */
+}AIR_ACL_ACT_TRTCM_T;
+
+typedef struct AIR_ACL_ACTION_S
+{
+ BOOL_T port_en;
+ BOOL_T dest_port_sel; /* Swap destination port member by portmap when port_en=1 */
+ BOOL_T vlan_port_sel; /* Swap VLAN port member by portmap when port_en=1 */
+ UI32_T portmap;
+
+ BOOL_T cnt_en;
+ UI32_T cnt_idx; /* Counter index */
+
+ BOOL_T attack_en;
+ UI32_T attack_idx; /* Attack rate index */
+
+ BOOL_T rate_en;
+ UI32_T rate_idx; /* Index of meter table */
+
+ BOOL_T vlan_en;
+ UI32_T vlan_idx; /* Vid from ACL */
+
+ UI8_T mirrormap; /* mirror session bitmap */
+
+ BOOL_T pri_user_en;
+ UI8_T pri_user; /* User Priority from ACL */
+
+ BOOL_T lyvlan_en;
+ BOOL_T lyvlan; /* Leaky VLAN */
+
+ BOOL_T mang; /* Management frame attribute */
+
+ BOOL_T bpdu; /* BPDU frame attribute */
+
+ BOOL_T fwd_en;
+ AIR_ACL_ACT_FWD_T fwd; /* Frame TO_CPU Forwarding */
+
+ BOOL_T egtag_en;
+ AIR_ACL_ACT_EGTAG_T egtag; /* Egress tag control */
+
+ BOOL_T trtcm_en;
+ AIR_ACL_ACT_TRTCM_T trtcm; /* TRTCM control */
+
+}AIR_ACL_ACTION_T;
+
+typedef struct AIR_ACL_TRTCM_S
+{
+ UI16_T cir; /* Committed information rate (unit: 64Kbps) */
+ UI16_T pir; /* Peak information rate (unit: 64Kbps) */
+ UI16_T cbs; /* Committed burst size (unit: byte) */
+ UI16_T pbs; /* Peak burst size (unit: byte) */
+}AIR_ACL_TRTCM_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_acl_setRuleCtrl
+ * PURPOSE:
+ * Set ACL rule control.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ * ptr_rule -- Structure of ACL rule control
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setRuleCtrl(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_CTRL_T *ptr_ctrl);
+
+/* FUNCTION NAME: air_acl_getRuleCtrl
+ * PURPOSE:
+ * Get ACL rule control.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * ptr_ctrl -- Structure of ACL rule control
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getRuleCtrl(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_CTRL_T *ptr_ctrl);
+
+/* FUNCTION NAME: air_acl_setRule
+ * PURPOSE:
+ * Set ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ * rule -- Structure of ACL rule entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_RULE_T *rule);
+
+/* FUNCTION NAME: air_acl_delRule
+ * PURPOSE:
+ * Delete an ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delRule(
+ const UI32_T unit,
+ const UI32_T rule_idx);
+
+/* FUNCTION NAME: air_acl_clearRule
+ * PURPOSE:
+ * Clear all ACL rule entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearRule(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_acl_getRule
+ * PURPOSE:
+ * Get ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * ptr_rule -- Structure of ACL rule entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_RULE_T *ptr_rule);
+
+/* FUNCTION NAME: air_acl_setAction
+ * PURPOSE:
+ * Set an ACL action entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ * act -- Structure of ACL action entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_NOT_SUPPORT
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setAction(
+ const UI32_T unit,
+ const UI32_T act_idx,
+ const AIR_ACL_ACTION_T act);
+
+/* FUNCTION NAME: air_acl_delAction
+ * PURPOSE:
+ * Delete an ACL action entry with specific index
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_ENTRY_NOT_FOUND
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delAction(
+ const UI32_T unit,
+ const UI32_T act_idx);
+
+/* FUNCTION NAME: air_acl_clearAction
+ * PURPOSE:
+ * Clear all ACL action entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearAction(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_acl_getAction
+ * PURPOSE:
+ * Get an ACL action entry with speficic index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ *
+ * OUTPUT:
+ * ptr_act -- Structure of ACL action entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_ENTRY_NOT_FOUND
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getAction(
+ const UI32_T unit,
+ const UI32_T act_idx,
+ AIR_ACL_ACTION_T *ptr_act);
+
+/* FUNCTION NAME: air_acl_setTrtcm
+ * PURPOSE:
+ * Set a trTCM entry with the specific index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * tcm_idx -- Index of trTCM entry
+ * tcm -- Structure of trTCM entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_setTrtcm(
+ const UI32_T unit,
+ const UI32_T tcm_idx,
+ const AIR_ACL_TRTCM_T tcm);
+
+/* FUNCTION NAME: air_acl_delTrtcm
+ * PURPOSE:
+ * Delete an ACL trTCM entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * trtcm_idx -- Index of ACL trTCM entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_delTrtcm(
+ const UI32_T unit,
+ const UI32_T trtcm_idx);
+
+/* FUNCTION NAME: air_acl_clearTrtcm
+ * PURPOSE:
+ * Clear all ACL trTCM entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearTrtcm(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_acl_getTrtcm
+ * PURPOSE:
+ * Get a trTCM entry with the specific index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * tcm_idx -- Index of trTCM entry
+ *
+ * OUTPUT:
+ * ptr_tcm -- Structure of trTCM entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_getTrtcm(
+ const UI32_T unit,
+ const UI32_T tcm_idx,
+ AIR_ACL_TRTCM_T *ptr_tcm);
+
+/* FUNCTION NAME: air_acl_setTrtcmEnable
+ * PURPOSE:
+ * Set trTCM enable so the meter table will be updated based on PIR and CIR.
+ * The color marker will also be enabled when ACL is hit.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setTrtcmEnable(
+ const UI32_T unit,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_acl_getTrtcm
+ * PURPOSE:
+ * Get a trTCM enable state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getTrtcmEnable(
+ const UI32_T unit,
+ BOOL_T *const ptr_state);
+
+/* FUNCTION NAME: air_acl_setPortEnable
+ * PURPOSE:
+ * Set ACL state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setPortEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_acl_getPortEnable
+ * PURPOSE:
+ * Get ACL state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getPortEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state);
+
+/* FUNCTION NAME: air_acl_setDropEnable
+ * PURPOSE:
+ * Set ACL drop precedence state
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setDropEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_acl_getDropEnable
+ * PURPOSE:
+ * Get ACL drop precedence state
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getDropEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_state);
+
+/* FUNCTION NAME: air_acl_setDropThreshold
+ * PURPOSE:
+ * Set ACL drop threshold.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ * high -- High threshold
+ * low -- Low threshold
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_setDropThreshold(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ const UI32_T high,
+ const UI32_T low);
+
+/* FUNCTION NAME: air_acl_getDropThreshold
+ * PURPOSE:
+ * Get ACL drop threshold.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ *
+ * OUTPUT:
+ * ptr_high -- High threshold
+ * ptr_low -- Low threshold
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_getDropThreshold(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ UI32_T *ptr_high,
+ UI32_T *ptr_low);
+
+/* FUNCTION NAME: air_acl_setDropProbability
+ * PURPOSE:
+ * Set ACL drop probability.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ * probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_setDropProbability(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ const UI32_T probability);
+
+/* FUNCTION NAME: air_acl_getDropProbability
+ * PURPOSE:
+ * Get ACL drop probability.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ *
+ * OUTPUT:
+ * ptr_probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_getDropProbability(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ UI32_T *ptr_probability);
+
+/* FUNCTION NAME:
+ * air_acl_setGlobalState
+ * PURPOSE:
+ * Set the ACL global enable state.
+ * INPUT:
+ * unit -- Device ID
+ * state -- Enable state of ACL
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setGlobalState(
+ const UI32_T unit,
+ const BOOL_T state);
+
+/* FUNCTION NAME:
+ * air_acl_getGlobalState
+ * PURPOSE:
+ * Get the ACL global enable state.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * ptr_state -- Enable state
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getGlobalState(
+ const UI32_T unit,
+ BOOL_T *ptr_state);
+
+/* FUNCTION NAME:
+ * air_acl_setUdfRule
+ * PURPOSE:
+ * Set ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * udf_rule -- Structure of ACL UDF rule entry
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setUdfRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_UDF_RULE_T udf_rule);
+
+/* FUNCTION NAME:
+ * air_acl_getUdfRule
+ * PURPOSE:
+ * Get ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * OUTPUT:
+ * ptr_udf_rule -- Structure of ACL UDF rule entry
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getUdfRule(
+ const UI32_T unit,
+ const UI8_T rule_idx,
+ AIR_ACL_UDF_RULE_T *ptr_udf_rule);
+
+/* FUNCTION NAME:
+ * air_acl_delUdfRule
+ * PURPOSE:
+ * Delete ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delUdfRule(
+ const UI32_T unit,
+ const UI8_T rule_idx);
+
+/* FUNCTION NAME:
+ * air_acl_clearUdfRule
+ * PURPOSE:
+ * Clear acl all udf rule.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearUdfRule(
+ const UI32_T unit);
+
+/* FUNCTION NAME:
+ * air_acl_setMeterTable
+ * PURPOSE:
+ * Set flow ingress rate limit by meter table.
+ * INPUT:
+ * unit -- Device ID
+ * meter_id -- Meter id
+ * enable -- Meter enable state
+ * rate -- Ratelimit(unit:64kbps)
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setMeterTable(
+ const UI32_T unit,
+ const UI32_T meter_id,
+ const BOOL_T enable,
+ const UI32_T rate);
+
+/* FUNCTION NAME:
+ * air_acl_getMeterTable
+ * PURPOSE:
+ * Get meter table configuration.
+ * INPUT:
+ * unit -- Device ID
+ * meter_id -- Meter id
+ * OUTPUT:
+ * ptr_enable -- Meter enable state
+ * ptr_rate -- Ratelimit(unit:64kbps)
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getMeterTable(
+ const UI32_T unit,
+ const UI32_T meter_id,
+ BOOL_T *ptr_enable,
+ UI32_T *ptr_rate);
+
+#endif /* End of AIR_ACL_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_aml.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_aml.h
new file mode 100644
index 0000000..49a38b6
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_aml.h
@@ -0,0 +1,214 @@
+/* FILE NAME: air_aml.h
+ * PURPOSE:
+ * Define the access management layer function in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_AML_H
+#define AIR_AML_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+typedef AIR_ERROR_NO_T
+(*AML_DEV_READ_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+typedef AIR_ERROR_NO_T
+(*AML_DEV_WRITE_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ const UI32_T data);
+
+typedef AIR_ERROR_NO_T
+(*AML_DEV_PHY_READ_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+typedef AIR_ERROR_NO_T
+(*AML_DEV_PHY_WRITE_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ const UI32_T data);
+
+typedef AIR_ERROR_NO_T
+(*AML_DEV_PHY_READ_CL45_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+typedef AIR_ERROR_NO_T
+(*AML_DEV_PHY_WRITE_CL45_FUNC_T)(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ const UI32_T data);
+
+/* To read or write the HW-intf registers. */
+typedef struct
+{
+ AML_DEV_READ_FUNC_T read_callback;
+ AML_DEV_WRITE_FUNC_T write_callback;
+ AML_DEV_PHY_READ_FUNC_T phy_read_callback;
+ AML_DEV_PHY_WRITE_FUNC_T phy_write_callback;
+ AML_DEV_PHY_READ_CL45_FUNC_T phy_cl45_read_callback;
+ AML_DEV_PHY_WRITE_CL45_FUNC_T phy_cl45_write_callback;
+}AML_DEV_ACCESS_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+extern AML_DEV_ACCESS_T _ext_dev_access;
+
+/* FUNCTION NAME: aml_readReg
+ * PURPOSE:
+ * To read data from the register of the specified chip unit.
+ * INPUT:
+ * unit -- the device unit
+ * addr_offset -- the address of register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readReg(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+/* FUNCTION NAME: aml_writeReg
+ * PURPOSE:
+ * To write data to the register of the specified chip unit.
+ * INPUT:
+ * unit -- the device unit
+ * addr_offset -- the address of register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writeReg(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ const UI32_T data);
+
+/* FUNCTION NAME: aml_readPhyReg
+ * PURPOSE:
+ * To read data from the phy register of the specified chip unit in Clause22.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * addr_offset -- the address of phy register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readPhyReg(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+/* FUNCTION NAME: aml_writePhyReg
+ * PURPOSE:
+ * To write data to the phy register of the specified chip unit in Clause22.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * addr_offset -- the address of phy register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writePhyReg(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ const UI32_T ptr_data);
+
+/* FUNCTION NAME: aml_readPhyRegCL45
+ * PURPOSE:
+ * To read data from the phy register of the specified chip unit in Clause45.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * dev_type -- phy register type
+ * addr_offset -- the address of phy register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readPhyRegCL45(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data);
+
+/* FUNCTION NAME: aml_writePhyRegCL45
+ * PURPOSE:
+ * To write data to the phy register of the specified chip unit in Clause45.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * dev_type -- phy register offset
+ * addr_offset -- the address of phy register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writePhyRegCL45(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ const UI32_T data);
+
+#endif /* AIR_AML_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_cmd.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_cmd.h
new file mode 100644
index 0000000..071d063
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_cmd.h
@@ -0,0 +1,50 @@
+/* FILE NAME: air_cmd.h
+ * PURPOSE:
+ * Define the command line function in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_CMD_H
+#define AIR_CMD_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+/* FUNCTION NAME: air_parse_cmd
+ * PURPOSE:
+ * This function is used process diagnostic cmd
+ * INPUT:
+ * argc -- parameter number
+ * argv -- parameter strings
+ * OUTPUT:
+ * None
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ *
+ */
+AIR_ERROR_NO_T
+air_parse_cmd(
+ const UI32_T argc,
+ const C8_T **argv);
+
+UI32_T
+_strtoul(
+ const C8_T *cp,
+ C8_T **endp,
+ UI32_T base);
+
+#endif /* AIR_CMD_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_diag.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_diag.h
new file mode 100644
index 0000000..60fe4f3
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_diag.h
@@ -0,0 +1,87 @@
+/* FILE NAME: air_diag.h
+ * PURPOSE:
+ * Define the diagnostic function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_DIAG_H
+#define AIR_DIAG_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+typedef enum
+{
+ AIR_DIAG_TXCOMPLY_MODE_10M_NLP,
+ AIR_DIAG_TXCOMPLY_MODE_10M_RANDOM,
+ AIR_DIAG_TXCOMPLY_MODE_10M_SINE,
+ AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_A,
+ AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_B,
+ AIR_DIAG_TXCOMPLY_MODE_1000M_TM1,
+ AIR_DIAG_TXCOMPLY_MODE_1000M_TM2,
+ AIR_DIAG_TXCOMPLY_MODE_1000M_TM3,
+ AIR_DIAG_TXCOMPLY_MODE_1000M_TM4,
+ AIR_DIAG_TXCOMPLY_MODE_LAST
+}AIR_DIAG_TXCOMPLY_MODE_T;
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_diag_setTxComplyMode
+ * PURPOSE:
+ * Set Ethernet TX Compliance mode.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Testing mode of Ethernet TX Compliance
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ */
+AIR_ERROR_NO_T
+air_diag_setTxComplyMode(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_DIAG_TXCOMPLY_MODE_T mode);
+
+/* FUNCTION NAME: air_diag_getTxComplyMode
+ * PURPOSE:
+ * Get Ethernet TX Compliance mode.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_mode -- Testing mode of Ethernet TX Compliance
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ */
+AIR_ERROR_NO_T
+air_diag_getTxComplyMode(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_DIAG_TXCOMPLY_MODE_T *ptr_mode);
+
+#endif /* End of AIR_DIAG_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_error.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_error.h
new file mode 100644
index 0000000..836d400
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_error.h
@@ -0,0 +1,56 @@
+/* FILE NAME: air_error.h
+ * PURPOSE:
+ * Define the error code in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_ERROR_H
+#define AIR_ERROR_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+typedef enum
+{
+ AIR_E_OK = 0, /* Ok and no error */
+ AIR_E_OTHERS, /* Operation is unsuccessful */
+ AIR_E_BAD_PARAMETER, /* Parameter is wrong */
+ AIR_E_TABLE_FULL, /* Table is full */
+ AIR_E_ENTRY_NOT_FOUND, /* Entry is not found */
+ AIR_E_ENTRY_EXISTS, /* Entry already exists */
+ AIR_E_NOT_SUPPORT, /* Feature is not supported */
+ AIR_E_TIMEOUT, /* Time out error */
+ AIR_E_LAST
+} AIR_ERROR_NO_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+/* FUNCTION NAME: air_error_getString
+ * PURPOSE:
+ * To obtain the error string of the specified error code
+ *
+ * INPUT:
+ * cause -- The specified error code
+ * OUTPUT:
+ * None
+ * RETURN:
+ * Pointer to the target error string
+ *
+ * NOTES:
+ *
+ *
+ */
+C8_T *
+air_error_getString(
+ const AIR_ERROR_NO_T cause );
+
+#endif /* AIR_ERROR_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_l2.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_l2.h
new file mode 100644
index 0000000..1e77305
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_l2.h
@@ -0,0 +1,323 @@
+/* FILE NAME: air_l2.h
+* PURPOSE:
+* Define the layer 2 functions in AIR SDK.
+*
+* NOTES:
+* None
+*/
+
+#ifndef AIR_L2_H
+#define AIR_L2_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define AIR_L2_MAC_MAX_AGE_OUT_TIME (1000000)
+
+#define AIR_L2_MAX_BUSY_TIME (200)
+#define AIR_L2_MAX_AGE_CNT (BITS(0, (AAC_AGE_CNT_LENGTH - 1)))
+#define AIR_L2_MAX_AGE_UNIT (BITS(0, (AAC_AGE_UNIT_LENGTH - 1)))
+#define AIR_L2_MAC_SET_NUM (4)
+#define AIR_L2_MAX_SIZE (512)
+
+/* Field for MAC Address Table */
+/* Field for MAC entry forward control when hit source MAC */
+typedef enum
+{
+ AIR_L2_FWD_CTRL_DEFAULT,
+ AIR_L2_FWD_CTRL_CPU_INCLUDE,
+ AIR_L2_FWD_CTRL_CPU_EXCLUDE,
+ AIR_L2_FWD_CTRL_CPU_ONLY,
+ AIR_L2_FWD_CTRL_DROP,
+ AIR_L2_FWD_CTRL_LAST
+} AIR_L2_FWD_CTRL_T;
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+/* Entry structure of MAC table */
+typedef struct AIR_MAC_ENTRY_S
+{
+ /* L2 MAC entry keys */
+ /* MAC Address */
+ AIR_MAC_T mac;
+
+ /* Customer VID (12bits) */
+ UI16_T cvid;
+
+ /* Filter ID */
+ UI16_T fid;
+
+ /* l2 mac entry attributes */
+#define AIR_L2_MAC_ENTRY_FLAGS_IVL (1U << 0)
+#define AIR_L2_MAC_ENTRY_FLAGS_STATIC (1U << 1)
+#define AIR_L2_MAC_ENTRY_FLAGS_UNAUTH (1U << 2)
+ UI32_T flags;
+
+ /* Destination Port Map */
+ AIR_PORT_BITMAP_T port_bitmap;
+
+ /* Source MAC address hit forward control */
+ AIR_L2_FWD_CTRL_T sa_fwd;
+
+ /* Age Timer only for getting information */
+ UI32_T timer;
+} AIR_MAC_ENTRY_T;
+
+/* FUNCTION NAME: air_l2_addMacAddr
+ * PURPOSE:
+ * Add or set a L2 unicast MAC address entry.
+ * If the address entry doesn't exist, it will add the entry.
+ * If the address entry already exists, it will set the entry
+ * with user input value.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- Structure of MAC Address table
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TABLE_FULL
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_addMacAddr(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+/* FUNCTION NAME: air_l2_delMacAddr
+ * PURPOSE:
+ * Delete a L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_delMacAddr(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+/* FUNCTION NAME: air_l2_getMacAddr
+ * PURPOSE:
+ * Get a L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * ptr_count -- The number of returned MAC entries
+ * ptr_mac_entry -- Structure of MAC Address table for
+ * searching result.
+ * The size of ptr_mac_entry depends
+ * on the maximun number of bank.
+ * The memory size should greater than
+ * ((# of Bank) * (Size of entry
+ * structure))
+ * AIR_MAC_ENTRY_T
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * AIR_E_TIMEOUT -- Timeout error.
+ * AIR_E_ENTRY_NOT_FOUND -- Entry is not found.
+ * NOTES:
+ * If the parameter:mac in input argument ptr_mac_entry[0] is
+ * empty. It means to search the first valid MAC address entry
+ * in MAC address table. Otherwise, to search the specific MAC
+ * address entry in input argument ptr_mac_entry[0].
+ * Input argument ptr_mac_entry[0] needs include mac, ivl and
+ * (fid or cvid) depends on ivl.
+ * If argument ivl is TRUE, cvid is necessary, or fid is.
+ */
+AIR_ERROR_NO_T
+air_l2_getMacAddr(
+ const UI32_T unit,
+ UI8_T *ptr_count,
+ AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+/* FUNCTION NAME: hal_sco_l2_getMacBucketSize
+ * PURPOSE:
+ * Get the bucket size of one MAC address set when searching L2 table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_size -- The bucket size
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getMacBucketSize(
+ const UI32_T unit,
+ UI32_T *ptr_size);
+
+
+/* FUNCTION NAME: air_l2_getNextMacAddr
+ * PURPOSE:
+ * Get the next L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * ptr_count -- The number of returned MAC entries
+ * ptr_mac_entry -- Structure of MAC Address table for searching result.
+ * The size of ptr_mac_entry depends on the max. number of bank.
+ * The memory size should greater than ((# of Bank) * (Table size))
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ * AIR_E_ENTRY_NOT_FOUND
+ * NOTES:
+ * If the parameter:mac in input argument ptr_mac_entry[0] is empty.
+ * It means to search the next valid MAC address entries of last searching result.
+ * Otherwise, to search the next valid MAC address entry of the specific MAC address
+ * entry in input argument ptr_mac_entry[0].
+ * Input argument ptr_mac_entry[0] needs include mac, ivl and (fid or cvid) depends on ivl.
+ * If argument ivl is TRUE, cvid is necessary, or fid is.
+ */
+AIR_ERROR_NO_T
+air_l2_getNextMacAddr(
+ const UI32_T unit,
+ UI8_T *ptr_count,
+ AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+/* FUNCTION NAME: air_l2_clearMacAddr
+ * PURPOSE:
+ * Clear all L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_clearMacAddr(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_l2_setMacAddrAgeOut
+ * PURPOSE:
+ * Set the age out time of L2 MAC address entries.
+ * INPUT:
+ * unit -- Device ID
+ * age_time -- Age out time (second)
+ * (1..AIR_L2_MAC_MAX_AGE_OUT_TIME)
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_l2_setMacAddrAgeOut(
+ const UI32_T unit,
+ const UI32_T age_time);
+
+/* FUNCTION NAME: air_l2_getMacAddrAgeOut
+ * PURPOSE:
+ * Get the age out time of unicast MAC address.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * ptr_age_time -- age out time
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getMacAddrAgeOut(
+ const UI32_T unit,
+ UI32_T *ptr_age_time);
+
+/* FUNCTION NAME: air_l2_setAgeEnable
+ * PURPOSE:
+ * Set aging state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_setAgeEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_l2_getAgeEnable
+ * PURPOSE:
+ * Get age state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getAgeEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state);
+
+#endif /* End of AIR_L2_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_lag.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_lag.h
new file mode 100644
index 0000000..7ab0132
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_lag.h
@@ -0,0 +1,330 @@
+/* FILE NAME: air_lag.h
+ * PURPOSE:
+ * Define the Link Agrregation function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_LAG_H
+#define AIR_LAG_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define AIR_LAG_MAX_MEM_NUM (4)
+#define AIR_LAG_MAX_PTG_NUM (2)
+
+#define AIR_LAG_MAX_SA_LRN_NUM BITS(0,12)
+#define AIR_GRP_PORT(p,n) (((p) & BITS(0,4)) << (n * 8))
+#define AIR_LAG_MAX_BUSY_TIME (20)
+
+
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef struct AIR_LAG_PTGINFO_S
+{
+ UI32_T csr_gp_enable[4];
+ UI32_T csr_gp_port[4];
+}AIR_LAG_PTGINFO_T;
+
+
+typedef struct AIR_LAG_DISTINFO_S
+{
+ UI32_T sp:1;
+ UI32_T sa:1;
+ UI32_T da:1;
+ UI32_T sip:1;
+ UI32_T dip:1;
+ UI32_T sport:1;
+ UI32_T dport:1;
+ UI32_T reverse:25;
+}AIR_LAG_DISTINFO_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_lag_setMember
+ * PURPOSE:
+ * Set LAG member(s) for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptg_index -- Port trunk index
+ * mem_index -- Member index
+ * mem_en -- enable Member
+ * port_index -- Member port
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setMember(
+ const UI32_T unit,
+ const UI32_T ptg_index,
+ const UI32_T mem_index,
+ const UI32_T mem_en,
+ const UI32_T port_index);
+
+
+/* FUNCTION NAME: air_lag_getMember
+ * PURPOSE:
+ * Get LAG member count.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptg_index -- Port trunk index
+ *
+ * OUTPUT:
+ * member -- Member ports of one port trunk
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getMember(
+ const UI32_T unit,
+ const UI32_T ptg_index,
+ AIR_LAG_PTGINFO_T * member);
+
+/* FUNCTION NAME: air_lag_set_ptgc_state
+ * PURPOSE:
+ * set port trunk group control state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptgc_enable -- enabble or disable port trunk function
+ *
+ * OUTPUT:
+ * none
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_set_ptgc_state(
+ const UI32_T unit,
+ const BOOL_T ptgc_enable);
+
+/* FUNCTION NAME: air_lag_get_ptgc_state
+ * PURPOSE:
+ * Get port trunk group control state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- port trunk fucntion is enable or disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_get_ptgc_state(
+ const UI32_T unit,
+ UI32_T *ptr_state);
+
+
+/* FUNCTION NAME: air_lag_setDstInfo
+ * PURPOSE:
+ * Set information for the packet distribution.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * dstInfo -- Infomation selection of packet distribution
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setDstInfo(
+ const UI32_T unit,
+ const AIR_LAG_DISTINFO_T dstInfo);
+
+/* FUNCTION NAME: air_lag_getDstInfo
+ * PURPOSE:
+ * Set port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_dstInfo -- Infomation selection of packet distribution
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getDstInfo(
+ const UI32_T unit,
+ AIR_LAG_DISTINFO_T *ptr_dstInfo);
+
+
+/* FUNCTION NAME: air_lag_setState
+ * PURPOSE:
+ * Set the enable/disable for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * hashtype -- crc32msb/crc32lsb/crc16/xor4
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_sethashtype(
+ const UI32_T unit,
+ const UI32_T hashtype);
+
+/* FUNCTION NAME: air_lag_getState
+ * PURPOSE:
+ * Get port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * hashtype -- crc32msb/crc32lsb/crc16/xor4
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_gethashtype(
+ const UI32_T unit,
+ UI32_T *hashtype);
+
+/* FUNCTION NAME: air_lag_setSpSel
+ * PURPOSE:
+ * Set the enable/disable for selection source port composition.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * enable -- enable or disable source port compare
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setSpSel(
+ const UI32_T unit,
+ const BOOL_T spsel_enable);
+
+/* FUNCTION NAME: air_lag_getSpSel
+ * PURPOSE:
+ * Get selection source port composition.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- source port compare is enable or disable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getSpSel(
+ const UI32_T unit,
+ UI32_T *ptr_state);
+
+/* FUNCTION NAME: air_lag_setPTSeed
+ * PURPOSE:
+ * Set the enable/disable for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptseed -- port trunk rand seed
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setPTSeed(
+ const UI32_T unit,
+ const UI32_T ptseed);
+
+/* FUNCTION NAME: air_lag_getPTSeed
+ * PURPOSE:
+ * Get port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptseed -- port trunk rand seed
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getPTSeed(
+ const UI32_T unit,
+ UI32_T *ptseed);
+
+
+#endif /* End of AIR_LAG_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_led.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_led.h
new file mode 100644
index 0000000..6419453
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_led.h
@@ -0,0 +1,299 @@
+/* FILE NAME: air_led.h
+ * PURPOSE:
+ * 1. Define information for air_led.c
+ * NOTES:
+ */
+
+#ifndef AIR_LED_H
+#define AIR_LED_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+#define MAX_NUM_LED_ENTITY 2
+#define UNIT_LED_BLINK_DURATION 1024
+
+typedef enum
+{
+ AIR_LED_MODE_DISABLE, /* ALL LED outputs ard disabled */
+ AIR_LED_MODE_2LED_MODE0, /* 2 LED pins are enabled. Active high.
+ LED 0: Link.
+ LED 1: Activity. */
+ AIR_LED_MODE_2LED_MODE1, /* 2 LED pins are enabled. Active high.
+ LED 0: Link 1000 Activity.
+ LED 1: Link 100 Activity. */
+ AIR_LED_MODE_2LED_MODE2, /* 2 LED pins are enabled. Active high.
+ LED 0: Link 1000 Activity.
+ LED 1: Link 10/100 Activity. */
+ AIR_LED_MODE_USER_DEFINE, /* LED functions of each pin are user-defined */
+ AIR_LED_MODE_LAST
+}AIR_LED_MODE_T;
+
+typedef enum
+{
+ AIR_LED_BLK_DUR_32M, /* Blink duration: 32 ms */
+ AIR_LED_BLK_DUR_64M, /* Blink duration: 64 ms */
+ AIR_LED_BLK_DUR_128M, /* Blink duration: 128 ms */
+ AIR_LED_BLK_DUR_256M, /* Blink duration: 256 ms */
+ AIR_LED_BLK_DUR_512M, /* Blink duration: 512 ms */
+ AIR_LED_BLK_DUR_1024M, /* Blink duration: 1024 ms */
+ AIR_LED_BLK_DUR_LAST
+}AIR_LED_BLK_DUR_T;
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef struct AIR_LED_ON_EVT_S
+{
+ BOOL_T link_1000m; /* Link 1000M */
+ BOOL_T link_100m; /* Link 100M */
+ BOOL_T link_10m; /* Link 10M */
+ BOOL_T link_dn; /* Link Down */
+ BOOL_T fdx; /* Full Duplex */
+ BOOL_T hdx; /* Half Duplex */
+ BOOL_T force; /* Force on (logic 1) */
+}AIR_LED_ON_EVT_T;
+
+typedef struct AIR_LED_BLK_EVT_S
+{
+ BOOL_T tx_act_1000m; /* 1000Mbps TX Activity */
+ BOOL_T rx_act_1000m; /* 1000Mbps RX Activity */
+ BOOL_T tx_act_100m; /* 100Mbps TX Activity */
+ BOOL_T rx_act_100m; /* 100Mbps RX Activity */
+ BOOL_T tx_act_10m; /* 10Mbps TX Activity */
+ BOOL_T rx_act_10m; /* 10Mbps RX Activity */
+ BOOL_T cls; /* Collision */
+ BOOL_T rx_crc; /* Rx CRC Error */
+ BOOL_T rx_idle; /* Rx Idle Error */
+ BOOL_T force; /* Force blinks (logic 1) */
+}AIR_LED_BLK_EVT_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_led_setMode
+ * PURPOSE:
+ * Set the LED processing mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Setting mode of LED
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setMode(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_LED_MODE_T mode);
+
+/* FUNCTION NAME:air_led_getMode
+ * PURPOSE:
+ * Get the LED processing mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_mode -- Setting mode of LED
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getMode(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_LED_MODE_T *ptr_mode);
+
+/* FUNCTION NAME: air_led_setState
+ * PURPOSE:
+ * Set the enable state for a specific LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * state -- TRUE: Enable
+ * FALSE: Disable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setState(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_led_getState
+ * PURPOSE:
+ * Get the enable state for a specific LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ *
+ * OUTPUT:
+ * ptr_state -- TRUE: Enable
+ * FALSE: Disable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getState(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ BOOL_T *ptr_state);
+
+/* FUNCTION NAME: air_led_setUsrDef
+ * PURPOSE:
+ * Set the user-defined configuration of a speficic LED.
+ * It only work when air_led_setState() set to AIR_LED_MODE_USER_DEFINE.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * polar -- LOW: Active low
+ * HIGH: Active high
+ * on_evt -- AIR_LED_ON_EVT_T
+ * LED turns on if any event is detected
+ * blk_evt -- AIR_LED_BLK_EVT_T
+ * LED blinks blink if any event is detected
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setUsrDef(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ const BOOL_T polar,
+ const AIR_LED_ON_EVT_T on_evt,
+ const AIR_LED_BLK_EVT_T blk_evt);
+
+/* FUNCTION NAME: air_led_getUsrDef
+ * PURPOSE:
+ * Get the user-defined configuration of a speficic LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * OUTPUT:
+ * ptr_polar -- LOW: Active low
+ * HIGH: Active high
+ * ptr_on_evt -- AIR_LED_ON_EVT_T
+ * LED turns on if any event is detected
+ * ptr_blk_evt -- AIR_LED_BLK_EVT_T
+ * LED blinks if any event is detected
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getUsrDef(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ BOOL_T *ptr_polar,
+ AIR_LED_ON_EVT_T *ptr_on_evt,
+ AIR_LED_BLK_EVT_T *ptr_blk_evt);
+
+/* FUNCTION NAME: air_led_setBlkTime
+ * PURPOSE:
+ * Set the Blinking duration of a speficic LED.
+ * It only work when air_led_setState() set to AIR_LED_MODE_USER_DEFINE.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * dur -- Blink duration
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setBlkTime(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_LED_BLK_DUR_T dur);
+
+/* FUNCTION NAME: air_led_getBlkTime
+ * PURPOSE:
+ * Get the Blinking duration of a speficic LED.
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_dur -- Blink duration
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getBlkTime(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_LED_BLK_DUR_T *ptr_dur);
+
+#endif /* End of AIR_LED_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mib.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mib.h
new file mode 100644
index 0000000..6ce0323
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mib.h
@@ -0,0 +1,250 @@
+/* FILE NAME: air_mib.h
+ * PURPOSE:
+ * Define the MIB counter function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_MIB_H
+#define AIR_MIB_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#define MIB_ALL_ITEM 0xFFFFFFFF
+#define AIR_MIB_MAX_ACL_EVENT_NUM (64)
+#define CSR_ACL_MIB_SEL_OFFSET (4)
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+typedef struct AIR_MIB_CNT_TX_S
+{
+ UI32_T TDPC; /* TX Drop Packet */
+ UI32_T TCRC; /* TX CRC Packet */
+ UI32_T TUPC; /* TX Unicast Packet */
+ UI32_T TMPC; /* TX Multicast Packet */
+ UI32_T TBPC; /* TX Broadcast Packet */
+ UI32_T TCEC; /* TX Collision Event Count */
+ UI32_T TSCEC; /* TX Single Collision Event Count */
+ UI32_T TMCEC; /* TX Multiple Conllision Event Count */
+ UI32_T TDEC; /* TX Deferred Event Count */
+ UI32_T TLCEC; /* TX Late Collision Event Count */
+ UI32_T TXCEC; /* TX Excessive Collision Event Count */
+ UI32_T TPPC; /* TX Pause Packet */
+ UI32_T TL64PC; /* TX Packet Length 64 bytes */
+ UI32_T TL65PC; /* TX Packet Length 65 ~ 127 bytes */
+ UI32_T TL128PC; /* TX Packet Length 128 ~ 255 bytes */
+ UI32_T TL256PC; /* TX Packet Length 256 ~ 511 bytes */
+ UI32_T TL512PC; /* TX Packet Length 512 ~ 1023 bytes */
+ UI32_T TL1024PC; /* TX Packet Length 1024 ~ 1518 bytes */
+ UI32_T TL1519PC; /* TX Packet Length 1519 ~ max bytes */
+ UI32_T TODPC; /* TX Oversize Drop Packet */
+ UI64_T TOC; /* TX Octets good or bad packtes determined by TX_OCT_CNT_GOOD or TX_OCT_CNT_BAD(64 bit-width)*/
+ UI64_T TOC2; /* TX Octets bad packets (64 bit-width)*/
+}AIR_MIB_CNT_TX_T;
+
+typedef struct AIR_MIB_CNT_RX_S
+{
+ UI32_T RDPC; /* RX Drop Packet */
+ UI32_T RFPC; /* RX filtering Packet */
+ UI32_T RUPC; /* RX Unicast Packet */
+ UI32_T RMPC; /* RX Multicast Packet */
+ UI32_T RBPC; /* RX Broadcast Packet */
+ UI32_T RAEPC; /* RX Alignment Error Packet */
+ UI32_T RCEPC; /* RX CRC Packet */
+ UI32_T RUSPC; /* RX Undersize Packet */
+ UI32_T RFEPC; /* RX Fragment Error Packet */
+ UI32_T ROSPC; /* RX Oversize Packet */
+ UI32_T RJEPC; /* RX Jabber Error Packet */
+ UI32_T RPPC; /* RX Pause Packet */
+ UI32_T RL64PC; /* RX Packet Length 64 bytes */
+ UI32_T RL65PC; /* RX Packet Length 65 ~ 127 bytes */
+ UI32_T RL128PC; /* RX Packet Length 128 ~ 255 bytes */
+ UI32_T RL256PC; /* RX Packet Length 256 ~ 511 bytes */
+ UI32_T RL512PC; /* RX Packet Length 512 ~ 1023 bytes */
+ UI32_T RL1024PC; /* RX Packet Length 1024 ~ 1518 bytes */
+ UI32_T RL1519PC; /* RX Packet Length 1519 ~ max bytes */
+ UI32_T RCDPC; /* RX_CTRL Drop Packet */
+ UI32_T RIDPC; /* RX Ingress Drop Packet */
+ UI32_T RADPC; /* RX ARL Drop Packet */
+ UI32_T FCDPC; /* FLow Control Drop Packet */
+ UI32_T WRDPC; /* WRED Drop Packtet */
+ UI32_T MRDPC; /* Mirror Drop Packet */
+ UI32_T SFSPC; /* RX sFlow Sampling Packet */
+ UI32_T SFTPC; /* Rx sFlow Total Packet */
+ UI32_T RXC_DPC; /* Port Control Drop Packet */
+ UI64_T ROC; /* RX Octets good or bad packtes determined by TX_OCT_CNT_GOOD or TX_OCT_CNT_BAD (64 bit-width)*/
+ UI64_T ROC2; /* RX Octets bad packets (64 bit-width)*/
+
+}AIR_MIB_CNT_RX_T;
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_mib_setEnable
+ * PURPOSE:
+ * Enable or Disable mib count fucntion.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * mib_en -- enable or disable mib_en
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_setEnable(
+ const UI32_T unit,
+ const BOOL_T mib_en);
+/* FUNCTION NAME: air_mib_getEnable
+ * PURPOSE:
+ * Enable or Disable mib count fucntion.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * mib_en -- enable or disable mib_en
+
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_getEnable(
+ const UI32_T unit,
+ BOOL_T *mib_en);
+
+/* FUNCTION NAME: air_mib_clear
+ * PURPOSE:
+ * Clear all counters of all MIB counters.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_clear(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_mib_clear_by_port
+ * PURPOSE:
+ * Clear all counters of all MIB counters.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- clear port number
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_clear_by_port(
+ const UI32_T unit,
+ const UI32_T port);
+
+/* FUNCTION NAME: air_mib_clearAclEvent
+ * PURPOSE:
+ * Clear all counters of ACL event
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+
+/* FUNCTION NAME: air_mib_get
+ * PURPOSE:
+ * Get the structure of MIB counter for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_rx_mib -- MIB Counters of Rx Event
+ * ptr_tx_mib -- MIB Counters of Tx Event
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_get(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_MIB_CNT_RX_T *ptr_rx_mib,
+ AIR_MIB_CNT_TX_T *ptr_tx_mib);
+
+AIR_ERROR_NO_T
+air_mib_clearAclEvent(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_mib_getAclEvent
+ * PURPOSE:
+ * Get the total number of ACL event occurred.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * idx -- Index of ACL event
+ *
+ * OUTPUT:
+ * ptr_cnt -- The total number of ACL event occured
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_getAclEvent(
+ const UI32_T unit,
+ const UI32_T idx,
+ UI32_T *ptr_cnt);
+
+#endif /* End of AIR_MIB_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mirror.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mirror.h
new file mode 100644
index 0000000..2bef998
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_mirror.h
@@ -0,0 +1,202 @@
+/* FILE NAME: air_mirror.h
+ * PURPOSE:
+ * Define the port mirror function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_MIRROR_H
+#define AIR_MIRROR_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define AIR_MAX_MIRROR_SESSION (2)
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* mirror session */
+typedef struct AIR_MIR_SESSION_S
+{
+#define AIR_MIR_SESSION_FLAGS_ENABLE (1U << 0)
+#define AIR_MIR_SESSION_FLAGS_DIR_TX (1U << 1)
+#define AIR_MIR_SESSION_FLAGS_DIR_RX (1U << 2)
+#define AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG (1U << 3)
+
+ /* flags refer to AIR_MIR_SESSION_FLAGS_XXX */
+ UI32_T flags;
+ UI32_T dst_port;
+ UI32_T src_port;
+} AIR_MIR_SESSION_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_mir_addSession
+* PURPOSE:
+* This API is used to add or set a mirror session.
+* INPUT:
+* unit -- Device unit number
+* session_id -- The session information
+* ptr_session -- The session information
+* OUTPUT:
+* None
+*
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_addSession(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const AIR_MIR_SESSION_T *ptr_session);
+
+/* FUNCTION NAME: air_mir_delSession
+* PURPOSE:
+* This API is used to delete a mirror session.
+* INPUT:
+* unit -- Device unit number
+* session_id -- The session information
+* OUTPUT:
+* None
+*
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_delSession(
+ const UI32_T unit,
+ const UI32_T session_id);
+
+
+/* FUNCTION NAME: air_mir_getSession
+* PURPOSE:
+* This API is used to get mirror session information.
+* INPUT:
+* unit -- Device unit number
+* session_id -- The session information
+* OUTPUT:
+* ptr_session -- The information of this session to be obtained
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_getSession(
+ const UI32_T unit,
+ const UI32_T session_id,
+ AIR_MIR_SESSION_T *ptr_session);
+
+
+/* FUNCTION NAME: air_mir_setSessionAdminMode
+* PURPOSE:
+* This API is used to set mirror session state
+* INPUT:
+* unit -- Device unit number
+* session_id -- mirror session id
+* state -- FALSE: disable
+* TRUE: enable
+* OUTPUT:
+* None
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_setSessionAdminMode(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const BOOL_T state);
+
+
+/* FUNCTION NAME: air_mir_getSessionAdminMode
+* PURPOSE:
+* This API is used to get mirror session state
+* INPUT:
+* unit -- Device unit number
+* session_id -- mirror session id
+* OUTPUT:
+* state -- FALSE: disable
+* TRUE: enable
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_getSessionAdminMode(
+ const UI32_T unit,
+ const UI32_T session_id,
+ BOOL_T *state);
+
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_mir_setMirrorPort
+* PURPOSE:
+* This API is used to set mirror port mirroring type
+* INPUT:
+* unit -- Device unit number
+* session_id -- mirror session id
+* ptr_session -- The session information
+* OUTPUT:
+* None
+*
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_setMirrorPort(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const AIR_MIR_SESSION_T *ptr_session);
+
+
+/* FUNCTION NAME: air_mir_getMirrorPort
+* PURPOSE:
+* This API is used to get mirror port mirroring type
+* INPUT:
+* unit -- Device unit number
+* session_id -- mirror session id
+* OUTPUT:
+* ptr_session -- The information of this session to be obtained
+* RETURN:
+* AIR_E_OK
+* AIR_E_BAD_PARAMETER
+*
+* NOTES:
+* None
+*/
+AIR_ERROR_NO_T
+air_mir_getMirrorPort(
+ const UI32_T unit,
+ const UI32_T session_id,
+ AIR_MIR_SESSION_T *ptr_session);
+
+
+#endif /* End of AIR_MIRROR_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_port.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_port.h
new file mode 100644
index 0000000..a8745eb
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_port.h
@@ -0,0 +1,963 @@
+/* FILE NAME: air_port.h
+ * PURPOSE:
+ * Define port function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_PORT_H
+#define AIR_PORT_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#define AIR_MAX_NUM_OF_UNIT (1)
+#define AIR_DST_DEFAULT_PORT (31)
+#define AIR_PORT_TX (0x00)
+#define AIR_PORT_RX (0x01)
+#define AIR_MAX_NUM_OF_PORTS (7)
+#define AIR_MAX_NUM_OF_GIGA_PORTS (5)
+#define AIR_SGMII_PORT_OFFSET_BEGIN (5)
+#define AIR_SGMII_PORT_OFFSET_END (6)
+#define AIR_ALL_PORT_BITMAP (0x7F)
+
+/* Definition of Power Saving mode */
+#define AIR_PORT_PS_LINKSTATUS (0x1 << 0)
+#define AIR_PORT_PS_EEE (0x1 << 1)
+#define AIR_PORT_PS_MASK (0x3)
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+/* AIR_PORT_BITMAP_T is the data type for physical port bitmap. */
+#define AIR_BITMAP_SIZE(bit_num) ((((bit_num) - 1) / AIR_MAX_NUM_OF_PORTS) + 1)
+#define AIR_PORT_BITMAP_SIZE AIR_BITMAP_SIZE(AIR_MAX_NUM_OF_PORTS)
+typedef UI32_T AIR_PORT_BITMAP_T[AIR_PORT_BITMAP_SIZE];
+
+#define AIR_INVALID_ID (0xFFFFFFFF)
+#define AIR_PORT_INVALID (AIR_INVALID_ID)
+
+/* Definition of SGMII mode */
+typedef enum
+{
+ AIR_PORT_SGMII_MODE_AN,
+ AIR_PORT_SGMII_MODE_FORCE,
+ AIR_PORT_SGMII_MODE_LAST
+}AIR_PORT_SGMII_MODE_T;
+
+/* Definition of port speed */
+typedef enum
+{
+ AIR_PORT_SPEED_10M,
+ AIR_PORT_SPEED_100M,
+ AIR_PORT_SPEED_1000M,
+ AIR_PORT_SPEED_2500M,
+ AIR_PORT_SPEED_LAST
+}AIR_PORT_SPEED_T;
+
+typedef enum
+{
+ AIR_PORT_DUPLEX_HALF,
+ AIR_PORT_DUPLEX_FULL,
+ AIR_PORT_DUPLEX_LAST
+}AIR_PORT_DUPLEX_T;
+
+typedef enum
+{
+ AIR_PORT_LINK_DOWN,
+ AIR_PORT_LINK_UP,
+ AIR_PORT_LINK_LAST
+}AIR_PORT_LINK_T;
+
+/* Definition of Smart speed down will occur after AN failed how many times */
+typedef enum
+{
+ AIR_PORT_SSD_2T,
+ AIR_PORT_SSD_3T,
+ AIR_PORT_SSD_4T,
+ AIR_PORT_SSD_5T,
+ AIR_PORT_SSD_LAST
+}AIR_PORT_SSD_T;
+
+typedef enum
+{
+ AIR_PORT_VLAN_MODE_PORT_MATRIX = 0, /* Port matrix mode */
+ AIR_PORT_VLAN_MODE_FALLBACK, /* Fallback mode */
+ AIR_PORT_VLAN_MODE_CHECK, /* Check mode */
+ AIR_PORT_VLAN_MODE_SECURITY, /* Security mode */
+ AIR_PORT_VLAN_MODE_LAST
+} AIR_PORT_VLAN_MODE_T;
+
+/* Definition of AN Advertisement Register */
+typedef struct AIR_AN_ADV_S
+{
+ BOOL_T advCap10HDX; /* Advertises 10 BASE-T HDX */
+ BOOL_T advCap10FDX; /* Advertises 10 BASE-T FDX */
+ BOOL_T advCap100HDX; /* Advertises 100 BASE-T HDX */
+ BOOL_T advCap100FDX; /* Advertises 100 BASE-T FDX */
+ BOOL_T advCap1000FDX; /* Advertises 1000 BASE-T FDX */
+ BOOL_T advPause; /* Advertieses Asynchronous Pause */
+}AIR_AN_ADV_T;
+
+/* Definition of Link Status of a specific port */
+typedef struct AIR_PORT_STATUS_S
+{
+ BOOL_T link;
+ BOOL_T duplex;
+ UI32_T speed;
+}AIR_PORT_STATUS_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+/* FUNCTION NAME: air_port_setPortMatrix
+ * PURPOSE:
+ * Set port matrix from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ * port_bitmap -- Matrix port bitmap
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_setPortMatrix(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T port_bitmap);
+
+/* FUNCTION NAME: air_port_getPortMatrix
+ * PURPOSE:
+ * Get port matrix from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ *
+ * OUTPUT:
+ * p_port_bitmap -- Matrix port bitmap
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_getPortMatrix(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *p_port_bitmap);
+
+/* FUNCTION NAME: air_port_setVlanMode
+ * PURPOSE:
+ * Set port-based vlan mechanism from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ * mode -- Port vlan mode
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_setVlanMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_PORT_VLAN_MODE_T mode);
+
+/* FUNCTION NAME: air_port_getVlanMode
+ * PURPOSE:
+ * Get port-based vlan mechanism from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ *
+ * OUTPUT:
+ * p_mode -- Port vlan mode
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_getVlanMode(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_VLAN_MODE_T *p_mode);
+
+/* FUNCTION NAME: air_port_setAnMode
+ * PURPOSE:
+ * Set the auto-negotiation mode for a specific port.(Auto or Forced)
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setAnMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_port_getAnMode
+ * PURPOSE:
+ * Get the auto-negotiation mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getAnMode(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_state);
+
+/* FUNCTION NAME: air_port_setLocalAdvAbility
+ * PURPOSE:
+ * Set the auto-negotiation advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * adv -- AN advertisement setting
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setLocalAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_AN_ADV_T adv);
+
+/* FUNCTION NAME: air_port_getLocalAdvAbility
+ * PURPOSE:
+ * Get the auto-negotiation advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_adv -- AN advertisement setting
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getLocalAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_AN_ADV_T *ptr_adv);
+
+/* FUNCTION NAME: air_port_getRemoteAdvAbility
+ * PURPOSE:
+ * Get the auto-negotiation remote advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_lp_adv -- AN advertisement of link partner
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getRemoteAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_AN_ADV_T *ptr_lp_adv);
+
+/* FUNCTION NAME: air_port_setSpeed
+ * PURPOSE:
+ * Set the speed for a specific port.
+ * This setting is used on force mode only.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M:1Gbps
+ * AIR_PORT_SPEED_2500M:2.5Gbps (Port5, Port6)
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSpeed(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T speed);
+
+/* FUNCTION NAME: air_port_getSpeed
+ * PURPOSE:
+ * Get the speed for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M:1Gbps
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSpeed(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_speed);
+
+/* FUNCTION NAME: air_port_setDuplex
+ * PURPOSE:
+ * Get the duplex for a specific port.
+ * This setting is used on force mode only.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * duplex -- AIR_PORT_DUPLEX_HALF
+ * AIR_PORT_DUPLEX_FULL
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setDuplex(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T duplex);
+
+/* FUNCTION NAME: air_port_getDuplex
+ * PURPOSE:
+ * Get the duplex for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_duplex -- AIR_PORT_DUPLEX_HALF
+ * AIR_PORT_DUPLEX_FULL
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getDuplex(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_duplex);
+
+/* FUNCTION NAME: air_port_getLink
+ * PURPOSE:
+ * Get the physical link status for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_ps -- AIR_PORT_STATUS_T
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getLink(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_STATUS_T *ptr_ps);
+
+/* FUNCTION NAME: air_port_setBckPres
+ * PURPOSE:
+ * Set the back pressure configuration for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * bckPres -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setBckPres(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T bckPres);
+
+/* FUNCTION NAME: air_port_getBckPres
+ * PURPOSE:
+ * Get the back pressure configuration for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_bckPres -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getBckPres(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_bckPres);
+
+/* FUNCTION NAME: air_port_setFlowCtrl
+ * PURPOSE:
+ * Set the flow control configuration for specific port.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0 - 6)
+ * dir -- Directions of AIR_PORT_TX or AIR_PORT_RX
+ * fc_en -- TRUE: Enable select port flow control
+ * FALSE:Disable select port flow control
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setFlowCtrl(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T dir,
+ const BOOL_T fc_en);
+
+/* FUNCTION NAME: air_port_getFlowCtrl
+ * PURPOSE:
+ * Get the flow control configuration for specific port.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_PORT_TX
+ * AIR_PORT_RX
+ * OUTPUT:
+ * ptr_fc_en -- FALSE: Port flow control disable
+ * TRUE: Port flow control enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getFlowCtrl(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T dir,
+ BOOL_T *ptr_fc_en);
+
+/* FUNCTION NAME: air_port_setJumbo
+ * PURPOSE:
+ * Set accepting jumbo frmes with specificied size.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pkt_len -- Select max packet length
+ * RX_PKT_LEN_1518
+ * RX_PKT_LEN_1536
+ * RX_PKT_LEN_1552
+ * RX_PKT_LEN_MAX_JUMBO
+ * frame_len -- Select max lenght of jumbo frames
+ * Range : 2 - 15
+ * Units : K Bytes
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setJumbo(
+ const UI32_T unit,
+ const UI32_T pkt_len,
+ const UI32_T frame_len);
+
+/* FUNCTION NAME: air_port_getJumbo
+ * PURPOSE:
+ * Get accepting jumbo frmes with specificied size.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ *
+ * OUTPUT:
+ * ptr_pkt_len -- Select max packet length
+ * RX_PKT_LEN_1518
+ * RX_PKT_LEN_1536
+ * RX_PKT_LEN_1552
+ * RX_PKT_LEN_MAX_JUMBO
+ * ptr_frame_len -- Select max lenght of jumbo frames
+ * Range : 2 - 15
+ * Units : K Bytes
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getJumbo(
+ const UI32_T unit,
+ UI32_T *ptr_pkt_len,
+ UI32_T *ptr_frame_len);
+
+
+/* FUNCTION NAME: air_port_setPsMode
+ * PURPOSE:
+ * Set the power saving mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Bit-map:
+ * AIR_PORT_PS_LINKSTATUS
+ * AIR_PORT_PS_EEE
+ * FALSE: Disable / TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setPsMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T mode);
+
+/* FUNCTION NAME: air_port_getPsMode
+ * PURPOSE:
+ * Get the power saving mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * OUTPUT:
+ * ptr_mode -- Bit-map:
+ * AIR_PORT_PS_LINKSTATUS
+ * AIR_PORT_PS_EEE
+ * FALSE: Disable / TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getPsMode(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_mode);
+
+/* FUNCTION NAME: air_port_setSmtSpdDwn
+ * PURPOSE:
+ * Set Smart speed down feature for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * time -- AIR_PORT_SSD_2T
+ * AIR_PORT_SSD_3T
+ * AIR_PORT_SSD_4T
+ * AIR_PORT_SSD_5T
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSmtSpdDwn(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state,
+ const UI32_T time);
+
+/* FUNCTION NAME: air_port_getSmtSpdDwn
+ * PURPOSE:
+ * Get Smart speed down feature for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * ptr_time -- AIR_PORT_SSD_2T
+ * AIR_PORT_SSD_3T
+ * AIR_PORT_SSD_4T
+ * AIR_PORT_SSD_5T
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSmtSpdDwn(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state,
+ UI32_T *ptr_time);
+
+/* FUNCTION NAME: air_port_setEnable
+ * PURPOSE:
+ * Set powerdown state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state);
+
+/* FUNCTION NAME: air_port_getEnable
+ * PURPOSE:
+ * Get powerdown state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state);
+
+/* FUNCTION NAME: air_port_setSpTag
+ * PURPOSE:
+ * Set special tag state of a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * sptag_en -- TRUE: Enable special tag
+ * FALSE: Disable special tag
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSpTag(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T sptag_en);
+
+/* FUNCTION NAME: air_port_getSpTag
+ * PURPOSE:
+ * Get special tag state of a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * OUTPUT:
+ * ptr_sptag_en -- TRUE: Special tag enable
+ * FALSE: Special tag disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSpTag(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_sptag_en);
+
+/* FUNCTION NAME: air_port_set5GBaseRModeEnable
+ * PURPOSE:
+ * Set the port5 5GBase-R mode enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_set5GBaseRModeEn(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_port_setHsgmiiModeEnable
+ * PURPOSE:
+ * Set the port5 HSGMII mode enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setHsgmiiModeEn(
+ const UI32_T unit);
+
+/* FUNCTION NAME: air_port_setSgmiiMode
+ * PURPOSE:
+ * Set the port5 SGMII mode for AN or force
+ *
+ * INPUT:
+ * unit -- Device ID
+ * mode -- AIR_PORT_SGMII_MODE_AN
+ * AIR_PORT_SGMII_MODE_FORCE
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M: 1Gbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSgmiiMode(
+ const UI32_T unit,
+ const UI32_T mode,
+ const UI32_T speed);
+
+
+/* FUNCTION NAME: air_port_setRmiiMode
+ * PURPOSE:
+ * Set the port5 RMII mode for 100Mbps or 10Mbps
+ *
+ * INPUT:
+ * unit -- Device ID
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setRmiiMode(
+ const UI32_T unit,
+ const UI32_T speed);
+
+/* FUNCTION NAME: air_port_setRgmiiMode
+ * PURPOSE:
+ * Set the port5 RGMII mode for 1Gbps or 100Mbps or 10Mbps
+ *
+ * INPUT:
+ * unit -- Device ID
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M: 1Gbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setRgmiiMode(
+ const UI32_T unit,
+ const UI32_T speed);
+
+#endif /* AIR_PORT_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_qos.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_qos.h
new file mode 100644
index 0000000..e1eaf3a
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_qos.h
@@ -0,0 +1,590 @@
+/* FILE NAME: air_qos.h
+* PURPOSE:
+ * Define the Quailty of Service function in AIR SDK.
+*
+* NOTES:
+* None
+*/
+
+#ifndef AIR_QOS_H
+#define AIR_QOS_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define AIR_QOS_MAX_TOKEN (128)
+#define AIR_QOS_MAX_CIR (80001)
+#define AIR_QOS_TOKEN_PERIOD_1_4MS (5)
+#define AIR_QOS_TOKEN_PERIOD_4MS (9)
+#define AIR_QOS_L1_RATE_LIMIT (0x18)
+#define AIR_QOS_L2_RATE_LIMIT (0x04)
+#define AIR_QOS_QUEUE_PIM_WIDTH (3)
+#define AIR_QOS_QUEUE_PIM_MASK (7)
+#define AIR_QOS_QUEUE_DEFAULT_VAL (0x222227)
+#define AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT (6)
+#define AIR_QOS_QUEUE_TRUST_MID_WEIGHT (5)
+#define AIR_QOS_QUEUE_TRUST_LOW_WEIGHT (4)
+#define AIR_QOS_SHAPER_RATE_MAX_EXP (4)
+#define AIR_QOS_SHAPER_RATE_MAX_MAN (0x1ffff)
+#define AIR_QOS_SHAPER_RATE_MIN_WEIGHT (1)
+#define AIR_QOS_SHAPER_RATE_MAX_WEIGHT (128)
+#define AIR_QOS_QUEUE_0 (0)
+#define AIR_QOS_QUEUE_1 (1)
+#define AIR_QOS_QUEUE_2 (2)
+#define AIR_QOS_QUEUE_3 (3)
+#define AIR_QOS_QUEUE_4 (4)
+#define AIR_QOS_QUEUE_5 (5)
+#define AIR_QOS_QUEUE_6 (6)
+#define AIR_QOS_QUEUE_7 (7)
+#define AIR_QOS_MIN_TRAFFIC_ARBITRATION_SCHEME_SP (1)
+#define AIR_QOS_MIN_TRAFFIC_ARBITRATION_SCHEME_WRR (0)
+#define AIR_QOS_MAX_TRAFFIC_ARBITRATION_SCHEME_SP (1)
+#define AIR_QOS_MAX_TRAFFIC_ARBITRATION_SCHEME_WFQ (0)
+#define AIR_QOS_MAX_EXCESS_SP (1)
+#define AIR_QOS_MAX_EXCESS_DROP (0)
+#define AIR_QOS_QUEUE_MAX_NUM (8)
+#define AIR_QOS_QUEUE_DSCP_MAX_NUM (64)
+#define AIR_MAX_NUM_OF_QUEUE (8) /*need to be replaced by AIR_QOS_QUEUE_MAX_NUM*/
+
+#define AIR_QOS_SHAPER_NOSETTING (0xffffffff)
+#define AIR_QOS_SHAPER_RATE_MIN_WEIGHT (1)
+#define AIR_QOS_SHAPER_RATE_MAX_WEIGHT (128)
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef enum
+{
+ AIR_QOS_SCH_MODE_SP,
+ AIR_QOS_SCH_MODE_WRR,
+ AIR_QOS_SCH_MODE_WFQ,
+ AIR_QOS_SCH_MODE_LAST,
+} AIR_QOS_SCH_MODE_T;
+
+typedef union AIR_QOS_SHAPER_MIN_S
+{
+ struct
+ {
+ UI32_T min_rate_man :17;
+ UI32_T min_reserve :2;
+ UI32_T min_rate_en :1;
+ UI32_T min_rate_exp :4;
+ UI32_T min_weight :7;
+ UI32_T min_sp_wrr_q :1;
+ }raw;
+ UI32_T byte;
+}AIR_QOS_SHAPER_MIN_T;
+
+typedef union AIR_QOS_SHAPER_MAX_S
+{
+ struct
+ {
+ UI32_T max_rate_man :17;
+ UI32_T max_reserve :1;
+ UI32_T max_excess_en :1;
+ UI32_T max_rate_en :1;
+ UI32_T max_rate_exp :4;
+ UI32_T max_weight :7;
+ UI32_T max_sp_wfq_q :1;
+ }raw;
+ UI32_T byte;
+}AIR_QOS_SHAPER_MAX_T;
+
+typedef enum
+{
+ /* The packet priority is based on port's priority. */
+ AIR_QOS_TRUST_MODE_PORT,
+
+ /*
+ * The precedence of packet priority is based on 802.1p,
+ * then port's priority.
+ */
+ AIR_QOS_TRUST_MODE_1P_PORT,
+
+ /*
+ * The precedence of packet priority is based on DSCP,
+ * then port's priority.
+ */
+ AIR_QOS_TRUST_MODE_DSCP_PORT,
+
+ /*
+ * The precedence of packet priority is based on DSCP, 802.1p,
+ * then port's priority.
+ */
+ AIR_QOS_TRUST_MODE_DSCP_1P_PORT,
+ AIR_QOS_TRUST_MODE_LAST
+} AIR_QOS_TRUST_MODE_T;
+
+typedef union AIR_QOS_QUEUE_UPW_S
+{
+ struct
+ {
+ UI32_T csr_acl_weight :3;
+ UI32_T :1;
+ UI32_T csr_stag_weight :3;/*Not use yet*/
+ UI32_T :1;
+ UI32_T csr_1p_weight :3;
+ UI32_T :1;
+ UI32_T csr_dscp_weight :3;
+ UI32_T :1;
+ UI32_T csr_port_weight :3;
+ UI32_T :1;
+ UI32_T csr_arl_weight :3;
+ UI32_T :9;
+ }raw;
+ UI32_T byte;
+}AIR_QOS_QUEUE_UPW_T;
+
+typedef union AIR_QOS_QUEUE_PEM_S
+{
+ struct
+ {
+ UI32_T csr_dscp_pri_l :6;/*Not use yet*/
+ UI32_T csr_que_lan_l :2;/*Not use yet*/
+ UI32_T csr_que_cpu_l :3;
+ UI32_T csr_tag_pri_l :3;/*Not use yet*/
+ UI32_T :2;
+ UI32_T csr_dscp_pri_h :6;/*Not use yet*/
+ UI32_T csr_que_lan_h :2;/*Not use yet*/
+ UI32_T csr_que_cpu_h :3;
+ UI32_T csr_tag_pri_h :3;/*Not use yet*/
+ UI32_T :2;
+ }raw;
+ UI32_T byte;
+}AIR_QOS_QUEUE_PEM_T;
+
+typedef enum
+{
+ AIR_QOS_RATE_DIR_INGRESS,
+ AIR_QOS_RATE_DIR_EGRESS,
+ AIR_QOS_RATE_DIR_LAST
+} AIR_QOS_RATE_DIR_T;
+
+typedef struct AIR_RATE_LIMIT_S
+{
+#define AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_INGRESS (1U << 0)
+#define AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_EGRESS (1U << 1)
+ UI32_T flags;
+
+ /*
+ * The limit cover up to 2.5G
+ * Rate = CIR * 32kbps
+ * Range = 0..80000
+ */
+ UI32_T ingress_cir;
+ UI32_T egress_cir;
+
+ /*
+ * Bucket = Max{(CBS * 512), (CIR * 2500)} Bytes
+ * Range: 0..127
+ */
+ UI32_T ingress_cbs;
+ UI32_T egress_cbs;
+} AIR_QOS_RATE_LIMIT_CFG_T;
+
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+
+/* FUNCTION NAME: air_qos_setScheduleAlgo
+ * PURPOSE:
+ * Set schedule mode of a port queue.
+ * INPUT:
+ * unit -- Device unit number
+ * port -- Port id
+ * queue -- Queue id
+ * sch_mode -- AIR_QOS_SCH_MODE_T
+ * weight -- weight for WRR/WFQ
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * Weight default value is 1, only for WRR/WFQ mode
+ */
+AIR_ERROR_NO_T
+air_qos_setScheduleAlgo(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T queue,
+ const AIR_QOS_SCH_MODE_T sch_mode,
+ const UI32_T weight);
+
+
+/* FUNCTION NAME: air_qos_getScheduleAlgo
+ * PURPOSE:
+ * Get schedule mode of a port queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Port id
+ * queue -- Queue id
+ * OUTPUT:
+ * ptr_sch_mode -- AIR_QOS_SCH_MODE_T
+ * ptr_weight -- weight for WRR/WFQ
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getScheduleAlgo(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T queue,
+ AIR_QOS_SCH_MODE_T *ptr_sch_mode,
+ UI32_T *ptr_weight);
+
+/* FUNCTION NAME: air_qos_setTrustMode
+ * PURPOSE:
+ * Set qos trust mode value.
+ * INPUT:
+ * unit -- Device unit number
+ * port -.Select port number
+ * mode -- Qos support mode
+ * AIR_QOS_TRUST_MODE_T
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_qos_setTrustMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_TRUST_MODE_T mode);
+
+
+/* FUNCTION NAME: air_qos_getTrustMode
+ * PURPOSE:
+ * Get qos trust mode value.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -.Select port number
+ * OUTPUT:
+ * ptr_weight -- All Qos weight value
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getTrustMode(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_TRUST_MODE_T *const ptr_mode);
+
+/* FUNCTION NAME: air_qos_setPri2Queue
+ * PURPOSE:
+ * Set per port priority to out queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pri -- Qos pri value
+ * queue -- Qos Queue value
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setPri2Queue(
+ const UI32_T unit,
+ const UI32_T pri,
+ const UI32_T queue);
+
+/* FUNCTION NAME: air_qos_getPri2Queue
+ * PURPOSE:
+ * Get per port priority to out queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pri -- Qos pri value
+ *
+ * OUTPUT:
+ * ptr_queue -- Select out queue (0..7)
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getPri2Queue(
+ const UI32_T unit,
+ const UI32_T pri,
+ UI32_T *const ptr_queue);
+
+/* FUNCTION NAME: air_qos_setDscp2Pri
+ * PURPOSE:
+ * Set DSCP mapping to priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dscp -- Select DSCP value (0..63)
+ * priority -- Select priority (0..7)
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setDscp2Pri(
+ const UI32_T unit,
+ const UI32_T dscp,
+ const UI32_T pri);
+
+/* FUNCTION NAME: air_qos_getDscp2Pri
+ * PURPOSE:
+ * Get DSCP mapping priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dscp -- Select DSCP value (0..63)
+ *
+ * OUTPUT:
+ * ptr_pri -- Priority value (0..7)
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getDscp2Pri(
+ const UI32_T unit,
+ const UI32_T dscp,
+ UI32_T * const ptr_pri);
+
+/* FUNCTION NAME: air_qos_setRateLimitEnable
+ * PURPOSE:
+ * Enable or disable port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_QOS_RATE_DIR_INGRESS
+ * AIR_QOS_RATE_DIR_EGRESS
+ * rate_en -- TRUE: eanble rate limit
+ * FALSE: disable rate limit
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimitEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_RATE_DIR_T dir,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_qos_getRateLimitEnable
+ * PURPOSE:
+ * Get port rate limit state.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_QOS_RATE_DIR_T
+ * OUTPUT:
+ * ptr_enable -- TRUE: eanble rate limit
+ * FALSE: disable rate limit
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimitEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_RATE_DIR_T dir,
+ BOOL_T *ptr_enable);
+
+/* FUNCTION NAME: air_qos_setRateLimit
+ * PURPOSE:
+ * Set per port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * ptr_cfg -- AIR_QOS_RATE_LIMIT_CFG_T
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimit(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_RATE_LIMIT_CFG_T *ptr_cfg);
+
+/* FUNCTION NAME: air_qos_getRateLimit
+ * PURPOSE:
+ * Get per port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ *
+ * OUTPUT:
+ * ptr_cfg -- AIR_QOS_RATE_LIMIT_CFG_T
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimit(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_RATE_LIMIT_CFG_T *ptr_cfg);
+
+/* FUNCTION NAME: air_qos_setPortPriority
+ * PURPOSE:
+ * Get poer port based priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * priority -- Select port priority
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setPortPriority(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T priority);
+
+/* FUNCTION NAME: air_qos_getPortPriority
+ * PURPOSE:
+ * Set per port based priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ *
+ * OUTPUT:
+ * ptr_pri -- Get port based priority
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getPortPriority(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_pri);
+
+/* FUNCTION NAME: air_qos_setRateLimitExMngFrm
+ * PURPOSE:
+ * Set rate limit control exclude/include management frames.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dir -- AIR_RATE_DIR_INGRESS
+ * AIR_RATE_DIR_EGRESS
+ * exclude -- TRUE: Exclude management frame
+ * FALSE:Include management frame
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimitExMngFrm(
+ const UI32_T unit,
+ const AIR_QOS_RATE_DIR_T dir,
+ const BOOL_T exclude);
+
+/* FUNCTION NAME: air_qos_getRateLimitExMngFrm
+ * PURPOSE:
+ * Get rate limit control exclude/include management frames.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dir -- AIR_RATE_DIR_INGRESS
+ * AIR_RATE_DIR_EGRESS
+ * OUTPUT:
+ * ptr_exclude -- TRUE: Exclude management frame
+ * FALSE:Include management frame
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimitExMngFrm(
+ const UI32_T unit,
+ const AIR_QOS_RATE_DIR_T dir,
+ BOOL_T *ptr_exclude);
+
+#endif /* End of AIR_QOS_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_reg.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_reg.h
new file mode 100644
index 0000000..90fb8ac
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_reg.h
@@ -0,0 +1,1233 @@
+/* FILE NAME: air_reg.h
+* PURPOSE:
+* Define the chip registers in AIR SDK.
+* NOTES:
+*/
+
+#ifndef AIR_REG_H
+#define AIR_REG_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define PORT_CTRL_PORT_OFFSET (0x200)
+
+/* SYS SCU */
+#define RST_CTRL1 (0x100050c0)
+#define SYS_SW_RST_OFFT (31)
+
+/* ARL Register Base */
+#define REG_ARL_BASE_ADDRESS (0x10200000)
+
+#define AGC (0x000C)
+/* fields of AGC */
+#define AGC_TICK_SEL (0x1 << 30)
+
+#define MFC (REG_ARL_BASE_ADDRESS + 0x0010)
+/* fields of MFC */
+
+
+#define VTCR_ADDR (0x0090)
+#define VTCR_VID_OFFT (0)
+#define VTCR_VID_LENG (12)
+#define VTCR_VID_RELMASK (0x00000FFF)
+#define VTCR_VID_MASK (VTCR_VID_RELMASK << VTCR_VID_OFFT)
+#define VTCR_FUNC_OFFT (12)
+#define VTCR_FUNC_LENG (4)
+#define VTCR_FUNC_RELMASK (0x0000000F)
+#define VTCR_FUNC_MASK (VTCR_FUNC_RELMASK << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_READ_ACL_RULE (0x4 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_WRITE_ACL_RULE (0x5 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_READ_TRTCM (0x6 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_WRITE_TRTCM (0x7 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_READ_ACL_MASK (0x8 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_WRITE_ACL_MASK (0x9 << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_READ_ACL_RULE_CTRL (0xA << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_WRITE_ACL_RULE_CTRL (0xB << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_READ_ACL_RATE_CTRL (0xC << VTCR_FUNC_OFFT)
+#define VTCR_FUNC_WRITE_ACL_RATE_CTRL (0xD << VTCR_FUNC_OFFT)
+#define VTCR_IDX_INVLD_OFFT (16)
+#define VTCR_IDX_INVLD_RELMASK (0x00000001)
+#define VTCR_IDX_INVLD_MASK (VTCR_IDX_INVLD_RELMASK << VTCR_IDX_INVLD_OFFT)
+#define VTCR_BUSY_OFFT (31)
+#define VTCR_BUSY_LENG (1)
+#define VTCR_BUSY_RELMASK (0x00000001)
+#define VTCR_BUSY_MASK (VTCR_BUSY_RELMASK << VTCR_BUSY_OFFT)
+
+#define PIM_DSCP(d) (0x0058 + (4 * (d / 10)))
+
+#define UNUF (0x102000B4)
+#define UNMF (0x102000B8)
+#define BCF (0x102000BC)
+#define QRYP (0x102000D8)
+
+#define VAWD1_ADDR (0x0094)
+#define VAWD2_ADDR (0x0098)
+#define VAWD3_ADDR (0x00E0)
+#define VAWD4_ADDR (0x00E4)
+#define VAWD5_ADDR (0x00E8)
+#define VAWD6_ADDR (0x00EC)
+#define VAWD7_ADDR (0x00F0)
+#define VAWD8_ADDR (0x00F4)
+#define VAWD_ADDR(n) ((n<2)?(VAWD1_ADDR+(0x4*n)):(VAWD3_ADDR+(0x4*(n-2))))
+
+#define SCH_CTRL_BASE (0x1000)
+#define SCH_CTRL_PORT_OFFSET (0x100)
+#define MMSCR(p) (SCH_CTRL_BASE + (p * SCH_CTRL_PORT_OFFSET) + 0x90)
+#define MMSCR0(p, q) (SCH_CTRL_BASE + (p * SCH_CTRL_PORT_OFFSET) + (8 * q))
+#define MMSCR1(p, q) (SCH_CTRL_BASE + (p * SCH_CTRL_PORT_OFFSET) + (8 * q) + 0x04)
+#define MMSCR2(p, q) (SCH_CTRL_BASE + (p * SCH_CTRL_PORT_OFFSET) + (8 * q) + 0x50)
+#define MMSCR3(p, q) (SCH_CTRL_BASE + (p * SCH_CTRL_PORT_OFFSET) + (8 * q) + 0x54)
+
+/* fields of GERLCR */
+#define EGC_MFRM_EX_OFFSET (9)
+#define EGC_MFRM_EX_LENGTH (1)
+
+#define BMU_CTRL_BASE (0x1800)
+#define BMU_CTRL_PORT_OFFSET (0x100)
+
+/* fields of MMDPR */
+#define MMDPR_BASE (BMU_CTRL_BASE + 0xC)
+#define MMDPR_PORT_OFFSET (0x100)
+#define MMDPR_COLOR_OFFSET (0x20)
+#define MMDPR_QUEUE_OFFSET (0x4)
+#define MMDPR(p,c,q) (MMDPR_BASE + (p * MMDPR_PORT_OFFSET) + (c * MMDPR_COLOR_OFFSET) + (q * MMDPR_QUEUE_OFFSET))
+#define MMDPR_EN (1 << 31)
+#define MMDPR_PR_OFFSET (24)
+#define MMDPR_PR_LENGTH (3)
+#define MMDPR_HT_OFFSET (12)
+#define MMDPR_HT_LENGTH (9)
+#define MMDPR_LT_OFFSET (0)
+#define MMDPR_LT_LENGTH (9)
+
+/* fields of GIRLCR */
+#define IGC_MFRM_EX_OFFSET (9)
+#define IGC_MFRM_EX_LENGTH (1)
+
+#define PORT_CTRL_BASE (0x10208000)
+#define PORT_CTRL_REG(p, r) (PORT_CTRL_BASE + (p) * PORT_CTRL_PORT_OFFSET + (r))
+
+#define PORTMATRIX(p) PORT_CTRL_REG(p, 0x44)
+
+#define PCR(p) PORT_CTRL_REG(p, 0x04)
+#define PCR_PORT_VLAN_OFFT (0)
+#define PCR_PORT_VLAN_LENG (2)
+#define PCR_PORT_VLAN_RELMASK (0x00000003)
+#define PCR_PORT_VLAN_MASK (PCR_PORT_VLAN_RELMASK << PCR_PORT_VLAN_OFFT)
+#define PCR_PORT_RX_MIR_OFFT (16)
+#define PCR_PORT_RX_MIR_LENG (2)
+#define PCR_PORT_TX_MIR_OFFT (20)
+#define PCR_PORT_TX_MIR_LENG (2)
+#define PCR_PORT_PRI_OFFT (24)
+#define PCR_PORT_PRI_LENG (3)
+#define PCR_PORT_PRI_RELMASK (0x00000007)
+#define PCR_PORT_PRI_MASK (PCR_PORT_PRI_RELMASK << PCR_PORT_PRI_OFFT)
+#define PCR_PORT_ACL_MIS_FWD_OFFT (4)
+#define PCR_PORT_ACL_MIS_FWD_LENG (3)
+#define PCR_PORT_ACL_MIS_FWD_RELMASK (0x00000007)
+#define PCR_PORT_ACL_MIS_FWD_MASK (PCR_PORT_ACL_MIS_FWD_RELMASK << PCR_PORT_ACL_MIS_FWD_OFFT)
+#define PCR_EG_TAG_OFFT (28)
+#define PCR_EG_TAG_LENG (2)
+#define PCR_EG_TAG_RELMASK (0x00000003)
+#define PCR_EG_TAG_MASK (PCR_EG_TAG_RELMASK << PCR_EG_TAG_OFFT)
+#define PCR_RMK_DSCP_EN (0x1000)
+#define PCR_RMK_1Q_EN (0x0800)
+
+#define PVC(p) PORT_CTRL_REG(p, 0x10)
+#define PVC_ACC_FRM_OFFT (0)
+#define PVC_ACC_FRM_LENG (2)
+#define PVC_ACC_FRM_RELMASK (0x00000003)
+#define PVC_ACC_FRM_MASK (PVC_ACC_FRM_RELMASK << PVC_ACC_FRM_OFFT)
+#define PVC_UC_LKYV_EN_OFFT (2)
+#define PVC_UC_LKYV_EN_LENG (1)
+#define PVC_UC_LKYV_EN_RELMASK (0x00000001)
+#define PVC_UC_LKYV_EN_MASK (PVC_UC_LKYV_EN_RELMASK << PVC_UC_LKYV_EN_OFFT)
+#define PVC_MC_LKYV_EN_OFFT (3)
+#define PVC_MC_LKYV_EN_LENG (1)
+#define PVC_MC_LKYV_EN_RELMASK (0x00000001)
+#define PVC_MC_LKYV_EN_MASK (PVC_MC_LKYV_EN_RELMASK << PVC_MC_LKYV_EN_OFFT)
+#define PVC_BC_LKYV_EN_OFFT (4)
+#define PVC_BC_LKYV_EN_LENG (1)
+#define PVC_BC_LKYV_EN_RELMASK (0x00000001)
+#define PVC_BC_LKYV_EN_MASK (PVC_BC_LKYV_EN_RELMASK << PVC_BC_LKYV_EN_OFFT)
+#define PVC_SPTAG_EN_OFFT (5)
+#define PVC_SPTAG_EN_LENG (1)
+#define PVC_SPTAG_EN_RELMASK (0x00000001)
+#define PVC_SPTAG_EN_MASK (PVC_SPTAG_EN_RELMASK << PVC_SPTAG_EN_OFFT)
+#define PVC_VLAN_ATTR_OFFT (6)
+#define PVC_VLAN_ATTR_LENG (2)
+#define PVC_VLAN_ATTR_RELMASK (0x00000003)
+#define PVC_VLAN_ATTR_MASK (PVC_VLAN_ATTR_RELMASK << PVC_VLAN_ATTR_OFFT)
+#define PVC_EG_TAG_OFFT (8)
+#define PVC_EG_TAG_LENG (3)
+#define PVC_EG_TAG_RELMASK (0x00000007)
+#define PVC_EG_TAG_MASK (PVC_EG_TAG_RELMASK << PVC_EG_TAG_OFFT)
+#define PVC_SPTAG_MODE_OFFT (11)
+#define PVC_SPTAG_MODE_LENG (1)
+#define PVC_STAG_VPID_OFFT (16)
+#define PVC_STAG_VPID_LENG (16)
+#define PVC_STAG_VPID_RELMASK (0x0000FFFF)
+#define PVC_STAG_VPID_MASK (PVC_STAG_VPID_RELMASK << PVC_STAG_VPID_OFFT)
+
+#define PPBV1(p) PORT_CTRL_REG(p, 0x14)
+#define PPBV1_G0_PORT_VID_OFFT (0)
+#define PPBV1_G0_PORT_VID_LENG (12)
+#define PPBV1_G0_PORT_VID_RELMASK (0x00000FFF)
+#define PPBV1_G0_PORT_VID_MASK (PPBV1_G0_PORT_VID_RELMASK << PPBV1_G0_PORT_VID_OFFT)
+
+#define PVID(p) PORT_CTRL_REG(p, 0x48)
+#define PVID_PCVID_OFFT (0)
+#define PVID_PCVID_LENG (12)
+#define PVID_PCVID_RELMASK (0x00000FFF)
+#define PVID_PCVID_MASK (PVID_PCVID_RELMASK << PVID_PCVID_OFFT)
+
+#define BSR(p) PORT_CTRL_REG(p, 0x50)
+#define BSR1(p) PORT_CTRL_REG(p, 0x54)
+#define BSR_EXT1(p) PORT_CTRL_REG(p, 0x58)
+#define BSR1_EXT1(p) PORT_CTRL_REG(p, 0x5C)
+#define BSR_EXT2(p) PORT_CTRL_REG(p, 0x60)
+#define BSR1_EXT2(p) PORT_CTRL_REG(p, 0x64)
+#define BSR_EXT3(p) PORT_CTRL_REG(p, 0x68)
+#define BSR1_EXT3(p) PORT_CTRL_REG(p, 0x6C)
+#define BSR_STORM_COUNT_MSK (0xFF)
+#define BSR_STORM_UNIT_MSK (7)
+#define BSR_STORM_UNIT_OFFT (8)
+#define BSR_STORM_RATE_BASED (0x1)
+#define BSR_STORM_DROP_EN (0x10)
+#define BSR_STORM_BCST_EN (0x2)
+#define BSR_STORM_MCST_EN (0x4)
+#define BSR_STORM_UCST_EN (0x8)
+#define BSR1_10M_COUNT_OFFT (0)
+#define BSR1_100M_COUNT_OFFT (8)
+#define BSR1_1000M_COUNT_OFFT (16)
+#define BSR1_2500M_COUNT_OFFT (24)
+
+#define PEM(p, q) (PORT_CTRL_REG(p, (0x44 + (4 * (q/2)))))
+
+#define PORT_MAC_CTRL_BASE (0x10210000)
+#define PORT_MAC_CTRL_PORT_OFFSET (0x200)
+#define PORT_MAC_CTRL_REG(p, r) (PORT_MAC_CTRL_BASE + (p) * PORT_MAC_CTRL_PORT_OFFSET + (r))
+
+#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00)
+
+#define ARL_CTRL_BASE (0x0000)
+#define CFC (0x0004)
+/* fields of CFC */
+#define CFC_MIRROR_EN_OFFSET (19)
+#define CFC_MIRROR_EN_LEN (1)
+#define CFC_MIRROR_PORT_OFFSET (16)
+#define CFC_MIRROR_PORT_LEN (3)
+#define MFC_CPU_PORT_OFFSET (8)
+#define MFC_CPU_PORT_LENGTH (5)
+#define MFC_CPU_EN_OFFSET (15)
+#define MFC_CPU_EN_LENGTH (1)
+
+
+#define ISC (0x0018)
+#define TSRA1 (0x0084)
+#define TSRA2 (0x0088)
+#define ATRD (0x008C)
+#define CPGC (0x00B0)
+
+#define PSC(p) PORT_CTRL_REG(p, 0xC)
+#define PSC_DIS_LRN_OFFSET (4)
+#define PSC_DIS_LRN_LENGTH (1)
+#define PSC_SA_CNT_EN_OFFSET (5)
+#define PSC_SA_CNT_EN_LENGTH (1)
+#define PSC_SA_CNT_LMT_OFFSET (8)
+#define PSC_SA_CNT_LMT_LENGTH (12)
+#define PSC_SA_CNT_LMT_REALMASK (0x00000FFF)
+#define PSC_SA_CNT_LMT_MASK (PSC_SA_CNT_LMT_REALMASK << PSC_SA_CNT_LMT_OFFSET)
+#define PSC_SA_CNT_LMT_MAX (0x800)
+
+/* fields of CPGC */
+#define COL_EN (0x01)
+#define COL_CLK_EN (0x02)
+
+#define CKGCR (0x10213E1C)
+#define CKG_LNKDN_GLB_STOP (0x01)
+#define CKG_LNKDN_PORT_STOP (0x02)
+
+/* fields of TRTCM*/
+#define TRTCM (ARL_CTRL_BASE + 0x009C)
+#define TRTCM_EN (1 << 31)
+
+#define ARL_TRUNK_BASE (0x10200000)
+#define PTC (ARL_TRUNK_BASE + 0x400)
+#define PTSEED (ARL_TRUNK_BASE + 0x404)
+#define PTGC (ARL_TRUNK_BASE + 0x408)
+#define PTG(g) (ARL_TRUNK_BASE + 0x40C + ((g) * 0x8 ))
+#define PTGRSTS (ARL_TRUNK_BASE + 0x44C)
+
+#define MIR (REG_ARL_BASE_ADDRESS + (0xCC))
+/* fields of MIR */
+#define MIR_MIRROR_BASE_OFFSER (8)
+#define MIR_MIRROR_EN_OFFSER(p) ((p) * MIR_MIRROR_BASE_OFFSER + 0x07)
+#define MIR_MIRROR_EN_LEN (1)
+#define MIR_MIRROR_PORT_OFFSER(p) ((p) * MIR_MIRROR_BASE_OFFSER + 0x00)
+#define MIR_MIRROR_PORT_LEN (5)
+#define MIR_MIRROR_TAG_TX_EN_OFFSER(p) ((p) * MIR_MIRROR_BASE_OFFSER + 0x06)
+#define MIR_MIRROR_TAG_TX_EN_LEN (1)
+
+/* fields of ATA1 */
+#define ATA1 (REG_ARL_BASE_ADDRESS + 0x0304)
+#define ATA1_MAC_ADDR_MSB_OFFSET (0)
+#define ATA1_MAC_ADDR_MSB_LENGTH (32)
+//#define ATA1_SAT_ADDR_OFFSET (0)
+//#define ATA1_SAT_ADDR_LENGTH (11)
+//#define ATA1_SAT_BANK_OFFSET (16)
+//#define ATA1_SAT_BANK_LENGTH (4)
+
+/* fields of ATA2 */
+#define ATA2 (REG_ARL_BASE_ADDRESS + 0x0308)
+#define ATA2_MAC_AGETIME_OFFSET (0)
+#define ATA2_MAC_AGETIME_LENGTH (9)
+#define ATA2_MAC_LIFETIME_OFFSET (9)
+#define ATA2_MAC_LIFETIME_LENGTH (1)
+#define ATA2_MAC_UNAUTH_OFFSET (10)
+#define ATA2_MAC_UNAUTH_LENGTH (1)
+#define ATA2_MAC_ADDR_LSB_OFFSET (16)
+#define ATA2_MAC_ADDR_LSB_LENGTH (16)
+
+/* fields of ATWD */
+#define ATWD (REG_ARL_BASE_ADDRESS + 0x0324)
+#define ATWD_MAC_LIVE_OFFSET (0)
+#define ATWD_MAC_LIVE_LENGTH (1)
+#define ATWD_MAC_LEAK_OFFSET (1)
+#define ATWD_MAC_LEAK_LENGTH (1)
+#define ATWD_MAC_UPRI_OFFSET (2)
+#define ATWD_MAC_UPRI_LENGTH (3)
+#define ATWD_MAC_FWD_OFFSET (5)
+#define ATWD_MAC_FWD_LENGTH (3)
+#define ATWD_MAC_MIR_OFFSET (8)
+#define ATWD_MAC_MIR_LENGTH (2)
+#define ATWD_MAC_ETAG_OFFSET (12)
+#define ATWD_MAC_ETAG_LENGTH (3)
+#define ATWD_MAC_IVL_OFFSET (15)
+#define ATWD_MAC_IVL_LENGTH (1)
+#define ATWD_MAC_VID_OFFSET (16)
+#define ATWD_MAC_VID_LENGTH (12)
+#define ATWD_MAC_FID_OFFSET (28)
+#define ATWD_MAC_FID_LENGTH (4)
+
+/* fields of ATWD2 */
+#define ATWD2 (REG_ARL_BASE_ADDRESS + 0x0328)
+#define ATWD2_MAC_PORT_OFFSET (0)
+#define ATWD2_MAC_PORT_LENGTH (8)
+
+/* fields of ATC */
+#define ATC (REG_ARL_BASE_ADDRESS + 0x0300)
+#define ATC_MAC_OFFSET (0)
+#define ATC_MAC_LENGTH (3)
+#define ATC_SAT_OFFSET (4)
+#define ATC_SAT_LENGTH (2)
+#define ATC_MAT_OFFSET (7)
+#define ATC_MAT_LENGTH (5)
+#define ATC_ENTRY_HIT_OFFSET (12)
+#define ATC_ENTRY_HIT_LENGTH (4)
+#define ATC_ADDR_OFFSET (16)
+#define ATC_ADDR_LENGTH (9)
+#define ATC_SINGLE_HIT_OFFSET (30)
+#define ATC_SINGLE_HIT_LENGTH (1)
+#define ATC_BUSY_OFFSET (31)
+#define ATC_BUSY_LENGTH (1)
+
+typedef enum {
+ _ATC_CMD_READ = 0,
+ _ATC_CMD_WRITE,
+ _ATC_CMD_CLEAN,
+ _ATC_CMD_SEARCH = 4,
+ _ATC_CMD_SEARCH_NEXT,
+ _ATC_CMD_LAST
+}_ATC_CMD_T;
+
+#define ATC_CMD_READ (_ATC_CMD_READ << ATC_MAC_OFFSET)
+#define ATC_CMD_WRITE (_ATC_CMD_WRITE << ATC_MAC_OFFSET)
+#define ATC_CMD_CLEAN (_ATC_CMD_CLEAN << ATC_MAC_OFFSET)
+#define ATC_CMD_SEARCH (_ATC_CMD_SEARCH << ATC_MAC_OFFSET)
+#define ATC_CMD_SEARCH_NEXT (_ATC_CMD_SEARCH_NEXT << ATC_MAC_OFFSET)
+
+typedef enum {
+ _ATC_SAT_MAC = 0,
+ _ATC_SAT_DIP,
+ _ATC_SAT_SIP,
+ _ATC_SAT_ADDR,
+ _ATC_SAT_LAST
+}_ATC_SAT_T;
+
+#define ATC_SAT_MAC (_ATC_SAT_MAC << ATC_SAT_OFFSET)
+#define ATC_SAT_DIP (_ATC_SAT_DIP << ATC_SAT_OFFSET)
+#define ATC_SAT_SIP (_ATC_SAT_SIP << ATC_SAT_OFFSET)
+#define ATC_SAT_ADDR (_ATC_SAT_ADDR << ATC_SAT_OFFSET)
+
+typedef enum {
+ _ATC_MAT_ALL = 0,
+ _ATC_MAT_MAC,
+ _ATC_MAT_DYNAMIC_MAC,
+ _ATC_MAT_STATIC_MAC,
+ _ATC_MAT_DIP,
+ _ATC_MAT_DIPV4,
+ _ATC_MAT_DIPV6,
+ _ATC_MAT_SIP,
+ _ATC_MAT_SIPV4,
+ _ATC_MAT_SIPV6,
+ _ATC_MAT_MAC_BY_VID,
+ _ATC_MAT_MAC_BY_FID,
+ _ATC_MAT_MAC_BY_PORT,
+ _ATC_MAT_SIP_BY_DIPV4,
+ _ATC_MAT_SIP_BY_SIPV4,
+ _ATC_MAT_SIP_BY_DIPV6,
+ _ATC_MAT_SIP_BY_SIPV6,
+ _ATC_MAT_LAST
+}_ATC_MAT_T;
+
+#define ATC_MAT_ALL (_ATC_MAT_ALL << ATC_MAT_OFFSET)
+#define ATC_MAT_MAC (_ATC_MAT_MAC << ATC_MAT_OFFSET)
+#define ATC_MAT_DYNAMIC_MAC (_ATC_MAT_DYNAMIC_MAC << ATC_MAT_OFFSET)
+#define ATC_MAT_STATIC_MAC (_ATC_MAT_STATIC_MAC << ATC_MAT_OFFSET)
+#define ATC_MAT_DIP (_ATC_MAT_DIP << ATC_MAT_OFFSET)
+#define ATC_MAT_DIPV4 (_ATC_MAT_DIPV4 << ATC_MAT_OFFSET)
+#define ATC_MAT_DIPV6 (_ATC_MAT_DIPV6 << ATC_MAT_OFFSET)
+#define ATC_MAT_SIP (_ATC_MAT_SIP << ATC_MAT_OFFSET)
+#define ATC_MAT_SIPV4 (_ATC_MAT_SIPV4 << ATC_MAT_OFFSET)
+#define ATC_MAT_SIPV6 (_ATC_MAT_SIPV6 << ATC_MAT_OFFSET)
+#define ATC_MAT_MAC_BY_VID (_ATC_MAT_MAC_BY_VID << ATC_MAT_OFFSET)
+#define ATC_MAT_MAC_BY_FID (_ATC_MAT_MAC_BY_FID << ATC_MAT_OFFSET)
+#define ATC_MAT_MAC_BY_PORT (_ATC_MAT_MAC_BY_PORT << ATC_MAT_OFFSET)
+#define ATC_MAT_SIP_BY_DIPV4 (_ATC_MAT_SIP_BY_DIPV4 << ATC_MAT_OFFSET)
+#define ATC_MAT_SIP_BY_SIPV4 (_ATC_MAT_SIP_BY_SIPV4 << ATC_MAT_OFFSET)
+#define ATC_MAT_SIP_BY_DIPV6 (_ATC_MAT_SIP_BY_DIPV6 << ATC_MAT_OFFSET)
+#define ATC_MAT_SIP_BY_SIPV6 (_ATC_MAT_SIP_BY_SIPV6 << ATC_MAT_OFFSET)
+
+#define ATC_START_BUSY (0x01 << ATC_BUSY_OFFSET)
+
+/* fields of AAC*/
+#define AAC (REG_ARL_BASE_ADDRESS + 0x00A0)
+#define AAC_AGE_UNIT_OFFSET (0)
+#define AAC_AGE_UNIT_LENGTH (11)
+#define AAC_AGE_CNT_OFFSET (12)
+#define AAC_AGE_CNT_LENGTH (9)
+#define AAC_AUTO_FLUSH_OFFSET (28)
+#define AAC_AUTO_FLUSH_LENGTH (1)
+
+#define AGDIS (REG_ARL_BASE_ADDRESS + 0x00C0)
+
+/* fields of ATWDS */
+#define ATRDS (REG_ARL_BASE_ADDRESS + 0x0330)
+#define ATRD0_MAC_SEL_OFFSET (0)
+#define ATRD0_MAC_SEL_LENGTH (2)
+
+/* fields of ATRD0 */
+#define ATRD0 (REG_ARL_BASE_ADDRESS + 0x0334)
+//need to verify 32'b 0
+#define ATRD0_MAC_LIVE_OFFSET (0)
+#define ATRD0_MAC_LIVE_LENGTH (1)
+#define ATRD0_MAC_LIFETIME_OFFSET (1)
+#define ATRD0_MAC_LIFETIME_LENGTH (2)
+#define ATRD0_MAC_TYPE_OFFSET (3)
+#define ATRD0_MAC_TYPE_LENGTH (2)
+#define ATRD0_MAC_LEAK_OFFSET (5)
+#define ATRD0_MAC_LEAK_LENGTH (1)
+#define ATRD0_MAC_UPRI_OFFSET (6)
+#define ATRD0_MAC_UPRI_LENGTH (3)
+#define ATRD0_MAC_IVL_OFFSET (9)
+#define ATRD0_MAC_IVL_LENGTH (1)
+#define ATRD0_MAC_VID_OFFSET (10)
+#define ATRD0_MAC_VID_LENGTH (12)
+#define ATRD0_MAC_ETAG_OFFSET (22)
+#define ATRD0_MAC_ETAG_LENGTH (3)
+#define ATRD0_MAC_FID_OFFSET (25)
+#define ATRD0_MAC_FID_LENGTH (4)
+#define ATRD1_MAC_UNAUTH_OFFSET (31)
+#define ATRD1_MAC_UNAUTH_LENGTH (1)
+
+/* fields of ATRD1 */
+#define ATRD1 (REG_ARL_BASE_ADDRESS + 0x0338)
+//need to verify 32'b 0
+#define ATRD1_MAC_FWD_OFFSET (0)
+#define ATRD1_MAC_FWD_LENGTH (3)
+#define ATRD1_MAC_AGETIME_OFFSET (3)
+#define ATRD1_MAC_AGETIME_LENGTH (9)
+#define ATRD1_MAC_MIR_OFFSET (12)
+#define ATRD1_MAC_MIR_LENGTH (4)
+#define ATRD1_MAC_ADDR_LSB_OFFSET (16)
+#define ATRD1_MAC_ADDR_LSB_LENGTH (16)
+
+/* fields of ATRD2 */
+#define ATRD2 (REG_ARL_BASE_ADDRESS + 0x033C)
+#define ATRD2_MAC_ADDR_MSB_OFFSET (0)
+#define ATRD2_MAC_ADDR_MSB_LENGTH (32)
+
+/* fields of ATRD3 */
+#define ATRD3 (REG_ARL_BASE_ADDRESS + 0x0340)
+//need to verify 32'b 0
+#define ATRD3_MAC_PORT_OFFSET (0)
+#define ATRD3_MAC_PORT_LENGTH (8)
+
+#define REG_SCH_PORT_ADDRESS (REG_ARL_BASE_ADDRESS + 0xc000)
+#define MMSCR0_Q0(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p))
+#define MMSCR1_Q0(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x4)
+#define MMSCR0_Q1(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x8)
+#define MMSCR1_Q1(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0xc)
+#define MMSCR0_Q2(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x10)
+#define MMSCR1_Q2(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x14)
+#define MMSCR0_Q3(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x18)
+#define MMSCR1_Q3(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x1c)
+#define MMSCR0_Q4(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x20)
+#define MMSCR1_Q4(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x24)
+#define MMSCR0_Q5(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x28)
+#define MMSCR1_Q5(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x2c)
+#define MMSCR0_Q6(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x30)
+#define MMSCR1_Q6(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x34)
+#define MMSCR0_Q7(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x38)
+#define MMSCR1_Q7(p) (REG_SCH_PORT_ADDRESS + PORT_CTRL_PORT_OFFSET * (p) + 0x3c)
+
+#define PUPW(p) PORT_CTRL_REG(p, 0x30)
+
+#define PEM1 (REG_ARL_BASE_ADDRESS + 0x0048)
+#define PEM2 (REG_ARL_BASE_ADDRESS + 0x004c)
+#define PEM3 (REG_ARL_BASE_ADDRESS + 0x0050)
+#define PEM4 (REG_ARL_BASE_ADDRESS + 0x0054)
+
+#define PIM1 (REG_ARL_BASE_ADDRESS + 0x0058)
+#define PIM2 (REG_ARL_BASE_ADDRESS + 0x005c)
+#define PIM3 (REG_ARL_BASE_ADDRESS + 0x0060)
+#define PIM4 (REG_ARL_BASE_ADDRESS + 0x0064)
+#define PIM5 (REG_ARL_BASE_ADDRESS + 0x0068)
+#define PIM6 (REG_ARL_BASE_ADDRESS + 0x006c)
+#define PIM7 (REG_ARL_BASE_ADDRESS + 0x0070)
+
+/* fields of ingress and egress rate control */
+#define IRLCR(p) (REG_ARL_BASE_ADDRESS + (p * PORT_CTRL_PORT_OFFSET) + 0x4000)
+#define ERLCR(p) (REG_ARL_BASE_ADDRESS + (p * PORT_CTRL_PORT_OFFSET) + 0xC040)
+#define REG_RATE_CIR_OFFT (0)
+#define REG_RATE_CIR_LENG (17)
+#define REG_TB_EN_OFFT (19)
+#define REG_RATE_TB_OFFT (20)
+#define REG_RATE_TB_LENG (4)
+#define REG_RATE_CBS_OFFT (24)
+#define REG_RATE_CBS_LENG (7)
+#define REG_RATE_EN_OFFT (31)
+
+/* fields of global ingress and egress rate control */
+#define GIRLCR (REG_ARL_BASE_ADDRESS + 0x7E24)
+#define GERLCR (REG_ARL_BASE_ADDRESS + 0xFE00)
+#define REG_IPG_BYTE_OFFT (0)
+#define REG_IPG_BYTE_LENG (8)
+#define REG_MFRM_EX_OFFT (9)
+#define REG_MFRM_EX_LENG (1)
+#define SFLOW_MFRM_EX_OFFT (25)
+#define SFLOW_MFRM_EX_LENG (1)
+#define L1_RATE_IPG_BYTE_CNT (0x18)
+#define L2_RATE_IPG_BYTE_CNT (0x04)
+
+
+/* fields of PTC */
+#define PTC_INFO_SEL_SP (1 << 0)
+#define PTC_INFO_SEL_SA (1 << 1)
+#define PTC_INFO_SEL_DA (1 << 2)
+#define PTC_INFO_SEL_SIP (1 << 3)
+#define PTC_INFO_SEL_DIP (1 << 4)
+#define PTC_INFO_SEL_SPORT (1 << 5)
+#define PTC_INFO_SEL_DPORT (1 << 6)
+
+#define SSC(p) PORT_CTRL_REG(p, 0x00)
+#define PIC(p) PORT_CTRL_REG(p, 0x08)
+
+/* fields of IGMP SNOOPING */
+#define IGMP_HW_GQUERY 1
+#define IGMP_HW_SQUERY (1 << 2)
+#define IGMP_HW_JOIN (1 << 4)
+#define IGMPV3_HW_JOIN (1 << 6)
+#define DMAC_01005E (1 << 8)
+#define DMAC_3333XX (1 << 9)
+#define MCAST_DIP (1 << 10)
+#define IGMP_HW_LEAVE (1 << 12)
+#define IGMP_AUTO_DOWNGRADE (1 << 20)
+#define IGMP_AUTO_ROUTER (1 << 18)
+#define IGMP_ROBUSTNESS_OFFSET 16
+#define IGMP_QUERYINTERVAL_OFFSET 8
+
+/* fields of MLD SNOOPING */
+#define MLD_HW_GQUERY (1 << 1)
+#define MLD_HW_SQUERY (1 << 3)
+#define MLD_HW_JOIN (1 << 5)
+#define MLDV2_HW_JOIN (1 << 7)
+#define MLD_HW_LEAVE (1 << 13)
+#define MLD_AUTO_ROUTER (1 << 19)
+
+#define PMSR(p) PORT_MAC_CTRL_REG(p, 0x10)
+
+/* fields of loop detect */
+#define LPDET_CTRL 0x30C0
+#define LPDET_OFFSET 24
+#define LPDET_TRIGGER_OFFSET 23
+#define LPDET_TRIGGER_PERIODICAL 1
+#define LPDET_TRIGGER_BROADCAST 0
+
+/* Port debug count register */
+#define DBG_CNT_BASE 0x3018
+#define DBG_CNT_PORT_BASE 0x100
+#define DBG_CNT(p) (DBG_CNT_BASE + (p) * DBG_CNT_PORT_BASE)
+#define DIS_CLR (1 << 31)
+
+#define PFC_STS(p) PORT_MAC_CTRL_REG(p, 0x24)
+#define PFC_CTRL (PORT_MAC_CTRL_BASE + 0xB0)
+#define PFC_EN(p) (1 << p)
+#define PFC_SYN_EN(p) (0x80 << p)
+
+#define GMACCR (PORT_MAC_CTRL_BASE + 0x3e00)
+#define MTCC_LMT_S 8
+#define MAX_RX_JUMBO_S 4
+
+/* Values of MAX_RX_PKT_LEN */
+#define RX_PKT_LEN_1518 (0)
+#define RX_PKT_LEN_1536 (1)
+#define RX_PKT_LEN_1522 (2)
+#define RX_PKT_LEN_MAX_JUMBO (3)
+
+/* Fields of PMCR */
+#define FORCE_MODE (1 << 31)
+#define IPG_CFG_S (20)
+#define IPG_CFG_M (0x300000)
+#define EXT_PHY (1 << 19)
+#define MAC_MODE (1 << 18)
+#define MAC_TX_EN (1 << 16)
+#define MAC_RX_EN (1 << 15)
+#define MAC_PRE (1 << 14)
+#define BKOFF_EN (1 << 12)
+#define BACKPR_EN (1 << 11)
+#define FORCE_EEE1G (1 << 7)
+#define FORCE_EEE100 (1 << 6)
+#define FORCE_RX_FC (1 << 5)
+#define FORCE_TX_FC (1 << 4)
+#define FORCE_SPD_S (28)
+#define FORCE_SPD_M (0x70000000)
+#define FORCE_DPX (1 << 25)
+#define FORCE_LINK (1 << 24)
+
+/* Fields of PMSR */
+#define EEE1G_STS (1 << 7)
+#define EEE100_STS (1 << 6)
+#define RX_FC_STS (1 << 5)
+#define TX_FC_STS (1 << 4)
+#define MAC_SPD_STS_S (28)
+#define MAC_SPD_STS_M (0x70000000)
+#define MAC_DPX_STS (1 << 25)
+#define MAC_LNK_STS (1 << 24)
+
+/* Values of MAC_SPD_STS */
+#define MAC_SPD_10 0
+#define MAC_SPD_100 1
+#define MAC_SPD_1000 2
+#define MAC_SPD_2500 3
+
+/* Values of IPG_CFG */
+#define IPG_96BIT 0
+#define IPG_96BIT_WITH_SHORT_IPG 1
+#define IPG_64BIT 2
+
+/* Register of MIB Base address */
+#define MAC_GLOBAL_REG_BASE 0x10213E00
+#define ARL_ACL_ATK_REG_BASE 0x10200000
+
+#define MIB_BASE 0x10214000
+#define MIB_PORT_OFFSET 0x0200
+#define MIB_ACL_EVENT_OFFSET 0x0F00
+#define MIB_TDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x00)
+#define MIB_TCRC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x04)
+#define MIB_TUPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x08)
+#define MIB_TMPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x0C)
+#define MIB_TBPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x10)
+#define MIB_TCEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x14)
+#define MIB_TSCEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x18)
+#define MIB_TMCEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x1C)
+#define MIB_TDEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x20)
+#define MIB_TLCEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x24)
+#define MIB_TXCEC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x28)
+#define MIB_TPPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x2C)
+#define MIB_TL64PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x30)
+#define MIB_TL65PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x34)
+#define MIB_TL128PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x38)
+#define MIB_TL256PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x3C)
+#define MIB_TL512PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x40)
+#define MIB_TL1024PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x44)
+#define MIB_TL1519PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x48)
+
+#define MIB_TOCL(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x4C)
+#define MIB_TOCH(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x50)
+#define MIB_TODPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x54)
+#define MIB_TOCL2(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x58)
+#define MIB_TOCH2(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x5C)
+
+
+
+#define MIB_RDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x80)
+#define MIB_RFPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x84)
+#define MIB_RUPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x88)
+#define MIB_RMPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x8C)
+#define MIB_RBPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x90)
+#define MIB_RAEPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x94)
+#define MIB_RCEPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x98)
+#define MIB_RUSPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x9C)
+#define MIB_RFEPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xA0)
+#define MIB_ROSPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xA4)
+#define MIB_RJEPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xA8)
+#define MIB_RPPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xAC)
+#define MIB_RL64PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xB0)
+#define MIB_RL65PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xB4)
+#define MIB_RL128PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xB8)
+#define MIB_RL256PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xBC)
+#define MIB_RL512PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xC0)
+#define MIB_RL1024PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xC4)
+#define MIB_RL1519PC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xC8)
+
+#define MIB_ROCL(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xCC)
+#define MIB_ROCH(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xD0)
+#define MIB_RCDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xD4)
+#define MIB_RIDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xD8)
+#define MIB_RADPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xDC)
+#define MIB_FCDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xE0)
+#define MIB_WRDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xE4)
+#define MIB_MRDPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xE8)
+#define MIB_ROCL2(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xEC)
+#define MIB_ROCH2(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xF0)
+#define MIB_SFSPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xF4)
+#define MIB_SFTPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xF8)
+#define MIB_RXC_DPC(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0xFC)
+
+
+#define MIB_TMIB_HF_STS(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x7C)
+#define MIB_RMIB_HF_STS(p) (MIB_BASE + (p) * MIB_PORT_OFFSET + 0x100)
+
+#define ACL_MIB_CNT_CFG (ARL_ACL_ATK_REG_BASE + 0x534)
+#define ACL_MIB_CNT (ARL_ACL_ATK_REG_BASE + 0x538)
+
+
+#define MIB_CCR (MAC_GLOBAL_REG_BASE + 0x0030)
+#define MIB_PCLR (MAC_GLOBAL_REG_BASE + 0x0034)
+#define MIB_CCR_MIB_ENABLE_OFFSET (31)
+#define MIB_CCR_MIB_ENABLE_LENGTH (1)
+#define MIB_CCR_MIB_ENABLE (1 << 31)
+#define MIB_CCR_RX_OCT_CNT_GOOD (1 << 7)
+#define MIB_CCR_RX_OCT_CNT_BAD (1 << 6)
+#define MIB_CCR_TX_OCT_CNT_GOOD (1 << 5)
+#define MIB_CCR_TX_OCT_CNT_BAD (1 << 4)
+
+#define CSR_ACL_MIB_CLEAR (1 << 0)
+
+#define SGMII_REG_BASE 0x5000
+#define SGMII_REG_PORT_BASE 0x1000
+#define SGMII_REG(p, r) (SGMII_REG_BASE + (p) * SGMII_REG_PORT_BASE + (r))
+#define PCS_CONTROL_1(p) SGMII_REG(p, 0x00)
+#define PCS_SPEED_ABILITY(p) SGMII_REG(p, 0x08)
+#define SGMII_MODE(p) SGMII_REG(p, 0x20)
+#define QPHY_PWR_STATE_CTRL(p) SGMII_REG(p, 0xE8)
+#define PHYA_CTRL_SIGNAL3(p) SGMII_REG(p, 0x128)
+
+/* Fields of PCS_CONTROL_1 */
+#define SGMII_AN_ABILITY (1 << 19)
+#define SGMII_LINK_STATUS (1 << 18)
+#define SGMII_AN_ENABLE_OFFT (12)
+#define SGMII_AN_ENABLE (1 << 12)
+#define SGMII_AN_RESTART (1 << 9)
+
+/* Fields of SGMII_MODE */
+#define SGMII_REMOTE_FAULT_DIS (1 << 8)
+#define SGMII_IF_MODE_FORCE_DUPLEX (1 << 4)
+#define SGMII_IF_MODE_FORCE_SPEED_OFFT (0x2)
+#define SGMII_IF_MODE_FORCE_SPEED_R (0x2)
+#define SGMII_IF_MODE_FORCE_SPEED_M (0x0C)
+#define SGMII_IF_MODE_ADVERT_AN (1 << 1)
+
+/* Config of AN Tx control information (SGMII)
+* LINK- 1:link up, 0:link down
+* DUPLEX- 1:full, 0:half
+* MODE - 1:SGMII, 0:Clause37
+*/
+#define AN_CONFIG_TX_LINK (1 << 15)
+#define AN_CONFIG_TX_DUPLEX (1 << 12)
+#define AN_CONFIG_TX_SPEED_OFFT (10)
+#define AN_CONFIG_TX_SPEED_MSK (3 << AN_CONFIG_TX_SPEED_OFFT)
+#define AN_CONFIG_TX_MODE_SGMII (1)
+
+/* Config of AN Tx control information (Clause37)
+* MODE - 1:SGMII, 0:Clause37
+*/
+#define AN_CONFIG_TX_FULL_DUPLEX_CL37 (1 << 5)
+#define AN_CONFIG_TX_HALF_DUPLEX_CL37 (1 << 6)
+#define AN_CONFIG_TX_SYMMETRIC_PAUSE (1 << 7)
+#define AN_CONFIG_TX_ASYMMETRIC_PAUSE (1 << 8)
+
+/* Values of SGMII_IF_MODE_FORCE_SPEED */
+#define SGMII_IF_MODE_FORCE_SPEED_10 0
+#define SGMII_IF_MODE_FORCE_SPEED_100 1
+#define SGMII_IF_MODE_FORCE_SPEED_1000 2
+
+/* Fields of QPHY_PWR_STATE_CTRL */
+#define PHYA_PWD (1 << 4)
+
+/* Fields of PHYA_CTRL_SIGNAL3 */
+#define RG_TPHY_SPEED_S 2
+#define RG_TPHY_SPEED_M 0x0c
+
+/* Values of RG_TPHY_SPEED */
+#define RG_TPHY_SPEED_1000 0
+#define RG_TPHY_SPEED_2500 1
+
+
+#define SCU_BASE 0x10000000
+#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0)
+
+#define HSGMII_AN_CSR_BASE 0x10220000
+#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000)
+#define SGMII_REG_AN_13 (HSGMII_AN_CSR_BASE + 0x034)
+#define SGMII_REG_AN_FORCE_CL37 (HSGMII_AN_CSR_BASE + 0x060)
+
+#define HSGMII_CSR_PCS_BASE 0x10220000
+#define RG_HSGMII_PCS_CTROL_1 (HSGMII_CSR_PCS_BASE + 0xa00)
+#define RG_AN_SGMII_MODE_FORCE (HSGMII_CSR_PCS_BASE + 0xa24)
+
+#define MULTI_SGMII_CSR_BASE 0x10224000
+#define SGMII_STS_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x018)
+#define MSG_RX_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x100)
+#define MSG_RX_LIK_STS_0 (MULTI_SGMII_CSR_BASE + 0x514)
+#define MSG_RX_LIK_STS_2 (MULTI_SGMII_CSR_BASE + 0x51c)
+#define PHY_RX_FORCE_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x520)
+
+#define XFI_CSR_PCS_BASE 0x10225000
+#define RG_USXGMII_AN_CONTROL_0 (XFI_CSR_PCS_BASE + 0xbf8)
+
+#define MULTI_PHY_RA_CSR_BASE 0x10226000
+#define RG_RATE_ADAPT_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x000)
+#define RATE_ADP_P0_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x100)
+#define MII_RA_AN_ENABLE (MULTI_PHY_RA_CSR_BASE + 0x300)
+
+#define QP_DIG_CSR_BASE 0x1022a000
+#define QP_CK_RST_CTRL_4 (QP_DIG_CSR_BASE + 0x310)
+#define QP_DIG_MODE_CTRL_0 (QP_DIG_CSR_BASE + 0x324)
+#define QP_DIG_MODE_CTRL_1 (QP_DIG_CSR_BASE + 0x330)
+
+#define SERDES_WRAPPER_BASE 0x1022c000
+#define USGMII_CTRL_0 (SERDES_WRAPPER_BASE + 0x000)
+
+#define QP_PMA_TOP_BASE 0x1022e000
+#define PON_RXFEDIG_CTRL_0 (QP_PMA_TOP_BASE + 0x100)
+#define PON_RXFEDIG_CTRL_9 (QP_PMA_TOP_BASE + 0x124)
+
+#define SS_LCPLL_PWCTL_SETTING_2 (QP_PMA_TOP_BASE + 0x208)
+#define SS_LCPLL_TDC_FLT_2 (QP_PMA_TOP_BASE + 0x230)
+#define SS_LCPLL_TDC_FLT_5 (QP_PMA_TOP_BASE + 0x23c)
+#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248)
+#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320)
+#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324)
+#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400)
+#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408)
+#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c)
+#define PLL_CTRL_4 (QP_PMA_TOP_BASE + 0x410)
+#define PLL_CK_CTRL_0 (QP_PMA_TOP_BASE + 0x414)
+#define RX_DLY_0 (QP_PMA_TOP_BASE + 0x614)
+#define RX_CTRL_2 (QP_PMA_TOP_BASE + 0x630)
+#define RX_CTRL_5 (QP_PMA_TOP_BASE + 0x63c)
+#define RX_CTRL_6 (QP_PMA_TOP_BASE + 0x640)
+#define RX_CTRL_7 (QP_PMA_TOP_BASE + 0x644)
+#define RX_CTRL_8 (QP_PMA_TOP_BASE + 0x648)
+#define RX_CTRL_26 (QP_PMA_TOP_BASE + 0x690)
+#define RX_CTRL_42 (QP_PMA_TOP_BASE + 0x6d0)
+
+#define QP_ANA_CSR_BASE 0x1022f000
+#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00)
+#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04)
+#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c)
+#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14)
+#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18)
+#define RG_QP_CDR_PR_KBAND_DIV_PCIE (QP_ANA_CSR_BASE + 0x1c)
+#define RG_QP_CDR_FORCE_IBANDLPF_R_OFF (QP_ANA_CSR_BASE + 0x20)
+#define RG_QP_TX_MODE_16B_EN (QP_ANA_CSR_BASE + 0x28)
+#define RG_QP_PLL_IPLL_DIG_PWR_SEL (QP_ANA_CSR_BASE + 0x3c)
+#define RG_QP_PLL_SDM_ORD (QP_ANA_CSR_BASE + 0x40)
+
+#define ETHER_SYS_BASE 0x1028c800
+#define RG_P5MUX_MODE (ETHER_SYS_BASE + 0x00)
+#define RG_FORCE_CKDIR_SEL (ETHER_SYS_BASE + 0x04)
+#define RG_SWITCH_MODE (ETHER_SYS_BASE + 0x08)
+#define RG_FORCE_MAC5_SB (ETHER_SYS_BASE + 0x2c)
+#define CSR_RMII (ETHER_SYS_BASE + 0x70)
+
+
+#define SYS_CTRL 0x7000
+#define SW_PHY_RST (1 << 2)
+#define SW_SYS_RST (1 << 1)
+#define SW_REG_RST (1 << 0)
+
+#define PHY_IAC 0x1000e000
+
+#define CLKGEN_CTRL 0x7500
+#define CLK_SKEW_OUT_S 8
+#define CLK_SKEW_OUT_M 0x300
+#define CLK_SKEW_IN_S 6
+#define CLK_SKEW_IN_M 0xc0
+#define RXCLK_NO_DELAY (1 << 5)
+#define TXCLK_NO_REVERSE (1 << 4)
+#define GP_MODE_S 1
+#define GP_MODE_M 0x06
+#define GP_CLK_EN (1 << 0)
+
+/* Values of GP_MODE */
+#define GP_MODE_RGMII 0
+#define GP_MODE_MII 1
+#define GP_MODE_REV_MII 2
+
+/* Values of CLK_SKEW_IN */
+#define CLK_SKEW_IN_NO_CHANGE 0
+#define CLK_SKEW_IN_DELAY_100PPS 1
+#define CLK_SKEW_IN_DELAY_200PPS 2
+#define CLK_SKEW_IN_REVERSE 3
+
+/* Values of CLK_SKEW_OUT */
+#define CLK_SKEW_OUT_NO_CHANGE 0
+#define CLK_SKEW_OUT_DELAY_100PPS 1
+#define CLK_SKEW_OUT_DELAY_200PPS 2
+#define CLK_SKEW_OUT_REVERSE 3
+
+#define HWSTRAP 0x7800
+#define XTAL_FSEL_S 7
+#define XTAL_FSEL_M (1 << 7)
+
+#define XTAL_40MHZ 0
+#define XTAL_25MHZ 1
+
+#define PLLGP_EN 0x7820
+#define EN_COREPLL (1 << 2)
+#define SW_CLKSW (1 << 1)
+#define SW_PLLGP (1 << 0)
+
+#define PLLGP_CR0 0x78a8
+#define RG_COREPLL_EN (1 << 22)
+#define RG_COREPLL_POSDIV_S 23
+#define RG_COREPLL_POSDIV_M 0x3800000
+#define RG_COREPLL_SDM_PCW_S 1
+#define RG_COREPLL_SDM_PCW_M 0x3ffffe
+#define RG_COREPLL_SDM_PCW_CHG (1 << 0)
+
+#define MHWSTRAP 0x7804
+#define STRAP_CHG_STRAP (1 << 8)
+#define STRAP_PHY_EN (1 << 6)
+
+#define TOP_SIG_SR 0x780c
+#define PAD_DUAL_SGMII_EN (1 << 1)
+
+/* RGMII and SGMII PLL clock */
+#define ANA_PLLGP_CR2 0x78b0
+#define ANA_PLLGP_CR5 0x78bc
+
+/* Efuse Register Define */
+#define GBE_EFUSE 0x7bc8
+#define GBE_SEL_EFUSE_EN (1 << 0)
+
+/* GPIO_PAD_0 */
+#define GPIO_MODE0 0x7c0c
+#define GPIO_MODE0_S 0
+#define GPIO_MODE0_M 0xf
+#define GPIO_0_INTERRUPT_MODE 0x1
+
+#define SMT0_IOLB 0x7f04
+#define SMT_IOLB_5_SMI_MDC_EN (1 << 5)
+
+/* PHY CL22 reg */
+#define PHY_PAGE_0 0x0
+/* Mode Control Register */
+#define PHY_MCR 0x00
+#define MCR_SR (1 << 15)
+#define MCR_LB (1 << 14)
+#define MCR_MR_FC_SPD_INT_0 (1 << 13)
+#define MCR_AN_EN (1 << 12)
+#define MCR_PW_DN (1 << 11)
+#define MCR_ISO (1 << 10)
+#define MCR_RST_AN (1 << 9)
+#define MCR_MR_DUX (1 << 8)
+#define MCR_MR_CLS_TEST (1 << 7)
+#define MCR_MR_FC_SPD_INT_1 (1 << 6)
+
+/* Mode Status Register */
+#define PHY_MSR 0x01
+#define MSR_CAP_100T4 (1 << 15)
+#define MSR_CAP_100X_FDX (1 << 14)
+#define MSR_CAP_100X_HDX (1 << 13)
+#define MSR_CAP_10T_FDX (1 << 12)
+#define MSR_CAP_10T_HDX (1 << 11)
+#define MSR_CAP_100T2_HDX (1 << 10)
+#define MSR_CAP_100T2_FDX (1 << 9)
+#define MSR_EXT_STA_EN (1 << 8)
+#define MSR_PRAM_SUP_CAP (1 << 6)
+#define MSR_AN_COMP (1 << 5)
+#define MSR_RMT_FAULT (1 << 4)
+#define MSR_AN_CAP (1 << 3)
+#define MSR_LINK_STA (1 << 2)
+#define MSR_JAB_DECT (1 << 1)
+#define MSR_EXT_CAP (1 << 0)
+
+/* Auto-Negotiation Advertisement Register */
+#define PHY_AN_ADV 0x04
+#define AN_ADV_NX_PAGE_REQ (1 << 15)
+#define AN_ADV_RF (1 << 13)
+#define AN_ADV_CAP_PAUSE (3 << 10)
+#define AN_ADV_CAP_100_T4 (1 << 9)
+#define AN_ADV_CAP_100_FDX (1 << 8)
+#define AN_ADV_CAP_100_HDX (1 << 7)
+#define AN_ADV_CAP_10_FDX (1 << 6)
+#define AN_ADV_CAP_10_HDX (1 << 5)
+#define AN_ADV_802_9_ISLAN_16T (2 << 0)
+#define AN_ADV_802_3 (1 << 0)
+
+/* Auto-Negotiation Link Partner Advertisement Register */
+#define PHY_AN_LP_ADV 0x05
+#define AN_LP_NX_PAGE_REQ (1 << 15)
+#define AN_LP_ACK (1 << 14)
+#define AN_LP_RF (1 << 13)
+#define AN_LP_CAP_PAUSE (3 << 10)
+#define AN_LP_CAP_100_T4 (1 << 9)
+#define AN_LP_CAP_100_FDX (1 << 8)
+#define AN_LP_CAP_100_HDX (1 << 7)
+#define AN_LP_CAP_10_FDX (1 << 6)
+#define AN_LP_CAP_10_HDX (1 << 5)
+#define AN_LP_802_9_ISLAN_16T (2 << 0)
+#define AN_LP_802_3 (1 << 0)
+
+/* 1000BASE-T Control Register */
+#define PHY_CR1G 0x09
+#define CR1G_TEST_TM4 (4 << 13)
+#define CR1G_TEST_TM3 (3 << 13)
+#define CR1G_TEST_TM2 (2 << 13)
+#define CR1G_TEST_TM1 (1 << 13)
+#define CR1G_TEST_NORMAL (0 << 13)
+#define CR1G_MS_EN (1 << 12)
+#define CR1G_MS_CONF (1 << 11)
+#define CR1G_PORT_TYPE (1 << 10)
+#define CR1G_ADV_CAP1000_FDX (1 << 9)
+#define CR1G_ADV_CAP1000_HDX (1 << 8)
+
+/* 1000BASE-T Status Register */
+#define PHY_SR1G 0x0A
+#define SR1G_MS_CFG_FAULT (1 << 15)
+#define SR1G_MS_CFG_RES (1 << 14)
+#define SR1G_LOC_RX (1 << 13)
+#define SR1G_RMT_RX (1 << 12)
+#define SR1G_CAP1000_FDX (1 << 11)
+#define SR1G_CAP1000_HDX (1 << 10)
+#define SR1G_IDLE_ERR_MASK 0xFF
+
+#define PHY_PAGE_1 0x1
+/* Ethernet Packet Generator Control Register */
+#define PHY_EPG 0x1D
+#define EPG_EN (1 << 15)
+#define EPG_RUN (1 << 14)
+#define EPG_TX_DUR (1 << 13)
+#define EPG_PKT_LEN_10KB (3 << 11)
+#define EPG_PKT_LEN_1518B (2 << 11)
+#define EPG_PKT_LEN_64B (1 << 11)
+#define EPG_PKT_LEN_125B (0 << 11)
+#define EPG_PKT_GAP (1 << 10)
+#define EPG_DES_ADDR(a) ( ( (a) & 0xF ) << 6 )
+#define EPG_SUR_ADDR(a) ( ( (a) & 0xF ) << 2 )
+#define EPG_PL_TYP_RANDOM (1 << 1)
+#define EPG_BAD_FCS (1 << 0)
+
+/* external*/
+#define EXPHY_CMD_WRITE (0x10)
+#define DFETAILDC_COEFF_L (0x11)
+#define DFETAILDC_COEFF_M (0x12)
+
+/* PHY CL22 reg */
+#define PHY_PAGE (0x1F)
+
+/* PHY CL45 reg */
+#define PHY_DEV_07H (0x07)
+#define PHY_DEV_1FH (0x1F)
+#define PHY_DEV_1EH (0x1E)
+
+/* dev 07h, reg 03Ch: EEE Advertisement Register */
+#define EEE_ADV_REG (0x3C)
+#define EEE_ADV_1000BT (1 << 2)
+#define EEE_ADV_100BT (1 << 1)
+
+/* dev 1Eh, reg 013h: TX pair delay Register */
+#define TX_PAIR_DELAY_SEL_REG (0x013)
+
+/* dev 1Eh, reg 03Ch: Bypass power-down Register */
+#define BYPASS_POWER_DOWN_REG0 (0x3C)
+#define BYPASS_POWER_DOWN_REG1 (0x3D)
+#define BYPASS_POWER_DOWN_REG2 (0x3E)
+
+
+/* dev 1Eh, reg 145h: T10 Test Conttrol Register */
+#define PD_DIS (1 << 15)
+#define FC_TDI_EN (1 << 14)
+#define FC_DI_ACT (1 << 13)
+#define FC_LITN_NO_COMP (1 << 12)
+#define FC_MDI_CO_MDIX (3 << 3)
+#define FC_MDI_CO_MDI (2 << 3)
+#define FC_MDI_CO_NOT (0 << 3)
+#define FC_10T_POLAR_SWAP (3 << 1)
+#define FC_10T_POLAR_NORMAL (2 << 1)
+#define FC_10T_POLAR_NOT (0 << 1)
+
+/* dev 1Eh, reg 14Ah: DSP control 1 Register */
+#define DSP_CONTROL_REG (0x14A)
+#define PICMD_MISER_MODE_INT(v) (((v) & 0x7ff) << 5)
+
+/* dev 1Eh, reg 20Bh: DSP state machine PM control Register */
+#define DSP_FRE_PM_REG (0x20B)
+
+/* dev 1Eh, reg 20Eh: DSP state machine FRE control Register */
+#define DSP_FRE_REG (0x20E)
+#define DSP_FRE_RP_FSM_EN (1 << 4)
+#define DSP_FRE_DW_AUTO_INC (1 << 2)
+#define DSP_FRE_WR_EN (1 << 1)
+#define DSP_FRE_SW_RST (1 << 0)
+
+/* dev 1Eh, reg 2d1h: Register */
+#define RG_LPI_REG (0x2D1)
+#define RG_LPI_VCO_EEE_STGO_EN (1 << 10)
+#define RG_LPI_TR_READY (1 << 9)
+#define RG_LPI_SKIP_SD_SLV_TR (1 << 8)
+#define VCO_SLICER_THRES_H (0x33)
+
+/* dev 1Fh, reg 021h: LED Basic control Register */
+#define LED_BCR (0x021)
+#define LED_BCR_EXT_CTRL (1 << 15)
+#define LED_BCR_EVT_ALL (1 << 4)
+#define LED_BCR_CLK_EN (1 << 3)
+#define LED_BCR_TIME_TEST (1 << 2)
+#define LED_BCR_MODE_MASK (3)
+#define LED_BCR_MODE_DISABLE (0)
+#define LED_BCR_MODE_2LED (1)
+#define LED_BCR_MODE_3LED_1 (2)
+#define LED_BCR_MODE_3LED_2 (3)
+
+/* dev 1Fh, reg 022h: LED On Duration Register */
+#define LED_ON_DUR (0x022)
+#define LED_ON_DUR_MASK (0xFFFF)
+
+/* dev 1Fh, reg 023h: LED Blinking Duration Register */
+#define LED_BLK_DUR (0x023)
+#define LED_BLK_DUR_MASK (0xFFFF)
+
+/* dev 1Fh, reg 024h: LED On Control Register */
+#define LED_ON_CTRL(i) (0x024 + ( (i) * 2 ))
+#define LED_ON_EN (1 << 15)
+#define LED_ON_POL (1 << 14)
+#define LED_ON_EVT_MASK (0x7F)
+#define LED_ON_EVT_FORCE (1 << 6)
+#define LED_ON_EVT_HDX (1 << 5)
+#define LED_ON_EVT_FDX (1 << 4)
+#define LED_ON_EVT_LINK_DN (1 << 3)
+#define LED_ON_EVT_LINK_10M (1 << 2)
+#define LED_ON_EVT_LINK_100M (1 << 1)
+#define LED_ON_EVT_LINK_1000M (1 << 0)
+
+/* dev 1Fh, reg 025h: LED Blinking Control Register */
+#define LED_BLK_CTRL(i) (0x025 + ( (i) * 2 ))
+#define LED_BLK_EVT_MASK (0x3FF)
+#define LED_BLK_EVT_FORCE (1 << 9)
+#define LED_BLK_EVT_RX_IDL (1 << 8)
+#define LED_BLK_EVT_RX_CRC (1 << 7)
+#define LED_BLK_EVT_CLS (1 << 6)
+#define LED_BLK_EVT_10M_RX_ACT (1 << 5)
+#define LED_BLK_EVT_10M_TX_ACT (1 << 4)
+#define LED_BLK_EVT_100M_RX_ACT (1 << 3)
+#define LED_BLK_EVT_100M_TX_ACT (1 << 2)
+#define LED_BLK_EVT_1000M_RX_ACT (1 << 1)
+#define LED_BLK_EVT_1000M_TX_ACT (1 << 0)
+
+/* dev 1Fh, reg 27Bh: 10M Driver Register */
+#define CR_RG_TX_CM_10M(val) ( ( (val) & 0x3 ) << 12 )
+#define CR_RG_DELAY_TX_10M(val) ( ( (val) & 0x3 ) << 8 )
+#define CR_DA_TX_GAIN_10M_EEE(val) ( ( ( ( (val) / 10 ) - 3 ) & 0x7 ) << 4 )
+#define CR_DA_TX_GAIN_10M(val) ( ( ( (val) / 10 ) - 3 ) & 0x7 )
+
+/* dev 1Fh, reg 403h: PLL_group Control Register */
+#define PLL_GROUP_CONTROL_REG (0x403)
+#define RG_SYSPLL_DDSFBK_EN (1 << 12)
+#define RG_SYSPLL_DMY1 (3 << 8)
+#define RG_SYSPLL_EEE_EN (1 << 7) //1:enable/0:disable EEE mode when RG_SYSPLL_EEE_EN_PYPASS = 1
+#define RG_SYSPLL_EEE_EN_PYPASS (1 << 6) //EEE enable is control by 0:top/1:RG_SYSPLL_EEE_EN
+#define RG_SYSPLL_AFE_PWD (1 << 5) //1:enable/0:disable analog power down when RG_SYSPLL_AFE_PWD_BYPASS = 1
+#define RG_SYSPLL_AFE_PWD_BYPASS (1 << 4) //Analog power down is control by 0:top/1:RG_SYSPLL_AFE_PWD
+#define RG_SYSPLL_EFUSE_DIS (1 << 3) //1:efuse mode / 0:disable efuse mode, and use internal RG
+#define RG_CLKDRV_FORCEIN (3 << 1) //analog test mode
+#define RG_XSQ_LPF_EN (1 << 0) //analog test mode
+
+/* Register of ACL address */
+#define ARL_GLOBAL_CNTRL (REG_ARL_BASE_ADDRESS + 0x00c)
+#define ACL_BASE (REG_ARL_BASE_ADDRESS + 0x500)
+#define ACL_GLOBAL_CFG (ACL_BASE + 0x00)
+#define ACL_PORT_EN (ACL_BASE + 0x04)
+#define ACL_GROUP_CFG (ACL_BASE + 0x08)
+#define ACL_MEM_CFG (ACL_BASE + 0x0c)
+#define ACL_MEM_CFG_WDATA0 (ACL_BASE + 0x10)
+#define ACL_MEM_CFG_WDATA1 (ACL_BASE + 0x14)
+#define ACL_MEM_CFG_WDATA2 (ACL_BASE + 0x18)
+#define ACL_MEM_CFG_WDATA3 (ACL_BASE + 0x1c)
+#define ACL_MEM_CFG_RDATA0 (ACL_BASE + 0x20)
+#define ACL_MEM_CFG_RDATA1 (ACL_BASE + 0x24)
+#define ACL_MEM_CFG_RDATA2 (ACL_BASE + 0x28)
+#define ACL_MEM_CFG_RDATA3 (ACL_BASE + 0x2c)
+#define ACL_STATUS (ACL_BASE + 0x30)
+#define ACL_TRTCM (REG_ARL_BASE_ADDRESS + 0x100)
+#define ACL_TRTCMA (REG_ARL_BASE_ADDRESS + 0x104)
+#define ACL_TRTCMW_CBS (REG_ARL_BASE_ADDRESS + 0x108)
+#define ACL_TRTCMW_EBS (REG_ARL_BASE_ADDRESS + 0x10C)
+#define ACL_TRTCMW_CIR (REG_ARL_BASE_ADDRESS + 0x110)
+#define ACL_TRTCMW_EIR (REG_ARL_BASE_ADDRESS + 0x114)
+#define ACL_TRTCMR_CBS (REG_ARL_BASE_ADDRESS + 0x118)
+#define ACL_TRTCMR_EBS (REG_ARL_BASE_ADDRESS + 0x11c)
+#define ACL_TRTCMR_CIR (REG_ARL_BASE_ADDRESS + 0x120)
+#define ACL_TRTCMR_EIR (REG_ARL_BASE_ADDRESS + 0x124)
+
+#define ACLRMC (REG_ARL_BASE_ADDRESS + 0x470)
+#define ACLRMD1 (REG_ARL_BASE_ADDRESS + 0x474)
+#define ACLRMD2 (REG_ARL_BASE_ADDRESS + 0x478)
+
+#define ACL_UDF_BASE (REG_ARL_BASE_ADDRESS + 0x200)
+#define ACL_AUTC (ACL_UDF_BASE + 0x00)
+#define ACL_AUTW0 (ACL_UDF_BASE + 0x08)
+#define ACL_AUTW1 (ACL_UDF_BASE + 0x0c)
+#define ACL_AUTW2 (ACL_UDF_BASE + 0x10)
+#define ACL_AUTR0 (ACL_UDF_BASE + 0x20)
+#define ACL_AUTR1 (ACL_UDF_BASE + 0x24)
+#define ACL_AUTR2 (ACL_UDF_BASE + 0x28)
+
+/* Register of DPCR */
+#define BMU_PORT_BASE (0x10204000)
+#define DPCR_COLOR_OFFSET (0x20)
+#define DPCR_QUEUE_OFFSET (0x4)
+#define DPCR_EN(p) (BMU_PORT_BASE + (p * PORT_CTRL_PORT_OFFSET) + 0x08)
+#define DPCR_BASE (BMU_PORT_BASE + 0x10)
+#define DPCR(p, c, q) (DPCR_BASE + (p * PORT_CTRL_PORT_OFFSET) + (c * DPCR_COLOR_OFFSET) + (q * DPCR_QUEUE_OFFSET))
+
+/* Register of VLAN */
+#define VTCR (0x10200600)
+#define VLNWDATA0 (0x10200604)
+#define VLNWDATA1 (0x10200608)
+#define VLNWDATA2 (0x1020060C)
+#define VLNWDATA3 (0x10200610)
+#define VLNWDATA4 (0x10200614)
+#define VLNRDATA0 (0x10200618)
+#define VLNRDATA1 (0x1020061C)
+#define VLNRDATA2 (0x10200620)
+#define VLNRDATA3 (0x10200624)
+#define VLNRDATA4 (0x10200628)
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+
+#endif /* AIR_REG_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sec.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sec.h
new file mode 100644
index 0000000..1f56fdd
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sec.h
@@ -0,0 +1,308 @@
+/* FILE NAME: air_sec.h
+ * PURPOSE:
+ * Define the security function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_SEC_H
+#define AIR_SEC_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* Field for storm control */
+#define AIR_STORM_MAX_COUNT (255)
+
+#define AIR_MAX_NUM_OF_MAC (2048)
+
+typedef enum
+{
+ AIR_STORM_TYPE_BCST,
+ AIR_STORM_TYPE_MCST,
+ AIR_STORM_TYPE_UCST,
+ AIR_STORM_TYPE_LAST
+}AIR_STORM_TYPE_T;
+
+typedef enum
+{
+ AIR_STORM_UNIT_64K,
+ AIR_STORM_UNIT_256K,
+ AIR_STORM_UNIT_1M,
+ AIR_STORM_UNIT_4M,
+ AIR_STORM_UNIT_16M,
+ AIR_STORM_UNIT_32M,
+ AIR_STORM_UNIT_LAST
+}AIR_STORM_UNIT_T;
+
+/* Field for flooding port */
+typedef enum
+{
+ AIR_FLOOD_TYPE_BCST,
+ AIR_FLOOD_TYPE_MCST,
+ AIR_FLOOD_TYPE_UCST,
+ AIR_FLOOD_TYPE_QURY,
+ AIR_FLOOD_TYPE_LAST
+}AIR_FLOOD_TYPE_T;
+
+/* Port security port control configurations */
+typedef struct AIR_SEC_PORTSEC_PORT_CONFIG_S
+{
+ /* Source MAC address learning mode */
+ BOOL_T sa_lrn_en;
+
+ /* Learned source MAC address counter */
+ BOOL_T sa_lmt_en;
+
+ /* Rx SA allowable learning limit number */
+ UI32_T sa_lmt_cnt;
+
+}AIR_SEC_PORTSEC_PORT_CONFIG_T;
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_sec_setStormEnable
+ * PURPOSE:
+ * Enable or disable per port storm control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * storm_en -- TRUE
+ * FALSE
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setStormEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ const BOOL_T storm_en);
+
+/* FUNCTION NAME: air_sec_getStormEnable
+ * PURPOSE:
+ * Get per port status of storm control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * OUTPUT:
+ * ptr_storm_en -- TRUE
+ * FALSE
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getStormEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ BOOL_T *ptr_storm_en);
+
+/* FUNCTION NAME: air_sec_setStormRate
+ * PURPOSE:
+ * Set per port storm rate limit control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * count -- Count of the unit
+ * Range 0..255
+ * Rate = (count * unit) bps
+ * unit -- AIR_STORM_UNIT_64K
+ * AIR_STORM_UNIT_256K
+ * AIR_STORM_UNIT_1M
+ * AIR_STORM_UNIT_4M
+ * AIR_STORM_UNIT_16M
+ * AIR_STORM_UNIT_32M
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setStormRate(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ const UI32_T count,
+ const AIR_STORM_UNIT_T storm_unit);
+
+/* FUNCTION NAME: air_sec_getStormRate
+ * PURPOSE:
+ * Get per port storm rate limit control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * OUTPUT:
+ * ptr_count -- Count of the unit
+ * Range 0..255
+ * Rate = (count * unit) bps
+ * ptr_unit -- AIR_STORM_UNIT_64K
+ * AIR_STORM_UNIT_256K
+ * AIR_STORM_UNIT_1M
+ * AIR_STORM_UNIT_4M
+ * AIR_STORM_UNIT_16M
+ * AIR_STORM_UNIT_32M
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getStormRate(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ UI32_T *ptr_count,
+ AIR_STORM_UNIT_T *ptr_unit);
+
+/* FUNCTION NAME: air_sec_setFldMode
+ * PURPOSE:
+ * Set per port flooding status for unknown type frame.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port to setting
+ * type -- AIR_FLOOD_TYPE_BCST
+ * AIR_FLOOD_TYPE_MCST
+ * AIR_FLOOD_TYPE_UCST
+ * AIR_FLOOD_TYPE_QURY
+ * fld_en -- TRUE : flooding specific type frame for specific port
+ * FALSE: drop specific type frame for specific port
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setFldMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_FLOOD_TYPE_T type,
+ const BOOL_T fld_en);
+
+/* FUNCTION NAME: air_sec_getFldMode
+ * PURPOSE:
+ * Get per port flooding status for unknown type frame.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port to setting
+ * type -- AIR_FLOOD_TYPE_BCST
+ * AIR_FLOOD_TYPE_MCST
+ * AIR_FLOOD_TYPE_UCST
+ * AIR_FLOOD_TYPE_QURY
+ * OUTPUT:
+ * ptr_fld_en -- TRUE : flooding specific type frame for specific port
+ * FALSE: drop specific type frame for specific port
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getFldMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_FLOOD_TYPE_T type,
+ BOOL_T *ptr_fld_en);
+
+/* FUNCTION NAME: air_sec_setPortSecPortCfg
+ * PURPOSE:
+ * Set port security configurations for specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Port ID
+ * port_config -- Structure of port configuration.
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setPortSecPortCfg(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_SEC_PORTSEC_PORT_CONFIG_T port_config);
+
+/* FUNCTION NAME: air_sec_getPortSecPortCfg
+ * PURPOSE:
+ * Get port security configurations for specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Port ID
+ *
+ * OUTPUT:
+ * ptr_port_config -- Structure of port configuration.
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getPortSecPortCfg(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_SEC_PORTSEC_PORT_CONFIG_T *ptr_port_config);
+
+#endif /* End of AIR_SEC_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sptag.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sptag.h
new file mode 100644
index 0000000..99d2028
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_sptag.h
@@ -0,0 +1,277 @@
+/* FILE NAME: air_sptag.h
+ * PURPOSE:
+ * Define the Special Tag function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_SPTAG_H
+#define AIR_SPTAG_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+#define AIR_STAG_BUF_LEN (4)
+#define AIR_STAG_ALIGN_BIT_WIDTH (8)
+#define AIR_STAG_REPLACE_MODE_MAX_DP (10)
+
+/* cpu tx stag offset */
+#define AIR_STAG_TX_OPC_BIT_OFFSET (5)
+#define AIR_STAG_TX_OPC_BIT_WIDTH (3)
+#define AIR_STAG_TX_VPM_BIT_OFFSET (0)
+#define AIR_STAG_TX_VPM_BIT_WIDTH (2)
+#define AIR_STAG_TX_PCP_BIT_OFFSET (5)
+#define AIR_STAG_TX_PCP_BIT_WIDTH (3)
+#define AIR_STAG_TX_DEI_BIT_OFFSET (4)
+#define AIR_STAG_TX_DEI_BIT_WIDTH (1)
+
+/* cpu rx stag offset */
+#define AIR_STAG_RX_RSN_BIT_OFFSET (2)
+#define AIR_STAG_RX_RSN_BIT_WIDTH (3)
+#define AIR_STAG_RX_VPM_BIT_OFFSET (0)
+#define AIR_STAG_RX_VPM_BIT_WIDTH (2)
+#define AIR_STAG_RX_SP_BIT_OFFSET (0)
+#define AIR_STAG_RX_SP_BIT_WIDTH (5)
+#define AIR_STAG_RX_PCP_BIT_OFFSET (5)
+#define AIR_STAG_RX_PCP_BIT_WIDTH (3)
+#define AIR_STAG_RX_DEI_BIT_OFFSET (4)
+#define AIR_STAG_RX_DEI_BIT_WIDTH (1)
+#define AIR_PORT_NUM (6)
+
+#define AIR_PORT_FOREACH(bitmap, port) \
+ for(port = 0; port < AIR_PORT_NUM; port++) \
+ if(bitmap & BIT(port))
+
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef enum
+{
+ AIR_STAG_MODE_INSERT,
+ AIR_STAG_MODE_REPLACE,
+ AIR_STAG_MODE_LAST
+} AIR_STAG_MODE_T;
+
+typedef enum
+{
+ /* Egress DP is port map */
+ AIR_STAG_OPC_PORTMAP,
+
+ /* Egress DP is port id */
+ AIR_STAG_OPC_PORTID,
+
+ /* Forward the packet according to lookup result */
+ AIR_STAG_OPC_LOOKUP,
+ AIR_STAG_OPC_LAST
+} AIR_STAG_OPC_T;
+
+typedef enum
+{
+ AIR_STAG_REASON_CODE_NORMAL,
+ AIR_STAG_REASON_CODE_SFLOW,
+ AIR_STAG_REASON_CODE_TTL_ERR,
+ AIR_STAG_REASON_CODE_ACL,
+ AIR_STAG_REASON_CODE_SA_FULL,
+ AIR_STAG_REASON_CODE_PORT_MOVE_ERR,
+ AIR_STAG_REASON_CODE_LAST,
+} AIR_STAG_REASON_CODE_T;
+
+typedef enum
+{
+ AIR_STAG_VPM_UNTAG,
+ AIR_STAG_VPM_TPID_8100,
+ AIR_STAG_VPM_TPID_88A8,
+ AIR_STAG_VPM_TPID_PRE_DEFINED,
+ AIR_STAG_VPM_LAST,
+} AIR_STAG_VPM_T;
+
+typedef struct AIR_STAG_TX_PARA_S
+{
+ /* destination port operation code */
+ AIR_STAG_OPC_T opc;
+
+ /* tag attribute */
+ AIR_STAG_VPM_T vpm;
+
+ /* destination port map */
+ UI32_T pbm;
+
+ /* PRI in vlan tag */
+ UI32_T pri :3;
+
+ /* CFI in vlan tag */
+ UI32_T cfi :1;
+
+ /* VID in vlan tag */
+ UI32_T vid :12;
+} AIR_STAG_TX_PARA_T;
+
+
+typedef struct AIR_SPTAG_RX_PARA_S
+{
+ AIR_STAG_REASON_CODE_T rsn; /* tag attribute */
+ AIR_STAG_VPM_T vpm; /* tag attribute */
+ UI32_T spn; /* source port */
+ UI32_T pri; /* PRI in vlan tag */
+ UI32_T cfi; /* CFI in vlan tag */
+ UI32_T vid; /* VID in vlan tag */
+}AIR_SPTAG_RX_PARA_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_sptag_setState
+ * PURPOSE:
+ * Set special tag enable/disable for port
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ * sp_en -- special tag Enable or Disable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_setState(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T sp_en);
+
+/* FUNCTION NAME: air_switch_getCpuPortEn
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ *
+ * OUTPUT:
+ * sp_en -- special tag enable or disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_getState(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *sp_en);
+
+/* FUNCTION NAME: air_sptag_setMode
+ * PURPOSE:
+ * Set special tag enable/disable for port
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ * mode -- insert mode or replace mode
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_setMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T mode);
+
+/* FUNCTION NAME: air_sptag_getMode
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ *
+ * OUTPUT:
+ * mode -- insert or replace mode
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_getMode(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *mode);
+
+/* FUNCTION NAME: air_sptag_encodeTx
+ * PURPOSE:
+ * Encode tx special tag into buffer.
+ * INPUT:
+ * unit -- Device ID
+ * ptr_sptag_tx -- Special tag parameters
+ * ptr_buf -- Buffer address
+ * ptr_len -- Buffer length
+ * OUTPUT:
+ * ptr_len -- Written buffer length
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_encodeTx(
+ const UI32_T unit,
+ const AIR_STAG_MODE_T mode,
+ AIR_STAG_TX_PARA_T *ptr_sptag_tx,
+ UI8_T *ptr_buf,
+ UI32_T *ptr_len);
+
+/* FUNCTION NAME: air_sptag_decodeRx
+ * PURPOSE:
+ * Decode rx special tag from buffer.
+ * INPUT:
+ * unit -- Device ID
+ * ptr_buf -- Buffer address
+ * len -- Buffer length
+ * OUTPUT:
+ * ptr_sptag_rx -- Special tag parameters
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_decodeRx(
+ const UI32_T unit,
+ const UI8_T *ptr_buf,
+ const UI32_T len,
+ AIR_SPTAG_RX_PARA_T *ptr_sptag_rx);
+
+#endif /* AIR_SPTAG_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_stp.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_stp.h
new file mode 100644
index 0000000..2497392
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_stp.h
@@ -0,0 +1,101 @@
+/* FILE NAME: air_stp.h
+ * PURPOSE:
+ * Define the STP function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_STP_H
+#define AIR_STP_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* Definition of STP state
+ * 2'b00: Disable(STP) / Discard(RSTP)
+ * 2'b01: Listening(STP) / Discard(RSTP)
+ * 2'b10: Learning(STP) / Learning(RSTP)
+ * 2'b11: Forwarding(STP) / Forwarding(RSTP)
+ * */
+typedef enum
+{
+ AIR_STP_STATE_DISABLE,
+ AIR_STP_STATE_LISTEN,
+ AIR_STP_STATE_LEARN,
+ AIR_STP_STATE_FORWARD,
+ AIR_STP_STATE_LAST
+}AIR_STP_STATE_T;
+
+#define AIR_STP_FID_NUMBER (16)
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+/* FUNCTION NAME: air_stp_setPortstate
+ * PURPOSE:
+ * Set the STP port state for a specifiec port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * fid -- Filter ID for MSTP
+ * state -- AIR_STP_STATE_DISABLE
+ * AIR_STP_STATE_LISTEN
+ * AIR_STP_STATE_LEARN
+ * AIR_STP_STATE_FORWARD
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_stp_setPortstate(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T fid,
+ const AIR_STP_STATE_T state);
+
+/* FUNCTION NAME: air_stp_getPortstate
+ * PURPOSE:
+ * Get the STP port state for a specifiec port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * fid -- Filter ID for MSTP
+ *
+ * OUTPUT:
+ * ptr_state -- AIR_STP_STATE_DISABLE
+ * AIR_STP_STATE_LISTEN
+ * AIR_STP_STATE_LEARN
+ * AIR_STP_STATE_FORWARD
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_stp_getPortstate(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T fid,
+ AIR_STP_STATE_T *ptr_state);
+
+#endif /* End of AIR_STP_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_switch.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_switch.h
new file mode 100644
index 0000000..0c10cc4
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_switch.h
@@ -0,0 +1,250 @@
+/* FILE NAME: air_switch.h
+ * PURPOSE:
+ * Define the switch function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_SWITCH_H
+#define AIR_SWITCH_H
+
+/* INCLUDE FILE DECLARATIONS
+*/
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+#define SYS_INT_EN 0x1021C010
+#define SYS_INT_STS 0x1021C014
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef enum
+{
+ AIR_SYS_INTR_TYPE_PHY0_LC = 0,
+ AIR_SYS_INTR_TYPE_PHY1_LC,
+ AIR_SYS_INTR_TYPE_PHY2_LC,
+ AIR_SYS_INTR_TYPE_PHY3_LC,
+ AIR_SYS_INTR_TYPE_PHY4_LC,
+ AIR_SYS_INTR_TYPE_PHY5_LC,
+ AIR_SYS_INTR_TYPE_PHY6_LC,
+ AIR_SYS_INTR_TYPE_PHY7_LC,
+ AIR_SYS_INTR_TYPE_MAC_PC = 16,
+ AIR_SYS_INTR_TYPE_LAST
+}AIR_SYS_INTR_TYPE_T;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+*/
+
+/* FUNCTION NAME: air_switch_setCpuPort
+ * PURPOSE:
+ * Set CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- CPU port index
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setCpuPort(
+ const UI32_T unit,
+ const UI32_T portmap);
+
+/* FUNCTION NAME: air_switch_getCpuPort
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_port -- CPU port index
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getCpuPort(
+ const UI32_T unit,
+ UI32_T *ptr_portmap);
+
+/* FUNCTION NAME: air_switch_setCpuPortEN
+ * PURPOSE:
+ * Set CPU port Enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * cpu_en -- CPU Port Enable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setCpuPortEn(
+ const UI32_T unit,
+ const BOOL_T cpu_en);
+
+/* FUNCTION NAME: air_switch_getCpuPortEn
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * cpu_en -- CPU Port enable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getCpuPortEn(
+ const UI32_T unit,
+ BOOL_T *cpu_en);
+
+/* FUNCTION NAME: air_switch_setSysIntrEn
+ * PURPOSE:
+ * Set system interrupt enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ * enable -- system interrupt enable/disable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setSysIntrEn(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_switch_getSysIntrEn
+ * PURPOSE:
+ * Get system interrupt enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ *
+ * OUTPUT:
+ * ptr_enable -- system interrupt enable/disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getSysIntrEn(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ BOOL_T *ptr_enable);
+
+/* FUNCTION NAME: air_switch_setSysIntrStatus
+ * PURPOSE:
+ * Set system interrupt status
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ * enable -- write TRUE to clear interrupt status
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setSysIntrStatus(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_switch_getSysIntrStatus
+ * PURPOSE:
+ * Get system interrupt status
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ *
+ * OUTPUT:
+ * ptr_enable -- system interrupt status
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getSysIntrStatus(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ BOOL_T *ptr_enable);
+
+/* FUNCTION NAME: air_switch_reset
+ * PURPOSE:
+ * Reset whole system
+ *
+ * INPUT:
+ * None
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_reset(
+ const UI32_T unit);
+
+#endif /* End of AIR_SWITCH_H */
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_types.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_types.h
new file mode 100644
index 0000000..3bae3bd
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_types.h
@@ -0,0 +1,56 @@
+/* FILE NAME: air_types.h
+ * PURPOSE:
+ * Define the commom data type in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_TYPES_H
+#define AIR_TYPES_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+#ifndef LOW
+#define LOW 0
+#endif
+
+#ifndef HIGH
+#define HIGH 1
+#endif
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+typedef int BOOL_T;
+typedef signed char I8_T;
+typedef unsigned char UI8_T;
+typedef signed short I16_T;
+typedef unsigned short UI16_T;
+typedef signed int I32_T;
+typedef unsigned int UI32_T;
+typedef char C8_T;
+typedef unsigned long long UI64_T;
+
+typedef UI8_T AIR_MAC_T[6];
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+
+#endif /* AIR_TYPES_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_ver.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_ver.h
new file mode 100644
index 0000000..0681b6c
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_ver.h
@@ -0,0 +1,29 @@
+/* FILE NAME: air_ver.h
+ * PURPOSE:
+ * Define the version for AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+#ifndef AIR_VER_H
+#define AIR_VER_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#define AIR_VER_SDK "v1.0.1"
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+
+#endif /* AIR_VER_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_vlan.h b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_vlan.h
new file mode 100644
index 0000000..1ae6237
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/inc/air_vlan.h
@@ -0,0 +1,977 @@
+/* FILE NAME: air_vlan.h
+ * PURPOSE:
+ * Define the vlan functions in AIR SDK.
+ * NOTES:
+ */
+
+#ifndef AIR_VLAN_H
+#define AIR_VLAN_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#define AIR_VLAN_ID_MIN 0
+#define AIR_VLAN_ID_MAX 4095
+#define AIR_DEFAULT_VLAN_ID 1
+
+#define AIR_FILTER_ID_MAX 7
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+typedef enum
+{
+ AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_UNTAGGED = 0,
+ AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_TAGGED = 2,
+ AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_LAST,
+} AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_T;
+
+typedef enum
+{
+ AIR_PORT_EGS_TAG_ATTR_UNTAGGED = 0,
+ AIR_PORT_EGS_TAG_ATTR_SWAP,
+ AIR_PORT_EGS_TAG_ATTR_TAGGED,
+ AIR_PORT_EGS_TAG_ATTR_STACK,
+ AIR_PORT_EGS_TAG_ATTR_LAST
+} AIR_PORT_EGS_TAG_ATTR_T;
+
+typedef enum
+{
+ AIR_VLAN_ACCEPT_FRAME_TYPE_ALL = 0, /* untagged, priority-tagged and tagged */
+ AIR_VLAN_ACCEPT_FRAME_TYPE_TAG_ONLY, /* tagged */
+ AIR_VLAN_ACCEPT_FRAME_TYPE_UNTAG_ONLY, /* untagged and priority-tagged */
+ AIR_VLAN_ACCEPT_FRAME_TYPE_RESERVED, /* reserved */
+ AIR_VLAN_ACCEPT_FRAME_TYPE_LAST
+} AIR_VLAN_ACCEPT_FRAME_TYPE_T;
+
+typedef enum
+{
+ AIR_LEAKY_PKT_TYPE_UNICAST = 0, /* unicast pkt */
+ AIR_LEAKY_PKT_TYPE_MULTICAST, /* multicast pkt */
+ AIR_LEAKY_PKT_TYPE_BROADCAST, /* broadcast pkt */
+ AIR_LEAKY_PKT_TYPE_LAST
+} AIR_LEAKY_PKT_TYPE_T;
+
+typedef enum
+{
+ AIR_VLAN_PORT_ATTR_USER_PORT = 0, /* user port */
+ AIR_VLAN_PORT_ATTR_STACK_PORT, /* stack port */
+ AIR_VLAN_PORT_ATTR_TRANSLATION_PORT, /* translation port */
+ AIR_VLAN_PORT_ATTR_TRANSPARENT_PORT, /* transparent port */
+ AIR_VLAN_PORT_ATTR_LAST
+} AIR_VLAN_PORT_ATTR_T;
+
+typedef enum
+{
+ AIR_IGR_PORT_EG_TAG_ATTR_DISABLE = 0,
+ AIR_IGR_PORT_EG_TAG_ATTR_CONSISTENT,
+ AIR_IGR_PORT_EG_TAG_ATTR_UNTAGGED = 4,
+ AIR_IGR_PORT_EG_TAG_ATTR_SWAP,
+ AIR_IGR_PORT_EG_TAG_ATTR_TAGGED,
+ AIR_IGR_PORT_EG_TAG_ATTR_STACK,
+ AIR_IGR_PORT_EG_TAG_ATTR_LAST
+} AIR_IGR_PORT_EG_TAG_ATTR_T;
+
+typedef union AIR_VLAN_ENTRY_S
+{
+ UI8_T valid : 1;
+ struct
+ {
+ UI32_T vlan_table0;
+ UI32_T vlan_table1;
+ } vlan_table;
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T fid : 4;
+ UI64_T ivl : 1;
+ UI64_T copy_pri : 1;
+ UI64_T user_pri : 3;
+ UI64_T eg_ctrl_en : 1;
+ UI64_T eg_con : 1;
+ UI64_T eg_ctrl : 14;
+ UI64_T port_mem : 7;
+ UI64_T port_stag : 1;
+ UI64_T stag : 12;
+ UI64_T unm_vlan_drop : 1;
+ } vlan_entry_format;
+} AIR_VLAN_ENTRY_T;
+
+typedef union AIR_VLAN_ENTRY_ATTR_S
+{
+ UI8_T valid : 1;
+ struct
+ {
+ UI32_T vlan_table0;
+ UI32_T vlan_table1;
+ UI32_T vlan_table2;
+ UI32_T vlan_table3;
+ UI32_T vlan_table4;
+ } vlan_table;
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T fid : 4;
+ UI64_T ivl : 1;
+ UI64_T copy_pri : 1;
+ UI64_T user_pri : 3;
+ UI64_T eg_ctrl_en : 1;
+ UI64_T eg_con : 1;
+ UI64_T eg_ctrl : 14;
+ UI64_T port_mem : 7;
+ UI64_T port_stag : 1;
+ UI64_T stag : 12;
+ UI64_T unm_vlan_drop : 1;
+ } vlan_entry_format;
+#if 0
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T type : 3;
+ UI64_T mac_addr : 48;
+ UI64_T mac_mask_len : 6;
+ UI64_T priority : 3;
+ UI64_T :0;
+ UI64_T vid : 12;
+ } mac_based_vlan_entry_format;
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T type : 3;
+ UI64_T check_field : 36;
+ UI64_T :0;
+ UI64_T check_field_mask : 36;
+ UI64_T untagged_packet : 1;
+ UI64_T vlan_priority : 3;
+ UI64_T svid : 12;
+ } qinq_based_vlan_entry_format;
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T type : 3;
+ UI64_T ipv4 : 32;
+ UI64_T :0;
+ UI64_T subnetmask : 32;
+ UI64_T priority : 3;
+ UI64_T cvid : 12;
+ } ipv4_based_vlan_entry_format;
+ struct
+ {
+ UI64_T valid : 1;
+ UI64_T :0;
+ UI64_T ipv6_high : 64;
+ UI64_T ipv6_low : 64;
+ UI64_T subnetmask : 8;
+ UI64_T priority : 3;
+ UI64_T cvid : 12;
+ } ipv6_based_vlan_entry_format;
+#endif
+} AIR_VLAN_ENTRY_ATTR_T;
+
+void
+_air_vlan_readEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_T* vlan_entry);
+
+void
+_air_vlan_writeEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_T* vlan_entry);
+
+void
+_air_untagged_vlan_readEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T* vlan_entry);
+
+void
+_air_untagged_vlan_writeEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T* vlan_entry);
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+/* FUNCTION NAME: air_vlan_create
+ * PURPOSE:
+ * Create the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * p_attr -- vlan attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan creation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_create(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T *p_attr);
+
+/* FUNCTION NAME: air_vlan_destroy
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan destroy failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_destroy(
+ const UI32_T unit,
+ const UI16_T vid);
+
+/* FUNCTION NAME: air_vlan_destroyAll
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan destroy failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_destroyAll(
+ const UI32_T unit,
+ const UI32_T keep_and_restore_default_vlan);
+
+/* FUNCTION NAME: air_vlan_reset
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully reset the data.
+ * AIR_E_OTHERS -- Vlan reset failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_reset(
+ const UI32_T unit,
+ const UI16_T vid);
+
+/* FUNCTION NAME: air_vlan_setFid
+ * PURPOSE:
+ * Set the filter id of the vlan to the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * fid -- filter id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setFid(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI8_T fid);
+
+/* FUNCTION NAME: air_vlan_getFid
+ * PURPOSE:
+ * Get the filter id of the vlan from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id to be created
+ * OUTPUT:
+ * p_fid -- filter id
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getFid(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI8_T *p_fid);
+
+/* FUNCTION NAME: air_vlan_addMemberPort
+ * PURPOSE:
+ * Add one vlan member to the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_addMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port);
+
+/* FUNCTION NAME: air_vlan_delMemberPort
+ * PURPOSE:
+ * Delete one vlan member from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_delMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port);
+
+/* FUNCTION NAME: air_vlan_setMemberPort
+ * PURPOSE:
+ * Replace the vlan members in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port_bitmap -- member port bitmap
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port_bitmap);
+
+/* FUNCTION NAME: air_vlan_getMemberPort
+ * PURPOSE:
+ * Get the vlan members from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * port_bitmap -- member port bitmap
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI32_T *p_port_bitmap);
+
+/* FUNCTION NAME: air_vlan_setIVL
+ * PURPOSE:
+ * Set L2 lookup mode IVL/SVL for L2 traffic.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable IVL
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setIVL(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_vlan_getIVL
+ * PURPOSE:
+ * Get L2 lookup mode IVL/SVL for L2 traffic.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_enable -- enable IVL
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getIVL(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *p_enable);
+
+/* FUNCTION NAME: air_vlan_setPortAcceptFrameType
+ * PURPOSE:
+ * Set vlan accept frame type of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * type -- accept frame type
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortAcceptFrameType(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_VLAN_ACCEPT_FRAME_TYPE_T type);
+
+/* FUNCTION NAME: air_vlan_getPortAcceptFrameType
+ * PURPOSE:
+ * Get vlan accept frame type of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_type -- accept frame type
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortAcceptFrameType(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_VLAN_ACCEPT_FRAME_TYPE_T *p_type);
+
+/* FUNCTION NAME: air_vlan_setPortLeakyVlanEnable
+ * PURPOSE:
+ * Set leaky vlan enable of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pkt_type -- packet type
+ * enable -- enable leaky
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortLeakyVlanEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_LEAKY_PKT_TYPE_T pkt_type,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_vlan_getPortLeakyVlanEnable
+ * PURPOSE:
+ * Get leaky vlan enable of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pkt_type -- packet type
+ * OUTPUT:
+ * p_enable -- enable leaky
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortLeakyVlanEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_LEAKY_PKT_TYPE_T pkt_type,
+ BOOL_T *p_enable);
+
+/* FUNCTION NAME: air_vlan_setPortAttr
+ * PURPOSE:
+ * Set vlan port attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- vlan port attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_VLAN_PORT_ATTR_T attr);
+
+/* FUNCTION NAME: air_vlan_getPortAttr
+ * PURPOSE:
+ * Get vlan port attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_attr -- vlan port attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_VLAN_PORT_ATTR_T *p_attr);
+
+/* FUNCTION NAME: air_vlan_setIgrPortTagAttr
+ * PURPOSE:
+ * Set vlan incoming port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- egress tag attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setIgrPortTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_IGR_PORT_EG_TAG_ATTR_T attr);
+
+/* FUNCTION NAME: air_vlan_getIgrPortTagAttr
+ * PURPOSE:
+ * Get vlan incoming port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_attr -- egress tag attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getIgrPortTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_IGR_PORT_EG_TAG_ATTR_T *p_attr);
+
+/* FUNCTION NAME: air_vlan_setPortEgsTagAttr
+ * PURPOSE:
+ * Set vlan port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- egress tag attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortEgsTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_PORT_EGS_TAG_ATTR_T attr);
+
+/* FUNCTION NAME: air_vlan_getPortEgsTagAttr
+ * PURPOSE:
+ * Get vlan port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_attr -- egress tag attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortEgsTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_EGS_TAG_ATTR_T *p_attr);
+
+/* FUNCTION NAME: air_vlan_setPortOuterTPID
+ * PURPOSE:
+ * Set stack tag TPID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * tpid -- TPID
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortOuterTPID(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI16_T tpid);
+
+/* FUNCTION NAME: air_vlan_getPortOuterTPID
+ * PURPOSE:
+ * Get stack tag TPID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_tpid -- TPID
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortOuterTPID(
+ const UI32_T unit,
+ const UI32_T port,
+ UI16_T *p_tpid);
+
+/* FUNCTION NAME: air_vlan_setPortPVID
+ * PURPOSE:
+ * Set PVID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pvid -- native vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortPVID(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI16_T pvid);
+
+/* FUNCTION NAME: air_vlan_getPortPVID
+ * PURPOSE:
+ * Get PVID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * p_pvid -- native vlan id
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortPVID(
+ const UI32_T unit,
+ const UI32_T port,
+ UI16_T *p_pvid);
+
+/* FUNCTION NAME: air_vlan_setServiceTag
+ * PURPOSE:
+ * Set Vlan service tag.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * stag -- service stag
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setServiceTag(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI16_T stag);
+
+/* FUNCTION NAME: air_vlan_getServiceTag
+ * PURPOSE:
+ * Get Vlan service tag.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_stag -- service stag
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getServiceTag(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI16_T *p_stag);
+
+/* FUNCTION NAME: air_vlan_setEgsTagCtlEnable
+ * PURPOSE:
+ * Set per vlan egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable vlan egress tag control
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setEgsTagCtlEnable(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_vlan_getEgsTagCtlEnable
+ * PURPOSE:
+ * Get per vlan egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_enable -- enable vlan egress tag control
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getEgsTagCtlEnable(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *p_enable);
+
+/* FUNCTION NAME: air_vlan_setEgsTagConsistent
+ * PURPOSE:
+ * Set per vlan egress tag consistent.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable vlan egress tag consistent
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setEgsTagConsistent(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_vlan_getEgsTagConsistent
+ * PURPOSE:
+ * Get per vlan egress tag consistent.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_enable -- enable vlan egress tag consistent
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getEgsTagConsistent(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *p_enable);
+
+/* FUNCTION NAME: air_vlan_setPortBasedStag
+ * PURPOSE:
+ * Set vlan port based stag enable.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- vlan port based stag enable
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortBasedStag(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable);
+
+/* FUNCTION NAME: air_vlan_getPortBasedStag
+ * PURPOSE:
+ * Get vlan port based stag enable.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_enable -- vlan port based stag enable
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortBasedStag(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *p_enable);
+
+/* FUNCTION NAME: air_vlan_setPortEgsTagCtl
+ * PURPOSE:
+ * Set vlan port egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * tag_ctl -- egress tag control
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortEgsTagCtl(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port,
+ const AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_T tag_ctl);
+
+/* FUNCTION NAME: air_vlan_getPortEgsTagCtl
+ * PURPOSE:
+ * Get vlan port egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * p_tag_ctl -- egress tag control
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortEgsTagCtl(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port,
+ AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_T *ptr_tag_ctl);
+
+#endif /* AIR_VLAN_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_acl.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_acl.c
new file mode 100644
index 0000000..9be3e0f
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_acl.c
@@ -0,0 +1,2032 @@
+/* FILE NAME: air_acl.c
+ * PURPOSE:
+ * Define the ACL function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+#define ACL_DERIVE_TBL_MULTIFIELDS(data_buffer, offset, width, dst) \
+({ \
+ UI32_T value = 0; \
+ _deriveTblMultiFields((data_buffer), (offset), (width), &value); \
+ dst = value; \
+})
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+static AIR_ERROR_NO_T
+_checkDone(
+ const UI32_T unit,
+ const AIR_ACL_CHECK_TYPE_T type)
+{
+ UI32_T check_bit = 0, i = 0, reg = 0, value = 0, offset = 0;
+
+ switch(type)
+ {
+ case AIR_ACL_CHECK_ACL:
+ check_bit = 1;
+ reg = ACL_MEM_CFG;
+ offset = ACL_MEM_CFG_DONE_OFFSET;
+ break;
+ case AIR_ACL_CHECK_UDF:
+ check_bit = 0;
+ reg = ACL_AUTC;
+ offset = ACL_UDF_ACC_OFFSET;
+ break;
+ case AIR_ACL_CHECK_TRTCM:
+ check_bit = 0;
+ reg = ACL_TRTCMA;
+ offset = ACL_TRTCM_BUSY_OFFSET;
+ break;
+ case AIR_ACL_CHECK_METER:
+ check_bit = 0;
+ reg = ACLRMC;
+ offset = ACL_RATE_BUSY_OFFSET;
+ break;
+ default:
+ return AIR_E_BAD_PARAMETER;
+ }
+ for(i=0; i < ACL_MAX_BUSY_TIME; i++)
+ {
+ aml_readReg(unit, reg, &value);
+ if (check_bit == (value >> offset))
+ {
+ break;
+ }
+ AIR_UDELAY(1);
+ }
+ if(i >= ACL_MAX_BUSY_TIME)
+ {
+ return AIR_E_TIMEOUT;
+ }
+ return AIR_E_OK;
+}
+
+static void
+_convertToTCcell(
+ const UI32_T *data0,
+ const UI32_T *data1,
+ UI32_T *arr0,
+ UI32_T *arr1,
+ UI32_T size)
+{
+ UI32_T i = 0;
+
+ for(i = 0; i < size; i++)
+ {
+ arr0[i] = data0[i] | (~data1[i]);
+ arr1[i] = (~data0[i]) | (~data1[i]);
+ }
+}
+
+static void
+_parseFromTCcell(
+ const UI32_T *data0,
+ const UI32_T *data1,
+ UI32_T *arr0,
+ UI32_T *arr1,
+ UI32_T size)
+{
+ UI32_T i = 0;
+
+ for(i = 0; i < size; i++)
+ {
+ arr1[i] = ~(data0[i] & data1[i]);
+ arr0[i] = data0[i] | (~arr1[i]);
+ }
+}
+
+static int
+_fillTblMultiFields(
+ UI32_T *data_buffer,
+ UI32_T data_count,
+ const UI32_T offset,
+ const UI32_T width,
+ const UI32_T value)
+{
+ UI32_T data_index = 0, bit_index = 0;
+ UI32_T extended_data[2] = {0};
+ UI32_T extended_mask[2] = {0};
+ UI32_T msk;
+ UI32_T val;
+
+ AIR_CHECK_PTR(data_buffer);
+
+ if((0 == data_count) || (0 == width) || (width > 32) || (offset+width > data_count*32))
+ {
+ return 0;
+ }
+
+ msk = ((1U<<(width-1U))<<1U)-1U;
+ val = value & msk;
+ data_index = offset / 32;
+ bit_index = offset % 32;
+
+ extended_data[0] = val << bit_index;
+ extended_data[1] = (val >> (31U-bit_index))>>1U;
+ extended_mask[0] = msk << bit_index;
+ extended_mask[1] = (msk >> (31U-bit_index))>>1U;
+
+ data_buffer[data_index] = (data_buffer[data_index] & ~extended_mask[0]) | extended_data[0];
+ if ((data_index+1)<data_count)
+ {
+ data_buffer[data_index+1] = (data_buffer[data_index+1] & ~extended_mask[1]) | extended_data[1];
+ }
+
+ return 0;
+}
+
+static int
+_deriveTblMultiFields(
+ UI32_T *data_buffer,
+ const UI32_T offset,
+ const UI32_T width,
+ UI32_T *ptr_value)
+{
+ UI32_T data_index = 0, bit_index = 0;
+ UI32_T extended_data[2] = {0};
+ UI32_T extended_mask[2] = {0};
+ UI32_T msk = 0;
+
+ AIR_CHECK_PTR(data_buffer);
+ AIR_CHECK_PTR(ptr_value);
+
+ if(width==0 || width>32)
+ {
+ return 0;
+ }
+ msk = ((1U<<(width-1U))<<1U)-1U;
+ data_index = offset / 32;
+ bit_index = offset % 32;
+
+ extended_mask[0] = msk << bit_index;
+ extended_mask[1] = (msk >> (31U-bit_index))>>1U;
+ extended_data[0] = (data_buffer[data_index] & extended_mask[0]) >> bit_index;
+ extended_data[1] = ((data_buffer[data_index+1] & extended_mask[1]) << (31U-bit_index))<<1U;
+
+ *ptr_value = extended_data[0] | extended_data[1];
+ return 0;
+}
+
+static void
+_air_acl_setRuleTable(
+ const AIR_ACL_RULE_TYPE_T type,
+ const BOOL_T iskey,
+ const AIR_ACL_FIELD_T *ptr_field,
+ UI32_T *data)
+{
+ UI32_T n = 0;
+
+ switch(type)
+ {
+ case AIR_ACL_RULE_TYPE_0:
+ if(TRUE == iskey)
+ {
+ _fillTblMultiFields(data, 12, RULE_TYPE0_OFFSET, RULE_TYPE0_WIDTH, 0);
+ }
+ else
+ {
+ _fillTblMultiFields(data, 12, RULE_TYPE0_OFFSET, RULE_TYPE0_WIDTH, 1);
+ }
+ for(n=0; n<6; n++)
+ {
+ _fillTblMultiFields(data, 12, DMAC_OFFSET + DMAC_WIDTH*(5-n), DMAC_WIDTH, ptr_field->dmac[n]);
+ }
+ for(n=0; n<6; n++)
+ {
+ _fillTblMultiFields(data, 12, SMAC_OFFSET + SMAC_WIDTH*(5-n), SMAC_WIDTH, ptr_field->smac[n]);
+ }
+ _fillTblMultiFields(data, 12, STAG_OFFSET, STAG_WIDTH, ptr_field->stag);
+ _fillTblMultiFields(data, 12, CTAG_OFFSET, CTAG_WIDTH, ptr_field->ctag);
+ _fillTblMultiFields(data, 12, ETYPE_OFFSET, ETYPE_WIDTH, ptr_field->etype);
+ _fillTblMultiFields(data, 12, DIP_OFFSET, DIP_WIDTH, ptr_field->dip[0]);
+ _fillTblMultiFields(data, 12, SIP_OFFSET, SIP_WIDTH, ptr_field->sip[0]);
+ _fillTblMultiFields(data, 12, DSCP_OFFSET, DSCP_WIDTH, ptr_field->dscp);
+ _fillTblMultiFields(data, 12, PROTOCOL_OFFSET, PROTOCOL_WIDTH, ptr_field->protocol);
+ _fillTblMultiFields(data, 12, DPORT_OFFSET, DPORT_WIDTH, ptr_field->dport);
+ _fillTblMultiFields(data, 12, SPORT_OFFSET, SPORT_WIDTH, ptr_field->sport);
+ _fillTblMultiFields(data, 12, UDF_OFFSET, UDF_WIDTH, ptr_field->udf);
+ _fillTblMultiFields(data, 12, FIELDMAP_OFFSET, FIELDMAP_WIDTH, ptr_field->fieldmap);
+ _fillTblMultiFields(data, 12, IS_IPV6_OFFSET, IS_IPV6_WIDTH, ptr_field->isipv6);
+ _fillTblMultiFields(data, 12, PORTMAP_OFFSET, PORTMAP_WIDTH, ptr_field->portmap);
+ break;
+ case AIR_ACL_RULE_TYPE_1:
+ _fillTblMultiFields(data, 12, RULE_TYPE1_OFFSET, RULE_TYPE1_WIDTH, 1);
+ for(n=1; n<4; n++)
+ {
+ _fillTblMultiFields(data, 12, DIP_IPV6_OFFSET + DIP_IPV6_WIDTH*(n-1), DIP_IPV6_WIDTH, ptr_field->dip[n]);
+ }
+ for(n=1; n<4; n++)
+ {
+ _fillTblMultiFields(data, 12, SIP_IPV6_OFFSET + SIP_IPV6_WIDTH*(n-1), SIP_IPV6_WIDTH, ptr_field->sip[n]);
+ }
+ _fillTblMultiFields(data, 12, FLOW_LABEL_OFFSET, FLOW_LABEL_WIDTH, ptr_field->flow_label);
+ break;
+ default:
+ return;
+ }
+}
+
+static void
+_air_acl_getRuleTable(
+ const AIR_ACL_RULE_TYPE_T type,
+ UI32_T *data,
+ AIR_ACL_FIELD_T *ptr_field)
+{
+ UI32_T n = 0;
+
+ switch(type)
+ {
+ case AIR_ACL_RULE_TYPE_0:
+ for(n=0; n<6; n++)
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DMAC_OFFSET + DMAC_WIDTH*(5-n), DMAC_WIDTH, ptr_field->dmac[n]);
+ }
+ for(n=0; n<6; n++)
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, SMAC_OFFSET + SMAC_WIDTH*(5-n), SMAC_WIDTH, ptr_field->smac[n]);
+ }
+ ACL_DERIVE_TBL_MULTIFIELDS(data, STAG_OFFSET, STAG_WIDTH, ptr_field->stag);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CTAG_OFFSET, CTAG_WIDTH, ptr_field->ctag);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ETYPE_OFFSET, ETYPE_WIDTH, ptr_field->etype);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DIP_OFFSET, DIP_WIDTH, ptr_field->dip[0]);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, SIP_OFFSET, SIP_WIDTH, ptr_field->sip[0]);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DSCP_OFFSET, DSCP_WIDTH, ptr_field->dscp);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PROTOCOL_OFFSET, PROTOCOL_WIDTH, ptr_field->protocol);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DPORT_OFFSET, DPORT_WIDTH, ptr_field->dport);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, SPORT_OFFSET, SPORT_WIDTH, ptr_field->sport);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_OFFSET, UDF_WIDTH, ptr_field->udf);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, FIELDMAP_OFFSET, FIELDMAP_WIDTH, ptr_field->fieldmap);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, IS_IPV6_OFFSET, IS_IPV6_WIDTH, ptr_field->isipv6);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PORTMAP_OFFSET, PORTMAP_WIDTH, ptr_field->portmap);
+ break;
+ case AIR_ACL_RULE_TYPE_1:
+ for(n=1; n<4; n++)
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DIP_IPV6_OFFSET + DIP_IPV6_WIDTH*(n-1), DIP_IPV6_WIDTH, ptr_field->dip[n]);
+ }
+ for(n=1; n<4; n++)
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, SIP_IPV6_OFFSET + SIP_IPV6_WIDTH*(n-1), SIP_IPV6_WIDTH, ptr_field->sip[n]);
+ }
+ ACL_DERIVE_TBL_MULTIFIELDS(data, FLOW_LABEL_OFFSET, FLOW_LABEL_WIDTH, ptr_field->flow_label);
+ break;
+ default:
+ return;
+ }
+}
+
+static void
+_air_acl_setActionTable(
+ const AIR_ACL_ACTION_T *ptr_action,
+ UI32_T *data)
+{
+ int i = 0;
+
+ _fillTblMultiFields(data, 4, PORT_FORCE_OFFSET, PORT_FORCE_WIDTH, ptr_action->port_en);
+ _fillTblMultiFields(data, 4, VLAN_PORT_SWAP_OFFSET, VLAN_PORT_SWAP_WIDTH, ptr_action->vlan_port_sel);
+ _fillTblMultiFields(data, 4, DST_PORT_SWAP_OFFSET, DST_PORT_SWAP_WIDTH, ptr_action->dest_port_sel);
+ _fillTblMultiFields(data, 4, PORT_OFFSET, PORT_WIDTH, ptr_action->portmap);
+
+ _fillTblMultiFields(data, 4, ACL_MIB_EN_OFFSET, ACL_MIB_EN_WIDTH, ptr_action->cnt_en);
+ _fillTblMultiFields(data, 4, ACL_MIB_ID_OFFSET, ACL_MIB_ID_WIDTH, ptr_action->cnt_idx);
+
+ _fillTblMultiFields(data, 4, ATTACK_RATE_EN_OFFSET, ATTACK_RATE_EN_WIDTH, ptr_action->attack_en);
+ _fillTblMultiFields(data, 4, ATTACK_RATE_ID_OFFSET, ATTACK_RATE_ID_WIDTH, ptr_action->attack_idx);
+
+ _fillTblMultiFields(data, 4, RATE_EN_OFFSET, RATE_EN_WIDTH, ptr_action->rate_en);
+ _fillTblMultiFields(data, 4, RATE_INDEX_OFFSET, RATE_INDEX_WIDTH, ptr_action->rate_idx);
+
+ _fillTblMultiFields(data, 4, PORT_FW_EN_OFFSET, PORT_FW_EN_WIDTH, ptr_action->fwd_en);
+ _fillTblMultiFields(data, 4, FW_PORT_OFFSET, FW_PORT_WIDTH, ptr_action->fwd);
+
+ _fillTblMultiFields(data, 4, MIRROR_OFFSET, MIRROR_WIDTH, ptr_action->mirrormap);
+
+ _fillTblMultiFields(data, 4, PRI_USER_EN_OFFSET, PRI_USER_EN_WIDTH, ptr_action->pri_user_en);
+ _fillTblMultiFields(data, 4, PRI_USER_OFFSET, PRI_USER_WIDTH, ptr_action->pri_user);
+
+ _fillTblMultiFields(data, 4, EG_TAG_EN_OFFSET, EG_TAG_EN_WIDTH, ptr_action->egtag_en);
+ _fillTblMultiFields(data, 4, EG_TAG_OFFSET, EG_TAG_WIDTH, ptr_action->egtag);
+
+ _fillTblMultiFields(data, 4, LKY_VLAN_EN_OFFSET, LKY_VLAN_EN_WIDTH, ptr_action->lyvlan_en);
+ _fillTblMultiFields(data, 4, LKY_VLAN_OFFSET, LKY_VLAN_WIDTH, ptr_action->lyvlan);
+
+ _fillTblMultiFields(data, 4, BPDU_OFFSET, BPDU_WIDTH, ptr_action->bpdu);
+
+ _fillTblMultiFields(data, 4, ACL_MANG_OFFSET, ACL_MANG_WIDTH, ptr_action->mang);
+
+ _fillTblMultiFields(data, 4, TRTCM_EN_OFFSET, TRTCM_EN_WIDTH, ptr_action->trtcm_en);
+ _fillTblMultiFields(data, 4, DROP_PCD_SEL_OFFSET, DROP_PCD_SEL_WIDTH, ptr_action->trtcm.drop_pcd_sel);
+ _fillTblMultiFields(data, 4, ACL_DROP_PCD_R_OFFSET, ACL_DROP_PCD_R_WIDTH, ptr_action->trtcm.drop_pcd_r);
+ _fillTblMultiFields(data, 4, ACL_DROP_PCD_Y_OFFSET, ACL_DROP_PCD_Y_WIDTH, ptr_action->trtcm.drop_pcd_y);
+ _fillTblMultiFields(data, 4, ACL_DROP_PCD_G_OFFSET, ACL_DROP_PCD_G_WIDTH, ptr_action->trtcm.drop_pcd_g);
+ _fillTblMultiFields(data, 4, CLASS_SLR_SEL_OFFSET, CLASS_SLR_SEL_WIDTH, ptr_action->trtcm.cls_slr_sel);
+ _fillTblMultiFields(data, 4, CLASS_SLR_OFFSET, CLASS_SLR_WIDTH, ptr_action->trtcm.cls_slr);
+ _fillTblMultiFields(data, 4, ACL_TCM_SEL_OFFSET, ACL_TCM_SEL_WIDTH, ptr_action->trtcm.tcm_sel);
+ _fillTblMultiFields(data, 4, ACL_TCM_OFFSET, ACL_TCM_WIDTH, ptr_action->trtcm.usr_tcm);
+ _fillTblMultiFields(data, 4, ACL_CLASS_IDX_OFFSET, ACL_CLASS_IDX_WIDTH, ptr_action->trtcm.tcm_idx);
+
+ _fillTblMultiFields(data, 4, ACL_VLAN_HIT_OFFSET, ACL_VLAN_HIT_WIDTH, ptr_action->vlan_en);
+ _fillTblMultiFields(data, 4, ACL_VLAN_VID_OFFSET, ACL_VLAN_VID_WIDTH, ptr_action->vlan_idx);
+}
+
+static void
+_air_acl_getActionTable(
+ UI32_T *data,
+ AIR_ACL_ACTION_T *ptr_action)
+{
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_FORCE_OFFSET, PORT_FORCE_WIDTH, ptr_action->port_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, VLAN_PORT_SWAP_OFFSET, VLAN_PORT_SWAP_WIDTH, ptr_action->vlan_port_sel);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DST_PORT_SWAP_OFFSET, DST_PORT_SWAP_WIDTH, ptr_action->dest_port_sel);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_OFFSET, PORT_WIDTH, ptr_action->portmap);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MIB_EN_OFFSET, ACL_MIB_EN_WIDTH, ptr_action->cnt_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MIB_ID_OFFSET, ACL_MIB_ID_WIDTH, ptr_action->cnt_idx);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ATTACK_RATE_EN_OFFSET, ATTACK_RATE_EN_WIDTH, ptr_action->attack_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ATTACK_RATE_ID_OFFSET, ATTACK_RATE_ID_WIDTH, ptr_action->attack_idx);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, RATE_EN_OFFSET, RATE_EN_WIDTH, ptr_action->rate_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, RATE_INDEX_OFFSET, RATE_INDEX_WIDTH, ptr_action->rate_idx);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_FW_EN_OFFSET, PORT_FW_EN_WIDTH, ptr_action->fwd_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, FW_PORT_OFFSET, FW_PORT_WIDTH, ptr_action->fwd);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, MIRROR_OFFSET, MIRROR_WIDTH, ptr_action->mirrormap);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PRI_USER_EN_OFFSET, PRI_USER_EN_WIDTH, ptr_action->pri_user_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PRI_USER_OFFSET, PRI_USER_WIDTH, ptr_action->pri_user);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, EG_TAG_EN_OFFSET, EG_TAG_EN_WIDTH, ptr_action->egtag_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, EG_TAG_OFFSET, EG_TAG_WIDTH, ptr_action->egtag);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, LKY_VLAN_EN_OFFSET, LKY_VLAN_EN_WIDTH, ptr_action->lyvlan_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, LKY_VLAN_OFFSET, LKY_VLAN_WIDTH, ptr_action->lyvlan);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, BPDU_OFFSET, BPDU_WIDTH, ptr_action->bpdu);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_MANG_OFFSET, ACL_MANG_WIDTH, ptr_action->mang);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, TRTCM_EN_OFFSET, TRTCM_EN_WIDTH, ptr_action->trtcm_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, DROP_PCD_SEL_OFFSET, DROP_PCD_SEL_WIDTH, ptr_action->trtcm.drop_pcd_sel);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_R_OFFSET, ACL_DROP_PCD_R_WIDTH, ptr_action->trtcm.drop_pcd_r);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_Y_OFFSET, ACL_DROP_PCD_Y_WIDTH, ptr_action->trtcm.drop_pcd_y);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_DROP_PCD_G_OFFSET, ACL_DROP_PCD_G_WIDTH, ptr_action->trtcm.drop_pcd_g);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CLASS_SLR_SEL_OFFSET, CLASS_SLR_SEL_WIDTH, ptr_action->trtcm.cls_slr_sel);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CLASS_SLR_OFFSET, CLASS_SLR_WIDTH, ptr_action->trtcm.cls_slr);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_TCM_SEL_OFFSET, ACL_TCM_SEL_WIDTH, ptr_action->trtcm.tcm_sel);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_TCM_OFFSET, ACL_TCM_WIDTH, ptr_action->trtcm.usr_tcm);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_CLASS_IDX_OFFSET, ACL_CLASS_IDX_WIDTH, ptr_action->trtcm.tcm_idx);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_VLAN_HIT_OFFSET, ACL_VLAN_HIT_WIDTH, ptr_action->vlan_en);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, ACL_VLAN_VID_OFFSET, ACL_VLAN_VID_WIDTH, ptr_action->vlan_idx);
+
+}
+
+static AIR_ERROR_NO_T
+_air_acl_writeReg(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ const UI32_T block_num,
+ const AIR_ACL_RULE_TCAM_T type,
+ const AIR_ACL_MEM_SEL_T sel,
+ const AIR_ACL_MEM_FUNC_T func,
+ const UI32_T *data)
+{
+ UI32_T bn = 0, value = 0;
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ for (bn = 0; bn < block_num; bn++)
+ {
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_ACL))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ aml_writeReg(unit, ACL_MEM_CFG_WDATA0, data[bn*4]);
+ aml_writeReg(unit, ACL_MEM_CFG_WDATA1, data[bn*4+1]);
+ aml_writeReg(unit, ACL_MEM_CFG_WDATA2, data[bn*4+2]);
+ aml_writeReg(unit, ACL_MEM_CFG_WDATA3, data[bn*4+3]);
+
+ value = (rule_idx << ACL_MEM_CFG_RULE_ID_OFFSET) | (type << ACL_MEM_CFG_TCAM_CELL_OFFSET) |
+ (bn << ACL_MEM_CFG_DATA_BN_OFFSET) | (sel << ACL_MEM_CFG_MEM_SEL_OFFSET) |
+ (func << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
+ if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ }
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+_air_acl_readReg(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ const UI32_T block_num,
+ const AIR_ACL_RULE_TCAM_T type,
+ const AIR_ACL_MEM_SEL_T sel,
+ const AIR_ACL_MEM_FUNC_T func,
+ UI32_T *data)
+{
+ UI32_T bn = 0, value = 0;
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ for (bn = 0; bn < block_num; bn++)
+ {
+ value = (rule_idx << ACL_MEM_CFG_RULE_ID_OFFSET) | (type << ACL_MEM_CFG_TCAM_CELL_OFFSET) |
+ (bn << ACL_MEM_CFG_DATA_BN_OFFSET) | (sel << ACL_MEM_CFG_MEM_SEL_OFFSET) |
+ (func << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
+ if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_ACL))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ aml_readReg(unit, ACL_MEM_CFG_RDATA0, data+bn*4);
+ aml_readReg(unit, ACL_MEM_CFG_RDATA1, data+bn*4+1);
+ aml_readReg(unit, ACL_MEM_CFG_RDATA2, data+bn*4+2);
+ aml_readReg(unit, ACL_MEM_CFG_RDATA3, data+bn*4+3);
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setRuleCtrl
+ * PURPOSE:
+ * Set ACL rule control.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ * ptr_rule -- Structure of ACL rule control
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setRuleCtrl(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_CTRL_T *ptr_ctrl)
+{
+ UI32_T data_en[4] = {0}, data_end[4] = {0}, data_rev[4] = {0};
+
+ if(TRUE == ptr_ctrl->rule_en)
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
+ data_en[rule_idx/32] |= (1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_en);
+ }
+ else
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
+ data_en[rule_idx/32] &= ~(1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_en);
+ }
+
+ if(TRUE == ptr_ctrl->end)
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
+ data_end[rule_idx/32] |= (1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_end);
+ }
+ else
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
+ data_end[rule_idx/32] &= ~(1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_end);
+
+ }
+
+ if(TRUE == ptr_ctrl->reverse)
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
+ data_rev[rule_idx/32] |= (1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_rev);
+ }
+ else
+ {
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
+ data_rev[rule_idx/32] &= ~(1 << (rule_idx%32));
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data_rev);
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_getRuleCtrl
+ * PURPOSE:
+ * Get ACL rule control.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * ptr_ctrl -- Structure of ACL rule control
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getRuleCtrl(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_CTRL_T *ptr_ctrl)
+{
+ UI32_T data_en[4] = {0}, data_end[4] = {0}, data_rev[4] = {0};
+
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_en);
+ if(data_en[rule_idx/32] & (1 << (rule_idx%32)))
+ {
+ ptr_ctrl->rule_en = TRUE;
+ }
+ else
+ {
+ ptr_ctrl->rule_en = FALSE;
+ }
+
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_end);
+ if(data_end[rule_idx/32] & (1 << (rule_idx%32)))
+ {
+ ptr_ctrl->end = TRUE;
+ }
+ else
+ {
+ ptr_ctrl->end = FALSE;
+ }
+
+ _air_acl_readReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_READ, data_rev);
+ if(data_rev[rule_idx/32] & (1 << (rule_idx%32)))
+ {
+ ptr_ctrl->reverse = TRUE;
+ }
+ else
+ {
+ ptr_ctrl->reverse = FALSE;
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setRule
+ * PURPOSE:
+ * Set ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ * rule -- Structure of ACL rule entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_RULE_T *rule)
+{
+ UI32_T type0_key[12] = {0}, type0_mask[12] = {0};
+ UI32_T type1_key[12] = {0}, type1_mask[12] = {0};
+ UI32_T type0_t[12] = {0}, type0_c[12] = {0};
+ UI32_T type1_t[12] = {0}, type1_c[12] = {0};
+ AIR_ACL_CTRL_T ctrl;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((rule->key.flow_label > BITS_RANGE(0, FLOW_LABEL_WIDTH)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((rule->key.fieldmap > BITS_RANGE(0, AIR_ACL_FIELD_TYPE_LAST)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != rule->key.isipv6) && (FALSE != rule->key.isipv6), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((rule->key.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != rule->ctrl.rule_en) && (FALSE != rule->ctrl.rule_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != rule->ctrl.reverse) && (FALSE != rule->ctrl.reverse), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != rule->ctrl.end) && (FALSE != rule->ctrl.end), AIR_E_BAD_PARAMETER);
+
+ memset(type0_key, 0, sizeof(type0_key));
+ memset(type0_mask, 0, sizeof(type0_mask));
+ memset(type1_key, 0, sizeof(type1_key));
+ memset(type1_mask, 0, sizeof(type1_mask));
+
+ memset(type0_t, 0, sizeof(type0_t));
+ memset(type0_c, 0, sizeof(type0_c));
+ memset(type1_t, 0, sizeof(type1_t));
+ memset(type1_c, 0, sizeof(type1_c));
+
+ /* Fill rule type table */
+ _air_acl_setRuleTable(AIR_ACL_RULE_TYPE_0, TRUE, &rule->key, type0_key);
+ _air_acl_setRuleTable(AIR_ACL_RULE_TYPE_0, FALSE, &rule->mask, type0_mask);
+
+ /* Calculate T/C cell */
+ _convertToTCcell(type0_key, type0_mask, type0_t, type0_c, 12);
+
+ /* Set T/C cell to reg */
+ _air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_t);
+ _air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_c);
+
+ /* If match ipv6 flow lable or dip/dip, set rule type 1 */
+ if ((1 == rule->key.isipv6) && (rule->key.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
+ {
+ _air_acl_setRuleTable(AIR_ACL_RULE_TYPE_1, TRUE, &rule->key, type1_key);
+ _air_acl_setRuleTable(AIR_ACL_RULE_TYPE_1, FALSE, &rule->mask, type1_mask);
+ _convertToTCcell(type1_key, type1_mask, type1_t, type1_c, 12);
+ _air_acl_writeReg(unit, rule_idx+1, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type1_t);
+ _air_acl_writeReg(unit, rule_idx+1, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type1_c);
+ }
+
+ /* Config rule enable/end/rev */
+ memcpy(&ctrl, &rule->ctrl, sizeof(AIR_ACL_CTRL_T));
+ if ((1 == rule->key.isipv6) && (rule->key.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
+ {
+ ctrl.end = 0;
+ air_acl_setRuleCtrl(unit, rule_idx, &ctrl);
+ air_acl_setRuleCtrl(unit, rule_idx+1, &rule->ctrl);
+ }
+ else
+ {
+ air_acl_setRuleCtrl(unit, rule_idx, &rule->ctrl);
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_delRule
+ * PURPOSE:
+ * Delete an ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delRule(
+ const UI32_T unit,
+ const UI32_T rule_idx)
+{
+ UI32_T type0_t[12]={0}, type0_c[12]={0}, type1_t[12]={0}, type1_c[12]={0};
+ AIR_ACL_CTRL_T ctrl={0};
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
+
+ /* Delete the entry from ACL rule table */
+ _air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_t);
+ _air_acl_writeReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_WRITE, type0_c);
+ air_acl_setRuleCtrl(unit, rule_idx, &ctrl);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_clearRule
+ * PURPOSE:
+ * Clear all ACL rule entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearRule(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data[4]={0};
+
+ value = (AIR_ACL_MEM_FUNC_CLEAR << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
+ if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_ENABLE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_END, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
+ _air_acl_writeReg(unit, AIR_ACL_RULE_CONFIG_REVERSE, 1, 0, 0, AIR_ACL_MEM_FUNC_CONFIG_WRITE, data);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_clearAction
+ * PURPOSE:
+ * Clear all ACL action entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearAction(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data[4]={0};
+
+ value = (AIR_ACL_MEM_SEL_ACTION << ACL_MEM_CFG_MEM_SEL_OFFSET) | (AIR_ACL_MEM_FUNC_CLEAR << ACL_MEM_CFG_FUNC_SEL_OFFSET) | ACL_MEM_CFG_EN;
+ if ((ret = aml_writeReg(unit, ACL_MEM_CFG, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_getRule
+ * PURPOSE:
+ * Get ACL rule entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- Index of ACL rule entry
+ *
+ * OUTPUT:
+ * ptr_rule -- Structure of ACL rule entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_RULE_T *ptr_rule)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T bn = 0;
+ UI32_T value = 0, n = 0, idx = 0;
+ UI32_T type0_key[12] = {0}, type0_mask[12] = {0};
+ UI32_T type1_key[12] = {0}, type1_mask[12] = {0};
+ UI32_T type0_t[12] = {0}, type0_c[12] = {0};
+ UI32_T type1_t[12] = {0}, type1_c[12] = {0};
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_RULE_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_rule);
+
+ _air_acl_readReg(unit, rule_idx, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type0_t);
+ _air_acl_readReg(unit, rule_idx, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type0_c);
+ /* rule type 1 */
+ if(1 == (type0_t[0] & 0x1))
+ {
+ idx = rule_idx-1;
+ AIR_PRINT("This is the part of ipv6 rule, please get rule(%d)\n", idx);
+ return AIR_E_OK;
+ }
+
+ _parseFromTCcell(type0_t, type0_c, type0_key, type0_mask, 12);
+
+ _air_acl_getRuleTable(AIR_ACL_RULE_TYPE_0, type0_key, &ptr_rule->key);
+ _air_acl_getRuleTable(AIR_ACL_RULE_TYPE_0, type0_mask, &ptr_rule->mask);
+
+ if ((TRUE == ptr_rule->key.isipv6) && (ptr_rule->mask.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
+ {
+ _air_acl_readReg(unit, rule_idx+1, 3, AIR_ACL_RULE_T_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type1_t);
+ _air_acl_readReg(unit, rule_idx+1, 3, AIR_ACL_RULE_C_CELL, AIR_ACL_MEM_SEL_RULE, AIR_ACL_MEM_FUNC_READ, type1_c);
+ _parseFromTCcell(type1_t, type1_c, type1_key, type1_mask, 12);
+
+ _air_acl_getRuleTable(AIR_ACL_RULE_TYPE_1, type1_key, &ptr_rule->key);
+ _air_acl_getRuleTable(AIR_ACL_RULE_TYPE_1, type1_mask, &ptr_rule->mask);
+ }
+ if ((TRUE == ptr_rule->key.isipv6) && (ptr_rule->mask.fieldmap & ((1 << AIR_ACL_DIP) | (1 << AIR_ACL_SIP) | (1 << AIR_ACL_FLOW_LABEL))))
+ {
+ air_acl_getRuleCtrl(unit, rule_idx+1, &ptr_rule->ctrl);
+ }
+ else
+ {
+ air_acl_getRuleCtrl(unit, rule_idx, &ptr_rule->ctrl);
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setAction
+ * PURPOSE:
+ * Set an ACL action entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ * act -- Structure of ACL action entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_NOT_SUPPORT
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setAction(
+ const UI32_T unit,
+ const UI32_T act_idx,
+ const AIR_ACL_ACTION_T act)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T data[4] = {0};
+
+ /* Check parameter */
+ AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.port_en) && (FALSE != act.port_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.dest_port_sel) && (FALSE != act.dest_port_sel), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.vlan_port_sel) && (FALSE != act.vlan_port_sel), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.cnt_en) && (FALSE != act.cnt_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.cnt_idx >= ACL_MAX_MIB_NUM), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.attack_en) && (FALSE != act.attack_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.attack_idx >= ACL_MAX_ATTACK_RATE_NUM), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.rate_en) && (FALSE != act.rate_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.rate_idx >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.vlan_en) && (FALSE != act.vlan_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.vlan_idx >= ACL_MAX_VLAN_NUM), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((act.mirrormap > BITS_RANGE(0, ACL_MAX_MIR_SESSION_NUM)), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.pri_user_en) && (FALSE != act.pri_user_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.pri_user >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.lyvlan_en) && (FALSE != act.lyvlan_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.lyvlan) && (FALSE != act.lyvlan), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.mang) && (FALSE != act.mang), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.bpdu) && (FALSE != act.bpdu), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.fwd_en) && (FALSE != act.fwd_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.fwd >= AIR_ACL_ACT_FWD_LAST), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.egtag_en) && (FALSE != act.egtag_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.egtag >= AIR_ACL_ACT_EGTAG_LAST), AIR_E_BAD_PARAMETER);
+
+ AIR_PARAM_CHK((TRUE != act.trtcm_en) && (FALSE != act.trtcm_en), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.trtcm.cls_slr_sel) && (FALSE != act.trtcm.cls_slr), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.cls_slr >= ACL_MAX_CLASS_SLR_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.trtcm.drop_pcd_sel) && (FALSE != act.trtcm.drop_pcd_sel), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.drop_pcd_g >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.drop_pcd_y >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.drop_pcd_r >= ACL_MAX_DROP_PCD_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != act.trtcm.tcm_sel) && (FALSE != act.trtcm.tcm_sel), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.usr_tcm >= AIR_ACL_ACT_USR_TCM_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((act.trtcm.tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
+
+ _air_acl_setActionTable(&act, data);
+ _air_acl_writeReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_WRITE, data);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_acl_getAction
+ * PURPOSE:
+ * Get an ACL action entry with speficic index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ *
+ * OUTPUT:
+ * ptr_act -- Structure of ACL action entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_ENTRY_NOT_FOUND
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getAction(
+ const UI32_T unit,
+ const UI32_T act_idx,
+ AIR_ACL_ACTION_T *ptr_act)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T i = 0;
+ UI32_T data[4] = {0};
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_act);
+
+ _air_acl_readReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_READ, data);
+ _air_acl_getActionTable(data, ptr_act);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_delAction
+ * PURPOSE:
+ * Delete an ACL action entry with specific index
+ *
+ * INPUT:
+ * unit -- Device ID
+ * act_idx -- Index of ACL action entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_ENTRY_NOT_FOUND
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delAction(
+ const UI32_T unit,
+ const UI32_T act_idx)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data[4] = {0};
+
+ /* Check parameter */
+ AIR_PARAM_CHK((act_idx >= ACL_MAX_ACTION_NUM), AIR_E_BAD_PARAMETER);
+
+ _air_acl_writeReg(unit, act_idx, 1, 0, AIR_ACL_MEM_SEL_ACTION, AIR_ACL_MEM_FUNC_WRITE, data);
+ return ret;
+}
+
+/* FUNCTION NAME: air_acl_setTrtcm
+ * PURPOSE:
+ * Set a trTCM entry with the specific index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * tcm_idx -- Index of trTCM entry
+ * tcm -- Structure of trTCM entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_setTrtcm(
+ const UI32_T unit,
+ const UI32_T tcm_idx,
+ const AIR_ACL_TRTCM_T tcm)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((tcm.cbs > ACL_MAX_CBS_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((tcm.cir > ACL_MAX_CIR_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((tcm.pbs > ACL_MAX_PBS_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((tcm.pir > ACL_MAX_PIR_NUM), AIR_E_BAD_PARAMETER);
+
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_TRTCM))
+ {
+ return AIR_E_TIMEOUT;
+ }
+
+ aml_writeReg(unit, ACL_TRTCMW_CBS, tcm.cbs & ACL_TRTCM_CBS_MASK);
+ aml_writeReg(unit, ACL_TRTCMW_EBS, tcm.pbs & ACL_TRTCM_EBS_MASK);
+ aml_writeReg(unit, ACL_TRTCMW_CIR, tcm.cir & ACL_TRTCM_CIR_MASK);
+ aml_writeReg(unit, ACL_TRTCMW_EIR, tcm.pir & ACL_TRTCM_EIR_MASK);
+
+ value = (1 << ACL_TRTCM_BUSY_OFFSET) | ACL_TRTCM_WRITE | ((tcm_idx & ACL_TRTCM_ID_MASK) << ACL_TRTCM_ID_OFFSET);
+
+ if ((ret = aml_writeReg(unit, ACL_TRTCMA, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_delTrtcm
+ * PURPOSE:
+ * Delete an ACL trTCM entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * trtcm_idx -- Index of ACL trTCM entry
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_delTrtcm(
+ const UI32_T unit,
+ const UI32_T tcm_idx)
+{
+ AIR_ACL_TRTCM_T tcm;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
+
+ /* Delete the entry from trTCM table */
+ memset(&tcm, 0, sizeof(tcm));
+ return air_acl_setTrtcm(unit, tcm_idx, tcm);
+}
+
+/* FUNCTION NAME: air_acl_clearTrtcm
+ * PURPOSE:
+ * Clear all ACL trTCM entries.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearTrtcm(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_ACL_TRTCM_T tcm;
+ UI32_T i = 0;
+
+ /* Delete all entries from trTCM table */
+ memset(&tcm, 0, sizeof(tcm));
+ for(i=0; i < ACL_MAX_TRTCM_NUM; i++)
+ {
+ ret = air_acl_setTrtcm(unit, i, tcm);
+ if(AIR_E_OK != ret)
+ {
+ return ret;
+ }
+ }
+ return ret;
+}
+
+/* FUNCTION NAME: air_acl_getTrtcm
+ * PURPOSE:
+ * Get a trTCM entry with the specific index.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * tcm_idx -- Index of trTCM entry
+ *
+ * OUTPUT:
+ * ptr_tcm -- Structure of trTCM entry
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * Index 0 ~ 31 can be selected in tcm_idx.
+ */
+AIR_ERROR_NO_T
+air_acl_getTrtcm(
+ const UI32_T unit,
+ const UI32_T tcm_idx,
+ AIR_ACL_TRTCM_T *ptr_tcm)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0, trtcmr1 = 0, trtcmr2 = 0, trtcmr3 = 0, trtcmr4 = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((tcm_idx >= ACL_MAX_TRTCM_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_tcm);
+
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_TRTCM))
+ {
+ return AIR_E_TIMEOUT;
+ }
+
+ value = (1 << ACL_TRTCM_BUSY_OFFSET) | ACL_TRTCM_READ | ((tcm_idx & ACL_TRTCM_ID_MASK) << ACL_TRTCM_ID_OFFSET);
+
+ if ((ret = aml_writeReg(unit, ACL_TRTCMA, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ aml_readReg(unit, ACL_TRTCMR_CBS, &trtcmr1);
+ aml_readReg(unit, ACL_TRTCMR_EBS, &trtcmr2);
+ aml_readReg(unit, ACL_TRTCMR_CIR, &trtcmr3);
+ aml_readReg(unit, ACL_TRTCMR_EIR, &trtcmr4);
+
+ ptr_tcm->cbs = trtcmr1 & ACL_TRTCM_CBS_MASK;
+ ptr_tcm->pbs = trtcmr2 & ACL_TRTCM_EBS_MASK;
+ ptr_tcm->cir = trtcmr3 & ACL_TRTCM_CIR_MASK;
+ ptr_tcm->pir = trtcmr4 & ACL_TRTCM_EIR_MASK;
+
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_acl_setTrtcmEnable
+ * PURPOSE:
+ * Set trTCM enable so the meter table will be updated based on PIR and CIR.
+ * The color marker will also be enabled when ACL is hit.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setTrtcmEnable(
+ const UI32_T unit,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, ACL_TRTCM, &u32dat);
+
+ if (TRUE == state)
+ {
+ u32dat |= (BIT(ACL_TRTCM_EN_OFFSET));
+ }
+ else
+ {
+ u32dat &= ~(BIT(ACL_TRTCM_EN_OFFSET));
+ }
+
+ /* Write data to register */
+ aml_writeReg(unit, ACL_TRTCM, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_getTrtcm
+ * PURPOSE:
+ * Get a trTCM enable state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getTrtcmEnable(
+ const UI32_T unit,
+ BOOL_T *const ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readReg(unit, ACL_TRTCM, &u32dat);
+
+ if (u32dat & BIT(ACL_TRTCM_EN_OFFSET))
+ {
+ (*ptr_state) = TRUE;
+ }
+ else
+ {
+ (*ptr_state) = FALSE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setPortEnable
+ * PURPOSE:
+ * Set ACL state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setPortEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0, value = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ value = state ? 1 : 0;
+ aml_readReg(unit, ACL_PORT_EN, &u32dat);
+ u32dat = (u32dat & ~(ACL_EN_MASK << port)) | (value << port);
+ aml_writeReg(unit, ACL_PORT_EN, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_getPortEnable
+ * PURPOSE:
+ * Get ACL state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getPortEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readReg(unit, ACL_PORT_EN, &u32dat);
+
+ (*ptr_state) = BITS_OFF_R(u32dat, port, ACL_EN_MASK);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setDropEnable
+ * PURPOSE:
+ * Set ACL drop precedence state
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setDropEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ u32dat = state ? 1 : 0;
+ aml_writeReg(unit, DPCR_EN(port), u32dat);
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_acl_getDropEnable
+ * PURPOSE:
+ * Get ACL drop precedence state
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getDropEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_state);
+
+ aml_readReg(unit, DPCR_EN(port), &u32dat);
+ *ptr_state = u32dat ? TRUE : FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_acl_setDropThreshold
+ * PURPOSE:
+ * Set ACL drop threshold.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ * high -- High threshold
+ * low -- Low threshold
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_setDropThreshold(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ const UI32_T high,
+ const UI32_T low)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((high > BITS_RANGE(0, DPCR_HIGH_THRSH_WIDTH)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((low > BITS_RANGE(0, DPCR_LOW_THRSH_WIDTH)), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, DPCR(port, color, queue), &u32dat);
+ u32dat = (u32dat & ~(DPCR_LOW_THRSH_MASK)) | low;
+ u32dat = (u32dat & ~(DPCR_HIGH_THRSH_MASK << DPCR_HIGH_THRSH_OFFSET)) | (high << DPCR_HIGH_THRSH_OFFSET);
+ aml_writeReg(unit, DPCR(port, color, queue), u32dat);
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_acl_getDropThreshold
+ * PURPOSE:
+ * Get ACL drop threshold.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ *
+ * OUTPUT:
+ * ptr_high -- High threshold
+ * ptr_low -- Low threshold
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_getDropThreshold(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ UI32_T *ptr_high,
+ UI32_T *ptr_low)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_high);
+ AIR_CHECK_PTR(ptr_low);
+
+ aml_readReg(unit, DPCR(port, color, queue), &u32dat);
+ *ptr_low = u32dat & DPCR_LOW_THRSH_MASK;
+ *ptr_high = (u32dat >> DPCR_HIGH_THRSH_OFFSET) & DPCR_HIGH_THRSH_MASK;
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_acl_setDropProbability
+ * PURPOSE:
+ * Set ACL drop probability.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ * probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_setDropProbability(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ const UI32_T probability)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((probability > BITS_RANGE(0, DPCR_PBB_WIDTH)), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, DPCR(port, color, queue), &u32dat);
+ u32dat = (u32dat & ~(DPCR_PBB_MASK << DPCR_PBB_OFFSET)) | (probability << DPCR_PBB_OFFSET);
+ aml_writeReg(unit, DPCR(port, color, queue), u32dat);
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_acl_getDropProbability
+ * PURPOSE:
+ * Get ACL drop probability.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * color -- AIR_ACL_DP_COLOR_YELLOW: Yellow
+ * AIR_ACL_DP_COLOR_RED : Red
+ * queue -- Output queue number
+ *
+ * OUTPUT:
+ * ptr_probability -- Drop probability (value:0 ~ 1023, unit:1/1023; eg: value-102 = 10% )
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * Key parameter include port, color, queue.
+ */
+AIR_ERROR_NO_T
+air_acl_getDropProbability(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_ACL_DP_COLOR_T color,
+ const UI8_T queue,
+ UI32_T *ptr_probability)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((color >= AIR_ACL_DP_COLOR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_MAX_NUM_OF_QUEUE), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_probability);
+
+ /* Read data from register */
+ aml_readReg(unit, DPCR(port, color, queue), &u32dat);
+
+ (*ptr_probability) = BITS_OFF_R(u32dat, DPCR_PBB_OFFSET, DPCR_PBB_WIDTH);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_setGlobalState
+ * PURPOSE:
+ * Set the ACL global enable state.
+ * INPUT:
+ * unit -- Device ID
+ * state -- Enable state of ACL
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setGlobalState(
+ const UI32_T unit,
+ const BOOL_T state)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0, data = 0;
+
+ AIR_PARAM_CHK((TRUE != state) && (FALSE != state), AIR_E_BAD_PARAMETER);
+
+ value = state ? 1 : 0;
+ if ((ret = aml_readReg(unit, ACL_GLOBAL_CFG, &data)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ data = (data & ~ACL_EN_MASK) | value;
+ if ((ret = aml_writeReg(unit, ACL_GLOBAL_CFG, data)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_getGlobalState
+ * PURPOSE:
+ * Get the ACL global enable state.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * ptr_state -- Enable state
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getGlobalState(
+ const UI32_T unit,
+ BOOL_T *ptr_state)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+
+ AIR_CHECK_PTR(ptr_state);
+ if ((ret = aml_readReg(unit, ACL_GLOBAL_CFG, &value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ value &= ACL_EN_MASK;
+ *ptr_state = value ? TRUE : FALSE;
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_setUdfRule
+ * PURPOSE:
+ * Set ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * udf_rule -- Structure of ACL UDF rule entry
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setUdfRule(
+ const UI32_T unit,
+ const UI32_T rule_idx,
+ AIR_ACL_UDF_RULE_T udf_rule)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data[3] = {0};
+
+ /* Check parameter */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != udf_rule.valid) && (FALSE != udf_rule.valid), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.offset_format >= AIR_ACL_RULE_OFS_FMT_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.offset >= ACL_MAX_WORD_OFST_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.cmp_sel >= AIR_ACL_RULE_CMP_SEL_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.pattern > ACL_MAX_CMP_PAT_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.mask > ACL_MAX_CMP_BIT_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.low_threshold > ACL_MAX_CMP_PAT_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.high_threshold > ACL_MAX_CMP_BIT_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((udf_rule.portmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
+
+ _fillTblMultiFields(data, 3, PORT_BITMAP_OFFSET, PORT_BITMAP_WIDTH, udf_rule.portmap);
+ _fillTblMultiFields(data, 3, UDF_RULE_EN_OFFSET, UDF_RULE_EN_WIDTH, udf_rule.valid);
+ _fillTblMultiFields(data, 3, UDF_PKT_TYPE_OFFSET, UDF_PKT_TYPE_WIDTH, udf_rule.offset_format);
+ _fillTblMultiFields(data, 3, WORD_OFST_OFFSET, WORD_OFST_WIDTH, udf_rule.offset);
+
+ _fillTblMultiFields(data, 3, CMP_SEL_OFFSET, CMP_SEL_WIDTH, udf_rule.cmp_sel);
+ if(AIR_ACL_RULE_CMP_SEL_PATTERN == udf_rule.cmp_sel)
+ {
+ _fillTblMultiFields(data, 3, CMP_PAT_OFFSET, CMP_PAT_WIDTH, udf_rule.pattern);
+ _fillTblMultiFields(data, 3, CMP_MASK_OFFSET, CMP_MASK_WIDTH, udf_rule.mask);
+ }
+ else
+ {
+ _fillTblMultiFields(data, 3, CMP_PAT_OFFSET, CMP_PAT_WIDTH, udf_rule.low_threshold);
+ _fillTblMultiFields(data, 3, CMP_MASK_OFFSET, CMP_MASK_WIDTH, udf_rule.high_threshold);
+ }
+
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_UDF))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ aml_writeReg(unit, ACL_AUTW0, data[0]);
+ aml_writeReg(unit, ACL_AUTW1, data[1]);
+ aml_writeReg(unit, ACL_AUTW2, data[2]);
+ value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_WRITE | (1U << ACL_UDF_ACC_OFFSET);
+ if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_getUdfRule
+ * PURPOSE:
+ * Get ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * OUTPUT:
+ * ptr_udf_rule -- Structure of ACL UDF rule entry
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getUdfRule(
+ const UI32_T unit,
+ const UI8_T rule_idx,
+ AIR_ACL_UDF_RULE_T *ptr_udf_rule)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data[3] = {0};
+
+ /* Check parameter */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_udf_rule);
+
+ value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_READ | (1U << ACL_UDF_ACC_OFFSET);
+ if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_UDF))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ aml_readReg(unit, ACL_AUTR0, data);
+ aml_readReg(unit, ACL_AUTR1, data+1);
+ aml_readReg(unit, ACL_AUTR2, data+2);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, PORT_BITMAP_OFFSET, PORT_BITMAP_WIDTH, ptr_udf_rule->portmap);
+
+ ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_RULE_EN_OFFSET, UDF_RULE_EN_WIDTH, ptr_udf_rule->valid);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, UDF_PKT_TYPE_OFFSET, UDF_PKT_TYPE_WIDTH, ptr_udf_rule->offset_format);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, WORD_OFST_OFFSET, WORD_OFST_WIDTH, ptr_udf_rule->offset);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_SEL_OFFSET, CMP_SEL_WIDTH, ptr_udf_rule->cmp_sel);
+ if(AIR_ACL_RULE_CMP_SEL_PATTERN == ptr_udf_rule->cmp_sel)
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_PAT_OFFSET, CMP_PAT_WIDTH, ptr_udf_rule->pattern);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_MASK_OFFSET, CMP_MASK_WIDTH, ptr_udf_rule->mask);
+ }
+ else
+ {
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_PAT_OFFSET, CMP_PAT_WIDTH, ptr_udf_rule->low_threshold);
+ ACL_DERIVE_TBL_MULTIFIELDS(data, CMP_MASK_OFFSET, CMP_MASK_WIDTH, ptr_udf_rule->high_threshold);
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_delUdfRule
+ * PURPOSE:
+ * Delete ACL UDF rule of specified entry index.
+ * INPUT:
+ * unit -- Device ID
+ * rule_idx -- ACLUDF table entry index
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_delUdfRule(
+ const UI32_T unit,
+ const UI8_T rule_idx)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+ UI32_T data = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((rule_idx >= ACL_MAX_UDF_NUM), AIR_E_BAD_PARAMETER);
+
+ aml_writeReg(unit, ACL_AUTW0, data);
+ aml_writeReg(unit, ACL_AUTW1, data);
+ aml_writeReg(unit, ACL_AUTW2, data);
+
+ value = (rule_idx & ACL_UDF_ADDR_MASK) | ACL_UDF_WRITE | (1U << ACL_UDF_ACC_OFFSET);
+ if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_clearUdfRule
+ * PURPOSE:
+ * Clear acl all udf rule.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_clearUdfRule(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+
+ value = ACL_UDF_CLEAR | (1U << ACL_UDF_ACC_OFFSET);
+ if ((ret = aml_writeReg(unit, ACL_AUTC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_setMeterTable
+ * PURPOSE:
+ * Set flow ingress rate limit by meter table.
+ * INPUT:
+ * unit -- Device ID
+ * meter_id -- Meter id
+ * enable -- Meter enable state
+ * rate -- Ratelimit(unit:64kbps)
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_setMeterTable(
+ const UI32_T unit,
+ const UI32_T meter_id,
+ const BOOL_T enable,
+ const UI32_T rate)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((meter_id >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((rate > ACL_MAX_TOKEN_NUM), AIR_E_BAD_PARAMETER);
+
+ if(TRUE == enable)
+ {
+ value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_WRITE | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_EN |
+ (rate & ACL_RATE_TOKEN_MASK);
+ }
+ else if(FALSE == enable)
+ {
+ value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_WRITE | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_DIS;
+ }
+ else
+ {
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_METER))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ if ((ret = aml_writeReg(unit, ACLRMC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:
+ * air_acl_getMeterTable
+ * PURPOSE:
+ * Get meter table configuration.
+ * INPUT:
+ * unit -- Device ID
+ * meter_id -- Meter id
+ * OUTPUT:
+ * ptr_enable -- Meter enable state
+ * ptr_rate -- Ratelimit(unit:64kbps)
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_acl_getMeterTable(
+ const UI32_T unit,
+ const UI32_T meter_id,
+ BOOL_T *ptr_enable,
+ UI32_T *ptr_rate)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T value = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((meter_id >= ACL_MAX_METER_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+ AIR_CHECK_PTR(ptr_rate);
+
+ if(AIR_E_TIMEOUT == _checkDone(unit, AIR_ACL_CHECK_METER))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ value = (1 << ACL_RATE_BUSY_OFFSET) | ACL_RATE_READ | ((meter_id & ACL_RATE_ID_MASK) << ACL_RATE_ID_OFFSET) | ACL_RATE_EN;
+
+ if ((ret = aml_writeReg(unit, ACLRMC, value)) != AIR_E_OK)
+ {
+ return ret;
+ }
+ aml_readReg(unit, ACLRMD1, &value);
+ *ptr_enable = ((value >> ACL_RATE_EN_OFFSET) & 0x1) ? TRUE : FALSE;
+ *ptr_rate = value & ACL_RATE_TOKEN_MASK;
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_aml.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_aml.c
new file mode 100644
index 0000000..38b85a4
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_aml.c
@@ -0,0 +1,218 @@
+/* FILE NAME: air_aml.c
+ * PURPOSE:
+ * It provides access management layer function.
+ * NOTES:
+ *
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+AML_DEV_ACCESS_T _ext_dev_access;
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+/* FUNCTION NAME: aml_readReg
+ * PURPOSE:
+ * To read data from the register of the specified chip unit.
+ * INPUT:
+ * unit -- the device unit
+ * addr_offset -- the address of register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readReg(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data)
+{
+ AIR_CHECK_PTR(ptr_data);
+
+ if (!_ext_dev_access.read_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.read_callback(unit, addr_offset, ptr_data);
+}
+
+/* FUNCTION NAME: aml_writeReg
+ * PURPOSE:
+ * To write data to the register of the specified chip unit.
+ * INPUT:
+ * unit -- the device unit
+ * addr_offset -- the address of register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writeReg(
+ const UI32_T unit,
+ const UI32_T addr_offset,
+ const UI32_T data)
+{
+ if (!_ext_dev_access.write_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.write_callback(unit, addr_offset, data);
+}
+
+/* FUNCTION NAME: aml_readPhyReg
+ * PURPOSE:
+ * To read data from the phy register of the specified chip unit in Clause22.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * addr_offset -- the address of phy register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readPhyReg(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data)
+{
+ AIR_CHECK_PTR(ptr_data);
+
+ if (!_ext_dev_access.phy_read_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.phy_read_callback(unit, port_id, addr_offset, ptr_data);
+}
+
+/* FUNCTION NAME: aml_writePhyReg
+ * PURPOSE:
+ * To write data to the phy register of the specified chip unit in Clause22.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * addr_offset -- the address of phy register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writePhyReg(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset,
+ const UI32_T data)
+{
+ if (!_ext_dev_access.phy_write_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.phy_write_callback(unit, port_id, addr_offset, data);
+}
+
+/* FUNCTION NAME: aml_readPhyRegCL45
+ * PURPOSE:
+ * To read data from the phy register of the specified chip unit in Clause45.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * dev_type -- phy register type
+ * addr_offset -- the address of phy register
+ * OUTPUT:
+ * ptr_data -- pointer for the register data
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_readPhyRegCL45(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ UI32_T *ptr_data)
+{
+ AIR_CHECK_PTR(ptr_data);
+
+ if (!_ext_dev_access.phy_cl45_read_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.phy_cl45_read_callback(unit, port_id, dev_type, addr_offset, ptr_data);
+}
+
+/* FUNCTION NAME: aml_writePhyRegCL45
+ * PURPOSE:
+ * To write data to the phy register of the specified chip unit in Clause45.
+ * INPUT:
+ * unit -- the device unit
+ * port_id -- physical port number
+ * dev_type -- phy register offset
+ * addr_offset -- the address of phy register
+ * data -- written data
+ * OUTPUT:
+ * none
+ * RETURN:
+ * NPS_E_OK -- Successfully write the data.
+ * NPS_E_OTHERS -- Failed to write the data.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+aml_writePhyRegCL45(
+ const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset,
+ const UI32_T data)
+{
+ if (!_ext_dev_access.phy_cl45_write_callback)
+ {
+ return AIR_E_OTHERS;
+ }
+
+ return _ext_dev_access.phy_cl45_write_callback(unit, port_id, dev_type, addr_offset, data);
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_cmd.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_cmd.c
new file mode 100644
index 0000000..95c11e8
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_cmd.c
@@ -0,0 +1,8022 @@
+/* FILE NAME: air_cmd.c
+ * PURPOSE:
+ * Define the command line function in AIR SDK.
+ * NOTES:
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+#define MAC_STR "%02X%02X%02X%02X%02X%02X"
+#define MAC2STR(m) (m)[0],(m)[1],(m)[2],(m)[3],(m)[4],(m)[5]
+#define AIR_MAC_LEN (12)
+#define CMD_NO_PARA (0xFFFFFFFF)
+#define CMD_VARIABLE_PARA (0xFFFFFFFE)
+#define L2_WDOG_KICK_NUM (100)
+
+#define TOLOWER(x) ((x) | 0x20)
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') || ('a' <= (c) && (c) <= 'f') || ('A' <= (c) && (c) <= 'F'))
+#define isdigit(c) ('0' <= (c) && (c) <= '9')
+#define CMD_CHECK_PARA(__shift__, __op__, __size__) do \
+{ \
+ if ((__shift__) __op__ (__size__)) \
+ { \
+ ; \
+ } \
+ else \
+ { \
+ return (AIR_E_BAD_PARAMETER); \
+ } \
+} while(0)
+
+/* DATA TYPE DECLARATIONS
+*/
+typedef struct {
+ C8_T* name;
+ AIR_ERROR_NO_T (*func)(UI32_T argc, C8_T *argv[]);
+ UI32_T argc_min;
+ C8_T* argc_errmsg;
+} AIR_CMD_T;
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+/* String Utility */
+static BOOL_T _strcmp(const char *s1, const char *s2);
+static C8_T * _strtok_r(C8_T *s, const C8_T *delim, C8_T **last);
+static C8_T * _strtok(C8_T *s, const C8_T *delim, C8_T **last);
+UI32_T _strtoul(const C8_T *cp, C8_T **endp, UI32_T base);
+static I32_T _strtol(const C8_T *cp, C8_T **endp, UI32_T base);
+
+/* Type Converter */
+static AIR_ERROR_NO_T _str2mac(C8_T *str, C8_T *mac);
+static AIR_ERROR_NO_T _hex2bit(const UI32_T hex, UI32_T *ptr_bit);
+static AIR_ERROR_NO_T _hex2bitstr(const UI32_T hex, C8_T *ptr_bit_str, UI32_T str_len);
+static AIR_ERROR_NO_T _portListStr2Ary(const C8_T *str, UI32_T *ary, const UI32_T ary_num);
+
+/* Register Operation */
+static AIR_ERROR_NO_T doRegRead(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doRegWrite(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doReg(UI32_T argc, C8_T *argv[]);
+
+/* PHY Operation */
+static AIR_ERROR_NO_T doPhyCL22Read(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhyCL22Write(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhyCL22(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhyCL45Read(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhyCL45Write(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhyCL45(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPhy(UI32_T argc, C8_T *argv[]);
+
+/* Porting setting */
+static AIR_ERROR_NO_T doPortSetMatrix(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSetVlanMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSet(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doPortGetMatrix(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortGetVlanMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortGet(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doPort(UI32_T argc, C8_T *argv[]);
+
+/* Vlan setting */
+static AIR_ERROR_NO_T doVlanInitiate(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanCreate(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanDestroy(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanDestroyAll(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanDump(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanAddPortMem(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanDelPortMem(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doVlanSetFid(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetMemPort(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetIVL(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPortBaseStag(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetStag(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetEgsTagCtlEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetEgsTagCtlCon(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetEgsTagCtl(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPortActFrame(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetLeakyVlanEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPortVlanAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetIgsPortETagAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPortETagAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPortOuterTPID(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSetPvid(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanSet(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doVlanGetPortActFrame(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetLeakyVlanEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetPortVlanAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetIgsPortETagAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetPortETagAttr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetPortOuterTPID(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGetPvid(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doVlanGet(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doVlan(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doFlowCtrl(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doJumbo(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doL2Add(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2Del(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2Clear(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2Get(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2Set(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2Dump(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doL2(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doAnMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLocalAdv(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doRemoteAdv(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSpeed(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortDuplex(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortStatus(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortBckPres(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortPsMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSmtSpdDwn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSpTag(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortEnable(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPort5GBaseRMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortHsgmiiMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortSgmiiMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortRmiiMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doPortRgmiiMode(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doSptagEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSptagMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSptagDecode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSptagEncode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSptag(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doMacAddr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T _printMacEntry(AIR_MAC_ENTRY_T * mt, UI32_T age_unit, UI8_T count, UI8_T title);
+static AIR_ERROR_NO_T doGetMacAddr(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMacAddrAgeOut(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doDumpMacAddr(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doLagMember(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagMemberCnt(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagPtseed(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagHashtype(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagDstInfo(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagState(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagSpsel(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLagSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLag(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doStpPortstate(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doStpGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doStpSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doStp(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doMirrorGetSid(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorDelSid(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorAddRlist(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorAddTlist(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorSetSessionEnable(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorSetSession(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorAdd(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirrorDel(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMirror(UI32_T argc,C8_T *argv[]);
+
+static AIR_ERROR_NO_T doMibClearPort(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMibClearAcl(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMibGetPort(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMibGetAcl(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMibClear(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMibGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doMib(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doQosScheduleAlgo(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosTrustMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosPri2Queue(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosDscp2Pri(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosRateLimitEnable(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosRateLimit(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosPortPriority(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosRateLimitExMngFrm(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQosSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doQos(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doDiagTxComply(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doDiagSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doDiagGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doDiag(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doLedMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLedState(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLedUsrDef(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLedBlkTime(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLedSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLedGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doLed(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doSwitchCpuPortEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitchCpuPort(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitchPhyLCIntrEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitchPhyLCIntrSts(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitchSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitchGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSwitch(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doShowVersion(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doShow(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T doStormEnable(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doStormRate(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doFldMode(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSaLearning(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSaLimit(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSecGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSecSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doSec(UI32_T argc, C8_T *argv[]);
+
+static void _air_acl_printRuleMap(UI32_T *rule_map, UI32_T ary_num);
+static AIR_ERROR_NO_T doAclEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclRule(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclUdfRule(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclRmvRule(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclRmvUdfRule(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclAction(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclRmvAction(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDumpAction(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclTrtcm(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclTrtcmEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclRmvTrtcm(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclPortEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDropEn(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDropThrsh(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDropPbb(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclMeter(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDump(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclSet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclGet(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclDel(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAclClear(UI32_T argc, C8_T *argv[]);
+static AIR_ERROR_NO_T doAcl(UI32_T argc, C8_T *argv[]);
+
+static AIR_ERROR_NO_T subcmd(const AIR_CMD_T tab[], UI32_T argc, C8_T *argv[]);
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+const static C8_T *_sptag_vpm[] =
+{
+ "untagged",
+ "8100",
+ "predefined",
+ "unknown"
+};
+
+const static C8_T *_sptag_pt[] =
+{
+ "disable pass through",
+ "enable pass through"
+};
+
+const static C8_T *_air_mac_address_forward_control_string [] =
+{
+ "Default",
+ "CPU include",
+ "CPU exclude",
+ "CPU only",
+ "Drop"
+};
+
+static AIR_CMD_T regCmds[] =
+{
+ {"r", doRegRead, 1, "reg r <reg(4'hex)>"},
+ {"w", doRegWrite, 2, "reg w <reg(4'hex)> <value(8'hex)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T phyCL22Cmds[] =
+{
+ {"r", doPhyCL22Read, 2, "phy cl22 r <port(0..4)> <reg(2'hex)>"},
+ {"w", doPhyCL22Write, 3, "phy cl22 w <port(0..4)> <reg(2'hex)> <value(4'hex)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T phyCL45Cmds[] =
+{
+ {"r", doPhyCL45Read, 3, "phy cl45 r <port(0..4)> <dev(2'hex)> <reg(3'hex)>"},
+ {"w", doPhyCL45Write, 4, "phy cl45 w <port(0..4)> <dev(2'hex)> <reg(3'hex)> <value(4'hex)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T phyCmds[] =
+{
+ {"cl22", doPhyCL22, 0, NULL},
+ {"cl45", doPhyCL45, 0, NULL},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T portSetCmds[] =
+{
+ {"matrix", doPortSetMatrix, 2, "port set matrix <port(0..6)> <matrix(6:0)>"},
+ {"vlanMode", doPortSetVlanMode, 2, "port set vlanMode <port(0..6)> <vlanMode(0:matrix,1:fallback,2:check,3:security)>"},
+ {"flowCtrl", doFlowCtrl, 3, "port set flowCtrl <port(0..6)> <dir(0:Tx,1:Rx)> <fc_en(1:En,0:Dis)>"},
+ {"jumbo", doJumbo, 2, "port set jumbo <pkt_len(0:1518,1:1536,2:1552,3:max)> <frame_len(2..15)>"},
+ {"anMode", doAnMode, 2, "port set anMode <port(0..4)> <en(0:force,1:AN)>"},
+ {"localAdv", doLocalAdv, 7, "port set localAdv <port(0..4)> <10H(1:En,0:Dis)> <10F(1:En,0:Dis)> <100H(1:En,0:Dis)> <100F(1:En,0:Dis)> <1000F(1:En,0:Dis)> <pause(1:En,0:Dis)>"},
+ {"speed", doPortSpeed, 2, "port set speed <port(0..4)> <speed(0:10M,1:100M,2:1G,3:2.5G)>"},
+ {"duplex", doPortDuplex, 2, "port set duplex <port(0..4)> <duplex(0:half,1:full)>"},
+ {"bckPres", doPortBckPres, 2, "port set bckPres <port(0..6)> <bckPres(1:En,0:Dis)>"},
+ {"psMode", doPortPsMode, 3, "port set psMode <port(0..4)> <ls(1:En,0:Dis)> <eee(1:En,0:Dis)>"},
+ {"smtSpdDwn", doPortSmtSpdDwn, 3, "port set smtSpdDwn <port(0..4)> <en(1:En,0:Dis)> <retry(2..5)>"},
+ {"spTag", doPortSpTag, 2, "port set spTag <port(0..6)> <en(1:En,0:Dis)>"},
+ {"enable", doPortEnable, 2, "port set enable <port(0..4)> <en(1:En,0:Dis)>"},
+ {"5GBaseRMode", doPort5GBaseRMode, CMD_NO_PARA, "port set 5GBaseRMode"},
+ {"hsgmiiMode", doPortHsgmiiMode, CMD_NO_PARA, "port set hsgmiiMode"},
+ {"sgmiiMode", doPortSgmiiMode, 2, "port set sgmiiMode <mode(0:AN,1:Force)> <speed(0:10M,1:100M,2:1G)>"},
+ {"rmiiMode", doPortRmiiMode, 1, "port set rmiiMode <speed(0:10M,1:100M)>"},
+ {"rgmiiMode", doPortRgmiiMode, 1, "port set rgmiiMode <speed(0:10M,1:100M,2:1G)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T portGetCmds[] =
+{
+ {"matrix", doPortGetMatrix, 1, "port get matrix <port(0..6)>"},
+ {"vlanMode", doPortGetVlanMode, 1, "port get vlanMode <port(0..6)>"},
+ {"flowCtrl", doFlowCtrl, 2, "port get flowCtrl <port(0..6)> <dir(0:Tx,1:Rx)>"},
+ {"jumbo", doJumbo, CMD_NO_PARA, "port get jumbo"},
+ {"anMode", doAnMode, 1, "port get anMode <port(0..4)>"},
+ {"localAdv", doLocalAdv, 1, "port get localAdv <port(0..4)>"},
+ {"remoteAdv", doRemoteAdv, 1, "port get remoteAdv <port(0..4)>"},
+ {"speed", doPortSpeed, 1, "port get speed <port(0..4)>"},
+ {"duplex", doPortDuplex, 1, "port get duplex <port(0..4)>"},
+ {"status", doPortStatus, 1, "port get status <port(0..4)>"},
+ {"bckPres", doPortBckPres, 1, "port get bckPres <port(0..6)>"},
+ {"psMode", doPortPsMode, 1, "port get psMode <port(0..4)>"},
+ {"smtSpdDwn", doPortSmtSpdDwn, 1, "port get smtSpdDwn <port(0..4)>"},
+ {"spTag", doPortSpTag, 1, "port get spTag <port(0..6)>"},
+ {"enable", doPortEnable, 1, "port get enable <port(0..4)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T portCmds[] =
+{
+ {"set", doPortSet, 0, NULL},
+ {"get", doPortGet, 0, NULL},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T sptagCmds[] =
+{
+ {"setEnable", doSptagEn, 2, "sptag setEnable port<port(0..6)> enable<1:enable 0:disable>"},
+ {"getEnable", doSptagEn, 1, "sptag getEnable port<port(0..6)>"},
+ {"setmode", doSptagMode, 2, "sptag setmode port<port(0..6)> mode<0:inset 1:replace>"},
+ {"getmode", doSptagMode, 1, "sptag getmode port<port(0..6)>"},
+ {"encode", doSptagEncode, 7, "sptag encode mode={ insert | replace } opc={ portmap | portid | lookup } dp={bitimap hex} vpm={ untagged | 8100 | 88a8 } pri=<UINT> cfi=<UINT> vid=<UINT> "},
+ {"decode", doSptagDecode, 4, "sptag decode <byte(hex)> <byte(hex)> <byte(hex)> <byte(hex)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T vlanSetCmds[] =
+{
+ {"fid", doVlanSetFid, 2, "vlan set fid <vid(0..4095)> <fid(0..7)>"},
+ {"memPort", doVlanSetMemPort, 2, "vlan set memPort <vid(0..4095)> <bitmap(6:0)>"},
+ {"ivl", doVlanSetIVL, 2, "vlan set ivl <vid(0..4095)> <(1:En,0:Dis)>"},
+ {"portBaseStag", doVlanSetPortBaseStag, 2, "vlan set portBaseStag <vid(0..4095)> <(1:En,0:Dis)>"},
+ {"stag", doVlanSetStag, 2, "vlan set stag <vid(0..4095)> <stag(0..4095)>"},
+ {"egsTagCtlEn", doVlanSetEgsTagCtlEn, 2, "vlan set egsTagCtlEn <vid(0..4095)> <(1:En,0:Dis)>"},
+ {"egsTagCtlCon", doVlanSetEgsTagCtlCon, 2, "vlan set egsTagCtlCon <vid(0..4095)> <(1:En,0:Dis)>"},
+ {"egsTagCtl", doVlanSetEgsTagCtl, 3, "vlan set egsTagCtl <vid(0..4095)> <port(0..6)> <ctlType(0:untag,2:tagged)>"},
+
+ {"portActFrame", doVlanSetPortActFrame, 2, "vlan set portActFrame <port(0..6)> <frameType(0:all,1:tagged,2:untagged)>"},
+ {"leakyVlanEn", doVlanSetLeakyVlanEn, 3, "vlan set LeakyVlanEn <port(0..6)> <pktType(0:uc,1:mc,2:bc,3:ipmc)> <(1:En,0:Dis)>"},
+ {"portVlanAttr", doVlanSetPortVlanAttr, 2, "vlan set portVlanAttr <port(0..6)> <vlanAttr(0:user,1:stack,2:translation,3:transparent)>"},
+ {"igsPortETagAttr", doVlanSetIgsPortETagAttr, 2, "vlan set igsPortETagAttr <port(0..6)> <egsTagAttr(0:disable,1:consistent,4:untagged,5:swap,6:tagged,7:stack)>"},
+ {"portEgsTagAttr", doVlanSetPortETagAttr, 2, "vlan set portEgsTagAttr <port(0..6)> <egsTagAttr(0:untagged,1:swap,2:tagged,3:stack)>"},
+ {"portOuterTPID", doVlanSetPortOuterTPID, 2, "vlan set portOuterTPID <port(0..6)> <TPID(hex)>"},
+ {"pvid", doVlanSetPvid, 2, "vlan set pvid <port(0..6)> <vid(0..4095)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T vlanGetCmds[] =
+{
+ {"portActFrame", doVlanGetPortActFrame, 1, "vlan get portActFrame <port(0..6)>"},
+ {"leakyVlanEn", doVlanGetLeakyVlanEn, 1, "vlan get leakyVlanEn <port(0..6)>"},
+ {"portVlanAttr", doVlanGetPortVlanAttr, 1, "vlan get portVlanAttr <port(0..6)>"},
+ {"igsPortETagAttr", doVlanGetIgsPortETagAttr, 1, "vlan get igsPortETagAttr <port(0..6)>"},
+ {"portEgsTagAttr", doVlanGetPortETagAttr, 1, "vlan get portEgsTagAttr <port(0..6)>"},
+ {"portOuterTPID", doVlanGetPortOuterTPID, 1, "vlan get portOuterTPID <port(0..6)>"},
+ {"pvid", doVlanGetPvid, 1, "vlan get pvid <port(0..6)>"},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T vlanCmds[] =
+{
+ {"initiate", doVlanInitiate, 9, "vlan initiate <vid(0..4095)> <fid(0..7)> <bitmap(6:0)> <ivl(1:En,0:Dis)> <portbasestag(1:En,0:Dis)> <stag(0..4095)> <egstagctlen(1:En,0:Dis)> <egstagcon(1:En,0:Dis)> <taggedbitmap(6:0)>"},
+ {"create", doVlanCreate, 1, "vlan create <vid(0..4095)>"},
+ {"destroy", doVlanDestroy, 1, "vlan destroy [ <vid(0..4095)> | <vidRange(vid0-vid1)> ]"},
+ {"destroyAll", doVlanDestroyAll, 0, "vlan destroyAll [ <restoreDefVlan(0:false,1:true)> | ]"},
+ {"dump", doVlanDump, 0, "vlan dump [ <vid(0..4095)> | <vidRange(vid0-vid1)> | ]"},
+ {"addPortMem", doVlanAddPortMem, 2, "vlan addPortMem <vid(0..4095)> <port(0..6)>"},
+ {"delPortMem", doVlanDelPortMem, 2, "vlan addPortMem <vid(0..4095)> <port(0..6)>"},
+ {"set", doVlanSet, 0, NULL},
+ {"get", doVlanGet, 0, NULL},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2ClearCmds[] =
+{
+ {"mac", doMacAddr, CMD_NO_PARA, "l2 clear mac"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2DelCmds[] =
+{
+ {"mac", doMacAddr, 3, "l2 del mac <mac(12'hex)> [ vid <vid(0..4095)> | fid <fid(0..15)> ]"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2AddCmds[] =
+{
+ {"mac", doMacAddr, 7, "l2 add mac <static(0:dynamic,1:static)> <unauth(0:auth,1:unauth)> <mac(12'hex)> <portlist(uintlist)> [ vid <vid(0..4095)> | fid <fid(0..15)> ] <src_mac_forward=(0:default,1:cpu-exclude,2:cpu-include,3:cpu-only,4:drop)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2SetCmds[] =
+{
+ {"macAddrAgeOut", doMacAddrAgeOut, 1, "l2 set macAddrAgeOut <time(1, 1000000)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2GetCmds[] =
+{
+ {"mac", doGetMacAddr, 3, "l2 get mac <mac(12'hex)> [ vid <vid(0..4095)> | fid <fid(0..15)> ]"},
+ {"macAddrAgeOut", doMacAddrAgeOut, CMD_NO_PARA, "l2 get macAddrAgeOut"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2DumpCmds[] =
+{
+ {"mac", doDumpMacAddr, 0, "l2 dump mac"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T l2Cmds[] =
+{
+ {"add", doL2Add, 0, NULL},
+ {"del", doL2Del, 0, NULL},
+ {"clear", doL2Clear, 0, NULL},
+ {"get", doL2Get, 0, NULL},
+ {"set", doL2Set, 0, NULL},
+ {"dump", doL2Dump, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T lagGetCmds[] =
+{
+ {"member", doLagMember, 1, "lag get member group_id(0 or 1)"},
+ {"dstInfo", doLagDstInfo, CMD_NO_PARA, "lag get dstInfo"},
+ {"ptseed", doLagPtseed, CMD_NO_PARA, "lag get ptseed"},
+ {"hashtype", doLagHashtype, CMD_NO_PARA, "lag get hashtype"},
+ {"state", doLagState, CMD_NO_PARA, "lag get state"},
+ {"spsel", doLagSpsel, CMD_NO_PARA, "lag get spsel"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T lagSetCmds[] =
+{
+ {"member", doLagMember, 4, "lag set member <group_id(0 or 1)> <member_index(0..3)> <enable(0,1)> <port index(0..6)>"},
+ {"dstInfo", doLagDstInfo, 7, "lag set dstInfo <sp(1:En,0:Dis)> <sa(1:En,0:Dis)> <da(1:En,0:Dis)> <sip(1:En,0:Dis)> <dip(1:En,0:Dis)> <sport(1:En,0:Dis)> <dport(1:En,0:Dis)>"},
+ {"ptseed", doLagPtseed, 1, "lag set ptseed <hex32>"},
+ {"hashtype", doLagHashtype, 1, "lag set hashtype <0-crc32lsb;1-crc32msb;2-crc16;3-xor4>"},
+ {"state", doLagState, 1, "lag set state <state(1:En,0:Dis)>"},
+ {"spsel", doLagSpsel, 1, "lag set spsel <soure port enable(1:En,0:Dis)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T lagCmds[] =
+{
+ {"get", doLagGet, 0, NULL},
+ {"set", doLagSet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T stpGetCmds[] =
+{
+ {"portstate", doStpPortstate, 2, "stp get portstate <port(0..6)> <fid(0..15)>"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T stpSetCmds[] =
+{
+ {"portstate", doStpPortstate, 3, "stp set portstate <port(0..6)> <fid(0..15)> <state(0:disable,1:listen,2:learn,3:forward)>"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T stpCmds[] =
+{
+ {"get", doStpGet, 0, NULL},
+ {"set", doStpSet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mirrorSetCmds[] =
+{
+ {"session", doMirrorSetSession, 6, "mirror set session <sid(0,1)> <dst_port(UINT)> <state(1:En,0:Dis)> <tag(1:on, 0:off)> <list(UINTLIST)> <dir(0:none,1:tx,2:rx,3:both)>"},
+ {"session-enable", doMirrorSetSessionEnable, 2, "mirror set session-enable <sid(0,1)> <state(1:En,0:Dis)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mirrorAddCmds[] =
+{
+ {"session-rlist", doMirrorAddRlist, 2, "mirror add session-rlist <sid(0,1)> <list(UINTLIST)>"},
+ {"session-tlist", doMirrorAddTlist, 2, "mirror add session-tlist <sid(0,1)> <list(UINTLIST)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mirrorGetCmds[] =
+{
+ {"session", doMirrorGetSid, 1, "mirror get session <sid(0,1)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mirrorDelCmds[] =
+{
+ {"session", doMirrorDelSid, 1, "mirror del session <sid(0,1)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mirrorCmds[] =
+{
+ {"set", doMirrorSet, 0, NULL},
+ {"add", doMirrorAdd, 0, NULL},
+ {"get", doMirrorGet, 0, NULL},
+ {"del", doMirrorDel, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mibClearCmds[] =
+{
+ {"port", doMibClearPort, 1, "mib clear port <port(0..6)>"},
+ {"all", doMibClearPort, 0, "mib clear all"},
+ {"acl", doMibClearAcl, 0, "mib clear acl"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mibGetCmds[] =
+{
+ {"port", doMibGetPort, 1, "mib get port <port(0..6)>"},
+ {"acl", doMibGetAcl, 1, "mib get acl <event(0..7)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T mibCmds[] =
+{
+ {"clear", doMibClear, 0, NULL},
+ {"get", doMibGet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T qosGetCmds[] =
+{
+ {"scheduleAlgo", doQosScheduleAlgo, 2, "qos get scheduleAlgo <portlist(UINTLIST)> <queue(UINT)>"},
+ {"trustMode", doQosTrustMode, 1, "qos get trustMode <portlist(UINTLIST)>"},
+ {"pri2Queue", doQosPri2Queue, 0, "qos get pri2Queue"},
+ {"dscp2Pri", doQosDscp2Pri, 1, "qos get dscp2Pri <dscp(0..63)>"},
+ {"rateLimitEnable", doQosRateLimitEnable, 1, "qos get rateLimitEnable <portlist(UINTLIST)>"},
+ {"rateLimit", doQosRateLimit, 1, "qos get rateLimit <portlist(UINTLIST)>"},
+ {"portPriority", doQosPortPriority, 1, "qos get portPriority <portlist(UINTLIST)>"},
+ {"rateLmtExMngFrm", doQosRateLimitExMngFrm, 0, "qos get rateLmtExMngFrm"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T qosSetCmds[] =
+{
+ {"scheduleAlgo", doQosScheduleAlgo, 4, "qos set scheduleAlgo <portlist(UINTLIST)> <queue(UINT)> <scheduler(0:SP,1:WRR,2:WFQ)> <weight(0..128)>, weight 0 is valid only on sp mode"},
+ {"trustMode", doQosTrustMode, 2, "qos set trustMode <portlist(UINTLIST)> <mode(0:port,1:1p-port,2:dscp-port,3:dscp-1p-port>"},
+ {"pri2Queue", doQosPri2Queue, 2, "qos set pri2Queue <priority(0..7)> <queue(0..7)>"},
+ {"dscp2Pri", doQosDscp2Pri, 2, "qos set dscp2Pri <dscp(0..63)> <priority(0..7)>"},
+ {"rateLimitEnable", doQosRateLimitEnable, 3, "qos set rateLimitEnable <portlist(UINTLIST)> <dir(0:egress,1:ingress)> <rate_en(1:En,0:Dis)>"},
+ {"rateLimit", doQosRateLimit, 5, "qos set rateLimit <portlist(UINTLIST)> <I_CIR(0..80000)> <I_CBS(0..127)> <E_CIR(0..80000)> <E_CBS(0..127)>"},
+ {"portPriority", doQosPortPriority, 2, "qos set portPriority <portlist(UINTLIST)> <priority(0..7)>"},
+ {"rateLmtExMngFrm", doQosRateLimitExMngFrm, 2, "qos set rateLmtExMngFrm <dir(0:egress)> <en(0:include,1:exclude)>"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T qosCmds[] =
+{
+ {"get", doQosGet, 0, NULL},
+ {"set", doQosSet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T diagSetCmds[] =
+{
+ {"txComply", doDiagTxComply, 2, "diag set txComply <phy(0..5)> <mode(0..8)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T diagGetCmds[] =
+{
+ {"txComply", doDiagTxComply, 1, "diag get txComply <phy(0..5)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T diagCmds[] =
+{
+ {"set", doDiagSet, 0, NULL},
+ {"get", doDiagGet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T ledSetCmds[] =
+{
+ {"mode", doLedMode, 1, "led set mode <mode(0:disable, 1..3:2 LED, 4:user-define)>"},
+ {"state", doLedState, 2, "led set state <led(0..1)> <state(1:En,0:Dis)>"},
+ {"usr", doLedUsrDef, 4, "led set usr <led(0..1)> <polarity(0:low, 1:high)> <on_evt(7'bin)> <blink_evt(10'bin)>"},
+ {"time", doLedBlkTime, 1, "led set time <time(0..5:32ms~1024ms)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T ledGetCmds[] =
+{
+ {"mode", doLedMode, CMD_NO_PARA, "led get mode"},
+ {"state", doLedState, 1, "led get state <led(0..1)>"},
+ {"usr", doLedUsrDef, 1, "led get usr <led(0..1)>"},
+ {"time", doLedBlkTime, CMD_NO_PARA, "led get time"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T ledCmds[] =
+{
+ {"set", doLedSet, 0, NULL},
+ {"get", doLedGet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T showCmds[] =
+{
+ {"version", doShowVersion, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T secGetCmds[] =
+{
+ {"stormEnable", doStormEnable, 2, "sec get stormEnable <port(0..6)> <type(0:bcst,1:mcst,2:ucst)>"},
+ {"stormRate", doStormRate, 2, "sec get stormRate <port(0..6)> <type(0:bcst,1:mcst,2:ucst)>"},
+ {"fldMode", doFldMode, 2, "sec get fldMode <port(0..6)> <type(0:bcst,1:mcst,2:ucst,3:qury>"},
+ {"saLearning", doSaLearning, 1, "sec get saLearning <port(0..6)>"},
+ {"saLimit", doSaLimit, 1, "sec get saLimit <port(0..6)>"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T secSetCmds[] =
+{
+ {"stormEnable", doStormEnable, 3, "sec set stormEnable <port(0..6)> <type(0:bcst,1:mcst,2:ucst)> <en(1:En,0:Dis)>"},
+ {"stormRate", doStormRate, 4, "sec set stormRate <port(0..6)> <type(0:bcst,1:mcst,2:ucst)> <count(0..255)> <unit(0:64k,1:256k,2:1M,3:4M,4:16M)>"},
+ {"fldMode", doFldMode, 3, "sec set fldMode <port(0..6)> <type(0:bcst,1:mcst,2:ucst,3:qury> <en(1:En,0:Dis)>"},
+ {"saLearning", doSaLearning, 2, "sec set saLearning <port(0..6)> <learn(0:disable,1:enable)>"},
+ {"saLimit", doSaLimit, 3, "sec set saLimit <port(0..6)> <mode(0:disable,1:enable)> <count(0..4095)>"},
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T secCmds[] =
+{
+ {"get", doSecGet, 0, NULL},
+ {"set", doSecSet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T switchSetCmds[] =
+{
+ {"cpuPortEn", doSwitchCpuPortEn, 1, "switch set cpuPortEn <cpu_en(1:En,0:Dis)>"},
+ {"cpuPort", doSwitchCpuPort, 1, "switch set cpuPort <port_number>"},
+ {"phyLCIntrEn", doSwitchPhyLCIntrEn, 2, "switch set phyLCIntrEn <phy(0..6)> <(1:En,0:Dis)>"},
+ {"phyLCIntrSts", doSwitchPhyLCIntrSts, 2, "switch set phyLCIntrSts <phy(0..6)> <(1:Clear)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T switchGetCmds[] =
+{
+ {"cpuPortEn", doSwitchCpuPortEn, CMD_NO_PARA, "switch get cpuPortEn"},
+ {"cpuPort", doSwitchCpuPort, CMD_NO_PARA, "switch get cpuPort"},
+ {"phyLCIntrEn", doSwitchPhyLCIntrEn, 1, "switch get phyLCIntrEn <phy(0..6)>"},
+ {"phyLCIntrSts", doSwitchPhyLCIntrSts, 1, "switch get phyLCIntrSts <phy(0..6)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T switchCmds[] =
+{
+ {"set", doSwitchSet, 0, NULL},
+ {"get", doSwitchGet, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T aclSetCmds[] =
+{
+ {"en", doAclEn, 1, "acl set en <en(1:En,0:Dis)>"},
+ {"rule", doAclRule, CMD_VARIABLE_PARA, "acl set rule <idx(0..127)>\n <state(0:Dis,1:En)> <reverse(0:Dis,1:En)> <end(0:Dis,1:En)>\n <portmap(7'bin)><ipv6(0:Dis,1:En,2:Not care)>\n[ dmac <dmac(12'hex)> <dmac_mask(12'hex)> ]\n[ smac <smac(12'hex)> <smac_mask(12'hex)> ]\n[ stag <stag(4'hex)> <stag_mask(4'hex)> ]\n[ ctag <ctag(4'hex)> <ctag_mask(4'hex)> ]\n[ etype <etype(4'hex)> <etype_mask(4'hex)> ]\n[ dip <dip(IPADDR)> <dip_mask(IPADDR)> ]\n[ sip <sip(IPADDR)> <sip_mask(IPADDR)> ]\n[ dscp <dscp(2'hex)> <dscp_mask(2'hex)> ]\n[ protocol <protocol(12'hex)> <protocol_mask(12'hex)> ]\n[ dport <dport(4'hex)> <dport_mask(4'hex)> ]\n[ sport <sport(4'hex)> <sport_mask(4'hex)> ]\n[ flow_label <flow_label(4'hex)> <flow_label_mask(4'hex)> ]\n[ udf <udf(4'hex)> <udf_mask(4'hex)> ] "},
+ {"udfRule", doAclUdfRule, 7, "acl set udfRule <idx(0..15)> <mode(0:pattern, 1:threshold)> [ <pat(4'hex)> <mask(4'hex)> | <low(4'hex)> <high(4'hex)> ] <start(0:MAC header, 1:L2 payload, 2:IPv4 header, 3:IPv6 header, 4:L3 payload, 5:TCP header, 6:UDP header, 7: L4 payload)> <offset(0..127,unit:2 bytes)> <portmap(7'bin)>"},
+ {"action", doAclAction, CMD_VARIABLE_PARA, "acl set action <idx(0..127)> \n[ forward <forward(0:Default,4:Exclude CPU,5:Include CPU,6:CPU only,7:Drop)> ]\n[ egtag <egtag(0:Default,1:Consistent,4:Untag,5:Swap,6:Tag,7:Stack)> ]\n[ mirrormap <mirrormap(2'bin)> ]\n[ priority <priority(0..7)> ]\n[ redirect <redirect(0:Dst,1:Vlan)> <portmap(7'bin)> ]\n[ leaky_vlan <leaky_vlan(1:En,0:Dis)> ]\n[ cnt_idx <cnt_idx(0..63)> ]\n[ rate_idx <rate_idx(0..31)> ] \n[ attack_idx <attack_idx(0..95)> ] \n[ vid <vid(0..4095)> ] \n[ manage <manage(1:En,0:Dis)> ] \n[ bpdu <bpdu(1:En,0:Dis)> ]\n[ class <class(0:Original,1:Defined)>[0..7] ]\n[ drop_pcd <drop_pcd(0:Original,1:Defined)> [red <red(0..7)>][yellow <yellow(0..7)>][green <green(0..7)>] ]\n[ color <color(0:Defined,1:Trtcm)> [ <defined_color(0:Dis,1:Green,2:Yellow,3:Red)> | <trtcm_idx(0..31)> ] ]"},
+ {"trtcm", doAclTrtcm, 5, "acl set trtcm <idx(1..31)> <cir(4'hex)> <pir(4'hex)> <cbs(4'hex)> <pbs(4'hex)>"},
+ {"trtcmEn", doAclTrtcmEn, 1, "acl set trtcmEn <en(1:En,0:Dis)>"},
+ {"portEn", doAclPortEn, 2, "acl set portEn <port(0..6)> <en(1:En,0:Dis)>"},
+ {"dropEn", doAclDropEn, 2, "acl set dropEn <port(0..6)> <en(1:En,0:Dis)>"},
+ {"dropThrsh", doAclDropThrsh, 5, "acl set dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <high(0..2047)> <low(0..2047)>"},
+ {"dropPbb", doAclDropPbb, 4, "acl set dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <probability(0..1023)>"},
+ {"meter", doAclMeter, 3, "acl set meter <idx(0..31)> <en(1:En,0:Dis)> <rate(0..65535)>\n Note: Limit rate = rate * 64Kbps"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T aclGetCmds[] =
+{
+ {"en", doAclEn, CMD_NO_PARA, "acl get en"},
+ {"rule", doAclRule, 1, "acl get rule <idx(0..127)> "},
+ {"udfRule", doAclUdfRule, 1, "acl get udfRule <idx(0..15)>"},
+ {"action", doAclAction, 1, "acl get action <idx(0..127)>"},
+ {"trtcm", doAclTrtcm, 1, "acl get trtcm <idx(1..31)>"},
+ {"trtcmEn", doAclTrtcmEn, CMD_NO_PARA, "acl get trtcmEn"},
+ {"portEn", doAclPortEn, 1, "acl get portEn <port(0..6)>"},
+ {"dropEn", doAclDropEn, 1, "acl get dropEn <port(0..6)>"},
+ {"dropThrsh", doAclDropThrsh, 3, "acl get dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)>"},
+ {"dropPbb", doAclDropPbb, 3, "acl get dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)>"},
+ {"meter", doAclMeter, 1, "acl get meter <idx(0..31)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T aclDelCmds[] =
+{
+ {"rule", doAclRmvRule, 1, "acl del rule <idx(0..127)>"},
+ {"udfRule", doAclRmvUdfRule, 1, "acl del udfRule <idx(0..15)>"},
+ {"action", doAclRmvAction, 1, "acl del action <idx(0..127)>"},
+ {"trtcm", doAclRmvTrtcm, 1, "acl del trtcm <idx(0..31)>"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T aclClearCmds[] =
+{
+ {"rule", doAclRmvRule, CMD_NO_PARA, "acl clear rule"},
+ {"udfRule", doAclRmvUdfRule, CMD_NO_PARA, "acl clear udfRule"},
+ {"action", doAclRmvAction, CMD_NO_PARA, "acl clear action"},
+ {"trtcm", doAclRmvTrtcm, CMD_NO_PARA, "acl clear trtcm"},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T aclCmds[] =
+{
+ {"set", doAclSet, 0, NULL},
+ {"get", doAclGet, 0, NULL},
+ {"del", doAclDel, 0, NULL},
+ {"clear", doAclClear, 0, NULL},
+ {"dump", doAclDump, 0, NULL},
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+static AIR_CMD_T Cmds[] =
+{
+ {"reg", doReg, 0, NULL},
+ {"phy", doPhy, 0, NULL},
+ {"port", doPort, 0, NULL},
+ {"vlan", doVlan, 0, NULL},
+ {"l2", doL2, 0, NULL},
+ {"lag", doLag, 0, NULL},
+ {"stp", doStp, 0, NULL},
+ {"mirror", doMirror, 0, NULL},
+ {"mib", doMib, 0, NULL},
+ {"qos", doQos, 0, NULL},
+ {"diag", doDiag, 0, NULL},
+ {"led", doLed, 0, NULL},
+ {"switch", doSwitch, 0, NULL},
+ {"show", doShow, 0, NULL},
+ {"sec", doSec, 0, NULL},
+ {"acl", doAcl, 0, NULL},
+ {"sptag", doSptag, 0, NULL},
+
+ /* last entry, do not modify this entry */
+ {NULL, NULL, 0, NULL},
+};
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+static BOOL_T
+_strcmp(const char *s1, const char *s2)
+{
+ while(*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 -1));
+}
+
+static C8_T *
+_strtok_r(
+ C8_T *s,
+ const C8_T *delim,
+ C8_T **last)
+{
+ char *spanp;
+ int c = 0, sc = 0;
+ char *tok;
+
+ if (s == NULL && (s = *last) == NULL)
+ {
+ return (NULL);
+ }
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+ for (;;)
+ {
+ c = *s++;
+ spanp = (char *)delim;
+ do
+ {
+ if (c == (sc = *spanp++))
+ {
+ break;
+ }
+ } while (sc != 0);
+ if (sc == 0)
+ {
+ break;
+ }
+ }
+
+ if (c == 0)
+ { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;)
+ {
+ c = *s++;
+ spanp = (char *)delim;
+ do
+ {
+ if ((sc = *spanp++) == c)
+ {
+ if (c == 0)
+ {
+ s = NULL;
+ }
+ else
+ {
+ s[-1] = 0;
+ }
+ *last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+static C8_T *
+_strtok(
+ C8_T *s,
+ const C8_T *delim,
+ C8_T **last)
+{
+ return _strtok_r(s, delim, last);
+}
+
+UI32_T
+_strtoul(
+ const C8_T *cp,
+ C8_T **endp,
+ UI32_T base)
+{
+ UI32_T result = 0, value = 0;
+
+ if (!base)
+ {
+ base = 10;
+ if (*cp == '0')
+ {
+ base = 8;
+ cp++;
+ if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1]))
+ {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ else if (base == 16)
+ {
+ if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+ {
+ cp += 2;
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base)
+ {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ {
+ *endp = (char *)cp;
+ }
+ return result;
+}
+
+static I32_T
+_strtol(
+ const C8_T *cp,
+ C8_T **endp,
+ UI32_T base)
+{
+ if(*cp=='-')
+ {
+ return -_strtoul(cp + 1, endp, base);
+ }
+ return _strtoul(cp, endp, base);
+}
+
+static AIR_ERROR_NO_T
+_str2mac(
+ C8_T *str,
+ C8_T *mac)
+{
+ UI32_T i = 0;
+ C8_T tmpstr[3];
+
+ /* check str */
+ AIR_CHECK_PTR(str);
+ AIR_PARAM_CHK(strlen(str) != AIR_MAC_LEN, AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(mac);
+
+ for(i=0; i<6; i++)
+ {
+ strncpy(tmpstr, str+(i*2), 2);
+ tmpstr[2] = '\0';
+ mac[i] = _strtoul(tmpstr, NULL, 16);
+ }
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+_str2ipv4(
+ const C8_T *ptr_str,
+ UI32_T *ptr_addr)
+{
+ UI32_T value = 0, idx = 0, shift = 0;
+
+ AIR_CHECK_PTR(ptr_str);
+ AIR_CHECK_PTR(ptr_addr);
+
+ /* e.g. 192.168.1.2, strlen = 11 */
+ for (idx = 0; idx < strlen(ptr_str); idx++)
+ {
+ if (('0' <= ptr_str[idx]) && ('9' >= ptr_str[idx]))
+ {
+ value = (value * 10) + (ptr_str[idx] - '0');
+ }
+ else if ('.' == ptr_str[idx])
+ {
+ CMD_CHECK_PARA(value, <, 256); /* Error: invalid value */
+ CMD_CHECK_PARA(shift, <, 4); /* Error: mem-overwrite */
+ *ptr_addr |= value << (24 - shift * 8);
+ shift += 1;
+ value = 0;
+ }
+ else
+ {
+ return AIR_E_BAD_PARAMETER; /* Error: not a digit number or dot */
+ }
+ }
+ CMD_CHECK_PARA(value, <, 256); /* Error: invalid value */
+ CMD_CHECK_PARA(shift, ==, 3); /* Error: not an ipv4 addr */
+ *ptr_addr |= value << (24 - shift * 8);
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+_str2ipv6(
+ const C8_T *ptr_str,
+ UI8_T *ptr_addr)
+{
+ UI32_T hex_value = 0, dec_value = 0, idx = 0;
+ BOOL_T double_colon = FALSE, ipv4_compatible = FALSE;
+ UI32_T double_colon_pos = 0, last_pos = 0;
+ UI8_T tmp_ipv6[16] = {0};
+
+ AIR_CHECK_PTR(ptr_str);
+ AIR_CHECK_PTR(ptr_addr);
+
+ /* e.g. invalid:
+ * 3ffe::c0a8:0: last cannot be colon except double-colon
+ * 3ffe:::c0a8:0 triple-colon
+ * 3ffe::c0a8::0 two double-colons
+ */
+
+ /* e.g. valid:
+ * 3ffe::c0a8:0 strlen = 12 (double-colon in middle)
+ * 3ffe:c0a8:0:: strlen = 13 (double-colon in last)
+ * ::3ffe:c0a8:0 strlen = 13 (double-colon in first)
+ * 3ffe::192.168.0.0 strlen = 17 (IPv4-compatible address)
+ */
+ for (idx = 0; idx < strlen(ptr_str); idx++)
+ {
+ if (('0' <= ptr_str[idx]) && ('9' >= ptr_str[idx]))
+ {
+ hex_value = (hex_value << 4) + (ptr_str[idx] - '0');
+ dec_value = (dec_value * 10) + (ptr_str[idx] - '0');
+ }
+ else if (('a' <= ptr_str[idx]) && ('f' >= ptr_str[idx]))
+ {
+ hex_value = (hex_value << 4) + (ptr_str[idx] - 'a') + 10;
+ }
+ else if (('A' <= ptr_str[idx]) && ('F' >= ptr_str[idx]))
+ {
+ hex_value = (hex_value << 4) + (ptr_str[idx] - 'A') + 10;
+ }
+ else if (':' == ptr_str[idx])
+ {
+ /* must belong to double-colon, calculate from last */
+ if (0 == idx)
+ {
+ continue;
+ }
+ /* not the first ch but a double-colon */
+ else if (':' == ptr_str[idx - 1])
+ {
+ CMD_CHECK_PARA(double_colon, ==, FALSE); /* Error: triple-colon or two double-colons */
+ double_colon = TRUE;
+ }
+ /* not the first ch and a double-colon */
+ else
+ {
+ CMD_CHECK_PARA(double_colon_pos, <, 15); /* Error: only 16 units for UI8_T */
+ CMD_CHECK_PARA(last_pos, <, 15); /* Error: only 16 units for UI8_T */
+ tmp_ipv6[last_pos] = (UI8_T)((hex_value >> 8) & 0xff);
+ tmp_ipv6[last_pos + 1] = (UI8_T)((hex_value >> 0) & 0xff);
+ double_colon_pos += (FALSE == double_colon)? 2 : 0;
+ last_pos += 2;
+ hex_value = 0;
+ dec_value = 0;
+ }
+ }
+ else if ('.' == ptr_str[idx])
+ {
+ CMD_CHECK_PARA(last_pos, <, 16); /* Error: only 16 units for UI8_T */
+ tmp_ipv6[last_pos] = dec_value;
+ last_pos += 1;
+ dec_value = 0;
+ ipv4_compatible = TRUE;
+ }
+ else
+ {
+ return AIR_E_BAD_PARAMETER; /* Error: not a hex number or colon */
+ }
+ }
+
+ /* last data */
+ if (':' != ptr_str[idx - 1])
+ {
+ if (FALSE == ipv4_compatible)
+ {
+ CMD_CHECK_PARA(last_pos, <, 15); /* Error: only 16 units for UI8_T */
+ tmp_ipv6[last_pos] = (UI8_T)((hex_value >> 8) & 0xff);
+ tmp_ipv6[last_pos + 1] = (UI8_T)((hex_value >> 0) & 0xff);
+ last_pos += 2;
+ }
+ else
+ {
+ CMD_CHECK_PARA(last_pos, <, 16); /* Error: only 16 units for UI8_T */
+ tmp_ipv6[last_pos] = dec_value;
+ last_pos += 1;
+ }
+ }
+ else
+ {
+ if (':' != ptr_str[idx - 2])
+ {
+ return AIR_E_BAD_PARAMETER; /* Error: last cannot be colon except double-colon */
+ }
+ }
+
+ /* move tmp_ipv6 to ptr_value */
+ if (TRUE == double_colon)
+ {
+ /* e.g.
+ * 3ffe::c0a8:0 double_colon_pos = 2, last_pos = 4+2, tmp_ipv6 = {3f,fe,c0,a8,00,00,...}
+ * 3ffe:c0a8:0:: double_colon_pos = 6, last_pos = 6, tmp_ipv6 = {3f,fe,c0,a8,00,00,...}
+ * ::3ffe:c0a8:0 double_colon_pos = 0, last_pos = 4+2, tmp_ipv6 = {3f,fe,c0,a8,00,00,...}
+ * 3ffe::192.168.0.0 double_colon_pos = 2, last_pos = 5+1, tmp_ipv6 = {3f,fe,c0,a8,00,00,...}
+ *
+ * 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ * 3ffe::c0a8:0 ptr_value = {3f,fe,--,--,--,--,--,--,--,--,--,--,--,--,--,--}
+ * 3ffe:c0a8:0:: ptr_value = {3f,fe,c0,a8,00,00,--,--,--,--,--,--,--,--,--,--}
+ * ::3ffe:c0a8:0 ptr_value = {--,--,--,--,--,--,--,--,--,--,--,--,--,--,--,--}
+ * 3ffe::192.168.0.0 ptr_value = {3f,fe,--,--,--,--,--,--,--,--,--,--,--,--,--,--}
+ */
+ for (idx = 0; idx < double_colon_pos; idx++)
+ {
+ ptr_addr[idx] = tmp_ipv6[idx];
+ }
+ /* e.g.
+ * 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ * 3ffe::c0a8:0 ptr_value = {3f,fe,--,--,--,--,--,--,--,--,--,--,c0,a8,00,00}
+ * 3ffe:c0a8:0:: ptr_value = {3f,fe,c0,a8,00,00,--,--,--,--,--,--,--,--,--,--}
+ * ::3ffe:c0a8:0 ptr_value = {--,--,--,--,--,--,--,--,--,--,3f,fe,c0,a8,00,00}
+ * 3ffe::192.168.0.0 ptr_value = {3f,fe,--,--,--,--,--,--,--,--,--,--,c0,a8,00,00}
+ */
+ for (idx = double_colon_pos; idx < last_pos; idx++)
+ {
+ ptr_addr[16 - (last_pos - idx)] = tmp_ipv6[idx];
+ }
+ }
+ else
+ {
+ for (idx = 0; idx < 16; idx++)
+ {
+ ptr_addr[idx] = tmp_ipv6[idx];
+ }
+ }
+
+ return AIR_E_OK;
+}
+
+void
+_showIpv6Str(
+ const UI8_T *ptr_ipv6,
+ C8_T *ptr_str)
+{
+ UI32_T idx = 0, next = 0, last = 16;
+ UI32_T cont_zero = 0;
+
+ while (idx < last)
+ {
+ if ((0 == cont_zero) && (0 == ptr_ipv6[idx]) && (0 == ptr_ipv6[idx + 1]))
+ {
+ next = idx + 2;
+
+ while (next < last)
+ {
+ if ((ptr_ipv6[next]) || (ptr_ipv6[next + 1]))
+ {
+ AIR_PRINT(
+ ptr_str + strlen(ptr_str),
+ 40 - strlen(ptr_str),
+ "%s", (cont_zero) ? (":") : (":0"));
+ break;
+ }
+
+ if (0 == cont_zero)
+ {
+ cont_zero = 1;
+ }
+ next += 2;
+ }
+
+ if (next == last)
+ {
+
+ AIR_PRINT(
+ ptr_str + strlen(ptr_str),
+ 40 - strlen(ptr_str),
+ "%s", (cont_zero) ? ("::") : (":0"));
+ }
+
+ idx = next;
+ }
+ else
+ {
+ if (idx)
+ {
+ AIR_PRINT(
+ ptr_str + strlen(ptr_str),
+ 40 - strlen(ptr_str),
+ ":");
+ }
+
+ if (ptr_ipv6[idx])
+ {
+ AIR_PRINT(
+ ptr_str + strlen(ptr_str),
+ 40 - strlen(ptr_str),
+ "%0x%02x", ptr_ipv6[idx], ptr_ipv6[idx + 1]);
+ }
+ else
+ {
+ AIR_PRINT(
+ ptr_str + strlen(ptr_str),
+ 40 - strlen(ptr_str),
+ "%0x", ptr_ipv6[idx + 1]);
+ }
+
+ idx += 2;
+ }
+ }
+}
+
+static AIR_ERROR_NO_T
+_hex2bit(
+ const UI32_T hex,
+ UI32_T *ptr_bit)
+{
+ UI32_T i = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptr_bit);
+
+ (*ptr_bit) = 0;
+ for(i=0; i<AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(hex & BIT(i))
+ {
+ (*ptr_bit) |= BITS_OFF_L(1UL, 4*(AIR_MAX_NUM_OF_PORTS - i - 1), 4);
+ }
+ }
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+_hex2bitstr(
+ const UI32_T hex,
+ C8_T *ptr_bit_str,
+ UI32_T str_len)
+{
+ UI32_T i = 0;
+ C8_T str_bitmap[AIR_MAX_NUM_OF_PORTS+1];
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptr_bit_str);
+ AIR_PARAM_CHK(str_len <= AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+
+ memset(str_bitmap, 0, AIR_MAX_NUM_OF_PORTS+1);
+
+ for(i=0; i<AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(hex & BIT(i))
+ {
+ str_bitmap[i] = '1';
+ }
+ else
+ {
+ str_bitmap[i] = '-';
+ }
+ }
+ str_bitmap[i] = '\0';
+ strncpy(ptr_bit_str, str_bitmap, i+1);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+_portListStr2Ary(
+ const C8_T *str,
+ UI32_T *ary,
+ const UI32_T ary_num)
+{
+ UI32_T i = 0;
+ UI32_T str_len = 0;
+ UI32_T val = 0;
+ C8_T *str2;
+ C8_T *pch;
+ C8_T *last;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(str);
+ AIR_CHECK_PTR(ary);
+ AIR_PARAM_CHK(0 == ary_num, AIR_E_BAD_PARAMETER);
+
+ /* Allocate new string */
+ str_len = strlen(str);
+ str2 = AIR_MALLOC(str_len+1);
+ AIR_CHECK_PTR(str2);
+ memset(str2, 0, str_len+1);
+ strncpy(str2, str, str_len+1);
+
+ /* clear array */
+ memset(ary, 0, ary_num*4);
+
+ /* split string by ',' */
+ pch = _strtok(str2, ",", &last);
+ while(NULL != pch)
+ {
+ val = _strtoul(pch, NULL, 0);
+ ary[val/32] |= BIT(val%32);
+ pch = _strtok(NULL, ",", &last);
+ }
+
+ AIR_FREE(str2);
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doRegRead(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T reg = 0, val = 0;
+
+ reg = _strtoul(argv[0], NULL, 16);
+ aml_readReg(0, reg, &val);
+ AIR_PRINT("Read reg=0x%x, value=0x%x\n", reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doRegWrite(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T reg = 0, val = 0;
+
+ reg = _strtoul(argv[0], NULL, 16);
+ val = _strtoul(argv[1], NULL, 16);
+ aml_writeReg(0, reg, val);
+ AIR_PRINT("Write reg=0x%x, value=0x%x\n", reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doReg(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(regCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPhyCL22Read(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T port = 0, reg = 0, val = 0;
+
+ port = _strtoul(argv[0], NULL, 0);
+ reg = _strtoul(argv[1], NULL, 16);
+ aml_readPhyReg(0, port, reg, &val);
+ AIR_PRINT("Phy read port=%d, reg=0x%x, value=0x%x\n", port, reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doPhyCL22Write(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T port = 0, reg = 0, val = 0;
+
+ port = _strtoul(argv[0], NULL, 0);
+ reg = _strtoul(argv[1], NULL, 16);
+ val = _strtoul(argv[2], NULL, 16);
+ aml_writePhyReg(0, port, reg, val);
+ AIR_PRINT("Phy write port=%d, reg=0x%x, value=0x%x\n", port, reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doPhyCL22(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(phyCL22Cmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPhyCL45Read(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T port = 0, dev = 0, reg = 0, val = 0;
+
+ port = _strtoul(argv[0], NULL, 0);
+ dev = _strtoul(argv[1], NULL, 16);
+ reg = _strtoul(argv[2], NULL, 16);
+ aml_readPhyRegCL45(0, port, dev, reg, &val);
+ AIR_PRINT("Phy read port=%d, dev=0x%x, reg=0x%x, value=0x%x\n", port, dev, reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doPhyCL45Write(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ UI32_T port = 0, dev = 0, reg = 0, val = 0;
+
+ port = _strtoul(argv[0], NULL, 0);
+ dev = _strtoul(argv[1], NULL, 16);
+ reg = _strtoul(argv[2], NULL, 16);
+ val = _strtoul(argv[3], NULL, 16);
+ aml_writePhyRegCL45(0, port, dev, reg, val);
+ AIR_PRINT("Phy write port=%d, dev=0x%x, reg=0x%x, value=0x%x\n", port, dev, reg, val);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doPhyCL45(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(phyCL45Cmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPhy(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(phyCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPortSetMatrix(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ UI32_T matrix = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ matrix = _strtoul(argv[1], NULL, 16);
+ rc = air_port_setPortMatrix(0, port, matrix);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doPortSetVlanMode(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_PORT_VLAN_MODE_T vlan_mode;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ vlan_mode = _strtoul(argv[1], NULL, 0);
+ rc = air_port_setVlanMode(0, port, vlan_mode);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doPortSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(portSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPortGetMatrix(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ UI32_T matrix = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_port_getPortMatrix(0, port, &matrix);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Matrix: %2x\n", port, matrix);
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doPortGetVlanMode(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_PORT_VLAN_MODE_T vlan_mode;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_port_getVlanMode(0, port, &vlan_mode);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Vlan Mode: ", port);
+ switch(vlan_mode)
+ {
+ case AIR_PORT_VLAN_MODE_PORT_MATRIX:
+ AIR_PRINT("matrix(%d)\n", vlan_mode);
+ break;
+ case AIR_PORT_VLAN_MODE_FALLBACK:
+ AIR_PRINT("fallback(%d)\n", vlan_mode);
+ break;
+ case AIR_PORT_VLAN_MODE_CHECK:
+ AIR_PRINT("check(%d)\n", vlan_mode);
+ break;
+ case AIR_PORT_VLAN_MODE_SECURITY:
+ AIR_PRINT("security(%d)\n", vlan_mode);
+ break;
+ default:
+ AIR_PRINT("unknown(%d)\n", vlan_mode);
+ break;
+ };
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doPortGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(portGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doPort(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(portCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doVlanInitiate(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ AIR_VLAN_ENTRY_ATTR_T vlan_entry = {0};
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ if (9 == argc)
+ {
+ vlan_entry.vlan_entry_format.fid = _strtoul(argv[1], NULL, 0);
+ vlan_entry.vlan_entry_format.port_mem = _strtoul(argv[2], NULL, 0);
+ vlan_entry.vlan_entry_format.ivl = _strtoul(argv[3], NULL, 0);
+ vlan_entry.vlan_entry_format.port_stag = _strtoul(argv[4], NULL, 0);
+ vlan_entry.vlan_entry_format.stag = _strtoul(argv[5], NULL, 0);
+ vlan_entry.vlan_entry_format.eg_ctrl_en = _strtoul(argv[6], NULL, 0);
+ vlan_entry.vlan_entry_format.eg_con = _strtoul(argv[7], NULL, 0);
+ vlan_entry.vlan_entry_format.eg_ctrl = _strtoul(argv[8], NULL, 0);
+
+ rc = air_vlan_create(0, vid, &vlan_entry);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ rc = AIR_E_BAD_PARAMETER;
+ }
+
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_EXISTS: AIR_PRINT("VLAN already exist!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanCreate(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_create(0, vid, NULL);
+
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_EXISTS: AIR_PRINT("VLAN already exist!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanDestroy(UI32_T argc, C8_T *argv[])
+{
+ C8_T *token = NULL;
+ UI16_T vid = 0, vid_limit = AIR_VLAN_ID_MAX;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ if (argc > 0)
+ {
+ if (isdigit(argv[0][0]))
+ {
+ token = _strtok(argv[0], "-", &argv[0]);
+ vid = _strtoul(token, NULL, 0);
+ if ((token = _strtok(argv[0], "-", &argv[0])))
+ vid_limit = _strtoul(token, NULL, 0);
+ else
+ vid_limit = vid;
+ if (AIR_VLAN_ID_MAX < vid_limit)
+ {
+ AIR_PRINT("vid number should less than %d!\n", AIR_VLAN_ID_MAX);
+ return AIR_E_BAD_PARAMETER;
+ }
+ if (vid > vid_limit)
+ {
+ AIR_PRINT("vid0 should less than vid1!\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Bad parameter!\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+
+ for (; vid <= vid_limit; vid++)
+ {
+ rc = air_vlan_destroy(0, vid);
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanDestroyAll(UI32_T argc, C8_T *argv[])
+{
+ UI32_T restore_def_vlan = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ if (argc > 0)
+ {
+ restore_def_vlan = _strtoul(argv[0], NULL, 0);
+ }
+
+ rc = air_vlan_destroyAll(0, restore_def_vlan);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanDump(UI32_T argc, C8_T *argv[])
+{
+ C8_T *token = NULL;
+ UI16_T port = 0, valid_count = 0, vid = 0, vid_limit = AIR_VLAN_ID_MAX;
+ AIR_PORT_EGS_TAG_ATTR_T tag_ctl[AIR_MAX_NUM_OF_PORTS] = {0};
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ if (argc > 0)
+ {
+ if (isdigit(argv[0][0]))
+ {
+ token = _strtok(argv[0], "-", &argv[0]);
+ vid = _strtoul(token, NULL, 0);
+ if ((token = _strtok(argv[0], "-", &argv[0])))
+ vid_limit = _strtoul(token, NULL, 0);
+ else
+ vid_limit = vid;
+ if (AIR_VLAN_ID_MAX < vid_limit)
+ {
+ AIR_PRINT("vid number should less than %d!\n", AIR_VLAN_ID_MAX);
+ return AIR_E_BAD_PARAMETER;
+ }
+ if (vid > vid_limit)
+ {
+ AIR_PRINT("vid0 should less than vid1!\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Bad parameter!\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+
+ for (valid_count = 0; vid <= vid_limit; vid++)
+ {
+ _air_vlan_readEntry(0, vid, &vlan_entry);
+ if (vlan_entry.valid)
+ {
+ valid_count++;
+ if (1 == valid_count)
+ AIR_PRINT(" Vid Fid MemPort Ivl PortBaseStag Stag EgsTagCtlEn EgsTagCon EgsTagCtl\n======================================================================\n");
+ for (port = 0; port < AIR_MAX_NUM_OF_PORTS; port++)
+ tag_ctl[port] = (vlan_entry.vlan_entry_format.eg_ctrl >> (port * 2)) & 0x3;
+ AIR_PRINT("%4d %3d %2x %3d %12d %4d %11d %9d %1x%1x%1x%1x%1x%1x%1x\n",
+ vid, vlan_entry.vlan_entry_format.fid, vlan_entry.vlan_entry_format.port_mem, vlan_entry.vlan_entry_format.ivl,
+ vlan_entry.vlan_entry_format.port_stag, vlan_entry.vlan_entry_format.stag, vlan_entry.vlan_entry_format.eg_ctrl_en, vlan_entry.vlan_entry_format.eg_con,
+ tag_ctl[6], tag_ctl[5], tag_ctl[4], tag_ctl[3], tag_ctl[2], tag_ctl[1], tag_ctl[0]);
+ }
+ }
+
+ if (!valid_count)
+ AIR_PRINT("not found!\n");
+ else
+ AIR_PRINT("Found %d valid entries!\n", valid_count);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doVlanAddPortMem(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0, port = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ port = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_addMemberPort(0, vid, port);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanDelPortMem(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0, port = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ port = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_delMemberPort(0, vid, port);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetFid(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ UI8_T fid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ fid = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setFid(0, vid, fid);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetMemPort(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0, port_bitmap = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ port_bitmap = _strtoul(argv[1], NULL, 16);
+ rc = air_vlan_setMemberPort(0, vid, port_bitmap);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetIVL(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ BOOL_T enable = TRUE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ enable = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setIVL(0, vid, enable);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPortBaseStag(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ BOOL_T enable = TRUE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ enable = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setPortBasedStag(0, vid, enable);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetStag(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0, stag = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ stag = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setServiceTag(0, vid, stag);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetEgsTagCtlEn(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ BOOL_T enable = TRUE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ enable = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setEgsTagCtlEnable(0, vid, enable);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetEgsTagCtlCon(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0;
+ BOOL_T enable = TRUE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ enable = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setEgsTagConsistent(0, vid, enable);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetEgsTagCtl(UI32_T argc, C8_T *argv[])
+{
+ UI16_T vid = 0, port = 0;
+ AIR_PORT_EGS_TAG_ATTR_T tag_ctl = AIR_PORT_EGS_TAG_ATTR_UNTAGGED;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ vid = _strtoul(argv[0], NULL, 0);
+ port = _strtoul(argv[1], NULL, 0);
+ tag_ctl = _strtoul(argv[2], NULL, 0);
+ rc = air_vlan_setPortEgsTagCtl(0, vid, port, tag_ctl);
+ switch (rc)
+ {
+ case AIR_E_OK: break;
+ case AIR_E_ENTRY_NOT_FOUND: AIR_PRINT("VLAN not found!\n"); break;
+ default: AIR_PRINT("Error %d: Operation failed!\n", rc); break;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPortActFrame(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0;
+ AIR_VLAN_ACCEPT_FRAME_TYPE_T type = AIR_VLAN_ACCEPT_FRAME_TYPE_ALL;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ type = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setPortAcceptFrameType(0, port, type);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetLeakyVlanEn(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0;
+ AIR_LEAKY_PKT_TYPE_T pkt_type = AIR_LEAKY_PKT_TYPE_UNICAST;
+ BOOL_T enable = TRUE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ pkt_type = _strtoul(argv[1], NULL, 0);
+ enable = _strtoul(argv[2], NULL, 0);
+ rc = air_vlan_setPortLeakyVlanEnable(0, port, pkt_type, enable);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPortVlanAttr(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0;
+ AIR_VLAN_PORT_ATTR_T attr = AIR_VLAN_PORT_ATTR_USER_PORT;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ attr = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setPortAttr(0, port, attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetIgsPortETagAttr(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0;
+ AIR_IGR_PORT_EG_TAG_ATTR_T attr = AIR_IGR_PORT_EG_TAG_ATTR_DISABLE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ attr = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setIgrPortTagAttr(0, port, attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPortETagAttr(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0;
+ AIR_PORT_EGS_TAG_ATTR_T attr = AIR_PORT_EGS_TAG_ATTR_UNTAGGED;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ attr = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setPortEgsTagAttr(0, port, attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPortOuterTPID(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0, tpid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ tpid = _strtoul(argv[1], NULL, 16);
+ rc = air_vlan_setPortOuterTPID(0, port, tpid);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSetPvid(UI32_T argc, C8_T *argv[])
+{
+ UI16_T port = 0, pvid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ pvid = _strtoul(argv[1], NULL, 0);
+ rc = air_vlan_setPortPVID(0, port, pvid);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(vlanSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doVlanGetPortActFrame(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_VLAN_ACCEPT_FRAME_TYPE_T type;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getPortAcceptFrameType(0, port, &type);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Acceptable Frame Type: ", port);
+ switch(type)
+ {
+ case AIR_VLAN_ACCEPT_FRAME_TYPE_ALL:
+ AIR_PRINT("all(%d)\n", type);
+ break;
+ case AIR_VLAN_ACCEPT_FRAME_TYPE_TAG_ONLY:
+ AIR_PRINT("tagged-only(%d)\n", type);
+ break;
+ case AIR_VLAN_ACCEPT_FRAME_TYPE_UNTAG_ONLY:
+ AIR_PRINT("untagged-only(%d)\n", type);
+ break;
+ default:
+ AIR_PRINT("unknown(%d)\n", type);
+ break;
+ };
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetLeakyVlanEn(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ BOOL_T uc = FALSE, mc = FALSE, bc = FALSE;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc += air_vlan_getPortLeakyVlanEnable(0, port, AIR_LEAKY_PKT_TYPE_UNICAST, &uc);
+ rc += air_vlan_getPortLeakyVlanEnable(0, port, AIR_LEAKY_PKT_TYPE_MULTICAST, &mc);
+ rc += air_vlan_getPortLeakyVlanEnable(0, port, AIR_LEAKY_PKT_TYPE_BROADCAST, &bc);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+
+ AIR_PRINT("Port %d Leaky Vlan Enable\n", port);
+ AIR_PRINT("Unicast : %s\n", uc ? "TRUE" : "FALSE");
+ AIR_PRINT("Multicast : %s\n", mc ? "TRUE" : "FALSE");
+ AIR_PRINT("Broadcast : %s\n", bc ? "TRUE" : "FALSE");
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetPortVlanAttr(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_VLAN_PORT_ATTR_T attr;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getPortAttr(0, port, &attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Vlan Attr: ", port);
+ switch(attr)
+ {
+ case AIR_VLAN_PORT_ATTR_USER_PORT:
+ AIR_PRINT("user port(%d)\n", attr);
+ break;
+ case AIR_VLAN_PORT_ATTR_STACK_PORT:
+ AIR_PRINT("stack port(%d)\n", attr);
+ break;
+ case AIR_VLAN_PORT_ATTR_TRANSLATION_PORT:
+ AIR_PRINT("translation port(%d)\n", attr);
+ break;
+ case AIR_VLAN_PORT_ATTR_TRANSPARENT_PORT:
+ AIR_PRINT("transparent port(%d)\n", attr);
+ break;
+ default:
+ AIR_PRINT("unknown(%d)\n", attr);
+ break;
+ };
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetIgsPortETagAttr(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_IGR_PORT_EG_TAG_ATTR_T attr;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getIgrPortTagAttr(0, port, &attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Incomming Port Egress Tag Attr: ", port);
+ switch(attr)
+ {
+ case AIR_IGR_PORT_EG_TAG_ATTR_DISABLE:
+ AIR_PRINT("disable(%d)\n", attr);
+ break;
+ case AIR_IGR_PORT_EG_TAG_ATTR_CONSISTENT:
+ AIR_PRINT("consistent(%d)\n", attr);
+ break;
+ case AIR_IGR_PORT_EG_TAG_ATTR_UNTAGGED:
+ AIR_PRINT("untagged(%d)\n", attr);
+ break;
+ case AIR_IGR_PORT_EG_TAG_ATTR_SWAP:
+ AIR_PRINT("swap(%d)\n", attr);
+ break;
+ case AIR_IGR_PORT_EG_TAG_ATTR_TAGGED:
+ AIR_PRINT("tagged(%d)\n", attr);
+ break;
+ case AIR_IGR_PORT_EG_TAG_ATTR_STACK:
+ AIR_PRINT("stack(%d)\n", attr);
+ break;
+ default:
+ AIR_PRINT("unknown(%d)\n", attr);
+ break;
+ };
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetPortETagAttr(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_PORT_EGS_TAG_ATTR_T attr;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getPortEgsTagAttr(0, port, &attr);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Egress Tag Attr: ", port);
+ switch(attr)
+ {
+ case AIR_PORT_EGS_TAG_ATTR_UNTAGGED:
+ AIR_PRINT("untagged(%d)\n", attr);
+ break;
+ case AIR_PORT_EGS_TAG_ATTR_SWAP:
+ AIR_PRINT("swap(%d)\n", attr);
+ break;
+ case AIR_PORT_EGS_TAG_ATTR_TAGGED:
+ AIR_PRINT("tagged(%d)\n", attr);
+ break;
+ case AIR_PORT_EGS_TAG_ATTR_STACK:
+ AIR_PRINT("stack(%d)\n", attr);
+ break;
+ default:
+ AIR_PRINT("unknown(%d)\n", attr);
+ break;
+ };
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetPortOuterTPID(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ UI16_T tpid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getPortOuterTPID(0, port, &tpid);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d Outer TPID: %4x\n", port, tpid);
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGetPvid(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ UI16_T pvid = 0;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ rc = air_vlan_getPortPVID(0, port, &pvid);
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("Error: Operation failed!\n");
+ return rc;
+ }
+ AIR_PRINT("Port %d PVID: %d\n", port, pvid);
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doVlanGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(vlanGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doVlan(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(vlanCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doJumbo(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ I32_T pkt_len = 0, frame_len = 0;
+
+ if(0 == argc)
+ {
+ /* get command */
+ ret = air_port_getJumbo(0, &pkt_len, &frame_len);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get ");
+ switch(pkt_len)
+ {
+ case 0:
+ AIR_PRINT("RX_1518 ");
+ break;
+ case 1:
+ AIR_PRINT("RX_1536 ");
+ break;
+ case 2:
+ AIR_PRINT("RX_1552 ");
+ break;
+ case 3:
+ AIR_PRINT("RX_JUMBO ");
+ break;
+ }
+ AIR_PRINT("frames lengths %d KBytes\n", frame_len);
+ }
+ else
+ {
+ AIR_PRINT("Get Jumbo Fail.\n");
+ }
+ }
+ else
+ {
+ /* set command */
+ pkt_len = _strtol(argv[0], NULL, 10);
+ frame_len = _strtol(argv[1], NULL, 10);
+
+ ret = air_port_setJumbo(0, pkt_len, frame_len);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set ");
+ switch(pkt_len)
+ {
+ case 0:
+ AIR_PRINT("RX_1518 ");
+ break;
+ case 1:
+ AIR_PRINT("RX_1536 ");
+ break;
+ case 2:
+ AIR_PRINT("RX_1552 ");
+ break;
+ case 3:
+ AIR_PRINT("RX_JUMBO ");
+ break;
+ }
+ AIR_PRINT("frames lengths %d KBytes\n", frame_len);
+ }
+ else
+ AIR_PRINT("Set Jumbo Fail.\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doFlowCtrl(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ BOOL_T fc_en = 0, dir = 0;
+ I32_T port = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+ dir = _strtol(argv[1], NULL, 10);
+
+ if(2 == argc)
+ {
+ /* get command */
+ ret = air_port_getFlowCtrl(0, port, dir, &fc_en);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Get Port%02d %s Flow Control %s\n", port, ((dir)?"RX":"TX"), ((fc_en)?"Enable":"Disable"));
+ else
+ AIR_PRINT("Get Flow Control Fail.\n");
+ }
+ else
+ {
+ /* set command */
+ fc_en = _strtol(argv[2], NULL, 10);
+
+ ret = air_port_setFlowCtrl(0, port, dir, fc_en);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port%02d %s Flow Control %s\n", port, ((dir)?"RX":"TX"), ((fc_en)?"Enable":"Disable"));
+ else
+ AIR_PRINT("Set Flow Control Fail.\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doL2Set(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2SetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2Get(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2GetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2Clear(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2ClearCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2Del(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2DelCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2Add(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2AddCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2Cmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doAnMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ BOOL_T en = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get anCap <port> */
+ ret = air_port_getAnMode(0, port, &en);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Get Port%02d Auto-Negotiation %s\n", port, ((en)?"Enabled":"Disabled"));
+ else
+ AIR_PRINT("Get Port%02d Auto-Negotiation Fail.\n", port);
+ }
+ else if(2 == argc)
+ {
+ /* "port set anMode <port> <en> */
+ en = _strtol(argv[1], NULL, 10);
+ ret = air_port_setAnMode(0, port, en);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port%02d Auto-Negotiation Mode:%s\n", port, ((en)?"Enabled":"Disabled"));
+ else
+ AIR_PRINT("Set Port%02d Auto-Negotiation Fail.\n", port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLocalAdv(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ AIR_AN_ADV_T adv;
+
+ memset(&adv, 0, sizeof(AIR_AN_ADV_T));
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get localAdv <port> */
+ ret = air_port_getLocalAdvAbility(0, port, &adv);
+ AIR_PRINT("Get Port%02d Local Auto-Negotiation Advertisement: ", port);
+ if(AIR_E_OK != ret)
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else if(7 == argc)
+ {
+ /* port set localAdv <port> <10H> <10F> <100H> <100F> <1000F> <pause> */
+ adv.advCap10HDX = _strtol(argv[1], NULL, 0) & BIT(0);
+ adv.advCap10FDX = _strtol(argv[2], NULL, 0) & BIT(0);
+ adv.advCap100HDX = _strtol(argv[3], NULL, 0) & BIT(0);
+ adv.advCap100FDX = _strtol(argv[4], NULL, 0) & BIT(0);
+ adv.advCap1000FDX = _strtol(argv[5], NULL, 0) & BIT(0);
+ adv.advPause = _strtol(argv[6], NULL, 0) & BIT(0);
+ ret = air_port_setLocalAdvAbility(0, port, adv);
+ AIR_PRINT("Set Port%02d Local Auto-Negotiation Advertisement: ", port);
+ if(AIR_E_OK != ret)
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("\n");
+ AIR_PRINT("\tAdvertise 10BASE-T Half Duplex: %s\n", (adv.advCap10HDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 10BASE-T Full Duplex: %s\n", (adv.advCap10FDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 100BASE-T Half Duplex: %s\n", (adv.advCap100HDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 100BASE-T Full Duplex: %s\n", (adv.advCap100FDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 1000BASE-T Full Duplex: %s\n", (adv.advCap1000FDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise Asynchronous Pause: %s\n", (adv.advPause)?"Effective":"Not Effective" );
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doRemoteAdv(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ AIR_AN_ADV_T lp_adv;
+
+ memset(&lp_adv, 0, sizeof(AIR_AN_ADV_T));
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get remoteAdv <port> */
+ ret = air_port_getRemoteAdvAbility(0, port, &lp_adv);
+ AIR_PRINT("Get Port%02d Remote Auto-Negotiation Advertisement: ", port);
+ if(AIR_E_OK != ret)
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("\n");
+ AIR_PRINT("\tAdvertise 10BASE-T Half Duplex: %s\n", lp_adv.advCap10HDX?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 10BASE-T Full Duplex: %s\n", lp_adv.advCap10FDX?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 100BASE-T Half Duplex: %s\n", lp_adv.advCap100HDX?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 100BASE-T Full Duplex: %s\n", lp_adv.advCap100FDX?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise 1000BASE-T Full Duplex: %s\n", (lp_adv.advCap1000FDX)?"Effective":"Not Effective" );
+ AIR_PRINT("\tAdvertise Asynchronous Pause: %s\n", (lp_adv.advPause)?"Effective":"Not Effective" );
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortSpeed(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T speed = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get speed <port> */
+ ret = air_port_getSpeed(0, port, &speed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%02d Speed:", port);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d Speed Fail!\n", port);
+ }
+ }
+ else if(2 == argc)
+ {
+ /* port set speed <port> <speed> */
+ speed = _strtol(argv[1], NULL, 10);
+ ret = air_port_setSpeed(0, port, speed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port%02d Speed:", port);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d Speed Fail!\n", port);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ switch(speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ AIR_PRINT(" 10 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_100M:
+ AIR_PRINT(" 100 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_1000M:
+ AIR_PRINT(" 1 Gbps\n");
+ break;
+ case AIR_PORT_SPEED_2500M:
+ AIR_PRINT(" 2.5 Gbps\n");
+ break;
+ default:
+ AIR_PRINT(" Reserved\n");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortDuplex(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T duplex = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get duplex <port> */
+ ret = air_port_getDuplex(0, port, &duplex);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%02d Duplex:%s\n", port, duplex?"Full":"Half");
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d Duplex Fail!\n", port);
+ }
+ }
+ else if(2 == argc)
+ {
+ /* port set duplex <port> <duplex> */
+ duplex = _strtol(argv[1], NULL, 10);
+ ret = air_port_setDuplex(0, port, duplex);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port%02d Duplex:%s\n", port, duplex?"Full":"Half");
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d Duplex Fail!\n", port);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortStatus(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ AIR_PORT_STATUS_T ps;
+
+ memset(&ps, 0, sizeof(AIR_PORT_STATUS_T));
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get status <port> */
+ ret = air_port_getLink(0, port, &ps);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%02d Link-Status\n", port);
+ AIR_PRINT("\tLink: %s\n", ps.link?"Up":"Down");
+ AIR_PRINT("\tDuplex: %s\n", ps.duplex?"Full":"Half");
+ AIR_PRINT("\tSpeed: ");
+ switch(ps.speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ AIR_PRINT("10 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_100M:
+ AIR_PRINT("100 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_1000M:
+ AIR_PRINT("1 Gbps\n");
+ break;
+ case AIR_PORT_SPEED_2500M:
+ AIR_PRINT("2.5 Gbps\n");
+ break;
+ default:
+ AIR_PRINT("Reserved\n");
+ break;
+ }
+ }
+ else
+ AIR_PRINT("Get Port%02d Link-Status Fail!", port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortBckPres(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T bckPres = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get bckPres <port> */
+ ret = air_port_getBckPres(0, port, &bckPres);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Get Port%02d BckPres:%s\n", port, bckPres?"Enabled":"Disabled");
+ else
+ AIR_PRINT("Get Port%02d BckPres Fail!\n", port);
+ }
+ else if(2 == argc)
+ {
+ /* port set bckPres <port> <bckPres> */
+ bckPres = _strtol(argv[1], NULL, 10);
+ ret = air_port_setBckPres(0, port, bckPres);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port%02d BckPres:%s\n", port, bckPres?"Enabled":"Disabled");
+ else
+ AIR_PRINT("Set Port%02d BckPres Fail!\n", port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortPsMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T mode = 0;
+ BOOL_T ls_en = 0;
+ BOOL_T eee_en = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get psMode <port> */
+ ret = air_port_getPsMode(0, port, &mode);
+ AIR_PRINT("Get Port%02d Power-Saving: ", port);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Done\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else if(3 == argc)
+ {
+ /* port set psMode <port> <ls> <eee> */
+ ls_en = _strtol(argv[1], NULL, 0);
+ eee_en = _strtol(argv[2], NULL, 0);
+ if(TRUE == ls_en)
+ {
+ mode |= AIR_PORT_PS_LINKSTATUS;
+ }
+ if(TRUE == eee_en)
+ {
+ mode |= AIR_PORT_PS_EEE;
+ }
+ ret = air_port_setPsMode(0, port, mode);
+ AIR_PRINT("Set Port%02d Power-Saving: ", port);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Done\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("\tLink status:%s\n", (mode & AIR_PORT_PS_LINKSTATUS)?"Enable":"Disable");
+ AIR_PRINT("\tEEE:%s\n", (mode & AIR_PORT_PS_EEE)?"Enable":"Disable");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortSmtSpdDwn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T state = 0;
+ UI32_T retry = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get smtSpdDwn <port> */
+ ret = air_port_getSmtSpdDwn(0, port, &state, &retry);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%02d Smart Speed Down: %s\n", port, state?"Enabled":"Disabled");
+ AIR_PRINT("Get Port%02d Retry Time: %d\n", port, retry + 2);
+ }
+ else
+ AIR_PRINT("Get Port%02d Smart-SpeedDown Fail!\n", port);
+ }
+ else if(3 == argc)
+ {
+ /* port set smtSpdDwn <port> <en> <retry> */
+ state = _strtol(argv[1], NULL, 10);
+ retry = _strtol(argv[2], NULL, 10);
+ if(retry >= 2)
+ {
+ ret = air_port_setSmtSpdDwn(0, port, state, retry - 2);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port%02d Smart Speed Down: %s\n", port, state?"Enabled":"Disabled");
+ AIR_PRINT("Set Port%02d Retry Time: %d\n", port, retry);
+ }
+ else
+ AIR_PRINT("Set Port%02d Smart-SpeedDown Fail!\n", port);
+ }
+ else
+ {
+ ret = AIR_E_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortSpTag(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ BOOL_T sptag_en = FALSE;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get spTag <port> */
+ ret = air_port_getSpTag(0, port, &sptag_en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get Port%02d Special Tag %s\n", port, ((sptag_en)?"Enabled":"Disabled"));
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d Special Tag Fail.\n", port);
+ }
+ }
+ else if(2 == argc)
+ {
+ /* port set spTag <port> <en> */
+ sptag_en = _strtol(argv[1], NULL, 10);
+ ret = air_port_setSpTag(0, port, sptag_en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d Special Tag:%s\n", port, ((sptag_en)?"Enabled":"Disabled"));
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d Special Tag Fail.\n", port);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortEnable(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T state = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+
+ if(1 == argc)
+ {
+ /* port get enable <port> */
+ ret = air_port_getEnable(0, port, &state);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Get Port%02d State:%s\n", port, state?"Enable":"Disable");
+ else
+ AIR_PRINT("Get Port%02d State Fail!\n", port);
+ }
+ else if(2 == argc)
+ {
+ /* port set enable <port> <en> */
+ state = _strtol(argv[1], NULL, 10);
+ ret = air_port_setEnable(0, port, state);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port%02d State:%s\n", port, state?"Enable":"Disable");
+ else
+ AIR_PRINT("Set Port%02d State Fail!\n", port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPort5GBaseRMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ if(0 == argc)
+ {
+ /* port set 5GBaseRMode */
+ ret = air_port_set5GBaseRModeEn(0);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port05 Mode: 5GBase-R\n");
+ else
+ AIR_PRINT("Set Port05 HSGMII Mode Fail.\n");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortHsgmiiMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ if(0 == argc)
+ {
+ /* port set hsgmiiMode */
+ ret = air_port_setHsgmiiModeEn(0);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port05 Mode: HSGMII\n");
+ else
+ AIR_PRINT("Set Port05 HSGMII Mode Fail.\n");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortSgmiiMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T mode = 0;
+ UI32_T speed = 0;
+
+ if(2 == argc)
+ {
+ /* port set sgmiiMode <mode(0:AN,1:Force)> <speed> */
+ mode = _strtol(argv[0], NULL, 10);
+ speed = _strtol(argv[1], NULL, 10);
+ ret = air_port_setSgmiiMode(0, mode, speed);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Set Port05 SGMII Mode:%s\nIf in Force Mode, speed:", mode?"Force":"AN");
+ else
+ AIR_PRINT("Set Port05 SGMII Mode Fail.\n");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ switch(speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ AIR_PRINT(" 10 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_100M:
+ AIR_PRINT(" 100 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_1000M:
+ AIR_PRINT(" 1 Gbps\n");
+ break;
+ default:
+ AIR_PRINT(" Reserved\n");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortRmiiMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T speed = 0;
+
+ if(1 == argc)
+ {
+ /* port set rmiiMode <speed> */
+ speed = _strtol(argv[0], NULL, 10);
+ ret = air_port_setRmiiMode(0, speed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port05 RMII Mode Speed:");
+ }
+ else
+ {
+ AIR_PRINT("Set Port05 RMII Mode Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ switch(speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ AIR_PRINT(" 10 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_100M:
+ AIR_PRINT(" 100 Mbps\n");
+ break;
+ default:
+ AIR_PRINT(" Reserved\n");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doPortRgmiiMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T speed = 0;
+
+ if(1 == argc)
+ {
+ /* port set rgmiiMode <speed> */
+ speed = _strtol(argv[0], NULL, 10);
+ ret = air_port_setRgmiiMode(0, speed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port05 RGMII Mode Speed:");
+ }
+ else
+ {
+ AIR_PRINT("Set Port05 RGMII Mode Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ switch(speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ AIR_PRINT(" 10 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_100M:
+ AIR_PRINT(" 100 Mbps\n");
+ break;
+ case AIR_PORT_SPEED_1000M:
+ AIR_PRINT(" 1 Gbps\n");
+ break;
+ default:
+ AIR_PRINT(" Reserved\n");
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSptagEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ BOOL_T sp_en = FALSE;
+
+ port = _strtol(argv[0], NULL, 10);
+ if (2 == argc)
+ {
+ sp_en = _strtol(argv[1], NULL, 10);
+ ret = air_sptag_setState(0,port,sp_en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("set port %d SpTag state %s sucess\n", port,sp_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("set port %d SpTag state %s fail\n", port,sp_en?"Enable":"Disable");
+ }
+ }
+ else if(1 == argc)
+ {
+ air_sptag_getState(0,port,&sp_en);
+ AIR_PRINT("get port %d SpTag state: %s \n", port,sp_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSptagMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ BOOL_T sp_mode = FALSE;
+
+
+ port = _strtol(argv[0], NULL, 10);
+ if (2 == argc)
+ {
+ sp_mode = _strtol(argv[1], NULL, 10);
+ ret = air_sptag_setMode(0,port,sp_mode);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("set port %d SpTag Mode %s sucess\n", port,sp_mode?"replace":"insert");
+ }
+ else
+ {
+ AIR_PRINT("set port %d SpTag state %s fail\n", port,sp_mode?"replace":"insert");
+ }
+ }
+ else if(1 == argc)
+ {
+ air_sptag_getMode(0,port,&sp_mode);
+ AIR_PRINT("get port %d SpTag state: %s \n", port,sp_mode?"replace":"insert");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSptagDecode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_SPTAG_RX_PARA_T sptag_rx = {0};
+ UI8_T buf[AIR_STAG_BUF_LEN] = {0};
+ UI32_T len = AIR_STAG_BUF_LEN, i = 0;
+
+ if (4 == argc)
+ {
+ for(i = 0; i < len; i++)
+ {
+ buf[i] = _strtoul(argv[i], NULL, 16);
+ }
+
+ ret = air_sptag_decodeRx(0, buf, len, &sptag_rx);
+ if (AIR_E_OK != ret)
+ {
+ AIR_PRINT("SpTag decode fail\n");
+ return ret;
+ }
+
+ AIR_PRINT("SpTag decode success:\n");
+ AIR_PRINT("RSN : %s\n", _sptag_pt[sptag_rx.rsn]);
+ AIR_PRINT("VPM : %s\n", _sptag_vpm[sptag_rx.vpm]);
+ AIR_PRINT("SPN : %d\n", sptag_rx.spn);
+ AIR_PRINT("PRI : %d\n", sptag_rx.pri);
+ AIR_PRINT("CFI : %d\n", sptag_rx.cfi);
+ AIR_PRINT("VID : %d\n", sptag_rx.vid);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSptagEncode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_STAG_TX_PARA_T sptag_tx = {0};
+ UI8_T buf[AIR_STAG_BUF_LEN] = {0};
+ UI32_T len = AIR_STAG_BUF_LEN;
+ char str[128] = {'\0'};
+ UI32_T data = 0;
+ AIR_STAG_MODE_T mode = AIR_STAG_MODE_LAST;
+
+ if (7 == argc)
+ {
+ if(_strcmp(argv[0],"mode=replace") == 0)
+ mode = AIR_STAG_MODE_REPLACE;
+ else if(_strcmp(argv[0],"mode=insert") == 0)
+ mode = AIR_STAG_MODE_INSERT;
+ else
+ printf("mode is wrong!!");
+
+ if(_strcmp(argv[1],"opc=portmap") == 0)
+ sptag_tx.opc = AIR_STAG_OPC_PORTMAP;
+ else if(_strcmp(argv[1],"opc=portid") == 0)
+ sptag_tx.opc = AIR_STAG_OPC_PORTID;
+ else if(_strcmp(argv[1],"opc=lookup") == 0)
+ sptag_tx.opc = AIR_STAG_OPC_LOOKUP;
+ else
+ printf("opc is wrong!!");
+
+ if(sscanf(argv[2],"dp=%x",&data) != -1)
+ {
+ sptag_tx.pbm = data;
+ AIR_PRINT("sptag_tx.pbm %x\n",sptag_tx.pbm);
+ }
+
+ if(_strcmp(argv[3],"vpm=untagged") == 0)
+ sptag_tx.vpm = AIR_STAG_VPM_UNTAG;
+ else if(_strcmp(argv[3],"vpm=8100") == 0)
+ sptag_tx.vpm = AIR_STAG_VPM_TPID_8100;
+ else if(_strcmp(argv[3],"vpm=88a8") == 0)
+ sptag_tx.vpm = AIR_STAG_VPM_TPID_88A8;
+ else
+ printf("vpm is wrong!!");
+
+ if(sscanf(argv[4],"pri=%d",&data) != -1)
+ {
+ sptag_tx.pri = data;
+ AIR_PRINT("sptag_tx.pri %d\n",sptag_tx.pri);
+ }
+
+ if(sscanf(argv[5],"cfi=%d",&data) != -1)
+ {
+ sptag_tx.cfi = data;
+ AIR_PRINT("sptag_tx.cfi %d\n",sptag_tx.cfi);
+ }
+
+ if(sscanf(argv[6],"vid=%d",&data) != -1)
+ {
+ sptag_tx.vid = data;
+ AIR_PRINT("sptag_tx.vid %d\n",sptag_tx.vid);
+ }
+
+ ret = air_sptag_encodeTx(0,mode, &sptag_tx, (UI8_T *)&buf, &len);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("SpTag encode sucess, returned len=%d\n", len);
+ AIR_PRINT("Encoded SpTag: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
+ }
+ else
+ {
+ AIR_PRINT("SpTag encode fail\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSptag(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(sptagCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doL2Dump(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(l2DumpCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMacAddr(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_MAC_ENTRY_T mt;
+ UI32_T fwd = 0;
+
+ memset(&mt, 0, sizeof(AIR_MAC_ENTRY_T));
+
+ if(0 == argc)
+ {
+ /* l2 clear mac */
+ ret = air_l2_clearMacAddr(0);
+ if(ret == AIR_E_OK)
+ AIR_PRINT("Clear MAC Address Table Done.\n");
+ else
+ AIR_PRINT("Clear MAC Address Table Fail.\n");
+ }
+ else if(3 == argc)
+ {
+ /* l2 del mac <mac(12'hex)> { vid <vid(0..4095)> | fid <fid(0..15)> } */
+ ret = _str2mac(argv[0], (C8_T *)mt.mac);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+
+ /* check argument 1 */
+ if(FALSE == _strcmp(argv[1], "vid"))
+ {
+ /* get mac entry by MAC address & vid */
+ mt.cvid = _strtoul(argv[2], NULL, 0);
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ AIR_PRINT("Get MAC Address:" MAC_STR " with vid:%u", MAC2STR(mt.mac), mt.cvid);
+ }
+ else if(FALSE == _strcmp(argv[1], "fid"))
+ {
+ /* get mac entry by MAC address & fid */
+ mt.fid = _strtoul(argv[2], NULL, 0);
+ AIR_PRINT("Get MAC Address:" MAC_STR " with fid:%u", MAC2STR(mt.mac), mt.fid);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ ret = air_l2_delMacAddr(0, &mt);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(" Done.\n");
+ }
+ else
+ AIR_PRINT("\n Fail!\n");
+ }
+ else if(7 == argc)
+ {
+ /* l2 add mac <static(0:dynamic,1:static)> <unauth(0:auth,1:unauth)> <mac(12'hex)> <portlist(uintlist)> [ vid <vid(0..4095)> | fid <fid(0..15)> ] <src_mac_forward=(0:default,1:cpu-include,2:cpu-exclude,3:cpu-only,4:drop)> */
+ if(argv[0])
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_STATIC;
+
+ if(argv[1])
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_UNAUTH;
+
+ ret = _str2mac(argv[2], (C8_T *)mt.mac);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+
+ ret = _portListStr2Ary(argv[3], mt.port_bitmap, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+
+ /* check argument fid or vid */
+ if(FALSE == _strcmp(argv[4], "vid"))
+ {
+ /* get mac entry by MAC address & vid */
+ mt.cvid = _strtoul(argv[5], NULL, 0);
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ }
+ else if(FALSE == _strcmp(argv[4], "fid"))
+ {
+ /* get mac entry by MAC address & fid */
+ mt.fid = _strtoul(argv[5], NULL, 0);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ fwd = _strtoul(argv[6], NULL, 0);
+ if(0 == fwd)
+ mt.sa_fwd = AIR_L2_FWD_CTRL_DEFAULT;
+ else if(1 == fwd)
+ mt.sa_fwd = AIR_L2_FWD_CTRL_CPU_INCLUDE;
+ else if(2 == fwd)
+ mt.sa_fwd = AIR_L2_FWD_CTRL_CPU_EXCLUDE;
+ else if(3 == fwd)
+ mt.sa_fwd = AIR_L2_FWD_CTRL_CPU_ONLY;
+ else if(4 == fwd)
+ mt.sa_fwd = AIR_L2_FWD_CTRL_DROP;
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ ret = air_l2_addMacAddr(0, &mt);
+ AIR_PRINT("Add MAC Address:" MAC_STR, MAC2STR(mt.mac));
+ if(ret == AIR_E_OK)
+ AIR_PRINT(" Done.\n");
+ else
+ AIR_PRINT(" Fail.\n");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+_printMacEntry(
+ AIR_MAC_ENTRY_T *mt,
+ UI32_T age_unit,
+ UI8_T count,
+ UI8_T title)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ I32_T i = 0, j = 0;
+ UI8_T first = 0;
+ UI8_T find = 0;
+ if(title)
+ {
+ AIR_PRINT("%-6s%-15s%-5s%-5s%-5s%-10s%-10s%-6s\n",
+ "unit",
+ "mac",
+ "ivl",
+ "vid",
+ "fid",
+ "age-time",
+ "forward",
+ "port");
+ return ret;
+ }
+ for(i = 0; i < count; i++)
+ {
+ AIR_PRINT("%-6d", age_unit);
+ AIR_PRINT(MAC_STR, MAC2STR(mt[i].mac));
+ AIR_PRINT("...");
+ if(mt[i].flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ AIR_PRINT("%-3s..", "ivl");
+ AIR_PRINT("%-5d", mt[i].cvid);
+ AIR_PRINT("%-5s", ".....");
+ }
+ else
+ {
+ AIR_PRINT("%-3s..", "svl");
+ AIR_PRINT("%-5s", ".....");
+ AIR_PRINT("%-5d", mt[i].fid);
+ }
+ if(mt[i].flags & AIR_L2_MAC_ENTRY_FLAGS_STATIC)
+ {
+ AIR_PRINT("%-10s.", "static");
+ }
+ else
+ {
+ AIR_PRINT("%d sec..", mt[i].timer);
+ }
+ AIR_PRINT("%-10s", _air_mac_address_forward_control_string[mt[i].sa_fwd]);
+ first = 0;
+ find = 0;
+ for (j = (AIR_MAX_NUM_OF_PORTS - 1); j >= 0; j--)
+ {
+ if((mt[i].port_bitmap[0]) & (1 << j))
+ {
+ first = j;
+ find = 1;
+ break;
+ }
+ }
+ if(find)
+ {
+ for (j = 0; j < AIR_MAX_NUM_OF_PORTS; j++)
+ {
+ if((mt[i].port_bitmap[0]) & (1 << j))
+ {
+ if(j == first)
+ AIR_PRINT("%-2d", j);
+ else
+ AIR_PRINT("%-2d,", j);
+ }
+ }
+ }
+ else
+ AIR_PRINT("no dst port");
+ AIR_PRINT("\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doGetMacAddr(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI8_T count = 0;
+ AIR_MAC_ENTRY_T * ptr_mt;
+
+ if(3 == argc)
+ {
+ ptr_mt = AIR_MALLOC(sizeof(AIR_MAC_ENTRY_T));
+ if (NULL == ptr_mt)
+ {
+ AIR_PRINT("***Error***, allocate memory fail\n");
+ return AIR_E_OTHERS;
+ }
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ /* l2 get mac <mac(12'hex)> { vid <vid(0..4095)> | fid <fid(0..15)> } */
+ ret = _str2mac(argv[0], (C8_T *)ptr_mt->mac);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ AIR_FREE(ptr_mt);
+ return ret;
+ }
+
+ /* check argument 1 */
+ if(FALSE == _strcmp(argv[1], "vid"))
+ {
+ /* get mac entry by MAC address & vid */
+ ptr_mt->cvid = _strtoul(argv[2], NULL, 0);
+ ptr_mt->flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ AIR_PRINT("Get MAC Address:" MAC_STR " with vid:%u", MAC2STR(ptr_mt->mac), ptr_mt->cvid);
+ }
+ else if(FALSE == _strcmp(argv[1], "fid"))
+ {
+ /* get mac entry by MAC address & fid */
+ ptr_mt->fid = _strtoul(argv[2], NULL, 0);
+ AIR_PRINT("Get MAC Address:" MAC_STR " with fid:%u", MAC2STR(ptr_mt->mac), ptr_mt->fid);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ AIR_FREE(ptr_mt);
+ return AIR_E_BAD_PARAMETER;
+ }
+ ret = air_l2_getMacAddr(0, &count, ptr_mt);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(" Done.\n");
+ _printMacEntry(ptr_mt, 0, 1, TRUE);
+ _printMacEntry(ptr_mt, 0, 1, FALSE);
+ }
+ else
+ AIR_PRINT("\n Not found!\n");
+ AIR_FREE(ptr_mt);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doMacAddrAgeOut(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T time = 0;
+ if(0 == argc)
+ {
+ /* l2 get macAddrAgeOut */
+ ret = air_l2_getMacAddrAgeOut(0, &time);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get MAC Address Age Out Time Done.\n");
+ }
+ else
+ {
+ AIR_PRINT("Get MAC Address Age Out Time Fail.\n");
+ }
+ }
+ else if(1 == argc)
+ {
+ /* l2 set macAddrAgeOut <time(1, 1000000)> */
+ time = _strtoul(argv[0], NULL, 0);
+ if(time < 1 || time > 1000000)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ ret = air_l2_setMacAddrAgeOut(0, time);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set MAC Address Age Out Time Done.\n");
+ }
+ else
+ {
+ AIR_PRINT("Set MAC Address Age Out Time Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("MAC Address Age Out Time: %u seconds.\n", time);
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doDumpMacAddr(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_MAC_ENTRY_T *ptr_mt;
+ UI8_T count = 0;
+ UI32_T bucket_size = 0;
+ UI32_T total_count = 0;
+
+ if(0 != argc)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ /* get unit of aging time */
+ ret = air_l2_getMacBucketSize(0, &bucket_size);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Get MAC Age Time Fail!\n");
+ return ret;
+ }
+ ptr_mt = AIR_MALLOC(sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ if (NULL == ptr_mt)
+ {
+ AIR_PRINT("***Error***, allocate memory fail\n");
+ return AIR_E_OTHERS;
+ }
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ _printMacEntry(ptr_mt, 0, count, TRUE);
+ /* get 1st entry of MAC table */
+ ret = air_l2_getMacAddr(0, &count, ptr_mt);
+ switch(ret)
+ {
+ case AIR_E_ENTRY_NOT_FOUND:
+ AIR_FREE(ptr_mt);
+ AIR_PRINT("Not Found!\n");
+ return ret;
+ case AIR_E_TIMEOUT:
+ AIR_FREE(ptr_mt);
+ AIR_PRINT("Time Out!\n");
+ return ret;
+ case AIR_E_BAD_PARAMETER:
+ AIR_FREE(ptr_mt);
+ AIR_PRINT("Bad Parameter!\n");
+ return ret;
+ default:
+ break;
+ }
+ total_count += count;
+ _printMacEntry(ptr_mt, 0, count, FALSE);
+
+ /* get other entries of MAC table */
+ while(1)
+ {
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ ret = air_l2_getNextMacAddr(0, &count, ptr_mt);
+ if(AIR_E_OK != ret)
+ {
+ break;
+ }
+ total_count += count;
+ _printMacEntry(ptr_mt, 0, count, FALSE);
+ }
+ switch(ret)
+ {
+ case AIR_E_TIMEOUT:
+ AIR_PRINT("Time Out!\n");
+ break;
+ case AIR_E_BAD_PARAMETER:
+ AIR_PRINT("Bad Parameter!\n");
+ break;
+ default:
+ AIR_PRINT("Found %u %s\n", total_count, (total_count>1)?"entries":"entry");
+ break;
+ }
+ AIR_FREE(ptr_mt);
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLagMember(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T portrunk_index = 0, member_index = 0, member_enable = 0, port_index = 0, i = 0;
+ AIR_LAG_PTGINFO_T member;
+ memset(&member,0,sizeof(AIR_LAG_PTGINFO_T));
+
+ if(4 == argc)
+ {
+ /* lag set member <port trunk index> <member index> <member enable> <port_index>*/
+ portrunk_index = _strtol(argv[0], NULL, 10);
+ member_index = _strtol(argv[1], NULL, 10);
+ member_enable = _strtol(argv[2], NULL, 10);
+ port_index = _strtol(argv[3], NULL, 10);
+ ret = air_lag_setMember(0, portrunk_index, member_index, member_enable,port_index);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set port trunk index %d member_index:%d member_enable:%d, port_index:%d ok.\n", portrunk_index, member_index, member_enable,port_index);
+ }
+ else
+ {
+ AIR_PRINT("Set port trunk index %d member_index:%d member_enable:%d, port_index:%d fail.\n", portrunk_index, member_index, member_enable,port_index);
+ }
+ memset(&member,0,sizeof(member));
+ air_lag_getMember(0, portrunk_index, &member);
+ if(! member.csr_gp_enable[0])
+ {
+ AIR_PRINT("\r\n!!!!!!!!!Port trunk index %d member_index:0 must be set,or else have taffic issues.\n", portrunk_index);
+ }
+ }
+ else if(1 == argc)
+ {
+ portrunk_index = _strtol(argv[0], NULL, 10);
+
+ /* lag get member <port> */
+ memset(&member,0,sizeof(member));
+ ret = air_lag_getMember(0, portrunk_index, &member);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get port trunk %u member:\n", portrunk_index);
+ for(i = 0; i < AIR_LAG_MAX_MEM_NUM; i++)
+ {
+ if(member.csr_gp_enable[i])
+ AIR_PRINT("port %d \r\n", member.csr_gp_port[i]);
+ }
+ AIR_PRINT("\r\n");
+ }
+ else
+ {
+ AIR_PRINT("Get port trunk:%u Member Fail.\n", portrunk_index);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+
+static AIR_ERROR_NO_T
+doLagDstInfo(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_LAG_DISTINFO_T dstInfo;
+
+ memset(&dstInfo, 0, sizeof(AIR_LAG_DISTINFO_T));
+ if(7 == argc)
+ {
+ /* lag set dstInfo <sp> <sa> <da> <sip> <dip> <sport> <dport> */
+ dstInfo.sp = _strtol(argv[0], NULL, 10) & BIT(0);
+ dstInfo.sa = _strtol(argv[1], NULL, 10) & BIT(0);
+ dstInfo.da = _strtol(argv[2], NULL, 10) & BIT(0);
+ dstInfo.sip = _strtol(argv[3], NULL, 10) & BIT(0);
+ dstInfo.dip = _strtol(argv[4], NULL, 10) & BIT(0);
+ dstInfo.sport = _strtol(argv[5], NULL, 10) & BIT(0);
+ dstInfo.dport = _strtol(argv[6], NULL, 10) & BIT(0);
+ ret = air_lag_setDstInfo(0, dstInfo);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set LAG packet distrubution.\n");
+ }
+ else
+ {
+ AIR_PRINT("Set LAG packet distrubution Fail.\n");
+ }
+ }
+ else if(0 == argc)
+ {
+ /* lag get dstInfo */
+ ret = air_lag_getDstInfo(0, &dstInfo);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get LAG packet distrubution:\n");
+ }
+ else
+ {
+ AIR_PRINT("Get LAG packet distrubution Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("%-5s|%-5s|%-5s|%-5s|%-5s|%-5s|%-5s\n",
+ "SP", "SA", "DA", "SIP", "DIP", "SPORT", "DPORT");
+ AIR_PRINT("%-5s|%-5s|%-5s|%-5s|%-5s|%-5s|%-5s\n",
+ (dstInfo.sp)?"En":"Dis",
+ (dstInfo.sa)?"En":"Dis",
+ (dstInfo.da)?"En":"Dis",
+ (dstInfo.sip)?"En":"Dis",
+ (dstInfo.dip)?"En":"Dis",
+ (dstInfo.sport)?"En":"Dis",
+ (dstInfo.dport)?"En":"Dis");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLagHashtype(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T hashtype = 0;
+
+ if(1 == argc)
+ {
+ hashtype = _strtol(argv[0], NULL, 10);
+ ret = air_lag_sethashtype(0, hashtype);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set LAG hashtype Ok.\n");
+ }
+ else
+ {
+ AIR_PRINT("Set LAG hashtype Fail.\n");
+ }
+ }
+ else if(0 == argc)
+ {
+ /* lag get dstInfo */
+ ret = air_lag_gethashtype(0, &hashtype);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get LAG hashtype:\n");
+ }
+ else
+ {
+ AIR_PRINT("Get LLAG hashtype Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+ if(ret == AIR_E_OK)
+ {
+ switch (hashtype)
+ {
+ case 0:
+ AIR_PRINT("hashtype:crc32lsb.\n");
+ break;
+ case 1:
+ AIR_PRINT("hashtype:crc32msb.\n");
+ break;
+ case 2:
+ AIR_PRINT("hashtype:crc16.\n");
+ break;
+ case 3:
+ AIR_PRINT("hashtype:xor4.\n");
+ break;
+ default:
+ AIR_PRINT("wrong hashtype:%d.\n",hashtype);
+ }
+
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLagPtseed(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T ptseed = 0;
+
+ if(1 == argc)
+ {
+ ptseed = _strtol(argv[0], NULL, 16);
+ ret = air_lag_setPTSeed(0, ptseed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set LAG Port Seed:%x(hex) ok\n",ptseed);
+ }
+ else
+ {
+ AIR_PRINT("Set LAG Port Seed:%x(hex) fail\n",ptseed);
+ }
+ }
+ else if(0 == argc)
+ {
+ /* lag get seed */
+ ret = air_lag_getPTSeed(0, &ptseed);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get port trunk seed: %x(hex)\n",ptseed);
+ }
+ else
+ {
+ AIR_PRINT("Get port trunk seed Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLagSpsel(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T state = 0;
+
+ if(1 == argc)
+ {
+ /* lag set spsel <state> */
+ state = _strtol(argv[0], NULL, 10);
+ ret = air_lag_setSpSel(0,state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set source port compare function:%s.\n", (state)?"Enabled":"Disabled");
+ }
+ else
+ {
+ AIR_PRINT("Set source port compare function Fail.\n");
+ }
+ }
+ else if(0 == argc)
+ {
+ /* lag get spsel*/
+ ret = air_lag_getSpSel(0, &state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get source port compare function:%s.\n", (state)?"Enabled":"Disabled");
+ }
+ else
+ {
+ AIR_PRINT("Get source port compare function Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+
+static AIR_ERROR_NO_T
+doLagState(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T state = 0;
+
+ if(1 == argc)
+ {
+ /* lag set state <state> */
+ state = _strtol(argv[0], NULL, 10);
+ ret = air_lag_set_ptgc_state(0,state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set LAG Port Trunk State:%s.\n", (state)?"Enabled":"Disabled");
+ }
+ else
+ {
+ AIR_PRINT("Set LAG Port Trunk State Fail.\n");
+ }
+ }
+ else if(0 == argc)
+ {
+ /* lag get state*/
+ ret = air_lag_get_ptgc_state(0, &state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get LAG Port Trunk State:%s.\n", (state)?"Enabled":"Disabled");
+ }
+ else
+ {
+ AIR_PRINT("Get LAG Port Trunk State Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLagGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(lagGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doLagSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(lagSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doLag(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(lagCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doStpPortstate(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T fid = 0;
+ UI32_T state = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+ fid = _strtol(argv[1], NULL, 10);
+ if(3 == argc)
+ {
+ /* stp set portstate <port> <fid(0..15)> <state> */
+ state = _strtol(argv[2], NULL, 10);
+ ret = air_stp_setPortstate(0, port, fid, state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set STP Port:%u FID:%u State:", port, fid);
+ switch(state)
+ {
+ case AIR_STP_STATE_DISABLE:
+ AIR_PRINT("Disable(STP) / Discard(RSTP).\n");
+ break;
+ case AIR_STP_STATE_LISTEN:
+ AIR_PRINT("Listening(STP) / Discard(RSTP).\n");
+ break;
+ case AIR_STP_STATE_LEARN:
+ AIR_PRINT("Learning(STP) / Learning(RSTP).\n");
+ break;
+ case AIR_STP_STATE_FORWARD:
+ AIR_PRINT("Forwarding(STP) / Forwarding(RSTP).\n");
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Set STP Port:%u FID:%u State Fail.", port, fid);
+ }
+ }
+ else if(2 == argc)
+ {
+ /* stp get portstate <port> <fid(0..15)> */
+ ret = air_stp_getPortstate(0, port, fid, &state);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get STP Port:%u FID:%u State:", port, fid);
+ switch(state)
+ {
+ case AIR_STP_STATE_DISABLE:
+ AIR_PRINT("Disable(STP) / Discard(RSTP).\n");
+ break;
+ case AIR_STP_STATE_LISTEN:
+ AIR_PRINT("Listening(STP) / Discard(RSTP).\n");
+ break;
+ case AIR_STP_STATE_LEARN:
+ AIR_PRINT("Learning(STP) / Learning(RSTP).\n");
+ break;
+ case AIR_STP_STATE_FORWARD:
+ AIR_PRINT("Forwarding(STP) / Forwarding(RSTP).\n");
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Get STP Port:%u FID:%u State Fail.", port, fid);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doStpGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(stpGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doStpSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(stpSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doStp(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(stpCmds, argc, argv);
+}
+
+static void
+_mir_printPortList(UI32_T * mt)
+{
+ I8_T j = 0;
+ UI8_T first = 0;
+ UI8_T find = 0;
+ for(j = (AIR_MAX_NUM_OF_PORTS - 1); j >= 0; j--)
+ {
+ if((*mt) & (1 << j))
+ {
+ first = j;
+ find = 1;
+ break;
+ }
+ }
+ if(find)
+ {
+ for(j = 0; j < AIR_MAX_NUM_OF_PORTS; j++)
+ {
+ if((*mt) & (1 << j))
+ {
+ if(j == first)
+ AIR_PRINT("%-2d", j);
+ else
+ AIR_PRINT("%-2d,", j);
+ }
+ }
+ }
+ else
+ AIR_PRINT("NULL");
+ AIR_PRINT("\n");
+}
+
+static void
+_mir_printSrcPortList(
+ const UI32_T unit,
+ const UI32_T sessionid)
+{
+
+ I8_T i = 0;
+ AIR_MIR_SESSION_T session;
+ AIR_PORT_BITMAP_T txPbm = {0}, rxPbm = {0};
+
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ memset(&session, 0, sizeof(session));
+ session.src_port = i;
+ air_mir_getMirrorPort(unit, sessionid, &session);
+
+ if(session.flags & AIR_MIR_SESSION_FLAGS_DIR_TX)
+ {
+ txPbm[0] |= (1 << i);
+ }
+ if(session.flags & AIR_MIR_SESSION_FLAGS_DIR_RX)
+ {
+ rxPbm[0] |= (1 << i);
+ }
+ }
+ AIR_PRINT("Src PortList\n");
+ AIR_PRINT(" - Rx portlist = ");
+ _mir_printPortList(rxPbm);
+ AIR_PRINT(" - Tx portlist = ");
+ _mir_printPortList(txPbm);
+}
+
+static void
+_mir_printSession(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const AIR_MIR_SESSION_T *ptr_session)
+{
+
+ AIR_PRINT("Session id: %d\n", session_id);
+ AIR_PRINT("State: %s \n", (ptr_session->flags & AIR_MIR_SESSION_FLAGS_ENABLE)? "enable": "disable");
+ AIR_PRINT("Tx tag: %s \n", (ptr_session->flags & AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG)? "On": "Off");
+ AIR_PRINT("Dst port: %d \n", ptr_session->dst_port);
+ _mir_printSrcPortList(unit,session_id);
+}
+
+static AIR_ERROR_NO_T
+doMirrorGetSid(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ AIR_MIR_SESSION_T session = {0};
+ I8_T i = 0;
+
+ session_id = _strtoul(argv[0], NULL, 0);
+ rc = air_mir_getSession(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***, get mirror session fail\n");
+ return rc;
+ }
+ /* print session information */
+ if(session.dst_port == AIR_PORT_INVALID)
+ {
+ AIR_PRINT("Session id %d not found\n", session_id);
+ }
+ else
+ {
+ _mir_printSession(0, session_id, &session);
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doMirrorDelSid(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ AIR_MIR_SESSION_T session = {0};
+ UI8_T i = 0;
+
+ session_id = _strtoul(argv[0], NULL, 0);
+ rc = air_mir_delSession(0, session_id);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***, del mirror session fail\n");
+ return rc;
+ }
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ session.src_port = i;
+ rc = air_mir_setMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,port=%u error\n", i);
+ return rc;
+ }
+ }
+ if (rc != AIR_E_OK)
+ {
+ AIR_PRINT("***Error***, delete mirror session fail\n");
+ }
+ else
+ AIR_PRINT("***OK***, delete mirror session success\n");
+
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doMirrorAddRlist(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ AIR_MIR_SESSION_T session = {0};
+ AIR_PORT_BITMAP_T rxPbm = {0};
+ UI8_T i = 0;
+
+ /*mirror add session-rlist <sid(0..3)> <list(UINTLIST)>*/
+ session_id = _strtoul(argv[0], NULL, 0);
+ rc = _portListStr2Ary(argv[1], rxPbm, 1);
+ if(rc != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return rc;
+ }
+ if(!rxPbm[0])
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+ session.src_port = i;
+ rc = air_mir_getMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,get port=%u error\n", i);
+ return rc;
+ }
+
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_RX;
+ session.src_port = i;
+ rc = air_mir_setMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,set rx port=%u error\n", i);
+ return rc;
+ }
+ }
+ }
+ else
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(rxPbm[0] & (1 << i))
+ {
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+ session.src_port = i;
+ rc = air_mir_getMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,get port=%u error\n", i);
+ return rc;
+ }
+
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ session.src_port = i;
+ rc = air_mir_setMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,port=%u error\n", i);
+ return rc;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doMirrorAddTlist(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ AIR_MIR_SESSION_T session = {0};
+ AIR_PORT_BITMAP_T txPbm = {0};
+ UI8_T i = 0;
+
+ /*mirror add session-tlist <sid(0..3)> <list(UINTLIST)>*/
+ session_id = _strtoul(argv[0], NULL, 0);
+ rc = _portListStr2Ary(argv[1], txPbm, 1);
+ if(rc != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return rc;
+ }
+ if(!txPbm[0])
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+ session.src_port = i;
+ rc = air_mir_getMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,get port=%u error\n", i);
+ return rc;
+ }
+
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_TX;
+ session.src_port = i;
+ rc = air_mir_setMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,set rx port=%u error\n", i);
+ return rc;
+ }
+ }
+ }
+ else
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(txPbm[0] & (1 << i))
+ {
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+ session.src_port = i;
+ rc = air_mir_getMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,get port=%u error\n", i);
+ return rc;
+ }
+
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ session.src_port = i;
+ rc = air_mir_setMirrorPort(0, session_id, &session);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("***Error***,port=%u error\n", i);
+ return rc;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doMirrorSetSessionEnable(
+ UI32_T argc,
+ C8_T *argv[])
+
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ UI32_T enable = 0;
+ BOOL_T tmp_en = FALSE;
+
+ /*mirror set session-enable <sid(0..3)> <state(1:En,0:Dis)>*/
+ session_id = _strtoul(argv[0], NULL, 0);
+ enable = _strtoul(argv[1], NULL, 0);
+ if(enable)
+ tmp_en = TRUE;
+ /* set port mirror state */
+ rc = air_mir_setSessionAdminMode(0, session_id, tmp_en);
+ if(AIR_E_OK!=rc)
+ {
+ AIR_PRINT("***Error***\n");
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doMirrorSetSession(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T session_id = 0;
+ UI32_T dst_port = 0;
+ UI8_T enable = 0;
+ UI8_T tag_en = 0;
+ UI8_T dir = 0;
+ AIR_MIR_SESSION_T session = {0};
+ AIR_PORT_BITMAP_T rxPbm = {0};
+ I8_T i = 0;
+
+ /*mirror set session <sid(0..3)> <dst_port(UINT)> <state(1:En,0:Dis)> <tag(1:on, 0:off)> <list(UINTLIST)> <dir(0:none,1:tx,2:rx,3:both)>*/
+ session_id = _strtoul(argv[0], NULL, 0);
+ dst_port = _strtoul(argv[1], NULL, 0);
+ AIR_PRINT("session id %d dst port %d.\n", session_id, dst_port);
+ session.dst_port = dst_port;
+ enable = _strtoul(argv[2], NULL, 0);
+ if(enable)
+ {
+ session.flags |= AIR_MIR_SESSION_FLAGS_ENABLE;
+ }
+ else
+ {
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_ENABLE;
+ }
+ tag_en = _strtoul(argv[3], NULL, 0);
+ if(tag_en)
+ {
+ session.flags |= AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG;
+ }
+ else
+ {
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG;
+ }
+ rc = _portListStr2Ary(argv[4], rxPbm, 1);
+ if(rc != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return rc;
+ }
+ AIR_PRINT("pbm %x.\n", rxPbm);
+ dir = _strtoul(argv[5], NULL, 0);
+ if(dir == 1)
+ {
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ }
+ else if(dir == 2)
+ {
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ }
+ else if(dir == 3)
+ {
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ }
+ else if (!dir)
+ {
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_TX;
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_RX;
+ }
+ else
+ {
+ return AIR_E_BAD_PARAMETER;
+ }
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(rxPbm[0] & (1 << i))
+ {
+ session.src_port = i;
+ /* set port mirror session */
+ rc = air_mir_addSession(0, session_id, &session);
+
+ if(AIR_E_OK!=rc)
+ {
+ AIR_PRINT("***Error***,dst-port=%u, src-port=%u error\n", session.dst_port, session.src_port);
+ return rc;
+ }
+ else
+ AIR_PRINT("add session %d,dst-port=%u, src-port=%u\n", session_id, session.dst_port, session.src_port);
+ }
+ }
+
+ return rc;
+}
+
+
+
+static AIR_ERROR_NO_T
+doMirrorSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mirrorSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMirrorAdd(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mirrorAddCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMirrorGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mirrorGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMirrorDel(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mirrorDelCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMirror(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mirrorCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMibClearPort(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+
+ if(1 == argc)
+ {
+ /* mib clear port */
+ port = _strtoul(argv[0], NULL, 0);
+ ret = air_mib_clear_by_port(0,port);
+ AIR_PRINT("Clear port %d mib stats",port);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ }
+ else if(0 == argc)
+ {
+ /*restart mib counter*/
+ air_mib_clear(0);
+ AIR_PRINT("Clear all mib stats",port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doMibClearAcl(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+
+ if(0 == argc)
+ {
+ /* mib clear acl */
+ ret = air_mib_clearAclEvent(0);
+ AIR_PRINT("Clear ACL Event Counter ");
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doMibGetPort(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0;
+ UI32_T tmp32 = 0xffffffff;
+ AIR_MIB_CNT_RX_T rx_mib = {0};
+ AIR_MIB_CNT_TX_T tx_mib = {0};
+
+ port = _strtoul(argv[0], NULL, 0);
+ if(1 == argc)
+ {
+ /* mib get <port(0..6)> */
+ ret = air_mib_get(0, port, &rx_mib, &tx_mib);
+ AIR_PRINT("Get MIB Counter of Port %u ", port);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ AIR_PRINT("RX Drop Packet : %u\n", rx_mib.RDPC);
+ AIR_PRINT("RX filtering Packet : %u\n", rx_mib.RFPC);
+ AIR_PRINT("RX Unicast Packet : %u\n", rx_mib.RUPC);
+ AIR_PRINT("RX Multicast Packet : %u\n", rx_mib.RMPC);
+ AIR_PRINT("RX Broadcast Packet : %u\n", rx_mib.RBPC);
+ AIR_PRINT("RX Alignment Error Packet : %u\n", rx_mib.RAEPC);
+ AIR_PRINT("RX CRC Packet : %u\n", rx_mib.RCEPC);
+ AIR_PRINT("RX Undersize Packet : %u\n", rx_mib.RUSPC);
+ AIR_PRINT("RX Fragment Error Packet : %u\n", rx_mib.RFEPC);
+ AIR_PRINT("RX Oversize Packet : %u\n", rx_mib.ROSPC);
+ AIR_PRINT("RX Jabber Error Packet : %u\n", rx_mib.RJEPC);
+ AIR_PRINT("RX Pause Packet : %u\n", rx_mib.RPPC);
+ AIR_PRINT("RX Packet Length 64 bytes : %u\n", rx_mib.RL64PC);
+ AIR_PRINT("RX Packet Length 65 ~ 127 bytes : %u\n", rx_mib.RL65PC);
+ AIR_PRINT("RX Packet Length 128 ~ 255 bytes : %u\n", rx_mib.RL128PC);
+ AIR_PRINT("RX Packet Length 256 ~ 511 bytes : %u\n", rx_mib.RL256PC);
+ AIR_PRINT("RX Packet Length 512 ~ 1023 bytes : %u\n", rx_mib.RL512PC);
+ AIR_PRINT("RX Packet Length 1024 ~ 1518 bytes: %u\n", rx_mib.RL1024PC);
+ AIR_PRINT("RX Packet Length 1519 ~ max bytes : %u\n", rx_mib.RL1519PC);
+ AIR_PRINT("RX_CTRL Drop Packet : %u\n", rx_mib.RCDPC);
+ AIR_PRINT("RX Ingress Drop Packet : %u\n", rx_mib.RIDPC);
+ AIR_PRINT("RX ARL Drop Packet : %u\n", rx_mib.RADPC);
+ AIR_PRINT("FLow Control Drop Packet : %u\n", rx_mib.FCDPC);
+ AIR_PRINT("WRED Drop Packtet : %u\n", rx_mib.WRDPC);
+ AIR_PRINT("Mirror Drop Packet : %u\n", rx_mib.MRDPC);
+ AIR_PRINT("RX sFlow Sampling Packet : %u\n", rx_mib.SFSPC);
+ AIR_PRINT("Rx sFlow Total Packet : %u\n", rx_mib.SFTPC);
+ AIR_PRINT("Port Control Drop Packet : %u\n", rx_mib.RXC_DPC);
+ AIR_PRINT("RX Octets good or bad packtes l32 : %u\n", (UI32_T)(rx_mib.ROC & tmp32));
+ AIR_PRINT("RX Octets good or bad packtes h32 : %u\n", (UI32_T)((rx_mib.ROC >> 32) & tmp32));
+ AIR_PRINT("RX Octets bad packets l32 : %u\n", (UI32_T)(rx_mib.ROC2 & tmp32));
+ AIR_PRINT("RX Octets bad packets h32 : %u\n", (UI32_T)((rx_mib.ROC2 >> 32) & tmp32));
+ AIR_PRINT("\n");
+ AIR_PRINT("TX Drop Packet : %u\n", tx_mib.TDPC);
+ AIR_PRINT("TX CRC Packet : %u\n", tx_mib.TCRC);
+ AIR_PRINT("TX Unicast Packet : %u\n", tx_mib.TUPC);
+ AIR_PRINT("TX Multicast Packet : %u\n", tx_mib.TMPC);
+ AIR_PRINT("TX Broadcast Packet : %u\n", tx_mib.TBPC);
+ AIR_PRINT("TX Collision Event Count : %u\n", tx_mib.TCEC);
+ AIR_PRINT("TX Single Collision Event Count : %u\n", tx_mib.TSCEC);
+ AIR_PRINT("TX Multiple Conllision Event Count: %u\n", tx_mib.TMCEC);
+ AIR_PRINT("TX Deferred Event Count : %u\n", tx_mib.TDEC);
+ AIR_PRINT("TX Late Collision Event Count : %u\n", tx_mib.TLCEC);
+ AIR_PRINT("TX Excessive Collision Event Count: %u\n", tx_mib.TXCEC);
+ AIR_PRINT("TX Pause Packet : %u\n", tx_mib.TPPC);
+ AIR_PRINT("TX Packet Length 64 bytes : %u\n", tx_mib.TL64PC);
+ AIR_PRINT("TX Packet Length 65 ~ 127 bytes : %u\n", tx_mib.TL65PC);
+ AIR_PRINT("TX Packet Length 128 ~ 255 bytes : %u\n", tx_mib.TL128PC);
+ AIR_PRINT("TX Packet Length 256 ~ 511 bytes : %u\n", tx_mib.TL256PC);
+ AIR_PRINT("TX Packet Length 512 ~ 1023 bytes : %u\n", tx_mib.TL512PC);
+ AIR_PRINT("TX Packet Length 1024 ~ 1518 bytes: %u\n", tx_mib.TL1024PC);
+ AIR_PRINT("TX Packet Length 1519 ~ max bytes : %u\n", tx_mib.TL1519PC);
+ AIR_PRINT("TX Oversize Drop Packet : %u\n", tx_mib.TODPC);
+ AIR_PRINT("TX Octets good or bad packtes l32 : %u\n", (UI32_T)(tx_mib.TOC & tmp32));
+ AIR_PRINT("TX Octets good or bad packtes h32 : %u\n", (UI32_T)((tx_mib.TOC >> 32) & tmp32));
+ AIR_PRINT("TX Octets bad packets l32 : %u\n", (UI32_T)(tx_mib.TOC2 & tmp32));
+ AIR_PRINT("TX Octets bad packets h32 : %u\n", (UI32_T)((tx_mib.TOC2 >> 32) & tmp32));
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doMibGetAcl(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T event = 0;
+ UI32_T cnt = 0;
+
+ if(1 == argc)
+ {
+ /* mib get acl <event(0..7)> */
+ event = _strtoul(argv[0], NULL, 0);
+ ret = air_mib_getAclEvent(0, event, &cnt);
+ AIR_PRINT("Get counter of ACL event %u ", event);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ AIR_PRINT("ACL Event Counter:%u\n", cnt);
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doMibClear(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mibClearCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMibGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mibGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doMib(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(mibCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doQosRateLimitExMngFrm(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T dir = 0;
+ BOOL_T enable = FALSE;
+
+ dir = _strtoul(argv[0], NULL, 0);
+ if(2 == argc)
+ {
+ if(dir == 0)
+ dir = AIR_QOS_RATE_DIR_EGRESS;
+ else if(dir == 1)
+ dir = AIR_QOS_RATE_DIR_INGRESS;
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ return ret;
+ }
+ enable = _strtoul(argv[1], NULL, 0);
+ ret = air_qos_setRateLimitExMngFrm(0, dir, enable);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Success.\n");
+ AIR_PRINT("Set %s Rate Limit Control %s management frame.\n",
+ (AIR_QOS_RATE_DIR_INGRESS == dir)?"Ingress":"Egress",
+ (TRUE == enable)?"exclude":"include");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ return ret;
+ }
+ }
+ else if(0 == argc)
+ {
+ dir = AIR_QOS_RATE_DIR_EGRESS;
+ ret = air_qos_getRateLimitExMngFrm(0, dir, &enable);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Success.\n");
+ AIR_PRINT("Get %s Rate Limit Control %s management frame.\n",
+ (AIR_QOS_RATE_DIR_INGRESS == dir)?"Ingress":"Egress",
+ (TRUE == enable)?"exclude":"include");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ return ret;
+ }
+ dir = AIR_QOS_RATE_DIR_INGRESS;
+ ret = air_qos_getRateLimitExMngFrm(0, dir, &enable);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Success.\n");
+ AIR_PRINT("Get %s Rate Limit Control %s management frame.\n",
+ (AIR_QOS_RATE_DIR_INGRESS == dir)?"Ingress":"Egress",
+ (TRUE == enable)?"exclude":"include");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ return ret;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+
+}
+
+static AIR_ERROR_NO_T
+doQosPortPriority(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_PORT_BITMAP_T portlist = {0};
+ UI32_T priority = 0;
+ UI8_T i = 0;
+
+ ret = _portListStr2Ary(argv[0], portlist, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+ if(2 == argc)
+ {
+ priority = _strtoul(argv[1], NULL, 0);
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_setPortPriority(0, i, priority);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port%02d port based priority %d Success.\n", i, priority);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d port based priority %d Fail.\n", i, priority);
+ }
+ }
+ }
+ }
+ else if(1 == argc)
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_getPortPriority(0, i, &priority);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%d port based priority %d.\n", i, priority);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%d port based priority Fail.\n", i);
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosRateLimit(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_PORT_BITMAP_T portlist = {0};
+ AIR_QOS_RATE_LIMIT_CFG_T rl = {0};
+ UI8_T i = 0;
+
+ ret = _portListStr2Ary(argv[0], portlist, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+ if(5 == argc)
+ {
+ rl.ingress_cir = _strtoul(argv[1], NULL, 0);
+ rl.ingress_cbs = _strtoul(argv[2], NULL, 0);
+ rl.egress_cir = _strtoul(argv[3], NULL, 0);
+ rl.egress_cbs = _strtoul(argv[4], NULL, 0);
+ rl.flags |= AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_INGRESS;
+ rl.flags |= AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_EGRESS;
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_setRateLimit(0, i, &rl);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Set Port%02d Ingress CIR %d CBS %d Egress CIR %d CBS %d Success.\n", i, rl.ingress_cir, rl.ingress_cbs, rl.egress_cir, rl.egress_cbs);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d Ingress CIR %d CBS %d Egress CIR %d CBS %d Fail.\n", i, rl.ingress_cir, rl.ingress_cbs, rl.egress_cir, rl.egress_cbs);
+ }
+ }
+ }
+ }
+ else if(1 == argc)
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_getRateLimit(0, i, &rl);
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("Get Port%02d Ingress CIR %d CBS %d Egress CIR %d CBS %d\n", i, rl.ingress_cir, rl.ingress_cbs, rl.egress_cir, rl.egress_cbs);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d Rate Info Fail.\n", i);
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosRateLimitEnable(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_PORT_BITMAP_T portlist = {0};
+ C8_T sten[2][10] = {"Disable", "Enable"};
+ C8_T stdir[2][10] = {"Egress", "Ingress"};
+ UI32_T dir = 0, en = 0;
+ AIR_QOS_RATE_DIR_T tmp_dir = AIR_QOS_RATE_DIR_LAST;
+ BOOL_T state = FALSE;
+ UI8_T i = 0;
+
+ ret = _portListStr2Ary(argv[0], portlist, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+ if(3 == argc)
+ {
+ dir = _strtoul(argv[1], NULL, 0);
+ en = _strtoul(argv[2], NULL, 0);
+ if(dir == 0)
+ tmp_dir = AIR_QOS_RATE_DIR_EGRESS;
+ else if(dir == 1)
+ tmp_dir = AIR_QOS_RATE_DIR_INGRESS;
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ if(en)
+ state= TRUE;
+ else
+ state = FALSE;
+
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_setRateLimitEnable(0, i, tmp_dir, state);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d %s rate %s Success.\n", i, stdir[dir], sten[en]);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d %s rate %s Fail.\n", i, stdir[dir], sten[en]);
+ }
+ }
+ }
+ }
+ else if(1 == argc)
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ tmp_dir = AIR_QOS_RATE_DIR_EGRESS;
+ dir = 0;
+ ret = air_qos_getRateLimitEnable(0, i, tmp_dir, &state);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get Port%02d %s rate %s Success.\n", i, stdir[dir], sten[state]);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d %s rate state Fail.\n", i, stdir[dir]);
+ }
+ tmp_dir = AIR_QOS_RATE_DIR_INGRESS;
+ dir = 1;
+ ret = air_qos_getRateLimitEnable(0, i, tmp_dir, &state);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get Port%02d %s rate %s Success.\n", i, stdir[dir], sten[state]);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d %s rate state Fail.\n", i, stdir[dir]);
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+
+}
+
+static AIR_ERROR_NO_T
+doQosDscp2Pri(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T dscp = 0, priority = 0;
+
+ dscp = _strtoul(argv[0], NULL, 0);
+ if(2 == argc)
+ {
+ priority = _strtoul(argv[1], NULL, 0);
+ ret = air_qos_setDscp2Pri(0, dscp, priority);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set DSCP %d to priority %d Success.\n", dscp, priority);
+ }
+ else
+ {
+ AIR_PRINT("Set DSCP %d to priority %d Fail.\n", dscp, priority);
+ }
+ }
+ else if(1 == argc)
+ {
+ ret = air_qos_getDscp2Pri(0, dscp, &priority);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get DSCP %d to priority %d\n", dscp, priority);
+ }
+ else
+ {
+ AIR_PRINT("Get DSCP %d to priority Fail.\n", dscp);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosPri2Queue(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T priority = 0, queue = 0;
+
+ priority = _strtoul(argv[1], NULL, 0);
+
+ if(2 == argc)
+ {
+ priority = _strtoul(argv[0], NULL, 0);
+ queue = _strtoul(argv[1], NULL, 0);
+ ret = air_qos_setPri2Queue(0, priority, queue);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set priority %d to queue %d Success.\n", priority, queue);
+ }
+ else
+ {
+ AIR_PRINT("Set priority %d to queue %d Fail.\n", priority, queue);
+ }
+ }
+ else
+ {
+ for(; priority < AIR_QOS_QUEUE_MAX_NUM; priority++)
+ {
+ ret = air_qos_getPri2Queue(0, priority, &queue);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get priority %d to queue %d\n", priority, queue);
+ }
+ else
+ {
+ AIR_PRINT("Get priority %d to queue Fail.\n", priority);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosTrustMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T mode = 0;
+ C8_T bs[4][13] = {"port", "1p_port", "dscp_port", "dscp_1p_port"};
+ AIR_QOS_TRUST_MODE_T mode_t = AIR_QOS_TRUST_MODE_LAST;
+ AIR_PORT_BITMAP_T portlist = {0};
+ UI8_T i = 0;
+
+ ret = _portListStr2Ary(argv[0], portlist, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+ if(2 == argc)
+ {
+ mode = _strtoul(argv[1], NULL, 0);
+ if(mode == 0)
+ mode_t = AIR_QOS_TRUST_MODE_PORT;
+ else if(mode == 1)
+ mode_t = AIR_QOS_TRUST_MODE_1P_PORT;
+ else if(mode == 2)
+ mode_t = AIR_QOS_TRUST_MODE_DSCP_PORT;
+ else if(mode == 3)
+ mode_t = AIR_QOS_TRUST_MODE_DSCP_1P_PORT;
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_setTrustMode(0, i, mode_t);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("port %d Set Trust mode %s Success.\n", i, bs[mode]);
+ }
+ else
+ {
+ AIR_PRINT("port %d Set Trust mode %s Fail.\n", i, bs[mode]);
+ }
+ }
+ }
+ }
+ else if(1 == argc)
+ {
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ mode_t = AIR_QOS_TRUST_MODE_LAST;
+ ret = air_qos_getTrustMode(0, i, &mode_t);
+ if(AIR_E_OK == ret)
+ {
+ if(mode_t == AIR_QOS_TRUST_MODE_PORT)
+ mode = 0;
+ else if(mode_t == AIR_QOS_TRUST_MODE_1P_PORT)
+ mode = 1;
+ else if(mode_t == AIR_QOS_TRUST_MODE_DSCP_PORT)
+ mode = 2;
+ else if(mode_t == AIR_QOS_TRUST_MODE_DSCP_1P_PORT)
+ mode = 3;
+ else
+ {
+ AIR_PRINT("port %d Get Trust mode Fail.\n", i);
+ return AIR_E_OTHERS;
+ }
+ AIR_PRINT("port %d Get Trust mode %s\n", i, bs[mode]);
+ }
+ else
+ {
+ AIR_PRINT("port %d Get Trust mode Fail.\n", i);
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosScheduleAlgo(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_PORT_BITMAP_T portlist = {0};
+ AIR_QOS_SCH_MODE_T sch_mode = AIR_QOS_SCH_MODE_LAST;
+ UI32_T scheduler = 0;
+ UI8_T queue = 0;
+ C8_T sche[3][5] = {"SP", "WRR", "WFQ"};
+ UI32_T weight = AIR_QOS_SHAPER_NOSETTING;
+ UI8_T i = 0;
+
+ ret = _portListStr2Ary(argv[0], portlist, 1);
+ if(ret != AIR_E_OK)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return ret;
+ }
+ AIR_PRINT("port list is %d\n", portlist[0]);
+ if(4 == argc)
+ {
+ queue = _strtoul(argv[1], NULL, 0);
+ AIR_PRINT("queue is %d\n", queue);
+ scheduler = _strtoul(argv[2], NULL, 0);
+ AIR_PRINT("scheduler is %d\n", scheduler);
+ weight = _strtoul(argv[3], NULL, 0);
+ AIR_PRINT("weight is %d\n", weight);
+ if(scheduler == 0)
+ {
+ sch_mode = AIR_QOS_SCH_MODE_SP;
+ weight = AIR_QOS_SHAPER_NOSETTING;
+ if(weight != AIR_QOS_SHAPER_NOSETTING)
+ AIR_PRINT("[Warning] SP schedule mode no need weight\n");
+ }
+ else if(scheduler == 1)
+ {
+ sch_mode = AIR_QOS_SCH_MODE_WRR;
+ if(weight == AIR_QOS_SHAPER_NOSETTING)
+ {
+ AIR_PRINT("[Warning] No weight value input , plz check\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ AIR_PRINT("sch_mode is 1\n");
+ }
+ else if(scheduler == 2)
+ {
+ sch_mode = AIR_QOS_SCH_MODE_WFQ;
+ if(weight == AIR_QOS_SHAPER_NOSETTING)
+ {
+ AIR_PRINT("[Warning] No weight value input , plz check\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unknown schedule mode, plz check again\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ AIR_PRINT("port %d\n", i);
+ ret = air_qos_setScheduleAlgo(0, i, queue, sch_mode, weight);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d Scheduler %s Success.\n", i, sche[scheduler]);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d Scheduler %s Fail.\n", i, sche[scheduler]);
+ }
+ }
+ }
+ }
+ else if(2 == argc)
+ {
+ queue = _strtoul(argv[1], NULL, 0);
+ for(i = 0; i < AIR_MAX_NUM_OF_PORTS; i++)
+ {
+ if(portlist[0] & (1 << i))
+ {
+ ret = air_qos_getScheduleAlgo(0, i, queue, &sch_mode, &weight);
+ if(AIR_E_OK == ret)
+ {
+ if(sch_mode == AIR_QOS_SCH_MODE_SP)
+ AIR_PRINT("Get Port%02d queue %d Scheduler %s\n", i, queue, sche[sch_mode]);
+ else if((sch_mode == AIR_QOS_SCH_MODE_WRR) || (sch_mode == AIR_QOS_SCH_MODE_WFQ))
+ AIR_PRINT("Get Port%02d queue %d Scheduler %s weight %d\n", i, queue, sche[sch_mode], weight);
+ else
+ AIR_PRINT("Get Port%02d queue %d Scheduler unknown\n", i, queue);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d queue %d Scheduler Fail.\n", i, queue);
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doQosGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(qosGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doQosSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(qosSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doQos(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(qosCmds, argc, argv);
+}
+static AIR_ERROR_NO_T
+doDiagTxComply(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T phy = 0;
+ UI32_T mode = 0;
+
+ phy = _strtoul(argv[0], NULL, 0);
+ if(2 == argc)
+ {
+ /* diag set txComply <phy(0~5)> <mode(0~8)> */
+ mode = _strtoul(argv[1], NULL, 0);
+ ret = air_diag_setTxComplyMode(0, phy, mode);
+ AIR_PRINT("Set diagnostic function: PHY %u Tx Compliance mode = %u ", phy, mode);
+ }
+ else if(1 == argc)
+ {
+ /* diag get txComply <phy(0~5)> */
+ ret = air_diag_getTxComplyMode(0, phy, &mode);
+ AIR_PRINT("Get diagnostic function: PHY %u Tx Compliance mode ", phy);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n\tMode=");
+ switch(mode)
+ {
+ case AIR_DIAG_TXCOMPLY_MODE_10M_NLP:
+ AIR_PRINT("%s\n", "10M_NLP");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_10M_RANDOM:
+ AIR_PRINT("%s\n", "10M_Random");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_10M_SINE:
+ AIR_PRINT("%s\n", "10M_Sine");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_A:
+ AIR_PRINT("%s\n", "100M_Pair_a");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_B:
+ AIR_PRINT("%s\n", "100M_Pair_b");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM1:
+ AIR_PRINT("%s\n", "1000M_TM1");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM2:
+ AIR_PRINT("%s\n", "1000M_TM2");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM3:
+ AIR_PRINT("%s\n", "1000M_TM3");
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM4:
+ AIR_PRINT("%s\n", "1000M_TM4");
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ if(AIR_E_OTHERS == ret)
+ {
+ AIR_PRINT("isn't setting.\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doDiagSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(diagSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doDiagGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(diagGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doDiag(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(diagCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doLedMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T mode = 0;
+
+ if(1 == argc)
+ {
+ /* led set mode <mode(0:disable, 1~3:2 LED, 4:User-Define)> */
+ mode = _strtoul(argv[0], NULL, 0);
+ ret = air_led_setMode(0, 0, mode);
+ AIR_PRINT("Set LED mode ");
+ }
+ else if(0 == argc)
+ {
+ /* led get mode */
+ ret = air_led_getMode(0, 0, &mode);
+ AIR_PRINT("Get LED mode ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ switch(mode)
+ {
+ case AIR_LED_MODE_DISABLE:
+ AIR_PRINT(": Disabled.\n");
+ break;
+ case AIR_LED_MODE_2LED_MODE0:
+ AIR_PRINT(": LED 0:Link / LED 1:Activity.\n");
+ break;
+ case AIR_LED_MODE_2LED_MODE1:
+ AIR_PRINT(": LED 0:1000M Activity / LED 1:100M Activity.\n");
+ break;
+ case AIR_LED_MODE_2LED_MODE2:
+ AIR_PRINT(": LED 0:1000M Activity / LED 1:10&100M Activity.\n");
+ break;
+ case AIR_LED_MODE_USER_DEFINE:
+ AIR_PRINT(": User-Defined.\n");
+ break;
+ default:
+ AIR_PRINT(": Fail.\n");
+ break;
+ }
+ }
+ else
+ if(AIR_E_OTHERS == ret)
+ {
+ AIR_PRINT(": Unrecognized.\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLedState(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI8_T entity = 0;
+ BOOL_T state = FALSE;
+
+ entity = _strtoul(argv[0], NULL, 0);
+ if(2 == argc)
+ {
+ /* led set state <led(0..1)> <state(1:En 0:Dis)> */
+ state = _strtoul(argv[1], NULL, 0);
+ ret = air_led_setState(0, 0, entity, state);
+ AIR_PRINT("Set LED %u state ", entity);
+ }
+ else if(1 == argc)
+ {
+ /* led get state <led(0..1)> */
+ ret = air_led_getState(0, 0, entity, &state);
+ AIR_PRINT("Get LED %u state ", entity );
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT(": %s.\n", (state)?"Enable":"Disabled");
+ }
+ else
+ if(AIR_E_OTHERS == ret)
+ {
+ AIR_PRINT(": Unrecognized.\n");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLedUsrDef(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T i = 0;
+ UI8_T entity = 0;
+ BOOL_T polarity = LOW;
+ UI32_T on_evt_map = 0;
+ UI32_T blk_evt_map = 0;
+ AIR_LED_ON_EVT_T on_evt;
+ AIR_LED_BLK_EVT_T blk_evt;
+
+ entity = _strtoul(argv[0], NULL, 0);
+ if(4 == argc)
+ {
+ /* led set usr <led(0..1)> <polarity(0:low, 1:high)> <on_evt(7'bin)> <blink_evt(10'bin)> */
+ polarity = _strtoul(argv[1], NULL, 0);
+ on_evt_map = _strtoul(argv[2], NULL, 2);
+ blk_evt_map = _strtoul(argv[3], NULL, 2);
+
+ memset(&on_evt, 0, sizeof(AIR_LED_ON_EVT_T));
+ if(on_evt_map & BIT(0))
+ {
+ on_evt.link_1000m = TRUE;
+ }
+ if(on_evt_map & BIT(1))
+ {
+ on_evt.link_100m = TRUE;
+ }
+ if(on_evt_map & BIT(2))
+ {
+ on_evt.link_10m = TRUE;
+ }
+ if(on_evt_map & BIT(3))
+ {
+ on_evt.link_dn = TRUE;
+ }
+ if(on_evt_map & BIT(4))
+ {
+ on_evt.fdx = TRUE;
+ }
+ if(on_evt_map & BIT(5))
+ {
+ on_evt.hdx = TRUE;
+ }
+ if(on_evt_map & BIT(6))
+ {
+ on_evt.force = TRUE;
+ }
+
+ memset(&blk_evt, 0, sizeof(AIR_LED_BLK_EVT_T));
+ if(blk_evt_map & BIT(0))
+ {
+ blk_evt.tx_act_1000m = TRUE;
+ }
+ if(blk_evt_map & BIT(1))
+ {
+ blk_evt.rx_act_1000m = TRUE;
+ }
+ if(blk_evt_map & BIT(2))
+ {
+ blk_evt.tx_act_100m = TRUE;
+ }
+ if(blk_evt_map & BIT(3))
+ {
+ blk_evt.rx_act_100m = TRUE;
+ }
+ if(blk_evt_map & BIT(4))
+ {
+ blk_evt.tx_act_10m = TRUE;
+ }
+ if(blk_evt_map & BIT(5))
+ {
+ blk_evt.rx_act_10m = TRUE;
+ }
+ if(blk_evt_map & BIT(6))
+ {
+ blk_evt.cls = TRUE;
+ }
+ if(blk_evt_map & BIT(7))
+ {
+ blk_evt.rx_crc = TRUE;
+ }
+ if(blk_evt_map & BIT(8))
+ {
+ blk_evt.rx_idle = TRUE;
+ }
+ if(blk_evt_map & BIT(9))
+ {
+ blk_evt.force = TRUE;
+ }
+ ret = air_led_setUsrDef(0, 0, entity, polarity, on_evt, blk_evt);
+ AIR_PRINT("Set LED %u User-define ", entity);
+ }
+ else if(1 == argc)
+ {
+ /* led get usr <led(0..1)> */
+ ret = air_led_getUsrDef(0, 0, entity, &polarity, &on_evt, &blk_evt);
+ AIR_PRINT("Get LED %u User-define ", entity );
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ AIR_PRINT("Polarity:%u.\n", polarity);
+ AIR_PRINT("On Event:\n");
+ i = 6;
+ AIR_PRINT("\t(%u)Force on :%s\n", i--, (on_evt.force)?"On":"Off");
+ AIR_PRINT("\t(%u)Half Duplex :%s\n", i--, (on_evt.hdx)?"On":"Off");
+ AIR_PRINT("\t(%u)Full Duplex :%s\n", i--, (on_evt.fdx)?"On":"Off");
+ AIR_PRINT("\t(%u)Link Down :%s\n", i--, (on_evt.link_dn)?"On":"Off");
+ AIR_PRINT("\t(%u)Link 10M :%s\n", i--, (on_evt.link_10m)?"On":"Off");
+ AIR_PRINT("\t(%u)Link 100M :%s\n", i--, (on_evt.link_100m)?"On":"Off");
+ AIR_PRINT("\t(%u)Link 1000M :%s\n", i--, (on_evt.link_1000m)?"On":"Off");
+
+ AIR_PRINT("Blinking Event:\n");
+ i = 9;
+ AIR_PRINT("\t(%u)Force blinks :%s\n", i--, (blk_evt.force)?"On":"Off");
+ AIR_PRINT("\t(%u)Rx Idle Error :%s\n", i--, (blk_evt.rx_idle)?"On":"Off");
+ AIR_PRINT("\t(%u)Rx CRC Error :%s\n", i--, (blk_evt.rx_crc)?"On":"Off");
+ AIR_PRINT("\t(%u)Collision :%s\n", i--, (blk_evt.cls)?"On":"Off");
+ AIR_PRINT("\t(%u)10Mbps RX Activity :%s\n", i--, (blk_evt.rx_act_10m)?"On":"Off");
+ AIR_PRINT("\t(%u)10Mbps TX Activity :%s\n", i--, (blk_evt.tx_act_10m)?"On":"Off");
+ AIR_PRINT("\t(%u)100Mbps RX Activity :%s\n", i--, (blk_evt.rx_act_100m)?"On":"Off");
+ AIR_PRINT("\t(%u)100Mbps TX Activity :%s\n", i--, (blk_evt.tx_act_100m)?"On":"Off");
+ AIR_PRINT("\t(%u)1000Mbps RX Activity :%s\n", i--, (blk_evt.rx_act_1000m)?"On":"Off");
+ AIR_PRINT("\t(%u)1000Mbps TX Activity :%s\n", i--, (blk_evt.tx_act_1000m)?"On":"Off");
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLedBlkTime(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_LED_BLK_DUR_T time = 0;
+
+ if(1 == argc)
+ {
+ /* led set time <time(0~5)> */
+ time = _strtoul(argv[0], NULL, 0);
+ ret = air_led_setBlkTime(0, 0, time);
+ AIR_PRINT("Set Blinking Duration ");
+ }
+ else if(0 == argc)
+ {
+ /* led get time */
+ ret = air_led_getBlkTime(0, 0, &time);
+ AIR_PRINT("Get Blinking Duration ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Done.\n");
+ AIR_PRINT("\tBlinking duration : %u (ms)\n", (32 << time) );
+ }
+ else
+ {
+ AIR_PRINT("Fail.\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doLedSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(ledSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doLedGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(ledGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doLed(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(ledCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doShowVersion(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_PRINT("VERSION: %s\n", AIR_VER_SDK);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T
+doShow(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(showCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doStormRate(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0, type = 0;
+ UI32_T unit = 0, count = 0;
+ C8_T stype[3][5] = {"Bcst", "Mcst", "Ucst"};
+ UI32_T kb = 0;
+
+ port = _strtol(argv[0], NULL, 10);
+ type = _strtol(argv[1], NULL, 10);
+ if(4 == argc)
+ {
+ count = _strtol(argv[2], NULL, 10);
+ unit = _strtol(argv[3], NULL, 10);
+
+ if(0 == unit)
+ kb = 64;
+ else if(1 == unit)
+ kb = 256;
+ else if(2 == unit)
+ kb = 1024;
+ else if(3 == unit)
+ kb = 4096;
+ else
+ kb = 16384;
+ ret = air_sec_setStormRate(0, port, type, count, unit);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d %s storm rate (%d * %d) = %d Kbps\n", port, stype[type], count, kb, (count*kb));
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d %s storm rate Fail.\n", port, stype[type]);
+ AIR_PRINT("Note: Port(0..4) can only select unit(0..3), port(5..6) can only select unit(4)\n");
+ }
+ }
+ else if(2 == argc)
+ {
+ ret = air_sec_getStormRate(0, port, type, &count, &unit);
+ if(AIR_E_OK == ret)
+ {
+ if(0 == unit)
+ kb = 64;
+ else if(1 == unit)
+ kb = 256;
+ else if(2 == unit)
+ kb = 1024;
+ else if(3 == unit)
+ kb = 4096;
+ else
+ kb = 16384;
+ AIR_PRINT("Port%02d %s storm rate (%d * %d) = %d Kbps\n", port, stype[type], count, kb, (count*kb));
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d %s storm rate Fail\n", port, stype[type]);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doFldMode(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0, type = 0;
+ BOOL_T fld_en = 0;
+ C8_T stype[4][5] = {"Bcst", "Mcst", "Ucst", "Qury"};
+ C8_T sen[2][10] = {"Disable", "Enable"};
+
+ port = _strtol(argv[0], NULL, 10);
+ type = _strtol(argv[1], NULL, 10);
+
+ if(2 == argc)
+ {
+ ret = air_sec_getFldMode(0, port, type, &fld_en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Get Port%02d flooding %s frame %s\n", port, stype[type], sen[fld_en]);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d flooding %s frame Fail\n", port, stype[type]);
+ }
+ }
+ else if(3 == argc)
+ {
+ fld_en = _strtol(argv[2], NULL, 10);
+ ret = air_sec_setFldMode(0, port, type, fld_en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d flooding %s frame %s Success\n", port, stype[type], sen[fld_en]);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d flooding %s frame %s Fail\n", port, stype[type], sen[fld_en]);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doStormEnable(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T port = 0, type = 0;
+ BOOL_T en = 0;
+ C8_T sen[2][10] = {"Disable", "Enable"};
+ C8_T stype[3][5] = {"Bcst", "Mcst", "Ucst"};
+
+ port = _strtol(argv[0], NULL, 10);
+ type = _strtol(argv[1], NULL, 10);
+ if(3 == argc)
+ {
+ en = _strtol(argv[2], NULL, 10);
+ ret = air_sec_setStormEnable(0, port, type, en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Set Port%02d %s storm %s Success.\n", port, stype[type], sen[en]);
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d %s storm %s Fail.\n", port, stype[type], sen[en]);
+ }
+ }
+ else if(2 == argc)
+ {
+ ret = air_sec_getStormEnable(0, port, type, &en);
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("Port%02d %s storm %s\n", port, stype[type], sen[en]);
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d %s storm Fail\n", port, stype[type]);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSaLearning(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_SEC_PORTSEC_PORT_CONFIG_T port_config;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ if(2 == argc)
+ {
+ memset(&port_config, 0, sizeof(AIR_SEC_PORTSEC_PORT_CONFIG_T));
+ rc = air_sec_getPortSecPortCfg(0, port, &port_config);
+ port_config.sa_lrn_en = _strtoul(argv[1], NULL, 0);
+ rc = air_sec_setPortSecPortCfg(0, port, port_config);
+ if(AIR_E_OK == rc)
+ {
+ AIR_PRINT("Set Port%02d sa learn %s Success.\n", port, port_config.sa_lrn_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d sa learn %s Fail.\n", port, port_config.sa_lrn_en?"Enable":"Disable");
+ }
+ }
+ else if(1 == argc)
+ {
+ rc = air_sec_getPortSecPortCfg(0, port, &port_config);
+ if(AIR_E_OK == rc)
+ {
+ AIR_PRINT("Port%02d sa learn: %s\n", port, port_config.sa_lrn_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d sa learn Fail\n", port);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ rc = AIR_E_BAD_PARAMETER;
+ }
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doSaLimit(UI32_T argc, C8_T *argv[])
+{
+ UI32_T port = 0;
+ AIR_SEC_PORTSEC_PORT_CONFIG_T port_config;
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ port = _strtoul(argv[0], NULL, 0);
+ if(3 == argc)
+ {
+ memset(&port_config, 0, sizeof(AIR_SEC_PORTSEC_PORT_CONFIG_T));
+ rc = air_sec_getPortSecPortCfg(0, port, &port_config);
+ port_config.sa_lmt_en = _strtoul(argv[1], NULL, 0);
+ port_config.sa_lmt_cnt = _strtoul(argv[2], NULL, 0);
+ rc = air_sec_setPortSecPortCfg(0, port, port_config);
+ if(AIR_E_OK == rc)
+ {
+ AIR_PRINT("Set Port%02d sa limit %s Success.\n", port, port_config.sa_lmt_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Set Port%02d sa limit %s Fail.\n", port, port_config.sa_lmt_en?"Enable":"Disable");
+ }
+ }
+ else if(1 == argc)
+ {
+ rc = air_sec_getPortSecPortCfg(0, port, &port_config);
+ if(AIR_E_OK == rc)
+ {
+ AIR_PRINT("Port%02d ", port);
+ AIR_PRINT("sa limit: %s\n", port_config.sa_lmt_en?"Enable":"Disable");
+ if(TRUE == (port_config.sa_lmt_en && (AIR_MAX_NUM_OF_MAC == port_config.sa_lmt_cnt)))
+ {
+ AIR_PRINT("Sa learning without limitation\n");
+ }
+ else if(TRUE == (port_config.sa_lmt_en && (AIR_MAX_NUM_OF_MAC > port_config.sa_lmt_cnt)))
+ {
+ AIR_PRINT("Rx sa allowable learning number: %d\n", port_config.sa_lmt_cnt);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Get Port%02d sa limit Fail\n", port);
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ rc = AIR_E_BAD_PARAMETER;
+ }
+
+ return rc;
+}
+
+static AIR_ERROR_NO_T
+doSecGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(secGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doSecSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(secSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doSec(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(secCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doSwitchCpuPortEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ BOOL_T cpu_en = FALSE;
+
+ if(0 == argc)
+ {
+ /* switch get sysPhyEn */
+ ret = air_switch_getCpuPortEn(0, &cpu_en);
+ AIR_PRINT("Get Cpu Port State ");
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(": %s\n", cpu_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else if(1 == argc)
+ {
+ /* switch set sysPhyEn <phy_en> */
+ cpu_en = _strtol(argv[0], NULL, 0);
+ ret = air_switch_setCpuPortEn(0, cpu_en);
+ AIR_PRINT("Set CPU port State ");
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(": %s\n", cpu_en?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSwitchCpuPort(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ BOOL_T cpu_en = FALSE;
+ UI32_T port = 0;
+ C8_T str_temp[AIR_MAX_NUM_OF_PORTS+1];
+
+ if(1 == argc)
+ {
+ /* switch set cpuPort <portnumber> */
+ port = _strtol(argv[0], NULL, 10);
+ ret = air_switch_setCpuPort(0, port);
+ AIR_PRINT("Set CPU Port ");
+ }
+ else if(0 == argc)
+ {
+ /* switch get cpuPort */
+ ret = air_switch_getCpuPort(0, &port);
+ AIR_PRINT("Get CPU Port ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT(": %d\n", port);
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSwitchPhyLCIntrEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T phy = 0;
+ BOOL_T enable = FALSE;
+
+ if(2 == argc)
+ {
+ /* switch set phyLCIntrEn <phy(0..6)> <(1:En,0:Dis)> */
+ phy = _strtol(argv[0], NULL, 10);
+ enable = _strtol(argv[1], NULL, 10);
+ ret = air_switch_setSysIntrEn(0, (phy + AIR_SYS_INTR_TYPE_PHY0_LC), enable);
+ }
+ else if(1 == argc)
+ {
+ /* switch get phyLCIntrEn <phy(0..6)> */
+ phy = _strtol(argv[0], NULL, 10);
+ ret = air_switch_getSysIntrEn(0, (phy + AIR_SYS_INTR_TYPE_PHY0_LC), &enable);
+ AIR_PRINT("PHY(%d) LinkChange interrupt : %s\n", phy, (TRUE == enable) ? "enable" : "disable");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doSwitchPhyLCIntrSts(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T phy = 0;
+ BOOL_T enable = FALSE;
+
+ if(2 == argc)
+ {
+ /* switch set phyLCIntrSts <phy(0..6)> <(1:En)> */
+ phy = _strtol(argv[0], NULL, 10);
+ enable = _strtol(argv[1], NULL, 10);
+ ret = air_switch_setSysIntrStatus(0, (phy + AIR_SYS_INTR_TYPE_PHY0_LC), enable);
+ }
+ else if(1 == argc)
+ {
+ /* switch get phyLCIntrSts <phy(0..6)> */
+ phy = _strtol(argv[0], NULL, 10);
+ ret = air_switch_getSysIntrStatus(0, (phy + AIR_SYS_INTR_TYPE_PHY0_LC), &enable);
+ AIR_PRINT("PHY(%d) LinkChange interrupt state : %s\n", phy, (TRUE == enable) ? "set" : "unset");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ ret = AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+
+static AIR_ERROR_NO_T
+doSwitchSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(switchSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doSwitchGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(switchGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doSwitch(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(switchCmds, argc, argv);
+}
+
+static void _air_acl_printRuleMap(UI32_T *rule_map, UI32_T ary_num)
+{
+ UI32_T i;
+ BOOL_T first;
+
+ first = TRUE;
+ for(i=0; i<ary_num*32; i++)
+ {
+ if(rule_map[i/32] & BIT(i%32))
+ {
+ if(TRUE == first)
+ {
+ AIR_PRINT("%u", i);
+ first = FALSE;
+ }
+ else
+ {
+ AIR_PRINT(",%u", i);
+ }
+ }
+ }
+ AIR_PRINT("\n");
+}
+
+static AIR_ERROR_NO_T
+doAclEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi=0;
+ UI32_T port = 0;
+ BOOL_T en = FALSE;
+
+ if(1 == argc)
+ {
+ /* acl set en <en(1:En,0:Dis)> */
+ en = _strtoul(argv[argi++], NULL, 2);
+ ret = air_acl_setGlobalState(0, en);
+ AIR_PRINT("Set Global ACL function ");
+ }
+ else if(0 == argc)
+ {
+ /* acl get en */
+ ret = air_acl_getGlobalState(0, &en);
+ AIR_PRINT("Get Global ACL function ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(": %s\n", (TRUE == en)?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclRule(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T rule_idx = 0;
+ BOOL_T state = FALSE, reverse = FALSE, end = FALSE;
+ UI32_T argi = 0, ipv6 = 0, i = 0;
+ AIR_ACL_RULE_T rule;
+ UI8_T tmp_ip[16] = {0};
+ C8_T str_temp[AIR_MAX_NUM_OF_PORTS+1];
+ C8_T str[40];
+
+ memset(&rule, 0, sizeof(AIR_ACL_RULE_T));
+ if(argc >= 6)
+ {
+ /* acl set rule <idx(0..255)> <state(0:Dis,1:En)> <reverse(0:Dis,1:En)> <end(0:Dis,1:En)> <portmap(7'bin)>
+ <ipv6(0:Dis,1:En,2:Not care)>
+ [ dmac <dmac(12'hex)> <dmac_mask(12'hex)> ]
+ [ smac <smac(12'hex)> <smac_mask(12'hex)> ]
+ [ stag <stag(4'hex)> <stag_mask(4'hex)> ]
+ [ ctag <ctag(4'hex)> <ctag_mask(4'hex)> ]
+ [ etype <etype(4'hex)> <etype_mask(4'hex)> ]
+ [ dip <dip(IPADDR)> <dip_mask(IPADDR)> ]
+ [ sip <sip(IPADDR)> <sip_mask(IPADDR)> ]
+ [ dscp <dscp(2'hex)> <dscp_mask(2'hex)> ]
+ [ protocol <protocol(2'hex)> <protocol_mask(2'hex)> ]
+ [ dport <dport(4'hex)> <dport_mask(4'hex)> ]
+ [ sport <sport(4'hex)> <sport_mask(4'hex)> ]
+ [ flow_label <flow_label(4'hex)> <flow_label_mask(4'hex)> ]
+ [ udf <udf(4'hex)> <udf_mask(4'hex)> ] */
+
+ rule_idx = _strtoul(argv[argi++], NULL, 0);
+
+ rule.ctrl.rule_en = _strtoul(argv[argi++], NULL, 0);
+ rule.ctrl.reverse = _strtoul(argv[argi++], NULL, 0);
+ rule.ctrl.end = _strtoul(argv[argi++], NULL, 0);
+
+ rule.key.portmap = _strtoul(argv[argi++], NULL, 2);
+ rule.mask.portmap = (~rule.key.portmap) & AIR_ALL_PORT_BITMAP;
+
+ ipv6 = _strtoul(argv[argi++], NULL, 0);
+ if(0 == ipv6)
+ {
+ rule.key.isipv6 = FALSE;
+ rule.mask.isipv6 = TRUE;
+ }
+ else if(1 == ipv6)
+ {
+ rule.key.isipv6 = TRUE;
+ rule.mask.isipv6 = TRUE;
+ }
+ else
+ {
+ rule.mask.isipv6 = FALSE;
+ }
+
+ if(0 == _strcmp(argv[argi], "dmac"))
+ {
+ argi++;
+ _str2mac(argv[argi++], rule.key.dmac);
+ _str2mac(argv[argi++], rule.mask.dmac);
+ rule.key.fieldmap |= 1 << AIR_ACL_DMAC;
+ }
+
+ if(0 == _strcmp(argv[argi], "smac"))
+ {
+ argi++;
+ _str2mac(argv[argi++], rule.key.smac);
+ _str2mac(argv[argi++], rule.mask.smac);
+ rule.key.fieldmap |= 1 << AIR_ACL_SMAC;
+ }
+
+ if(0 == _strcmp(argv[argi], "stag"))
+ {
+ argi++;
+ rule.key.stag = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.stag = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_STAG;
+ }
+
+ if(0 == _strcmp(argv[argi], "ctag"))
+ {
+ argi++;
+ rule.key.ctag = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.ctag = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_CTAG;
+ }
+
+ if(0 == _strcmp(argv[argi], "etype"))
+ {
+ argi++;
+ rule.key.etype= _strtoul(argv[argi++], NULL, 16);
+ rule.mask.etype = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_ETYPE;
+ }
+
+ if(0 == _strcmp(argv[argi], "dip"))
+ {
+ argi++;
+ if(0 == ipv6)
+ {
+ _str2ipv4(argv[argi++], rule.key.dip);
+ _str2ipv4(argv[argi++], rule.mask.dip);
+ }
+ else if(1 == ipv6)
+ {
+ _str2ipv6(argv[argi++], tmp_ip);
+ rule.key.dip[3] = (tmp_ip[0]<<24) | (tmp_ip[1]<<16) | (tmp_ip[2]<<8) | tmp_ip[3];
+ rule.key.dip[2] = (tmp_ip[4]<<24) | (tmp_ip[5]<<16) | (tmp_ip[6]<<8) | tmp_ip[7];
+ rule.key.dip[1] = (tmp_ip[8]<<24) | (tmp_ip[9]<<16) | (tmp_ip[10]<<8) | tmp_ip[11];
+ rule.key.dip[0] = (tmp_ip[12]<<24) | (tmp_ip[13]<<16) | (tmp_ip[14]<<8) | tmp_ip[15];
+ _str2ipv6(argv[argi++], tmp_ip);
+ rule.mask.dip[3] = (tmp_ip[0]<<24) | (tmp_ip[1]<<16) | (tmp_ip[2]<<8) | tmp_ip[3];
+ rule.mask.dip[2] = (tmp_ip[4]<<24) | (tmp_ip[5]<<16) | (tmp_ip[6]<<8) | tmp_ip[7];
+ rule.mask.dip[1] = (tmp_ip[8]<<24) | (tmp_ip[9]<<16) | (tmp_ip[10]<<8) | tmp_ip[11];
+ rule.mask.dip[0] = (tmp_ip[12]<<24) | (tmp_ip[13]<<16) | (tmp_ip[14]<<8) | tmp_ip[15];
+ }
+ rule.key.fieldmap |= 1 << AIR_ACL_DIP;
+ }
+
+ if(0 == _strcmp(argv[argi], "sip"))
+ {
+ argi++;
+ if(0 == ipv6)
+ {
+ _str2ipv4(argv[argi++], rule.key.sip);
+ _str2ipv4(argv[argi++], rule.mask.sip);
+ }
+ else if(1 == ipv6)
+ {
+ _str2ipv6(argv[argi++], tmp_ip);
+ rule.key.sip[3] = (tmp_ip[0]<<24) | (tmp_ip[1]<<16) | (tmp_ip[2]<<8) | tmp_ip[3];
+ rule.key.sip[2] = (tmp_ip[4]<<24) | (tmp_ip[5]<<16) | (tmp_ip[6]<<8) | tmp_ip[7];
+ rule.key.sip[1] = (tmp_ip[8]<<24) | (tmp_ip[9]<<16) | (tmp_ip[10]<<8) | tmp_ip[11];
+ rule.key.sip[0] = (tmp_ip[12]<<24) | (tmp_ip[13]<<16) | (tmp_ip[14]<<8) | tmp_ip[15];
+ _str2ipv6(argv[argi++], tmp_ip);
+ rule.mask.sip[3] = (tmp_ip[0]<<24) | (tmp_ip[1]<<16) | (tmp_ip[2]<<8) | tmp_ip[3];
+ rule.mask.sip[2] = (tmp_ip[4]<<24) | (tmp_ip[5]<<16) | (tmp_ip[6]<<8) | tmp_ip[7];
+ rule.mask.sip[1] = (tmp_ip[8]<<24) | (tmp_ip[9]<<16) | (tmp_ip[10]<<8) | tmp_ip[11];
+ rule.mask.sip[0] = (tmp_ip[12]<<24) | (tmp_ip[13]<<16) | (tmp_ip[14]<<8) | tmp_ip[15];
+ }
+ rule.key.fieldmap |= 1 << AIR_ACL_SIP;
+ }
+
+ if(0 == _strcmp(argv[argi], "dscp"))
+ {
+ argi++;
+ rule.key.dscp = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.dscp = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_DSCP;
+ }
+
+ if(0 == _strcmp(argv[argi], "protocol"))
+ {
+ argi++;
+ rule.key.protocol = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.protocol = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_PROTOCOL;
+ }
+
+ if(0 == _strcmp(argv[argi], "dport"))
+ {
+ argi++;
+ rule.key.dport = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.dport = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_DPORT;
+ }
+
+ if(0 == _strcmp(argv[argi], "sport"))
+ {
+ argi++;
+ rule.key.sport = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.sport = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_SPORT;
+ }
+
+ if(0 == _strcmp(argv[argi], "flow_label"))
+ {
+ argi++;
+ rule.key.flow_label= _strtoul(argv[argi++], NULL, 16);
+ rule.mask.flow_label= _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_FLOW_LABEL;
+ }
+
+ if(0 == _strcmp(argv[argi], "udf"))
+ {
+ argi++;
+ rule.key.udf = _strtoul(argv[argi++], NULL, 16);
+ rule.mask.udf = _strtoul(argv[argi++], NULL, 16);
+ rule.key.fieldmap |= 1 << AIR_ACL_UDF;
+ }
+
+ rule.mask.fieldmap = rule.key.fieldmap;
+ ret = air_acl_setRule(0, rule_idx, &rule);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Set ACL Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else if(1 == argc)
+ {
+ rule_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_getRule(0, rule_idx, &rule);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Get ACL Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ if(TRUE == rule.ctrl.rule_en)
+ {
+ AIR_PRINT("\t Rule end : %s\n", (TRUE == rule.ctrl.end)?"Enable":"Disable");
+ AIR_PRINT("\t Rule reverse : %s\n", (TRUE == rule.ctrl.reverse)?"Enable":"Disable");
+ _hex2bitstr((~rule.mask.portmap) & AIR_ALL_PORT_BITMAP, str_temp, AIR_MAX_NUM_OF_PORTS+1);
+ AIR_PRINT("\t Portmap[0:6] : %s\n", str_temp);
+ for(i = AIR_ACL_DMAC; i < AIR_ACL_FIELD_TYPE_LAST; i++)
+ {
+ if((1 << i) & rule.mask.fieldmap)
+ {
+ switch (i)
+ {
+ case AIR_ACL_DMAC:
+ AIR_PRINT("\t dmac: ");
+ AIR_PRINT("%02x-%02x-%02x-%02x-%02x-%02x",
+ rule.key.dmac[0], rule.key.dmac[1], rule.key.dmac[2],
+ rule.key.dmac[3], rule.key.dmac[4], rule.key.dmac[5]);
+ AIR_PRINT(", dmac-mask: ");
+ AIR_PRINT("%02x-%02x-%02x-%02x-%02x-%02x\n",
+ rule.mask.dmac[0], rule.mask.dmac[1], rule.mask.dmac[2],
+ rule.mask.dmac[3], rule.mask.dmac[4], rule.mask.dmac[5]);
+ break;
+ case AIR_ACL_SMAC:
+ AIR_PRINT("\t smac: ");
+ AIR_PRINT("%02x-%02x-%02x-%02x-%02x-%02x",
+ rule.key.smac[0], rule.key.smac[1], rule.key.smac[2],
+ rule.key.smac[3], rule.key.smac[4], rule.key.smac[5]);
+ AIR_PRINT(", smac-mask: ");
+ AIR_PRINT("%02x-%02x-%02x-%02x-%02x-%02x\n",
+ rule.mask.smac[0], rule.mask.smac[1], rule.mask.smac[2],
+ rule.mask.smac[3], rule.mask.smac[4], rule.mask.smac[5]);
+ break;
+ case AIR_ACL_ETYPE:
+ AIR_PRINT("\t etype: 0x%x, etype-mask: 0x%x\n", rule.key.etype, rule.mask.etype);
+ break;
+ case AIR_ACL_STAG:
+ AIR_PRINT("\t stag: 0x%x, stag-mask: 0x%x\n", rule.key.stag, rule.mask.stag);
+ break;
+ case AIR_ACL_CTAG:
+ AIR_PRINT("\t ctag: 0x%x, ctag-mask: 0x%x\n", rule.key.ctag, rule.mask.ctag);
+ break;
+ case AIR_ACL_DPORT:
+ AIR_PRINT("\t dport: 0x%x, dport-mask: 0x%x\n", rule.key.dport, rule.mask.dport);
+ break;
+ case AIR_ACL_SPORT:
+ AIR_PRINT("\t sport: 0x%x, sport-mask: 0x%x\n", rule.key.sport, rule.mask.sport);
+ break;
+ case AIR_ACL_UDF:
+ AIR_PRINT("\t udf: 0x%x, udf-mask: 0x%x\n", rule.key.udf, rule.mask.udf);
+ break;
+ case AIR_ACL_DIP:
+ if (0 == rule.key.isipv6)
+ {
+ AIR_PRINT("\t dip: ");
+ AIR_PRINT("%d.%d.%d.%d",
+ ((rule.key.dip[0])&0xFF000000)>>24,((rule.key.dip[0])&0x00FF0000)>>16,
+ ((rule.key.dip[0])&0x0000FF00)>>8, ((rule.key.dip[0])&0x000000FF));
+ AIR_PRINT(", dip-mask: ");
+ AIR_PRINT("%d.%d.%d.%d\n ",
+ ((rule.mask.dip[0])&0xFF000000)>>24,((rule.mask.dip[0])&0x00FF0000)>>16,
+ ((rule.mask.dip[0])&0x0000FF00)>>8, ((rule.mask.dip[0])&0x000000FF));
+ }
+ else
+ {
+ for(i=0; i<4; i++){
+ tmp_ip[i] = (rule.key.dip[3] >> (8*(3-i))) & 0xff;
+ AIR_PRINT("get tmp_ip[%d]=0x%x\n", i, tmp_ip[i]);
+ }
+ for(i=4; i<8; i++){
+ tmp_ip[i] = (rule.key.dip[2] >> (8*(7-i))) & 0xff;
+ }
+ for(i=8; i<12; i++){
+ tmp_ip[i] = (rule.key.dip[1] >> (8*(11-i))) & 0xff;
+ }
+ for(i=12; i<16; i++){
+ tmp_ip[i] = (rule.key.dip[0] >> (8*(15-i))) & 0xff;
+ }
+
+ AIR_PRINT("\t dip: ");
+ AIR_PRINT("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ tmp_ip[0], tmp_ip[1],tmp_ip[2], tmp_ip[3],tmp_ip[4], tmp_ip[5],tmp_ip[6], tmp_ip[7],
+ tmp_ip[8], tmp_ip[9],tmp_ip[10], tmp_ip[11],tmp_ip[12], tmp_ip[13],tmp_ip[14], tmp_ip[15]);
+ for(i=0; i<4; i++){
+ tmp_ip[i] = (rule.mask.dip[3] >> (8*(3-i))) & 0xff;
+ }
+ for(i=4; i<8; i++){
+ tmp_ip[i] = (rule.mask.dip[2] >> (8*(7-i))) & 0xff;
+ }
+ for(i=8; i<12; i++){
+ tmp_ip[i] = (rule.mask.dip[1] >> (8*(11-i))) & 0xff;
+ }
+ for(i=12; i<16; i++){
+ tmp_ip[i] = (rule.mask.dip[0] >> (8*(15-i))) & 0xff;
+ }
+ AIR_PRINT(", dip-mask: ");
+ AIR_PRINT("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ tmp_ip[0], tmp_ip[1],tmp_ip[2], tmp_ip[3],tmp_ip[4], tmp_ip[5],tmp_ip[6], tmp_ip[7],
+ tmp_ip[8], tmp_ip[9],tmp_ip[10], tmp_ip[11],tmp_ip[12], tmp_ip[13],tmp_ip[14], tmp_ip[15]);
+ }
+ break;
+ case AIR_ACL_SIP:
+ if (0 == rule.key.isipv6)
+ {
+ AIR_PRINT("\t sip: ");
+ AIR_PRINT("%d.%d.%d.%d ",
+ ((rule.key.sip[0])&0xFF000000)>>24,((rule.key.sip[0])&0x00FF0000)>>16,
+ ((rule.key.sip[0])&0x0000FF00)>>8, ((rule.key.sip[0])&0x000000FF));
+ AIR_PRINT(", sip-mask: ");
+ AIR_PRINT("%d.%d.%d.%d\n ",
+ ((rule.mask.sip[0])&0xFF000000)>>24,((rule.mask.sip[0])&0x00FF0000)>>16,
+ ((rule.mask.sip[0])&0x0000FF00)>>8, ((rule.mask.sip[0])&0x000000FF));
+ }
+ else
+ {
+ for(i=0; i<4; i++){
+ tmp_ip[i] = (rule.key.sip[3] >> (8*(3-i))) & 0xff;
+ }
+ for(i=4; i<8; i++){
+ tmp_ip[i] = (rule.key.sip[2] >> (8*(7-i))) & 0xff;
+ }
+ for(i=8; i<12; i++){
+ tmp_ip[i] = (rule.key.sip[1] >> (8*(11-i))) & 0xff;
+ }
+ for(i=12; i<16; i++){
+ tmp_ip[i] = (rule.key.sip[0] >> (8*(15-i))) & 0xff;
+ }
+ AIR_PRINT("\t sip: ");
+ AIR_PRINT("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+ tmp_ip[0], tmp_ip[1],tmp_ip[2], tmp_ip[3],tmp_ip[4], tmp_ip[5],tmp_ip[6], tmp_ip[7],
+ tmp_ip[8], tmp_ip[9],tmp_ip[10], tmp_ip[11],tmp_ip[12], tmp_ip[13],tmp_ip[14], tmp_ip[15]);
+ for(i=0; i<4; i++){
+ tmp_ip[i] = (rule.mask.sip[3] >> (8*(3-i))) & 0xff;
+ }
+ for(i=4; i<8; i++){
+ tmp_ip[i] = (rule.mask.sip[2] >> (8*(7-i))) & 0xff;
+ }
+ for(i=8; i<12; i++){
+ tmp_ip[i] = (rule.mask.sip[1] >> (8*(11-i))) & 0xff;
+ }
+ for(i=12; i<16; i++){
+ tmp_ip[i] = (rule.mask.sip[0] >> (8*(15-i))) & 0xff;
+ }
+ AIR_PRINT(", sip-mask: ");
+ AIR_PRINT("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
+ tmp_ip[0], tmp_ip[1],tmp_ip[2], tmp_ip[3],tmp_ip[4], tmp_ip[5],tmp_ip[6], tmp_ip[7],
+ tmp_ip[8], tmp_ip[9],tmp_ip[10], tmp_ip[11],tmp_ip[12], tmp_ip[13],tmp_ip[14], tmp_ip[15]);
+ }
+ break;
+ case AIR_ACL_DSCP:
+ AIR_PRINT("\t dscp: 0x%x, dscp-mask: 0x%x\n", rule.key.dscp, rule.mask.dscp);
+ break;
+ case AIR_ACL_PROTOCOL:
+ AIR_PRINT("\t protocol: 0x%x, protocol-mask: 0x%x\n", rule.key.protocol, rule.mask.protocol);
+ break;
+ case AIR_ACL_FLOW_LABEL:
+ AIR_PRINT("\t flow-label: 0x%x, flow-label-mask: 0x%x\n", rule.key.flow_label, rule.mask.flow_label);
+ break;
+ default:
+ AIR_PRINT("error\n");
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ AIR_PRINT("Entry is Invalid.\n");
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclRmvRule(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T rule_idx = 0;
+
+ if(1 == argc)
+ {
+ /* acl del rule <idx(0..127)> */
+ rule_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_delRule(0, rule_idx);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Delete ACL Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else if(0 == argc)
+ {
+ /* acl clear rule */
+ ret = air_acl_clearRule(0);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Clear ACL Rule: %s\n", air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclUdfRule(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T rule_idx;
+ AIR_ACL_UDF_RULE_T rule;
+ C8_T start_addr[8][12]=
+ {
+ "MAC header",
+ "L2 payload",
+ "IPv4 header",
+ "IPv6 header",
+ "L3 payload",
+ "TCP header",
+ "UDP header",
+ "L4 payload"
+ };
+ C8_T str_temp[AIR_MAX_NUM_OF_PORTS+1];
+
+ memset(&rule, 0, sizeof(AIR_ACL_UDF_RULE_T));
+ if(7 == argc)
+ {
+ /* acl set rule <idx(0..255)> <mode(0:pattern, 1:threshold)> [ <pat(4'hex)> <mask(4'hex)> | <low(4'hex)> <high(4'hex)> ] <start(0:MAC,1:ether,2:IP,3:IP_data,4:TCP/UDP,5:TCP/UDP data,6:IPv6)> <offset(0..62,unit:2 bytes)> <portmap(7'bin)> */
+ rule_idx = _strtoul(argv[0], NULL, 0);
+ rule.cmp_sel = _strtoul(argv[1], NULL, 2);
+ if(AIR_ACL_RULE_CMP_SEL_PATTERN == rule.cmp_sel)
+ {
+ rule.pattern = _strtoul(argv[2], NULL, 16);
+ rule.mask = _strtoul(argv[3], NULL, 16);
+ }
+ else
+ {
+ rule.low_threshold = _strtoul(argv[2], NULL, 16);
+ rule.high_threshold = _strtoul(argv[3], NULL, 16);
+ }
+ rule.offset_format = _strtoul(argv[4], NULL, 0);
+ rule.offset = _strtoul(argv[5], NULL, 0);
+ rule.portmap = _strtoul(argv[6], NULL, 2);
+ rule.valid = TRUE;
+ ret = air_acl_setUdfRule(0, rule_idx, rule);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Set ACL UDF Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else if(1 == argc)
+ {
+ rule_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_getUdfRule(0, rule_idx, &rule);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Get ACL UDF Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ if(TRUE == rule.valid)
+ {
+ AIR_PRINT("\tMode : %s\n", (AIR_ACL_RULE_CMP_SEL_PATTERN == rule.cmp_sel)?"Pattern":"Threshold");
+ if(AIR_ACL_RULE_CMP_SEL_PATTERN == rule.cmp_sel)
+ {
+ AIR_PRINT("\tPattern : 0x%04X\n", rule.pattern);
+ AIR_PRINT("\tMask : 0x%04X\n", rule.mask);
+ }
+ else
+ {
+ AIR_PRINT("\tLow Threshold : 0x%04X\n", rule.low_threshold);
+ AIR_PRINT("\tHigh Threshold: 0x%04X\n", rule.high_threshold);
+ }
+ AIR_PRINT("\tOffset Start : %s\n", start_addr[rule.offset_format]);
+ AIR_PRINT("\tOffset : %u %s\n", rule.offset*2, (0==rule.offset)?"Byte":"Bytes");
+ _hex2bitstr(rule.portmap, str_temp, AIR_MAX_NUM_OF_PORTS+1);
+ AIR_PRINT("\tPortmap[0:6] : %s\n", str_temp);
+ }
+ else
+ {
+ AIR_PRINT("Entry is Invalid.\n");
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclRmvUdfRule(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T rule_idx;
+
+ if(1 == argc)
+ {
+ /* acl del udfRule <idx(0..15)> */
+ rule_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_delUdfRule(0, rule_idx);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Delete ACL UDF Rule(%u): %s\n", rule_idx, air_error_getString(ret));
+ }
+ else if(0 == argc)
+ {
+ /* acl clear udfRule */
+ ret = air_acl_clearUdfRule(0);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Clear ACL UDF Rule: %s\n", air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclAction(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi = 0;
+ UI32_T act_idx;
+ AIR_ACL_ACTION_T act;
+ UI32_T redirect, trtcm, fwd;
+ C8_T fwding[AIR_ACL_ACT_FWD_LAST][25] =
+ {
+ "Default",
+ "Default",
+ "Default",
+ "Default",
+ "Default & CPU excluded",
+ "Default & CPU included",
+ "CPU only",
+ "Drop"
+ };
+ C8_T trtcm_usr[AIR_ACL_ACT_USR_TCM_LAST][8] =
+ {
+ "Default",
+ "Green",
+ "Yellow",
+ "Red"
+ };
+ C8_T egtag[AIR_ACL_ACT_EGTAG_LAST][11] =
+ {
+ "Default",
+ "Consistent",
+ "",
+ "",
+ "Untag",
+ "Swap",
+ "Tag",
+ "Stack"
+ };
+ C8_T str_temp[20];
+
+ memset(&act, 0, sizeof(AIR_ACL_ACTION_T));
+ if(2 < argc)
+ {
+ /* acl set action <idx(0..127)>
+ [ forward <forward(0:Default,4:Exclude CPU,5:Include CPU,6:CPU only,7:Drop)> ]
+ [ egtag <egtag(0:Default,1:Consistent,4:Untag,5:Swap,6:Tag,7:Stack)> ]
+ [ mirrormap <mirrormap(2'bin)> ]
+ [ priority <priority(0..7)> ]
+ [ redirect <redirect(0:Dst,1:Vlan)> <portmap(7'bin)> ]
+ [ leaky_vlan <leaky_vlan(1:En,0:Dis)> ]
+ [ cnt_idx <cnt_idx(0..63)> ]
+ [ rate_idx <rate_idx(0..31)> ]
+ [ attack_idx <attack_idx(0..95)> ]
+ [ vid <vid(0..4095)> ]
+ [ manage <manage(1:En,0:Dis)> ]
+ [ bpdu <bpdu(1:En,0:Dis)> ]
+ [ class <class(0:Original,1:Defined)>[0..7] ]
+ [ drop_pcd <drop_pcd(0:Original,1:Defined)> [red <red(0..7)>][yellow <yellow(0..7)>][green <green(0..7)>] ]
+ [ color <color(0:Defined,1:Trtcm)> [ <defined_color(0:Dis,1:Green,2:Yellow,3:Red)> | <trtcm_idx(0..31)> ] ]*/
+
+ act_idx = _strtoul(argv[argi++], NULL, 0);
+ if(0 == _strcmp(argv[argi], "forward"))
+ {
+ argi++;
+ fwd = _strtoul(argv[argi++], NULL, 0);
+ act.fwd_en = TRUE;
+ act.fwd = fwd;
+ }
+
+ if(0 == _strcmp(argv[argi], "egtag"))
+ {
+ argi++;
+ act.egtag_en = TRUE;
+ act.egtag = _strtoul(argv[argi++], NULL, 0);
+ }
+
+ if(0 == _strcmp(argv[argi], "mirrormap"))
+ {
+ argi++;
+ act.mirrormap = _strtoul(argv[argi++], NULL, 2);
+ }
+
+ if(0 == _strcmp(argv[argi], "priority"))
+ {
+ argi++;
+ act.pri_user_en = TRUE;
+ act.pri_user= _strtoul(argv[argi++], NULL, 0);
+ }
+
+ if(0 == _strcmp(argv[argi], "redirect"))
+ {
+ argi++;
+ redirect = _strtoul(argv[argi++], NULL, 0);
+ if(0 == redirect)
+ {
+ act.port_en = TRUE;
+ act.dest_port_sel = TRUE;
+ act.portmap = _strtoul(argv[argi++], NULL, 2);
+ }
+ else
+ {
+ act.port_en = TRUE;
+ act.vlan_port_sel = TRUE;
+ act.portmap = _strtoul(argv[argi++], NULL, 2);
+ }
+ }
+
+ if(0 == _strcmp(argv[argi], "leaky_vlan"))
+ {
+ argi++;
+ act.lyvlan_en = TRUE;
+ act.lyvlan = _strtoul(argv[argi++], NULL, 0);
+ }
+
+ /* ACL event counter */
+ if(0 == _strcmp(argv[argi], "cnt_idx"))
+ {
+ argi++;
+ act.cnt_en = TRUE;
+ act.cnt_idx = _strtol(argv[argi++], NULL, 0);
+ }
+
+ if(0 == _strcmp(argv[argi], "rate_idx"))
+ {
+ argi++;
+ act.rate_en = TRUE;
+ act.rate_idx = _strtol(argv[argi++], NULL, 0);
+ }
+
+ if(0 == _strcmp(argv[argi], "attack_idx"))
+ {
+ argi++;
+ act.attack_en = TRUE;
+ act.attack_idx = _strtol(argv[argi++], NULL, 0);
+ }
+
+ if(0 == _strcmp(argv[argi], "vid"))
+ {
+ argi++;
+ act.vlan_en = TRUE;
+ act.vlan_idx = _strtol(argv[argi++], NULL, 0);
+ }
+
+ /* Management frame */
+ if(0 == _strcmp(argv[argi], "manage"))
+ {
+ argi++;
+ act.mang = _strtoul(argv[argi++], NULL, 2);
+ }
+
+ if(0 == _strcmp(argv[argi], "bpdu"))
+ {
+ argi++;
+ act.bpdu = _strtoul(argv[argi++], NULL, 2);
+ }
+
+ /* DSCP class remap */
+ if(0 == _strcmp(argv[argi], "class"))
+ {
+ argi++;
+ act.trtcm_en = TRUE;
+ act.trtcm.cls_slr_sel = _strtoul(argv[argi++], NULL, 2);
+ if(TRUE == act.trtcm.cls_slr_sel)
+ {
+ act.trtcm.cls_slr = _strtoul(argv[argi++], NULL, 0);
+ }
+ }
+ if(0 == _strcmp(argv[argi], "drop_pcd"))
+ {
+ argi++;
+ act.trtcm_en = TRUE;
+ act.trtcm.drop_pcd_sel = _strtoul(argv[argi++], NULL, 2);
+ if(TRUE == act.trtcm.drop_pcd_sel)
+ {
+ if(0 == _strcmp(argv[argi], "red"))
+ {
+ argi++;
+ act.trtcm.drop_pcd_r= _strtoul(argv[argi++], NULL, 0);
+ }
+ if(0 == _strcmp(argv[argi], "yellow"))
+ {
+ argi++;
+ act.trtcm.drop_pcd_y= _strtoul(argv[argi++], NULL, 0);
+ }
+ if(0 == _strcmp(argv[argi], "green"))
+ {
+ argi++;
+ act.trtcm.drop_pcd_g= _strtoul(argv[argi++], NULL, 0);
+ }
+ }
+ }
+
+ /* trTCM */
+ if(0 == _strcmp(argv[argi], "color"))
+ {
+ argi++;
+ act.trtcm_en = TRUE;
+ act.trtcm.tcm_sel = _strtoul(argv[argi++], NULL, 2);
+ trtcm = _strtoul(argv[argi++], NULL, 0);
+ if(FALSE == act.trtcm.tcm_sel)
+ {
+ act.trtcm.usr_tcm = trtcm;
+ }
+ else
+ {
+ act.trtcm.tcm_idx = trtcm;
+ }
+ }
+ ret = air_acl_setAction(0, act_idx, act);
+ AIR_PRINT("Set ACL Action(%u): %s\n", act_idx, air_error_getString(ret));
+ }
+ else if(1 == argc)
+ {
+ /* acl get action <idx(0..127)> */
+ act_idx = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getAction(0, act_idx, &act);
+ AIR_PRINT("Get ACL Action(%u): %s\n", act_idx, air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ if(TRUE == act.fwd_en)
+ {
+ AIR_PRINT("\t Forwarding : %s\n", fwding[act.fwd]);
+ }
+
+ if(TRUE == act.egtag_en)
+ {
+ AIR_PRINT("\t Egress tag : %s\n", egtag[act.egtag]);
+ }
+
+ if(act.mirrormap)
+ {
+ AIR_PRINT("\t Mirror Session Map : %u\n", act.mirrormap);
+ }
+
+ if(TRUE == act.pri_user_en)
+ {
+ AIR_PRINT("\t User Priority : %u\n", act.pri_user);
+ }
+
+ if(TRUE == act.port_en)
+ {
+ _hex2bitstr(act.portmap, str_temp, AIR_MAX_NUM_OF_PORTS+1);
+ if(TRUE == act.dest_port_sel)
+ {
+ AIR_PRINT("\t Destination Port[0:6]: %s\n", str_temp);
+ }
+ else
+ {
+ AIR_PRINT("\t VLAN Port[0:6] : %s\n", str_temp);
+ }
+ }
+
+ if(TRUE == act.lyvlan_en)
+ {
+ AIR_PRINT("\t Leaky VLAN : %s\n", (TRUE == act.lyvlan)?"Enable":"Disable");
+ }
+ AIR_PRINT("\t Management Frame : %s\n", (TRUE == act.mang)?"Enable":"Disable");
+ AIR_PRINT("\t BPDU Frame : %s\n", (TRUE == act.bpdu)?"Enable":"Disable");
+
+ if(TRUE == act.cnt_en)
+ {
+ AIR_PRINT("\t Event Index : %u\n", act.cnt_idx);
+ }
+
+ /* trTCM*/
+ if(TRUE == act.trtcm_en)
+ {
+ if(TRUE == act.trtcm.cls_slr_sel)
+ {
+ AIR_PRINT("\t Class Selector Remap : %u\n", act.trtcm.cls_slr);
+ }
+ else
+ {
+ AIR_PRINT("\t Class Selector Remap : %s\n", "Disable");
+ }
+ if(TRUE == act.trtcm.drop_pcd_sel)
+ {
+ AIR_PRINT("\t Drop Precedence Remap(Red): %u\n", act.trtcm.drop_pcd_r);
+ AIR_PRINT("\t Drop Precedence Remap(Yel): %u\n", act.trtcm.drop_pcd_y);
+ AIR_PRINT("\t Drop Precedence Remap(Gre): %u\n", act.trtcm.drop_pcd_g);
+ }
+ else
+ {
+ AIR_PRINT("\t Drop Precedence Remap: %s\n", "Disable");
+ }
+
+ if(TRUE == act.trtcm.tcm_sel)
+ {
+ AIR_PRINT("\t trTCM Meter Index : %u\n", act.trtcm.tcm_idx);
+ }
+ else
+ {
+ AIR_PRINT("\t trTCM User Defined : %s\n", trtcm_usr[act.trtcm.usr_tcm]);
+ }
+ }
+ /* rate control */
+ if(TRUE == act.rate_en)
+ {
+ AIR_PRINT("\t Rate Control Index : %u\n", act.rate_idx);
+ }
+
+ if(TRUE == act.attack_en)
+ {
+ AIR_PRINT("\t Attack Rate Control Index: %u\n", act.attack_idx);
+ }
+
+ if(TRUE == act.vlan_en)
+ {
+ AIR_PRINT("\t ACL VLAN Index : %u\n", act.vlan_idx);
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclRmvAction(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T act_idx;
+
+ if(1 == argc)
+ {
+ /* acl del action <idx(0..127)> */
+ act_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_delAction(0, act_idx);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Delete ACL Action(%u): %s\n", act_idx, air_error_getString(ret));
+ }
+ else if(0 == argc)
+ {
+ /* acl clear action */
+ ret = air_acl_clearAction(0);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Clear ACL Action: %s\n", air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclTrtcm(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi = 0;
+ UI32_T tcm_idx;
+ AIR_ACL_TRTCM_T tcm;
+
+ memset(&tcm, 0, sizeof(AIR_ACL_TRTCM_T));
+ if(5 == argc)
+ {
+ /* acl set trtcm <idx(0..31)> <cir(4'hex)> <pir(4'hex)> <cbs(4'hex)> <pbs(4'hex)> */
+ tcm_idx = _strtoul(argv[argi++], NULL, 0);
+ tcm.cir = _strtoul(argv[argi++], NULL, 16);
+ tcm.pir = _strtoul(argv[argi++], NULL, 16);
+ tcm.cbs = _strtoul(argv[argi++], NULL, 16);
+ tcm.pbs = _strtoul(argv[argi++], NULL, 16);
+
+ ret = air_acl_setTrtcm(0, tcm_idx, tcm);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Set ACL trTCM(%u): %s\n", tcm_idx, air_error_getString(ret));
+ }
+ else if(1 == argc)
+ {
+ /* acl get trtcm <idx(1..31)> */
+ tcm_idx = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getTrtcm(0, tcm_idx, &tcm);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Get ACL trTCM(%u): %s\n", tcm_idx, air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("\t CIR: 0x%04X(unit:64Kbps)\n", tcm.cir);
+ AIR_PRINT("\t PIR: 0x%04X(unit:64Kbps)\n", tcm.pir);
+ AIR_PRINT("\t CBS: 0x%04X(unit:Byte)\n", tcm.cbs);
+ AIR_PRINT("\t PBS: 0x%04X(unit:Byte)\n", tcm.pbs);
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclTrtcmEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ BOOL_T state = FALSE;
+
+ if (1 == argc)
+ {
+ /* acl set trtcmEn <en(1:En,0:Dis)> */
+ state = _strtol(argv[0], NULL, 10);
+ ret = air_acl_setTrtcmEnable(0, state);
+ AIR_PRINT("Set trTCM State ");
+ }
+ else if (0 == argc)
+ {
+ /* acl get trtcmEn */
+ ret = air_acl_getTrtcmEnable(0, &state);
+ AIR_PRINT("Get trTCM State ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if (ret == AIR_E_OK)
+ {
+ AIR_PRINT(": %s\n", (TRUE == state) ? "Enable" : "Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclRmvTrtcm(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T tcm_idx;
+
+ if(1 == argc)
+ {
+ /* acl del trtcm <idx(1..31)> */
+ tcm_idx = _strtoul(argv[0], NULL, 0);
+ ret = air_acl_delTrtcm(0, tcm_idx);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Delete ACL TRTCM(%u): %s\n", tcm_idx, air_error_getString(ret));
+ }
+ else if(0 == argc)
+ {
+ /* acl clear trtcm */
+ ret = air_acl_clearTrtcm(0);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Clear ACL TRTCM: %s\n", air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclPortEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi=0;
+ UI32_T port = 0;
+ BOOL_T en;
+
+ if(2 == argc)
+ {
+ /* acl set portEn <port(0..6)> <en(1:En,0:Dis)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ en = _strtoul(argv[argi++], NULL, 2);
+ ret = air_acl_setPortEnable(0, port, en);
+ AIR_PRINT("Set Port:%u ACL function ", port);
+ }
+ else if(1 == argc)
+ {
+ /* acl get portEn <port(0..6)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getPortEnable(0, port, &en);
+ AIR_PRINT("Get Port:%u ACL function ", port);
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT(": %s\n", (TRUE == en)?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclDropEn(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi=0;
+ UI32_T port = 0;
+ BOOL_T en;
+
+ if(2 == argc)
+ {
+ /* acl set dropEn <port(0..6)> <en(1:En,0:Dis)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ en = _strtoul(argv[argi++], NULL, 2);
+ ret = air_acl_setDropEnable(0, port, en);
+ AIR_PRINT("Set ACL Drop precedence ");
+ }
+ else if(1 == argc)
+ {
+ /* acl set dropEn <port(0..6)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getDropEnable(0, port, &en);
+ AIR_PRINT("Get ACL Drop precedence ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("(Port %u):%s\n",
+ port,
+ (TRUE == en)?"Enable":"Disable");
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclDropThrsh(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi=0;
+ UI32_T port = 0;
+ AIR_ACL_DP_COLOR_T color;
+ UI8_T queue;
+ UI32_T high, low;
+ C8_T dp_color[AIR_ACL_DP_COLOR_LAST][7] =
+ {
+ "Green",
+ "Yellow",
+ "Red"
+ };
+
+ if(5 == argc)
+ {
+ /* acl set dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <high(0..2047)> <low(0..2047) */
+ port = _strtoul(argv[argi++], NULL, 0);
+ color = _strtoul(argv[argi++], NULL, 0);
+ queue = _strtoul(argv[argi++], NULL, 0);
+ high = _strtoul(argv[argi++], NULL, 0);
+ low = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_setDropThreshold(0, port, color, queue, high, low);
+ AIR_PRINT("Set ACL Drop precedence ");
+ }
+ else if(3 == argc)
+ {
+ /* acl get dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ color = _strtoul(argv[argi++], NULL, 0);
+ queue = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getDropThreshold(0, port, color, queue, &high, &low);
+ AIR_PRINT("Get ACL Drop precedence ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("(Port %u, color:%s, queue:%u):\n",
+ port,
+ dp_color[color],
+ queue);
+ AIR_PRINT("\tHigh Threshold :%u\n", high);
+ AIR_PRINT("\tLow Threshold :%u\n", low);
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclDropPbb(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi=0;
+ UI32_T port = 0;
+ AIR_ACL_DP_COLOR_T color;
+ UI8_T queue;
+ UI32_T pbb;
+ C8_T dp_color[AIR_ACL_DP_COLOR_LAST][7] =
+ {
+ "Green",
+ "Yellow",
+ "Red"
+ };
+
+ if(4 == argc)
+ {
+ /* acl set dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <probability(0..1023) */
+ port = _strtoul(argv[argi++], NULL, 0);
+ color = _strtoul(argv[argi++], NULL, 0);
+ queue = _strtoul(argv[argi++], NULL, 0);
+ pbb = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_setDropProbability(0, port, color, queue, pbb);
+ AIR_PRINT("Set ACL Drop precedence ");
+ }
+ else if(3 == argc)
+ {
+ /* acl get dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> */
+ port = _strtoul(argv[argi++], NULL, 0);
+ color = _strtoul(argv[argi++], NULL, 0);
+ queue = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getDropProbability(0, port, color, queue, &pbb);
+ AIR_PRINT("Get ACL Drop precedence ");
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(ret == AIR_E_OK)
+ {
+ AIR_PRINT("(Port %u, color:%s, queue %u):\n",
+ port,
+ dp_color[color],
+ queue);
+ AIR_PRINT("\tDrop probability:%u(unit=1/1023)\n", pbb);
+ }
+ else
+ {
+ AIR_PRINT("Fail!\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclMeter(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T argi = 0;
+ UI32_T meter_idx, state, rate;
+
+ if(3 == argc)
+ {
+ /* acl set meter <idx(0..31)> <en(1:En,0:Dis)> <rate(0..65535)>
+ Note: Limit rate = rate * 64Kbps */
+ meter_idx = _strtoul(argv[argi++], NULL, 0);
+ state = _strtoul(argv[argi++], NULL, 2);
+ rate = _strtoul(argv[argi++], NULL, 0);
+
+ ret = air_acl_setMeterTable(0, meter_idx, state, rate);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Set ACL Meter(%u): %s\n", meter_idx, air_error_getString(ret));
+ }
+ else if(1 == argc)
+ {
+ /* acl get meter <idx(0..31)> */
+ meter_idx = _strtoul(argv[argi++], NULL, 0);
+ ret = air_acl_getMeterTable(0, meter_idx, &state, &rate);
+ if(ret < AIR_E_LAST)
+ AIR_PRINT("Get ACL Meter(%u): %s\n", meter_idx, air_error_getString(ret));
+ }
+ else
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK == ret)
+ {
+ AIR_PRINT("\t State: %s\n", (TRUE == state)?"Enable":"Disable");
+ if(TRUE == state)
+ {
+ AIR_PRINT("\t Rate : %u(unit:64Kbps)\n", rate);
+ }
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclDump(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T i, cnt = 0;
+ AIR_ACL_CTRL_T ctrl;
+
+ if(0 != argc)
+ {
+ AIR_PRINT("Unrecognized command.\n");
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ for(i=0; i<ACL_MAX_RULE_NUM; i++)
+ {
+ memset(&ctrl, 0, sizeof(AIR_ACL_CTRL_T));
+ ret = air_acl_getRuleCtrl(0, i, &ctrl);
+ if(AIR_E_OK == ret)
+ {
+ if(TRUE == ctrl.rule_en)
+ {
+ cnt++;
+ AIR_PRINT("\t Entry-%d vaild\n", i);
+ }
+ }
+ }
+ if(0 == cnt)
+ {
+ AIR_PRINT("\t No entry vaild\n");
+ }
+
+ return ret;
+}
+
+static AIR_ERROR_NO_T
+doAclSet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(aclSetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doAclGet(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(aclGetCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doAclDel(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(aclDelCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doAclClear(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(aclClearCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+doAcl(
+ UI32_T argc,
+ C8_T *argv[])
+{
+ return subcmd(aclCmds, argc, argv);
+}
+
+static AIR_ERROR_NO_T
+subcmd(
+ const AIR_CMD_T tab[],
+ UI32_T argc,
+ C8_T *argv[])
+{
+ const AIR_CMD_T *cmdp;
+ I32_T found = 0;
+ I32_T i, len;
+
+ if (argc < 1)
+ {
+ goto print_out_cmds;
+ }
+
+ for (cmdp = tab; cmdp->name != NULL; cmdp++)
+ {
+ if (strlen(argv[0]) == strlen(cmdp->name))
+ {
+ if (strncmp(argv[0], cmdp->name, strlen(argv[0])) == 0)
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if(!found)
+ {
+ C8_T buf[66];
+
+print_out_cmds:
+ AIR_PRINT("valid subcommands:\n");
+ memset(buf, ' ', sizeof(buf));
+ buf[64] = '\n';
+ buf[65] = '\0';
+
+ for (i=0, cmdp = tab; cmdp->name != NULL; cmdp++)
+ {
+ len = strlen(cmdp->name);
+ strncpy(&buf[i*16], cmdp->name, (len > 16) ? 16 : len);
+ if(3 == i)
+ {
+ AIR_PRINT("%s\n", buf);
+ memset(buf, ' ', sizeof(buf));
+ buf[64] = '\n';
+ buf[65] = '\0';
+ }
+ i = (i + 1) % 4;
+ }
+
+ if (0 != i)
+ AIR_PRINT("%s\n", buf);
+
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if (CMD_NO_PARA == cmdp->argc_min)
+ {
+ if (argc != 1)
+ {
+ if (cmdp->argc_errmsg != NULL)
+ {
+ AIR_PRINT("Usage: %s\n", cmdp->argc_errmsg);
+ }
+
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+ else if (CMD_VARIABLE_PARA == cmdp->argc_min)
+ {
+ if (argc < 3)
+ {
+ if (cmdp->argc_errmsg != NULL)
+ {
+ AIR_PRINT("Usage: %s\n", cmdp->argc_errmsg);
+ }
+
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ if ((argc <= cmdp->argc_min) || ((cmdp->argc_min != 0) && (argc != (cmdp->argc_min + 1))))
+ {
+ if (cmdp->argc_errmsg != NULL)
+ {
+ AIR_PRINT("Usage: %s\n", cmdp->argc_errmsg);
+ }
+
+ return AIR_E_BAD_PARAMETER;
+ }
+ }
+
+ if (cmdp->func)
+ {
+ argc--;
+ argv++;
+ return (*cmdp->func)(argc, argv);
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_parse_cmd
+ * PURPOSE:
+ * This function is used process diagnostic cmd
+ * INPUT:
+ * argc -- parameter number
+ * argv -- parameter strings
+ * OUTPUT:
+ * None
+ * RETURN:
+ * NPS_E_OK -- Successfully read the data.
+ * NPS_E_OTHERS -- Failed to read the data.
+ * NOTES:
+ *
+ */
+AIR_ERROR_NO_T
+air_parse_cmd(
+ const UI32_T argc,
+ const C8_T **argv)
+{
+ return subcmd(Cmds, argc, (C8_T **)argv);
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_diag.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_diag.c
new file mode 100644
index 0000000..2f89ddf
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_diag.c
@@ -0,0 +1,410 @@
+/* FILE NAME: air_diag.c
+ * PURPOSE:
+ * Define the diagnostic function in AIR SDK.
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+/* FUNCTION NAME: air_diag_setTxComplyMode
+ * PURPOSE:
+ * Set Ethernet TX Compliance mode.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Testing mode of Ethernet TX Compliance
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ */
+AIR_ERROR_NO_T
+air_diag_setTxComplyMode(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_DIAG_TXCOMPLY_MODE_T mode)
+{
+ UI32_T page = 0;
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mode >= AIR_DIAG_TXCOMPLY_MODE_LAST), AIR_E_BAD_PARAMETER);
+
+ /* Backup page of CL22 */
+ aml_readPhyReg(unit, port, PHY_PAGE, &page);
+
+ switch(mode)
+ {
+ case AIR_DIAG_TXCOMPLY_MODE_10M_NLP:
+ /* PHY 00h = 0x0100 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_writePhyReg(unit, port, PHY_MCR, MCR_MR_DUX);
+ /* PHY dev 1Eh reg 145h = 0x5010 */
+ u32dat = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x0145, u32dat);
+ /* PHY dev 1Fh reg 17Bh = 0x1177 */
+ u32dat = (CR_RG_TX_CM_10M(1) | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) | CR_DA_TX_GAIN_10M(100));
+ aml_writePhyRegCL45(unit, port, 0x1f, 0x027b, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_10M_RANDOM:
+ /* PHY 00h = 0x0100 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_writePhyReg(unit, port, PHY_MCR, MCR_MR_DUX);
+ /* PHY dev 1Eh reg 145h = 0x5010 */
+ u32dat = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x0145, u32dat);
+ /* PHY dev 1Fh reg 27Bh = 0x1177 */
+ u32dat = (CR_RG_TX_CM_10M(1) | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) | CR_DA_TX_GAIN_10M(100));
+ aml_writePhyRegCL45(unit, port, 0x1f, 0x027b, u32dat);
+ /* PHY 11dh = 0xf842 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_1);
+ u32dat = (EPG_EN | EPG_RUN | EPG_TX_DUR | EPG_PKT_LEN_10KB \
+ | EPG_DES_ADDR(1) | EPG_PL_TYP_RANDOM);
+ aml_writePhyReg(unit, port, PHY_EPG, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_10M_SINE:
+ /* PHY 00h = 0x0100 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_writePhyReg(unit, port, PHY_MCR, MCR_MR_DUX);
+ /* PHY dev 1Eh reg 145h = 0x5010 */
+ u32dat = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x0145, u32dat);
+ /* PHY dev 1Fh reg 27Bh = 0x1177 */
+ u32dat = (CR_RG_TX_CM_10M(1) | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) | CR_DA_TX_GAIN_10M(100));
+ aml_writePhyRegCL45(unit, port, 0x1f, 0x027b, u32dat);
+ /* PHY dev 1Eh reg 1A3h = 0x0000 */
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x01a3, 0x0000);
+ /* PHY dev 1Eh reg 1A4h = 0x0000 */
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x01a4, 0x0000);
+ /* PHY 11dh = 0xf840 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_1);
+ u32dat = (EPG_EN | EPG_RUN | EPG_TX_DUR \
+ | EPG_PKT_LEN_10KB | EPG_DES_ADDR(1));
+ aml_writePhyReg(unit, port, PHY_EPG, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_A:
+ /* PHY 00h = 0x2100 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ u32dat = (MCR_MR_FC_SPD_INT_0 | MCR_MR_DUX);
+ aml_writePhyReg(unit, port, PHY_MCR, u32dat);
+ /* PHY dev 1Eh reg 145h = 0x5010 */
+ u32dat = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x0145, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_B:
+ /* PHY 00h = 0x2100 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ u32dat = (MCR_MR_FC_SPD_INT_0 | MCR_MR_DUX);
+ aml_writePhyReg(unit, port, PHY_MCR, u32dat);
+ /* PHY dev 1Eh reg 145h = 0x5018 */
+ u32dat = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDIX);
+ aml_writePhyRegCL45(unit, port, 0x1e, 0x0145, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM1:
+ /* PHY 09h = 0x2700 */
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ u32dat = (CR1G_TEST_TM1 | CR1G_PORT_TYPE \
+ | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+ aml_writePhyReg(unit, port, PHY_CR1G, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM2:
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ /* PHY 09h = 0x4700 */
+ u32dat = (CR1G_TEST_TM2 | CR1G_PORT_TYPE \
+ | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+ aml_writePhyReg(unit, port, PHY_CR1G, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM3:
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ /* PHY 09h = 0x6700 */
+ u32dat = (CR1G_TEST_TM3 | CR1G_PORT_TYPE \
+ | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+ aml_writePhyReg(unit, port, PHY_CR1G, u32dat);
+ break;
+ case AIR_DIAG_TXCOMPLY_MODE_1000M_TM4:
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ /* PHY 09h = 0x8700 */
+ u32dat = (CR1G_TEST_TM4 | CR1G_PORT_TYPE \
+ | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+ aml_writePhyReg(unit, port, PHY_CR1G, u32dat);
+ break;
+ default:
+ /* Unrecognized argument */
+ return AIR_E_BAD_PARAMETER;
+ }
+ /* Restore page of CL22 */
+ aml_writePhyReg(unit, port, PHY_PAGE, page);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_diag_getTxComplyMode
+ * PURPOSE:
+ * Get Ethernet TX Compliance mode.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_mode -- Testing mode of Ethernet TX Compliance
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ */
+AIR_ERROR_NO_T
+air_diag_getTxComplyMode(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_DIAG_TXCOMPLY_MODE_T *ptr_mode)
+{
+ UI32_T page = 0;
+ UI32_T curReg[4] = {0};
+ UI32_T cmpReg[4] = {0};
+ BOOL_T hit = FALSE;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mode);
+
+ /* Backup page of CL22 */
+ aml_readPhyReg(unit, port, PHY_PAGE, &page);
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_1000M_TM1 */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_CR1G, &curReg[0]);
+ cmpReg[0] = (CR1G_TEST_TM1 | CR1G_PORT_TYPE | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+
+ if( cmpReg[0] == curReg[0] )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_1000M_TM1;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_1000M_TM2 */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_CR1G, &curReg[0]);
+ cmpReg[0] = (CR1G_TEST_TM2 | CR1G_PORT_TYPE | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+
+ if( cmpReg[0] == curReg[0] )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_1000M_TM2;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_1000M_TM3 */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_CR1G, &curReg[0]);
+ cmpReg[0] = (CR1G_TEST_TM3 | CR1G_PORT_TYPE | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+
+ if( cmpReg[0] == curReg[0] )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_1000M_TM3;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_1000M_TM4 */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_CR1G, &curReg[0]);
+ cmpReg[0] = (CR1G_TEST_TM4 | CR1G_PORT_TYPE | CR1G_ADV_CAP1000_FDX | CR1G_ADV_CAP1000_HDX);
+
+ if( cmpReg[0] == curReg[0] )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_1000M_TM4;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_A */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_MCR, &curReg[0]);
+ cmpReg[0] = (MCR_MR_FC_SPD_INT_0 | MCR_MR_DUX);
+
+ aml_readPhyRegCL45(unit, port, 0x1e, 0x0145, &curReg[1]);
+ cmpReg[1] = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+
+ if( (cmpReg[0] == curReg[0]) && (cmpReg[1] == curReg[1]) )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_A;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_B */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_MCR, &curReg[0]);
+ cmpReg[0] = (MCR_MR_FC_SPD_INT_0 | MCR_MR_DUX);
+
+ aml_readPhyRegCL45(unit, port, 0x1e, 0x0145, &curReg[1]);
+ cmpReg[1] = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDIX);
+
+ if( (cmpReg[0] == curReg[0]) && (cmpReg[1] == curReg[1]) )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_100M_PAIR_B;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_10M_SINE */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_MCR, &curReg[0]);
+ cmpReg[0] = MCR_MR_DUX;
+
+ aml_readPhyRegCL45(unit, port, 0x1e, 0x0145, &curReg[1]);
+ cmpReg[1] = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+
+ aml_readPhyRegCL45(unit, port, 0x1f, 0x027b, &curReg[2]);
+ cmpReg[2] = (CR_RG_TX_CM_10M(1) \
+ | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) \
+ | CR_DA_TX_GAIN_10M(100));
+
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_1);
+ aml_readPhyReg(unit, port, PHY_EPG, &curReg[3]);
+ cmpReg[3] = (EPG_EN \
+ | EPG_RUN \
+ | EPG_TX_DUR \
+ | EPG_PKT_LEN_10KB \
+ | EPG_DES_ADDR(1));
+
+ if( (cmpReg[0] == curReg[0]) \
+ && (cmpReg[1] == curReg[1]) \
+ && (cmpReg[2] == curReg[2]) \
+ && (cmpReg[3] == curReg[3]) )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_10M_SINE;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_10M_RANDOM */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_MCR, &curReg[0]);
+ cmpReg[0] = MCR_MR_DUX;
+
+ aml_readPhyRegCL45(unit, port, 0x1e, 0x0145, &curReg[1]);
+ cmpReg[1] = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+
+ aml_readPhyRegCL45(unit, port, 0x1f, 0x027b, &curReg[2]);
+ cmpReg[2] = (CR_RG_TX_CM_10M(1) \
+ | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) \
+ | CR_DA_TX_GAIN_10M(100));
+
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_1);
+ aml_readPhyReg(unit, port, PHY_EPG, &curReg[3]);
+ cmpReg[3] = (EPG_EN \
+ | EPG_RUN \
+ | EPG_TX_DUR \
+ | EPG_PKT_LEN_10KB \
+ | EPG_DES_ADDR(1) \
+ | EPG_PL_TYP_RANDOM);
+
+ if( (cmpReg[0] == curReg[0]) \
+ && (cmpReg[1] == curReg[1]) \
+ && (cmpReg[2] == curReg[2]) \
+ && (cmpReg[3] == curReg[3]) )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_10M_RANDOM;
+ hit = TRUE;
+ }
+ }
+
+ /* Test for AIR_DIAG_TXCOMPLY_MODE_10M_NLP */
+ if( FALSE == hit )
+ {
+ aml_writePhyReg(unit, port, PHY_PAGE, PHY_PAGE_0);
+ aml_readPhyReg(unit, port, PHY_MCR, &curReg[0]);
+ cmpReg[0] = MCR_MR_DUX;
+
+ aml_readPhyRegCL45(unit, port, 0x1e, 0x0145, &curReg[1]);
+ cmpReg[1] = (FC_TDI_EN | FC_LITN_NO_COMP | FC_MDI_CO_MDI);
+
+ aml_readPhyRegCL45(unit, port, 0x1f, 0x027b, &curReg[2]);
+ cmpReg[2] = (CR_RG_TX_CM_10M(1) \
+ | CR_RG_DELAY_TX_10M(1) \
+ | CR_DA_TX_GAIN_10M_EEE(100) \
+ | CR_DA_TX_GAIN_10M(100));
+
+ if( (cmpReg[0] == curReg[0]) \
+ && (cmpReg[1] == curReg[1]) \
+ && (cmpReg[2] == curReg[2]) )
+ {
+ (*ptr_mode) = AIR_DIAG_TXCOMPLY_MODE_10M_NLP;
+ hit = TRUE;
+ }
+ }
+
+ /* Restore page of CL22 */
+ aml_writePhyReg(unit, port, PHY_PAGE, page);
+
+ if( TRUE == hit)
+ {
+ return AIR_E_OK;
+ }
+ else
+ {
+ return AIR_E_OTHERS;
+ }
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_error.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_error.c
new file mode 100644
index 0000000..3323e54
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_error.c
@@ -0,0 +1,73 @@
+/* FILE NAME: air_error.c
+ * PURPOSE:
+ * Define the software modules in AIR SDK.
+ * NOTES:
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+static C8_T *_air_error_cause[AIR_E_LAST] =
+{
+ "OK",
+ "NOT_OK",
+ "BAD_PARAMETER",
+ "TABLE_FULL",
+ "ENTRY_NOT_FOUND",
+ "ENTRY_EXISTS",
+ "NOT_SUPPORT",
+ "TIMEOUT",
+};
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+/* FUNCTION NAME: air_error_getString
+ * PURPOSE:
+ * To obtain the error string of the specified error code
+ *
+ * INPUT:
+ * The specified error code
+ * OUTPUT:
+ * None
+ * RETURN:
+ * Pointer to the target error string
+ *
+ * NOTES:
+ *
+ *
+ */
+C8_T *
+air_error_getString(
+const AIR_ERROR_NO_T cause )
+{
+ if(cause < AIR_E_LAST)
+ {
+ return _air_error_cause[cause];
+ }
+ else
+ {
+ return "";
+ }
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_init.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_init.c
new file mode 100644
index 0000000..8a4f96f
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_init.c
@@ -0,0 +1,147 @@
+/* FILE NAME: air_init.c
+ * PURPOSE:
+ * Define the initialization function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+AIR_PRINTF _ext_printf;
+AIR_UDELAY _ext_udelay;
+AIR_MALLOC _ext_malloc;
+AIR_FREE _ext_free;
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+
+/* FUNCTION NAME: air_init
+ * PURPOSE:
+ * This API is used to initialize the SDK.
+ *
+ * INPUT:
+ * unit -- The device unit
+ * ptr_init_param -- The sdk callback functions.
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_init(
+ const UI32_T unit,
+ AIR_INIT_PARAM_T *ptr_init_param)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T u32dat = 0;
+ UI8_T port = 0;
+ AIR_LED_ON_EVT_T on_evt;
+ AIR_LED_BLK_EVT_T blk_evt;
+
+ /* check point */
+ AIR_CHECK_PTR(ptr_init_param);
+
+ _ext_dev_access.read_callback = ptr_init_param->dev_access.read_callback;
+ _ext_dev_access.write_callback = ptr_init_param->dev_access.write_callback;
+ _ext_dev_access.phy_read_callback = ptr_init_param->dev_access.phy_read_callback;
+ _ext_dev_access.phy_write_callback = ptr_init_param->dev_access.phy_write_callback;
+ _ext_dev_access.phy_cl45_read_callback = ptr_init_param->dev_access.phy_cl45_read_callback;
+ _ext_dev_access.phy_cl45_write_callback = ptr_init_param->dev_access.phy_cl45_write_callback;
+ _ext_printf = ptr_init_param->printf;
+ _ext_udelay = ptr_init_param->udelay;
+ _ext_malloc = ptr_init_param->malloc;
+ _ext_free = ptr_init_param->free;
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_hw_reset
+ * PURPOSE:
+ * This API is used to reset hardware.
+ *
+ * INPUT:
+ * unit -- The device unit
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_hw_reset(
+ const UI32_T unit)
+{
+ AIR_PRINT(">>>>> enct_hw_reset\n");
+ /* Set an8855 reset pin to 0 */
+
+ /* Delay 100ms */
+
+ /* Set an8855 reset pin to 1 */
+
+ /* Delay 600ms */
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_set_gpio_pin_mux
+ * PURPOSE:
+ * This API is used to set gpio pin mux.
+ *
+ * INPUT:
+ * unit -- The device unit
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_set_gpio_pin_mux(
+ const UI32_T unit)
+{
+ AIR_PRINT(">>>>> enct_set_gpio_pin_mux\n");
+ /* Set GPIO_MODE0 */
+ /* Implementation for SLT HW */
+ aml_writeReg(unit, GPIO_MODE0, 0x11111111);
+
+ return AIR_E_OK;
+}
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_l2.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_l2.c
new file mode 100644
index 0000000..f8da749
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_l2.c
@@ -0,0 +1,1368 @@
+/* FILE NAME: air_l2.c
+ * PURPOSE:
+ * Define the layer 2 function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#define AIR_L2_DELAY_US (1000)
+#define AIR_L2_WDOG_KICK_NUM (1000)
+#define AIR_L2_FORWARD_VALUE (0xFFFFFFFF)
+#define AIR_L2_AGING_MS_CONSTANT (1024)
+#define AIR_L2_AGING_1000MS (1000)
+
+typedef enum
+{
+ AIR_L2_EXEC_FWD_CTRL_DEFAULT = 0x0,
+ AIR_L2_EXEC_FWD_CTRL_CPU_EXCLUDE = 0x4,
+ AIR_L2_EXEC_FWD_CTRL_CPU_INCLUDE = 0x5,
+ AIR_L2_EXEC_FWD_CTRL_CPU_ONLY = 0x6,
+ AIR_L2_EXEC_FWD_CTRL_DROP = 0x7,
+ AIR_L2_EXEC_FWD_CTRL_LAST
+}AIR_L2_EXEC_FWD_CTRL_T;
+
+typedef enum
+{
+ AIR_L2_MAC_MAT_MAC,
+ AIR_L2_MAC_MAT_DYNAMIC_MAC,
+ AIR_L2_MAC_MAT_STATIC_MAC,
+ AIR_L2_MAC_MAT_MAC_BY_VID,
+ AIR_L2_MAC_MAT_MAC_BY_FID,
+ AIR_L2_MAC_MAT_MAC_BY_PORT,
+ AIR_L2_MAC_MAT_MAC_BY_LAST
+}AIR_L2_MAC_MAT_T;
+
+/* L2 MAC table multi-searching */
+typedef enum
+{
+ AIR_L2_MAC_MS_START, /* Start search */
+ AIR_L2_MAC_MS_NEXT, /* Next search */
+ AIR_L2_MAC_MS_LAST
+}AIR_L2_MAC_MS_T;
+
+typedef enum
+{
+ AIR_L2_MAC_TB_TY_MAC,
+ AIR_L2_MAC_TB_TY_DIP,
+ AIR_L2_MAC_TB_TY_DIP_SIP,
+ AIR_L2_MAC_TB_TY_LAST
+}AIR_L2_MAC_TB_TY_T;
+
+/*
+typedef enum
+{
+ AIR_MAC_MAT_MAC,
+ AIR_MAC_MAT_DYNAMIC_MAC,
+ AIR_MAC_MAT_STATIC_MAC,
+ AIR_MAC_MAT_MAC_BY_VID,
+ AIR_MAC_MAT_MAC_BY_FID,
+ AIR_MAC_MAT_MAC_BY_PORT,
+ AIR_MAC_MAT_MAC_BY_LAST
+}AIR_MAC_MAT_T;
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+#define AIR_L2_AGING_TIME(__cnt__, __unit__) \
+ (((__cnt__) + 1) * ((__unit__) + 1) * AIR_L2_AGING_MS_CONSTANT / AIR_L2_AGING_1000MS)
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+static BOOL_T _search_end = FALSE;
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+static BOOL_T
+_cmpMac(
+ const UI8_T mac1[6],
+ const UI8_T mac2[6]);
+
+static AIR_ERROR_NO_T
+_searchMacEntry(
+ const UI32_T unit,
+ const AIR_L2_MAC_MS_T ms,
+ const AIR_L2_MAC_MAT_T multi_target,
+ UI32_T *ptr_addr,
+ UI32_T *ptr_bank);
+
+static AIR_ERROR_NO_T
+_checkL2Busy(
+ const UI32_T unit);
+
+static void
+_fill_MAC_ATA(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+static void
+_fill_MAC_ATWD(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry,
+ const BOOL_T valid);
+
+static UI32_T
+_checkL2EntryHit(
+ const UI32_T unit);
+
+static void
+_fill_MAC_ATRDS(
+ const UI32_T unit,
+ UI8_T bank);
+
+static AIR_ERROR_NO_T
+_read_MAC_ATRD(
+ const UI32_T unit,
+ AIR_MAC_ENTRY_T *ptr_mac_entry);
+
+/* FUNCTION NAME: _cmpMac
+ * PURPOSE:
+ * Compare MAC address to check whether those MAC is same.
+ *
+ * INPUT:
+ * mac1 -- 1st MAC address
+ * mac2 -- 2nd MAC address
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * TRUE
+ * FALSE
+ *
+ * NOTES:
+ * None
+ */
+static BOOL_T
+_cmpMac(
+ const UI8_T mac1[6],
+ const UI8_T mac2[6])
+{
+ UI32_T i;
+ for(i=0; i<6; i++)
+ {
+ if(mac1[i] != mac2[i])
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+/* FUNCTION NAME: _searchMacEntry
+ * PURPOSE:
+ * Search MAC Address table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ms -- _HAL_SCO_L2_MAC_MS_START: Start search command
+ * _HAL_SCO_L2_MAC_MS_NEXT: Next search command
+ * multi_target -- _HAL_SCO_L2_MAC_MAT_MAC: MAC address entries
+ * _HAL_SCO_L2_MAC_MAT_DYNAMIC_MAC: Dynamic MAC address entries
+ * _HAL_SCO_L2_MAC_MAT_STATIC_MAC: Static MAC address entries
+ * _HAL_SCO_L2_MAC_MAT_MAC_BY_VID: MAC address entries with specific CVID
+ * _HAL_SCO_L2_MAC_MAT_MAC_BY_FID: MAC address entries with specific FID
+ * _HAL_SCO_L2_MAC_MAT_MAC_BY_PORT: MAC address entries with specific port
+ * OUTPUT:
+ * ptr_addr -- MAC Table Access Index
+ * ptr_bank -- Searching result in which bank
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+static AIR_ERROR_NO_T
+_searchMacEntry(
+ const UI32_T unit,
+ const AIR_L2_MAC_MS_T ms,
+ const AIR_L2_MAC_MAT_T multi_target,
+ UI32_T *ptr_addr,
+ UI32_T *ptr_bank)
+{
+ UI32_T u32dat = 0;
+
+ u32dat = (ATC_SAT_MAC | ATC_START_BUSY);
+ if (AIR_L2_MAC_MS_START == ms)
+ {
+ /* Start search 1st valid entry */
+ u32dat |= ATC_CMD_SEARCH;
+ }
+ else if (AIR_L2_MAC_MS_NEXT == ms)
+ {
+ /* Search next valid entry */
+ u32dat |= ATC_CMD_SEARCH_NEXT;
+ }
+ else
+ {
+ /* Unknown commnad */
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ switch(multi_target)
+ {
+ case AIR_L2_MAC_MAT_MAC:
+ u32dat |= ATC_MAT_MAC;
+ break;
+ case AIR_L2_MAC_MAT_DYNAMIC_MAC:
+ u32dat |= ATC_MAT_DYNAMIC_MAC;
+ break;
+ case AIR_L2_MAC_MAT_STATIC_MAC:
+ u32dat |= ATC_MAT_STATIC_MAC;
+ break;
+ case AIR_L2_MAC_MAT_MAC_BY_VID:
+ u32dat |= ATC_MAT_MAC_BY_VID;
+ break;
+ case AIR_L2_MAC_MAT_MAC_BY_FID:
+ u32dat |= ATC_MAT_MAC_BY_FID;
+ break;
+ case AIR_L2_MAC_MAT_MAC_BY_PORT:
+ u32dat |= ATC_MAT_MAC_BY_PORT;
+ break;
+ default:
+ /* Unknown searching mode */
+ return AIR_E_BAD_PARAMETER;
+ }
+ aml_writeReg(unit, ATC, u32dat);
+ if (AIR_E_TIMEOUT == _checkL2Busy(unit))
+ {
+ return AIR_E_TIMEOUT;
+ }
+
+ aml_readReg(unit, ATC, &u32dat);
+ /* Get address */
+ (*ptr_addr) = BITS_OFF_R(u32dat, ATC_ADDR_OFFSET, ATC_ADDR_LENGTH);
+ /* Get banks */
+ (*ptr_bank) = BITS_OFF_R(u32dat, ATC_ENTRY_HIT_OFFSET, ATC_ENTRY_HIT_LENGTH);
+ if ((AIR_L2_MAX_SIZE - 1) == (*ptr_addr))
+ {
+ _search_end = TRUE;
+ }
+ else
+ {
+ _search_end = FALSE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: _checkL2Busy
+ * PURPOSE:
+ * Check BUSY bit of ATC
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+static AIR_ERROR_NO_T
+_checkL2Busy(
+ const UI32_T unit)
+{
+ UI32_T i = 0;
+ UI32_T reg_atc = 0;
+
+ /* Check BUSY bit is 0 */
+ for(i = 0; i < AIR_L2_MAX_BUSY_TIME; i++)
+ {
+ aml_readReg(unit, ATC, ®_atc);
+ if(!BITS_OFF_R(reg_atc, ATC_BUSY_OFFSET, ATC_BUSY_LENGTH))
+ {
+ break;
+ }
+ AIR_UDELAY(AIR_L2_DELAY_US);
+ }
+ if(i >= AIR_L2_MAX_BUSY_TIME)
+ {
+ return AIR_E_TIMEOUT;
+ }
+ return AIR_E_OK;
+}
+/***************************************************************/
+/* FUNCTION NAME: _fill_MAC_ATA
+ * PURPOSE:
+ * Fill register ATA for MAC Address table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- Structure of MAC Address table
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * None
+ *
+ * NOTES:
+ * None
+ */
+static void
+_fill_MAC_ATA(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ UI32_T u32dat = 0;
+ UI32_T i = 0;
+
+ /* Fill ATA1 */
+ for (i = 0; i < 4; i++)
+ {
+ u32dat |= ((UI32_T)(ptr_mac_entry->mac[i] & BITS(0,7))) << ( (3-i) * 8);
+ }
+ aml_writeReg(unit, ATA1, u32dat);
+ AIR_UDELAY(AIR_L2_DELAY_US);
+
+ /* Fill ATA2 */
+ u32dat=0;
+ for (i = 4; i < 6; i++)
+ {
+ u32dat |= ((UI32_T)(ptr_mac_entry->mac[i] & BITS(0,7))) << ( (7-i) * 8);
+ }
+ if (!(ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_STATIC))
+ {
+ /* type is dynamic */
+ u32dat |= BITS_OFF_L(1UL, ATA2_MAC_LIFETIME_OFFSET, ATA2_MAC_LIFETIME_LENGTH);
+ /* set aging counter as system aging conuter */
+ u32dat |= BITS_OFF_L(ptr_mac_entry->timer, ATA2_MAC_AGETIME_OFFSET, ATA2_MAC_AGETIME_LENGTH);
+ }
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_UNAUTH)
+ {
+ u32dat |= BITS_OFF_L(1UL, ATA2_MAC_UNAUTH_OFFSET, ATA2_MAC_UNAUTH_LENGTH);
+ }
+
+ aml_writeReg(unit, ATA2, u32dat);
+ AIR_UDELAY(AIR_L2_DELAY_US);
+}
+
+/* FUNCTION NAME: _fill_MAC_ATWD
+ * PURPOSE:
+ * Fill register ATWD for MAC Address table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- Structure of MAC Address table
+ * valid -- TRUE
+ * FALSE
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * None
+ *
+ * NOTES:
+ * None
+ */
+static void
+_fill_MAC_ATWD(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry,
+ const BOOL_T valid)
+{
+ UI32_T u32dat = 0;
+ UI32_T fwd_val = 0;
+
+ u32dat = 0;
+ /* Fill ATWD */
+ /* set valid bit */
+ if (TRUE == valid)
+ {
+ u32dat |= BITS_OFF_L(1UL, ATWD_MAC_LIVE_OFFSET, ATWD_MAC_LIVE_LENGTH);
+ }
+
+ /* set IVL */
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ u32dat |= BITS_OFF_L(1UL, ATWD_MAC_IVL_OFFSET, ATWD_MAC_IVL_LENGTH);
+ }
+ /* set VID */
+ u32dat |= BITS_OFF_L(ptr_mac_entry->cvid, ATWD_MAC_VID_OFFSET, ATWD_MAC_VID_LENGTH);
+ /* set FID */
+ u32dat |= BITS_OFF_L(ptr_mac_entry->fid, ATWD_MAC_FID_OFFSET, ATWD_MAC_FID_LENGTH);
+
+ /* Set forwarding control */
+ switch (ptr_mac_entry->sa_fwd)
+ {
+ case AIR_L2_FWD_CTRL_DEFAULT:
+ fwd_val = AIR_L2_EXEC_FWD_CTRL_DEFAULT;
+ break;
+ case AIR_L2_FWD_CTRL_CPU_INCLUDE:
+ fwd_val = AIR_L2_EXEC_FWD_CTRL_CPU_INCLUDE;
+ break;
+ case AIR_L2_FWD_CTRL_CPU_EXCLUDE:
+ fwd_val = AIR_L2_EXEC_FWD_CTRL_CPU_EXCLUDE;
+ break;
+ case AIR_L2_FWD_CTRL_CPU_ONLY:
+ fwd_val = AIR_L2_EXEC_FWD_CTRL_CPU_ONLY;
+ break;
+ case AIR_L2_FWD_CTRL_DROP:
+ fwd_val = AIR_L2_EXEC_FWD_CTRL_DROP;
+ break;
+ default:
+ break;
+ }
+ u32dat |= BITS_OFF_L(fwd_val, ATWD_MAC_FWD_OFFSET, ATWD_MAC_FWD_LENGTH);
+ aml_writeReg(unit, ATWD, u32dat);
+ AIR_UDELAY(AIR_L2_DELAY_US);
+
+ /* Fill ATWD2 */
+ u32dat = BITS_OFF_L(ptr_mac_entry->port_bitmap[0], ATWD2_MAC_PORT_OFFSET, ATWD2_MAC_PORT_LENGTH);
+ aml_writeReg(unit, ATWD2, u32dat);
+ AIR_UDELAY(AIR_L2_DELAY_US);
+}
+
+/* FUNCTION NAME: _checkL2EntryHit
+ * PURPOSE:
+ * Check entry hit of ATC
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * The entry hit bitmap
+ *
+ * NOTES:
+ * None
+ */
+static UI32_T
+_checkL2EntryHit(
+ const UI32_T unit)
+{
+ UI32_T reg_atc = 0;
+ aml_readReg(unit, ATC, ®_atc);
+ return BITS_OFF_R(reg_atc, ATC_ENTRY_HIT_OFFSET, ATC_ENTRY_HIT_LENGTH);
+}
+
+/* FUNCTION NAME: _fill_MAC_ATRDS
+ * PURPOSE:
+ * Fill register ATRDS for select bank after ATC search L2 table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * bank -- Selected index of bank
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * None
+ *
+ * NOTES:
+ * None
+ */
+static void
+_fill_MAC_ATRDS(
+ const UI32_T unit,
+ UI8_T bank)
+{
+ UI32_T u32dat = 0;
+
+ /* Fill ATRDS */
+ u32dat = BITS_OFF_L(bank, ATRD0_MAC_SEL_OFFSET, ATRD0_MAC_SEL_LENGTH);
+ aml_writeReg(unit, ATRDS, u32dat);
+ AIR_UDELAY(AIR_L2_DELAY_US);
+}
+
+/* FUNCTION NAME: _read_MAC_ATRD
+ * PURPOSE:
+ * Read register ATRD for MAC Address table.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_mac_entry -- Structure of MAC Address table
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_ENTRY_NOT_FOUND
+ *
+ * NOTES:
+ * None
+ */
+static AIR_ERROR_NO_T
+_read_MAC_ATRD(
+ const UI32_T unit,
+ AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ UI32_T u32dat = 0;
+ UI32_T i = 0;
+ BOOL_T live = FALSE;
+ UI32_T type = 0;
+ UI32_T age_unit = 0;
+ UI32_T age_cnt = 0;
+ UI32_T sa_fwd = 0;
+
+ /* Read ATRD0 */
+ aml_readReg(unit, ATRD0, &u32dat);
+ live = BITS_OFF_R(u32dat, ATRD0_MAC_LIVE_OFFSET, ATRD0_MAC_LIVE_LENGTH);
+ type = BITS_OFF_R(u32dat, ATRD0_MAC_TYPE_OFFSET, ATRD0_MAC_TYPE_LENGTH);
+ if (FALSE == live)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ if (AIR_L2_MAC_TB_TY_MAC != type)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ /* Clear table */
+ memset(ptr_mac_entry, 0, sizeof(AIR_MAC_ENTRY_T));
+
+ ptr_mac_entry->cvid = (UI16_T)BITS_OFF_R(u32dat, ATRD0_MAC_VID_OFFSET, ATRD0_MAC_VID_LENGTH);
+ ptr_mac_entry->fid = (UI16_T)BITS_OFF_R(u32dat, ATRD0_MAC_FID_OFFSET, ATRD0_MAC_FID_LENGTH);
+ if (!!BITS_OFF_R(u32dat, ATRD0_MAC_LIFETIME_OFFSET, ATRD0_MAC_LIFETIME_LENGTH))
+ {
+ ptr_mac_entry->flags |= AIR_L2_MAC_ENTRY_FLAGS_STATIC;
+ }
+ if (!!BITS_OFF_R(u32dat, ATRD0_MAC_IVL_OFFSET, ATRD0_MAC_IVL_LENGTH))
+ {
+ ptr_mac_entry->flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ }
+ if (!!BITS_OFF_R(u32dat, ATRD1_MAC_UNAUTH_OFFSET, ATRD1_MAC_UNAUTH_LENGTH))
+ {
+ ptr_mac_entry->flags |= AIR_L2_MAC_ENTRY_FLAGS_UNAUTH;
+ }
+
+ /* Get the L2 MAC aging unit */
+ aml_readReg(unit, AAC, &u32dat);
+ age_unit = BITS_OFF_R(u32dat, AAC_AGE_UNIT_OFFSET, AAC_AGE_UNIT_LENGTH);
+
+ /* Read ATRD1 */
+ aml_readReg(unit, ATRD1, &u32dat);
+ for (i = 4; i < 6; i++)
+ {
+ ptr_mac_entry->mac[i] = BITS_OFF_R(u32dat, (7 - i)*8, 8);
+ }
+ /* Aging time */
+ age_cnt = BITS_OFF_R(u32dat, ATRD1_MAC_AGETIME_OFFSET, ATRD1_MAC_AGETIME_LENGTH);
+ ptr_mac_entry->timer = AIR_L2_AGING_TIME(age_cnt, age_unit);
+ /* SA forwarding */
+ sa_fwd = BITS_OFF_R(u32dat, ATRD1_MAC_FWD_OFFSET, ATRD1_MAC_FWD_LENGTH);
+ switch (sa_fwd)
+ {
+ case AIR_L2_EXEC_FWD_CTRL_DEFAULT:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_DEFAULT;
+ break;
+ case AIR_L2_EXEC_FWD_CTRL_CPU_INCLUDE:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_CPU_INCLUDE;
+ break;
+ case AIR_L2_EXEC_FWD_CTRL_CPU_EXCLUDE:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_CPU_EXCLUDE;
+ break;
+ case AIR_L2_EXEC_FWD_CTRL_CPU_ONLY:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_CPU_ONLY;
+ break;
+ case AIR_L2_EXEC_FWD_CTRL_DROP:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_DROP;
+ break;
+ default:
+ ptr_mac_entry->sa_fwd = AIR_L2_FWD_CTRL_DEFAULT;
+ break;
+ }
+
+ /* Read ATRD2 */
+ aml_readReg(unit, ATRD2, &u32dat);
+ for (i = 0; i < 4; i++)
+ {
+ ptr_mac_entry->mac[i] = BITS_OFF_R(u32dat, (3 - i)*8, 8);
+ }
+
+ /* Read ATRD3 */
+ aml_readReg(unit, ATRD3, &u32dat);
+ ptr_mac_entry->port_bitmap[0] = BITS_OFF_R(u32dat, ATRD3_MAC_PORT_OFFSET, ATRD3_MAC_PORT_LENGTH);
+
+ return AIR_E_OK;
+}
+
+static AIR_ERROR_NO_T _mac_entry_init(AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ AIR_CHECK_PTR(ptr_mac_entry);
+ memset(ptr_mac_entry->mac, 0, sizeof(ptr_mac_entry->mac));
+ ptr_mac_entry->cvid = 0;
+ ptr_mac_entry->fid = 0;
+ ptr_mac_entry->flags = 0;
+ ptr_mac_entry->port_bitmap[0] = 0;
+ ptr_mac_entry->sa_fwd = 0;
+ ptr_mac_entry->timer = 0;
+ return AIR_E_OK;
+}
+/* FUNCTION NAME: air_l2_addMacAddr
+ * PURPOSE:
+ * Add or set a L2 unicast MAC address entry.
+ * If the address entry doesn't exist, it will add the entry.
+ * If the address entry already exists, it will set the entry
+ * with user input value.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- Structure of MAC Address table
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TABLE_FULL
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_addMacAddr(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ UI32_T u32dat = 0;
+ UI32_T reg_aac = 0;
+ AIR_MAC_ENTRY_T set_mac_entry;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mac_entry);
+ AIR_PARAM_CHK(((ptr_mac_entry->port_bitmap[0] & AIR_ALL_PORT_BITMAP) == 0), AIR_E_BAD_PARAMETER);
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->cvid < 1) || (ptr_mac_entry->cvid > 4095)), AIR_E_BAD_PARAMETER);
+ }
+ else
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->fid > (AIR_STP_FID_NUMBER - 1))), AIR_E_BAD_PARAMETER);
+ }
+ _mac_entry_init(&set_mac_entry);
+ /* Set the target MAC entry as setting entry no mater the hash addrees is existed or not */
+ memcpy(&set_mac_entry, ptr_mac_entry, sizeof(AIR_MAC_ENTRY_T));
+ /* Translate port bitmap type */
+ /* set aging counter as system aging conuter */
+ aml_readReg(unit, AAC, ®_aac);
+ set_mac_entry.timer = BITS_OFF_R(reg_aac, AAC_AGE_CNT_OFFSET, AAC_AGE_CNT_LENGTH);
+
+ /* Fill MAC address entry */
+ _fill_MAC_ATA(unit, &set_mac_entry);
+ _fill_MAC_ATWD(unit, &set_mac_entry, TRUE);
+
+ /* Write data by ATC */
+ u32dat = (ATC_SAT_MAC | ATC_CMD_WRITE | ATC_START_BUSY);
+ aml_writeReg(unit, ATC, u32dat);
+ if (AIR_E_TIMEOUT == _checkL2Busy(unit))
+ {
+ return AIR_E_TIMEOUT;
+ }
+ if ( !_checkL2EntryHit(unit))
+ {
+ return AIR_E_TABLE_FULL;
+ }
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_delMacAddr
+ * PURPOSE:
+ * Delete a L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_delMacAddr(
+ const UI32_T unit,
+ const AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ UI32_T u32dat = 0;
+ AIR_MAC_ENTRY_T del_mac_entry;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mac_entry);
+ //AIR_PARAM_CHK(((ptr_mac_entry->port_bitmap[0] & AIR_ALL_PORT_BITMAP) == 0), AIR_E_BAD_PARAMETER);
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->cvid < 1) || (ptr_mac_entry->cvid > 4095)), AIR_E_BAD_PARAMETER);
+ }
+ else
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->fid > (AIR_STP_FID_NUMBER - 1))), AIR_E_BAD_PARAMETER);
+ }
+ _mac_entry_init(&del_mac_entry);
+ memcpy(&del_mac_entry, ptr_mac_entry, sizeof(AIR_MAC_ENTRY_T));
+
+ /* Fill MAC address entry */
+ _fill_MAC_ATA(unit, &del_mac_entry);
+ _fill_MAC_ATWD(unit, &del_mac_entry, FALSE);
+
+ /* Write data by ATC to delete entry */
+ u32dat = (ATC_SAT_MAC | ATC_CMD_WRITE | ATC_START_BUSY);
+ aml_writeReg(unit, ATC, u32dat);
+ if (AIR_E_TIMEOUT == _checkL2Busy(unit))
+ {
+ return AIR_E_TIMEOUT;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_getMacBucketSize
+ * PURPOSE:
+ * Get the bucket size of one MAC address set when searching L2
+ * table.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * ptr_size -- The bucket size
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getMacBucketSize(
+ const UI32_T unit,
+ UI32_T *ptr_size)
+{
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_size);
+
+ /* Access regiser */
+ (*ptr_size) = AIR_L2_MAC_SET_NUM;
+
+ return AIR_E_OK;
+}
+
+
+/* FUNCTION NAME: air_l2_getMacAddr
+ * PURPOSE:
+ * Get a L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * ptr_count -- The number of returned MAC entries
+ * ptr_mac_entry -- Structure of MAC Address table for
+ * searching result.
+ * The size of ptr_mac_entry depends
+ * on the maximun number of bank.
+ * The memory size should greater than
+ * ((# of Bank) * (Size of entry
+ * structure))
+ * AIR_MAC_ENTRY_T
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * AIR_E_TIMEOUT -- Timeout error.
+ * AIR_E_ENTRY_NOT_FOUND -- Entry is not found.
+ * NOTES:
+ * If the parameter:mac in input argument ptr_mac_entry[0] is
+ * empty. It means to search the first valid MAC address entry
+ * in MAC address table. Otherwise, to search the specific MAC
+ * address entry in input argument ptr_mac_entry[0].
+ * Input argument ptr_mac_entry[0] needs include mac, ivl and
+ * (fid or cvid) depends on ivl.
+ * If argument ivl is TRUE, cvid is necessary, or fid is.
+ */
+AIR_ERROR_NO_T
+air_l2_getMacAddr(
+ const UI32_T unit,
+ UI8_T *ptr_count,
+ AIR_MAC_ENTRY_T *ptr_mac_entry)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T i = 0;
+ BOOL_T is_mac_empty = TRUE;
+ BOOL_T found_target = FALSE;
+ AIR_MAC_ENTRY_T mt_read;
+ UI32_T addr = 0;
+ UI32_T banks = 0;
+ AIR_L2_MAC_MAT_T mat = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mac_entry);
+ //AIR_PARAM_CHK(((ptr_mac_entry->port_bitmap[0] & AIR_ALL_PORT_BITMAP) == 0), AIR_E_BAD_PARAMETER);
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->cvid < 1) || (ptr_mac_entry->cvid > 4095)), AIR_E_BAD_PARAMETER);
+ }
+ else
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->fid > (AIR_STP_FID_NUMBER - 1))), AIR_E_BAD_PARAMETER);
+ }
+ _mac_entry_init(&mt_read);
+ /* Check MAC Address field of input data */
+ for (i = 0; i < 6; i++)
+ {
+ if (0 != ptr_mac_entry->mac[i])
+ {
+ is_mac_empty = FALSE;
+ break;
+ }
+ }
+
+ (*ptr_count) = 0;
+ if (FALSE == is_mac_empty)
+ {
+ /* MAC address isn't empty, means to search a specific MAC entry */
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ mat = AIR_L2_MAC_MAT_MAC_BY_VID;
+ }
+ else
+ {
+ mat = AIR_L2_MAC_MAT_MAC_BY_FID;
+ }
+ _fill_MAC_ATA(unit, ptr_mac_entry);
+ _fill_MAC_ATWD(unit, ptr_mac_entry, TRUE);
+
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_START, mat, &addr, &banks);
+
+ while(AIR_E_OK == rc)
+ {
+ AIR_PRINT("banks=(%d)\n", banks);
+ if (0 == banks)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ for (i = 0; i < AIR_L2_MAC_SET_NUM; i++)
+ {
+ if (!!BITS_OFF_R(banks, i, 1))
+ {
+ /* Found a valid MAC entry */
+ /* Select bank */
+ _fill_MAC_ATRDS(unit, i);
+
+ /* Read MAC entry */
+ memset(&mt_read, 0, sizeof(AIR_MAC_ENTRY_T));
+ rc = _read_MAC_ATRD(unit, &mt_read);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ continue;
+ }
+ if (TRUE == _cmpMac(ptr_mac_entry->mac, mt_read.mac))
+ {
+ /* The found MAC is the target, restore data and leave */
+ memcpy(ptr_mac_entry, &mt_read, sizeof(AIR_MAC_ENTRY_T));
+ /* Translate port bitmap type */
+ found_target = TRUE;
+ (*ptr_count)++;
+ break;
+ }
+ }
+ }
+
+ if ( TRUE == found_target)
+ {
+ break;
+ }
+
+ /* The found MAC isn't the target, keep searching or leave
+ * when found the last entry */
+ if (TRUE == _search_end)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ else
+ {
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_NEXT, mat, &addr, &banks);
+ }
+ }
+ return rc;
+ }
+ else
+ {
+ /* MAC address is empty, means to search the 1st MAC entry */
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_START, AIR_L2_MAC_MAT_MAC, &addr, &banks);
+
+ switch(rc)
+ {
+ case AIR_E_OK:
+ /* Searching bank and read data */
+ AIR_PRINT("banks=(%d)\n", banks);
+ if (0 == banks)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ for (i = 0; i < AIR_L2_MAC_SET_NUM; i++)
+ {
+ if (!!BITS_OFF_R(banks, i, 1))
+ {
+ /* Found a valid MAC entry */
+ /* Select bank */
+ _fill_MAC_ATRDS(unit, i);
+
+ /* Read MAC entry */
+ memset(&mt_read, 0, sizeof(AIR_MAC_ENTRY_T));
+ rc = _read_MAC_ATRD(unit, &mt_read);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ continue;
+ }
+ memcpy(&ptr_mac_entry[(*ptr_count)], &mt_read, sizeof(AIR_MAC_ENTRY_T));
+ /* Translate port bitmap type */
+ (*ptr_count)++;
+ }
+ }
+ return AIR_E_OK;
+ case AIR_E_TIMEOUT:
+ /* Searching over time */
+ return AIR_E_TIMEOUT;
+ default:
+ AIR_PRINT("rc=(%d)\n", rc);
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ }
+}
+
+/* FUNCTION NAME: air_l2_getNextMacAddr
+ * PURPOSE:
+ * Get the next L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptr_mac_entry -- The structure of MAC Address table
+ *
+ * OUTPUT:
+ * ptr_count -- The number of returned MAC entries
+ * ptr_mac_entry -- Structure of MAC Address table for searching result.
+ * The size of ptr_mac_entry depends on the max. number of bank.
+ * The memory size should greater than ((# of Bank) * (Table size))
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ * AIR_E_ENTRY_NOT_FOUND
+ * NOTES:
+ * If the parameter:mac in input argument ptr_mac_entry[0] is empty.
+ * It means to search the next valid MAC address entries of last searching result.
+ * Otherwise, to search the next valid MAC address entry of the specific MAC address
+ * entry in input argument ptr_mac_entry[0].
+ * Input argument ptr_mac_entry[0] needs include mac, ivl and (fid or cvid) depends on ivl.
+ * If argument ivl is TRUE, cvid is necessary, or fid is.
+ */
+AIR_ERROR_NO_T
+air_l2_getNextMacAddr(
+ const UI32_T unit,
+ UI8_T *ptr_count,
+ AIR_MAC_ENTRY_T *ptr_mac_entry)
+
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T i = 0;
+ BOOL_T is_mac_empty = TRUE;
+ BOOL_T found_target = FALSE;
+ AIR_MAC_ENTRY_T mt_read;
+ UI32_T addr = 0;
+ UI32_T banks = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mac_entry);
+ //AIR_PARAM_CHK(((ptr_mac_entry->port_bitmap[0] & AIR_ALL_PORT_BITMAP) == 0), AIR_E_BAD_PARAMETER);
+ if (ptr_mac_entry->flags & AIR_L2_MAC_ENTRY_FLAGS_IVL)
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->cvid < 1) || (ptr_mac_entry->cvid > 4095)), AIR_E_BAD_PARAMETER);
+ }
+ else
+ {
+ AIR_PARAM_CHK(((ptr_mac_entry->fid > (AIR_STP_FID_NUMBER - 1))), AIR_E_BAD_PARAMETER);
+ }
+ _mac_entry_init(&mt_read);
+ /* If found the lastest entry last time, we couldn't keep to search the next entry */
+ if(TRUE == _search_end)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+
+ /* Check MAC Address field of input data */
+ for (i = 0; i < 6; i++)
+ {
+ if (0 != ptr_mac_entry->mac[i])
+ {
+ is_mac_empty = FALSE;
+ break;
+ }
+ }
+ (*ptr_count)=0;
+
+ if (FALSE == is_mac_empty)
+ {
+ /* MAC address isn't empty, means to search the next entries of input MAC Address */
+ /* Search the target MAC entry */
+ _fill_MAC_ATA(unit, ptr_mac_entry);
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_START, AIR_L2_MAC_MAT_MAC, &addr, &banks);
+ while(AIR_E_OK == rc)
+ {
+ AIR_PRINT("banks=(%d)\n", banks);
+ if (0 == banks)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ for (i = 0; i < AIR_L2_MAC_SET_NUM; i++)
+ {
+ if (!!BITS_OFF_R(banks, i, 1))
+ {
+ /* Found a valid MAC entry */
+ /* Select bank */
+ _fill_MAC_ATRDS(unit, i);
+
+ /* Read MAC entry */
+ memset(&mt_read, 0, sizeof(AIR_MAC_ENTRY_T));
+ rc = _read_MAC_ATRD(unit, &mt_read);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ continue;
+ }
+ if (TRUE == _cmpMac(ptr_mac_entry->mac, mt_read.mac))
+ {
+ /* The found MAC is the target, restore data and leave */
+ found_target = TRUE;
+ break;
+ }
+ }
+ }
+
+ if ( TRUE == found_target)
+ {
+ break;
+ }
+
+ /* The found MAC isn't the target, keep searching or leave
+ * when found the last entry */
+ if (TRUE == _search_end)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ else
+ {
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_NEXT, AIR_L2_MAC_MAT_MAC, &addr, &banks);
+ }
+ }
+
+ if ( FALSE == found_target )
+ {
+ /* Entry not bank */
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ else
+ {
+ /* Found the target MAC entry, and try to search the next address */
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_NEXT, AIR_L2_MAC_MAT_MAC, &addr, &banks);
+ if (AIR_E_OK == rc)
+ {
+ AIR_PRINT("banks=(%d)\n", banks);
+ if (0 == banks)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ for (i = 0; i < AIR_L2_MAC_SET_NUM; i++)
+ {
+ if (!!BITS_OFF_R(banks, i, 1))
+ {
+ /* Found a valid MAC entry */
+ /* Select bank */
+ _fill_MAC_ATRDS(unit, i);
+
+ /* Read MAC entry */
+ memset(&mt_read, 0, sizeof(AIR_MAC_ENTRY_T));
+ rc = _read_MAC_ATRD(unit, &mt_read);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ continue;
+ }
+ memcpy(&ptr_mac_entry[(*ptr_count)], &mt_read, sizeof(AIR_MAC_ENTRY_T));
+ /* Translate port bitmap type */
+ (*ptr_count)++;
+ }
+ }
+ return AIR_E_OK;
+ }
+ else
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ }
+ }
+ else
+ {
+ /* MAC address is empty, means to search next entry */
+ rc = _searchMacEntry(unit, AIR_L2_MAC_MS_NEXT, AIR_L2_MAC_MAT_MAC, &addr, &banks);
+ if (AIR_E_OK == rc)
+ {
+ AIR_PRINT("banks=(%d)\n", banks);
+ if (0 == banks)
+ {
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ for (i = 0; i < AIR_L2_MAC_SET_NUM; i++)
+ {
+ if (!!BITS_OFF_R(banks, i, 1))
+ {
+ /* Found a valid MAC entry */
+ /* Select bank */
+ _fill_MAC_ATRDS(unit, i);
+
+ /* Read MAC entry */
+ memset(&mt_read, 0, sizeof(AIR_MAC_ENTRY_T));
+ rc = _read_MAC_ATRD(unit, &mt_read);
+ if (AIR_E_OK != rc)
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ continue;
+ }
+ memcpy(&ptr_mac_entry[(*ptr_count)], &mt_read, sizeof(AIR_MAC_ENTRY_T));
+ /* Translate port bitmap type */
+ (*ptr_count)++;
+ }
+ }
+ return AIR_E_OK;
+ }
+ else
+ {
+ AIR_PRINT("rc=(%d)\n", rc);
+ return AIR_E_ENTRY_NOT_FOUND;
+ }
+ }
+}
+
+/* FUNCTION NAME: air_l2_clearMacAddr
+ * PURPOSE:
+ * Clear all L2 unicast MAC address entry.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_clearMacAddr(
+ const UI32_T unit)
+{
+ UI32_T u32dat = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ /* Write data by ATC to clear all MAC address entries */
+ u32dat = (ATC_SAT_MAC | ATC_CMD_CLEAN | ATC_START_BUSY);
+ aml_writeReg(unit, ATC, u32dat);
+ if (AIR_E_TIMEOUT == _checkL2Busy(unit))
+ {
+ return AIR_E_TIMEOUT;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_setMacAddrAgeOut
+ * PURPOSE:
+ * Set the age out time of L2 MAC address entries.
+ * INPUT:
+ * unit -- Device ID
+ * age_time -- Age out time (second)
+ * (1..AIR_L2_MAC_MAX_AGE_OUT_TIME)
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_l2_setMacAddrAgeOut(
+ const UI32_T unit,
+ const UI32_T age_time)
+{
+
+ UI32_T u32dat = 0;
+ UI32_T age_cnt = 0, age_unit = 0, age_value = 0;
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((age_time > AIR_L2_MAC_MAX_AGE_OUT_TIME) || (age_time < 1)), AIR_E_BAD_PARAMETER);
+
+ /* Read the old register value */
+ aml_readReg(unit, AAC, &u32dat);
+
+ u32dat &= ~ BITS_RANGE(AAC_AGE_UNIT_OFFSET, AAC_AGE_UNIT_LENGTH);
+ u32dat &= ~ BITS_RANGE(AAC_AGE_CNT_OFFSET, AAC_AGE_CNT_LENGTH);
+
+ /* Calcuate the aging count/unit */
+ age_value = age_time * AIR_L2_AGING_1000MS / AIR_L2_AGING_MS_CONSTANT;
+ age_unit = (age_value / BIT(AAC_AGE_CNT_LENGTH) + 1);
+ age_cnt = (age_value / age_unit + 1);
+
+ /* Write the new register value */
+ u32dat |= BITS_OFF_L((age_unit - 1), AAC_AGE_UNIT_OFFSET, AAC_AGE_UNIT_LENGTH);
+ u32dat |= BITS_OFF_L((age_cnt - 1), AAC_AGE_CNT_OFFSET, AAC_AGE_CNT_LENGTH);
+
+ aml_writeReg(unit, AAC, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_getMacAddrAgeOut
+ * PURPOSE:
+ * Get the age out time of unicast MAC address.
+ * INPUT:
+ * unit -- Device ID
+ * OUTPUT:
+ * ptr_age_time -- age out time
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getMacAddrAgeOut(
+ const UI32_T unit,
+ UI32_T *ptr_age_time)
+{
+ UI32_T u32dat = 0;
+ UI32_T age_cnt = 0, age_unit = 0;
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_age_time);
+
+ /* Read data from register */
+ aml_readReg(unit, AAC, &u32dat);
+
+ age_cnt = BITS_OFF_R(u32dat, AAC_AGE_CNT_OFFSET, AAC_AGE_CNT_LENGTH);
+ age_unit = BITS_OFF_R(u32dat, AAC_AGE_UNIT_OFFSET, AAC_AGE_UNIT_LENGTH);
+ (*ptr_age_time) = AIR_L2_AGING_TIME(age_cnt, age_unit);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_setAgeEnable
+ * PURPOSE:
+ * Set aging state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_setAgeEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, AGDIS, &u32dat);
+ if (state)
+ {
+ u32dat &= ~BIT(port);
+ }
+ else
+ {
+ u32dat |= BIT(port);
+ }
+ aml_writeReg(unit, AGDIS, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_l2_getAgeEnable
+ * PURPOSE:
+ * Get age state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_l2_getAgeEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readReg(unit, AGDIS, &u32dat);
+
+ (*ptr_state) = (u32dat & BIT(port)) ? TRUE : FALSE;
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_lag.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_lag.c
new file mode 100644
index 0000000..d3f4e14
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_lag.c
@@ -0,0 +1,530 @@
+/* FILE NAME: air_lag.c
+ * PURPOSE:
+ * Define the Link Agrregation function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+/* FUNCTION NAME: air_lag_setMember
+ * PURPOSE:
+ * Set LAG member(s) for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptg_index -- Port trunk index
+ * mem_index -- Member index
+ * mem_en -- enable Member
+ * port_index -- Member port
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setMember(
+ const UI32_T unit,
+ const UI32_T ptg_index,
+ const UI32_T mem_index,
+ const UI32_T mem_en,
+ const UI32_T port_index)
+{
+ UI32_T val = 0;
+ UI32_T i = 0, offset = 0;
+ UI32_T reg = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((ptg_index >= AIR_LAG_MAX_PTG_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mem_index > AIR_LAG_MAX_MEM_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mem_en !=0 && mem_en !=1), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port_index > AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ offset = mem_index;
+ reg = (UI32_T)PTG(ptg_index);
+
+ AIR_PRINT("PTC REG:%x.\n", reg);
+
+ aml_readReg(unit,reg, &val);
+ AIR_PRINT("PTC REG val:%x.---1\n", val);
+ if(mem_en == 0)
+ {
+ val = val & ~(BIT(7 + 8*offset)); //port turnk group ptg_index; port port_index
+ }
+ else
+ {
+ val = val | (BIT(7 + 8*offset)); //port turnk group ptg_index; port port_index
+ }
+ AIR_PRINT("PTC REG val:%x.----2\n", val);
+ val = val & ~( 0x1F << 8*offset);
+ val = val | AIR_GRP_PORT(port_index,offset); //port turnk group ptg_index; port port_index
+ AIR_PRINT("PTC REG val:%x. port %d----3\n", val,port_index);
+
+ aml_writeReg(unit, reg, val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_getMember
+ * PURPOSE:
+ * Get LAG member count.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptg_index -- Port trunk index
+ *
+ * OUTPUT:
+ * member -- Member ports of one port trunk
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getMember(
+ const UI32_T unit,
+ const UI32_T ptg_index,
+ AIR_LAG_PTGINFO_T * member)
+{
+ UI32_T val0 = 0, val1 = 0, i = 0, offset = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((ptg_index >= AIR_LAG_MAX_PTG_NUM), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(member);
+ aml_readReg(unit, (UI32_T)PTG(ptg_index), &val0);
+
+ for(i = 0; i < AIR_LAG_MAX_MEM_NUM; i++){
+ member->csr_gp_enable[i] = (UI32_T)BITS_OFF_R(val0, 7 + 8*i, 1);
+ member->csr_gp_port[i] = (UI32_T)BITS_OFF_R(val0, 8*i, 5);
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_set_ptgc_state
+ * PURPOSE:
+ * set port trunk group control state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptgc_enable -- enabble or disable port trunk function
+ *
+ * OUTPUT:
+ * none
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_set_ptgc_state(
+ const UI32_T unit,
+ const BOOL_T ptgc_enable)
+{
+ /* Mistake proofing */
+ AIR_PARAM_CHK(((TRUE != ptgc_enable) && (FALSE != ptgc_enable)), AIR_E_BAD_PARAMETER);
+
+ aml_writeReg(unit, PTGC, ptgc_enable);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_get_ptgc_state
+ * PURPOSE:
+ * Get port trunk group control state.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- port trunk fucntion is enable or disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_get_ptgc_state(
+ const UI32_T unit,
+ UI32_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ AIR_CHECK_PTR(ptr_state);
+ aml_readReg(unit, PTGC, &u32dat);
+ (*ptr_state) = BITS_OFF_R(u32dat, 0, 1);
+
+ return AIR_E_OK;
+}
+
+
+/* FUNCTION NAME: air_lag_setDstInfo
+ * PURPOSE:
+ * Set information for the packet distribution.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * dstInfo -- Infomation selection of packet distribution
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setDstInfo(
+ const UI32_T unit,
+ const AIR_LAG_DISTINFO_T dstInfo)
+{
+ UI32_T val = 0;
+ aml_readReg(unit, (UI32_T)PTC, &val);
+
+ /* Set infomation control bit map */
+ val = val & ~ BITS(0,6);
+ if(dstInfo.sp)
+ {
+ val |= PTC_INFO_SEL_SP;
+ }
+ if(dstInfo.sa)
+ {
+ val |= PTC_INFO_SEL_SA;
+ }
+ if(dstInfo.da)
+ {
+ val |= PTC_INFO_SEL_DA;
+ }
+ if(dstInfo.sip)
+ {
+ val |= PTC_INFO_SEL_SIP;
+ }
+ if(dstInfo.dip)
+ {
+ val |= PTC_INFO_SEL_DIP;
+ }
+ if(dstInfo.sport)
+ {
+ val |= PTC_INFO_SEL_SPORT;
+ }
+ if(dstInfo.dport)
+ {
+ val |= PTC_INFO_SEL_DPORT;
+ }
+
+ /* Write register */
+ aml_writeReg(unit, (UI32_T)PTC, val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_getDstInfo
+ * PURPOSE:
+ * Set port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_dstInfo -- Infomation selection of packet distribution
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_TIMEOUT
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getDstInfo(
+ const UI32_T unit,
+ AIR_LAG_DISTINFO_T *ptr_dstInfo)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptr_dstInfo);
+
+ /* Get infomation control bit map */
+ aml_readReg(unit, (UI32_T)PTC, &val);
+ if(val & PTC_INFO_SEL_SP)
+ {
+ ptr_dstInfo ->sp = 1;
+ }
+ if(val & PTC_INFO_SEL_SA)
+ {
+ ptr_dstInfo ->sa = 1;
+ }
+ if(val & PTC_INFO_SEL_DA)
+ {
+ ptr_dstInfo ->da = 1;
+ }
+ if(val & PTC_INFO_SEL_SIP)
+ {
+ ptr_dstInfo ->sip = 1;
+ }
+ if(val & PTC_INFO_SEL_DIP)
+ {
+ ptr_dstInfo ->dip = 1;
+ }
+ if(val & PTC_INFO_SEL_SPORT)
+ {
+ ptr_dstInfo ->sport = 1;
+ }
+ if(val & PTC_INFO_SEL_DPORT)
+ {
+ ptr_dstInfo ->dport = 1;
+ }
+
+ return AIR_E_OK;
+}
+
+
+/* FUNCTION NAME: air_lag_setState
+ * PURPOSE:
+ * Set the enable/disable for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * hashtype -- crc32msb/crc32lsb/crc16/xor4
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_sethashtype(
+ const UI32_T unit,
+ const UI32_T hashtype)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((hashtype > 3), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, (UI32_T)PTC, &val);
+
+ val = val & ~ BITS(8,9);
+ val |= hashtype << 8;
+
+ aml_writeReg(unit, (UI32_T)PTC, val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_getState
+ * PURPOSE:
+ * Get port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * hashtype -- crc32msb/crc32lsb/crc16/xor4
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_gethashtype(
+ const UI32_T unit,
+ UI32_T *hashtype)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(hashtype);
+
+ /* Read data from register */
+ aml_readReg(unit, (UI32_T)PTC, &val);
+ (*hashtype) = BITS_OFF_R(val, 8, 9);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_setSpSel
+ * PURPOSE:
+ * Set the enable/disable for selection source port composition.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * enable -- enable or disable source port compare
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setSpSel(
+ const UI32_T unit,
+ const BOOL_T spsel_enable)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK(((TRUE != spsel_enable) && (FALSE != spsel_enable)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, (UI32_T)PTC, &val);
+ val = val & ~ BIT(20);
+ val |= spsel_enable << 20;
+ aml_writeReg(unit, (UI32_T)PTC, val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_getSpSel
+ * PURPOSE:
+ * Get selection source port composition.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_state -- source port compare is enable or disable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getSpSel(
+ const UI32_T unit,
+ UI32_T *ptr_state)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ AIR_CHECK_PTR(ptr_state);
+ aml_readReg(unit, PTC, &val);
+ (*ptr_state) = val & BIT(20);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_setPTSeed
+ * PURPOSE:
+ * Set the enable/disable for a specific LAG port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * ptseed -- port trunk rand seed
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_setPTSeed(
+ const UI32_T unit,
+ const UI32_T ptseed)
+{
+ aml_writeReg(unit, (UI32_T)PTSEED, ptseed);
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_lag_getPTSeed
+ * PURPOSE:
+ * Get port trunk hashtype.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptseed -- port trunk rand seed
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_lag_getPTSeed(
+ const UI32_T unit,
+ UI32_T *ptseed)
+{
+ UI32_T val = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptseed);
+
+ /* Read data from register */
+ aml_readReg(unit, (UI32_T)PTSEED, ptseed);
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_led.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_led.c
new file mode 100644
index 0000000..d89caa9
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_led.c
@@ -0,0 +1,528 @@
+/* FILE NAME: air_led.c
+ * PURPOSE:
+ * Define the LED function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+#define LED_SET_EVT(evt, reg, bit) \
+ do{ \
+ if( TRUE == evt) \
+ { \
+ reg |= bit; \
+ } \
+ }while(0)
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_led_setMode
+ * PURPOSE:
+ * Set the LED processing mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Setting mode of LED
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setMode(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_LED_MODE_T mode)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( mode >= AIR_LED_BLK_DUR_LAST ), AIR_E_BAD_PARAMETER );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BCR, &u32dat );
+
+ /* Set LED mode */
+ switch( mode )
+ {
+ case AIR_LED_MODE_DISABLE:
+ u32dat &= ~LED_BCR_EXT_CTRL;
+ u32dat &= ~LED_BCR_MODE_MASK;
+ u32dat |= LED_BCR_MODE_DISABLE;
+ break;
+ case AIR_LED_MODE_2LED_MODE0:
+ u32dat &= ~LED_BCR_EXT_CTRL;
+ u32dat &= ~LED_BCR_MODE_MASK;
+ u32dat |= LED_BCR_MODE_2LED;
+ break;
+ case AIR_LED_MODE_2LED_MODE1:
+ u32dat &= ~LED_BCR_EXT_CTRL;
+ u32dat &= ~LED_BCR_MODE_MASK;
+ u32dat |= LED_BCR_MODE_3LED_1;
+ break;
+ case AIR_LED_MODE_2LED_MODE2:
+ u32dat &= ~LED_BCR_EXT_CTRL;
+ u32dat &= ~LED_BCR_MODE_MASK;
+ u32dat |= LED_BCR_MODE_3LED_2;
+ break;
+ case AIR_LED_MODE_USER_DEFINE:
+ u32dat |= LED_BCR_EXT_CTRL;
+ break;
+ }
+
+ /* Write data to register */
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_BCR, u32dat );
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME:air_led_getMode
+ * PURPOSE:
+ * Get the LED processing mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_mode -- Setting mode of LED
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getMode(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_LED_MODE_T *ptr_mode)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_CHECK_PTR( ptr_mode );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BCR, &u32dat );
+
+ /* Get LED mode */
+ if( LED_BCR_EXT_CTRL & u32dat )
+ {
+ (*ptr_mode ) = AIR_LED_MODE_USER_DEFINE;
+ }
+ else
+ {
+ switch( u32dat & LED_BCR_MODE_MASK )
+ {
+ case LED_BCR_MODE_DISABLE:
+ (*ptr_mode ) = AIR_LED_MODE_DISABLE;
+ break;
+ case LED_BCR_MODE_2LED:
+ (*ptr_mode ) = AIR_LED_MODE_2LED_MODE0;
+ break;
+ case LED_BCR_MODE_3LED_1:
+ (*ptr_mode ) = AIR_LED_MODE_2LED_MODE1;
+ break;
+ case LED_BCR_MODE_3LED_2:
+ (*ptr_mode ) = AIR_LED_MODE_2LED_MODE2;
+ break;
+ default:
+ return AIR_E_OTHERS;
+ }
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_setState
+ * PURPOSE:
+ * Set the enable state for a specific LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * state -- TRUE: Enable
+ * FALSE: Disable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setState(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( entity >= MAX_NUM_LED_ENTITY ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( ( TRUE != state ) && ( FALSE != state ) ), AIR_E_BAD_PARAMETER );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), &u32dat );
+
+ /* Set LED state */
+ if( TRUE == state)
+ {
+ u32dat |= LED_ON_EN;
+ }
+ else
+ {
+ u32dat &= ~LED_ON_EN;
+ }
+
+ /* Write data to register */
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), u32dat );
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_getState
+ * PURPOSE:
+ * Get the enable state for a specific LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ *
+ * OUTPUT:
+ * ptr_state -- TRUE: Enable
+ * FALSE: Disable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getState(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ BOOL_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( entity >= MAX_NUM_LED_ENTITY ), AIR_E_BAD_PARAMETER );
+ AIR_CHECK_PTR( ptr_state );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), &u32dat );
+
+ /* Get LED state */
+ (*ptr_state) = ( LED_ON_EN & u32dat )?TRUE:FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_setUsrDef
+ * PURPOSE:
+ * Set the user-defined configuration of a speficic LED.
+ * It only work when air_led_setState() set to AIR_LED_MODE_USER_DEFINE.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * polar -- LOW: Active low
+ * HIGH: Active high
+ * on_evt -- AIR_LED_ON_EVT_T
+ * LED turns on if any event is detected
+ * blk_evt -- AIR_LED_BLK_EVT_T
+ * LED blinks blink if any event is detected
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setUsrDef(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ const BOOL_T polar,
+ const AIR_LED_ON_EVT_T on_evt,
+ const AIR_LED_BLK_EVT_T blk_evt)
+{
+ UI32_T on_reg = 0;
+ UI32_T blk_reg = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( entity >= MAX_NUM_LED_ENTITY ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( ( HIGH != polar ) && ( LOW != polar ) ), AIR_E_BAD_PARAMETER );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), &on_reg );
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BLK_CTRL(entity), &blk_reg );
+
+ /* Set LED polarity */
+ if( HIGH == polar)
+ {
+ on_reg |= LED_ON_POL;
+ }
+ else
+ {
+ on_reg &= ~LED_ON_POL;
+ }
+
+ /* Set LED On Event */
+ on_reg &= ~LED_ON_EVT_MASK;
+ LED_SET_EVT(on_evt.link_1000m, on_reg, LED_ON_EVT_LINK_1000M);
+ LED_SET_EVT(on_evt.link_100m, on_reg, LED_ON_EVT_LINK_100M);
+ LED_SET_EVT(on_evt.link_10m, on_reg, LED_ON_EVT_LINK_10M);
+ LED_SET_EVT(on_evt.link_dn, on_reg, LED_ON_EVT_LINK_DN);
+ LED_SET_EVT(on_evt.fdx, on_reg, LED_ON_EVT_FDX);
+ LED_SET_EVT(on_evt.hdx, on_reg, LED_ON_EVT_HDX);
+ LED_SET_EVT(on_evt.force, on_reg, LED_ON_EVT_FORCE);
+
+ /* Set LED Blinking Event */
+ blk_reg &= ~LED_BLK_EVT_MASK;
+ LED_SET_EVT(blk_evt.tx_act_1000m, blk_reg, LED_BLK_EVT_1000M_TX_ACT);
+ LED_SET_EVT(blk_evt.rx_act_1000m, blk_reg, LED_BLK_EVT_1000M_RX_ACT);
+ LED_SET_EVT(blk_evt.tx_act_100m, blk_reg, LED_BLK_EVT_100M_TX_ACT);
+ LED_SET_EVT(blk_evt.rx_act_100m, blk_reg, LED_BLK_EVT_100M_RX_ACT);
+ LED_SET_EVT(blk_evt.tx_act_10m, blk_reg, LED_BLK_EVT_10M_TX_ACT);
+ LED_SET_EVT(blk_evt.rx_act_10m, blk_reg, LED_BLK_EVT_10M_RX_ACT);
+ LED_SET_EVT(blk_evt.cls, blk_reg, LED_BLK_EVT_CLS);
+ LED_SET_EVT(blk_evt.rx_crc, blk_reg, LED_BLK_EVT_RX_CRC);
+ LED_SET_EVT(blk_evt.rx_idle, blk_reg, LED_BLK_EVT_RX_IDL);
+ LED_SET_EVT(blk_evt.force, blk_reg, LED_BLK_EVT_FORCE);
+
+ /* Write data to register */
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), on_reg );
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_BLK_CTRL(entity), blk_reg );
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_getUsrDef
+ * PURPOSE:
+ * Get the user-defined configuration of a speficic LED.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * entity -- Entity of LED
+ * OUTPUT:
+ * ptr_polar -- LOW: Active low
+ * HIGH: Active high
+ * ptr_on_evt -- AIR_LED_ON_EVT_T
+ * LED turns on if any event is detected
+ * ptr_blk_evt -- AIR_LED_BLK_EVT_T
+ * LED blinks if any event is detected
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getUsrDef(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T entity,
+ BOOL_T *ptr_polar,
+ AIR_LED_ON_EVT_T *ptr_on_evt,
+ AIR_LED_BLK_EVT_T *ptr_blk_evt)
+{
+ UI32_T on_reg = 0;
+ UI32_T blk_reg = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( entity >= MAX_NUM_LED_ENTITY ), AIR_E_BAD_PARAMETER );
+ AIR_CHECK_PTR( ptr_polar );
+ AIR_CHECK_PTR( ptr_on_evt );
+ AIR_CHECK_PTR( ptr_blk_evt );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_ON_CTRL(entity), &on_reg );
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BLK_CTRL(entity), &blk_reg );
+
+ /* Get LED polarity */
+ (*ptr_polar) = ( on_reg & LED_ON_POL)?TRUE:FALSE;
+
+ /* Get LED On Event */
+ ptr_on_evt ->link_1000m = (on_reg & LED_ON_EVT_LINK_1000M)?TRUE:FALSE;
+ ptr_on_evt ->link_100m = (on_reg & LED_ON_EVT_LINK_100M)?TRUE:FALSE;
+ ptr_on_evt ->link_10m = (on_reg & LED_ON_EVT_LINK_10M)?TRUE:FALSE;
+ ptr_on_evt ->link_dn = (on_reg & LED_ON_EVT_LINK_DN)?TRUE:FALSE;
+ ptr_on_evt ->fdx = (on_reg & LED_ON_EVT_FDX)?TRUE:FALSE;
+ ptr_on_evt ->hdx = (on_reg & LED_ON_EVT_HDX)?TRUE:FALSE;
+ ptr_on_evt ->force = (on_reg & LED_ON_EVT_FORCE)?TRUE:FALSE;
+
+ /* Set LED Blinking Event */
+ ptr_blk_evt ->tx_act_1000m = (blk_reg & LED_BLK_EVT_1000M_TX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->rx_act_1000m = (blk_reg & LED_BLK_EVT_1000M_RX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->tx_act_100m = (blk_reg & LED_BLK_EVT_100M_TX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->rx_act_100m = (blk_reg & LED_BLK_EVT_100M_RX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->tx_act_10m = (blk_reg & LED_BLK_EVT_10M_TX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->rx_act_10m = (blk_reg & LED_BLK_EVT_10M_RX_ACT)?TRUE:FALSE;
+ ptr_blk_evt ->cls = (blk_reg & LED_BLK_EVT_CLS)?TRUE:FALSE;
+ ptr_blk_evt ->rx_crc = (blk_reg & LED_BLK_EVT_RX_CRC)?TRUE:FALSE;
+ ptr_blk_evt ->rx_idle = (blk_reg & LED_BLK_EVT_RX_IDL)?TRUE:FALSE;
+ ptr_blk_evt ->force = (blk_reg & LED_BLK_EVT_FORCE)?TRUE:FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_setBlkTime
+ * PURPOSE:
+ * Set the Blinking duration of a speficic LED.
+ * It only work when air_led_setState() set to AIR_LED_MODE_USER_DEFINE.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * dur -- Blink duration
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * The LED control register is shared with all port on AN8855.
+ * Setting LED on any one port will also set to each other ports.
+ */
+AIR_ERROR_NO_T
+air_led_setBlkTime(
+ const UI32_T unit,
+ const UI8_T port,
+ const AIR_LED_BLK_DUR_T dur)
+{
+ UI32_T on_dur = 0;
+ UI32_T blk_dur = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_PARAM_CHK( ( dur >= AIR_LED_BLK_DUR_LAST ), AIR_E_BAD_PARAMETER );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_ON_DUR, &on_dur );
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BLK_DUR, &blk_dur );
+
+ /* Set LED Blinking duration */
+ /* Setting unit = 32ms, register unit = 32.768 us */
+ blk_dur = UNIT_LED_BLINK_DURATION << dur;
+ /* On duration should be half of blinking duration */
+ on_dur = blk_dur >> 1;
+
+ /* Write data to register */
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_ON_DUR, on_dur );
+ aml_writePhyRegCL45( unit, port, 0x1f, LED_BLK_DUR, blk_dur );
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_led_getBlkTime
+ * PURPOSE:
+ * Get the Blinking duration of a speficic LED.
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_dur -- Blink duration
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_led_getBlkTime(
+ const UI32_T unit,
+ const UI8_T port,
+ AIR_LED_BLK_DUR_T *ptr_dur)
+{
+ UI32_T blk_dur = 0;
+ UI32_T u32dat = 0;
+ I8_T i = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK( ( port >= AIR_MAX_NUM_OF_GIGA_PORTS ), AIR_E_BAD_PARAMETER );
+ AIR_CHECK_PTR( ptr_dur );
+
+ /* Read data from register */
+ aml_readPhyRegCL45( unit, port, 0x1f, LED_BLK_DUR, &blk_dur );
+
+ /* Get LED Blinking duration */
+ u32dat = blk_dur / UNIT_LED_BLINK_DURATION;
+ for(i = AIR_LED_BLK_DUR_LAST; i>=0; i--)
+ {
+ if( (u32dat >> i) & 0x1 )
+ {
+ break;
+ }
+ }
+ (*ptr_dur) = i;
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mib.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mib.c
new file mode 100644
index 0000000..67088d1
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mib.c
@@ -0,0 +1,366 @@
+/* FILE NAME: air_mib.c
+ * PURPOSE:
+ * Define the MIB counter function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+#define MIB_READ_DATA(unit, port, mib, reg, val) \
+ do{ \
+ aml_readReg(unit, MIB_##reg(port), &val ); \
+ mib -> reg = val; \
+ }while(0)
+
+
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_mib_setEnable
+ * PURPOSE:
+ * Enable or Disable mib count fucntion.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * mib_en -- enable or disable mib_en
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_setEnable(
+ const UI32_T unit,
+ const BOOL_T mib_en)
+{
+ UI32_T u32dat = 0;
+ AIR_PARAM_CHK(((TRUE != mib_en) && (FALSE != mib_en)), AIR_E_BAD_PARAMETER);
+
+ /* Write data to register */
+ aml_readReg(unit, MIB_CCR, &u32dat);
+ if(mib_en)
+ {
+ u32dat |= MIB_CCR_MIB_ENABLE;
+ }
+ else
+ {
+ u32dat &= ~MIB_CCR_MIB_ENABLE;
+ }
+ aml_writeReg(unit, MIB_CCR, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mib_getEnable
+ * PURPOSE:
+ * Enable or Disable mib count fucntion.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * mib_en -- enable or disable mib_en
+
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_getEnable(
+ const UI32_T unit,
+ BOOL_T *mib_en)
+{
+ UI32_T u32dat = 0;
+ /* Mistake proofing */
+ AIR_CHECK_PTR(mib_en);
+
+
+ /* Write data to register */
+ aml_readReg(unit, MIB_CCR, &u32dat);
+ (*mib_en) = BITS_OFF_R(u32dat, MIB_CCR_MIB_ENABLE_OFFSET, MIB_CCR_MIB_ENABLE_LENGTH);
+
+
+ return AIR_E_OK;
+}
+/* FUNCTION NAME: air_mib_clear
+ * PURPOSE:
+ * Clear all counters of all MIB counters.
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_clear(
+ const UI32_T unit)
+{
+ UI32_T u32dat = 0;
+
+ /* Write data to register */
+ aml_readReg(unit, MIB_CCR, &u32dat);
+ /* Restart MIB counter */
+ u32dat &= ~MIB_CCR_MIB_ENABLE;
+ aml_writeReg(unit, MIB_CCR, u32dat);
+ u32dat |= MIB_CCR_MIB_ENABLE;
+ aml_writeReg(unit, MIB_CCR, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_mib_clear_by_port
+ * PURPOSE:
+ * Clear all counters of all MIB counters.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- clear port number
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_clear_by_port(
+ const UI32_T unit,
+ const UI32_T port)
+{
+ /* Mistake proofing */
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+
+ /* Write data to register */
+ aml_writeReg(unit, MIB_PCLR, 1 << port);
+ aml_writeReg(unit, MIB_PCLR, 0);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mib_get
+ * PURPOSE:
+ * Get the structure of MIB counter for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_rx_mib -- MIB Counters of Rx Event
+ * ptr_tx_mib -- MIB Counters of Tx Event
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_get(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_MIB_CNT_RX_T *ptr_rx_mib,
+ AIR_MIB_CNT_TX_T *ptr_tx_mib)
+{
+ UI32_T u32dat = 0, u32dat_h = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_rx_mib);
+ AIR_CHECK_PTR(ptr_tx_mib);
+
+ /* Read data from register */
+
+ /* Read Tx MIB Counter */
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TCRC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TUPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TMPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TBPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TCEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TSCEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TMCEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TDEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TLCEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TXCEC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TPPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL64PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL65PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL128PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL256PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL512PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL1024PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TL1519PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_tx_mib, TODPC, u32dat);
+ aml_readReg(unit, MIB_TOCL(port), &u32dat);
+ aml_readReg(unit, MIB_TOCH(port), &u32dat_h);
+ ptr_tx_mib->TOC = u32dat | ((UI64_T)(u32dat_h) << 32);
+ u32dat = 0;
+ u32dat_h = 0;
+ aml_readReg(unit, MIB_TOCL2(port), &u32dat);
+ aml_readReg(unit, MIB_TOCH2(port), &u32dat_h);
+ ptr_tx_mib->TOC2 = u32dat | ((UI64_T)(u32dat_h) << 32);
+
+ /* Read Rx MIB Counter */
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RFPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RUPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RMPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RBPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RAEPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RCEPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RUSPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RFEPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, ROSPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RJEPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RPPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL64PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL65PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL128PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL256PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL512PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL1024PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RL1519PC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RCDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RIDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RADPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, FCDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, WRDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, MRDPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, SFSPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, SFTPC, u32dat);
+ MIB_READ_DATA(unit, port, ptr_rx_mib, RXC_DPC, u32dat);
+ u32dat = 0;
+ u32dat_h = 0;
+ aml_readReg(unit, MIB_ROCL(port), &u32dat);
+ aml_readReg(unit, MIB_ROCH(port), &u32dat_h);
+ ptr_rx_mib->ROC = u32dat | ((UI64_T)(u32dat_h) << 32);
+ u32dat = 0;
+ u32dat_h = 0;
+ aml_readReg(unit, MIB_ROCL2(port), &u32dat);
+ aml_readReg(unit, MIB_ROCH2(port), &u32dat_h);
+ ptr_rx_mib->ROC2 = u32dat | ((UI64_T)(u32dat_h) << 32);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mib_clearAclEvent
+ * PURPOSE:
+ * Clear all counters of ACL event
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_clearAclEvent(
+ const UI32_T unit)
+{
+ UI32_T u32dat = 0;
+
+ aml_readReg(unit, ACL_MIB_CNT_CFG, &u32dat);
+ u32dat |= CSR_ACL_MIB_CLEAR;
+ aml_writeReg(unit, ACL_MIB_CNT_CFG, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mib_getAclEvent
+ * PURPOSE:
+ * Get the total number of ACL event occurred.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * idx -- Index of ACL event
+ *
+ * OUTPUT:
+ * ptr_cnt -- The total number of ACL event occured
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mib_getAclEvent(
+ const UI32_T unit,
+ const UI32_T idx,
+ UI32_T *ptr_cnt)
+{
+ UI32_T reg = 0;
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((idx >= AIR_MIB_MAX_ACL_EVENT_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_cnt);
+
+ aml_readReg(unit, ACL_MIB_CNT_CFG, &u32dat);
+ u32dat = u32dat | (idx << CSR_ACL_MIB_SEL_OFFSET);
+ aml_writeReg(unit, ACL_MIB_CNT_CFG, u32dat);
+
+ aml_readReg(unit, ACL_MIB_CNT, &u32dat);
+ (*ptr_cnt) = u32dat;
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mirror.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mirror.c
new file mode 100644
index 0000000..00a72e4
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_mirror.c
@@ -0,0 +1,391 @@
+/* FILE NAME: air_mirror.c
+ * PURPOSE:
+ * Define the port mirror function in ECNT SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_mir_addSession
+ * PURPOSE:
+ * This API is used to add or set a mirror session.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * ptr_session -- Session information
+ * AIR_MIR_SESSION_T
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_addSession(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const AIR_MIR_SESSION_T *ptr_session)
+{
+ UI32_T regMIR = 0, regPCR = 0;
+ UI32_T dst_mac_port = 0, src_mac_port = 0;
+ BOOL_T enable=FALSE, tx_tag_enable=FALSE;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_session);
+ AIR_PARAM_CHK((ptr_session->src_port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_session->dst_port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_session->dst_port == ptr_session->src_port), AIR_E_BAD_PARAMETER);
+
+ src_mac_port = ptr_session->src_port;
+ dst_mac_port = ptr_session->dst_port;
+ /* Read MIR */
+ aml_readReg(unit, MIR, ®MIR);
+
+ /* Set mirroring port */
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_PORT_OFFSER(session_id), MIR_MIRROR_PORT_LEN);
+ regMIR |= BITS_OFF_L(dst_mac_port, MIR_MIRROR_PORT_OFFSER(session_id), MIR_MIRROR_PORT_LEN);
+
+ /* Set mirroring port tx tag state */
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG)
+ {
+ tx_tag_enable = TRUE;
+ }
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_TAG_TX_EN_OFFSER(session_id), MIR_MIRROR_TAG_TX_EN_LEN);
+ regMIR |= BITS_OFF_L(tx_tag_enable, MIR_MIRROR_TAG_TX_EN_OFFSER(session_id), MIR_MIRROR_TAG_TX_EN_LEN);
+
+ /* Set mirroring port state */
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_ENABLE)
+ {
+ enable = TRUE;
+ }
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+ regMIR |= BITS_OFF_L(enable, MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+
+ /* Write MIR */
+ aml_writeReg(unit, MIR, regMIR);
+
+ /* Read PCR */
+ aml_readReg(unit, PCR(src_mac_port), ®PCR);
+
+ /* Set mirroring source port */
+ regPCR &= ~ BIT(PCR_PORT_TX_MIR_OFFT + session_id);
+ regPCR &= ~ BIT(PCR_PORT_RX_MIR_OFFT + session_id);
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_DIR_TX)
+ {
+ regPCR |= BIT(PCR_PORT_TX_MIR_OFFT + session_id);
+ }
+
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_DIR_RX)
+ {
+ regPCR |= BIT(PCR_PORT_RX_MIR_OFFT + session_id);
+ }
+
+ /* Write PCR */
+ aml_writeReg(unit, PCR(src_mac_port), regPCR);
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_delSession
+ * PURPOSE:
+ * This API is used to delete a mirror session.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_delSession(
+ const UI32_T unit,
+ const UI32_T session_id)
+{
+ UI32_T regMIR = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+
+ /* Read MIR */
+ aml_readReg(unit, MIR, ®MIR);
+
+ /* Set mirroring port */
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_PORT_OFFSER(session_id), MIR_MIRROR_PORT_LEN);
+ regMIR |= BITS_OFF_L(AIR_DST_DEFAULT_PORT, MIR_MIRROR_PORT_OFFSER(session_id), MIR_MIRROR_PORT_LEN);
+ /* Set mirroring port tx tag state */
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_TAG_TX_EN_OFFSER(session_id), MIR_MIRROR_TAG_TX_EN_LEN);
+ /* Set mirroring port state */
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+
+ /* Write MIR */
+ aml_writeReg(unit, MIR, regMIR);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_getSession
+ * PURPOSE:
+ * This API is used to get mirror session information.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * OUTPUT:
+ * ptr_session -- The information of the session to be
+ * obtained
+ * AIR_MIR_SESSION_T
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_getSession(
+ const UI32_T unit,
+ const UI32_T session_id,
+ AIR_MIR_SESSION_T *ptr_session)
+{
+ UI32_T regMIR = 0;
+ UI32_T dst_mac_port = 0;
+ BOOL_T enable = FALSE, tx_tag_enable = FALSE;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_session);
+
+ /* Read MIR */
+ aml_readReg(unit, MIR, ®MIR);
+ /* Get mirroring port */
+ dst_mac_port = BITS_OFF_R(regMIR, MIR_MIRROR_PORT_OFFSER(session_id), MIR_MIRROR_PORT_LEN);
+ /* Get mirroring port state */
+ enable = BITS_OFF_R(regMIR, MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+ /* Get mirroring tx tag state*/
+ tx_tag_enable = BITS_OFF_R(regMIR, MIR_MIRROR_TAG_TX_EN_OFFSER(session_id), MIR_MIRROR_TAG_TX_EN_LEN);
+ ptr_session->dst_port = dst_mac_port;
+ if(enable)
+ {
+ ptr_session->flags |= AIR_MIR_SESSION_FLAGS_ENABLE;
+ }
+ if(tx_tag_enable)
+ {
+ ptr_session->flags |= AIR_MIR_SESSION_FLAGS_TX_TAG_OBEY_CFG;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_setSessionAdminMode
+ * PURPOSE:
+ * This API is used to set mirror session state.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * enable -- State of session
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_setSessionAdminMode(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const BOOL_T enable)
+{
+ UI32_T regMIR = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((enable != TRUE && enable != FALSE), AIR_E_BAD_PARAMETER);
+
+ /* Read MIR */
+ aml_readReg(unit, MIR, ®MIR);
+
+ /* Set mirroring port state */
+ regMIR &= ~ BITS_RANGE(MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+ regMIR |= BITS_OFF_L(enable, MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+
+ /* Write MIR */
+ aml_writeReg(unit, MIR, regMIR);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_getSessionAdminMode
+ * PURPOSE:
+ * This API is used to get mirror session state.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- mirror session id
+ * OUTPUT:
+ * ptr_enable -- State of session
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_getSessionAdminMode(
+ const UI32_T unit,
+ const UI32_T session_id,
+ BOOL_T *ptr_enable)
+{
+ UI32_T regMIR = 0;
+ BOOL_T enable = FALSE;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ /* Read MIR */
+ aml_readReg(unit, MIR, ®MIR);
+
+ /* Get mirroring port state */
+ enable = BITS_OFF_R(regMIR, MIR_MIRROR_EN_OFFSER(session_id), MIR_MIRROR_EN_LEN);
+
+ *ptr_enable = enable;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_setMirrorPort
+ * PURPOSE:
+ * This API is used to set mirror port mirroring type.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * ptr_session -- Session information
+ * AIR_MIR_SESSION_T
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_setMirrorPort(
+ const UI32_T unit,
+ const UI32_T session_id,
+ const AIR_MIR_SESSION_T *ptr_session)
+{
+ UI32_T regPCR = 0;
+ UI32_T src_mac_port = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_session);
+ AIR_PARAM_CHK((ptr_session->src_port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ src_mac_port = ptr_session->src_port;
+ /* Read data from register */
+ aml_readReg(unit, PCR(src_mac_port), ®PCR);
+
+ regPCR &= ~ BIT(PCR_PORT_TX_MIR_OFFT + session_id);
+ regPCR &= ~ BIT(PCR_PORT_RX_MIR_OFFT + session_id);
+
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_DIR_TX)
+ {
+ regPCR |= BIT(PCR_PORT_TX_MIR_OFFT + session_id);
+ }
+
+ if(ptr_session->flags & AIR_MIR_SESSION_FLAGS_DIR_RX)
+ {
+ regPCR |= BIT(PCR_PORT_RX_MIR_OFFT + session_id);
+ }
+ /* Write data to register */
+ aml_writeReg(unit, PCR(src_mac_port), regPCR);
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_mir_getMirrorPort
+ * PURPOSE:
+ * This API is used to get mirror port mirroring type.
+ * INPUT:
+ * unit -- Device unit number
+ * session_id -- Session id
+ * OUTPUT:
+ * ptr_session -- The information of this session to be
+ * obtained.
+ * AIR_MIR_SESSION_T
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_mir_getMirrorPort(
+ const UI32_T unit,
+ const UI32_T session_id,
+ AIR_MIR_SESSION_T *ptr_session)
+{
+ UI32_T regPCR = 0;
+ UI32_T src_mac_port = 0;
+
+ /* parameter sanity check */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((session_id >= AIR_MAX_MIRROR_SESSION), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_session);
+ AIR_PARAM_CHK((ptr_session->src_port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ src_mac_port = ptr_session->src_port;
+ /* Read data from register */
+ aml_readReg(unit, PCR(src_mac_port), ®PCR);
+
+ if(regPCR & BIT(PCR_PORT_TX_MIR_OFFT + session_id))
+ {
+ ptr_session->flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ }
+
+ if(regPCR & BIT(PCR_PORT_RX_MIR_OFFT + session_id))
+ {
+ ptr_session->flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ }
+
+ return AIR_E_OK;
+}
+
+
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_port.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_port.c
new file mode 100644
index 0000000..09dcef1
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_port.c
@@ -0,0 +1,2456 @@
+/* FILE NAME: air_port.c
+ * PURPOSE:
+ * Define the port function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+#include "air_port.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+#define AIR_SET_REG_BIT(cond, reg, bit) \
+ do{ \
+ if(TRUE == (cond)) \
+ { \
+ (reg) |= (bit); \
+ } \
+ else \
+ { \
+ (reg) &= ~(bit); \
+ } \
+ }while(0)
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+
+/* FUNCTION NAME: air_port_setAnMode
+ * PURPOSE:
+ * Set the auto-negotiation mode for a specific port.(Auto or Forced)
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setAnMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state)
+{
+ UI32_T u32CtrlReg = 0;
+ UI32_T u32Pmcr = 0;
+ UI32_T i = 0;
+ UI32_T mii_port = 0;
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from phy register */
+ aml_readPhyReg(unit, port, 0x0, &u32CtrlReg);
+
+ if(TRUE == state)
+ {
+ /* Enable AN mode of PHY port */
+ u32CtrlReg |= BIT(12);
+ }
+ else
+ {
+ /* Disable AN mode of PHY port */
+ u32CtrlReg &= ~BIT(12);
+ }
+
+ /* Restart AN */
+ u32CtrlReg |= BIT(9);
+
+ /* Write data to register */
+ aml_writePhyReg(unit, port, 0x00, u32CtrlReg);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_getAnMode
+ * PURPOSE:
+ * Get the auto-negotiation mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getAnMode(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+ UI32_T i = 0, mii_port = 0;
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+ (*ptr_state) = BITS_OFF_R(u32dat, 12, 1);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setLocalAdvAbility
+ * PURPOSE:
+ * Set the auto-negotiation advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * adv -- AN advertisement setting
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setLocalAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_AN_ADV_T adv)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Read AN Advertisement from register */
+ aml_readPhyReg(unit, port, PHY_AN_ADV, &u32dat);
+
+ /* Modify AN Advertisement */
+ AIR_SET_REG_BIT(adv.advCap10HDX, u32dat, AN_ADV_CAP_10_HDX);
+ AIR_SET_REG_BIT(adv.advCap10FDX, u32dat, AN_ADV_CAP_10_FDX);
+ AIR_SET_REG_BIT(adv.advCap100HDX, u32dat, AN_ADV_CAP_100_HDX);
+ AIR_SET_REG_BIT(adv.advCap100FDX, u32dat, AN_ADV_CAP_100_FDX);
+ AIR_SET_REG_BIT(adv.advPause, u32dat, AN_ADV_CAP_PAUSE);
+
+ /* Write AN Advertisement to register */
+ aml_writePhyReg(unit, port, PHY_AN_ADV, u32dat);
+
+ /* Write 1000BASE-T duplex capbility to register */
+ aml_readPhyReg(unit, port, PHY_CR1G, &u32dat);
+ AIR_SET_REG_BIT(adv.advCap1000FDX, u32dat, CR1G_ADV_CAP1000_FDX);
+ aml_writePhyReg(unit, port, PHY_CR1G, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getLocalAdvAbility
+ * PURPOSE:
+ * Get the auto-negotiation advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_adv -- AN advertisement setting
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getLocalAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_AN_ADV_T *ptr_adv)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ /* Mistake proofing checking */
+ AIR_CHECK_PTR(ptr_adv);
+
+ /* Read AN Advertisement from register */
+ aml_readPhyReg(unit, port, PHY_AN_ADV, &u32dat);
+ ptr_adv ->advCap10HDX = (u32dat & AN_ADV_CAP_10_HDX)?TRUE:FALSE;
+ ptr_adv ->advCap10FDX = (u32dat & AN_ADV_CAP_10_FDX)?TRUE:FALSE;
+ ptr_adv ->advCap100HDX = (u32dat & AN_ADV_CAP_100_HDX)?TRUE:FALSE;
+ ptr_adv ->advCap100FDX = (u32dat & AN_ADV_CAP_100_FDX)?TRUE:FALSE;
+ ptr_adv ->advPause = (u32dat & AN_ADV_CAP_PAUSE)?TRUE:FALSE;
+
+ /* Read 1000BASE-T duplex capalibity from register */
+ aml_readPhyReg(unit, port, PHY_CR1G, &u32dat);
+ ptr_adv ->advCap1000FDX = (u32dat & CR1G_ADV_CAP1000_FDX)?TRUE:FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getRemoteAdvAbility
+ * PURPOSE:
+ * Get the auto-negotiation remote advertisement for a
+ * specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_lp_adv -- AN advertisement of link partner
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getRemoteAdvAbility(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_AN_ADV_T *ptr_lp_adv)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_lp_adv);
+
+ /* Read AN LP Advertisement from register */
+ aml_readPhyReg(unit, port, PHY_AN_LP_ADV, &u32dat);
+ ptr_lp_adv ->advCap10HDX = (u32dat & AN_LP_CAP_10_HDX)?TRUE:FALSE;
+ ptr_lp_adv ->advCap10FDX = (u32dat & AN_LP_CAP_10_FDX)?TRUE:FALSE;
+ ptr_lp_adv ->advCap100HDX = (u32dat & AN_LP_CAP_100_HDX)?TRUE:FALSE;
+ ptr_lp_adv ->advCap100FDX = (u32dat & AN_LP_CAP_100_FDX)?TRUE:FALSE;
+ ptr_lp_adv ->advPause = (u32dat & AN_LP_CAP_PAUSE)?TRUE:FALSE;
+
+ /* Read LP 1000BASE-T duplex capalibity from register */
+ aml_readPhyReg(unit, port, PHY_SR1G, &u32dat);
+ ptr_lp_adv ->advCap1000FDX = (u32dat & SR1G_CAP1000_FDX)?TRUE:FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setSpeed
+ * PURPOSE:
+ * Set the speed for a specific port.
+ * This setting is used on force mode only.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M:1Gbps
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * AIR_E_OTHERS
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSpeed(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T speed)
+{
+ UI32_T u32dat = 0;
+ UI32_T mii_port = 0;
+ BOOL_T an = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for speed checking */
+ AIR_PARAM_CHK((speed >= AIR_PORT_SPEED_2500M), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+
+ u32dat &= ~(BIT(13) | BIT(6));
+ switch(speed)
+ {
+ case AIR_PORT_SPEED_10M:
+ /* (bit6, bit13) = 2b'00 means 10M */
+ break;
+ case AIR_PORT_SPEED_100M:
+ /* (bit6, bit13) = 2b'01 means 100M */
+ u32dat |= BIT(13);
+ break;
+ case AIR_PORT_SPEED_1000M:
+ /* (bit6, bit13) = 2b'10 means 1000M */
+ u32dat |= BIT(6);
+ break;
+ default:
+ /* (bit6, bit13) = 2b'11 means reverse,
+ * other value is invalid */
+ AIR_PRINT("argument 3: speed(%u) is invalid.\n", speed);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ /* Write data to register */
+ aml_writePhyReg(unit, port, 0x00, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getSpeed
+ * PURPOSE:
+ * Get the speed for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M:1Gbps
+ * AIR_PORT_SPEED_2500M:2.5Gbps
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSpeed(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_speed)
+{
+ UI32_T u32dat = 0;
+ UI32_T mii_port = 0, sp = 0;
+ UI32_T ret = AIR_E_OK;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for speed checking */
+ AIR_CHECK_PTR(ptr_speed);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+ (*ptr_speed) = (BITS_OFF_R(u32dat, 6, 1) << 1) | BITS_OFF_R(u32dat, 13, 1);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setDuplex
+ * PURPOSE:
+ * Get the duplex for a specific port.
+ * This setting is used on force mode only.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * duplex -- AIR_PORT_DUPLEX_HALF
+ * AIR_PORT_DUPLEX_FULL
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setDuplex(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T duplex)
+{
+ UI32_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+ UI32_T mii_port = 0, speed = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for duplex checking */
+ AIR_PARAM_CHK(((AIR_PORT_DUPLEX_HALF != duplex) && (AIR_PORT_DUPLEX_FULL != duplex)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+ speed = (BITS_OFF_R(u32dat, 6, 1) << 1) | BITS_OFF_R(u32dat, 13, 1);
+ if(AIR_PORT_SPEED_100M >= speed)
+ {
+ if(TRUE == duplex)
+ {
+ u32dat |= BIT(8);
+ }
+ else
+ {
+ u32dat &= ~BIT(8);
+ }
+ }
+ else
+ {
+ /* 1G support full duplex only */
+ u32dat |= BIT(8);
+ }
+
+ /* Write data to register */
+ aml_writePhyReg(unit, port, 0x0, u32dat);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_getDuplex
+ * PURPOSE:
+ * Get the duplex for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_duplex -- AIR_PORT_DUPLEX_HALF
+ * AIR_PORT_DUPLEX_FULL
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getDuplex(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_duplex)
+{
+ UI32_T u32dat = 0;
+ UI32_T mii_port = 0, duplex = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ /* Mistake proofing for duplex checking */
+ AIR_CHECK_PTR(ptr_duplex);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+ (*ptr_duplex) = BITS_OFF_R(u32dat, 8, 1);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getLink
+ * PURPOSE:
+ * Get the physical link status for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_ps -- AIR_PORT_STATUS_T
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getLink(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_STATUS_T *ptr_ps)
+{
+ UI32_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+ UI32_T mii_port = 0;
+ BOOL_T an = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ /* Mistake proofing for duplex checking */
+ AIR_CHECK_PTR(ptr_ps);
+
+ /* Read data from register */
+ aml_readReg(unit, PMSR(port), &u32dat);
+ ptr_ps->link = BITS_OFF_R(u32dat, 24, 1);
+ ptr_ps->duplex = BITS_OFF_R(u32dat, 25, 1);
+ ptr_ps->speed = BITS_OFF_R(u32dat, 28, 3);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setBckPres
+ * PURPOSE:
+ * Set the back pressure configuration for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * bckPres -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setBckPres(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T bckPres)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ /* Mistake proofing for speed checking */
+ AIR_PARAM_CHK(((TRUE != bckPres) && (FALSE != bckPres)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, PMCR(port), &u32dat);
+ if(TRUE == bckPres)
+ {
+ u32dat |= BIT(11);
+ }
+ else
+ {
+ u32dat &= ~BIT(11);
+ }
+
+ /* Write data to register */
+ aml_writeReg(unit, PMCR(port), u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getBckPres
+ * PURPOSE:
+ * Get the back pressure configuration for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_bckPres -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getBckPres(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_bckPres)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for speed checking */
+ AIR_CHECK_PTR(ptr_bckPres);
+
+ /* Read data from register */
+ aml_readReg(unit, PMCR(port), &u32dat);
+ (*ptr_bckPres) = BITS_OFF_R(u32dat, 11, 1);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setFlowCtrl
+ * PURPOSE:
+ * Set the flow control configuration for specific port.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0 - 6)
+ * dir -- Directions of AIR_PORT_TX or AIR_PORT_RX
+ * fc_en -- TRUE: Enable select port flow control
+ * FALSE:Disable select port flow control
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setFlowCtrl(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T dir,
+ const BOOL_T fc_en)
+{
+ UI32_T u32dat = 0;
+
+ /* Check port range */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Check directions */
+ if(dir != AIR_PORT_TX && dir != AIR_PORT_RX)
+ return AIR_E_BAD_PARAMETER;;
+
+ /* Check fc_en */
+ AIR_PARAM_CHK(((TRUE != fc_en) && (FALSE != fc_en)), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PMCR(port), &u32dat);
+ if(TRUE == fc_en)
+ {
+ /* Enable port flow control */
+ if(dir == AIR_PORT_TX)
+ {
+ u32dat |= FORCE_TX_FC;
+ }
+ else
+ {
+ u32dat |= FORCE_RX_FC;
+ }
+ }
+ else
+ {
+ /* Disable port flow control */
+ if(dir == AIR_PORT_TX)
+ {
+ u32dat &= ~(FORCE_TX_FC);
+ }
+ else
+ {
+ u32dat &= ~(FORCE_RX_FC);
+ }
+ }
+ aml_writeReg(unit, PMCR(port), u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getFlowCtrl
+ * PURPOSE:
+ * Get the flow control configuration for specific port.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_PORT_TX
+ * AIR_PORT_RX
+ * OUTPUT:
+ * ptr_fc_en -- FALSE: Port flow control disable
+ * TRUE: Port flow control enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getFlowCtrl(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T dir,
+ BOOL_T *ptr_fc_en)
+{
+ UI32_T u32dat = 0;
+
+ /* Check port range */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_fc_en);
+
+ /* Check directions */
+ if(dir != AIR_PORT_TX && dir != AIR_PORT_RX)
+ return AIR_E_BAD_PARAMETER;
+
+ /* Read port flow control status*/
+ aml_readReg(unit, PMCR(port), &u32dat);
+ if(dir == AIR_PORT_TX)
+ {
+ if((u32dat & FORCE_TX_FC) == FORCE_TX_FC)
+ *ptr_fc_en = TRUE;
+ else
+ *ptr_fc_en = FALSE;
+ }
+ else
+ {
+ if((u32dat & FORCE_RX_FC) == FORCE_RX_FC)
+ *ptr_fc_en = TRUE;
+ else
+ *ptr_fc_en = FALSE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setJumbo
+ * PURPOSE:
+ * Set accepting jumbo frmes with specificied size.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pkt_len -- Select max packet length
+ * RX_PKT_LEN_1518
+ * RX_PKT_LEN_1536
+ * RX_PKT_LEN_1552
+ * RX_PKT_LEN_MAX_JUMBO
+ * frame_len -- Select max lenght of jumbo frames
+ * Range : 2 - 16
+ * Units : K Bytes
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setJumbo(
+ const UI32_T unit,
+ const UI32_T pkt_len,
+ const UI32_T frame_len)
+{
+ UI32_T u32dat = 0;
+
+ /* Check packet length */
+ AIR_PARAM_CHK((pkt_len > 3), AIR_E_BAD_PARAMETER);
+
+ /* Check frame length */
+ AIR_PARAM_CHK((frame_len < 2), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((frame_len > 16), AIR_E_BAD_PARAMETER);
+
+ /* Read and clear jumbo frame info */
+ aml_readReg(unit, GMACCR, &u32dat);
+ u32dat &= ~0x00F3;
+
+ /* Set max packet length */
+ u32dat |= pkt_len;
+
+ /* Set jumbo frames max length */
+ u32dat |= (frame_len << 4);
+
+ aml_writeReg(unit, GMACCR, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getJumbo
+ * PURPOSE:
+ * Get accepting jumbo frmes with specificied size.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ *
+ * OUTPUT:
+ * ptr_pkt_len -- Select max packet length
+ * RX_PKT_LEN_1518
+ * RX_PKT_LEN_1536
+ * RX_PKT_LEN_1552
+ * RX_PKT_LEN_MAX_JUMBO
+ * ptr_frame_len -- Select max lenght of jumbo frames
+ * Range : 2 - 16
+ * Units : K Bytes
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getJumbo(
+ const UI32_T unit,
+ UI32_T *ptr_pkt_len,
+ UI32_T *ptr_frame_len)
+{
+ UI32_T u32dat = 0;
+
+ AIR_CHECK_PTR(ptr_pkt_len);
+ AIR_CHECK_PTR(ptr_frame_len);
+
+ /* Read and clear jumbo frame info */
+ aml_readReg(unit, GMACCR, &u32dat);
+
+ /* Set max packet length */
+ *ptr_pkt_len = (0x03 & u32dat);
+
+ /* Set jumbo frames max length */
+ *ptr_frame_len = (0x0F & (u32dat >> 4));
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setPsMode
+ * PURPOSE:
+ * Set the power saving mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * mode -- Bit-map:
+ * AIR_PORT_PS_LINKSTATUS
+ * AIR_PORT_PS_EEE
+ * FALSE: Disable / TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setPsMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T mode)
+{
+ UI32_T u32dat = 0;
+ UI32_T u32cl45_1e_3c = 0;
+ UI32_T u32cl45_1e_3d = 0;
+ UI32_T u32cl45_1e_3e = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mode & (~AIR_PORT_PS_MASK)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readPhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG0, &u32cl45_1e_3c);
+ aml_readPhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG1, &u32cl45_1e_3d);
+ aml_readPhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG2, &u32cl45_1e_3e);
+
+ if(mode & AIR_PORT_PS_LINKSTATUS)
+ {
+ /* Set Link Status
+ * Disable bypass function to enable */
+ u32cl45_1e_3c &= ~BITS(12, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG0, u32cl45_1e_3c);
+ u32cl45_1e_3d &= ~BITS(12, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG1, u32cl45_1e_3d);
+ u32cl45_1e_3e &= ~BITS(11, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG2, u32cl45_1e_3e);
+ }
+ else
+ {
+ /* Set Link Status
+ * Enable bypass function to disable */
+ u32cl45_1e_3c |= BITS(12, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG0, u32cl45_1e_3c);
+ u32cl45_1e_3d |= BITS(12, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG1, u32cl45_1e_3d);
+ u32cl45_1e_3e |= BITS(11, 15);
+ aml_writePhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG2, u32cl45_1e_3e);
+ }
+
+ if(mode & AIR_PORT_PS_EEE)
+ {
+ /* Enable EEE */
+ u32dat = (EEE_ADV_1000BT | EEE_ADV_100BT );
+ aml_writePhyRegCL45(unit, port, PHY_DEV_07H, EEE_ADV_REG, u32dat);
+ }
+ else
+ {
+ /* Disable EEE */
+ aml_writePhyRegCL45(unit, port, PHY_DEV_07H, EEE_ADV_REG, 0);
+ }
+ return AIR_E_OK;
+
+}
+
+/* FUNCTION NAME: air_port_getPsMode
+ * PURPOSE:
+ * Get the power saving mode for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * OUTPUT:
+ * ptr_mode -- Bit-map:
+ * AIR_PORT_PS_LINKSTATUS
+ * AIR_PORT_PS_EEE
+ * FALSE: Disable / TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getPsMode(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_mode)
+{
+ UI32_T u32cl45_1e_3e = 0;
+ UI32_T u32cl45_07_3c = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for mode checking */
+ AIR_CHECK_PTR(ptr_mode);
+
+ (*ptr_mode) = 0;
+
+ /* Check link-status power saving */
+ aml_readPhyRegCL45(unit, port, PHY_DEV_1EH, BYPASS_POWER_DOWN_REG2, &u32cl45_1e_3e);
+ if(!BITS_OFF_R(u32cl45_1e_3e, 11, 5))
+ {
+ /* Read Bypass the power-down TXVLD to check link-status
+ * power saving function state */
+ (*ptr_mode) |= AIR_PORT_PS_LINKSTATUS;
+ }
+
+ /* Check EEE */
+ aml_readPhyRegCL45(unit, port, PHY_DEV_07H, EEE_ADV_REG, &u32cl45_07_3c);
+ if( (u32cl45_07_3c & EEE_ADV_1000BT) && (u32cl45_07_3c & EEE_ADV_100BT) )
+ {
+ /* Read PMCR to check EEE ability */
+ (*ptr_mode) |= AIR_PORT_PS_EEE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setSmtSpdDwn
+ * PURPOSE:
+ * Set Smart speed down feature for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * time -- AIR_PORT_SSD_2T
+ * AIR_PORT_SSD_3T
+ * AIR_PORT_SSD_4T
+ * AIR_PORT_SSD_5T
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSmtSpdDwn(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state,
+ const UI32_T time)
+{
+ UI32_T u32ext14 = 0;
+ UI32_T page = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for time checking */
+ AIR_PARAM_CHK((time >= AIR_PORT_SSD_LAST), AIR_E_BAD_PARAMETER);
+
+ /* Backup page */
+ aml_readPhyReg(unit, port, 0x1F, &page);
+
+ /* Switch to page 1*/
+ aml_writePhyReg(unit, port, 0x1F, 0x1);
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x14, &u32ext14);
+
+ /* Write data to register */
+ if(TRUE == state)
+ {
+ u32ext14 |= BIT(4);
+ }
+ else
+ {
+ u32ext14 &= ~BIT(4);
+ }
+ u32ext14 &= ~BITS(2,3);
+ u32ext14 |= time << 2;
+
+ /* Switch to page 1*/
+ aml_writePhyReg(unit, port, 0x1F, 0x1);
+ /* Read data from register */
+ aml_writePhyReg(unit, port, 0x14, u32ext14);
+
+ /* Restore page */
+ aml_writePhyReg(unit, port, 0x1F, page);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getSmtSpdDwn
+ * PURPOSE:
+ * Get Smart speed down feature for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * ptr_time -- AIR_PORT_SSD_2T
+ * AIR_PORT_SSD_3T
+ * AIR_PORT_SSD_4T
+ * AIR_PORT_SSD_5T
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSmtSpdDwn(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state,
+ UI32_T *ptr_time)
+{
+ UI32_T u32ext14 = 0;
+ UI32_T page = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Mistake proofing for time checking */
+ AIR_CHECK_PTR(ptr_time);
+
+ /* Backup page */
+ aml_readPhyReg(unit, port, 0x1F, &page);
+
+ /* Switch to page 1*/
+ aml_writePhyReg(unit, port, 0x1F, 0x1);
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x14, &u32ext14);
+
+ (*ptr_state) = BITS_OFF_R(u32ext14, 4, 1);
+ (*ptr_time) = BITS_OFF_R(u32ext14, 2, 2);
+
+ /* Restore page */
+ aml_writePhyReg(unit, port, 0x1F, page);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setEnable
+ * PURPOSE:
+ * Set powerdown state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * state -- FALSE:Disable
+ * TRUE: Enable
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != state) && (FALSE != state)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+
+ if(TRUE == state)
+ {
+ /* Enable port, so disable powerdown bit */
+ u32dat &= ~BIT(11);
+ }
+ else
+ {
+ /* Disable port, so enable powerdown bit */
+ u32dat |= BIT(11);
+ }
+
+ /* Write data to register */
+ aml_writePhyReg(unit, port, 0x0, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getEnable
+ * PURPOSE:
+ * Get powerdown state for a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ *
+ * OUTPUT:
+ * ptr_state -- FALSE:Disable
+ * TRUE: Enable
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_GIGA_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readPhyReg(unit, port, 0x0, &u32dat);
+
+ (*ptr_state) = (~BITS_OFF_R(u32dat, 11, 1))&BIT(0);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_setPortMatrix
+ * PURPOSE:
+ * Set port matrix from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ * port_bitmap -- Matrix port bitmap
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_setPortMatrix(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T port_bitmap)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port_bitmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
+
+ aml_writeReg(unit, PORTMATRIX(port), port_bitmap);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_port_getPortMatrix
+ * PURPOSE:
+ * Get port matrix from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ *
+ * OUTPUT:
+ * p_port_bitmap -- Matrix port bitmap
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_getPortMatrix(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *p_port_bitmap)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(p_port_bitmap);
+
+ aml_readReg(unit, PORTMATRIX(port), &val);
+ *p_port_bitmap = val;
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_port_setVlanMode
+ * PURPOSE:
+ * Set port-based vlan mechanism from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ * mode -- Port vlan mode
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_setVlanMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_PORT_VLAN_MODE_T mode)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mode >= AIR_PORT_VLAN_MODE_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PCR(port), &val);
+ val &= ~PCR_PORT_VLAN_MASK;
+ val |= (mode & PCR_PORT_VLAN_RELMASK) << PCR_PORT_VLAN_OFFT;
+ aml_writeReg(unit, PCR(port), val);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_port_getVlanMode
+ * PURPOSE:
+ * Get port-based vlan mechanism from the specified device.
+ *
+ * INPUT:
+ * unit -- Unit id
+ * port -- Port id
+ *
+ * OUTPUT:
+ * p_mode -- Port vlan mode
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_OTHERS
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_port_getVlanMode(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_VLAN_MODE_T *p_mode)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(p_mode);
+
+ aml_readReg(unit, PCR(port), &val);
+ *p_mode = (val >> PCR_PORT_VLAN_OFFT) & PCR_PORT_VLAN_RELMASK;
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_port_setSpTag
+ * PURPOSE:
+ * Set special tag state of a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * sptag_en -- TRUE: Enable special tag
+ * FALSE: Disable special tag
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSpTag(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T sptag_en)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != sptag_en) && (FALSE != sptag_en)), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, PVC(port), &u32dat);
+
+ /* Write data to register */
+ if(TRUE == sptag_en)
+ {
+ u32dat |= PVC_SPTAG_EN_MASK;
+ }
+ else
+ {
+ u32dat &= ~PVC_SPTAG_EN_MASK;
+ }
+ aml_writeReg(unit, PVC(port), u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_getSpTag
+ * PURPOSE:
+ * Get special tag state of a specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * OUTPUT:
+ * ptr_sptag_en -- TRUE: Special tag enable
+ * FALSE: Special tag disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_getSpTag(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *ptr_sptag_en)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_sptag_en);
+
+ /* Read data from register */
+ aml_readReg(unit, PVC(port), &u32dat);
+
+ *ptr_sptag_en = (u32dat & PVC_SPTAG_EN_MASK) >> PVC_SPTAG_EN_OFFT;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_port_set5GBaseRModeEnable
+ * PURPOSE:
+ * Set the port5 5GBase-R mode enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_set5GBaseRModeEn(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ /* PHYA Cal Enable (EFUSE) */
+ aml_readReg(unit, INTF_CTRL_8, &u32dat);
+ u32dat |= BIT(7);
+ aml_writeReg(unit, INTF_CTRL_8, u32dat);
+
+ aml_readReg(unit, INTF_CTRL_9, &u32dat);
+ u32dat |= BIT(31);
+ aml_writeReg(unit, INTF_CTRL_9, u32dat);
+
+ /* PMA Init */
+ /* PLL */
+ aml_readReg(unit, RX_CTRL_26, &u32dat);
+ u32dat |= BIT(23);
+ u32dat &= (~BIT(24));
+ u32dat |= BIT(26);
+ aml_writeReg(unit, RX_CTRL_26, u32dat);
+
+ aml_readReg(unit, QP_DIG_MODE_CTRL_1, &u32dat);
+ u32dat |= BITS(2, 3);
+ aml_writeReg(unit, QP_DIG_MODE_CTRL_1, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat |= BITS(0, 1);
+ u32dat &= ~(0x7 << 2);
+ u32dat |= (0x5 << 2);
+ u32dat &= ~(0x3 << 6);
+ u32dat |= (0x1 << 6);
+ u32dat &= ~(0x7 << 8);
+ u32dat |= (0x3 << 8);
+ u32dat |= BIT(29);
+ u32dat &= ~BITS(12, 13);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BIT(2);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(14);
+ u32dat &= ~(0xf << 16);
+ u32dat |= (0x8 << 16);
+ u32dat &= ~BITS(20, 21);
+ u32dat &= ~(0x3 << 24);
+ u32dat |= (0x1 << 24);
+ u32dat &= ~BIT(26);
+ u32dat |= BIT(22);
+ u32dat |= BIT(27);
+ u32dat |= BIT(28);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~(0x3 << 3);
+ u32dat |= (0x1 << 3);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ aml_readReg(unit, SS_LCPLL_PWCTL_SETTING_2, &u32dat);
+ u32dat |= BITS(16, 17);
+ aml_writeReg(unit, SS_LCPLL_PWCTL_SETTING_2, u32dat);
+
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_2, 0x1c800000);
+ aml_writeReg(unit, SS_LCPLL_TDC_PCW_1, 0x1c800000);
+
+ aml_readReg(unit, SS_LCPLL_TDC_FLT_5, &u32dat);
+ u32dat &= ~BIT(24);
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_5, u32dat);
+
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(8);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(0, 15);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BITS(0, 1);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(16, 31);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(9);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_QP_PLL_IPLL_DIG_PWR_SEL, &u32dat);
+ u32dat &= ~(0x3 << 25);
+ u32dat |= (0x1 << 25);
+ aml_writeReg(unit, RG_QP_PLL_IPLL_DIG_PWR_SEL, u32dat);
+
+ aml_readReg(unit, RG_QP_PLL_SDM_ORD, &u32dat);
+ u32dat |= BIT(3);
+ u32dat |= BIT(4);
+ aml_writeReg(unit, RG_QP_PLL_SDM_ORD, u32dat);
+
+ aml_readReg(unit, RG_QP_RX_DAC_EN, &u32dat);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x2 << 16);
+ aml_writeReg(unit, RG_QP_RX_DAC_EN, u32dat);
+
+ aml_readReg(unit, PON_RXFEDIG_CTRL_0, &u32dat);
+ u32dat &= ~BIT(12);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_0, u32dat);
+
+ /* RX Control */
+ aml_readReg(unit, RG_QP_CDR_LPF_MJV_LIM, &u32dat);
+ u32dat &= ~BITS(4, 5);
+ aml_writeReg(unit, RG_QP_CDR_LPF_MJV_LIM, u32dat);
+
+ aml_readReg(unit, RG_QP_RXAFE_RESERVE, &u32dat);
+ u32dat |= BIT(11);
+ aml_writeReg(unit, RG_QP_RXAFE_RESERVE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_CKREF_DIV1, &u32dat);
+ u32dat &= ~(0x1f << 8);
+ u32dat |= (0xc << 8);
+ aml_writeReg(unit, RG_QP_CDR_PR_CKREF_DIV1, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, &u32dat);
+ u32dat |= BIT(13);
+ aml_writeReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, &u32dat);
+ u32dat |= BIT(30);
+ aml_writeReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ aml_writeReg(unit, PLL_CTRL_0, u32dat);
+
+ aml_readReg(unit, RX_DLY_0, &u32dat);
+ u32dat &= ~(0xff << 0);
+ u32dat |= (0x6f << 0);
+ u32dat |= BITS(8, 13);
+ aml_writeReg(unit, RX_DLY_0, u32dat);
+
+ aml_readReg(unit, RX_CTRL_42, &u32dat);
+ u32dat &= ~(0x1fff << 0);
+ u32dat |= (0x150 << 0);
+ aml_writeReg(unit, RX_CTRL_42, u32dat);
+
+ aml_readReg(unit, RX_CTRL_2, &u32dat);
+ u32dat &= ~(0x1fff << 16);
+ u32dat |= (0x150 << 16);
+ aml_writeReg(unit, RX_CTRL_2, u32dat);
+
+ aml_readReg(unit, PON_RXFEDIG_CTRL_9, &u32dat);
+ u32dat |= BITS(0, 2);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_9, u32dat);
+
+ aml_readReg(unit, RX_CTRL_8, &u32dat);
+ u32dat &= ~(0xfff << 16);
+ u32dat |= (0x200 << 16);
+ aml_writeReg(unit, RX_CTRL_8, u32dat);
+
+ /* Frequency memter */
+ aml_readReg(unit, RX_CTRL_5, &u32dat);
+ u32dat &= ~(0xfffff << 10);
+ u32dat |= (0x9 << 10);
+ aml_writeReg(unit, RX_CTRL_5, u32dat);
+
+ aml_readReg(unit, RX_CTRL_6, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x64 << 0);
+ aml_writeReg(unit, RX_CTRL_6, u32dat);
+
+ aml_readReg(unit, RX_CTRL_7, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x2710 << 0);
+ aml_writeReg(unit, RX_CTRL_7, u32dat);
+
+ /* PCS Init */
+ aml_readReg(unit, RG_USXGMII_AN_CONTROL_0, &u32dat);
+ u32dat &= ~BIT(0);
+ aml_writeReg(unit, RG_USXGMII_AN_CONTROL_0, u32dat);
+
+ aml_readReg(unit, USGMII_CTRL_0, &u32dat);
+ u32dat |= BIT(2);
+ aml_writeReg(unit, USGMII_CTRL_0, u32dat);
+
+ aml_readReg(unit, MSG_RX_CTRL_0, &u32dat);
+ u32dat |= BIT(28);
+ aml_writeReg(unit, MSG_RX_CTRL_0, u32dat);
+
+ aml_readReg(unit, QP_CK_RST_CTRL_4, &u32dat);
+ u32dat |= BITS(14, 20);
+ aml_writeReg(unit, QP_CK_RST_CTRL_4, u32dat);
+
+ /* bypass flow control to MAC */
+ aml_writeReg(unit, MSG_RX_LIK_STS_0, 0x01010107);
+ aml_writeReg(unit, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setHsgmiiModeEnable
+ * PURPOSE:
+ * Set the port5 HSGMII mode enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setHsgmiiModeEn(
+ const UI32_T unit)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ /* PLL */
+ aml_readReg(unit, QP_DIG_MODE_CTRL_1, &u32dat);
+ u32dat &= ~(0x3 << 2);
+ u32dat |= (0x1 << 2);
+ aml_writeReg(unit, QP_DIG_MODE_CTRL_1, u32dat);
+
+ /* PLL - LPF */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0x3 << 0);
+ u32dat |= (0x1 << 0);
+ u32dat &= ~(0x7 << 2);
+ u32dat |= (0x5 << 2);
+ u32dat &= ~BITS(6, 7);
+ u32dat &= ~(0x7 << 8);
+ u32dat |= (0x3 << 8);
+ u32dat |= BIT(29);
+ u32dat &= ~BITS(12, 13);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - ICO */
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat |= BIT(2);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(14);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - CHP */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0xf << 16);
+ u32dat |= (0x6 << 16);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+
+ /* PLL - PFD */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0x3 << 20);
+ u32dat |= (0x1 << 20);
+ u32dat &= ~(0x3 << 24);
+ u32dat |= (0x1 << 24);
+ u32dat &= ~BIT(26);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - POSTDIV */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat |= BIT(22);
+ u32dat &= ~BIT(27);
+ u32dat &= ~BIT(28);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - SDM */
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BITS(3, 4);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ aml_readReg(unit, SS_LCPLL_PWCTL_SETTING_2, &u32dat);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x1 << 16);
+ aml_writeReg(unit, SS_LCPLL_PWCTL_SETTING_2, u32dat);
+
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_2, 0x7a000000);
+ aml_writeReg(unit, SS_LCPLL_TDC_PCW_1, 0x7a000000);
+
+ aml_readReg(unit, SS_LCPLL_TDC_FLT_5, &u32dat);
+ u32dat &= ~BIT(24);
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_5, u32dat);
+
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(8);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ /* PLL - SS */
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(0, 15);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BITS(0, 1);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(16, 31);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ /* PLL - TDC */
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(9);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_QP_PLL_SDM_ORD, &u32dat);
+ u32dat |= BIT(3);
+ u32dat |= BIT(4);
+ aml_writeReg(unit, RG_QP_PLL_SDM_ORD, u32dat);
+
+ aml_readReg(unit, RG_QP_RX_DAC_EN, &u32dat);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x2 << 16);
+ aml_writeReg(unit, RG_QP_RX_DAC_EN, u32dat);
+
+ /* TCL Disable (only for Co-SIM) */
+ aml_readReg(unit, PON_RXFEDIG_CTRL_0, &u32dat);
+ u32dat &= ~BIT(12);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_0, u32dat);
+
+ /* TX Init */
+ aml_readReg(unit, RG_QP_TX_MODE_16B_EN, &u32dat);
+ u32dat &= ~BIT(0);
+ u32dat &= ~(0xffff << 16);
+ u32dat |= (0x4 << 16);
+ aml_writeReg(unit, RG_QP_TX_MODE_16B_EN, u32dat);
+
+ /* RX Control */
+ aml_readReg(unit, RG_QP_RXAFE_RESERVE, &u32dat);
+ u32dat |= BIT(11);
+ aml_writeReg(unit, RG_QP_RXAFE_RESERVE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_LPF_MJV_LIM, &u32dat);
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x1 << 4);
+ aml_writeReg(unit, RG_QP_CDR_LPF_MJV_LIM, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_LPF_SETVALUE, &u32dat);
+ u32dat &= ~(0xf << 25);
+ u32dat |= (0x1 << 25);
+ u32dat &= ~(0x7 << 29);
+ u32dat |= (0x3 << 29);
+ aml_writeReg(unit, RG_QP_CDR_LPF_SETVALUE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_CKREF_DIV1, &u32dat);
+ u32dat &= ~(0x1f << 8);
+ u32dat |= (0xf << 8);
+ aml_writeReg(unit, RG_QP_CDR_PR_CKREF_DIV1, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, &u32dat);
+ u32dat &= ~(0x3f << 0);
+ u32dat |= (0x19 << 0);
+ u32dat &= ~BIT(6);
+ aml_writeReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, &u32dat);
+ u32dat &= ~(0x7f << 6);
+ u32dat |= (0x21 << 6);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x2 << 16);
+ u32dat &= ~BIT(13);
+ aml_writeReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_CKREF_DIV1, &u32dat);
+ u32dat &= ~(0x7 << 24);
+ u32dat |= (0x4 << 24);
+ aml_writeReg(unit, RG_QP_CDR_PR_CKREF_DIV1, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ aml_writeReg(unit, PLL_CTRL_0, u32dat);
+
+ aml_readReg(unit, RX_CTRL_26, &u32dat);
+ u32dat &= ~BIT(23);
+ u32dat |= BIT(26);
+ aml_writeReg(unit, RX_CTRL_26, u32dat);
+
+ aml_readReg(unit, RX_DLY_0, &u32dat);
+ u32dat &= ~(0xff << 0);
+ u32dat |= (0x6f << 0);
+ u32dat |= BITS(8, 13);
+ aml_writeReg(unit, RX_DLY_0, u32dat);
+
+ aml_readReg(unit, RX_CTRL_42, &u32dat);
+ u32dat &= ~(0x1fff << 0);
+ u32dat |= (0x150 << 0);
+ aml_writeReg(unit, RX_CTRL_42, u32dat);
+
+ aml_readReg(unit, RX_CTRL_2, &u32dat);
+ u32dat &= ~(0x1fff << 16);
+ u32dat |= (0x150 << 16);
+ aml_writeReg(unit, RX_CTRL_2, u32dat);
+
+ aml_readReg(unit, PON_RXFEDIG_CTRL_9, &u32dat);
+ u32dat &= ~(0x7 << 0);
+ u32dat |= (0x1 << 0);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_9, u32dat);
+
+ aml_readReg(unit, RX_CTRL_8, &u32dat);
+ u32dat &= ~(0xfff << 16);
+ u32dat |= (0x200 << 16);
+ u32dat &= ~(0x7fff << 14);
+ u32dat |= (0xfff << 14);
+ aml_writeReg(unit, RX_CTRL_8, u32dat);
+
+ /* Frequency memter */
+ aml_readReg(unit, RX_CTRL_5, &u32dat);
+ u32dat &= ~(0xfffff << 10);
+ u32dat |= (0x10 << 10);
+ aml_writeReg(unit, RX_CTRL_5, u32dat);
+
+ aml_readReg(unit, RX_CTRL_6, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x64 << 0);
+ aml_writeReg(unit, RX_CTRL_6, u32dat);
+
+ aml_readReg(unit, RX_CTRL_7, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x2710 << 0);
+ aml_writeReg(unit, RX_CTRL_7, u32dat);
+
+ /* PCS Init */
+ aml_readReg(unit, RG_HSGMII_PCS_CTROL_1, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, RG_HSGMII_PCS_CTROL_1, u32dat);
+
+ /* Rate Adaption */
+ aml_readReg(unit, RATE_ADP_P0_CTRL_0, &u32dat);
+ u32dat &= ~BIT(31);
+ aml_writeReg(unit, RATE_ADP_P0_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_RATE_ADAPT_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ u32dat |= BIT(4);
+ u32dat |= BITS(26, 27);
+ aml_writeReg(unit, RG_RATE_ADAPT_CTRL_0, u32dat);
+
+ /* Disable AN */
+ aml_readReg(unit, SGMII_REG_AN0, &u32dat);
+ u32dat &= ~BIT(12);
+ aml_writeReg(unit, SGMII_REG_AN0, u32dat);
+
+ /* Force Speed */
+ aml_readReg(unit, SGMII_STS_CTRL_0, &u32dat);
+ u32dat |= BIT(2);
+ u32dat |= BITS(4, 5);
+ aml_writeReg(unit, SGMII_STS_CTRL_0, u32dat);
+
+ /* bypass flow control to MAC */
+ aml_writeReg(unit, MSG_RX_LIK_STS_0, 0x01010107);
+ aml_writeReg(unit, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setSgmiiMode
+ * PURPOSE:
+ * Set the port5 SGMII mode for AN or force
+ *
+ * INPUT:
+ * unit -- Device ID
+ * mode -- AIR_PORT_SGMII_MODE_AN
+ * AIR_PORT_SGMII_MODE_FORCE
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M: 1Gbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setSgmiiMode(
+ const UI32_T unit,
+ const UI32_T mode,
+ const UI32_T speed)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ AIR_PARAM_CHK(((AIR_PORT_SGMII_MODE_AN != mode) && (AIR_PORT_SGMII_MODE_FORCE != mode)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((speed >= AIR_PORT_SPEED_2500M), AIR_E_BAD_PARAMETER);
+
+ /* PMA Init */
+ /* PLL */
+ aml_readReg(unit, QP_DIG_MODE_CTRL_1, &u32dat);
+ u32dat &= ~BITS(2, 3);
+ aml_writeReg(unit, QP_DIG_MODE_CTRL_1, u32dat);
+
+ /* PLL - LPF */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0x3 << 0);
+ u32dat |= (0x1 << 0);
+ u32dat &= ~(0x7 << 2);
+ u32dat |= (0x5 << 2);
+ u32dat &= ~BITS(6, 7);
+ u32dat &= ~(0x7 << 8);
+ u32dat |= (0x3 << 8);
+ u32dat |= BIT(29);
+ u32dat &= ~BITS(12, 13);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - ICO */
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat |= BIT(2);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(14);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - CHP */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0xf << 16);
+ u32dat |= (0x4 << 16);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+
+ /* PLL - PFD */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~(0x3 << 20);
+ u32dat |= (0x1 << 20);
+ u32dat &= ~(0x3 << 24);
+ u32dat |= (0x1 << 24);
+ u32dat &= ~BIT(26);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - POSTDIV */
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat |= BIT(22);
+ u32dat &= ~BIT(27);
+ u32dat &= ~BIT(28);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ /* PLL - SDM */
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BITS(3, 4);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_2, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, PLL_CTRL_2, u32dat);
+
+ aml_readReg(unit, SS_LCPLL_PWCTL_SETTING_2, &u32dat);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x1 << 16);
+ aml_writeReg(unit, SS_LCPLL_PWCTL_SETTING_2, u32dat);
+
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_2, 0x48000000);
+ aml_writeReg(unit, SS_LCPLL_TDC_PCW_1, 0x48000000);
+
+ aml_readReg(unit, SS_LCPLL_TDC_FLT_5, &u32dat);
+ u32dat &= ~BIT(24);
+ aml_writeReg(unit, SS_LCPLL_TDC_FLT_5, u32dat);
+
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(8);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ /* PLL - SS */
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(0, 15);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_4, &u32dat);
+ u32dat &= ~BITS(0, 1);
+ aml_writeReg(unit, PLL_CTRL_4, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_3, &u32dat);
+ u32dat &= ~BITS(16, 31);
+ aml_writeReg(unit, PLL_CTRL_3, u32dat);
+
+ /* PLL - TDC */
+ aml_readReg(unit, PLL_CK_CTRL_0, &u32dat);
+ u32dat &= ~BIT(9);
+ aml_writeReg(unit, PLL_CK_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_QP_PLL_SDM_ORD, &u32dat);
+ u32dat |= BIT(3);
+ u32dat |= BIT(4);
+ aml_writeReg(unit, RG_QP_PLL_SDM_ORD, u32dat);
+
+ aml_readReg(unit, RG_QP_RX_DAC_EN, &u32dat);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x2 << 16);
+ aml_writeReg(unit, RG_QP_RX_DAC_EN, u32dat);
+
+ /* PLL - TCL Disable (only for Co-SIM) */
+ aml_readReg(unit, PON_RXFEDIG_CTRL_0, &u32dat);
+ u32dat &= ~BIT(12);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_0, u32dat);
+
+ /* TX Init */
+ aml_readReg(unit, RG_QP_TX_MODE_16B_EN, &u32dat);
+ u32dat &= ~BIT(0);
+ u32dat &= ~BITS(16, 31);
+ aml_writeReg(unit, RG_QP_TX_MODE_16B_EN, u32dat);
+
+ /* RX Init */
+ aml_readReg(unit, RG_QP_RXAFE_RESERVE, &u32dat);
+ u32dat |= BIT(11);
+ aml_writeReg(unit, RG_QP_RXAFE_RESERVE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_LPF_MJV_LIM, &u32dat);
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x2 << 4);
+ aml_writeReg(unit, RG_QP_CDR_LPF_MJV_LIM, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_LPF_SETVALUE, &u32dat);
+ u32dat &= ~(0xf << 25);
+ u32dat |= (0x1 << 25);
+ u32dat &= ~(0x7 << 29);
+ u32dat |= (0x6 << 29);
+ aml_writeReg(unit, RG_QP_CDR_LPF_SETVALUE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_CKREF_DIV1, &u32dat);
+ u32dat &= ~(0x1f << 8);
+ u32dat |= (0xc << 8);
+ aml_writeReg(unit, RG_QP_CDR_PR_CKREF_DIV1, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, &u32dat);
+ u32dat &= ~(0x3f << 0);
+ u32dat |= (0x19 << 0);
+ u32dat &= ~BIT(6);
+ aml_writeReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, &u32dat);
+ u32dat &= ~(0x7f << 6);
+ u32dat |= (0x21 << 6);
+ u32dat &= ~(0x3 << 16);
+ u32dat |= (0x2 << 16);
+ u32dat &= ~BIT(13);
+ aml_writeReg(unit, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, RG_QP_CDR_PR_KBAND_DIV_PCIE, u32dat);
+
+ aml_readReg(unit, RG_QP_CDR_PR_CKREF_DIV1, &u32dat);
+ u32dat &= ~(0x7 << 24);
+ u32dat |= (0x4 << 24);
+ aml_writeReg(unit, RG_QP_CDR_PR_CKREF_DIV1, u32dat);
+
+ aml_readReg(unit, PLL_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ aml_writeReg(unit, PLL_CTRL_0, u32dat);
+
+ aml_readReg(unit, RX_CTRL_26, &u32dat);
+ u32dat &= ~BIT(23);
+ if(AIR_PORT_SGMII_MODE_AN == mode)
+ {
+ u32dat |= BIT(26);
+ }
+ aml_writeReg(unit, RX_CTRL_26, u32dat);
+
+ aml_readReg(unit, RX_DLY_0, &u32dat);
+ u32dat &= ~(0xff << 0);
+ u32dat |= (0x6f << 0);
+ u32dat |= BITS(8, 13);
+ aml_writeReg(unit, RX_DLY_0, u32dat);
+
+ aml_readReg(unit, RX_CTRL_42, &u32dat);
+ u32dat &= ~(0x1fff << 0);
+ u32dat |= (0x150 << 0);
+ aml_writeReg(unit, RX_CTRL_42, u32dat);
+
+ aml_readReg(unit, RX_CTRL_2, &u32dat);
+ u32dat &= ~(0x1fff << 16);
+ u32dat |= (0x150 << 16);
+ aml_writeReg(unit, RX_CTRL_2, u32dat);
+
+ aml_readReg(unit, PON_RXFEDIG_CTRL_9, &u32dat);
+ u32dat &= ~(0x7 << 0);
+ u32dat |= (0x1 << 0);
+ aml_writeReg(unit, PON_RXFEDIG_CTRL_9, u32dat);
+
+ aml_readReg(unit, RX_CTRL_8, &u32dat);
+ u32dat &= ~(0xfff << 16);
+ u32dat |= (0x200 << 16);
+ u32dat &= ~(0x7fff << 0);
+ u32dat |= (0xfff << 0);
+ aml_writeReg(unit, RX_CTRL_8, u32dat);
+
+ /* Frequency memter */
+ aml_readReg(unit, RX_CTRL_5, &u32dat);
+ u32dat &= ~(0xfffff << 10);
+ u32dat |= (0x28 << 10);
+ aml_writeReg(unit, RX_CTRL_5, u32dat);
+
+ aml_readReg(unit, RX_CTRL_6, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x64 << 0);
+ aml_writeReg(unit, RX_CTRL_6, u32dat);
+
+ aml_readReg(unit, RX_CTRL_7, &u32dat);
+ u32dat &= ~(0xfffff << 0);
+ u32dat |= (0x2710 << 0);
+ aml_writeReg(unit, RX_CTRL_7, u32dat);
+
+ if(AIR_PORT_SGMII_MODE_FORCE == mode)
+ {
+ /* PCS Init */
+ aml_readReg(unit, QP_DIG_MODE_CTRL_0, &u32dat);
+ u32dat &= ~BIT(0);
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ u32dat &= ~BITS(4, 5);
+ }
+ else if(AIR_PORT_SPEED_100M == speed)
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x1 << 4);
+ }
+ else
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x2 << 4);
+ }
+ aml_writeReg(unit, QP_DIG_MODE_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_HSGMII_PCS_CTROL_1, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, RG_HSGMII_PCS_CTROL_1, u32dat);
+
+ /* Rate Adaption - GMII path config. */
+ aml_readReg(unit, RG_AN_SGMII_MODE_FORCE, &u32dat);
+ u32dat |= BIT(0);
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ u32dat &= ~BITS(4, 5);
+ }
+ else if(AIR_PORT_SPEED_100M == speed)
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x1 << 4);
+ }
+ else
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x2 << 4);
+ }
+ aml_writeReg(unit, RG_AN_SGMII_MODE_FORCE, u32dat);
+
+ aml_readReg(unit, SGMII_STS_CTRL_0, &u32dat);
+ u32dat |= BIT(2);
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x2 << 4);
+ }
+ else if(AIR_PORT_SPEED_100M == speed)
+ {
+ u32dat &= ~(0x3 << 4);
+ u32dat |= (0x1 << 4);
+ }
+ else
+ {
+ u32dat &= ~BITS(4, 5);
+ }
+ aml_writeReg(unit, SGMII_STS_CTRL_0, u32dat);
+
+ aml_readReg(unit, SGMII_REG_AN0, &u32dat);
+ u32dat &= ~BIT(12);
+ aml_writeReg(unit, SGMII_REG_AN0, u32dat);
+
+ aml_readReg(unit, PHY_RX_FORCE_CTRL_0, &u32dat);
+ u32dat |= BIT(4);
+ aml_writeReg(unit, PHY_RX_FORCE_CTRL_0, u32dat);
+
+ aml_readReg(unit, RATE_ADP_P0_CTRL_0, &u32dat);
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ u32dat &= ~BITS(0, 3);
+ }
+ else if(AIR_PORT_SPEED_100M == speed)
+ {
+ u32dat &= ~(0xf << 0);
+ u32dat |= (0xc << 0);
+ }
+ else
+ {
+ u32dat |= BITS(0, 3);
+ }
+ u32dat |= BIT(28);
+ aml_writeReg(unit, RATE_ADP_P0_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_RATE_ADAPT_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ u32dat |= BIT(4);
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ u32dat |= BITS(26, 27);
+ }
+ else
+ {
+ u32dat &= ~BITS(26, 27);
+ }
+ aml_writeReg(unit, RG_RATE_ADAPT_CTRL_0, u32dat);
+
+ }
+ else
+ {
+ /* PCS Init */
+ aml_readReg(unit, RG_HSGMII_PCS_CTROL_1, &u32dat);
+ u32dat &= ~BIT(30);
+ aml_writeReg(unit, RG_HSGMII_PCS_CTROL_1, u32dat);
+
+ /* Set AN Ability - Interrupt */
+ aml_readReg(unit, SGMII_REG_AN_FORCE_CL37, &u32dat);
+ u32dat |= BIT(0);
+ aml_writeReg(unit, SGMII_REG_AN_FORCE_CL37, u32dat);
+
+ aml_readReg(unit, SGMII_REG_AN_13, &u32dat);
+ u32dat &= ~(0x3f << 0);
+ u32dat |= (0xb << 0);
+ u32dat |= BIT(8);
+ aml_writeReg(unit, SGMII_REG_AN_13, u32dat);
+
+ /* Rate Adaption - GMII path config. */
+ aml_readReg(unit, SGMII_REG_AN0, &u32dat);
+ u32dat |= BIT(12);
+ aml_writeReg(unit, SGMII_REG_AN0, u32dat);
+
+ aml_readReg(unit, MII_RA_AN_ENABLE, &u32dat);
+ u32dat |= BIT(0);
+ aml_writeReg(unit, MII_RA_AN_ENABLE, u32dat);
+
+ aml_readReg(unit, RATE_ADP_P0_CTRL_0, &u32dat);
+ u32dat |= BIT(28);
+ aml_writeReg(unit, RATE_ADP_P0_CTRL_0, u32dat);
+
+ aml_readReg(unit, RG_RATE_ADAPT_CTRL_0, &u32dat);
+ u32dat |= BIT(0);
+ u32dat |= BIT(4);
+ u32dat |= BITS(26, 27);
+ aml_writeReg(unit, RG_RATE_ADAPT_CTRL_0, u32dat);
+
+ /* Only for Co-SIM */
+
+ /* AN Speed up (Only for Co-SIM) */
+
+ /* Restart AN */
+ aml_readReg(unit, SGMII_REG_AN0, &u32dat);
+ u32dat |= BIT(9);
+ u32dat |= BIT(15);
+ aml_writeReg(unit, SGMII_REG_AN0, u32dat);
+ }
+
+ /* bypass flow control to MAC */
+ aml_writeReg(unit, MSG_RX_LIK_STS_0, 0x01010107);
+ aml_writeReg(unit, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setRmiiMode
+ * PURPOSE:
+ * Set the port5 RMII mode for 100Mbps or 10Mbps
+ *
+ * INPUT:
+ * unit -- Device ID
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setRmiiMode(
+ const UI32_T unit,
+ const UI32_T speed)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for speed checking */
+ AIR_PARAM_CHK((speed >= AIR_PORT_SPEED_1000M), AIR_E_BAD_PARAMETER);
+
+ if(AIR_PORT_SPEED_100M == speed)
+ {
+ aml_writeReg(unit, PMCR(5), 0x93159000);
+ aml_writeReg(unit, RG_P5MUX_MODE, 0x301);
+ aml_writeReg(unit, RG_FORCE_CKDIR_SEL, 0x101);
+ aml_writeReg(unit, RG_SWITCH_MODE, 0x101);
+ aml_writeReg(unit, RG_FORCE_MAC5_SB, 0x1010101);
+ aml_writeReg(unit, CSR_RMII, 0x420102);
+ aml_writeReg(unit, RG_RGMII_TXCK_C, 0x1100910);
+ }
+ else
+ {
+ aml_writeReg(unit, PMCR(5), 0x83159000);
+ aml_writeReg(unit, RG_P5MUX_MODE, 0x301);
+ aml_writeReg(unit, RG_FORCE_CKDIR_SEL, 0x101);
+ aml_writeReg(unit, RG_SWITCH_MODE, 0x101);
+ aml_writeReg(unit, RG_FORCE_MAC5_SB, 0x1000101);
+ aml_writeReg(unit, CSR_RMII, 0x420102);
+ aml_writeReg(unit, RG_RGMII_TXCK_C, 0x1100910);
+ }
+
+ return ret;
+}
+
+/* FUNCTION NAME: air_port_setRgmiiMode
+ * PURPOSE:
+ * Set the port5 RGMII mode for 1Gbps or 100Mbps or 10Mbps
+ *
+ * INPUT:
+ * unit -- Device ID
+ * speed -- AIR_PORT_SPEED_10M: 10Mbps
+ * AIR_PORT_SPEED_100M: 100Mbps
+ * AIR_PORT_SPEED_1000M: 1Gbps
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_port_setRgmiiMode(
+ const UI32_T unit,
+ const UI32_T speed)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for speed checking */
+ AIR_PARAM_CHK((speed >= AIR_PORT_SPEED_2500M), AIR_E_BAD_PARAMETER);
+
+ if(AIR_PORT_SPEED_1000M == speed)
+ {
+ aml_writeReg(unit, PMCR(5), 0xa3159000);
+ aml_writeReg(unit, RG_FORCE_MAC5_SB, 0x20101);
+ }
+ else if(AIR_PORT_SPEED_100M == speed)
+ {
+ aml_writeReg(unit, PMCR(5), 0x93159000);
+ aml_writeReg(unit, RG_FORCE_MAC5_SB, 0x10101);
+ }
+ else
+ {
+ aml_writeReg(unit, PMCR(5), 0x83159000);
+ aml_writeReg(unit, RG_FORCE_MAC5_SB, 0x101);
+ }
+
+ return ret;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_qos.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_qos.c
new file mode 100644
index 0000000..c3829c8
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_qos.c
@@ -0,0 +1,1495 @@
+/* FILE NAME: air_qos.c
+ * PURPOSE:
+ * Define the Quailty of Service function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+ /* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* FUNCTION NAME: air_qos_setScheduleAlgo
+ * PURPOSE:
+ * Set schedule mode of a port queue.
+ * INPUT:
+ * unit -- Device unit number
+ * port -- Port id
+ * queue -- Queue id
+ * sch_mode -- AIR_QOS_SCH_MODE_T
+ * weight -- weight for WRR/WFQ
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * Weight default value is 1, only for WRR/WFQ mode
+ */
+AIR_ERROR_NO_T
+air_qos_setScheduleAlgo(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T queue,
+ const AIR_QOS_SCH_MODE_T sch_mode,
+ const UI32_T weight)
+{
+ UI32_T rc = AIR_E_OK;
+ UI32_T mac_port = 0;
+ AIR_QOS_SHAPER_MIN_T min_v;
+ AIR_QOS_SHAPER_MAX_T max_v;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((sch_mode >= AIR_QOS_SCH_MODE_LAST), AIR_E_BAD_PARAMETER);
+ if (AIR_QOS_SHAPER_NOSETTING != weight)
+ {
+ AIR_PARAM_CHK(((weight > AIR_QOS_SHAPER_RATE_MAX_WEIGHT) ||
+ (weight < AIR_QOS_SHAPER_RATE_MIN_WEIGHT)), AIR_E_BAD_PARAMETER);
+ }
+ mac_port = port;
+ min_v.byte = 0;
+ max_v.byte = 0;
+ /*Read register data*/
+ switch(queue)
+ {
+ case AIR_QOS_QUEUE_0:
+ rc += aml_readReg(unit, MMSCR0_Q0(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q0(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_1:
+ rc += aml_readReg(unit, MMSCR0_Q1(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q1(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_2:
+ rc += aml_readReg(unit, MMSCR0_Q2(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q2(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_3:
+ rc += aml_readReg(unit, MMSCR0_Q3(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q3(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_4:
+ rc += aml_readReg(unit, MMSCR0_Q4(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q4(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_5:
+ rc += aml_readReg(unit, MMSCR0_Q5(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q5(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_6:
+ rc += aml_readReg(unit, MMSCR0_Q6(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q6(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_7:
+ rc += aml_readReg(unit, MMSCR0_Q7(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q7(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ default:
+ AIR_PRINT("Not Support this queue %d num, please check again\n", queue);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ /*Get para*/
+ switch(sch_mode)
+ {
+ case AIR_QOS_SCH_MODE_SP:
+ min_v.raw.min_sp_wrr_q = 1;
+ min_v.raw.min_rate_en = 0;
+ break;
+
+ case AIR_QOS_SCH_MODE_WRR:
+ min_v.raw.min_sp_wrr_q = 0;
+ min_v.raw.min_rate_en = 0;
+ min_v.raw.min_weight = weight - 1;
+ break;
+
+ case AIR_QOS_SCH_MODE_WFQ:
+ min_v.raw.min_sp_wrr_q = 1;
+ min_v.raw.min_rate_en = 1;
+ min_v.raw.min_rate_man = 0;
+ min_v.raw.min_rate_exp = 0;
+
+ max_v.raw.max_rate_en = 0;
+ max_v.raw.max_sp_wfq_q = 0;
+ max_v.raw.max_weight = weight - 1;
+ break;
+ default:
+ AIR_PRINT("Not Support this mode %d num, please check again\n", sch_mode);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ /*Send to driver*/
+ switch(queue)
+ {
+ case AIR_QOS_QUEUE_0:
+ rc += aml_writeReg(unit, MMSCR0_Q0(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q0(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_1:
+ rc += aml_writeReg(unit, MMSCR0_Q1(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q1(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_2:
+ rc += aml_writeReg(unit, MMSCR0_Q2(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q2(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_3:
+ rc += aml_writeReg(unit, MMSCR0_Q3(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q3(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_4:
+ rc += aml_writeReg(unit, MMSCR0_Q4(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q4(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_5:
+ rc += aml_writeReg(unit, MMSCR0_Q5(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q5(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_6:
+ rc += aml_writeReg(unit, MMSCR0_Q6(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q6(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_7:
+ rc += aml_writeReg(unit, MMSCR0_Q7(mac_port), min_v.byte);
+ rc += aml_writeReg(unit, MMSCR1_Q7(mac_port), max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Set port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ default:
+ AIR_PRINT("Not Support this queue %d num, please check again\n", queue);
+ return AIR_E_BAD_PARAMETER;
+ }
+ AIR_PRINT("Set schedule mode success,port is %d, queue is %d, min hex is %x, max hex is %x\n", port, queue, min_v.byte, max_v.byte);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_getScheduleAlgo
+ * PURPOSE:
+ * Get schedule mode of a port queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Port id
+ * queue -- Queue id
+ * OUTPUT:
+ * ptr_sch_mode -- AIR_QOS_SCH_MODE_T
+ * ptr_weight -- weight for WRR/WFQ
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getScheduleAlgo(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T queue,
+ AIR_QOS_SCH_MODE_T *ptr_sch_mode,
+ UI32_T *ptr_weight)
+{
+ UI32_T rc = AIR_E_OK;
+ UI32_T mac_port = 0;
+ AIR_QOS_SHAPER_MIN_T min_v;
+ AIR_QOS_SHAPER_MAX_T max_v;
+
+ /*Read register data*/
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_sch_mode);
+ AIR_CHECK_PTR(ptr_weight);
+
+ mac_port = port;
+ min_v.byte = 0;
+ max_v.byte = 0;
+
+ switch(queue)
+ {
+ case AIR_QOS_QUEUE_0:
+ rc += aml_readReg(unit, MMSCR0_Q0(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q0(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_1:
+ rc += aml_readReg(unit, MMSCR0_Q1(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q1(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_2:
+ rc += aml_readReg(unit, MMSCR0_Q2(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q2(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_3:
+ rc += aml_readReg(unit, MMSCR0_Q3(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q3(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_4:
+ rc += aml_readReg(unit, MMSCR0_Q4(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q4(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_5:
+ rc += aml_readReg(unit, MMSCR0_Q5(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q5(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_6:
+ rc += aml_readReg(unit, MMSCR0_Q6(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q6(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ case AIR_QOS_QUEUE_7:
+ rc += aml_readReg(unit, MMSCR0_Q7(mac_port), &min_v.byte);
+ rc += aml_readReg(unit, MMSCR1_Q7(mac_port), &max_v.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("Get port %d queue %d failed, rc is %d", port, queue, rc);
+ return AIR_E_OTHERS;
+ }
+ break;
+
+ default:
+ AIR_PRINT("Not Support this queue %d num, please check again", queue);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ /*Send para*/
+ if ((min_v.raw.min_rate_en) && AIR_QOS_MAX_TRAFFIC_ARBITRATION_SCHEME_WFQ == max_v.raw.max_sp_wfq_q)
+ {
+ *ptr_sch_mode = AIR_QOS_SCH_MODE_WFQ;
+ *ptr_weight = max_v.raw.max_weight + 1;
+ }
+ else
+ {
+ if(AIR_QOS_MIN_TRAFFIC_ARBITRATION_SCHEME_WRR == min_v.raw.min_sp_wrr_q)
+ {
+ *ptr_sch_mode = AIR_QOS_SCH_MODE_WRR;
+ *ptr_weight = min_v.raw.min_weight + 1;
+ }
+ else if(AIR_QOS_MIN_TRAFFIC_ARBITRATION_SCHEME_SP == min_v.raw.min_sp_wrr_q)
+ {
+ *ptr_sch_mode = AIR_QOS_SCH_MODE_SP;
+ *ptr_weight = AIR_QOS_SHAPER_NOSETTING;
+ }
+ }
+ AIR_PRINT("Get schedule mode success,port is %d, queue is %d, min hex is %x, max hex is %x\n", port, queue, min_v.byte, max_v.byte);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_setTrustMode
+ * PURPOSE:
+ * Set qos trust mode value.
+ * INPUT:
+ * unit -- Device unit number
+ * port -.Select port number
+ * mode -- Qos support mode
+ * AIR_QOS_TRUST_MODE_T
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Operation success.
+ * AIR_E_BAD_PARAMETER -- Parameter is wrong.
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_qos_setTrustMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_TRUST_MODE_T mode)
+
+{
+ UI32_T rc = AIR_E_OTHERS;
+ AIR_QOS_QUEUE_UPW_T stat;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((mode >= AIR_QOS_TRUST_MODE_LAST), AIR_E_BAD_PARAMETER);
+
+ stat.byte = 0;
+ /*get register val*/
+ rc = aml_readReg(unit, PUPW(port), &(stat.byte));
+ AIR_PRINT("[Dbg]: get port %d rate trust weight success, UPW hex is %x\n", port, stat.byte);
+ stat.byte = AIR_QOS_QUEUE_DEFAULT_VAL;
+ if(AIR_E_OK == rc)
+ {
+ switch(mode)
+ {
+ case AIR_QOS_TRUST_MODE_PORT:
+ stat.raw.csr_port_weight = AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT;
+ break;
+
+ case AIR_QOS_TRUST_MODE_1P_PORT:
+ stat.raw.csr_1p_weight = AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT;
+ stat.raw.csr_port_weight = AIR_QOS_QUEUE_TRUST_MID_WEIGHT;
+ break;
+
+ case AIR_QOS_TRUST_MODE_DSCP_PORT:
+ stat.raw.csr_dscp_weight = AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT;
+ stat.raw.csr_port_weight = AIR_QOS_QUEUE_TRUST_MID_WEIGHT;
+ break;
+
+ case AIR_QOS_TRUST_MODE_DSCP_1P_PORT:
+ stat.raw.csr_dscp_weight = AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT;
+ stat.raw.csr_1p_weight = AIR_QOS_QUEUE_TRUST_MID_WEIGHT;
+ stat.raw.csr_port_weight = AIR_QOS_QUEUE_TRUST_LOW_WEIGHT;
+ break;
+
+ default:
+ AIR_PRINT("Not Support this mode %d yet\n", mode);
+ return AIR_E_BAD_PARAMETER;
+
+ }
+ }
+
+ /*set register val*/
+ rc = aml_writeReg(unit, PUPW(port), stat.byte);
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("[Dbg]: set port %d rate trust mode failed rc is %d\n", port, rc);
+ }
+ else
+ {
+ AIR_PRINT("[Dbg]: set port %d rate trust mode %d weight success, UPW hex is %x\n", port, mode, stat.byte);
+ }
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_getTrustMode
+ * PURPOSE:
+ * Get qos trust mode value.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -.Select port number
+ * OUTPUT:
+ * ptr_weight -- All Qos weight value
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getTrustMode(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_TRUST_MODE_T *const ptr_mode)
+
+{
+ UI32_T rc = AIR_E_OTHERS;
+ AIR_QOS_QUEUE_UPW_T stat;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_mode);
+
+ /*get register val*/
+ stat.byte = 0;
+ *ptr_mode = AIR_QOS_TRUST_MODE_1P_PORT;
+ rc = aml_readReg(unit, PUPW(port), &(stat.byte));
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("[Dbg]: get port %d rate trust mode failed rc is %d\n",port, rc);
+ }
+ else
+ {
+ if (AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT == stat.raw.csr_1p_weight)
+ {
+ *ptr_mode = AIR_QOS_TRUST_MODE_1P_PORT;
+ }
+ else if (AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT == stat.raw.csr_dscp_weight)
+ {
+ if (AIR_QOS_QUEUE_TRUST_MID_WEIGHT == stat.raw.csr_1p_weight)
+ {
+ *ptr_mode = AIR_QOS_TRUST_MODE_DSCP_1P_PORT;
+ }
+ else if (AIR_QOS_QUEUE_TRUST_MID_WEIGHT == stat.raw.csr_port_weight)
+ {
+ *ptr_mode = AIR_QOS_TRUST_MODE_DSCP_PORT;
+ }
+ }
+ else if (AIR_QOS_QUEUE_TRUST_HIGH_WEIGHT == stat.raw.csr_port_weight)
+ {
+ *ptr_mode = AIR_QOS_TRUST_MODE_PORT;
+ }
+ else
+ {
+ AIR_PRINT("[Dbg]: port %d Not support this trust mode, UPW hex is %x\n", port, stat.byte);
+ }
+ }
+ AIR_PRINT("[Dbg]: port %d get trust mode success, UPW hex is %x\n", port, stat.byte);
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_setPri2Queue
+ * PURPOSE:
+ * Set per port priority to out queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pri -- Qos pri value
+ * queue -- Qos Queue value
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setPri2Queue(
+ const UI32_T unit,
+ const UI32_T pri,
+ const UI32_T queue)
+{
+ UI32_T rc = AIR_E_OTHERS;
+ AIR_QOS_QUEUE_PEM_T stat;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((queue >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pri >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+
+ stat.byte = 0;
+ /*get register val*/
+ switch(pri / 2)
+ {
+ case 0:
+ rc = aml_readReg(unit, PEM1, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ stat.raw.csr_que_cpu_h = queue;
+ }
+ else
+ {
+ stat.raw.csr_que_cpu_l = queue;
+ }
+ }
+ rc = aml_writeReg(unit, PEM1, stat.byte);
+ break;
+
+ case 1:
+ rc = aml_readReg(unit, PEM2, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ stat.raw.csr_que_cpu_h = queue;
+ }
+ else
+ {
+ stat.raw.csr_que_cpu_l = queue;
+ }
+ }
+ rc = aml_writeReg(unit, PEM2, stat.byte);
+ break;
+
+ case 2:
+ rc = aml_readReg(unit, PEM3, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ stat.raw.csr_que_cpu_h = queue;
+ }
+ else
+ {
+ stat.raw.csr_que_cpu_l = queue;
+ }
+ }
+ rc = aml_writeReg(unit, PEM3, stat.byte);
+ break;
+
+ case 3:
+ rc = aml_readReg(unit, PEM4, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ stat.raw.csr_que_cpu_h = queue;
+ }
+ else
+ {
+ stat.raw.csr_que_cpu_l = queue;
+ }
+ }
+ rc = aml_writeReg(unit, PEM4, stat.byte);
+ break;
+
+ default:
+ AIR_PRINT("[Dbg]: Not Support this pri %d yet\n", pri);
+ return AIR_E_BAD_PARAMETER;
+ }
+ AIR_PRINT("[Dbg]: set pri %d to queue %d success, PEM hex is %x\n"
+ , pri, queue, stat.byte);
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_getPri2Queue
+ * PURPOSE:
+ * Get per port priority to out queue.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * pri -- Qos pri value
+ *
+ * OUTPUT:
+ * ptr_queue -- Select out queue (0..7)
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getPri2Queue(
+ const UI32_T unit,
+ const UI32_T pri,
+ UI32_T *const ptr_queue)
+{
+ UI32_T rc = AIR_E_OTHERS;
+ AIR_QOS_QUEUE_PEM_T stat;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pri >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_queue);
+
+ /*get register val*/
+ stat.byte = 0;
+ switch(pri / 2)
+ {
+ case 0:
+ rc = aml_readReg(unit, PEM1, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_h;
+ }
+ else
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_l;
+ }
+ }
+ break;
+
+ case 1:
+ rc = aml_readReg(unit, PEM2, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_h;
+ }
+ else
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_l;
+ }
+ }
+ break;
+
+ case 2:
+ rc = aml_readReg(unit, PEM3, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_h;
+ }
+ else
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_l;
+ }
+ }
+ break;
+
+ case 3:
+ rc = aml_readReg(unit, PEM4, &stat.byte);
+ if(AIR_E_OK == rc)
+ {
+ if (1 == pri % 2)
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_h;
+ }
+ else
+ {
+ *ptr_queue = stat.raw.csr_que_cpu_l;
+ }
+ }
+ break;
+
+ default:
+ AIR_PRINT("[Dbg]: Not Support this pri %d yet\n", pri);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("[Dbg]: get pri to queue failed rc is %d\n", rc);
+ }
+
+ AIR_PRINT("[Dbg]: get pri %d to queue %d mode success, PEM hex is %x\n"
+ , pri, *ptr_queue, stat.byte);
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_setDscp2Pri
+ * PURPOSE:
+ * Set DSCP mapping to priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dscp -- Select DSCP value (0..63)
+ * priority -- Select priority (0..7)
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setDscp2Pri(
+ const UI32_T unit,
+ const UI32_T dscp,
+ const UI32_T pri)
+{
+ UI32_T rc = AIR_E_OTHERS;
+ UI32_T reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dscp >= AIR_QOS_QUEUE_DSCP_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pri >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+
+ /*get register val*/
+ switch (dscp/10)
+ {
+ case 0:
+ rc = aml_readReg(unit, PIM1, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << 3 * (dscp % 10);
+ rc = aml_writeReg(unit, PIM1, reg);
+ }
+ break;
+
+ case 1:
+ rc = aml_readReg(unit, PIM2, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM2, reg);
+ }
+ break;
+
+ case 2:
+ rc = aml_readReg(unit, PIM3, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM3, reg);
+ }
+ break;
+
+ case 3:
+ rc = aml_readReg(unit, PIM4, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM4, reg);
+ }
+ break;
+
+ case 4:
+ rc = aml_readReg(unit, PIM5, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM5, reg);
+ }
+ break;
+
+ case 5:
+ rc = aml_readReg(unit, PIM6, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM6, reg);
+ }
+ break;
+
+ case 6:
+ rc = aml_readReg(unit, PIM7, ®);
+ if(AIR_E_OK == rc)
+ {
+ reg &= ~(AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10));
+ reg |= pri << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ rc = aml_writeReg(unit, PIM7, reg);
+ }
+ break;
+
+ default:
+ AIR_PRINT("Not Support this dscp %d to pri, rc is %d\n", dscp, rc);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("set dscp to pri failed ,rc is %d\n", rc);
+ }
+ else
+ {
+ AIR_PRINT("set dscp %u to pri %u success, PIM hex is %x\n", dscp, pri, reg);
+ }
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_getDscp2Pri
+ * PURPOSE:
+ * Get DSCP mapping priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dscp -- Select DSCP value (0..63)
+ *
+ * OUTPUT:
+ * ptr_pri -- Priority value (0..7)
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getDscp2Pri(
+ const UI32_T unit,
+ const UI32_T dscp,
+ UI32_T * const ptr_pri)
+{
+ UI32_T rc = AIR_E_OTHERS;
+ UI32_T reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dscp >= AIR_QOS_QUEUE_DSCP_MAX_NUM), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_pri);
+
+ /*get register val*/
+ switch (dscp/10)
+ {
+ case 0:
+ rc = aml_readReg(unit, PIM1, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 1:
+ rc = aml_readReg(unit, PIM2, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 2:
+ rc = aml_readReg(unit, PIM3, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 3:
+ rc = aml_readReg(unit, PIM4, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 4:
+ rc = aml_readReg(unit, PIM5, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 5:
+ rc = aml_readReg(unit, PIM6, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ case 6:
+ rc = aml_readReg(unit, PIM7, ®);
+ if(AIR_E_OK == rc)
+ {
+ *ptr_pri = (reg & (AIR_QOS_QUEUE_PIM_MASK << AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10)))
+ >> AIR_QOS_QUEUE_PIM_WIDTH * (dscp % 10);
+ }
+ break;
+
+ default:
+ AIR_PRINT("Not Support this dscp %d to pri, rc is %d\n", dscp, rc);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ if(AIR_E_OK != rc)
+ {
+ AIR_PRINT("[Dbg]: get dscp %d to pri failed, rc is %d\n", dscp, rc);
+ }
+
+ AIR_PRINT("[Dbg]: get dscp %u to pri %d success, PIM hex is %d \n", dscp, *ptr_pri, reg);
+ return rc;
+}
+
+/* FUNCTION NAME: air_qos_setRateLimitEnable
+ * PURPOSE:
+ * Enable or disable port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_QOS_RATE_DIR_INGRESS
+ * AIR_QOS_RATE_DIR_EGRESS
+ * rate_en -- TRUE: eanble rate limit
+ * FALSE: disable rate limit
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimitEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_RATE_DIR_T dir,
+ const BOOL_T enable)
+{
+ UI32_T u32dat = 0, reg = 0;
+ UI32_T u32glo = 0, greg = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dir >= AIR_QOS_RATE_DIR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((enable != TRUE && enable != FALSE), AIR_E_BAD_PARAMETER);
+
+ mac_port = port;
+ if(AIR_QOS_RATE_DIR_EGRESS == dir)
+ {
+ reg = ERLCR(mac_port);
+ greg = GERLCR;
+ }
+ else if (AIR_QOS_RATE_DIR_INGRESS == dir)
+ {
+ reg = IRLCR(mac_port);
+ greg = GIRLCR;
+ }
+ else
+ {
+ AIR_PRINT("Not Support this dir %d yet\n", dir);
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ aml_readReg(unit, reg, &u32dat);
+ if(TRUE == enable)
+ {
+ u32dat |= BIT(REG_RATE_EN_OFFT);
+ /* Enable tobke bucket mode */
+ u32dat |= BIT(REG_TB_EN_OFFT);
+ }
+ else
+ {
+ u32dat &= ~(BIT(REG_RATE_EN_OFFT));
+ /* Disable tobke bucket mode */
+ u32dat &= ~(BIT(REG_TB_EN_OFFT));
+ }
+ aml_writeReg(unit, reg, u32dat);
+
+ /* Rate include preamble/IPG/CRC */
+ aml_readReg(unit, greg, &u32glo);
+ u32glo &= ~(BITS_RANGE(REG_IPG_BYTE_OFFT, REG_IPG_BYTE_LENG));
+ u32glo |= AIR_QOS_L1_RATE_LIMIT;
+ aml_writeReg(unit, greg, u32glo);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_getRateLimitEnable
+ * PURPOSE:
+ * Get port rate limit state.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number (0..6)
+ * dir -- AIR_QOS_RATE_DIR_T
+ * OUTPUT:
+ * ptr_enable -- TRUE: eanble rate limit
+ * FALSE: disable rate limit
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimitEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_QOS_RATE_DIR_T dir,
+ BOOL_T *ptr_enable)
+{
+ UI32_T u32dat = 0, reg = 0, ret = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dir >= AIR_QOS_RATE_DIR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ mac_port = port;
+ /* Get ingress / egress register value */
+ if(AIR_QOS_RATE_DIR_EGRESS == dir)
+ {
+ reg = ERLCR(mac_port);
+ }
+ else
+ {
+ reg = IRLCR(mac_port);
+ }
+ aml_readReg(unit, reg, &u32dat);
+
+ ret = (u32dat & BIT(REG_RATE_EN_OFFT));
+ if(!ret)
+ {
+ *ptr_enable = FALSE;
+ }
+ else
+ {
+ *ptr_enable = TRUE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_setRateLimit
+ * PURPOSE:
+ * Set per port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * ptr_cfg -- AIR_QOS_RATE_LIMIT_CFG_T
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimit(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_RATE_LIMIT_CFG_T *ptr_cfg)
+{
+ UI32_T u32dat = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_cfg);
+ AIR_PARAM_CHK((ptr_cfg->egress_cbs >= AIR_QOS_MAX_TOKEN), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_cfg->ingress_cbs >= AIR_QOS_MAX_TOKEN), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_cfg->egress_cir >= AIR_QOS_MAX_CIR), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_cfg->ingress_cir >= AIR_QOS_MAX_CIR), AIR_E_BAD_PARAMETER);
+
+ mac_port = port;
+ /* For Egress rate setting */
+ /* Set egress rate CIR */
+ aml_readReg(unit, ERLCR(mac_port), &u32dat);
+ u32dat &= ~ BITS_RANGE(REG_RATE_CIR_OFFT, REG_RATE_CIR_LENG);
+ u32dat |= ptr_cfg->egress_cir;
+ /* Set egress rate CBS */
+ u32dat &= ~ BITS_RANGE(REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+ u32dat |= BITS_OFF_L(ptr_cfg->egress_cbs, REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+ /* Enable tobke bucket mode */
+ u32dat |= BIT(REG_TB_EN_OFFT);
+ /* Set token period to 4ms */
+ u32dat &= ~ BITS_RANGE(REG_RATE_TB_OFFT, REG_RATE_TB_LENG);
+ u32dat |= BITS_OFF_L(AIR_QOS_TOKEN_PERIOD_4MS, REG_RATE_TB_OFFT, REG_RATE_TB_LENG);
+ if(ptr_cfg->flags & AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_EGRESS)
+ {
+ /* Enable ratelimit mode*/
+ u32dat |= BIT(REG_RATE_EN_OFFT);
+ }
+ aml_writeReg(unit, ERLCR(mac_port), u32dat);
+
+
+ /* For Ingress rate setting */
+ /* Set ingress rate CIR */
+ aml_readReg(unit, IRLCR(mac_port), &u32dat);
+ u32dat &= ~ BITS_RANGE(REG_RATE_CIR_OFFT, REG_RATE_CIR_LENG);
+ u32dat |= ptr_cfg->ingress_cir;
+ /* Set egress rate CBS */
+ u32dat &= ~ BITS_RANGE(REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+ u32dat |= BITS_OFF_L(ptr_cfg->ingress_cbs, REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+ /* Enable tobke bucket mode */
+ u32dat |= BIT(REG_TB_EN_OFFT);
+ /* Set token period to 4ms */
+ u32dat &= ~ BITS_RANGE(REG_RATE_TB_OFFT, REG_RATE_TB_LENG);
+ u32dat |= BITS_OFF_L(AIR_QOS_TOKEN_PERIOD_4MS, REG_RATE_TB_OFFT, REG_RATE_TB_LENG);
+ if(ptr_cfg->flags & AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_INGRESS)
+ {
+ /* Enable ratelimit mode*/
+ u32dat |= BIT(REG_RATE_EN_OFFT);
+ }
+ aml_writeReg(unit, IRLCR(mac_port), u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_getRateLimit
+ * PURPOSE:
+ * Get per port rate limit.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ *
+ * OUTPUT:
+ * ptr_cfg -- AIR_QOS_RATE_LIMIT_CFG_T
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimit(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_QOS_RATE_LIMIT_CFG_T *ptr_cfg)
+{
+ UI32_T u32dat = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_cfg);
+
+ mac_port = port;
+ /* For Egress rate info */
+ aml_readReg(unit, ERLCR(mac_port), &u32dat);
+ ptr_cfg->egress_cir = BITS_OFF_R(u32dat, REG_RATE_CIR_OFFT, REG_RATE_CIR_LENG);
+ ptr_cfg->egress_cbs = BITS_OFF_R(u32dat, REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+
+ /* For Ingress rate info */
+ aml_readReg(unit, IRLCR(mac_port), &u32dat);
+ ptr_cfg->ingress_cir = BITS_OFF_R(u32dat, REG_RATE_CIR_OFFT, REG_RATE_CIR_LENG);
+ ptr_cfg->ingress_cbs = BITS_OFF_R(u32dat, REG_RATE_CBS_OFFT, REG_RATE_CBS_LENG);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_setPortPriority
+ * PURPOSE:
+ * Get poer port based priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * priority -- Select port priority
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setPortPriority(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T priority)
+{
+ UI32_T regPCR = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((priority >= AIR_QOS_QUEUE_MAX_NUM), AIR_E_BAD_PARAMETER);
+ mac_port = port;
+ aml_readReg(unit, PCR(mac_port), ®PCR);
+ regPCR &= ~PCR_PORT_PRI_MASK;
+ regPCR |= (priority & PCR_PORT_PRI_RELMASK) << PCR_PORT_PRI_OFFT;
+ aml_writeReg(unit, PCR(mac_port), regPCR);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_getPortPriority
+ * PURPOSE:
+ * Set per port based priority.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ *
+ * OUTPUT:
+ * ptr_pri -- Get port based priority
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getPortPriority(
+ const UI32_T unit,
+ const UI32_T port,
+ UI32_T *ptr_pri)
+{
+ UI32_T regPCR = 0;
+ UI32_T mac_port = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_pri);
+ mac_port = port;
+ aml_readReg(unit, PCR(mac_port), ®PCR);
+ *ptr_pri = (regPCR >> PCR_PORT_PRI_OFFT) & PCR_PORT_PRI_RELMASK;
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_setRateLimitExMngFrm
+ * PURPOSE:
+ * Set rate limit control exclude/include management frames.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dir -- AIR_RATE_DIR_INGRESS
+ * AIR_RATE_DIR_EGRESS
+ * exclude -- TRUE: Exclude management frame
+ * FALSE:Include management frame
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_setRateLimitExMngFrm(
+ const UI32_T unit,
+ const AIR_QOS_RATE_DIR_T dir,
+ const BOOL_T exclude)
+{
+ UI32_T u32dat = 0, reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dir != AIR_QOS_RATE_DIR_EGRESS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != exclude) && (FALSE != exclude)), AIR_E_BAD_PARAMETER);
+
+ reg = GERLCR;
+ /* Set to register */
+ aml_readReg(unit, reg, &u32dat);
+ if(TRUE == exclude)
+ {
+ u32dat |= BIT(REG_MFRM_EX_OFFT);
+ }
+ else
+ {
+ u32dat &= ~(BIT(REG_MFRM_EX_OFFT));
+ }
+ aml_writeReg(unit, reg, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_qos_getRateLimitExMngFrm
+ * PURPOSE:
+ * Get rate limit control exclude/include management frames.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * dir -- AIR_RATE_DIR_INGRESS
+ * AIR_RATE_DIR_EGRESS
+ * OUTPUT:
+ * ptr_exclude -- TRUE: Exclude management frame
+ * FALSE:Include management frame
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_qos_getRateLimitExMngFrm(
+ const UI32_T unit,
+ const AIR_QOS_RATE_DIR_T dir,
+ BOOL_T *ptr_exclude)
+{
+ UI32_T reg = 0, u32dat = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((unit >= AIR_MAX_NUM_OF_UNIT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((dir >= AIR_QOS_RATE_DIR_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_exclude);
+
+
+ if(AIR_QOS_RATE_DIR_EGRESS == dir)
+ {
+ reg = GERLCR;
+ }
+ else
+ {
+ reg = GIRLCR;
+ }
+
+ /* Set to register */
+ aml_readReg(unit, reg, &u32dat);
+ if(BITS_OFF_R(u32dat, REG_MFRM_EX_OFFT, REG_MFRM_EX_LENG))
+ {
+ *ptr_exclude = TRUE;
+ }
+ else
+ {
+ *ptr_exclude = FALSE;
+ }
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sec.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sec.c
new file mode 100644
index 0000000..336a14f
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sec.c
@@ -0,0 +1,593 @@
+/* FILE NAME: air_sec.c
+ * PURPOSE:
+ * Define the security function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* FUNCTION NAME: air_sec_setStormEnable
+ * PURPOSE:
+ * Enable or disable per port storm control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * storm_en -- TRUE
+ * FALSE
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setStormEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ const BOOL_T storm_en)
+{
+ UI32_T u32dat = 0, reg = 0, sp_en = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_STORM_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((storm_en != TRUE) && (storm_en != FALSE)), AIR_E_BAD_PARAMETER);
+
+ /* Find register BSR:broadcast, BSR_EXT1:multicast, BSR_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR(port);
+ sp_en = BSR_STORM_BCST_EN;
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR_EXT1(port);
+ sp_en = BSR_STORM_MCST_EN;
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR_EXT2(port);
+ sp_en = BSR_STORM_UCST_EN;
+ break;
+ default:
+ break;
+ }
+
+ /* Enable specific type */
+ aml_readReg(unit, reg, &u32dat);
+ if(TRUE == storm_en)
+ {
+ u32dat |= (BSR_STORM_DROP_EN | BSR_STORM_RATE_BASED);
+ u32dat |= sp_en;
+ }
+ else
+ {
+ u32dat &= ~(BSR_STORM_DROP_EN | BSR_STORM_RATE_BASED);
+ u32dat &= ~sp_en;
+ }
+ aml_writeReg(unit, reg, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_getStormEnable
+ * PURPOSE:
+ * Get per port status of storm control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * OUTPUT:
+ * ptr_storm_en -- TRUE
+ * FALSE
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getStormEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ BOOL_T *ptr_storm_en)
+{
+ UI32_T u32dat = 0, reg = 0, en = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_STORM_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_storm_en);
+
+ /* Find register BSR:broadcast, BSR_EXT1:multicast, BSR_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR(port);
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR_EXT1(port);
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR_EXT2(port);
+ break;
+ default:
+ break;
+ }
+
+ /* Enable specific type */
+ aml_readReg(unit, reg, &u32dat);
+ en = (u32dat & BSR_STORM_DROP_EN);
+ if(FALSE == en)
+ {
+ *ptr_storm_en = FALSE;
+ }
+ else
+ {
+ *ptr_storm_en = TRUE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_setStormRate
+ * PURPOSE:
+ * Set per port storm rate limit control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * count -- Count of the unit
+ * Range 0..255
+ * Rate = (count * unit) bps
+ * unit -- AIR_STORM_UNIT_64K
+ * AIR_STORM_UNIT_256K
+ * AIR_STORM_UNIT_1M
+ * AIR_STORM_UNIT_4M
+ * AIR_STORM_UNIT_16M
+ AIR_STORM_UNIT_32M
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setStormRate(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ const UI32_T count,
+ const AIR_STORM_UNIT_T storm_unit)
+{
+ UI32_T u32dat = 0, reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_STORM_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((count > AIR_STORM_MAX_COUNT), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((storm_unit >= AIR_STORM_UNIT_LAST), AIR_E_BAD_PARAMETER);
+
+ /* Find register BSR:broadcast, BSR_EXT1:multicast, BSR_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR(port);
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR_EXT1(port);
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR_EXT2(port);
+ break;
+ default:
+ break;
+ }
+ /* Set storm rate limit unit */
+ aml_readReg(unit, reg, &u32dat);
+ u32dat &= ~(BSR_STORM_UNIT_MSK << BSR_STORM_UNIT_OFFT);
+ u32dat |= (storm_unit << BSR_STORM_UNIT_OFFT);
+ aml_writeReg(unit, reg, u32dat);
+
+ /* Find register BSR1:broadcast, BSR1_EXT1:multicast, BSR1_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR1(port);
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR1_EXT1(port);
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR1_EXT2(port);
+ break;
+ default:
+ break;
+ }
+ /* Set storm rate limit count */
+ u32dat &= ~(BSR_STORM_COUNT_MSK << BSR1_10M_COUNT_OFFT);
+ u32dat |= (count << BSR1_10M_COUNT_OFFT);
+
+ u32dat &= ~(BSR_STORM_COUNT_MSK << BSR1_100M_COUNT_OFFT);
+ u32dat |= (count << BSR1_100M_COUNT_OFFT);
+
+ u32dat &= ~(BSR_STORM_COUNT_MSK << BSR1_1000M_COUNT_OFFT);
+ u32dat |= (count << BSR1_1000M_COUNT_OFFT);
+
+ u32dat &= ~(BSR_STORM_COUNT_MSK << BSR1_2500M_COUNT_OFFT);
+ u32dat |= (count << BSR1_2500M_COUNT_OFFT);
+ aml_writeReg(unit, reg, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_getStormRate
+ * PURPOSE:
+ * Get per port storm rate limit control for specific type.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port number
+ * type -- AIR_STORM_TYPE_BCST
+ * AIR_STORM_TYPE_MCST
+ * AIR_STORM_TYPE_UCST
+ * OUTPUT:
+ * ptr_count -- Count of the unit
+ * Range 0..255
+ * Rate = (count * unit) bps
+ * ptr_unit -- AIR_STORM_UNIT_64K
+ * AIR_STORM_UNIT_256K
+ * AIR_STORM_UNIT_1M
+ * AIR_STORM_UNIT_4M
+ * AIR_STORM_UNIT_16M
+ * AIR_STORM_UNIT_32M
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getStormRate(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_STORM_TYPE_T type,
+ UI32_T *ptr_count,
+ AIR_STORM_UNIT_T *ptr_unit)
+{
+ UI32_T u32dat = 0, reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_STORM_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_count);
+ AIR_CHECK_PTR(ptr_unit);
+
+ /* Find register BSR:broadcast, BSR_EXT1:multicast, BSR_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR(port);
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR_EXT1(port);
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR_EXT2(port);
+ break;
+ default:
+ break;
+ }
+ aml_readReg(unit, reg, &u32dat);
+ /* Get storm rate limit unit */
+ *ptr_unit = (BSR_STORM_UNIT_MSK & (u32dat >> BSR_STORM_UNIT_OFFT));
+
+ /* Find register BSR1:broadcast, BSR1_EXT1:multicast, BSR1_EXT2:unicast */
+ switch(type)
+ {
+ case AIR_STORM_TYPE_BCST:
+ reg = BSR1(port);
+ break;
+ case AIR_STORM_TYPE_MCST:
+ reg = BSR1_EXT1(port);
+ break;
+ case AIR_STORM_TYPE_UCST:
+ reg = BSR1_EXT2(port);
+ break;
+ default:
+ break;
+ }
+ aml_readReg(unit, reg, &u32dat);
+ /* Get storm rate limit count */
+ *ptr_count = (u32dat & BSR_STORM_COUNT_MSK);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_setFldMode
+ * PURPOSE:
+ * Set per port flooding status for unknown type frame.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port to setting
+ * type -- AIR_FLOOD_TYPE_BCST
+ * AIR_FLOOD_TYPE_MCST
+ * AIR_FLOOD_TYPE_UCST
+ * AIR_FLOOD_TYPE_QURY
+ * fld_en -- TRUE : flooding specific type frame for specific port
+ * FALSE: drop specific type frame for specific port
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setFldMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_FLOOD_TYPE_T type,
+ const BOOL_T fld_en)
+{
+ UI32_T u32dat = 0, reg = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_FLOOD_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((fld_en != TRUE) && (fld_en != FALSE)), AIR_E_BAD_PARAMETER);
+
+ /* Find register */
+ switch(type)
+ {
+ case AIR_FLOOD_TYPE_BCST:
+ reg = BCF;
+ break;
+ case AIR_FLOOD_TYPE_MCST:
+ reg = UNMF;
+ break;
+ case AIR_FLOOD_TYPE_UCST:
+ reg = UNUF;
+ break;
+ case AIR_FLOOD_TYPE_QURY:
+ reg = QRYP;
+ break;
+ default:
+ break;
+ }
+
+ aml_readReg(unit, reg, &u32dat);
+ if(TRUE == fld_en)
+ {
+ u32dat |= BIT(port);
+ }
+ else
+ {
+ u32dat &= ~BIT(port);
+ }
+ aml_writeReg(unit, reg, u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_getFldMode
+ * PURPOSE:
+ * Get per port flooding status for unknown type frame.
+ *
+ * INPUT:
+ * unit -- Select device ID
+ * port -- Select port to setting
+ * type -- AIR_FLOOD_TYPE_BCST
+ * AIR_FLOOD_TYPE_MCST
+ * AIR_FLOOD_TYPE_UCST
+ * AIR_FLOOD_TYPE_QURY
+ * OUTPUT:
+ * ptr_fld_en -- TRUE : flooding specific type frame for specific port
+ * FALSE: drop specific type frame for specific port
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_getFldMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_FLOOD_TYPE_T type,
+ BOOL_T *ptr_fld_en)
+{
+ UI32_T u32dat = 0, reg = 0, value = 0;
+
+ /* Check parameter */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_FLOOD_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_fld_en);
+
+ /* Find register */
+ switch(type)
+ {
+ case AIR_FLOOD_TYPE_BCST:
+ reg = BCF;
+ break;
+ case AIR_FLOOD_TYPE_MCST:
+ reg = UNMF;
+ break;
+ case AIR_FLOOD_TYPE_UCST:
+ reg = UNUF;
+ break;
+ case AIR_FLOOD_TYPE_QURY:
+ reg = QRYP;
+ break;
+ default:
+ break;
+ }
+
+ aml_readReg(unit, reg, &u32dat);
+ value = u32dat & BIT(port);
+ if(FALSE == value)
+ {
+ *ptr_fld_en = FALSE;
+ }
+ else
+ {
+ *ptr_fld_en = TRUE;
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sec_setPortSecPortCfg
+ * PURPOSE:
+ * Set port security configurations for specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Port ID
+ * port_config -- Structure of port configuration.
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sec_setPortSecPortCfg(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_SEC_PORTSEC_PORT_CONFIG_T port_config)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T u32dat = 0, value = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != port_config.sa_lrn_en) && (FALSE != port_config.sa_lrn_en)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != port_config.sa_lmt_en) && (FALSE != port_config.sa_lmt_en)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port_config.sa_lmt_cnt > AIR_MAX_NUM_OF_MAC), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PSC(port), &u32dat);
+
+ if(FALSE == port_config.sa_lrn_en)
+ {
+ u32dat |= BITS_RANGE(PSC_DIS_LRN_OFFSET, PSC_DIS_LRN_LENGTH);
+ }
+ else
+ {
+ u32dat &= ~BITS_RANGE(PSC_DIS_LRN_OFFSET, PSC_DIS_LRN_LENGTH);
+ }
+ if(FALSE == port_config.sa_lmt_en)
+ {
+ u32dat &= ~BITS_RANGE(PSC_SA_CNT_EN_OFFSET, PSC_SA_CNT_EN_LENGTH);
+ u32dat &= ~PSC_SA_CNT_LMT_MASK;
+ u32dat |= (PSC_SA_CNT_LMT_MAX << PSC_SA_CNT_LMT_OFFSET);
+ }
+ else
+ {
+ u32dat |= BITS_RANGE(PSC_SA_CNT_EN_OFFSET, PSC_SA_CNT_EN_LENGTH);
+ u32dat &= ~PSC_SA_CNT_LMT_MASK;
+ value = (port_config.sa_lmt_cnt & PSC_SA_CNT_LMT_REALMASK);
+ u32dat |= (((value > PSC_SA_CNT_LMT_MAX) ? PSC_SA_CNT_LMT_MAX : value) << PSC_SA_CNT_LMT_OFFSET);
+ }
+
+ aml_writeReg(unit, PSC(port), u32dat);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_sec_getPortSecPortCfg
+ * PURPOSE:
+ * Get port security configurations for specific port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Port ID
+ *
+ * OUTPUT:
+ * ptr_port_config -- Structure of port configuration.
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+ AIR_ERROR_NO_T
+air_sec_getPortSecPortCfg(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_SEC_PORTSEC_PORT_CONFIG_T *ptr_port_config)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T u32dat = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_port_config);
+
+ aml_readReg(unit, PSC(port), &u32dat);
+
+ ptr_port_config ->sa_lrn_en = ((~BITS_OFF_R(u32dat, PSC_DIS_LRN_OFFSET, PSC_DIS_LRN_LENGTH)) & BIT(0));
+ ptr_port_config ->sa_lmt_en = BITS_OFF_R(u32dat, PSC_SA_CNT_EN_OFFSET, PSC_SA_CNT_EN_LENGTH);
+ ptr_port_config ->sa_lmt_cnt = (u32dat >> PSC_SA_CNT_LMT_OFFSET) & PSC_SA_CNT_LMT_REALMASK;
+
+ return rc;
+}
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sptag.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sptag.c
new file mode 100644
index 0000000..1f6e4ce
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_sptag.c
@@ -0,0 +1,342 @@
+/* FILE NAME: air_sptag.c
+ * PURPOSE:
+ * Define the Special Tag function in AIR SDK.
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_sptag_setState
+ * PURPOSE:
+ * Set special tag enable/disable for port
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ * sp_en -- special tag Enable or Disable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_setState(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T sp_en)
+{
+ UI32_T udat32 = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != sp_en) && (FALSE != sp_en)), AIR_E_BAD_PARAMETER);
+
+ /* Read PVC */
+ aml_readReg(unit, PVC(port), &udat32);
+ AIR_PRINT("PVC REG:%x. val:%x\n", PVC(port),udat32);
+
+ /* Set special tag enable or disable */
+ udat32 &= ~BITS_RANGE(PVC_SPTAG_EN_OFFT, PVC_SPTAG_EN_LENG);
+ udat32 |= (sp_en << PVC_SPTAG_EN_OFFT);
+
+ /* Write PVC */
+ aml_writeReg(unit, PVC(port), udat32);
+ AIR_PRINT("PVC REG:%x. val:%x\n", PVC(port),udat32);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_getCpuPortEn
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ *
+ * OUTPUT:
+ * sp_en -- special tag enable or disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_getState(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *sp_en)
+{
+ UI32_T udat32 = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(sp_en);
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+
+ /* Read PVC */
+ aml_readReg(unit, PVC(port), &udat32);
+
+ /* Get special tag state */
+ (*sp_en) = BITS_OFF_R(udat32, PVC_SPTAG_EN_OFFT, PVC_SPTAG_EN_LENG);
+
+ return AIR_E_OK;
+}
+
+
+/* FUNCTION NAME: air_sptag_setMode
+ * PURPOSE:
+ * Set special tag enable/disable for port
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ * mode -- insert mode or replace mode
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_setMode(
+ const UI32_T unit,
+ const UI32_T port,
+ const BOOL_T mode)
+{
+ UI32_T udat32 = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != mode) && (FALSE != mode)), AIR_E_BAD_PARAMETER);
+
+ /* Read PVC */
+ aml_readReg(unit, PVC(port), &udat32);
+ AIR_PRINT("PVC REG:%x. val:%x\n", PVC(port),udat32);
+
+ /* Set special tag enable or disable */
+ udat32 &= ~BITS_RANGE(PVC_SPTAG_MODE_OFFT, PVC_SPTAG_MODE_LENG);
+ udat32 |= (mode << PVC_SPTAG_MODE_OFFT);
+
+ /* Write PVC */
+ aml_writeReg(unit, PVC(port), udat32);
+ AIR_PRINT("PVC REG:%x. val:%x\n", PVC(port),udat32);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sptag_getMode
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Special tag Port
+ *
+ * OUTPUT:
+ * mode -- insert or replace mode
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_getMode(
+ const UI32_T unit,
+ const UI32_T port,
+ BOOL_T *mode)
+{
+ UI32_T udat32 = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(mode);
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+
+ /* Read PVC */
+ aml_readReg(unit, PVC(port), &udat32);
+
+ /* Get special tag mode */
+ (*mode) = BITS_OFF_R(udat32, PVC_SPTAG_MODE_OFFT, PVC_SPTAG_MODE_LENG);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sptag_encodeTx
+ * PURPOSE:
+ * Encode tx special tag into buffer.
+ * INPUT:
+ * unit -- Device ID
+ * ptr_sptag_tx -- Special tag parameters
+ * ptr_buf -- Buffer address
+ * ptr_len -- Buffer length
+ * OUTPUT:
+ * ptr_len -- Written buffer length
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_encodeTx(
+ const UI32_T unit,
+ const AIR_STAG_MODE_T mode,
+ AIR_STAG_TX_PARA_T *ptr_stag_tx,
+ UI8_T *ptr_buf,
+ UI32_T *ptr_len)
+{
+ UI32_T port = 0, byte_off = 0, bit_off = 0;
+ BOOL_T found = FALSE;
+ UI16_T mac_pbmp;
+
+ AIR_PARAM_CHK(((ptr_stag_tx->opc < AIR_STAG_OPC_PORTMAP) ||(ptr_stag_tx->opc > AIR_STAG_OPC_LOOKUP)),AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((ptr_stag_tx->vpm < AIR_STAG_VPM_UNTAG) ||(ptr_stag_tx->opc > AIR_STAG_VPM_TPID_PRE_DEFINED)),AIR_E_BAD_PARAMETER);
+
+ mac_pbmp = ptr_stag_tx->pbm;
+
+ /* insert mode only support port map */
+ if ((AIR_STAG_MODE_INSERT == mode)
+ && ((ptr_stag_tx->opc != AIR_STAG_OPC_PORTMAP) && (ptr_stag_tx->opc != AIR_STAG_OPC_LOOKUP)))
+ {
+ return AIR_E_BAD_PARAMETER;
+ }
+
+ /* clear output buffer */
+ memset(ptr_buf, 0, AIR_STAG_BUF_LEN);
+ AIR_PRINT("air_sptag_encode:mac_pbmp=%x\n", mac_pbmp);
+
+ ptr_buf[0] |= BITS_OFF_L(ptr_stag_tx->opc, AIR_STAG_TX_OPC_BIT_OFFSET, AIR_STAG_TX_OPC_BIT_WIDTH);
+ if (AIR_STAG_MODE_INSERT == mode)
+ { /*insert only support bitmap , opc always 000*/
+ AIR_PORT_FOREACH(mac_pbmp, port)
+ {
+ ptr_buf[1] |= (0x1 << port);
+ AIR_PRINT("air_sptag_encode:port=%d,value = %x\n", port,(0x1 << port));
+ }
+ }
+ else
+ {
+ ptr_buf[0] |= BITS_OFF_L(ptr_stag_tx->vpm, AIR_STAG_TX_VPM_BIT_OFFSET, AIR_STAG_TX_VPM_BIT_WIDTH);
+ ptr_buf[0] |= BITS_OFF_L(ptr_stag_tx->opc, AIR_STAG_TX_OPC_BIT_OFFSET, AIR_STAG_TX_OPC_BIT_WIDTH);
+ if (AIR_STAG_OPC_PORTMAP == ptr_stag_tx->opc)
+ {
+ AIR_PORT_FOREACH(mac_pbmp, port)
+ {
+ ptr_buf[1] |= 0x1 << port;
+
+ }
+ }
+ else if (AIR_STAG_OPC_PORTID == ptr_stag_tx->opc)
+ {
+ AIR_PORT_FOREACH(mac_pbmp, port)
+ {
+ if (TRUE ==found)
+ {
+ return AIR_E_BAD_PARAMETER;
+ }
+ ptr_buf[1] |= port;
+ found = TRUE;
+ }
+ }
+ AIR_PRINT("air_sptag_encode:pri = %d,cfi = %d,vid = %d\n", ptr_stag_tx->pri,ptr_stag_tx->cfi,ptr_stag_tx->vid);
+
+ ptr_buf[2] |= BITS_OFF_L(ptr_stag_tx->pri, AIR_STAG_TX_PCP_BIT_OFFSET, AIR_STAG_TX_PCP_BIT_WIDTH);
+ ptr_buf[2] |= BITS_OFF_L(ptr_stag_tx->cfi, AIR_STAG_TX_DEI_BIT_OFFSET, AIR_STAG_TX_DEI_BIT_WIDTH);
+ ptr_buf[2] |= BITS_OFF_L((ptr_stag_tx->vid >> AIR_STAG_ALIGN_BIT_WIDTH), 0,
+ (AIR_STAG_ALIGN_BIT_WIDTH - AIR_STAG_TX_PCP_BIT_WIDTH - AIR_STAG_TX_DEI_BIT_WIDTH));
+ AIR_PRINT("air_sptag_encode:pbuf[2] %02x\n", ptr_buf[2]);
+ ptr_buf[3] |= BITS_OFF_L((ptr_stag_tx->vid & 0xFF), 0, AIR_STAG_ALIGN_BIT_WIDTH);
+ AIR_PRINT("air_sptag_encode:pbuf[3] %02x\n", ptr_buf[3]);
+ }
+
+ *ptr_len = AIR_STAG_BUF_LEN;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_sptag_decodeRx
+ * PURPOSE:
+ * Decode rx special tag from buffer.
+ * INPUT:
+ * unit -- Device ID
+ * ptr_buf -- Buffer address
+ * len -- Buffer length
+ * OUTPUT:
+ * ptr_sptag_rx -- Special tag parameters
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_sptag_decodeRx(
+ const UI32_T unit,
+ const UI8_T *ptr_buf,
+ const UI32_T len,
+ AIR_SPTAG_RX_PARA_T *ptr_sptag_rx)
+{
+ AIR_CHECK_PTR(ptr_buf);
+ AIR_CHECK_PTR(ptr_sptag_rx);
+ AIR_PARAM_CHK((len != AIR_STAG_BUF_LEN), AIR_E_BAD_PARAMETER);
+
+ ptr_sptag_rx->vpm = BITS_OFF_R(ptr_buf[0], 0, 2);
+ ptr_sptag_rx->rsn = BITS_OFF_R(ptr_buf[0], 2, 3);
+ ptr_sptag_rx->spn = BITS_OFF_R(ptr_buf[1], 0, 5);
+ ptr_sptag_rx->pri = BITS_OFF_R(ptr_buf[2], 5, 3);
+ ptr_sptag_rx->cfi = BITS_OFF_R(ptr_buf[2], 4, 1);
+ ptr_sptag_rx->vid = BITS_OFF_R(ptr_buf[2], 0, 4);
+ ptr_sptag_rx->vid = (ptr_sptag_rx->vid << 8) | ptr_buf[3];
+
+ AIR_PARAM_CHK((ptr_sptag_rx->vpm >= AIR_STAG_REASON_CODE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((ptr_sptag_rx->rsn >= AIR_STAG_VPM_LAST), AIR_E_BAD_PARAMETER);
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_stp.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_stp.c
new file mode 100644
index 0000000..6f69ed5
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_stp.c
@@ -0,0 +1,133 @@
+/* FILE NAME: air_stp.c
+ * PURPOSE:
+ * Define the STP function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+/* FUNCTION NAME: air_stp_setPortstate
+ * PURPOSE:
+ * Set the STP port state for a specifiec port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * fid -- Filter ID for MSTP
+ * state -- AIR_STP_STATE_DISABLE
+ * AIR_STP_STATE_LISTEN
+ * AIR_STP_STATE_LEARN
+ * AIR_STP_STATE_FORWARD
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_stp_setPortstate(
+ const UI32_T unit,
+ const UI8_T port,
+ const UI8_T fid,
+ const AIR_STP_STATE_T state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for fid checking */
+ AIR_PARAM_CHK((fid >= AIR_STP_FID_NUMBER), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_PARAM_CHK((state >= AIR_STP_STATE_LAST), AIR_E_BAD_PARAMETER);
+
+ /* Read data from register */
+ aml_readReg(unit, SSC(port), &u32dat);
+
+ /* Write data to register */
+ u32dat &= ~BITS(fid*2, (fid*2)+1);
+ u32dat |= BITS_OFF_L(state, (fid*2), 2);
+ aml_writeReg(unit, SSC(port), u32dat);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_stp_getPortstate
+ * PURPOSE:
+ * Get the STP port state for a specifiec port.
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- Index of port number
+ * fid -- Filter ID for MSTP
+ *
+ * OUTPUT:
+ * ptr_state -- AIR_STP_STATE_DISABLE
+ * AIR_STP_STATE_LISTEN
+ * AIR_STP_STATE_LEARN
+ * AIR_STP_STATE_FORWARD
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+
+AIR_ERROR_NO_T
+air_stp_getPortstate(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI32_T fid,
+ AIR_STP_STATE_T *ptr_state)
+{
+ UI32_T u32dat = 0;
+
+ /* Mistake proofing for port checking */
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for fid checking */
+ AIR_PARAM_CHK((fid >= AIR_STP_FID_NUMBER), AIR_E_BAD_PARAMETER);
+
+ /* Mistake proofing for state checking */
+ AIR_CHECK_PTR(ptr_state);
+
+ /* Read data from register */
+ aml_readReg(unit, SSC(port), &u32dat);
+ (*ptr_state) = BITS_OFF_R(u32dat, fid*2, 2);
+
+ return AIR_E_OK;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_switch.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_switch.c
new file mode 100644
index 0000000..91f689e
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_switch.c
@@ -0,0 +1,369 @@
+/* FILE NAME: air_switch.c
+ * PURPOSE:
+ * Define the switch function in AIR SDK.
+ *
+ * NOTES:
+ * None
+ */
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+#define AIR_SYS_RST_WAIT_TIME (100000)
+
+/* MACRO FUNCTION DECLARATIONS
+*/
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+
+/* FUNCTION NAME: air_switch_setCpuPort
+ * PURPOSE:
+ * Set CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ * port -- CPU port index
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setCpuPort(
+ const UI32_T unit,
+ const UI32_T port)
+{
+ UI32_T regMFC = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK(port > AIR_MAX_NUM_OF_PORTS, AIR_E_BAD_PARAMETER);
+
+ /* Read CFC */
+ aml_readReg(unit, MFC, ®MFC);
+ AIR_PRINT("PTC REG:%x. val:%x\n", MFC,regMFC);
+
+ /* Set CPU portmap */
+ regMFC &= ~BITS_RANGE(MFC_CPU_PORT_OFFSET, MFC_CPU_PORT_LENGTH);
+ regMFC |= (port << MFC_CPU_PORT_OFFSET);
+
+ /* Write CFC */
+ aml_writeReg(unit, MFC, regMFC);
+ AIR_PRINT("PTC REG:%x. val:%x\n", MFC,regMFC);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_getCpuPort
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * ptr_port -- CPU port index
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getCpuPort(
+ const UI32_T unit,
+ UI32_T *ptr_port)
+{
+ UI32_T regMFC = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(ptr_port);
+
+ /* Read CFC */
+ aml_readReg(unit, MFC, ®MFC);
+
+ /* Get CPU portmap */
+ (*ptr_port) = BITS_OFF_R(regMFC, MFC_CPU_PORT_OFFSET, MFC_CPU_PORT_LENGTH);
+
+ return AIR_E_OK;
+}
+
+
+/* FUNCTION NAME: air_switch_setCpuPortEN
+ * PURPOSE:
+ * Set CPU port Enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * cpu_en -- CPU Port Enable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setCpuPortEn(
+ const UI32_T unit,
+ const BOOL_T cpu_en)
+{
+ UI32_T regMFC = 0;
+
+ /* Mistake proofing */
+ AIR_PARAM_CHK(((TRUE != cpu_en) && (FALSE != cpu_en)), AIR_E_BAD_PARAMETER);
+
+ /* Read CFC */
+ aml_readReg(unit, MFC, ®MFC);
+
+ /* Set CPU portmap */
+ regMFC &= ~BITS_RANGE(MFC_CPU_EN_OFFSET, MFC_CPU_EN_LENGTH);
+ regMFC |= cpu_en << MFC_CPU_EN_OFFSET ;
+
+ /* Write CFC */
+ aml_writeReg(unit, MFC, regMFC);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_getCpuPortEn
+ * PURPOSE:
+ * Get CPU port member
+ *
+ * INPUT:
+ * unit -- Device ID
+ *
+ * OUTPUT:
+ * cpu_en -- CPU Port enable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getCpuPortEn(
+ const UI32_T unit,
+ BOOL_T *cpu_en)
+{
+ UI32_T regMFC = 0;
+
+ /* Mistake proofing */
+ AIR_CHECK_PTR(cpu_en);
+
+ /* Read CFC */
+ aml_readReg(unit, MFC, ®MFC);
+
+ /* Get CPU portmap */
+ (*cpu_en) = BITS_OFF_R(regMFC, MFC_CPU_EN_OFFSET, MFC_CPU_EN_LENGTH);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_setSysIntrEn
+ * PURPOSE:
+ * Set system interrupt enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ * enable -- system interrupt enable/disable
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setSysIntrEn(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ const BOOL_T enable)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((intr >= AIR_SYS_INTR_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((intr > AIR_SYS_INTR_TYPE_PHY7_LC) && (intr < AIR_SYS_INTR_TYPE_MAC_PC)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((TRUE != enable) && (FALSE != enable)), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, SYS_INT_EN, &val);
+ val &= ~BIT(intr);
+ val |= (TRUE == enable) ? BIT(intr) : 0;
+ aml_writeReg(unit, SYS_INT_EN, val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_getSysIntrEn
+ * PURPOSE:
+ * Get system interrupt enable
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ *
+ * OUTPUT:
+ * ptr_enable -- system interrupt enable/disable
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getSysIntrEn(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ BOOL_T *ptr_enable)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((intr >= AIR_SYS_INTR_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((intr > AIR_SYS_INTR_TYPE_PHY7_LC) && (intr < AIR_SYS_INTR_TYPE_MAC_PC)), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ aml_readReg(unit, SYS_INT_EN, &val);
+ *ptr_enable = (val & BIT(intr)) ? TRUE : FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_setSysIntrStatus
+ * PURPOSE:
+ * Set system interrupt status
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ * enable -- write TRUE to clear interrupt status
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_setSysIntrStatus(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ const BOOL_T enable)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((intr >= AIR_SYS_INTR_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((intr > AIR_SYS_INTR_TYPE_PHY6_LC) && (intr < AIR_SYS_INTR_TYPE_MAC_PC)), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((TRUE != enable), AIR_E_BAD_PARAMETER);
+
+ aml_writeReg(unit, SYS_INT_STS, BIT(intr));
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_getSysIntrStatus
+ * PURPOSE:
+ * Get system interrupt status
+ *
+ * INPUT:
+ * unit -- Device ID
+ * intr -- system interrupt type
+ *
+ * OUTPUT:
+ * ptr_enable -- system interrupt status
+ *
+ * RETURN:
+ * AIR_E_OK
+ * AIR_E_BAD_PARAMETER
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_getSysIntrStatus(
+ const UI32_T unit,
+ const AIR_SYS_INTR_TYPE_T intr,
+ BOOL_T *ptr_enable)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((intr >= AIR_SYS_INTR_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK(((intr > AIR_SYS_INTR_TYPE_PHY6_LC) && (intr < AIR_SYS_INTR_TYPE_MAC_PC)), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ aml_readReg(unit, SYS_INT_STS, &val);
+ *ptr_enable = (val & BIT(intr)) ? TRUE : FALSE;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_switch_reset
+ * PURPOSE:
+ * Reset whole system
+ *
+ * INPUT:
+ * None
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * AIR_E_OK
+ *
+ * NOTES:
+ * None
+ */
+AIR_ERROR_NO_T
+air_switch_reset(
+ const UI32_T unit)
+{
+ UI32_T val = 0;
+
+ aml_writeReg(unit, RST_CTRL1, BIT(SYS_SW_RST_OFFT));
+ AIR_UDELAY(AIR_SYS_RST_WAIT_TIME);
+
+ return AIR_E_OK;
+}
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_vlan.c b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_vlan.c
new file mode 100644
index 0000000..6629165
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/api/src/air_vlan.c
@@ -0,0 +1,1448 @@
+/* FILE NAME: air_vlan.c
+ * PURPOSE:
+ * Define the VLAN function in AIR SDK.
+ * NOTES:
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "air.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+ */
+
+/* STATIC VARIABLE DECLARATIONS
+ */
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+
+/* LOCAL SUBPROGRAM BODIES
+*/
+void
+_air_vlan_readEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_T* vlan_entry)
+{
+ UI32_T val = 0;
+ val = (0x80000000 + vid); //r_vid_cmd
+ aml_writeReg(unit, VTCR, val);
+
+ for (;;)
+ {
+ aml_readReg(unit, VTCR, &val);
+ if ((val & 0x80000000) == 0)
+ break;
+ AIR_UDELAY(10);
+ }
+
+ aml_readReg(unit, VLNRDATA0, &(vlan_entry->vlan_table.vlan_table0));
+ aml_readReg(unit, VLNRDATA1, &(vlan_entry->vlan_table.vlan_table1));
+}
+
+void
+_air_vlan_writeEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_T* vlan_entry)
+{
+ UI32_T val = 0;
+
+ aml_writeReg(unit, VLNWDATA0, vlan_entry->vlan_table.vlan_table0);
+ aml_writeReg(unit, VLNWDATA1, vlan_entry->vlan_table.vlan_table1);
+ aml_writeReg(unit, VLNWDATA2, 0);
+ aml_writeReg(unit, VLNWDATA3, 0);
+ aml_writeReg(unit, VLNWDATA4, 0);
+
+ val = (0x80001000 + vid); //w_vid_cmd
+ aml_writeReg(unit, VTCR, val);
+
+ for (;;)
+ {
+ aml_readReg(unit, VTCR, &val);
+ if ((val & 0x80000000) == 0)
+ break;
+ AIR_UDELAY(10);
+ }
+}
+
+void
+_air_untagged_vlan_readEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T* vlan_entry)
+{
+ UI32_T val = 0;
+ val = (0x80000000 + vid); //r_vid_cmd
+ aml_writeReg(unit, VTCR, val);
+
+ for (;;)
+ {
+ aml_readReg(unit, VTCR, &val);
+ if ((val & 0x80000000) == 0)
+ break;
+ AIR_UDELAY(10);
+ }
+
+ aml_readReg(unit, VLNRDATA0, &(vlan_entry->vlan_table.vlan_table0));
+ aml_readReg(unit, VLNRDATA1, &(vlan_entry->vlan_table.vlan_table1));
+ aml_readReg(unit, VLNRDATA2, &(vlan_entry->vlan_table.vlan_table2));
+ aml_readReg(unit, VLNRDATA3, &(vlan_entry->vlan_table.vlan_table3));
+ aml_readReg(unit, VLNRDATA4, &(vlan_entry->vlan_table.vlan_table4));
+}
+
+void
+_air_untagged_vlan_writeEntry(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T* vlan_entry)
+{
+ UI32_T val = 0;
+
+ aml_writeReg(unit, VLNWDATA0, vlan_entry->vlan_table.vlan_table0);
+ aml_writeReg(unit, VLNWDATA1, vlan_entry->vlan_table.vlan_table1);
+ aml_writeReg(unit, VLNWDATA2, vlan_entry->vlan_table.vlan_table2);
+ aml_writeReg(unit, VLNWDATA3, vlan_entry->vlan_table.vlan_table3);
+ aml_writeReg(unit, VLNWDATA4, vlan_entry->vlan_table.vlan_table4);
+
+ val = (0x80001000 + vid); //w_vid_cmd
+ aml_writeReg(unit, VTCR, val);
+
+ for (;;)
+ {
+ aml_readReg(unit, VTCR, &val);
+ if ((val & 0x80000000) == 0)
+ break;
+ AIR_UDELAY(10);
+ }
+}
+
+/* FUNCTION NAME: air_vlan_create
+ * PURPOSE:
+ * Create the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * p_attr -- vlan attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan creation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_create(
+ const UI32_T unit,
+ const UI16_T vid,
+ AIR_VLAN_ENTRY_ATTR_T *p_attr)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (vlan_entry.valid)
+ return AIR_E_ENTRY_EXISTS;
+
+ if (NULL != p_attr)
+ {
+ p_attr->valid = 1;
+ _air_untagged_vlan_writeEntry(unit, vid, p_attr);
+ }
+ else
+ {
+ memset(&vlan_entry, 0, sizeof(vlan_entry));
+ vlan_entry.valid = 1;
+ _air_untagged_vlan_writeEntry(unit, vid, &vlan_entry);
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_destroy
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan destroy failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_destroy(
+ const UI32_T unit,
+ const UI16_T vid)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_destroyAll
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Vlan destroy failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_destroyAll(
+ const UI32_T unit,
+ const UI32_T keep_and_restore_default_vlan)
+{
+ UI16_T vid = 0;
+
+ for (vid = AIR_VLAN_ID_MIN; vid <= AIR_VLAN_ID_MAX; vid++)
+ {
+ if (keep_and_restore_default_vlan)
+ {
+ air_vlan_reset(unit, vid);
+ }
+ else
+ {
+ air_vlan_destroy(unit, vid);
+ }
+ }
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_reset
+ * PURPOSE:
+ * Destroy the vlan in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully reset the data.
+ * AIR_E_OTHERS -- Vlan reset failed.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_reset(
+ const UI32_T unit,
+ const UI16_T vid)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ vlan_entry.vlan_entry_format.port_mem = AIR_ALL_PORT_BITMAP;
+ vlan_entry.valid = TRUE;
+
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setFid
+ * PURPOSE:
+ * Set the filter id of the vlan to the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * fid -- filter id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setFid(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI8_T fid)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ /* VID check */
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((fid > AIR_FILTER_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.fid = fid;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getFid
+ * PURPOSE:
+ * Get the filter id of the vlan from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id to be created
+ * OUTPUT:
+ * ptr_fid -- filter id
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getFid(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI8_T *ptr_fid)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_fid);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_fid = vlan_entry.vlan_entry_format.fid;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_addMemberPort
+ * PURPOSE:
+ * Add one vlan member to the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_addMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.port_mem |= 1 << port;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_delMemberPort
+ * PURPOSE:
+ * Delete one vlan member from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_delMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.port_mem &= ~(1 << port);
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setMemberPort
+ * PURPOSE:
+ * Replace the vlan members in the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port_bitmap -- member port bitmap
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port_bitmap)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port_bitmap & (~AIR_ALL_PORT_BITMAP)), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.port_mem = port_bitmap;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getMemberPort
+ * PURPOSE:
+ * Get the vlan members from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * port_bitmap -- member port bitmap
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getMemberPort(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI32_T *ptr_port_bitmap)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_port_bitmap);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_port_bitmap = vlan_entry.vlan_entry_format.port_mem;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setIVL
+ * PURPOSE:
+ * Set L2 lookup mode IVL/SVL for L2 traffic.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable IVL
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setIVL(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.ivl = enable ? 1 : 0;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getIVL
+ * PURPOSE:
+ * Get L2 lookup mode IVL/SVL for L2 traffic.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_enable -- enable IVL
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getIVL(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *ptr_enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_enable = vlan_entry.vlan_entry_format.ivl;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortAcceptFrameType
+ * PURPOSE:
+ * Set vlan accept frame type of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * type -- accept frame type
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortAcceptFrameType(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_VLAN_ACCEPT_FRAME_TYPE_T type)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((type >= AIR_VLAN_ACCEPT_FRAME_TYPE_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVC(port), &val);
+ val &= ~PVC_ACC_FRM_MASK;
+ val |= (type & PVC_ACC_FRM_RELMASK) << PVC_ACC_FRM_OFFT;
+ aml_writeReg(unit, PVC(port), val);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_getPortAcceptFrameType
+ * PURPOSE:
+ * Get vlan accept frame type of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_type -- accept frame type
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortAcceptFrameType(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_VLAN_ACCEPT_FRAME_TYPE_T *ptr_type)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_type);
+
+ aml_readReg(unit, PVC(port), &val);
+ *ptr_type = (val >> PVC_ACC_FRM_OFFT) & PVC_ACC_FRM_RELMASK;
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_setPortLeakyVlanEnable
+ * PURPOSE:
+ * Set leaky vlan enable of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pkt_type -- packet type
+ * enable -- enable leaky
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortLeakyVlanEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_LEAKY_PKT_TYPE_T pkt_type,
+ const BOOL_T enable)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pkt_type >= AIR_LEAKY_PKT_TYPE_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVC(port), &val);
+
+ if (pkt_type == AIR_LEAKY_PKT_TYPE_UNICAST)
+ {
+ if (enable)
+ {
+ val |= PVC_UC_LKYV_EN_MASK;
+ }
+ else
+ {
+ val &= ~PVC_UC_LKYV_EN_MASK;
+ }
+ }
+ else if (pkt_type == AIR_LEAKY_PKT_TYPE_MULTICAST)
+ {
+ if (enable)
+ {
+ val |= PVC_MC_LKYV_EN_MASK;
+ }
+ else
+ {
+ val &= ~PVC_MC_LKYV_EN_MASK;
+ }
+ }
+ else
+ {
+ if (enable)
+ {
+ val |= PVC_BC_LKYV_EN_MASK;
+ }
+ else
+ {
+ val &= ~PVC_BC_LKYV_EN_MASK;
+ }
+ }
+
+ aml_writeReg(unit, PVC(port), val);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_getPortLeakyVlanEnable
+ * PURPOSE:
+ * Get leaky vlan enable of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pkt_type -- packet type
+ * OUTPUT:
+ * ptr_enable -- enable leaky
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortLeakyVlanEnable(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_LEAKY_PKT_TYPE_T pkt_type,
+ BOOL_T *ptr_enable)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pkt_type >= AIR_LEAKY_PKT_TYPE_LAST), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ aml_readReg(unit, PVC(port), &val);
+
+ if (pkt_type == AIR_LEAKY_PKT_TYPE_UNICAST)
+ {
+ *ptr_enable = val & PVC_UC_LKYV_EN_MASK ? TRUE : FALSE;
+ }
+ else if (pkt_type == AIR_LEAKY_PKT_TYPE_MULTICAST)
+ {
+ *ptr_enable = val & PVC_MC_LKYV_EN_MASK ? TRUE : FALSE;
+ }
+ else
+ {
+ *ptr_enable = val & PVC_BC_LKYV_EN_MASK ? TRUE : FALSE;
+ }
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_setPortAttr
+ * PURPOSE:
+ * Set vlan port attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- vlan port attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_VLAN_PORT_ATTR_T attr)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((attr >= AIR_VLAN_PORT_ATTR_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVC(port), &val);
+ val &= ~PVC_VLAN_ATTR_MASK;
+ val |= (attr & PVC_VLAN_ATTR_RELMASK) << PVC_VLAN_ATTR_OFFT;
+ aml_writeReg(unit, PVC(port), val);
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_getPortAttr
+ * PURPOSE:
+ * Get vlan port attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_attr -- vlan port attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_VLAN_PORT_ATTR_T *ptr_attr)
+{
+ AIR_ERROR_NO_T rc = AIR_E_OK;
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_attr);
+
+ aml_readReg(unit, PVC(port), &val);
+ *ptr_attr = (val >> PVC_VLAN_ATTR_OFFT) & PVC_VLAN_ATTR_RELMASK;
+
+ return rc;
+}
+
+/* FUNCTION NAME: air_vlan_setIgrPortTagAttr
+ * PURPOSE:
+ * Set vlan incoming port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- egress tag attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setIgrPortTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_IGR_PORT_EG_TAG_ATTR_T attr)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((attr >= AIR_IGR_PORT_EG_TAG_ATTR_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVC(port), &val);
+ val &= ~PVC_EG_TAG_MASK;
+ val |= (attr & PVC_EG_TAG_RELMASK) << PVC_EG_TAG_OFFT;
+ aml_writeReg(unit, PVC(port), val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getIgrPortTagAttr
+ * PURPOSE:
+ * Get vlan incoming port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_attr -- egress tag attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getIgrPortTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_IGR_PORT_EG_TAG_ATTR_T *ptr_attr)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_attr);
+
+ aml_readReg(unit, PVC(port), &val);
+ *ptr_attr = (val >> PVC_EG_TAG_OFFT) & PVC_EG_TAG_RELMASK;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortEgsTagAttr
+ * PURPOSE:
+ * Set vlan port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * attr -- egress tag attr
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortEgsTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ const AIR_PORT_EGS_TAG_ATTR_T attr)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((attr >= AIR_PORT_EGS_TAG_ATTR_LAST), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PCR(port), &val);
+ val &= ~PCR_EG_TAG_MASK;
+ val |= (attr & PCR_EG_TAG_RELMASK) << PCR_EG_TAG_OFFT;
+ aml_writeReg(unit, PCR(port), val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getPortEgsTagAttr
+ * PURPOSE:
+ * Get vlan port egress tag attribute from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_attr -- egress tag attr
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortEgsTagAttr(
+ const UI32_T unit,
+ const UI32_T port,
+ AIR_PORT_EGS_TAG_ATTR_T *ptr_attr)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_attr);
+
+ aml_readReg(unit, PCR(port), &val);
+ *ptr_attr = (val >> PCR_EG_TAG_OFFT) & PCR_EG_TAG_RELMASK;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortOuterTPID
+ * PURPOSE:
+ * Set stack tag TPID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * tpid -- TPID
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortOuterTPID(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI16_T tpid)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVC(port), &val);
+ val &= ~PVC_STAG_VPID_MASK;
+ val |= (tpid & PVC_STAG_VPID_RELMASK) << PVC_STAG_VPID_OFFT;
+ aml_writeReg(unit, PVC(port), val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getPortOuterTPID
+ * PURPOSE:
+ * Get stack tag TPID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_tpid -- TPID
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortOuterTPID(
+ const UI32_T unit,
+ const UI32_T port,
+ UI16_T *ptr_tpid)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_tpid);
+
+ aml_readReg(unit, PVC(port), &val);
+ *ptr_tpid = (val >> PVC_STAG_VPID_OFFT) & PVC_STAG_VPID_RELMASK;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortPVID
+ * PURPOSE:
+ * Set PVID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * pvid -- native vlan id
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortPVID(
+ const UI32_T unit,
+ const UI32_T port,
+ const UI16_T pvid)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((pvid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ aml_readReg(unit, PVID(port), &val);
+ val &= ~PVID_PCVID_MASK;
+ val |= (pvid & PVID_PCVID_RELMASK) << PVID_PCVID_OFFT;
+ aml_writeReg(unit, PVID(port), val);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getPortPVID
+ * PURPOSE:
+ * Get PVID of the port from the specified device.
+ * INPUT:
+ * unit -- unit id
+ * port -- port id
+ * OUTPUT:
+ * ptr_pvid -- native vlan id
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortPVID(
+ const UI32_T unit,
+ const UI32_T port,
+ UI16_T *ptr_pvid)
+{
+ UI32_T val = 0;
+
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_pvid);
+
+ aml_readReg(unit, PVID(port), &val);
+ *ptr_pvid = (val >> PVID_PCVID_OFFT) & PVID_PCVID_RELMASK;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setServiceTag
+ * PURPOSE:
+ * Set Vlan service tag.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * stag -- service stag
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setServiceTag(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI16_T stag)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((stag > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.stag = stag;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getServiceTag
+ * PURPOSE:
+ * Get Vlan service tag.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_stag -- service stag
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getServiceTag(
+ const UI32_T unit,
+ const UI16_T vid,
+ UI16_T *ptr_stag)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_stag);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_stag = vlan_entry.vlan_entry_format.stag;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setEgsTagCtlEnable
+ * PURPOSE:
+ * Set per vlan egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable vlan egress tag control
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setEgsTagCtlEnable(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.eg_ctrl_en = enable ? 1 : 0;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getEgsTagCtlEnable
+ * PURPOSE:
+ * Get per vlan egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_enable -- enable vlan egress tag control
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getEgsTagCtlEnable(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *ptr_enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_enable = vlan_entry.vlan_entry_format.eg_ctrl_en;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setEgsTagConsistent
+ * PURPOSE:
+ * Set per vlan egress tag consistent.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- enable vlan egress tag consistent
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setEgsTagConsistent(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.eg_con = enable;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getEgsTagConsistent
+ * PURPOSE:
+ * Get per vlan egress tag consistent.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_enable -- enable vlan egress tag consistent
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getEgsTagConsistent(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *ptr_enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_enable = vlan_entry.vlan_entry_format.eg_con;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortBasedStag
+ * PURPOSE:
+ * Set vlan port based stag enable.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * enable -- vlan port based stag enable
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortBasedStag(
+ const UI32_T unit,
+ const UI16_T vid,
+ const BOOL_T enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.port_stag = enable;
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getPortBasedStag
+ * PURPOSE:
+ * Get vlan port based stag enable.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_enable -- vlan port based stag enable
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortBasedStag(
+ const UI32_T unit,
+ const UI16_T vid,
+ BOOL_T *ptr_enable)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_enable);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_enable = vlan_entry.vlan_entry_format.port_stag;
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_setPortEgsTagCtl
+ * PURPOSE:
+ * Set vlan port egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * port -- port id
+ * tag_ctl -- egress tag control
+ * OUTPUT:
+ * None
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_setPortEgsTagCtl(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port,
+ const AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_T tag_ctl)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((tag_ctl >= AIR_PORT_EGS_TAG_ATTR_LAST), AIR_E_BAD_PARAMETER);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ vlan_entry.vlan_entry_format.eg_ctrl &= ~(0x3 << (port * 2));
+ vlan_entry.vlan_entry_format.eg_ctrl |= (tag_ctl & 0x3) << (port * 2);
+ _air_vlan_writeEntry(unit, vid, &vlan_entry);
+
+ return AIR_E_OK;
+}
+
+/* FUNCTION NAME: air_vlan_getPortEgsTagCtl
+ * PURPOSE:
+ * Get vlan port egress tag control.
+ * INPUT:
+ * unit -- unit id
+ * vid -- vlan id
+ * OUTPUT:
+ * ptr_tag_ctl -- egress tag control
+ * RETURN:
+ * AIR_E_OK -- Successfully read the data.
+ * AIR_E_OTHERS -- Operation failed.
+ * AIR_E_BAD_PARAMETER -- Invalid parameter.
+ * NOTES:
+ * none
+ */
+AIR_ERROR_NO_T
+air_vlan_getPortEgsTagCtl(
+ const UI32_T unit,
+ const UI16_T vid,
+ const UI32_T port,
+ AIR_VLAN_PORT_EGS_TAG_CTL_TYPE_T *ptr_tag_ctl)
+{
+ AIR_VLAN_ENTRY_T vlan_entry = {0};
+
+ AIR_PARAM_CHK((vid > AIR_VLAN_ID_MAX), AIR_E_BAD_PARAMETER);
+ AIR_PARAM_CHK((port >= AIR_MAX_NUM_OF_PORTS), AIR_E_BAD_PARAMETER);
+ AIR_CHECK_PTR(ptr_tag_ctl);
+
+ _air_vlan_readEntry(unit, vid, &vlan_entry);
+ if (!vlan_entry.valid)
+ return AIR_E_ENTRY_NOT_FOUND;
+
+ *ptr_tag_ctl = (vlan_entry.vlan_entry_format.eg_ctrl >> (port * 2)) & 0x3;
+
+ return AIR_E_OK;
+}
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_init.c b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_init.c
new file mode 100644
index 0000000..c754955
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_init.c
@@ -0,0 +1,138 @@
+/* FILE NAME: an8855_init.c
+ * PURPOSE:
+ * It provides an8855 switch intialize flow.
+ *
+ * NOTES:
+ *
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "an8855_reg.h"
+#include "an8855_mdio.h"
+#include "an8855_phy.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+/* FUNCTION NAME: an8855_hw_reset
+ * PURPOSE:
+ * This API is used to reset an8855 hw.
+ * INPUT:
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * Attention!! Customer should implement this func
+ */
+void
+an8855_hw_reset(void)
+{
+ //dbg_print(">>>>> an8855_hw_reset\n");
+ /* set an8855 reset pin to 0 */
+
+ /* delay 100ms */
+
+ /* set an8855 reset pin to 1 */
+
+ /* delay 600ms */
+
+}
+
+/* FUNCTION NAME: an8855_sw_reset
+ * PURPOSE:
+ * This API is used to reset an8855 system.
+ * INPUT:
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ */
+void
+an8855_sw_reset(void)
+{
+ //dbg_print(">>>>> an8855_sw_reset\n");
+ an8855_reg_write(0x100050c0, 0x80000000);
+ an8855_udelay(100000);
+}
+
+/* FUNCTION NAME: an8855_phy_calibration_setting
+ * PURPOSE:
+ * This API is used to set an8855 phy calibration.
+ * INPUT:
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * None
+ */
+void
+an8855_phy_calibration_setting(void)
+{
+ int i = 0;
+
+ //dbg_print("\nSMI IOMUX initial ...");
+ an8855_reg_write(0x10000070, 0x2);
+ an8855_udelay(10000);
+ //dbg_print("\nGPHY initial ...");
+ an8855_reg_write(0x1028C840, 0x0);
+ for(i = 0; i <= 4; i++)
+ {
+ an8855_phy_write(i, 0, 0x1040);
+ }
+ an8855_udelay(10000);
+ //dbg_print("Done");
+ //dbg_print("\nSw calibration ... ");
+ gphy_calibration(g_smi_addr);
+ //dbg_print("\nDone");
+}
+
+/* FUNCTION NAME: an8855_init
+ * PURPOSE:
+ * This API is used to init an8855.
+ * INPUT:
+ * OUTPUT:
+ * RETURN:
+ * 0 -- init success
+ * -1 -- init failure
+ * NOTES:
+ * Attention!! Customer should implement part of this func
+ */
+int
+an8855_init(void)
+{
+ u32 data = 0;
+
+ /* an8855 hw reset */
+ an8855_hw_reset();
+
+ /* an8855 system reset */
+ an8855_sw_reset();
+
+ /* Keep the clock ticking when all ports link down */
+ data = an8855_reg_read(0x10213e1c);
+ data &= ~(0x3);
+ an8855_reg_write(0x10213e1c, data);
+
+ /* internal phy calibration */
+ /* please comment out this func after calibration data loaded from ROM code */
+ an8855_phy_calibration_setting();
+
+ return 0;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.c b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.c
new file mode 100644
index 0000000..3ff7ded
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.c
@@ -0,0 +1,285 @@
+/* FILE NAME: an8855_mdio.c
+ * PURPOSE:
+ * It provides an8855 registers and PHY mdio access.
+ *
+ * NOTES:
+ *
+ */
+
+/* INCLUDE FILE DECLARATIONS
+ */
+#include "an8855_reg.h"
+#include "an8855_mdio.h"
+
+/* NAMING CONSTANT DECLARATIONS
+*/
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+#define AN8855_SMI_ADDR (1)
+
+/* DATA TYPE DECLARATIONS
+*/
+
+/* GLOBAL VARIABLE DECLARATIONS
+*/
+
+/* LOCAL SUBPROGRAM DECLARATIONS
+*/
+
+/* STATIC VARIABLE DECLARATIONS
+*/
+u32 g_smi_addr = AN8855_SMI_ADDR;
+
+static AIR_MII_READ_FUNC_T g_mii_read = NULL;
+static AIR_MII_WRITE_FUNC_T g_mii_write = NULL;
+static AIR_MII_C45_READ_FUNC_T g_mii_c45_read = NULL;
+static AIR_MII_C45_WRITE_FUNC_T g_mii_c45_write = NULL;
+
+/* EXPORTED SUBPROGRAM BODIES
+*/
+
+/* FUNCTION NAME: an8855_set_smi_addr
+ * PURPOSE:
+ * This API is used to set an8855 smi address.
+ * INPUT:
+ * smi_addr -- AN8855 smi address
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * None
+ */
+void
+an8855_set_smi_addr(u32 smi_addr)
+{
+ an8855_reg_write(0x1028C848, smi_addr);
+ g_smi_addr = smi_addr;
+}
+
+/* FUNCTION NAME: an8855_set_mii_callback
+ * PURPOSE:
+ * This API is used to set an8855 mii access callbacks.
+ * INPUT:
+ * mii_read -- mii read api function
+ * mii_write -- mii write api function
+ * mii_c45_read -- mii c45 read api function
+ * mii_c45_write -- mii c45 write api function
+ * OUTPUT:
+ * RETURN:
+ * 0 -- Successfully set callback.
+ * -1 -- Setting callback failed.
+ * NOTES:
+ * None
+ */
+int
+an8855_set_mii_callback(
+ AIR_MII_READ_FUNC_T mii_read,
+ AIR_MII_WRITE_FUNC_T mii_write,
+ AIR_MII_C45_READ_FUNC_T mii_c45_read,
+ AIR_MII_C45_WRITE_FUNC_T mii_c45_write)
+{
+ if (!mii_read || !mii_write || !mii_c45_read || !mii_c45_write)
+ return -1;
+
+ g_mii_read = mii_read;
+ g_mii_write = mii_write;
+ g_mii_c45_read = mii_c45_read;
+ g_mii_c45_write = mii_c45_write;
+
+ return 0;
+}
+
+/* FUNCTION NAME: an8855_reg_read
+ * PURPOSE:
+ * This API is used read an8855 registers.
+ * INPUT:
+ * reg -- register offset
+ * OUTPUT:
+ * RETURN:
+ * Register value
+ * NOTES:
+ * Attention!! Customer should implement mdio mutex
+ * lock in this func
+ */
+u32
+an8855_reg_read(u32 reg)
+{
+ u16 data_h = 0;
+ u16 data_l = 0;
+ int ret = 0;
+
+ g_mii_write(g_smi_addr, 0x1F, 0x4);
+ g_mii_write(g_smi_addr, 0x10, 0x0);
+
+ g_mii_write(g_smi_addr, 0x15, ((reg >> 16) & 0xFFFF));
+ g_mii_write(g_smi_addr, 0x16, (reg & 0xFFFF));
+
+ ret = g_mii_read(g_smi_addr, 0x17, &data_h);
+ if(ret != 0)
+ {
+ printf("read reg 0x%x 0x17 fail\n", reg);
+ }
+ ret = g_mii_read(g_smi_addr, 0x18, &data_l);
+ if(ret != 0)
+ {
+ printf("read reg 0x%x 0x18 fail\n", reg);
+ }
+
+ g_mii_write(g_smi_addr, 0x1F, 0x0);
+ g_mii_write(g_smi_addr, 0x10, 0x0);
+ //printf("read reg:0x%08x data:0x%08x\n", reg, ((data_h << 16) | (data_l & 0xffff)));
+
+ return ((data_h << 16) | (data_l & 0xffff));
+}
+
+/* FUNCTION NAME: an8855_reg_write
+ * PURPOSE:
+ * This API is used write an8855 registers.
+ * INPUT:
+ * reg -- register offset
+ * val -- register value
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * Attention!! Customer should implement mdio mutex
+ * lock in this func
+ */
+void
+an8855_reg_write(u32 reg, u32 val)
+{
+ g_mii_write(g_smi_addr, 0x1F, 0x4);
+ g_mii_write(g_smi_addr, 0x10, 0x0);
+
+ g_mii_write(g_smi_addr, 0x11, ((reg >> 16) & 0xFFFF));
+ g_mii_write(g_smi_addr, 0x12, (reg & 0xFFFF));
+
+ g_mii_write(g_smi_addr, 0x13, ((val >> 16) & 0xFFFF));
+ g_mii_write(g_smi_addr, 0x14, (val & 0xFFFF));
+
+ g_mii_write(g_smi_addr, 0x1F, 0x0);
+ g_mii_write(g_smi_addr, 0x10, 0x0);
+ //printf("write reg:0x%08x data:0x%08x\n", reg, val);
+}
+
+/* FUNCTION NAME: an8855_phy_read
+ * PURPOSE:
+ * This API is used read an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * reg -- phy register offset
+ * OUTPUT:
+ * p_val -- phy register value
+ * RETURN:
+ * 0 -- read success
+ * -1 -- read failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func
+ */
+int
+an8855_phy_read(u32 port_num, u32 reg, u32 *p_val)
+{
+ u32 phy = 0, data = 0;
+
+ if (port_num >= AN8855_PHY_NUM)
+ return -1;
+
+ phy = g_smi_addr + port_num;
+ g_mii_read(phy, reg, &data);
+ *p_val = data & 0x0000FFFF;
+
+ return 0;
+}
+
+/* FUNCTION NAME: an8855_phy_write
+ * PURPOSE:
+ * This API is used write an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * reg -- phy register offset
+ * val -- phy register value
+ * OUTPUT:
+ * RETURN:
+ * 0 -- write success
+ * -1 -- write failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func
+ */
+int
+an8855_phy_write(u32 port_num, u32 reg, u32 val)
+{
+ u32 phy = 0, data = 0;
+
+ if (port_num >= AN8855_PHY_NUM)
+ return -1;
+
+ phy = g_smi_addr + port_num;
+ data = val & 0x0000FFFF;
+ g_mii_write(phy, reg, data);
+
+ return 0;
+}
+
+/* FUNCTION NAME: an8855_phy_read_cl45
+ * PURPOSE:
+ * This API is used read an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * dev_addr -- phy device type
+ * reg_addr -- phy register offset
+ * OUTPUT:
+ * p_val -- phy register value
+ * RETURN:
+ * 0 -- read success
+ * -1 -- read failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func or before/after calling this func
+ */
+u32
+an8855_phy_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *p_val)
+{
+ u32 phy = 0, data = 0;
+
+ if (port_num >= AN8855_PHY_NUM)
+ return -1;
+
+ phy = g_smi_addr + port_num;
+ g_mii_c45_read(phy, dev_addr, reg_addr, &data);
+ *p_val = data & 0x0000FFFF;
+
+ return 0;
+}
+
+/* FUNCTION NAME: an8855_phy_write_cl45
+ * PURPOSE:
+ * This API is used write an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * dev_addr -- phy device type
+ * reg_addr -- phy register offset
+ * val -- phy register value
+ * OUTPUT:
+ * RETURN:
+ * 0 -- write success
+ * -1 -- write failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func or before/after calling this func
+ */
+int
+an8855_phy_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 val)
+{
+ u32 phy = 0, data = 0;
+
+ if (port_num >= AN8855_PHY_NUM)
+ return -1;
+
+ phy = g_smi_addr + port_num;
+ data = val & 0x0000FFFF;
+ g_mii_c45_write(phy, dev_addr, reg_addr, data);
+
+ return 0;
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.h b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.h
new file mode 100644
index 0000000..c2d4bd7
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_mdio.h
@@ -0,0 +1,203 @@
+/* FILE NAME: an8855_mdio.h
+ * PURPOSE:
+ * It provides AN8855 mdio access API.
+ * NOTES:
+ *
+ */
+
+#ifndef AN8855_MDIO_H
+#define AN8855_MDIO_H
+
+/* INCLUDE FILE DECLARATIONS
+ */
+//#include "CTP_type.h"
+//#include "CTP_shell.h"
+//#include "common.h"
+//#include "eth.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+
+/* MACRO FUNCTION DECLARATIONS
+ */
+/* Attention!! Customer should define udelay function */
+void delayUs(int usecond);
+#define an8855_udelay(us) delayUs(us)
+
+/* Attention!! Customer should define dbg_print to get dbg output */
+#ifndef dbg_print
+#define dbg_print(...)
+#endif
+
+#define AN8855_PHY_NUM 5
+
+/* DATA TYPE DECLARATIONS
+ */
+#ifndef NULL
+#define NULL 0L
+#endif
+
+#ifndef u32
+#define u32 unsigned int
+#endif
+
+#ifndef u16
+#define u16 unsigned short
+#endif
+
+#ifndef u8
+#define u8 unsigned char
+#endif
+
+typedef u32 (*AIR_MII_READ_FUNC_T) (u32 phy_addr, u32 reg, u32 *p_data);
+
+typedef u32 (*AIR_MII_WRITE_FUNC_T) (u32 phy_addr, u32 reg, u32 data);
+
+typedef u32 (*AIR_MII_C45_READ_FUNC_T) (u32 phy_addr, u32 dev, u32 reg, u32 *p_data);
+
+typedef u32 (*AIR_MII_C45_WRITE_FUNC_T) (u32 phy_addr, u32 dev, u32 reg, u32 data);
+
+extern u32 g_smi_addr;
+
+/* EXPORTED SUBPROGRAM SPECIFICATIONS
+ */
+
+/* FUNCTION NAME: an8855_set_smi_addr
+ * PURPOSE:
+ * This API is used to set an8855 smi address.
+ * INPUT:
+ * smi_addr -- AN8855 smi address
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * None
+ */
+void
+an8855_set_smi_addr(u32 smi_addr);
+
+/* FUNCTION NAME: an8855_set_mii_callback
+ * PURPOSE:
+ * This API is used to set an8855 mii access callbacks.
+ * INPUT:
+ * mii_read -- mii read api function
+ * mii_write -- mii write api function
+ * OUTPUT:
+ * RETURN:
+ * 0 -- Successfully set callback.
+ * -1 -- Setting callback failed.
+ * NOTES:
+ * None
+ */
+int
+an8855_set_mii_callback(
+ AIR_MII_READ_FUNC_T mii_read,
+ AIR_MII_WRITE_FUNC_T mii_write,
+ AIR_MII_C45_READ_FUNC_T mii_c45_read,
+ AIR_MII_C45_WRITE_FUNC_T mii_c45_write);
+
+/* FUNCTION NAME: an8855_reg_read
+ * PURPOSE:
+ * This API is used read an8855 registers.
+ * INPUT:
+ * reg -- register offset
+ * OUTPUT:
+ * RETURN:
+ * Register value
+ * NOTES:
+ * Attention!! Customer should implement mdio mutex
+ * lock in this func
+ */
+u32
+an8855_reg_read(u32 reg);
+
+/* FUNCTION NAME: an8855_reg_write
+ * PURPOSE:
+ * This API is used write an8855 registers.
+ * INPUT:
+ * reg -- register offset
+ * val -- register value
+ * OUTPUT:
+ * RETURN:
+ * NOTES:
+ * Attention!! Customer should implement mdio mutex
+ * lock in this func
+ */
+void
+an8855_reg_write(u32 reg, u32 val);
+
+/* FUNCTION NAME: an8855_phy_read
+ * PURPOSE:
+ * This API is used read an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * reg -- phy register offset
+ * OUTPUT:
+ * p_val -- phy register value
+ * RETURN:
+ * 0 -- read success
+ * -1 -- read failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func
+ */
+int
+an8855_phy_read(u32 port_num, u32 reg, u32 *p_val);
+
+/* FUNCTION NAME: an8855_phy_write
+ * PURPOSE:
+ * This API is used write an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * reg -- phy register offset
+ * val -- phy register value
+ * OUTPUT:
+ * RETURN:
+ * 0 -- write success
+ * -1 -- write failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func
+ */
+int
+an8855_phy_write(u32 port_num, u32 reg, u32 val);
+
+/* FUNCTION NAME: an8855_phy_read_cl45
+ * PURPOSE:
+ * This API is used read an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * dev_addr -- phy device type
+ * reg_addr -- phy register offset
+ * OUTPUT:
+ * p_val -- phy register value
+ * RETURN:
+ * 0 -- read success
+ * -1 -- read failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func or before/after calling this func
+ */
+u32
+an8855_phy_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *p_val);
+
+/* FUNCTION NAME: an8855_phy_write_cl45
+ * PURPOSE:
+ * This API is used write an8855 phy registers.
+ * INPUT:
+ * port_num -- port number, 0~4
+ * dev_addr -- phy device type
+ * reg_addr -- phy register offset
+ * val -- phy register value
+ * OUTPUT:
+ * RETURN:
+ * 0 -- write success
+ * -1 -- write failure
+ * NOTES:
+ * Attention!! Customer should implement mii mutex
+ * lock in this func or before/after calling this func
+ */
+int
+an8855_phy_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 val);
+
+#endif /* End of AN8855_MDIO_H */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy.h b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy.h
new file mode 100644
index 0000000..3c810e7
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy.h
@@ -0,0 +1,409 @@
+/* FILE NAME: an8855_phy.h
+ * PURPOSE:
+ * It provides AN8855 phy definition.
+ * NOTES:
+ *
+ */
+
+#ifndef _AN8855_PHY_H_
+#define _AN8855_PHY_H_
+
+
+/* Type Definitions */
+#define int8_t char
+#define uint8_t unsigned char
+#define int16_t short
+#define uint16_t unsigned short
+#define int32_t int
+#define uint32_t unsigned int
+/* DATA TYPE DECLARATIONS
+ */
+typedef int BOOL_T;
+typedef signed char I8_T;
+typedef unsigned char UI8_T;
+typedef signed short I16_T;
+typedef unsigned short UI16_T;
+typedef signed int I32_T;
+typedef unsigned int UI32_T;
+typedef char C8_T;
+typedef unsigned long long UI64_T;
+
+typedef UI8_T AIR_MAC_T[6];
+
+/* Debug flags */
+//#define _MDIO_BOOTS_MODE 1 // Boots for preamble
+#define _DEBUG_PRINT 1 // Debug print for Arduino
+//#define _DEBUG_PRINT_eFuse 1
+#define _write_eFuse 1
+
+#define _DEBUG_SCAN_ALL 0 // Scan all Code for SerDes Calibration
+#define _WRITE_RG_DIR 1 // Write RG directly for Calibration
+#define _USER_DEFINE_MODE 0 // Replace to user-defined RG for Calibration
+#define _DEBUG_MANUAL 1 // dbg_20210604 // manual dbg_20210604
+/**************************************************************************/
+
+/* Phy Address */
+//#define phyadd_common 0x1d // EN8801
+//#define PHY_NUM 1 // EN8801
+//#define phyadd_common 0x9 // EN7523
+//#define PHY_NUM 4 // EN7523
+//#define phyadd_common 0x0 // EN8850
+//#define PHY_NUM 5 // EN8850
+#define PHY_NUM 4 // EN8851
+#define CALIPOLARITY 1
+
+#define TXAMP_offset 0 // for 8851
+
+/* On/Off */
+//#define ENABLE 1
+//#define DISABLE 0
+#define Relay_ENABLE 1
+#define Relay_DISABLE 0
+
+/* FT Pattern */
+#define _MDIO 0x0
+#define _I2C 0x1
+#define FT_USB3_T101 0x0
+#define FT_PCIE0_T101 0x1
+#define FT_PCIE1_T101 0x2
+#define FT_PON_T101 0x3
+
+/********* Digital pin definition *************/
+#define Relay_Tx_PN 22 // relay 1
+#define Relay_R_R50 23 // relay 2
+#define Relay_Tx_Vol 24 // relay 3
+#define Relay_Rx_Vol 25 // relay 4
+#define Relay_DUT_GND 26 // relay 5
+#define Relay_I2C 27 // PIN for SCL&SDA , relay 6
+//#define Relay_I2C_SCL 27 // PIN for SCL&SDA , relay 6
+//#define Relay_I2C_SDA 28 // PIN for SCL&SDA , relay 6
+
+#define pin_MDIO 36 // PIN for MDIO
+#define pin_MDC 37 // PIN for MDC
+#define FT_PATTERN_bit0 49 // PIN for FT0
+#define FT_PATTERN_bit1 48 // PIN for FT1
+#define Relay_MDIO 35 // PIN for MDIO relay, relay 7
+
+/***********************************************/
+/* Use for I/O register PORTA control */
+#define POR_Relay_Tx_PN D22 // use for PORTA control, relay 1
+#define POR_Relay_R_R50 D23 // use for PORTA control, relay 2
+#define POR_Relay_Tx_Vol D24 // use for PORTA control, relay 3
+#define POR_Relay_Rx_Vol D25 // use for PORTA control, relay 4
+#define POR_Relay_DUT_GND D26 // use for PORTA control, relay 5
+//#define POR_Relay_I2C D27 // use for PORTA control, relay 6
+#define POR_Relay_I2C_SCL D27 // use for PORTA control, relay 6
+#define POR_Relay_I2C_SDA D28 // use for PORTA control, relay 7
+
+/* Use for I/O register PORTC control */
+#define POR_MDIO D36 // use for PORTC control
+#define POR_MDC D37 // use for PORTC control
+#define POR_Relay_MDIO D35 // use for PORTC control, relay 7
+
+/* Use for I/O register PORTL control */
+#define POR_FT_PATTERN_bit0 D49 // use for PORTL control
+#define POR_FT_PATTERN_bit1 D48 // use for PORTL control
+
+
+/* I/O register Port A */
+#define D22 0
+#define D23 1
+#define D24 2
+#define D25 3
+#define D26 4
+#define D27 5
+#define D28 6
+#define D29 7
+
+/* I/O register Port C */
+#define D37 0
+#define D36 1
+#define D35 2
+#define D34 3
+#define D33 4
+#define D32 5
+#define D31 6
+#define D30 7
+
+/* I/O register Port L */
+#define D49 0
+#define D48 1
+#define D47 2
+#define D46 3
+#define D45 4
+#define D44 5
+#define D43 6
+#define D42 7
+
+/* I/O register Port D */
+#define D21 0
+#define D20 1
+#define D19 2
+#define D18 3
+
+
+/***************************************************************************
+**************************************************************************
+* MDC/MDIO
+***************************************************************************
+***************************************************************************/
+#define SET_HIGH(data, nbit) ((data)|=(nbit))
+#define SET_LOW(data, nbit) ((data)&=~(nbit))
+
+#define MDIO_ONE _BV(POR_MDIO)
+#define MDIO_ZERO 0x00
+#define MDC_ONE _BV(POR_MDC)
+#define MDC_ZERO 0x00
+
+#define delay_us delayMicroseconds(0)
+
+#define ANACAL_INIT 0x01
+#define ANACAL_ERROR 0xFD
+#define ANACAL_SATURATION 0xFE
+#define ANACAL_FINISH 0xFF
+#define ANACAL_PAIR_A 0
+#define ANACAL_PAIR_B 1
+#define ANACAL_PAIR_C 2
+#define ANACAL_PAIR_D 3
+#define DAC_IN_0V 0x000
+#define DAC_IN_2V 0x0f0 // +/-1V
+
+#define ZCAL_MIDDLE 0x20
+#define TX_OFFSET_0mV_idx 31
+#define TX_AMP_MIDDLE 0x20
+
+#define TX_i2mpb_hbt_ofs 0x4 // 8851 fine tune 100M v1 (20220414)
+#define R50_OFFSET_VALUE 0x5
+
+//============== definition value for GbE ===================//
+#define BG_VOLTAGE_OUT 0xc0
+#define FORCE_MDI 2
+#define FORCE_MDIX 3
+#define LDO_1p15_VOSEL_1 1
+#define RX_CAL_VALUE_9 0x3
+#define RX_CAL_HVGA_BW_2 0x2
+#define RX_CAL_DCO_Normal 0x0
+#define RX_CAL_DCO_BYPASS_TX_RX 0x3
+#define RX_CAL_DCO_0xF 0xF
+
+#define TANA_MON_DCV_SEL__MASK 0xE0
+#define TANA_MON_DCV_SEL__MPX_TANA_A 0x20
+#define TANA_MON_DCV_SEL__MPX_TANA_B 0x40
+#define TANA_MON_DCV_SEL__MPX_TANA_C 0x60
+#define TANA_MON_DCV_SEL__MPX_TANA_D 0x80
+#define TANA_MON_DCV_SEL__MONVC__MASK 0x008000C8
+#define TANA_MON_DCV__TANA__VBG_MON 0x000000C0
+#define TANA_MON_DCV__TANA__MONVC 0x000000C8
+
+#define AN_disable_force_1000M 0x0140
+#define BG_voltage_output 0xc000
+#define Fix_mdi 0x1010
+#define Disable_tx_slew_control 0x0000
+#define LDO_control 0x0100
+#define Cal_control_BG 0x1110
+#define Cal_control_R50 0x1100
+#define Cal_control_TX_AMP 0x1100
+#define Cal_control_TX_OFST 0x0100
+#define Cal_control_R50_pairA_ENABLE 0x1101
+#define Disable_all 0x0
+#define Zcalen_A_ENABLE 0x0000
+#define Zcalen_B_ENABLE 0x1000
+#define Zcalen_C_ENABLE 0x0100
+#define Zcalen_D_ENABLE 0x0010
+#define MASK_MSB_8bit 0xff00
+#define MASK_LSB_8bit 0x00ff
+#define MASK_r50ohm_rsel_tx_a 0x7f00
+#define MASK_r50ohm_rsel_tx_b 0x007f
+#define MASK_r50ohm_rsel_tx_c 0x7f00
+#define MASK_r50ohm_rsel_tx_d 0x007f
+#define Rg_r50ohm_rsel_tx_a_en 0x8000
+#define Rg_r50ohm_rsel_tx_b_en 0x0080
+#define Rg_r50ohm_rsel_tx_c_en 0x8000
+#define Rg_r50ohm_rsel_tx_d_en 0x0080
+#define Rg_txvos_calen_ENABLE 0x0001
+#define Bypass_tx_offset_cal 0x8000
+#define Enable_Tx_VLD 0xf808
+#define Rg_txg_calen_a_ENABLE 0x1000
+#define Rg_txg_calen_b_ENABLE 0x0100
+#define Rg_txg_calen_c_ENABLE 0x0010
+#define Rg_txg_calen_d_ENABLE 0x0001
+#define Force_dasn_dac_in0_ENABLE 0x8000
+#define Force_dasn_dac_in1_ENABLE 0x8000
+#define MASK_cr_tx_amp_offset_MSB 0x3f00
+#define MASK_cr_tx_amp_offset_LSB 0x003f
+#define Rg_cal_refsel_ENABLE 0x0010
+#define MASK_da_tx_i2mpb_a_gbe 0xfc00
+#define MASK_da_tx_i2mpb_b_c_d_gbe 0x3f00
+
+#define LED_basic_control_en_active_low 0x800a
+#define LED_led0_en_active_high 0xc007
+#define LED_led0_force_blinking 0x0200
+
+
+
+/*phy calibration use*/
+//Type defines
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned long UINT32;
+
+typedef struct
+{
+ UINT16 DATA_Lo;
+ UINT8 DATA_Hi;
+}TR_DATA_T;
+
+//CL22 Reg Support Page Select//
+#define RgAddr_Reg1Fh 0x1f
+#define CL22_Page_Reg 0x0000
+#define CL22_Page_ExtReg 0x0001
+#define CL22_Page_MiscReg 0x0002
+#define CL22_Page_LpiReg 0x0003
+#define CL22_Page_tReg 0x02A3
+#define CL22_Page_TrReg 0x52B5
+
+//CL45 Reg Support DEVID//
+#define DEVID_03 0x03
+#define DEVID_07 0x07
+#define DEVID_1E 0x1E
+#define DEVID_1F 0x1F
+
+//TokenRing Reg Access//
+#define TrReg_PKT_XMT_STA 0x8000
+#define TrReg_WR 0x8000
+#define TrReg_RD 0xA000
+
+/* ----------------- gephy_all Bit Field Definitions ------------------- */
+
+
+
+//-------------------------------------
+//0x0000
+#define RgAddr_Reg00h 0x00
+
+//0x51e01200
+#define RgAddr_dev1Eh_reg120h 0x0120
+//0x51e01220
+#define RgAddr_dev1Eh_reg122h 0x0122
+//0x51e01440
+#define RgAddr_dev1Eh_reg144h 0x0144
+//0x51e014a0
+#define RgAddr_dev1Eh_reg14Ah 0x014a
+//0x51e019b0
+#define RgAddr_dev1Eh_reg19Bh 0x019b
+//0x51e02340
+#define RgAddr_dev1Eh_reg234h 0x0234
+//0x51e02380
+#define RgAddr_dev1Eh_reg238h 0x0238
+//0x51e02390
+#define RgAddr_dev1Eh_reg239h 0x0239
+//0x51f02680
+#define RgAddr_dev1Fh_reg268h 0x0268
+//0x51e02d10
+#define RgAddr_dev1Eh_reg2D1h 0x02d1
+//0x51e03230
+#define RgAddr_dev1Eh_reg323h 0x0323
+//0x51e03240
+#define RgAddr_dev1Eh_reg324h 0x0324
+//0x51e03260
+#define RgAddr_dev1Eh_reg326h 0x0326
+
+//0x51f01000
+#define RgAddr_dev1Fh_reg100h 0x0100
+//0x51e01450
+#define RgAddr_dev1Eh_reg145h 0x0145
+//0x51f00ff0
+#define RgAddr_dev1Fh_reg0FFh 0x00ff
+//0x51e00db0
+#define RgAddr_dev1Eh_reg0DBh 0x00db
+//0x51e00dc0
+#define RgAddr_dev1Eh_reg0DCh 0x00dc
+//0x51e00e00
+#define RgAddr_dev1Eh_reg0E0h 0x00e0
+//0x51e00e10
+#define RgAddr_dev1Eh_reg0E1h 0x00e1
+//0x51e00e00
+#define RgAddr_dev1Eh_reg0E0h 0x00e0
+//0x51e017a0
+#define RgAddr_dev1Eh_reg17Ah 0x017a
+//0x51f01150
+#define RgAddr_dev1Fh_reg115h 0x0115
+//0x51f01000
+#define RgAddr_dev1Fh_reg100h 0x0100
+//0x51e01450
+#define RgAddr_dev1Eh_reg145h 0x0145
+//0x51e01450
+#define RgAddr_dev1Eh_reg145h 0x0145
+//0x51e01850
+#define RgAddr_dev1Eh_reg185h 0x0185
+//0x51e00fb0
+#define RgAddr_dev1Eh_reg0FBh 0x00fb
+//0x51e01740
+#define RgAddr_dev1Eh_reg174h 0x0174
+//0x51e01750
+#define RgAddr_dev1Eh_reg175h 0x0175
+//0x51e01850
+#define RgAddr_dev1Eh_reg185h 0x0185
+//0x51e00fb0
+#define RgAddr_dev1Eh_reg0FBh 0x00fb
+//0x51e00960
+#define RgAddr_dev1Eh_reg096h 0x0096
+//0x51e003e0
+#define RgAddr_dev1Eh_reg03Eh 0x003e
+//0x51e00dd0
+#define RgAddr_dev1Eh_reg0DDh 0x00dd
+//0x51e017d0
+#define RgAddr_dev1Eh_reg17Dh 0x017d
+//0x51e01810
+#define RgAddr_dev1Eh_reg181h 0x0181
+//0x51e00120
+#define RgAddr_dev1Eh_reg012h 0x0012
+//0x51e017e0
+#define RgAddr_dev1Eh_reg17Eh 0x017e
+//0x51e01820
+#define RgAddr_dev1Eh_reg182h 0x0182
+//0x51e00170
+#define RgAddr_dev1Eh_reg017h 0x0017
+//0x51e01830
+#define RgAddr_dev1Eh_reg183h 0x0183
+//0x51e00190
+#define RgAddr_dev1Eh_reg019h 0x0019
+//0x51e01800
+#define RgAddr_dev1Eh_reg180h 0x0180
+//0x51e01840
+#define RgAddr_dev1Eh_reg184h 0x0184
+//0x51e00210
+#define RgAddr_dev1Eh_reg021h 0x0021
+//0x51e01720
+#define RgAddr_dev1Eh_reg172h 0x0172
+//0x51e01730
+#define RgAddr_dev1Eh_reg173h 0x0173
+//0x51e017c0
+#define RgAddr_dev1Eh_reg17Ch 0x017c
+//0x51e017f0
+#define RgAddr_dev1Eh_reg17Fh 0x017f
+
+//0x52b5100
+#define RgAddr_TrReg10h 0x10
+//0x52b5110
+#define RgAddr_TrReg11h 0x11
+//0x52b5120
+#define RgAddr_TrReg12h 0x12
+
+//0x31c0
+#define RgAddr_LpiReg1Ch 0x1c
+//0x31d0
+#define RgAddr_LpiReg1Dh 0x1d
+uint8_t BG_Calibration(uint8_t phyadd, int8_t calipolarity);
+uint8_t R50_Calibration(uint8_t phyadd, uint8_t phyadd_common);
+uint8_t TX_OFS_Calibration(uint8_t phyadd, uint8_t phyadd_common);
+uint8_t TX_AMP_Calibration(uint8_t phyadd, uint8_t phyadd_common);
+//void config_gphy_port(UINT8, UINT8);
+
+void set_gphy_reg_cl22(uint8_t, uint8_t, uint16_t);
+uint16_t get_gphy_reg_cl45(uint8_t, uint8_t, uint16_t);
+void set_gphy_reg_cl45(uint8_t, uint8_t, uint16_t, uint16_t);
+void anacal_exe(uint8_t);
+
+#endif /* _AN8855_PHY_H_ */
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy_cal.c b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy_cal.c
new file mode 100644
index 0000000..c2e8e5c
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_phy_cal.c
@@ -0,0 +1,967 @@
+/* FILE NAME: an8855_phy_cal.c
+* PURPOSE:
+* It provides an8855 switch phy calibration function.
+*
+* NOTES:
+*
+*/
+
+/* INCLUDE FILE DECLARATIONS
+*/
+#include "an8855_mdio.h"
+#include "an8855_phy.h"
+//#include "swk_gphy_reg.h"
+//#include "gphy_calibration.h"
+//#include "gsw_reg.h"
+
+/* NAMING CONSTANT DECLARATIONS
+ */
+#define MII_BMCR (0)
+#define BMCR_PDOWN (0x0800)
+/* MACRO FUNCTION DECLARATIONS
+ */
+
+#define FULL_BITS(_n_) ((1UL << (_n_)) - 1)
+
+/* DATA TYPE DECLARATIONS
+ */
+
+/* GLOBAL VARIABLE DECLARATIONS
+ */
+/* Zcal to R50 mapping table (20220404) */
+const uint8_t ZCAL_TO_R50ohm_TBL[64] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 123, 118, 114, 110, 106, 102, 98, 96, 92, 88, 85,
+ 82, 80, 76, 72, 70, 67, 64, 62, 60, 56, 54, 52, 49, 48, 45, 43,
+ 40, 39, 36, 34, 32, 32, 30, 28, 25, 24, 22, 20, 18, 16, 16, 14
+};
+
+/* Tx offset table, value is from small to big */
+const uint8_t EN753x_TX_OFS_TBL[64] =
+{
+ 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
+ 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+#define TOTAL_PATCH_C45_ITEMS (15)
+#define TOTAL_PATCH_TR_ITEMS (19)
+const uint16_t C45_PATCH_TABLE[TOTAL_PATCH_C45_ITEMS][3] =
+{
+ {0x1E, 0x120, 0x8014},
+ {0x1E, 0x122, 0xFFFF},
+ {0x1E, 0x122, 0xFFFF},
+ {0x1E, 0x144, 0x0200},
+ {0x1E, 0x14A, 0xEE20},
+ {0x1E, 0x189, 0x0110},
+ {0x1E, 0x19B, 0x0111},
+ {0x1E, 0x234, 0x0181},
+ {0x1E, 0x238, 0x0120},
+ {0x1E, 0x239, 0x0117},
+ {0x1F, 0x268, 0x07F4},
+ {0x1E, 0x2d1, 0x0733},
+ {0x1E, 0x323, 0x0011},
+ {0x1E, 0x324, 0x013F},
+ {0x1E, 0x326, 0x0037},
+};
+
+const uint32_t TR_PATCH_TABLE[TOTAL_PATCH_TR_ITEMS][2] =
+{
+ {0x83AA, 0x055a0 },
+ {0x83AE, 0x7FF3F },
+ {0x8F80, 0x0001e },
+ {0x8F82, 0x6FB90A},
+ {0x8FAE, 0x060671},
+ {0x8FB0, 0xE2F00 },
+ {0x8ECC, 0x444444},
+ {0x9686, 0x00000 },
+ {0x968C, 0x2EBAEF},
+ {0x9690, 0x00000b},
+ {0x9698, 0x0504D },
+ {0x969A, 0x2314f },
+ {0x969E, 0x03028 },
+ {0x96A0, 0x05010 },
+ {0x96A2, 0x40001 },
+ {0x96A6, 0x018670},
+ {0x96A8, 0x0024A },
+ {0x96B6, 0x00072 },
+ {0x96B8, 0x03210 },
+};
+
+#define TOTAL_NUMBER_OF_PATCH (14)
+static uint16_t eee_patch_table[TOTAL_NUMBER_OF_PATCH][2] = {
+ {RgAddr_dev1Eh_reg120h, 0x8014},
+ {RgAddr_dev1Eh_reg122h, 0xFFFF},
+ {RgAddr_dev1Eh_reg122h, 0xFFFF},
+ {RgAddr_dev1Eh_reg144h, 0x0200},
+ {RgAddr_dev1Eh_reg14Ah, 0xEE20},
+ {RgAddr_dev1Eh_reg19Bh, 0x0111},
+ {RgAddr_dev1Eh_reg234h, 0x1181},
+ {RgAddr_dev1Eh_reg238h, 0x0120},
+ {RgAddr_dev1Eh_reg239h, 0x0117},
+ {RgAddr_dev1Fh_reg268h, 0x07F4},
+ {RgAddr_dev1Eh_reg2D1h, 0x0733},
+ {RgAddr_dev1Eh_reg323h, 0x0011},
+ {RgAddr_dev1Eh_reg324h, 0x013F},
+ {RgAddr_dev1Eh_reg326h, 0x0037}
+};
+
+#define TOTAL_NUMBER_OF_TR (19)
+static uint16_t tr_reg_table[TOTAL_NUMBER_OF_TR][3] = {
+ {0x55A0, 0x0000, 0x83AA},
+ {0xFF3F, 0x0007, 0x83AE},
+ {0x001E, 0x0000, 0x8F80},
+ {0xB90A, 0x006F, 0x8F82},
+ {0x0671, 0x0006, 0x8FAE},
+ {0x2F00, 0x000E, 0x8FB0},
+ {0x4444, 0x0044, 0x8ECC},
+ {0x0004, 0x0000, 0x9686},
+ {0xBAEF, 0x002E, 0x968C},
+ {0x000B, 0x0000, 0x9690},
+ {0x504D, 0x0000, 0x9698},
+ {0x314F, 0x0002, 0x969A},
+ {0x3028, 0x0000, 0x969E},
+ {0x5010, 0x0000, 0x96A0},
+ {0x0001, 0x0004, 0x96A2},
+ {0x8670, 0x0001, 0x96A6},
+ {0x024A, 0x0000, 0x96A8},
+ {0x0072, 0x0000, 0x96B6},
+ {0x3210, 0x0000, 0x96B8}
+};
+
+void TR_RegWr(uint16_t phyadd, uint16_t tr_reg_addr, uint32_t tr_data);
+
+uint16_t get_gphy_reg_cl22(uint8_t phyad, uint8_t reg)
+{
+ uint32_t rdata = 0;
+
+ an8855_phy_read(phyad-g_smi_addr, reg, &rdata);
+
+ return ((uint16_t)rdata);
+ /*
+ gsw_top_reg_REG_PHY_IAC REG_PHY_IAC_val;
+ gsw_top_reg_REG_PHY_IAD REG_PHY_IAD_val;
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Set address
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 1;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 2;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = phyad;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = reg;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ REG_PHY_IAD_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAD);
+
+ return REG_PHY_IAD_val.Raw;
+ */
+}
+
+/* EXPORTED SUBPROGRAM BODIES
+ */
+void gphy_config(void)
+{
+ uint8_t port = 1;
+ uint8_t phy_base = 0, phys_in_chip = 8;
+
+ for (port = 1; port <= phys_in_chip; port++)
+ {
+ set_gphy_reg_cl45(phy_base + port, 0x7, 0x3c, 0x0006); // Enable EEE
+ set_gphy_reg_cl45(phy_base + port, 0x1e, 0x3e, 0xf000); // force on TXVLD
+ }
+}
+
+static void set_gphy_TrReg(uint8_t prtid, uint16_t parm_1, uint16_t parm_2, uint16_t parm_3)
+{
+ set_gphy_reg_cl22(prtid, RgAddr_TrReg11h, parm_1);
+ set_gphy_reg_cl22(prtid, RgAddr_TrReg12h, parm_2);
+ set_gphy_reg_cl22(prtid, RgAddr_TrReg10h, parm_3);
+}
+
+static void gphy_eee_patch(uint8_t phy_base)
+{
+ UI8_T port = 1, index = 0, phy_addr = 1;
+ UI16_T data = 0;
+
+ for (port = 1; port <=8; port++)
+ {
+ phy_addr = phy_base + port;
+ data = get_gphy_reg_cl22(phy_addr, MII_BMCR);
+ set_gphy_reg_cl22(phy_addr, MII_BMCR, data & ~(BMCR_PDOWN)); /* PHY power on */
+
+ /* Change EEE RG default value */
+ for (index = 0; index < TOTAL_NUMBER_OF_PATCH; index++)
+ {
+ set_gphy_reg_cl45(phy_addr, DEVID_1E, eee_patch_table[index][0], eee_patch_table[index][1]);
+ }
+
+ set_gphy_reg_cl22(phy_addr, RgAddr_Reg1Fh, CL22_Page_TrReg); /* change CL22page to LpiReg(0x3) */
+ for (index = 0; index < TOTAL_NUMBER_OF_TR; index++)
+ {
+ set_gphy_TrReg(phy_addr, tr_reg_table[index][0], tr_reg_table[index][1], tr_reg_table[index][2]);
+ }
+
+ set_gphy_reg_cl22(phy_addr, RgAddr_Reg1Fh, CL22_Page_LpiReg); /* change CL22page to LpiReg(0x3) */
+ set_gphy_reg_cl22(phy_addr, RgAddr_LpiReg1Ch, 0x0c92); /* Fine turn SigDet for B2B LPI link down issue */
+ set_gphy_reg_cl22(phy_addr, RgAddr_LpiReg1Dh, 0x0001); /* Enable "lpi_quit_waitafesigdet_en" for LPI link down issue */
+
+ set_gphy_reg_cl22(phy_addr, RgAddr_Reg1Fh, CL22_Page_Reg); /* change CL22page to Reg(0x0) */
+ }
+}
+
+void gphy_calibration(uint8_t phy_base)
+{
+ uint8_t port = 1, phy_addr = 1 ,phy_group = 1, index = 0;
+ uint8_t phys_in_chip = 5;
+
+ BG_Calibration(phy_base, 0x1);
+ if (phys_in_chip > 4)
+ {
+ BG_Calibration(phy_base + 0x4, 0x1);
+ }
+
+ for (port = 0; port < phys_in_chip; port++)
+ {
+ if (port < 4)
+ {
+ phy_group = phy_base; /* PHY group 1 */
+ }
+ else
+ {
+ phy_group = phy_base + 0x04; /* PHY group 2 */
+ }
+ phy_addr = phy_base + port;
+ R50_Calibration(phy_addr, phy_group);
+ TX_OFS_Calibration(phy_addr, phy_group);
+ TX_AMP_Calibration(phy_addr, phy_group);
+ }
+
+ for (port = 0; port < phys_in_chip; port++)
+ {
+ phy_addr = phy_base + port;
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x017d, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x017e, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x017f, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0180, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0181, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0182, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0183, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0184, 0x0000);
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x003e, 0x0000); // disable Tx VLD force mode
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x00dd, 0x0000); // disable Tx offset/amplitude calibration circuit
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0x0145, 0x1000); // enable auto MDI/MDIX
+
+ set_gphy_reg_cl22(phy_addr, 0, 0x1200);
+ /* GPHY Rx low pass filter */
+ set_gphy_reg_cl45(phy_addr, 0x1e, 0xc7, 0xd000);
+ /* patch */
+ for (index = 0; index < TOTAL_PATCH_C45_ITEMS; index++)
+ {
+ set_gphy_reg_cl45(phy_addr, C45_PATCH_TABLE[index][0], C45_PATCH_TABLE[index][1], C45_PATCH_TABLE[index][2]);
+ }
+ for (index = 0; index < TOTAL_PATCH_TR_ITEMS; index++)
+ {
+ TR_RegWr(phy_addr, TR_PATCH_TABLE[index][0], TR_PATCH_TABLE[index][1]);
+ }
+ set_gphy_reg_cl22(phy_addr, 0x1f, 0x0 );
+ set_gphy_reg_cl22(phy_addr, 0x1f, 0x3 );
+ set_gphy_reg_cl22(phy_addr, 0x1c, 0xc92);
+ set_gphy_reg_cl22(phy_addr, 0x1d, 0x01 );
+ set_gphy_reg_cl22(phy_addr, 0x1f, 0x0 );
+ }
+ gphy_eee_patch(phy_base);
+}
+
+/* LOCAL SUBPROGRAM BODIES
+ */
+void TR_RegWr(uint16_t phyadd, uint16_t tr_reg_addr, uint32_t tr_data)
+{
+ set_gphy_reg_cl22(phyadd, 0x1F, 0x52b5); /* page select */
+ set_gphy_reg_cl22(phyadd, 0x11, (uint16_t)(tr_data & 0xffff));
+ set_gphy_reg_cl22(phyadd, 0x12, (uint16_t)(tr_data >> 16));
+ set_gphy_reg_cl22(phyadd, 0x10, (uint16_t)(tr_reg_addr | TrReg_WR));
+ set_gphy_reg_cl22(phyadd, 0x1F, 0x0); /* page resetore */
+ return;
+}
+
+uint8_t BG_Calibration(uint8_t phyadd, int8_t calipolarity)
+{
+ int8_t rg_zcal_ctrl = 0, calibration_polarity = 0;
+ uint8_t all_ana_cal_status = 1;
+ uint16_t ad_cal_comp_out_init = 0;
+
+ /* setting */
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg1Fh, CL22_Page_Reg); // g0
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg00h, AN_disable_force_1000M); // AN disable, force 1000M
+ set_gphy_reg_cl45(phyadd, DEVID_1F, RgAddr_dev1Fh_reg100h, BG_voltage_output);// BG voltage output
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg145h, Fix_mdi);// fix mdi
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Fh_reg0FFh, 0x2);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_BG);// 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all);// 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E1h, Disable_all);// 1e_e1[4]:rg_cal_refsel(0:1.2V) enable BG 1.2V to REXT PAD
+
+ /* calibrate */
+ rg_zcal_ctrl = ZCAL_MIDDLE;
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (uint16_t)rg_zcal_ctrl);
+
+ anacal_exe(phyadd);
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+ ad_cal_comp_out_init = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1;
+
+
+ if (ad_cal_comp_out_init == 1)
+ {
+ calibration_polarity = -calipolarity;
+ }
+ else // ad_cal_comp_out_init == 0
+ {
+ calibration_polarity = calipolarity;
+ }
+
+ while (all_ana_cal_status < ANACAL_ERROR)
+ {
+ rg_zcal_ctrl += calibration_polarity;
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (uint16_t)rg_zcal_ctrl);
+
+
+ anacal_exe(phyadd);
+
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+
+ else if (((get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1) != ad_cal_comp_out_init)
+ {
+ all_ana_cal_status = ANACAL_FINISH;
+ }
+ else
+ {
+ if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00))
+ {
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
+ rg_zcal_ctrl = ZCAL_MIDDLE; // 0 dB
+ }
+ }
+ }
+
+ if (all_ana_cal_status == ANACAL_ERROR)
+ {
+ rg_zcal_ctrl = ZCAL_MIDDLE; // 0 dB
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (uint16_t)rg_zcal_ctrl);
+ }
+ else
+ {
+ // rg_zcal_ctrl[5:0] rg_rext_trim[13:8]
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (uint16_t)((rg_zcal_ctrl << 8) | rg_zcal_ctrl));
+
+ // 1f_115[2:0](rg_bg_rasel) = rg_zcal_ctrl[5:3]
+ set_gphy_reg_cl45(phyadd, DEVID_1F, RgAddr_dev1Fh_reg115h, (uint16_t)((rg_zcal_ctrl & 0x3f) >> 3));
+ }
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all);
+ return all_ana_cal_status;
+}
+
+uint8_t R50_Calibration(uint8_t phyadd, uint8_t phyadd_common)
+{
+ int8_t rg_zcal_ctrl = 0, rg_r50ohm_rsel_tx = 0, calibration_polarity = 0;
+ uint8_t all_ana_cal_status = 1;
+ int16_t backup_dev1e_e0 = 0, ad_cal_comp_out_init = 0, calibration_pair = 0;
+
+ /* setting */
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg1Fh, CL22_Page_Reg); // g0
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg00h, AN_disable_force_1000M); // AN disable, force 1000M
+
+ set_gphy_reg_cl45(phyadd_common, DEVID_1F, RgAddr_dev1Fh_reg100h, BG_voltage_output); // BG voltage output
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg145h, Fix_mdi); // fix mdi
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg185h, Disable_tx_slew_control); // disable tx slew control
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0FBh, LDO_control); // ldo
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_R50); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all); // 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0E1h, Disable_all); // 1e_e1[4]:rg_cal_refsel(0:1.2V) enable BG 1.2V to REXT PAD
+
+ for (calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair++)
+ {
+ all_ana_cal_status = 1;
+
+ if (calibration_pair == ANACAL_PAIR_A)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_R50_pairA_ENABLE); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Zcalen_A_ENABLE);
+ }
+ else if (calibration_pair == ANACAL_PAIR_B)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_R50); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Zcalen_B_ENABLE); // 1e_dc[12]:rg_zcalen_b
+ }
+ else if (calibration_pair == ANACAL_PAIR_C)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_R50); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Zcalen_C_ENABLE); // 1e_dc[8]:rg_zcalen_c
+ }
+ else // if(calibration_pair == ANACAL_PAIR_D)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_R50); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Zcalen_D_ENABLE); // 1e_dc[4]:rg_zcalen_d
+ }
+
+ /* calibrate */
+ rg_zcal_ctrl = ZCAL_MIDDLE; // start with 0 dB
+
+ backup_dev1e_e0 = (get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0E0h)&(~0x003f));
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (backup_dev1e_e0 | rg_zcal_ctrl));
+
+ anacal_exe(phyadd_common);
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+
+ ad_cal_comp_out_init = (get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
+
+ if (ad_cal_comp_out_init == 1)
+ {
+ calibration_polarity = -1;
+ }
+ else
+ {
+ calibration_polarity = 1;
+ }
+
+ while (all_ana_cal_status < ANACAL_ERROR)
+ {
+ rg_zcal_ctrl += calibration_polarity;
+
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0E0h, (backup_dev1e_e0 | rg_zcal_ctrl));
+
+ anacal_exe(phyadd_common);
+
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+ else if (((get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1) != ad_cal_comp_out_init)
+ {
+ all_ana_cal_status = ANACAL_FINISH;
+ }
+ else
+ {
+ if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00))
+ {
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
+ rg_zcal_ctrl = ZCAL_MIDDLE; // 0 dB
+ }
+ }
+ }
+
+ if (all_ana_cal_status == ANACAL_ERROR)
+ {
+ rg_r50ohm_rsel_tx = ZCAL_MIDDLE; // 0 dB
+ }
+ else
+ {
+ if (rg_zcal_ctrl > (0x3F - R50_OFFSET_VALUE))
+ {
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
+ rg_zcal_ctrl = ZCAL_MIDDLE; // 0 dB
+ }
+ else
+ {
+ rg_zcal_ctrl += R50_OFFSET_VALUE;
+ }
+
+ rg_r50ohm_rsel_tx = ZCAL_TO_R50ohm_TBL[rg_zcal_ctrl];
+ }
+
+ if (calibration_pair == ANACAL_PAIR_A)
+ {
+ // cr_r50ohm_rsel_tx_a
+ ad_cal_comp_out_init = get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg174h)&(~MASK_r50ohm_rsel_tx_a);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg174h, (ad_cal_comp_out_init | (((rg_r50ohm_rsel_tx << 8) & MASK_MSB_8bit) | Rg_r50ohm_rsel_tx_a_en))); // 1e_174[15:8]
+ }
+ else if (calibration_pair == ANACAL_PAIR_B)
+ {
+ // cr_r50ohm_rsel_tx_b
+ ad_cal_comp_out_init = get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg174h)&(~MASK_r50ohm_rsel_tx_b);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg174h, (ad_cal_comp_out_init | (((rg_r50ohm_rsel_tx << 0) & MASK_LSB_8bit) | Rg_r50ohm_rsel_tx_b_en))); // 1e_174[7:0]
+ }
+ else if (calibration_pair == ANACAL_PAIR_C)
+ {
+ // cr_r50ohm_rsel_tx_c
+ ad_cal_comp_out_init = get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg175h)&(~MASK_r50ohm_rsel_tx_c);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg175h, (ad_cal_comp_out_init | (((rg_r50ohm_rsel_tx << 8) & MASK_MSB_8bit) | Rg_r50ohm_rsel_tx_c_en))); // 1e_175[15:8]
+ }
+ else // if(calibration_pair == ANACAL_PAIR_D)
+ {
+ // cr_r50ohm_rsel_tx_d
+ ad_cal_comp_out_init = get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg175h)&(~MASK_r50ohm_rsel_tx_d);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg175h, (ad_cal_comp_out_init | (((rg_r50ohm_rsel_tx << 0) & MASK_LSB_8bit) | Rg_r50ohm_rsel_tx_d_en))); // 1e_175[7:0]
+ }
+ }
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all);
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all);
+
+ return all_ana_cal_status;
+}
+
+uint8_t TX_OFS_Calibration(uint8_t phyadd, uint8_t phyadd_common)
+{
+ int8_t tx_offset_index = 0, calibration_polarity = 0;
+ uint8_t all_ana_cal_status = 1, tx_offset_reg_shift = 0, tbl_idx = 0;
+ int16_t ad_cal_comp_out_init = 0, calibration_pair = 0, tx_offset_reg = 0, reg_temp = 0;
+
+ /* setting */
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg1Fh, CL22_Page_Reg); // g0
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg00h, AN_disable_force_1000M); // AN disable, force 1000M
+
+ set_gphy_reg_cl45(phyadd, DEVID_1F, RgAddr_dev1Fh_reg100h, BG_voltage_output); // BG voltage output
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg145h, Fix_mdi); // fix mdi
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg185h, Disable_tx_slew_control); // disable tx slew control
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0FBh, LDO_control); // ldo
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_TX_OFST); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Rg_txvos_calen_ENABLE); // 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_TX_OFST); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Rg_txvos_calen_ENABLE); // 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E1h, Disable_all); // 1e_e1[4]:rg_cal_refsel(0:1.2V) enable BG 1.2V to REXT PAD
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg096h, Bypass_tx_offset_cal); // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg03Eh, Enable_Tx_VLD); // 1e_3e:enable Tx VLD
+
+ for (calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair++)
+ {
+ all_ana_cal_status = 1;
+
+ tbl_idx = TX_OFFSET_0mV_idx;
+ tx_offset_index = EN753x_TX_OFS_TBL[tbl_idx];
+
+ if (calibration_pair == ANACAL_PAIR_A)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_a_ENABLE); // 1e_dd[12]:rg_txg_calen_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Dh, (Force_dasn_dac_in0_ENABLE | DAC_IN_0V)); // 1e_17d:dac_in0_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg181h, (Force_dasn_dac_in1_ENABLE | DAC_IN_0V)); // 1e_181:dac_in1_a
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg172h)&(~MASK_cr_tx_amp_offset_MSB));
+ tx_offset_reg_shift = 8; // 1e_172[13:8]
+ tx_offset_reg = RgAddr_dev1Eh_reg172h;
+ }
+ else if (calibration_pair == ANACAL_PAIR_B)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_b_ENABLE); // 1e_dd[8]:rg_txg_calen_b
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Eh, (Force_dasn_dac_in0_ENABLE | DAC_IN_0V)); // 1e_17e:dac_in0_b
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg182h, (Force_dasn_dac_in1_ENABLE | DAC_IN_0V)); // 1e_182:dac_in1_b
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg172h)&(~MASK_cr_tx_amp_offset_LSB));
+ tx_offset_reg_shift = 0; // 1e_172[5:0]
+ tx_offset_reg = RgAddr_dev1Eh_reg172h;
+ }
+ else if (calibration_pair == ANACAL_PAIR_C)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_c_ENABLE); // 1e_dd[4]:rg_txg_calen_c
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Fh, (Force_dasn_dac_in0_ENABLE | DAC_IN_0V)); // 1e_17f:dac_in0_c
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg183h, (Force_dasn_dac_in1_ENABLE | DAC_IN_0V)); // 1e_183:dac_in1_c
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg173h)&(~MASK_cr_tx_amp_offset_MSB));
+ tx_offset_reg_shift = 8; // 1e_173[13:8]
+ tx_offset_reg = RgAddr_dev1Eh_reg173h;
+ }
+ else // if(calibration_pair == ANACAL_PAIR_D)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_d_ENABLE); // 1e_dd[0]:rg_txg_calen_d
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg180h, (Force_dasn_dac_in0_ENABLE | DAC_IN_0V)); // 1e_180:dac_in0_d
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg184h, (Force_dasn_dac_in1_ENABLE | DAC_IN_0V)); // 1e_184:dac_in1_d
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg173h)&(~MASK_cr_tx_amp_offset_LSB));
+ tx_offset_reg_shift = 0; // 1e_173[5:0]
+ tx_offset_reg = RgAddr_dev1Eh_reg173h;
+ }
+
+ /* calibrate */
+ //tx_offset_index = TX_AMP_OFFSET_0mV;
+ tbl_idx = TX_OFFSET_0mV_idx;
+ tx_offset_index = EN753x_TX_OFS_TBL[tbl_idx];
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_offset_reg, (reg_temp | (tx_offset_index << tx_offset_reg_shift))); // 1e_172, 1e_173
+
+ anacal_exe(phyadd_common);
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+
+ ad_cal_comp_out_init = (get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
+
+ if (ad_cal_comp_out_init == 1)
+ {
+ calibration_polarity = -1;
+ }
+ else
+ {
+ calibration_polarity = 1;
+ }
+
+ while (all_ana_cal_status < ANACAL_ERROR)
+ {
+ tbl_idx += calibration_polarity;
+ tx_offset_index = EN753x_TX_OFS_TBL[tbl_idx];
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_offset_reg, (reg_temp | (tx_offset_index << tx_offset_reg_shift))); // 1e_172, 1e_173
+
+ anacal_exe(phyadd_common);
+
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+ else if (((get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1) != ad_cal_comp_out_init)
+ {
+ all_ana_cal_status = ANACAL_FINISH;
+ }
+ else
+ {
+ if ((tx_offset_index == 0x3f) || (tx_offset_index == 0x1f))
+ {
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
+ }
+ }
+ }
+
+ if (all_ana_cal_status == ANACAL_ERROR)
+ {
+ tbl_idx = TX_OFFSET_0mV_idx;
+ tx_offset_index = EN753x_TX_OFS_TBL[tbl_idx];
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_offset_reg, (reg_temp | (tx_offset_index << tx_offset_reg_shift))); // cr_tx_amp_offset_a/b/c/d, 1e_172, 1e_173
+ }
+ }
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Dh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Eh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Fh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg180h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg181h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg182h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg183h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg184h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all); // disable analog calibration circuit
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all); // disable Tx offset calibration circuit
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all); // disable analog calibration circuit
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all); // disable Tx offset calibration circuit
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg03Eh, Disable_all); // disable Tx VLD force mode
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Disable_all); // disable Tx offset/amplitude calibration circuit
+
+ return all_ana_cal_status;
+}
+
+uint8_t TX_AMP_Calibration(uint8_t phyadd, uint8_t phyadd_common)
+{
+ int8_t tx_amp_index = 0, calibration_polarity = 0;
+ uint8_t all_ana_cal_status = 1, tx_amp_reg_shift = 0;
+ uint8_t tx_amp_reg = 0, tx_amp_reg_100 = 0, tst_offset = 0, hbt_offset = 0, gbe_offset = 0, tbt_offset = 0;
+ uint16_t ad_cal_comp_out_init = 0, calibration_pair = 0, reg_temp = 0;
+
+ //phyadd_common = phyadd;
+
+ /* setting */
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg1Fh, CL22_Page_Reg); // g0
+ set_gphy_reg_cl22(phyadd, RgAddr_Reg00h, AN_disable_force_1000M); // AN disable, force 1000M
+
+ set_gphy_reg_cl45(phyadd, DEVID_1F, RgAddr_dev1Fh_reg100h, BG_voltage_output); // BG voltage output
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg145h, Fix_mdi); // fix mdi
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg185h, Disable_tx_slew_control); // disable tx slew control
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0FBh, LDO_control); // ldo
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_TX_AMP); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Rg_txvos_calen_ENABLE); // 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0E1h, Rg_cal_refsel_ENABLE); // 1e_e1[4]:rg_cal_refsel(0:1.2V) enable BG 1.2V to REXT PAD
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Cal_control_TX_AMP); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Rg_txvos_calen_ENABLE); // 1e_dc[0]:rg_txvos_calen
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg0E1h, Rg_cal_refsel_ENABLE); // 1e_e1[4]:rg_cal_refsel(0:1.2V) enable BG 1.2V to REXT PAD
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg096h, Bypass_tx_offset_cal); // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg03Eh, Enable_Tx_VLD); // 1e_3e:enable Tx VLD
+
+ for (calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair++)
+ //for (calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_B; calibration_pair++) // debugging
+ {
+ all_ana_cal_status = 1;
+
+ /* calibrate */
+ tx_amp_index = TX_AMP_MIDDLE; // start with 0 dB
+ if (calibration_pair == ANACAL_PAIR_A)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_a_ENABLE); // 1e_dd[12]:rg_txg_calen_a amp calibration enable
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Dh, (Force_dasn_dac_in0_ENABLE | DAC_IN_2V)); // 1e_17d:dac_in0_a
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg181h, (Force_dasn_dac_in1_ENABLE | DAC_IN_2V)); // 1e_181:dac_in1_a
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg012h)&(~MASK_da_tx_i2mpb_a_gbe));
+ tx_amp_reg_shift = 10; // 1e_12[15:10]
+ tx_amp_reg = RgAddr_dev1Eh_reg012h;
+ tx_amp_reg_100 = 0x16;
+ }
+ else if (calibration_pair == ANACAL_PAIR_B)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_b_ENABLE); // 1e_dd[8]:rg_txg_calen_b amp calibration enable
+ //Serial.println(Rg_txg_calen_b_ENABLE, HEX);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Eh, (Force_dasn_dac_in0_ENABLE | DAC_IN_2V)); // 1e_17e:dac_in0_b
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg182h, (Force_dasn_dac_in1_ENABLE | DAC_IN_2V)); // 1e_182:dac_in1_b
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg017h)&(~MASK_da_tx_i2mpb_b_c_d_gbe));
+ tx_amp_reg_shift = 8; // 1e_17[13:8]
+ tx_amp_reg = RgAddr_dev1Eh_reg017h;
+ tx_amp_reg_100 = 0x18;
+ }
+ else if (calibration_pair == ANACAL_PAIR_C)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_c_ENABLE); // 1e_dd[4]:rg_txg_calen_c amp calibration enable
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Fh, (Force_dasn_dac_in0_ENABLE | DAC_IN_2V)); // 1e_17f:dac_in0_c
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg183h, (Force_dasn_dac_in1_ENABLE | DAC_IN_2V)); // 1e_183:dac_in1_c
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg019h)&(~MASK_da_tx_i2mpb_b_c_d_gbe));
+ tx_amp_reg_shift = 8; // 1e_19[13:8]
+ tx_amp_reg = RgAddr_dev1Eh_reg019h;
+ tx_amp_reg_100 = 0x20;
+ }
+ else //if(calibration_pair == ANACAL_PAIR_D)
+ {
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Rg_txg_calen_d_ENABLE); // 1e_dd[0]:rg_txg_calen_d amp calibration enable
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg180h, (Force_dasn_dac_in0_ENABLE | DAC_IN_2V)); // 1e_180:dac_in0_d
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg184h, (Force_dasn_dac_in1_ENABLE | DAC_IN_2V)); // 1e_184:dac_in1_d
+
+ reg_temp = (get_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg021h)&(~MASK_da_tx_i2mpb_b_c_d_gbe));
+ tx_amp_reg_shift = 8; // 1e_21[13:8]
+ tx_amp_reg = RgAddr_dev1Eh_reg021h;
+ tx_amp_reg_100 = 0x22;
+ }
+
+ /* calibrate */
+ tx_amp_index = TX_AMP_MIDDLE; // start with 0 dB
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_amp_reg, (reg_temp | (tx_amp_index << tx_amp_reg_shift))); // 1e_12/17/19/21
+
+ anacal_exe(phyadd_common);
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+
+
+ ad_cal_comp_out_init = (get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
+ //Serial.println(ad_cal_comp_out_init, HEX);
+
+ if (ad_cal_comp_out_init == 1)
+ {
+ calibration_polarity = -1;
+ }
+ else
+ {
+ calibration_polarity = 1;
+ }
+ while (all_ana_cal_status < ANACAL_ERROR)
+ {
+ tx_amp_index += calibration_polarity;
+ //Serial.println(tx_amp_index, HEX);
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_amp_reg, (reg_temp | (tx_amp_index << tx_amp_reg_shift)));
+
+ anacal_exe(phyadd_common);
+
+ if (all_ana_cal_status == 0)
+ {
+ all_ana_cal_status = ANACAL_ERROR;
+ }
+ else if (((get_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ah) >> 8) & 0x1) != ad_cal_comp_out_init)
+ {
+ all_ana_cal_status = ANACAL_FINISH;
+ //Serial.print(" tx_amp_index: ");
+ //Serial.println(tx_amp_index, HEX);
+ //reg_temp = get_gphy_reg_cl45(phyadd, 0x1e, tx_amp_reg)&(~0xff00);
+ //set_gphy_reg_cl45(phyadd, 0x1e, tx_amp_reg, (reg_temp|((tx_amp_index + tst_offset)<<tx_amp_reg_shift))); // for gbe(DAC)
+ }
+ else
+ {
+ if ((tx_amp_index == 0x3f) || (tx_amp_index == 0x00))
+ {
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
+ tx_amp_index = TX_AMP_MIDDLE;
+ }
+ }
+ }
+
+ if (all_ana_cal_status == ANACAL_ERROR)
+ {
+ tx_amp_index = TX_AMP_MIDDLE;
+ }
+
+ // da_tx_i2mpb_a_gbe / b/c/d, only GBE for now
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_amp_reg, ((tx_amp_index - TXAMP_offset) | ((tx_amp_index - TXAMP_offset) << tx_amp_reg_shift))); // // temp modify
+ set_gphy_reg_cl45(phyadd, DEVID_1E, tx_amp_reg_100, ((tx_amp_index - TXAMP_offset) | ((tx_amp_index + TX_i2mpb_hbt_ofs) << tx_amp_reg_shift)));
+ }
+
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Dh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Eh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg17Fh, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg180h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg181h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg182h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg183h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg184h, Disable_all);
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DBh, Disable_all); // disable analog calibration circuit
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DCh, Disable_all); // disable Tx offset calibration circuit
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg03Eh, Disable_all); // disable Tx VLD force mode
+ set_gphy_reg_cl45(phyadd, DEVID_1E, RgAddr_dev1Eh_reg0DDh, Disable_all); // disable Tx offset/amplitude calibration circuit
+
+ return all_ana_cal_status;
+}
+
+void set_gphy_reg_cl22(uint8_t phyad, uint8_t reg, uint16_t value)
+{
+ an8855_phy_write(phyad-g_smi_addr, reg, value);
+ /*
+ gsw_top_reg_REG_PHY_IAC REG_PHY_IAC_val;
+ gsw_top_reg_REG_PHY_IAD REG_PHY_IAD_val;
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Set address
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 1;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 1;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = phyad;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = reg;
+ REG_PHY_IAC_val.Bits.csr_mdio_wr_data = value;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+ */
+}
+
+UINT16 get_gphy_reg_cl45(uint8_t prtid, uint8_t devid, uint16_t reg)
+{
+ UINT32 rdata = 0;
+
+ an8855_phy_read_cl45(prtid-g_smi_addr, devid, reg, &rdata);
+ return ((UINT16)rdata);
+ /*
+ gsw_top_reg_REG_PHY_IAC REG_PHY_IAC_val;
+ gsw_top_reg_REG_PHY_IAD REG_PHY_IAD_val;
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Set address
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = prtid;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = devid;
+ REG_PHY_IAC_val.Bits.csr_mdio_wr_data = reg;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Read value
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 3;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = prtid;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = devid;
+ REG_PHY_IAC_val.Bits.csr_mdio_wr_data = 0;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ REG_PHY_IAD_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAD);
+
+ return REG_PHY_IAD_val.Raw;
+ */
+}
+
+void set_gphy_reg_cl45(uint8_t prtid, uint8_t devid, uint16_t reg, uint16_t value)
+{
+ an8855_phy_write_cl45(prtid-g_smi_addr, devid, reg, value);
+ /*
+ gsw_top_reg_REG_PHY_IAC REG_PHY_IAC_val;
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Set address
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = prtid;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = devid;
+ REG_PHY_IAC_val.Bits.csr_mdio_wr_data = reg;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+
+ // Wait until done
+ do
+ {
+ REG_PHY_IAC_val.Raw = io_read32(RgAddr_gsw_top_reg_REG_PHY_IAC);
+ }
+ while(REG_PHY_IAC_val.Bits.csr_phy_acs_st);
+
+ // Write value
+ REG_PHY_IAC_val.Bits.csr_mdio_st = 0;
+ REG_PHY_IAC_val.Bits.csr_mdio_cmd = 1;
+ REG_PHY_IAC_val.Bits.csr_mdio_phy_addr = prtid;
+ REG_PHY_IAC_val.Bits.csr_mdio_reg_addr = devid;
+ REG_PHY_IAC_val.Bits.csr_mdio_wr_data = value;
+ REG_PHY_IAC_val.Bits.csr_phy_acs_st = 1;
+
+ io_write32(RgAddr_gsw_top_reg_REG_PHY_IAC, REG_PHY_IAC_val.Raw);
+ */
+}
+
+void anacal_exe(uint8_t phyadd_common)
+{
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ch, 1);// da_calin_flag pull high
+ an8855_udelay(1000);
+ set_gphy_reg_cl45(phyadd_common, DEVID_1E, RgAddr_dev1Eh_reg17Ch, 0);// da_calin_flag pull low
+}
+
diff --git a/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_reg.h b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_reg.h
new file mode 100644
index 0000000..3459cef
--- /dev/null
+++ b/recipes-devtools/switch/files/src/an8855_sdk/core/an8855_reg.h
@@ -0,0 +1,191 @@
+ /* FILE NAME: an8855_reg.h
+ * PURPOSE:
+ * It provides AN8855 register definition.
+ * NOTES:
+ *
+ */
+
+#ifndef AN8855_REG_H
+#define AN8855_REG_H
+
+#define PORT_CTRL_BASE 0x10208000
+#define PORT_CTRL_PORT_OFFSET 0x200
+#define PORT_CTRL_REG(p, r) (PORT_CTRL_BASE + (p) * PORT_CTRL_PORT_OFFSET + (r))
+#define PCR(p) PORT_CTRL_REG(p, 0x04)
+
+#define PORT_MAC_CTRL_BASE 0x10210000
+#define PORT_MAC_CTRL_PORT_OFFSET 0x200
+#define PORT_MAC_CTRL_REG(p, r) (PORT_MAC_CTRL_BASE + (p) * PORT_MAC_CTRL_PORT_OFFSET + (r))
+#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00)
+
+/* Port debug count register */
+#define DBG_CNT_BASE 0x3018
+#define DBG_CNT_PORT_BASE 0x100
+#define DBG_CNT(p) (DBG_CNT_BASE + (p) * DBG_CNT_PORT_BASE)
+#define DIS_CLR (1 << 31)
+
+#define GMACCR (PORT_MAC_CTRL_BASE + 0x30e0)
+#define MTCC_LMT_S 8
+#define MAX_RX_JUMBO_S 4
+
+/* Values of MAX_RX_PKT_LEN */
+#define RX_PKT_LEN_1518 0
+#define RX_PKT_LEN_1536 1
+#define RX_PKT_LEN_1522 2
+#define RX_PKT_LEN_MAX_JUMBO 3
+
+/* Fields of PMCR */
+#define FORCE_MODE (1 << 31)
+#define IPG_CFG_S 20
+#define IPG_CFG_M 0x300000
+#define EXT_PHY (1 << 19)
+#define MAC_MODE (1 << 18)
+#define MAC_TX_EN (1 << 16)
+#define MAC_RX_EN (1 << 15)
+#define MAC_PRE (1 << 14)
+#define BKOFF_EN (1 << 12)
+#define BACKPR_EN (1 << 11)
+#define FORCE_EEE1G (1 << 7)
+#define FORCE_EEE100 (1 << 6)
+#define FORCE_RX_FC (1 << 5)
+#define FORCE_TX_FC (1 << 4)
+#define FORCE_SPD_S 28
+#define FORCE_SPD_M 0x70000000
+#define FORCE_DPX (1 << 25)
+#define FORCE_LINK (1 << 24)
+
+/* Fields of PMSR */
+#define EEE1G_STS (1 << 7)
+#define EEE100_STS (1 << 6)
+#define RX_FC_STS (1 << 5)
+#define TX_FC_STS (1 << 4)
+#define MAC_SPD_STS_S 28
+#define MAC_SPD_STS_M 0x70000000
+#define MAC_DPX_STS (1 << 25)
+#define MAC_LNK_STS (1 << 24)
+
+/* Values of MAC_SPD_STS */
+#define MAC_SPD_10 0
+#define MAC_SPD_100 1
+#define MAC_SPD_1000 2
+#define MAC_SPD_2500 3
+
+/* Values of IPG_CFG */
+#define IPG_96BIT 0
+#define IPG_96BIT_WITH_SHORT_IPG 1
+#define IPG_64BIT 2
+
+#define SGMII_REG_BASE 0x5000
+#define SGMII_REG_PORT_BASE 0x1000
+#define SGMII_REG(p, r) (SGMII_REG_BASE + (p) * SGMII_REG_PORT_BASE + (r))
+#define PCS_CONTROL_1(p) SGMII_REG(p, 0x00)
+#define SGMII_MODE(p) SGMII_REG(p, 0x20)
+#define QPHY_PWR_STATE_CTRL(p) SGMII_REG(p, 0xe8)
+#define PHYA_CTRL_SIGNAL3(p) SGMII_REG(p, 0x128)
+
+/* Fields of PCS_CONTROL_1 */
+#define SGMII_LINK_STATUS (1 << 18)
+#define SGMII_AN_ENABLE (1 << 12)
+#define SGMII_AN_RESTART (1 << 9)
+
+/* Fields of SGMII_MODE */
+#define SGMII_REMOTE_FAULT_DIS (1 << 8)
+#define SGMII_IF_MODE_FORCE_DUPLEX (1 << 4)
+#define SGMII_IF_MODE_FORCE_SPEED_S 0x2
+#define SGMII_IF_MODE_FORCE_SPEED_M 0x0c
+#define SGMII_IF_MODE_ADVERT_AN (1 << 1)
+
+/* Values of SGMII_IF_MODE_FORCE_SPEED */
+#define SGMII_IF_MODE_FORCE_SPEED_10 0
+#define SGMII_IF_MODE_FORCE_SPEED_100 1
+#define SGMII_IF_MODE_FORCE_SPEED_1000 2
+
+/* Fields of QPHY_PWR_STATE_CTRL */
+#define PHYA_PWD (1 << 4)
+
+/* Fields of PHYA_CTRL_SIGNAL3 */
+#define RG_TPHY_SPEED_S 2
+#define RG_TPHY_SPEED_M 0x0c
+
+/* Values of RG_TPHY_SPEED */
+#define RG_TPHY_SPEED_1000 0
+#define RG_TPHY_SPEED_2500 1
+
+#define SYS_CTRL 0x7000
+#define SW_PHY_RST (1 << 2)
+#define SW_SYS_RST (1 << 1)
+#define SW_REG_RST (1 << 0)
+
+#define PHY_IAC (0x1000e000)
+#define IAC_MAX_BUSY_TIME (1000)
+
+#define CLKGEN_CTRL 0x7500
+#define CLK_SKEW_OUT_S 8
+#define CLK_SKEW_OUT_M 0x300
+#define CLK_SKEW_IN_S 6
+#define CLK_SKEW_IN_M 0xc0
+#define RXCLK_NO_DELAY (1 << 5)
+#define TXCLK_NO_REVERSE (1 << 4)
+#define GP_MODE_S 1
+#define GP_MODE_M 0x06
+#define GP_CLK_EN (1 << 0)
+
+/* Values of GP_MODE */
+#define GP_MODE_RGMII 0
+#define GP_MODE_MII 1
+#define GP_MODE_REV_MII 2
+
+/* Values of CLK_SKEW_IN */
+#define CLK_SKEW_IN_NO_CHANGE 0
+#define CLK_SKEW_IN_DELAY_100PPS 1
+#define CLK_SKEW_IN_DELAY_200PPS 2
+#define CLK_SKEW_IN_REVERSE 3
+
+/* Values of CLK_SKEW_OUT */
+#define CLK_SKEW_OUT_NO_CHANGE 0
+#define CLK_SKEW_OUT_DELAY_100PPS 1
+#define CLK_SKEW_OUT_DELAY_200PPS 2
+#define CLK_SKEW_OUT_REVERSE 3
+
+#define HWSTRAP 0x7800
+#define XTAL_FSEL_S 7
+#define XTAL_FSEL_M (1 << 7)
+
+#define XTAL_40MHZ 0
+#define XTAL_25MHZ 1
+
+#define PLLGP_EN 0x7820
+#define EN_COREPLL (1 << 2)
+#define SW_CLKSW (1 << 1)
+#define SW_PLLGP (1 << 0)
+
+#define PLLGP_CR0 0x78a8
+#define RG_COREPLL_EN (1 << 22)
+#define RG_COREPLL_POSDIV_S 23
+#define RG_COREPLL_POSDIV_M 0x3800000
+#define RG_COREPLL_SDM_PCW_S 1
+#define RG_COREPLL_SDM_PCW_M 0x3ffffe
+#define RG_COREPLL_SDM_PCW_CHG (1 << 0)
+
+#define MHWSTRAP 0x7804
+#define TOP_SIG_SR 0x780c
+#define PAD_DUAL_SGMII_EN (1 << 1)
+
+/* RGMII and SGMII PLL clock */
+#define ANA_PLLGP_CR2 0x78b0
+#define ANA_PLLGP_CR5 0x78bc
+
+/* Efuse Register Define */
+#define GBE_EFUSE 0x7bc8
+#define GBE_SEL_EFUSE_EN (1 << 0)
+
+/* GPIO_PAD_0 */
+#define GPIO_MODE0 0x7c0c
+#define GPIO_MODE0_S 0
+#define GPIO_MODE0_M 0xf
+#define GPIO_0_INTERRUPT_MODE 0x1
+
+#define SMT0_IOLB 0x7f04
+#define SMT_IOLB_5_SMI_MDC_EN (1 << 5)
+
+#endif /* End of AN8855_REG_H */
diff --git a/recipes-devtools/switch/files/src/switch_753x.c b/recipes-devtools/switch/files/src/switch_753x.c
index 9c7c921..6936f6a 100644
--- a/recipes-devtools/switch/files/src/switch_753x.c
+++ b/recipes-devtools/switch/files/src/switch_753x.c
@@ -12,10 +12,14 @@
#include "switch_netlink.h"
#include "switch_ioctl.h"
#include "switch_fun.h"
+#include "switch_fun_an8855.h"
+
+#define SWITCH_APP_VERSION "1.0.1"
struct mt753x_attr *attres;
int chip_name;
bool nl_init_flag;
+struct switch_func_s *p_switch_func;
static void usage(char *cmd)
{
@@ -23,16 +27,16 @@
/* 1. basic operations */
printf("1) mt753x switch Basic operations=================================================================================================================>>>>\n");
- printf(" 1.1) %s devs - list switch device id and model name \n", cmd);
- printf(" 1.2) %s sysctl - show the ways to access kenerl driver: netlink or ioctl \n", cmd);
+ printf(" 1.1) %s devs - list switch device id and model name\n", cmd);
+ printf(" 1.2) %s sysctl - show the ways to access kenerl driver: netlink or ioctl\n", cmd);
printf(" 1.3) %s reset - sw reset switch fsm and registers\n", cmd);
- printf(" 1.4) %s reg r [offset] - read the reg with default switch \n", cmd);
- printf(" 1.5) %s reg w [offset] [value] - write the reg with default switch \n", cmd);
+ printf(" 1.4) %s reg r [offset] - read the reg with default switch\n", cmd);
+ printf(" 1.5) %s reg w [offset] [value] - write the reg with default switch\n", cmd);
printf(" 1.6) %s reg d [offset] - dump the reg with default switch\n", cmd);
- printf(" 1.7) %s dev [devid] reg r [addr] - read the reg with the switch devid \n", cmd);
- printf(" 1.8) %s dev [devid] reg w [addr] [value] - write the regs with the switch devid \n", cmd);
- printf(" 1.9) %s dev [devid] reg d [addr] - dump the regs with the switch devid \n", cmd);
- printf(" \n");
+ printf(" 1.7) %s dev [devid] reg r [addr] - read the reg with the switch devid\n", cmd);
+ printf(" 1.8) %s dev [devid] reg w [addr] [value] - write the regs with the switch devid\n", cmd);
+ printf(" 1.9) %s dev [devid] reg d [addr] - dump the regs with the switch devid\n", cmd);
+ printf("\n");
/* 2. phy operations */
printf("2) mt753x switch PHY operations===================================================================================================================>>>>\n");
@@ -42,13 +46,13 @@
printf(" 2.4) %s phy cl22 w [port_num] [phy_reg] [value] - write specific phy register of specific port by clause 22\n", cmd);
printf(" 2.5) %s phy cl45 r [port_num] [dev_num] [phy_reg] - read specific phy register of specific port by clause 45\n", cmd);
printf(" 2.6) %s phy cl45 w [port_num] [dev_num] [phy_reg] [value] - write specific phy register of specific port by clause 45\n", cmd);
- printf(" 2.7) %s phy fc [port_num] [enable 0|1] - set switch phy flow control, port is 0~4, enable is 1, disable is 0 \n", cmd);
- printf(" 2.8) %s phy an [port_num] [enable 0|1] - set switch phy auto-negotiation, port is 0~4, enable is 1, disable is 0 \n", cmd);
+ printf(" 2.7) %s phy fc [port_num] [enable 0|1] - set switch phy flow control, port is 0~4, enable is 1, disable is 0\n", cmd);
+ printf(" 2.8) %s phy an [port_num] [enable 0|1] - set switch phy auto-negotiation, port is 0~4, enable is 1, disable is 0\n", cmd);
printf(" 2.9) %s trreg r [port_num] [ch_addr] [node_addr] [data_addr] - read phy token-ring of specific port\n", cmd);
printf(" 2.10) %s trreg w [port_num] [ch_addr] [node_addr] [data_addr] - write phy token-ring of specific port\n", cmd);
- printf(" [high_value] [low_value] \n");
+ printf(" [high_value] [low_value]\n");
printf(" 2.11) %s crossover [port_num] [mode auto|mdi|mdix] - switch auto or force mdi/mdix mode for crossover cable\n", cmd);
- printf(" \n");
+ printf("\n");
/* 3. mac operations */
printf("3) mt753x switch MAC operations====================================================================================================================>>>>\n");
@@ -65,35 +69,35 @@
printf(" 3.11) %s filt [mac] [portmap] - add a SA filtering entry (with portmap)to switch mac table\n", cmd);
printf(" 3.12) %s filt [mac] [portmap] [vlan id - add a SA filtering entry (with portmap, vlan id)to switch mac table\n", cmd);
printf(" 3.13) %s filt [mac] [portmap] [vlan id] [age] - add a SA filtering entry (with portmap, vlan id, age out time) to switch table\n", cmd);
- printf(" 3.14) %s arl aging [active:0|1] [time:1~65536] - set switch arl aging timeout value \n", cmd);
- printf(" 3.15) %s macctl fc [enable|disable] - set switch mac global flow control,enable is 1, disable is 0 \n", cmd);
- printf(" \n");
+ printf(" 3.14) %s arl aging [active:0|1] [time:1~65536] - set switch arl aging timeout value\n", cmd);
+ printf(" 3.15) %s macctl fc [enable|disable] - set switch mac global flow control,enable is 1, disable is 0\n", cmd);
+ printf("\n");
/* 4. mib counter operations */
printf("4) mt753x switch mib counter operations============================================================================================================>>>>\n");
- printf(" 4.1) %s esw_cnt get -get switch mib counters \n", cmd);
- printf(" 4.2) %s esw_cnt clear -clear switch mib counters \n", cmd);
- printf(" 4.3) %s output_queue_cnt get -get switch output queue counters \n", cmd);
- printf(" 4.4) %s free_page get -get switch system free page counters \n", cmd);
- printf(" \n");
+ printf(" 4.1) %s esw_cnt get -get switch mib counters\n", cmd);
+ printf(" 4.2) %s esw_cnt clear -clear switch mib counters\n", cmd);
+ printf(" 4.3) %s output_queue_cnt get -get switch output queue counters\n", cmd);
+ printf(" 4.4) %s free_page get -get switch system free page counters\n", cmd);
+ printf("\n");
/* 5. acl function operations */
printf("5) mt753x switch acl function operations============================================================================================================>>>>\n");
- printf(" 5.1) %s acl enable [port] [port_enable:0|1] - set switch acl function enabled, port is 0~6,enable is 1, disable is 0 \n", cmd);
- printf(" 5.2) %s acl etype add [ethtype] [portmap] - drop L2 ethertype packets \n", cmd);
- printf(" 5.3) %s acl dmac add [mac] [portmap] - drop L2 dest-Mac packets \n", cmd);
- printf(" 5.4) %s acl dip add [dip] [portmap] - drop dip packets \n", cmd);
+ printf(" 5.1) %s acl enable [port] [port_enable:0|1] - set switch acl function enabled, port is 0~6,enable is 1, disable is 0\n", cmd);
+ printf(" 5.2) %s acl etype add [ethtype] [portmap] - drop L2 ethertype packets\n", cmd);
+ printf(" 5.3) %s acl dmac add [mac] [portmap] - drop L2 dest-Mac packets\n", cmd);
+ printf(" 5.4) %s acl dip add [dip] [portmap] - drop dip packets\n", cmd);
printf(" 5.5) %s acl port add [sport] [portmap] - drop L4 UDP/TCP source port packets\n", cmd);
printf(" 5.6) %s acl L4 add [2byes] [portmap] - drop L4 packets with 2bytes payload\n", cmd);
- printf(" 5.7) %s acl acltbl-add [tbl_idx:0~63/255] [vawd1] [vawd2] - set switch acl table new entry, max index-7530:63,7531:255 \n", cmd);
- printf(" 5.8) %s acl masktbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl mask table new entry, max index-7530:31,7531:127 \n", cmd);
- printf(" 5.9) %s acl ruletbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl rule table new entry, max index-7530:31,7531:127 \n", cmd);
- printf(" 5.10) %s acl ratetbl-add [tbl_idx:0~31] [vawd1] [vawd2] - set switch acl rate table new entry \n", cmd);
- printf(" 5.11) %s acl dip meter [dip] [portmap][meter:kbps] - rate limit dip packets \n", cmd);
- printf(" 5.12) %s acl dip trtcm [dip] [portmap][CIR:kbps][CBS][PIR][PBS]- TrTCM dip packets \n", cmd);
- printf(" 5.13) %s acl dip modup [dip] [portmap][usr_pri] - modify usr priority from ACL \n", cmd);
- printf(" 5.14) %s acl dip pppoe [dip] [portmap] - pppoe header removal \n", cmd);
- printf(" \n");
+ printf(" 5.7) %s acl acltbl-add [tbl_idx:0~63/255] [vawd1] [vawd2] - set switch acl table new entry, max index-7530:63,7531:255\n", cmd);
+ printf(" 5.8) %s acl masktbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl mask table new entry, max index-7530:31,7531:127\n", cmd);
+ printf(" 5.9) %s acl ruletbl-add [tbl_idx:0~31/127] [vawd1] [vawd2] - set switch acl rule table new entry, max index-7530:31,7531:127\n", cmd);
+ printf(" 5.10) %s acl ratetbl-add [tbl_idx:0~31] [vawd1] [vawd2] - set switch acl rate table new entry\n", cmd);
+ printf(" 5.11) %s acl dip meter [dip] [portmap][meter:kbps] - rate limit dip packets\n", cmd);
+ printf(" 5.12) %s acl dip trtcm [dip] [portmap][CIR:kbps][CBS][PIR][PBS]- TrTCM dip packets\n", cmd);
+ printf(" 5.13) %s acl dip modup [dip] [portmap][usr_pri] - modify usr priority from ACL\n", cmd);
+ printf(" 5.14) %s acl dip pppoe [dip] [portmap] - pppoe header removal\n", cmd);
+ printf("\n");
/* 6. dip table operations */
printf("6) mt753x switch dip table operations=================================================================================================================>>>>\n");
@@ -101,7 +105,7 @@
printf(" 6.2) %s dip clear - clear switch dip table\n", cmd);
printf(" 6.3) %s dip add [dip] [portmap] - add a dip entry to switch table\n", cmd);
printf(" 6.4) %s dip del [dip] - del a dip entry to switch table\n", cmd);
- printf(" \n");
+ printf("\n");
/* 7. sip table operations */
printf("7) mt753x switch sip table operations=================================================================================================================>>>>\n");
@@ -109,36 +113,36 @@
printf(" 7.2) %s sip clear - clear switch sip table\n", cmd);
printf(" 7.3) %s sip add [sip] [dip] [portmap] - add a sip entry to switch table\n", cmd);
printf(" 7.4) %s sip del [sip] [dip] - del a sip entry to switch table\n", cmd);
- printf(" \n");
+ printf("\n");
/* 8. vlan table operations */
printf("8) mt753x switch sip table operations====================================================================================================================>>>>\n");
printf(" 8.1) %s vlan dump (egtag) - dump switch vlan table (with per port eg_tag setting)\n", cmd);
printf(" 8.2) %s vlan set [fid:0~7] [vid] [portmap] - set vlan id and associated member at switch vlan table\n", cmd);
- printf(" ([stag:0~4095] [eg_con:0|1] [egtagPortMap 0:untagged 2:tagged]) \n");
+ printf(" ([stag:0~4095] [eg_con:0|1] [egtagPortMap 0:untagged 2:tagged])\n");
printf(" Full Example: %s vlan set 0 3 10000100 0 0 20000200\n", cmd);
- printf(" 8.3) %s vlan vid [vlan idx] [active:0|1] [vid] [portMap] - set switch vlan vid elements \n", cmd);
- printf(" [egtagPortMap] [ivl_en] [fid] [stag] \n");
- printf(" 8.4) %s vlan pvid [port] [pvid] - set switch vlan pvid \n", cmd);
- printf(" 8.5) %s vlan acc-frm [port] [acceptable_frame_type:0~3] - set switch vlan acceptable_frame type : admit all frames: 0, \n", cmd);
- printf(" admit only vlan-taged frames: 1,admit only untagged or priority-tagged frames: 2, reserved:3 \n");
- printf(" 8.6) %s vlan port-attr [port] [attr:0~3] - set switch vlan port attribute: user port: 0, statck port: 1, \n", cmd);
- printf(" translation port: 2, transparent port:3 \n");
- printf(" 8.7) %s vlan port-mode [port] [mode:0~3] - set switch vlan port mode : port matrix mode: 0, fallback mode: 1, \n", cmd);
- printf(" check mode: 2, security mode:3 \n");
- printf(" 8.8) %s vlan eg-tag-pvc [port] [eg_tag:0~7] - set switch vlan eg tag pvc : disable: 0, consistent: 1, reserved: 2, \n", cmd);
- printf(" reserved:3,untagged:4,swap:5,tagged:6, stack:7 \n");
- printf(" 8.9) %s vlan eg-tag-pcr [port] [eg_tag:0~3] - set switch vlan eg tag pcr : untagged: 0, swap: 1, tagged: 2, stack:3 \n", cmd);
- printf(" \n");
+ printf(" 8.3) %s vlan vid [vlan idx] [active:0|1] [vid] [portMap] - set switch vlan vid elements\n", cmd);
+ printf(" [egtagPortMap] [ivl_en] [fid] [stag]\n");
+ printf(" 8.4) %s vlan pvid [port] [pvid] - set switch vlan pvid\n", cmd);
+ printf(" 8.5) %s vlan acc-frm [port] [acceptable_frame_type:0~3] - set switch vlan acceptable_frame type : admit all frames: 0,\n", cmd);
+ printf(" admit only vlan-taged frames: 1,admit only untagged or priority-tagged frames: 2, reserved:3\n");
+ printf(" 8.6) %s vlan port-attr [port] [attr:0~3] - set switch vlan port attribute: user port: 0, statck port: 1,\n", cmd);
+ printf(" translation port: 2, transparent port:3\n");
+ printf(" 8.7) %s vlan port-mode [port] [mode:0~3] - set switch vlan port mode : port matrix mode: 0, fallback mode: 1,\n", cmd);
+ printf(" check mode: 2, security mode:3\n");
+ printf(" 8.8) %s vlan eg-tag-pvc [port] [eg_tag:0~7] - set switch vlan eg tag pvc : disable: 0, consistent: 1, reserved: 2,\n", cmd);
+ printf(" reserved:3,untagged:4,swap:5,tagged:6, stack:7\n");
+ printf(" 8.9) %s vlan eg-tag-pcr [port] [eg_tag:0~3] - set switch vlan eg tag pcr : untagged: 0, swap: 1, tagged: 2, stack:3\n", cmd);
+ printf("\n");
/* 9. rate limit operations */
printf("9) mt753x switch rate limit operations=================================================================================================================>>>>\n");
- printf(" 9.1) %s ratectl [in_ex_gress:0|1] [port] [rate] - set switch port ingress(1) or egress(0) rate \n", cmd);
- printf(" 9.2) %s ingress-rate on [port] [Kbps] - set ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
- printf(" 9.3) %s egress-rate on [port] [Kbps] - set egress rate limit on port n (n= 0~ switch max port) \n", cmd);
- printf(" 9.4) %s ingress-rate off [port] - disable ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
+ printf(" 9.1) %s ratectl [in_ex_gress:0|1] [port] [rate] - set switch port ingress(1) or egress(0) rate\n", cmd);
+ printf(" 9.2) %s ingress-rate on [port] [Kbps] - set ingress rate limit on port n (n= 0~ switch max port)\n", cmd);
+ printf(" 9.3) %s egress-rate on [port] [Kbps] - set egress rate limit on port n (n= 0~ switch max port)\n", cmd);
+ printf(" 9.4) %s ingress-rate off [port] - disable ingress rate limit on port n (n= 0~ switch max port)\n", cmd);
printf(" 9.5) %s egress-rate off [port] - disable egress rate limit on port n (n= 0~ switch max port)\n", cmd);
- printf(" \n");
+ printf("\n");
/* 10. igmp operations */
printf("10) mt753x igmp operations===============================================================================================================================>>>>\n");
@@ -147,37 +151,37 @@
printf(" 10.2) %s igmpsnoop off - turn off IGMP snoop and router port learning\n", cmd);
printf(" 10.3) %s igmpsnoop enable [port#] - enable IGMP HW leave/join/Squery/Gquery\n", cmd);
printf(" 10.4) %s igmpsnoop disable [port#] - disable IGMP HW leave/join/Squery/Gquery\n", cmd);
- printf(" \n");
+ printf("\n");
/* 11. QoS operations */
printf("11) mt753x QoS operations================================================================================================================================>>>>\n");
- printf(" 11.1) %s qos sch [port:0~6] [queue:0~7] [shaper:min|max] [type:rr:0|sp:1|wfq:2] - set switch qos sch type\n", cmd);
- printf(" 11.2) %s qos base [port:0~6] [base] - set switch qos base(UPW); port-based:0, tag-based:1, \n", cmd);
- printf(" dscp-based:2, acl-based:3, arl-based:4, stag-based:5 \n");
- printf(" 11.3) %s qos port-weight [port:0~6] [q0] [q1][q2][q3] - set switch qos port queue weight; \n", cmd);
- printf(" [q4][q5][q6][q7] [qn]: the weight of queue n, range: 1~16 \n");
- printf(" 11.4) %s qos port-prio [port:0~6] [prio:0~7] - set switch port qos user priority; port is 0~6, priority is 0~7 \n", cmd);
- printf(" 11.5) %s qos dscp-prio [dscp:0~63] [prio:0~7] - set switch qos dscp user priority; dscp is 0~63, priority is 0~7 \n", cmd);
- printf(" 11.6) %s qos prio-qmap [port:0~6] [prio:0~7] [queue:0~7] - set switch qos priority queue map; priority is 0~7,queue is 0~7 \n", cmd);
- printf(" \n");
+ printf(" 11.1) %s qos sch [port:0~6] [queue:0~7] [shaper:min|max] [type:rr:0|sp:1|wfq:2] - set switch qos sch type\n", cmd);
+ printf(" 11.2) %s qos base [port:0~6] [base] - set switch qos base(UPW); port-based:0, tag-based:1,\n", cmd);
+ printf(" dscp-based:2, acl-based:3, arl-based:4, stag-based:5\n");
+ printf(" 11.3) %s qos port-weight [port:0~6] [q0] [q1][q2][q3] - set switch qos port queue weight;\n", cmd);
+ printf(" [q4][q5][q6][q7] [qn]: the weight of queue n, range: 1~16\n");
+ printf(" 11.4) %s qos port-prio [port:0~6] [prio:0~7] - set switch port qos user priority; port is 0~6, priority is 0~7\n", cmd);
+ printf(" 11.5) %s qos dscp-prio [dscp:0~63] [prio:0~7] - set switch qos dscp user priority; dscp is 0~63, priority is 0~7\n", cmd);
+ printf(" 11.6) %s qos prio-qmap [port:0~6] [prio:0~7] [queue:0~7] - set switch qos priority queue map; priority is 0~7,queue is 0~7\n", cmd);
+ printf("\n");
/*12. port mirror operations*/
printf(" 12) mt753x port mirror operations========================================================================================================================>>>>\n");
printf(" 12.1) %s mirror monitor [port] - enable port mirror and indicate monitor port number\n", cmd);
printf(" 12.2) %s mirror target [port] - set port mirror target\n", cmd);
- printf(" [direction| 0:off, 1:rx, 2:tx, 3:all] \n");
- printf(" 12.3) %s mirror enable [mirror_en:0|1] [mirror_port: 0-6] - set switch mirror function enable(1) or disabled(0) for port 0~6 \n", cmd);
+ printf(" [direction| 0:off, 1:rx, 2:tx, 3:all]\n");
+ printf(" 12.3) %s mirror enable [mirror_en:0|1] [mirror_port: 0-6] - set switch mirror function enable(1) or disabled(0) for port 0~6\n", cmd);
printf(" 12.4) %s mirror port-based [port] [port_tx_mir:0|1] - set switch mirror port: target tx/rx/acl/vlan/igmp\n", cmd);
- printf(" [port_rx_mir:0|1] [acl_mir:0|1] \n");
- printf(" [vlan_mis:0|1] [igmp_mir:0|1] \n");
- printf(" \n");
+ printf(" [port_rx_mir:0|1] [acl_mir:0|1]\n");
+ printf(" [vlan_mis:0|1] [igmp_mir:0|1]\n");
+ printf("\n");
/*13. stp function*/
printf(" 13) mt753x stp operations===============================================================================================================================>>>>\n");
- printf(" 13.1) %s stp [port] [fid] [state] - set switch spanning tree state, port is 0~6, fid is 0~7, \n", cmd);
- printf(" state is 0~3(Disable/Discarding:0,Blocking/Listening/Discarding:1,) \n");
- printf(" Learning:2,Forwarding:3 \n");
- printf(" \n");
+ printf(" 13.1) %s stp [port] [fid] [state] - set switch spanning tree state, port is 0~6, fid is 0~7,\n", cmd);
+ printf(" state is 0~3(Disable/Discarding:0,Blocking/Listening/Discarding:1,)\n");
+ printf(" Learning:2,Forwarding:3\n");
+ printf("\n");
/*14. collision pool operations*/
printf("14) mt753x collision pool operations========================================================================================================================>>>>\n");
@@ -185,20 +189,235 @@
printf(" 14.2) %s collision-pool mac dump - dump collision pool mac table\n", cmd);
printf(" 14.3) %s collision-pool dip dump - dump collision pool dip table\n", cmd);
printf(" 14.4) %s collision-pool sip dump - dump collision pool sip table\n", cmd);
- printf(" \n");
+ printf("\n");
/*15. pfc(priority flow control) operations*/
printf("15) mt753x pfc(priority flow control) operations==============================================================================================================>>>>\n");
- printf(" 15.1) %s pfc enable [port] [enable 0|1] - enable or disable port's pfc \n", cmd);
- printf(" 15.2) %s pfc rx_counter [port] - get port n pfc 8 up rx counter \n", cmd);
- printf(" 15.3) %s pfc tx_counter [port] - get port n pfc 8 up rx counter \n", cmd);
- printf(" \n");
+ printf(" 15.1) %s pfc enable [port] [enable 0|1] - enable or disable port's pfc\n", cmd);
+ printf(" 15.2) %s pfc rx_counter [port] - get port n pfc 8 up rx counter\n", cmd);
+ printf(" 15.3) %s pfc tx_counter [port] - get port n pfc 8 up rx counter\n", cmd);
+ printf("\n");
/*15. pfc(priority flow control) operations*/
printf("16) mt753x EEE(802.3az) operations==============================================================================================================>>>>\n");
printf(" 16.1) %s eee enable [enable 0|1] ([portMap]) - enable or disable EEE (by portMap)\n", cmd);
printf(" 16.2) %s eee dump ([port]) - dump EEE capability (by port)\n", cmd);
- printf(" \n");
+ printf("\n");
+
+ if (chip_name == 0x8855) {
+ printf("switch an8855 <sub cmd> supported commands===================================================================================================================>>>>\n");
+ printf("\n");
+ printf("Register/GPHY access commands===============================================================================================================>>>>\n");
+ printf("reg r <reg(4'hex)>\n");
+ printf("reg w <reg(4'hex)> <value(8'hex)>\n");
+ printf("phy cl22 r <port(0..4)> <reg(2'hex)>\n");
+ printf("phy cl22 w <port(0..4)> <reg(2'hex)> <value(4'hex)>\n");
+ printf("phy cl45 r <port(0..4)> <dev(2'hex)> <reg(3'hex)>\n");
+ printf("phy cl45 w <port(0..4)> <dev(2'hex)> <reg(3'hex)> <value(4'hex)>\n");
+ printf("\n");
+ printf("Port configuration commands=================================================================================================================>>>>\n");
+ printf("port set matrix <port(0..6)> <matrix(6:0)>\n");
+ printf("port get matrix <port(0..6)>\n");
+ printf("port set vlanMode <port(0..6)> <vlanMode(0:matrix,1:fallback,2:check,3:security)>\n");
+ printf("port get vlanMode <port(0..6)>\n");
+ printf("port set flowCtrl <port(0..6)> <dir(0:Tx,1:Rx)> <fc_en(1:En,0:Dis)>\n");
+ printf("port get flowCtrl <port(0..6)> <dir(0:Tx,1:Rx)>\n");
+ printf("port set jumbo <pkt_len(0:1518,1:1536,2:1552,3:max)> <frame_len(2..15)>\n");
+ printf("port get jumbo\n");
+ printf("port set anMode <port(0..4)> <en(0:force,1:AN)>\n");
+ printf("port get anMode <port(0..4)>\n");
+ printf("port set localAdv <port(0..4)> <10H(1:En,0:Dis)> <10F(1:En,0:Dis)> <100H(1:En,0:Dis)> <100F(1:En,0:Dis)> <1000F(1:En,0:Dis)> <pause(1:En,0:Dis)>\n");
+ printf("port get localAdv <port(0..4)>\n");
+ printf("port get remoteAdv <port(0..4)>\n");
+ printf("port set speed <port(0..4)> <speed(0:10M,1:100M,2:1G,3:2.5G)>\n");
+ printf("port get speed <port(0..4)>\n");
+ printf("port set duplex <port(0..4)> <duplex(0:half,1:full)>\n");
+ printf("port get duplex <port(0..4)>\n");
+ printf("port get status <port(0..4)>\n");
+ printf("port set bckPres <port(0..6)> <bckPres(1:En,0:Dis)>\n");
+ printf("port get bckPres <port(0..6)>\n");
+ printf("port set psMode <port(0..4)> <ls(1:En,0:Dis)> <eee(1:En,0:Dis)>\n");
+ printf("port get psMode <port(0..4)>\n");
+ printf("port set smtSpdDwn <port(0..4)> <en(1:En,0:Dis)> <retry(2..5)>\n");
+ printf("port get smtSpdDwn <port(0..4)>\n");
+ printf("port set spTag <port(0..6)> <en(1:En,0:Dis)>\n");
+ printf("port get spTag <port(0..6)>\n");
+ printf("port set enable <port(0..4)> <en(1:En,0:Dis)>\n");
+ printf("port get enable <port(0..4)>\n");
+ printf("port set 5GBaseRMode\n");
+ printf("port set hsgmiiMode\n");
+ printf("port set sgmiiMode <mode(0:AN,1:Force)> <speed(0:10M,1:100M,2:1G)>\n");
+ printf("port set rmiiMode <speed(0:10M,1:100M)>\n");
+ printf("port set rgmiiMode <speed(0:10M,1:100M,2:1G)>\n");
+ printf("\n");
+ printf("Special tag commands========================================================================================================================>>>>\n");
+ printf("sptag setEnable port<port(0..6)> enable<1:enable 0:disable>\n");
+ printf("sptag getEnable port<port(0..6)>\n");
+ printf("sptag setmode port<port(0..6)> mode<0:inset 1:replace>\n");
+ printf("sptag getmode port<port(0..6)>\n");
+ printf("sptag encode mode={ insert | replace } opc={ portmap | portid | lookup } dp={bitimap hex} vpm={ untagged | 8100 | 88a8 } pri=<UINT> cfi=<UINT> vid=<UINT>\n");
+ printf("sptag decode <byte(hex)> <byte(hex)> <byte(hex)> <byte(hex)>\n");
+ printf("\n");
+ printf("Vlan commands===============================================================================================================================>>>>\n");
+ printf("sptag set fid <vid(0..4095)> <fid(0..7)>\n");
+ printf("sptag set memPort <vid(0..4095)> <bitmap(6:0)>\n");
+ printf("sptag set ivl <vid(0..4095)> <(1:En,0:Dis)>\n");
+ printf("sptag set portBaseStag <vid(0..4095)> <(1:En,0:Dis)>\n");
+ printf("sptag set stag <vid(0..4095)> <stag(0..4095)>\n");
+ printf("sptag set egsTagCtlEn <vid(0..4095)> <(1:En,0:Dis)>\n");
+ printf("sptag set egsTagCtlCon <vid(0..4095)> <(1:En,0:Dis)>\n");
+ printf("sptag set egsTagCtl <vid(0..4095)> <port(0..6)> <ctlType(0:untag,2:tagged)>\n");
+ printf("sptag set portActFrame <port(0..6)> <frameType(0:all,1:tagged,2:untagged)>\n");
+ printf("sptag get portActFrame <port(0..6)>\n");
+ printf("sptag set LeakyVlanEn <port(0..6)> <pktType(0:uc,1:mc,2:bc,3:ipmc)> <(1:En,0:Dis)>\n");
+ printf("sptag get leakyVlanEn <port(0..6)>\n");
+ printf("sptag set portVlanAttr <port(0..6)> <vlanAttr(0:user,1:stack,2:translation,3:transparent)>\n");
+ printf("sptag get portVlanAttr <port(0..6)>\n");
+ printf("sptag set igsPortETagAttr <port(0..6)> <egsTagAttr(0:disable,1:consistent,4:untagged,5:swap,6:tagged,7:stack)>\n");
+ printf("sptag get igsPortETagAttr <port(0..6)>\n");
+ printf("sptag set portEgsTagAttr <port(0..6)> <egsTagAttr(0:untagged,1:swap,2:tagged,3:stack)>\n");
+ printf("sptag get portEgsTagAttr <port(0..6)>\n");
+ printf("sptag set portOuterTPID <port(0..6)> <TPID(hex)>\n");
+ printf("sptag get portOuterTPID <port(0..6)>\n");
+ printf("sptag set pvid <port(0..6)> <vid(0..4095)>\n");
+ printf("sptag get pvid <port(0..6)>\n");
+ printf("sptag initiate <vid(0..4095)> <fid(0..7)> <bitmap(6:0)> <ivl(1:En,0:Dis)> <portbasestag(1:En,0:Dis)> <stag(0..4095)> <egstagctlen(1:En,0:Dis)> <egstagcon(1:En,0:Dis)> <taggedbitmap(6:0)>\n");
+ printf("sptag create <vid(0..4095)>\n");
+ printf("sptag destroy [ <vid(0..4095)> | <vidRange(vid0-vid1)> ]\n");
+ printf("sptag destroyAll [ <restoreDefVlan(0:false,1:true)> | ]\n");
+ printf("sptag dump [ <vid(0..4095)> | <vidRange(vid0-vid1)> | ]\n");
+ printf("sptag addPortMem <vid(0..4095)> <port(0..6)>\n");
+ printf("sptag addPortMem <vid(0..4095)> <port(0..6)>\n");
+ printf("\n");
+ printf("Layer2 commands=============================================================================================================================>>>>\n");
+ printf("l2 dump mac\n");
+ printf("l2 add mac <static(0:dynamic,1:static)> <unauth(0:auth,1:unauth)> <mac(12'hex)> <portlist(uintlist)> [ vid <vid(0..4095)> | fid <fid(0..15)> ] <src_mac_forward=(0:default,1:cpu-exclude,2:cpu-include,3:cpu-only,4:drop)>\n");
+ printf("l2 del mac <mac(12'hex)> [ vid <vid(0..4095)> | fid <fid(0..15)> ]\n");
+ printf("l2 get mac <mac(12'hex)> [ vid <vid(0..4095)> | fid <fid(0..15)> ]\n");
+ printf("l2 clear mac\n");
+ printf("l2 set macAddrAgeOut <time(1, 1000000)>\n");
+ printf("l2 get macAddrAgeOut\n");
+ printf("\n");
+ printf("Link Aggregation commands===================================================================================================================>>>>\n");
+ printf("lag set member <group_id(0 or 1)> <member_index(0..3)> <enable(0,1)> <port index(0..6)>\n");
+ printf("lag get member group_id(0 or 1)\n");
+ printf("lag set dstInfo <sp(1:En,0:Dis)> <sa(1:En,0:Dis)> <da(1:En,0:Dis)> <sip(1:En,0:Dis)> <dip(1:En,0:Dis)> <sport(1:En,0:Dis)> <dport(1:En,0:Dis)>\n");
+ printf("lag get dstInfo\n");
+ printf("lag set ptseed <hex32>\n");
+ printf("lag get ptseed\n");
+ printf("lag set hashtype <0-crc32lsb;1-crc32msb;2-crc16;3-xor4>\n");
+ printf("lag get hashtype\n");
+ printf("lag set state <state(1:En,0:Dis)>\n");
+ printf("lag get state\n");
+ printf("lag set spsel <soure port enable(1:En,0:Dis)>\n");
+ printf("lag get spsel\n");
+ printf("\n");
+ printf("STP commands================================================================================================================================>>>>\n");
+ printf("stp set portstate <port(0..6)> <fid(0..15)> <state(0:disable,1:listen,2:learn,3:forward)>\n");
+ printf("stp get portstate <port(0..6)> <fid(0..15)>\n");
+ printf("\n");
+ printf("Mirror commands=============================================================================================================================>>>>\n");
+ printf("mirror set session <sid(0,1)> <dst_port(UINT)> <state(1:En,0:Dis)> <tag(1:on, 0:off)> <list(UINTLIST)> <dir(0:none,1:tx,2:rx,3:both)>\n");
+ printf("mirror set session-enable <sid(0,1)> <state(1:En,0:Dis)>\n");
+ printf("mirror add session-rlist <sid(0,1)> <list(UINTLIST)>\n");
+ printf("mirror add session-tlist <sid(0,1)> <list(UINTLIST)>\n");
+ printf("mirror get session <sid(0,1)>\n");
+ printf("mirror del session <sid(0,1)>\n");
+ printf("\n");
+ printf("MIB commands================================================================================================================================>>>>\n");
+ printf("mib get port <port(0..6)>\n");
+ printf("mib get acl <event(0..7)>\n");
+ printf("mib clear port <port(0..6)>\n");
+ printf("mib clear all\n");
+ printf("mib clear acl\n");
+ printf("\n");
+ printf("QoS commands================================================================================================================================>>>>\n");
+ printf("qos set scheduleAlgo <portlist(UINTLIST)> <queue(UINT)> <scheduler(0:SP,1:WRR,2:WFQ)> <weight(0..128)>, weight 0 is valid only on sp mode\n");
+ printf("qos get scheduleAlgo <portlist(UINTLIST)> <queue(UINT)>\n");
+ printf("qos set trustMode <portlist(UINTLIST)> <mode(0:port,1:1p-port,2:dscp-port,3:dscp-1p-port>\n");
+ printf("qos get trustMode <portlist(UINTLIST)>\n");
+ printf("qos set pri2Queue <priority(0..7)> <queue(0..7)>\n");
+ printf("qos get pri2Queue\n");
+ printf("qos set dscp2Pri <dscp(0..63)> <priority(0..7)>\n");
+ printf("qos get dscp2Pri <dscp(0..63)>\n");
+ printf("qos set rateLimitEnable <portlist(UINTLIST)> <dir(0:egress,1:ingress)> <rate_en(1:En,0:Dis)>\n");
+ printf("qos get rateLimitEnable <portlist(UINTLIST)>\n");
+ printf("qos set rateLimit <portlist(UINTLIST)> <I_CIR(0..80000)> <I_CBS(0..127)> <E_CIR(0..80000)> <E_CBS(0..127)>\n");
+ printf("qos get rateLimit <portlist(UINTLIST)>\n");
+ printf("qos set portPriority <portlist(UINTLIST)> <priority(0..7)>\n");
+ printf("qos get portPriority <portlist(UINTLIST)>\n");
+ printf("qos set rateLmtExMngFrm <dir(0:egress)> <en(0:include,1:exclude)>\n");
+ printf("qos get rateLmtExMngFrm\n");
+ printf("\n");
+ printf("Diag commands===============================================================================================================================>>>>\n");
+ printf("diag set txComply <phy(0..4)> <mode(0..8)>\n");
+ printf("diag get txComply <phy(0..4)>\n");
+ printf("\n");
+ printf("LED commands================================================================================================================================>>>>\n");
+ printf("led set mode <mode(0:disable, 1..3:2 LED, 4:user-define)>\n");
+ printf("led get mode\n");
+ printf("led set state <led(0..1)> <state(1:En,0:Dis)>\n");
+ printf("led get state <led(0..1)>\n");
+ printf("led set usr <led(0..1)> <polarity(0:low, 1:high)> <on_evt(7'bin)> <blink_evt(10'bin)>\n");
+ printf("led get usr <led(0..1)>\n");
+ printf("led set time <time(0..5:32ms~1024ms)>\n");
+ printf("led get time\n");
+ printf("\n");
+ printf("Security commands===========================================================================================================================>>>>\n");
+ printf("sec set stormEnable <port(0..6)> <type(0:bcst,1:mcst,2:ucst)> <en(1:En,0:Dis)>\n");
+ printf("sec get stormEnable <port(0..6)> <type(0:bcst,1:mcst,2:ucst)>\n");
+ printf("sec set stormRate <port(0..6)> <type(0:bcst,1:mcst,2:ucst)> <count(0..255)> <unit(0:64k,1:256k,2:1M,3:4M,4:16M)>\n");
+ printf("sec get stormRate <port(0..6)> <type(0:bcst,1:mcst,2:ucst)>\n");
+ printf("sec set fldMode <port(0..6)> <type(0:bcst,1:mcst,2:ucst,3:qury> <en(1:En,0:Dis)>\n");
+ printf("sec get fldMode <port(0..6)> <type(0:bcst,1:mcst,2:ucst,3:qury>\n");
+ printf("sec set saLearning <port(0..6)> <learn(0:disable,1:enable)>\n");
+ printf("sec get saLearning <port(0..6)>\n");
+ printf("sec set saLimit <port(0..6)> <mode(0:disable,1:enable)> <count(0..4095)>\n");
+ printf("sec get saLimit <port(0..6)>\n");
+ printf("\n");
+ printf("Switch commands=============================================================================================================================>>>>\n");
+ printf("switch set cpuPortEn <cpu_en(1:En,0:Dis)>\n");
+ printf("switch get cpuPortEn\n");
+ printf("switch set cpuPort <port_number>\n");
+ printf("switch get cpuPort\n");
+ printf("switch set phyLCIntrEn <phy(0..6)> <(1:En,0:Dis)>\n");
+ printf("switch get phyLCIntrEn <phy(0..6)>\n");
+ printf("switch set phyLCIntrSts <phy(0..6)> <(1:Clear)>\n");
+ printf("switch get phyLCIntrSts <phy(0..6)>\n");
+ printf("\n");
+ printf("ACL commands================================================================================================================================>>>>\n");
+ printf("acl set en <en(1:En,0:Dis)>\n");
+ printf("acl get en\n");
+ printf("acl set rule <idx(0..127)>\n <state(0:Dis,1:En)> <reverse(0:Dis,1:En)> <end(0:Dis,1:En)>\n <portmap(7'bin)><ipv6(0:Dis,1:En,2:Not care)>\n[ dmac <dmac(12'hex)> <dmac_mask(12'hex)> ]\n[ smac <smac(12'hex)> <smac_mask(12'hex)> ]\n[ stag <stag(4'hex)> <stag_mask(4'hex)> ]\n[ ctag <ctag(4'hex)> <ctag_mask(4'hex)> ]\n[ etype <etype(4'hex)> <etype_mask(4'hex)> ]\n[ dip <dip(IPADDR)> <dip_mask(IPADDR)> ]\n[ sip <sip(IPADDR)> <sip_mask(IPADDR)> ]\n[ dscp <dscp(2'hex)> <dscp_mask(2'hex)> ]\n[ protocol <protocol(12'hex)> <protocol_mask(12'hex)> ]\n[ dport <dport(4'hex)> <dport_mask(4'hex)> ]\n[ sport <sport(4'hex)> <sport_mask(4'hex)> ]\n[ flow_label <flow_label(4'hex)> <flow_label_mask(4'hex)> ]\n[ udf <udf(4'hex)> <udf_mask(4'hex)> ] ");
+ printf("acl get rule <idx(0..127)> ");
+ printf("acl del rule <idx(0..127)>\n");
+ printf("acl clear rule\n");
+ printf("acl set udfRule <idx(0..15)> <mode(0:pattern, 1:threshold)> [ <pat(4'hex)> <mask(4'hex)> | <low(4'hex)> <high(4'hex)> ] <start(0:MAC header, 1:L2 payload, 2:IPv4 header, 3:IPv6 header, 4:L3 payload, 5:TCP header, 6:UDP header, 7: L4 payload)> <offset(0..127,unit:2 bytes)> <portmap(7'bin)>\n");
+ printf("acl get udfRule <idx(0..15)>\n");
+ printf("acl del udfRule <idx(0..15)>\n");
+ printf("acl clear udfRule\n");
+ printf("acl set action <idx(0..127)>\n[ forward <forward(0:Default,4:Exclude CPU,5:Include CPU,6:CPU only,7:Drop)> ]\n[ egtag <egtag(0:Default,1:Consistent,4:Untag,5:Swap,6:Tag,7:Stack)> ]\n[ mirrormap <mirrormap(2'bin)> ]\n[ priority <priority(0..7)> ]\n[ redirect <redirect(0:Dst,1:Vlan)> <portmap(7'bin)> ]\n[ leaky_vlan <leaky_vlan(1:En,0:Dis)> ]\n[ cnt_idx <cnt_idx(0..63)> ]\n[ rate_idx <rate_idx(0..31)> ]\n[ attack_idx <attack_idx(0..95)> ]\n[ vid <vid(0..4095)> ]\n[ manage <manage(1:En,0:Dis)> ]\n[ bpdu <bpdu(1:En,0:Dis)> ]\n[ class <class(0:Original,1:Defined)>[0..7] ]\n[ drop_pcd <drop_pcd(0:Original,1:Defined)> [red <red(0..7)>][yellow <yellow(0..7)>][green <green(0..7)>] ]\n[ color <color(0:Defined,1:Trtcm)> [ <defined_color(0:Dis,1:Green,2:Yellow,3:Red)> | <trtcm_idx(0..31)> ] ]");
+ printf("acl get action <idx(0..127)>\n");
+ printf("acl del action <idx(0..127)>\n");
+ printf("acl clear action\n");
+ printf("acl set trtcm <idx(1..31)> <cir(4'hex)> <pir(4'hex)> <cbs(4'hex)> <pbs(4'hex)>\n");
+ printf("acl get trtcm <idx(1..31)>\n");
+ printf("acl del trtcm <idx(0..31)>\n");
+ printf("acl clear trtcm\n");
+ printf("acl set trtcmEn <en(1:En,0:Dis)>\n");
+ printf("acl get trtcmEn\n");
+ printf("acl set portEn <port(0..6)> <en(1:En,0:Dis)>\n");
+ printf("acl get portEn <port(0..6)>\n");
+ printf("acl set dropEn <port(0..6)> <en(1:En,0:Dis)>\n");
+ printf("acl get dropEn <port(0..6)>\n");
+ printf("acl set dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <high(0..2047)> <low(0..2047)>\n");
+ printf("acl get dropThrsh <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)>\n");
+ printf("acl set dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)> <probability(0..1023)>\n");
+ printf("acl get dropPbb <port(0..6)> <color(0:green,1:yellow,2:red)> <queue(0..7)>\n");
+ printf("acl set meter <idx(0..31)> <en(1:En,0:Dis)> <rate(0..65535)>\n Note: Limit rate = rate * 64Kbps");
+ printf("acl get meter <idx(0..31)>\n");
+ printf("\n");
+ }
exit_free();
exit(0);
@@ -227,7 +446,8 @@
for (i = 0; i < 16; i++) {
printf("0x%08x: ", off + 0x10 * i);
for (j = 0; j < 4; j++) {
- reg_read(off + i * 0x10 + j * 0x4, &val);
+ reg_read(off + i * 0x10 + j * 0x4,
+ &val);
printf(" 0x%08x", val);
}
printf("\n");
@@ -240,41 +460,48 @@
static int get_chip_name()
{
- int temp;
+ int temp = 0, rc = 0;
FILE *fp = NULL;
char buff[255];
- /*judge 7530*/
+ /*judge jaguar embedded switch */
+ fp = fopen("/proc/device-tree/compatible", "r");
+ if (fp != NULL) {
+ temp = -1;
+ if (fgets(buff, 255, (FILE *) fp) && strstr(buff, "mt7988"))
+ temp = 0x7988;
+
+ rc = fclose(fp);
+ if (rc == 0 && temp == 0x7988)
+ return temp;
+ }
+
+ /*judge 7530 */
reg_read((0x7ffc), &temp);
temp = temp >> 16;
if (temp == 0x7530)
return temp;
- /*judge 7531*/
+
+ /*judge 7531 */
reg_read(0x781c, &temp);
temp = temp >> 16;
if (temp == 0x7531)
return temp;
- /*judge jaguar embedded switch*/
- fp = fopen("/proc/device-tree/compatible", "r");
- if (fp != NULL) {
- temp = -1;
- if (fgets(buff, 255, (FILE *)fp) && strstr(buff, "mt7988"))
- temp = 0x7988;
-
- fclose(fp);
+ /*judge an8855 */
+ reg_read(0x10005000, &temp);
+ if (temp == 0x8855)
return temp;
- }
return -1;
}
static int phy_operate(int argc, char *argv[])
{
- unsigned int port_num;
- unsigned int dev_num;
- unsigned int value, cl_value;
- unsigned int reg;
+ unsigned int port_num = 0;
+ unsigned int dev_num = 0;
+ unsigned int value = 0, cl_value = 0;
+ unsigned int reg = 0;
int ret = 0, cl_ret = 0;
char op;
@@ -283,65 +510,125 @@
op = argv[3][0];
- switch(op) {
- case 'r':
- reg = strtoul(argv[argc-1], NULL, 0);
- if (argc == 6) {
- port_num = strtoul(argv[argc-2], NULL, 0);
- ret = mii_mgr_read(port_num, reg, &value);
- if (ret < 0)
- printf(" Phy read reg fail\n");
- else
- printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
- } else if (argc == 7) {
- dev_num = strtoul(argv[argc-2], NULL, 0);
- port_num = strtoul(argv[argc-3], NULL, 0);
- ret = mii_mgr_c45_read(port_num, dev_num, reg, &value);
- if (ret < 0)
- printf(" Phy read reg fail\n");
- else
- printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
- } else
- ret = phy_dump(32);
+ switch (op) {
+ case 'r':
+ reg = strtoul(argv[argc - 1], NULL, 16);
+ if (reg >= 0xFFFFFFFF) {
+ printf(" Phy read reg fail\n");
+ ret = -1;
break;
- case 'w':
- reg = strtoul(argv[argc-2], NULL, 0);
- value = strtoul(argv[argc-1], NULL, 0);
- if (argc == 7) {
- port_num = strtoul(argv[argc-3], NULL, 0);
- ret = mii_mgr_write(port_num, reg, value);
- cl_ret = mii_mgr_read(port_num, reg, &cl_value);
- if (cl_ret < 0)
- printf(" Phy read reg fail\n");
- else
- printf(" Phy read reg=0x%x, value=0x%x\n", reg, cl_value);
+ }
+
+ if (argc == 6) {
+ port_num = strtoul(argv[argc - 2], NULL, 0);
+ if (port_num > MAX_PORT) {
+ printf(" Phy read reg fail\n");
+ ret = -1;
+ break;
}
- else if (argc == 8) {
- dev_num = strtoul(argv[argc-3], NULL, 0);
- port_num = strtoul(argv[argc-4], NULL, 0);
- ret = mii_mgr_c45_write(port_num, dev_num, reg, value);
- cl_ret = mii_mgr_c45_read(port_num, dev_num, reg, &cl_value);
- if (cl_ret < 0)
- printf(" Phy read reg fail\n");
- else
- printf(" Phy read reg=0x%x, value=0x%x\n", reg, cl_value);
+
+ ret = mii_mgr_read(port_num, reg, &value);
+ if (ret < 0)
+ printf(" Phy read reg fail\n");
+ else
+ printf(" Phy read reg=0x%x, value=0x%x\n",
+ reg, value);
+ } else if (argc == 7) {
+ dev_num = strtoul(argv[argc - 2], NULL, 16);
+ if (dev_num > 0xFFFFFFFF) {
+ printf(" Phy read reg fail\n");
+ ret = -1;
+ break;
}
+
+ port_num = strtoul(argv[argc - 3], NULL, 0);
+ if (port_num > MAX_PORT) {
+ printf(" Phy read reg fail\n");
+ ret = -1;
+ break;
+ }
+
+ ret = mii_mgr_c45_read(port_num, dev_num, reg,
+ &value);
+ if (ret < 0)
+ printf(" Phy read reg fail\n");
else
- usage(argv[0]);
+ printf(" Phy read dev_num=0x%x, reg=0x%x, value=0x%x\n",
+ dev_num, reg, value);
+ } else
+ ret = phy_dump(32);
+ break;
+ case 'w':
+ reg = strtoul(argv[argc - 2], NULL, 16);
+ if (reg >= 0xFFFFFFFF) {
+ printf(" Phy write reg fail\n");
+ ret = -1;
break;
- default:
+ }
+
+ value = strtoul(argv[argc - 1], NULL, 16);
+ if (value > 0xFFFF) {
+ printf(" Phy write reg fail\n");
+ ret = -1;
break;
+ }
+
+ if (argc == 7) {
+ port_num = strtoul(argv[argc - 3], NULL, 0);
+ if (port_num > MAX_PORT) {
+ printf(" Phy write reg fail\n");
+ ret = -1;
+ break;
+ }
+
+ ret = mii_mgr_write(port_num, reg, value);
+ cl_ret = mii_mgr_read(port_num, reg, &cl_value);
+ if (cl_ret < 0)
+ printf(" Phy write reg fail\n");
+ else
+ printf(" Phy write reg=0x%x, value=0x%x\n",
+ reg, cl_value);
+ } else if (argc == 8) {
+ dev_num = strtoul(argv[argc - 3], NULL, 16);
+ if (dev_num > 0xFFFFFFFF) {
+ printf(" Phy write reg fail\n");
+ ret = -1;
+ break;
+ }
+
+ port_num = strtoul(argv[argc - 4], NULL, 0);
+ if (port_num > MAX_PORT) {
+ printf(" Phy write reg fail\n");
+ ret = -1;
+ break;
+ }
+
+ ret = mii_mgr_c45_write(port_num, dev_num, reg, value);
+ cl_ret = mii_mgr_c45_read(port_num, dev_num, reg,
+ &cl_value);
+ if (cl_ret < 0)
+ printf(" Phy write reg fail\n");
+ else
+ printf(" Phy write dev_num=0x%x reg=0x%x, value=0x%x\n",
+ dev_num, reg, cl_value);
+ }
+ break;
+ default:
+ break;
}
return ret;
}
-
int main(int argc, char *argv[])
{
int err;
attres = (struct mt753x_attr *)malloc(sizeof(struct mt753x_attr));
+ if (attres == NULL) {
+ printf("Failed to allocate memory.\n");
+ exit(0);
+ }
attres->dev_id = -1;
attres->port_num = -1;
attres->phy_dev = -1;
@@ -357,30 +644,96 @@
if (!err)
chip_name = get_chip_name();
}
-
+
+ if (err < 0) {
+ err = mt753x_netlink_init(AN8855_DSA_GENL_NAME);
+ if (!err)
+ chip_name = get_chip_name();
+ }
+
+ if (err < 0) {
+ err = mt753x_netlink_init(AN8855_GENL_NAME);
+ if (!err)
+ chip_name = get_chip_name();
+ }
+
if (err < 0) {
err = switch_ioctl_init();
if (!err) {
nl_init_flag = false;
chip_name = get_chip_name();
if (chip_name < 0) {
- printf("no chip unsupport or chip id is invalid!\n");
+ printf
+ ("no chip unsupport or chip id is invalid!\n");
exit_free();
exit(0);
}
}
}
+#ifndef COMPAT_MODE
+ if (chip_name == 0x8855) {
+ AIR_INIT_PARAM_T init_param = { 0 };
+
+ init_param.printf = printf;
+ init_param.malloc = malloc;
+ init_param.free = free;
+ init_param.udelay = usleep;
+ init_param.dev_access.read_callback = an8855_reg_read;
+ init_param.dev_access.write_callback = an8855_reg_write;
+ init_param.dev_access.phy_read_callback = an8855_phy_cl22_read;
+ init_param.dev_access.phy_write_callback =
+ an8855_phy_cl22_write;
+ init_param.dev_access.phy_cl45_read_callback =
+ an8855_phy_cl45_read;
+ init_param.dev_access.phy_cl45_write_callback =
+ an8855_phy_cl45_write;
+
+ air_init(0, &init_param);
+ air_parse_cmd((argc - 1), &argv[1]);
+ }
+ exit_free();
+ return 0;
+#else
if (argc < 2)
usage(argv[0]);
+ if (chip_name == 0x8855) {
+ AIR_INIT_PARAM_T init_param = { 0 };
+
+ init_param.printf = printf;
+ init_param.malloc = malloc;
+ init_param.free = free;
+ init_param.udelay = usleep;
+ init_param.dev_access.read_callback = an8855_reg_read;
+ init_param.dev_access.write_callback = an8855_reg_write;
+ init_param.dev_access.phy_read_callback = an8855_phy_cl22_read;
+ init_param.dev_access.phy_write_callback =
+ an8855_phy_cl22_write;
+ init_param.dev_access.phy_cl45_read_callback =
+ an8855_phy_cl45_read;
+ init_param.dev_access.phy_cl45_write_callback =
+ an8855_phy_cl45_write;
+ air_init(0, &init_param);
+
+ p_switch_func = &an8855_switch_func;
+ } else {
+ p_switch_func = &mt753x_switch_func;
+ }
+
+ if ((argc > 2) && !strcmp(argv[1], "an8855")
+ && (chip_name == 0x8855)) {
+ air_parse_cmd((argc - 2), (const char **)&argv[2]);
+ exit_free();
+ return 0;
+ }
+
if (!strcmp(argv[1], "dev")) {
attres->dev_id = strtoul(argv[2], NULL, 0);
argv += 2;
argc -= 2;
if (argc < 2)
usage(argv[0]);
-
}
if (argc == 2) {
@@ -388,60 +741,69 @@
attres->type = MT753X_ATTR_TYPE_MESG;
mt753x_list_swdev(attres, MT753X_CMD_REQUEST);
} else if (!strncmp(argv[1], "dump", 5)) {
- table_dump();
+ p_switch_func->pf_table_dump(argc, argv);
} else if (!strncmp(argv[1], "clear", 6)) {
- table_clear();
+ p_switch_func->pf_table_clear(argc, argv);
printf("done.\n");
} else if (!strncmp(argv[1], "reset", 5)) {
- switch_reset(argc, argv);
+ p_switch_func->pf_switch_reset(argc, argv);
} else if (!strncmp(argv[1], "phy", 4)) {
- phy_dump(32); //dump all phy register
+ phy_dump(32); //dump all phy register
} else if (!strncmp(argv[1], "sysctl", 7)) {
- if (nl_init_flag)
- printf("netlink(%s)\n",MT753X_GENL_NAME);
- else
- printf("ioctl(%s)\n",ETH_DEVNAME);
+ if (nl_init_flag) {
+ if (chip_name == 0x8855)
+ printf("netlink(%s)\n",
+ AN8855_GENL_NAME);
+ else
+ printf("netlink(%s)\n",
+ MT753X_GENL_NAME);
+ } else
+ printf("ioctl(%s)\n", ETH_DEVNAME);
+ } else if (!strncmp(argv[1], "ver", 4)) {
+ if (chip_name == 0x8855)
+ printf("Switch APP version: %s\r\n",
+ SWITCH_APP_VERSION);
} else
usage(argv[0]);
} else if (!strncmp(argv[1], "arl", 4)) {
if (!strncmp(argv[2], "aging", 6))
- doArlAging(argc, argv);
+ p_switch_func->pf_doArlAging(argc, argv);
} else if (!strncmp(argv[1], "esw_cnt", 8)) {
if (!strncmp(argv[2], "get", 4))
- read_mib_counters();
+ p_switch_func->pf_read_mib_counters(argc, argv);
else if (!strncmp(argv[2], "clear", 6))
- clear_mib_counters();
+ p_switch_func->pf_clear_mib_counters(argc, argv);
else
usage(argv[0]);
- }else if (!strncmp(argv[1], "output_queue_cnt", 17)) {
+ } else if (!strncmp(argv[1], "output_queue_cnt", 17)) {
if (!strncmp(argv[2], "get", 4))
- read_output_queue_counters();
+ p_switch_func->pf_read_output_queue_counters(argc,
+ argv);
else
usage(argv[0]);
- }else if (!strncmp(argv[1], "free_page", 10)) {
+ } else if (!strncmp(argv[1], "free_page", 10)) {
if (!strncmp(argv[2], "get", 4))
- read_free_page_counters();
+ p_switch_func->pf_read_free_page_counters(argc, argv);
else
usage(argv[0]);
- }
- else if (!strncmp(argv[1], "ratectl", 8))
- rate_control(argc, argv);
+ } else if (!strncmp(argv[1], "ratectl", 8))
+ p_switch_func->pf_rate_control(argc, argv);
else if (!strncmp(argv[1], "add", 4))
- table_add(argc, argv);
+ p_switch_func->pf_table_add(argc, argv);
else if (!strncmp(argv[1], "filt", 5))
- table_add(argc, argv);
+ p_switch_func->pf_table_add(argc, argv);
else if (!strncmp(argv[1], "del", 4)) {
if (!strncmp(argv[4], "fid", 4))
- table_del_fid(argc, argv);
+ p_switch_func->pf_table_del_fid(argc, argv);
else if (!strncmp(argv[4], "vid", 4))
- table_del_vid(argc, argv);
+ p_switch_func->pf_table_del_vid(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "search", 7)) {
if (!strncmp(argv[4], "fid", 4))
- table_search_mac_fid(argc, argv);
+ p_switch_func->pf_table_search_mac_fid(argc, argv);
else if (!strncmp(argv[4], "vid", 4))
- table_search_mac_vid(argc, argv);
+ p_switch_func->pf_table_search_mac_vid(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "phy", 4)) {
@@ -466,70 +828,70 @@
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "fc", 3))
- global_set_mac_fc(argc, argv);
+ p_switch_func->pf_global_set_mac_fc(argc, argv);
else if (!strncmp(argv[2], "pfc", 4))
- set_mac_pfc(argc, argv);
+ p_switch_func->pf_set_mac_pfc(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "qos", 4)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "sch", 4))
- qos_sch_select(argc, argv);
+ p_switch_func->pf_qos_sch_select(argc, argv);
else if (!strncmp(argv[2], "base", 5))
- qos_set_base(argc, argv);
+ p_switch_func->pf_qos_set_base(argc, argv);
else if (!strncmp(argv[2], "port-weight", 12))
- qos_wfq_set_weight(argc, argv);
+ p_switch_func->pf_qos_wfq_set_weight(argc, argv);
else if (!strncmp(argv[2], "port-prio", 10))
- qos_set_portpri(argc, argv);
+ p_switch_func->pf_qos_set_portpri(argc, argv);
else if (!strncmp(argv[2], "dscp-prio", 10))
- qos_set_dscppri(argc, argv);
+ p_switch_func->pf_qos_set_dscppri(argc, argv);
else if (!strncmp(argv[2], "prio-qmap", 10))
- qos_pri_mapping_queue(argc, argv);
+ p_switch_func->pf_qos_pri_mapping_queue(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "stp", 3)) {
if (argc < 3)
usage(argv[0]);
else
- doStp(argc, argv);
+ p_switch_func->pf_doStp(argc, argv);
} else if (!strncmp(argv[1], "sip", 5)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "dump", 5))
- sip_dump();
+ p_switch_func->pf_sip_dump(argc, argv);
else if (!strncmp(argv[2], "add", 4))
- sip_add(argc, argv);
+ p_switch_func->pf_sip_add(argc, argv);
else if (!strncmp(argv[2], "del", 4))
- sip_del(argc, argv);
+ p_switch_func->pf_sip_del(argc, argv);
else if (!strncmp(argv[2], "clear", 6))
- sip_clear();
+ p_switch_func->pf_sip_clear(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "dip", 4)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "dump", 5))
- dip_dump();
+ p_switch_func->pf_dip_dump(argc, argv);
else if (!strncmp(argv[2], "add", 4))
- dip_add(argc, argv);
+ p_switch_func->pf_dip_add(argc, argv);
else if (!strncmp(argv[2], "del", 4))
- dip_del(argc, argv);
+ p_switch_func->pf_dip_del(argc, argv);
else if (!strncmp(argv[2], "clear", 6))
- dip_clear();
+ p_switch_func->pf_dip_clear(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "mirror", 7)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "monitor", 8))
- set_mirror_to(argc, argv);
+ p_switch_func->pf_set_mirror_to(argc, argv);
else if (!strncmp(argv[2], "target", 7))
- set_mirror_from(argc, argv);
+ p_switch_func->pf_set_mirror_from(argc, argv);
else if (!strncmp(argv[2], "enable", 7))
- doMirrorEn(argc, argv);
+ p_switch_func->pf_doMirrorEn(argc, argv);
else if (!strncmp(argv[2], "port-based", 11))
- doMirrorPortBased(argc, argv);
+ p_switch_func->pf_doMirrorPortBased(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "acl", 4)) {
@@ -537,152 +899,127 @@
usage(argv[0]);
if (!strncmp(argv[2], "dip", 4)) {
if (!strncmp(argv[3], "add", 4))
- acl_dip_add(argc, argv);
+ p_switch_func->pf_acl_dip_add(argc, argv);
else if (!strncmp(argv[3], "modup", 6))
- acl_dip_modify(argc, argv);
+ p_switch_func->pf_acl_dip_modify(argc, argv);
else if (!strncmp(argv[3], "pppoe", 6))
- acl_dip_pppoe(argc, argv);
+ p_switch_func->pf_acl_dip_pppoe(argc, argv);
else if (!strncmp(argv[3], "trtcm", 4))
- acl_dip_trtcm(argc, argv);
+ p_switch_func->pf_acl_dip_trtcm(argc, argv);
else if (!strncmp(argv[3], "meter", 6))
- acl_dip_meter(argc, argv);
+ p_switch_func->pf_acl_dip_meter(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[2], "dmac", 6)) {
if (!strncmp(argv[3], "add", 4))
- acl_mac_add(argc, argv);
+ p_switch_func->pf_acl_mac_add(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[2], "etype", 6)) {
if (!strncmp(argv[3], "add", 4))
- acl_ethertype(argc, argv);
+ p_switch_func->pf_acl_ethertype(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[2], "port", 5)) {
if (!strncmp(argv[3], "add", 4))
- acl_sp_add(argc, argv);
+ p_switch_func->pf_acl_sp_add(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[2], "L4", 5)) {
if (!strncmp(argv[3], "add", 4))
- acl_l4_add(argc, argv);
+ p_switch_func->pf_acl_l4_add(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[2], "enable", 7))
- acl_port_enable(argc, argv);
+ p_switch_func->pf_acl_port_enable(argc, argv);
else if (!strncmp(argv[2], "acltbl-add", 11))
- acl_table_add(argc, argv);
+ p_switch_func->pf_acl_table_add(argc, argv);
else if (!strncmp(argv[2], "masktbl-add", 12))
- acl_mask_table_add(argc, argv);
+ p_switch_func->pf_acl_mask_table_add(argc, argv);
else if (!strncmp(argv[2], "ruletbl-add", 12))
- acl_rule_table_add(argc, argv);
+ p_switch_func->pf_acl_rule_table_add(argc, argv);
else if (!strncmp(argv[2], "ratetbl-add", 12))
- acl_rate_table_add(argc, argv);
+ p_switch_func->pf_acl_rate_table_add(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "vlan", 5)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "dump", 5))
- vlan_dump(argc, argv);
+ p_switch_func->pf_vlan_dump(argc, argv);
else if (!strncmp(argv[2], "set", 4))
- vlan_set(argc, argv);
+ p_switch_func->pf_vlan_set(argc, argv);
else if (!strncmp(argv[2], "clear", 6))
- vlan_clear(argc, argv);
+ p_switch_func->pf_vlan_clear(argc, argv);
else if (!strncmp(argv[2], "vid", 4))
- doVlanSetVid(argc, argv);
+ p_switch_func->pf_doVlanSetVid(argc, argv);
else if (!strncmp(argv[2], "pvid", 5))
- doVlanSetPvid(argc, argv);
+ p_switch_func->pf_doVlanSetPvid(argc, argv);
else if (!strncmp(argv[2], "acc-frm", 8))
- doVlanSetAccFrm(argc, argv);
+ p_switch_func->pf_doVlanSetAccFrm(argc, argv);
else if (!strncmp(argv[2], "port-attr", 10))
- doVlanSetPortAttr(argc, argv);
+ p_switch_func->pf_doVlanSetPortAttr(argc, argv);
else if (!strncmp(argv[2], "port-mode", 10))
- doVlanSetPortMode(argc, argv);
+ p_switch_func->pf_doVlanSetPortMode(argc, argv);
else if (!strncmp(argv[2], "eg-tag-pcr", 11))
- doVlanSetEgressTagPCR(argc, argv);
+ p_switch_func->pf_doVlanSetEgressTagPCR(argc, argv);
else if (!strncmp(argv[2], "eg-tag-pvc", 11))
- doVlanSetEgressTagPVC(argc, argv);
+ p_switch_func->pf_doVlanSetEgressTagPVC(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "reg", 4)) {
parse_reg_cmd(argc, argv, 4);
} else if (!strncmp(argv[1], "ingress-rate", 6)) {
- int port = 0, bw = 0;
- if (argv[2][1] == 'n') {
- port = strtoul(argv[3], NULL, 0);
- bw = strtoul(argv[4], NULL, 0);
- if (ingress_rate_set(1, port, bw) == 0)
- printf("switch port=%d, bw=%d\n", port, bw);
- }
- else if (argv[2][1] == 'f') {
- if (argc != 4)
- usage(argv[0]);
- port = strtoul(argv[3], NULL, 0);
- if (ingress_rate_set(0, port, bw) == 0)
- printf("switch port=%d ingress rate limit off\n", port);
- } else
- usage(argv[0]);
+ p_switch_func->pf_igress_rate_set(argc, argv);
} else if (!strncmp(argv[1], "egress-rate", 6)) {
- int port = 0, bw = 0;
- if (argv[2][1] == 'n') {
- port = strtoul(argv[3], NULL, 0);
- bw = strtoul(argv[4], NULL, 0);
- if (egress_rate_set(1, port, bw) == 0)
- printf("switch port=%d, bw=%d\n", port, bw);
- } else if (argv[2][1] == 'f') {
- if (argc != 4)
- usage(argv[0]);
- port = strtoul(argv[3], NULL, 0);
- if (egress_rate_set(0, port, bw) == 0)
- printf("switch port=%d egress rate limit off\n", port);
- } else
- usage(argv[0]);
+ p_switch_func->pf_egress_rate_set(argc, argv);
} else if (!strncmp(argv[1], "igmpsnoop", 10)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "on", 3))
- igmp_on(argc, argv);
+ p_switch_func->pf_igmp_on(argc, argv);
else if (!strncmp(argv[2], "off", 4))
- igmp_off();
+ p_switch_func->pf_igmp_off(argc, argv);
else if (!strncmp(argv[2], "enable", 7))
- igmp_enable(argc, argv);
+ p_switch_func->pf_igmp_enable(argc, argv);
else if (!strncmp(argv[2], "disable", 8))
- igmp_disable(argc, argv);
+ p_switch_func->pf_igmp_disable(argc, argv);
else
usage(argv[0]);
} else if (!strncmp(argv[1], "collision-pool", 15)) {
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "enable", 7))
- collision_pool_enable(argc, argv);
- else if (!strncmp(argv[2], "mac", 4)){
+ p_switch_func->pf_collision_pool_enable(argc, argv);
+ else if (!strncmp(argv[2], "mac", 4)) {
if (!strncmp(argv[3], "dump", 5))
- collision_pool_mac_dump();
+ p_switch_func->pf_collision_pool_mac_dump(argc,
+ argv);
else
usage(argv[0]);
- } else if (!strncmp(argv[2], "dip", 4)){
+ } else if (!strncmp(argv[2], "dip", 4)) {
if (!strncmp(argv[3], "dump", 5))
- collision_pool_dip_dump();
+ p_switch_func->pf_collision_pool_dip_dump(argc,
+ argv);
else
usage(argv[0]);
- } else if (!strncmp(argv[2], "sip", 4)){
+ } else if (!strncmp(argv[2], "sip", 4)) {
if (!strncmp(argv[3], "dump", 5))
- collision_pool_sip_dump();
+ p_switch_func->pf_collision_pool_sip_dump(argc,
+ argv);
else
usage(argv[0]);
- }
- else
+ } else
usage(argv[0]);
- } else if (!strncmp(argv[1], "pfc", 15)) {
+ } else if (!strncmp(argv[1], "pfc", 15)) {
if (argc < 4 || argc > 5)
usage(argv[0]);
if (!strncmp(argv[2], "enable", 7))
- set_mac_pfc(argc, argv);
- else if (!strncmp(argv[2], "rx_counter", 11)){
- pfc_get_rx_counter(argc, argv);
- } else if (!strncmp(argv[2], "tx_counter", 11)){
- pfc_get_tx_counter(argc, argv);
+ p_switch_func->pf_set_mac_pfc(argc, argv);
+ else if (!strncmp(argv[2], "rx_counter", 11)) {
+ p_switch_func->pf_pfc_get_rx_counter(argc, argv);
+ } else if (!strncmp(argv[2], "tx_counter", 11)) {
+ p_switch_func->pf_pfc_get_tx_counter(argc, argv);
} else
usage(argv[0]);
} else if (!strncmp(argv[1], "crossover", 10)) {
@@ -694,10 +1031,10 @@
if (argc < 3)
usage(argv[0]);
if (!strncmp(argv[2], "enable", 7) ||
- !strncmp(argv[2], "disable", 8))
- eee_enable(argc, argv);
+ !strncmp(argv[2], "disable", 8))
+ p_switch_func->pf_eee_enable(argc, argv);
else if (!strncmp(argv[2], "dump", 5))
- eee_dump(argc, argv);
+ p_switch_func->pf_eee_dump(argc, argv);
else
usage(argv[0]);
} else
@@ -705,4 +1042,5 @@
exit_free();
return 0;
+#endif
}
diff --git a/recipes-devtools/switch/files/src/switch_fun.c b/recipes-devtools/switch/files/src/switch_fun.c
index 8ee9675..9e9f4fe 100644
--- a/recipes-devtools/switch/files/src/switch_fun.c
+++ b/recipes-devtools/switch/files/src/switch_fun.c
@@ -19,6 +19,82 @@
#define leaky_bucket 0
+struct switch_func_s mt753x_switch_func = {
+ .pf_table_dump = table_dump,
+ .pf_table_clear = table_clear,
+ .pf_switch_reset = switch_reset,
+ .pf_doArlAging = doArlAging,
+ .pf_read_mib_counters = read_mib_counters,
+ .pf_clear_mib_counters = clear_mib_counters,
+ .pf_read_output_queue_counters = read_output_queue_counters,
+ .pf_read_free_page_counters = read_free_page_counters,
+ .pf_rate_control = rate_control,
+ .pf_igress_rate_set = ingress_rate_set,
+ .pf_egress_rate_set = egress_rate_set,
+ .pf_table_add = table_add,
+ .pf_table_del_fid = table_del_fid,
+ .pf_table_del_vid = table_del_vid,
+ .pf_table_search_mac_fid = table_search_mac_fid,
+ .pf_table_search_mac_vid = table_search_mac_vid,
+ .pf_global_set_mac_fc = global_set_mac_fc,
+ .pf_set_mac_pfc = set_mac_pfc,
+ .pf_qos_sch_select = qos_sch_select,
+ .pf_qos_set_base = qos_set_base,
+ .pf_qos_wfq_set_weight = qos_wfq_set_weight,
+ .pf_qos_set_portpri = qos_set_portpri,
+ .pf_qos_set_dscppri = qos_set_dscppri,
+ .pf_qos_pri_mapping_queue = qos_pri_mapping_queue,
+ .pf_doStp = doStp,
+ .pf_sip_dump = sip_dump,
+ .pf_sip_add = sip_add,
+ .pf_sip_del = sip_del,
+ .pf_sip_clear = sip_clear,
+ .pf_dip_dump = dip_dump,
+ .pf_dip_add = dip_add,
+ .pf_dip_del = dip_del,
+ .pf_dip_clear = dip_clear,
+ .pf_set_mirror_to = set_mirror_to,
+ .pf_set_mirror_from = set_mirror_from,
+ .pf_doMirrorEn = doMirrorEn,
+ .pf_doMirrorPortBased = doMirrorPortBased,
+ .pf_acl_dip_add = acl_dip_add,
+ .pf_acl_dip_modify = acl_dip_modify,
+ .pf_acl_dip_pppoe = acl_dip_pppoe,
+ .pf_acl_dip_trtcm = acl_dip_trtcm,
+ .pf_acl_dip_meter = acl_dip_meter,
+ .pf_acl_mac_add = acl_mac_add,
+ .pf_acl_ethertype = acl_ethertype,
+ .pf_acl_sp_add = acl_sp_add,
+ .pf_acl_l4_add = acl_l4_add,
+ .pf_acl_port_enable = acl_port_enable,
+ .pf_acl_table_add = acl_table_add,
+ .pf_acl_mask_table_add = acl_mask_table_add,
+ .pf_acl_rule_table_add = acl_rule_table_add,
+ .pf_acl_rate_table_add = acl_rate_table_add,
+ .pf_vlan_dump = vlan_dump,
+ .pf_vlan_set = vlan_set,
+ .pf_vlan_clear = vlan_clear,
+ .pf_doVlanSetVid = doVlanSetVid,
+ .pf_doVlanSetPvid = doVlanSetPvid,
+ .pf_doVlanSetAccFrm = doVlanSetAccFrm,
+ .pf_doVlanSetPortAttr = doVlanSetPortAttr,
+ .pf_doVlanSetPortMode = doVlanSetPortMode,
+ .pf_doVlanSetEgressTagPCR = doVlanSetEgressTagPCR,
+ .pf_doVlanSetEgressTagPVC = doVlanSetEgressTagPVC,
+ .pf_igmp_on = igmp_on,
+ .pf_igmp_off = igmp_off,
+ .pf_igmp_enable = igmp_enable,
+ .pf_igmp_disable = igmp_disable,
+ .pf_collision_pool_enable = collision_pool_enable,
+ .pf_collision_pool_mac_dump = collision_pool_mac_dump,
+ .pf_collision_pool_dip_dump = collision_pool_dip_dump,
+ .pf_collision_pool_sip_dump = collision_pool_sip_dump,
+ .pf_pfc_get_rx_counter = pfc_get_rx_counter,
+ .pf_pfc_get_tx_counter = pfc_get_tx_counter,
+ .pf_eee_enable = eee_enable,
+ .pf_eee_dump = eee_dump,
+};
+
static int getnext(char *src, int separator, char *dest)
{
char *c;
@@ -66,7 +142,7 @@
c[1] = *(ptr + 1);
c[2] = *(ptr + 2);
c[3] = *(ptr + 3);
- /*sprintf(str, "%d.%d.%d.%d", c[0], c[1], c[2], c[3]);*/
+ /*sprintf(str, "%d.%d.%d.%d", c[0], c[1], c[2], c[3]); */
sprintf(str, "%d.%d.%d.%d", c[3], c[2], c[1], c[0]);
}
@@ -153,7 +229,8 @@
return 0;
}
-int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int *value)
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg,
+ unsigned int *value)
{
int ret;
@@ -176,7 +253,8 @@
return 0;
}
-int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value)
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg,
+ unsigned int value)
{
int ret;
@@ -199,7 +277,6 @@
return 0;
}
-
int phy_dump(int phy_addr)
{
int ret;
@@ -221,7 +298,7 @@
void phy_crossover(int argc, char *argv[])
{
unsigned int port_num = strtoul(argv[2], NULL, 10);
- unsigned int value;
+ unsigned int value = 0;
int ret;
if (port_num > 4) {
@@ -230,9 +307,13 @@
}
if (nl_init_flag == true)
- ret = phy_cl45_read_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+ ret =
+ phy_cl45_read_netlink(attres, port_num, 0x1E,
+ MT7530_T10_TEST_CONTROL, &value);
else
- ret = mii_mgr_cl45_read_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+ ret =
+ mii_mgr_cl45_read_ioctl(port_num, 0x1E,
+ MT7530_T10_TEST_CONTROL, &value);
if (ret < 0) {
printf("phy_cl45 read fail\n");
exit_free();
@@ -240,10 +321,10 @@
}
printf("mii_mgr_cl45:");
- printf("Read: port#=%d, device=0x%x, reg=0x%x, value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+ printf("Read: port#=%d, device=0x%x, reg=0x%x, value=0x%x\n", port_num,
+ 0x1E, MT7530_T10_TEST_CONTROL, value);
- if (!strncmp(argv[3], "auto", 5))
- {
+ if (!strncmp(argv[3], "auto", 5)) {
value &= (~(0x3 << 3));
} else if (!strncmp(argv[3], "mdi", 4)) {
value &= (~(0x3 << 3));
@@ -254,12 +335,17 @@
printf("invaild parameter\n");
return;
}
- printf("Write: port#=%d, device=0x%x, reg=0x%x. value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+ printf("Write: port#=%d, device=0x%x, reg=0x%x. value=0x%x\n", port_num,
+ 0x1E, MT7530_T10_TEST_CONTROL, value);
if (nl_init_flag == true)
- ret = phy_cl45_write_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+ ret =
+ phy_cl45_write_netlink(attres, port_num, 0x1E,
+ MT7530_T10_TEST_CONTROL, value);
else
- ret = mii_mgr_cl45_write_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+ ret =
+ mii_mgr_cl45_write_ioctl(port_num, 0x1E,
+ MT7530_T10_TEST_CONTROL, value);
if (ret < 0) {
printf("phy_cl45 write fail\n");
@@ -282,7 +368,7 @@
if (argv[2][0] == 'r') {
if (argc != 7)
return -1;
- mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+ mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
port_num = strtoul(argv[3], NULL, 0);
if (port_num > MAX_PORT) {
printf("Illegal port index and port:0~6\n");
@@ -291,16 +377,21 @@
ch_addr = strtoul(argv[4], NULL, 0);
node_addr = strtoul(argv[5], NULL, 0);
data_addr = strtoul(argv[6], NULL, 0);
- printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
- tr_reg_control = (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
- mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
+ printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n",
+ port_num, ch_addr, node_addr, data_addr);
+ tr_reg_control =
+ (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) |
+ (data_addr << 1);
+ mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
mii_mgr_read(port_num, 17, &val_l);
mii_mgr_read(port_num, 18, &val_h);
- printf("switch trreg read tr_reg_control=%x, value_H=%x, value_L=%x\n", tr_reg_control, val_h, val_l);
+ printf
+ ("switch trreg read tr_reg_control=%x, value_H=%x, value_L=%x\n",
+ tr_reg_control, val_h, val_l);
} else if (argv[2][0] == 'w') {
if (argc != 9)
return -1;
- mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+ mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
port_num = strtoul(argv[3], NULL, 0);
if (port_num > MAX_PORT) {
printf("\n**Illegal port index and port:0~6\n");
@@ -311,20 +402,26 @@
data_addr = strtoul(argv[6], NULL, 0);
val_h = strtoul(argv[7], NULL, 0);
val_l = strtoul(argv[8], NULL, 0);
- printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
- tr_reg_control = (1 << 15) | (0 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
+ printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n",
+ port_num, ch_addr, node_addr, data_addr);
+ tr_reg_control =
+ (1 << 15) | (0 << 13) | (ch_addr << 11) | (node_addr << 7) |
+ (data_addr << 1);
mii_mgr_write(port_num, 17, val_l);
mii_mgr_write(port_num, 18, val_h);
- mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
- printf("switch trreg Write tr_reg_control=%x, value_H=%x, value_L=%x\n", tr_reg_control, val_h, val_l);
+ mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
+ printf
+ ("switch trreg Write tr_reg_control=%x, value_H=%x, value_L=%x\n",
+ tr_reg_control, val_h, val_l);
} else
return -1;
return 0;
}
-void write_acl_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+void write_acl_table(unsigned char tbl_idx, unsigned int vawd1,
+ unsigned int vawd2)
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
unsigned int max_index;
if (chip_name == 0x7531 || chip_name == 0x7988)
@@ -340,8 +437,7 @@
}
reg = REG_VTCR_ADDR;
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0) {
break;
@@ -356,8 +452,7 @@
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -366,8 +461,8 @@
void acl_table_add(int argc, char *argv[])
{
- unsigned int vawd1, vawd2;
- unsigned char tbl_idx;
+ unsigned int vawd1 = 0, vawd2 = 0;
+ unsigned char tbl_idx = 0;
tbl_idx = atoi(argv[3]);
vawd1 = strtoul(argv[4], (char **)NULL, 16);
@@ -375,10 +470,11 @@
write_acl_table(tbl_idx, vawd1, vawd2);
}
-void write_acl_mask_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+void write_acl_mask_table(unsigned char tbl_idx, unsigned int vawd1,
+ unsigned int vawd2)
{
- unsigned int value, reg;
- unsigned int max_index;
+ unsigned int value = 0, reg = 0;
+ unsigned int max_index = 0;
if (chip_name == 0x7531 || chip_name == 0x7988)
max_index = 128;
@@ -392,8 +488,7 @@
return;
}
reg = REG_VTCR_ADDR;
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -406,8 +501,7 @@
value = REG_VTCR_BUSY_MASK | (0x09 << REG_VTCR_FUNC_OFFT) | tbl_idx;
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -416,8 +510,8 @@
void acl_mask_table_add(int argc, char *argv[])
{
- unsigned int vawd1, vawd2;
- unsigned char tbl_idx;
+ unsigned int vawd1 = 0, vawd2 = 0;
+ unsigned char tbl_idx = 0;
tbl_idx = atoi(argv[3]);
vawd1 = strtoul(argv[4], (char **)NULL, 16);
@@ -425,10 +519,11 @@
write_acl_mask_table(tbl_idx, vawd1, vawd2);
}
-void write_acl_rule_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+void write_acl_rule_table(unsigned char tbl_idx, unsigned int vawd1,
+ unsigned int vawd2)
{
- unsigned int value, reg;
- unsigned int max_index;
+ unsigned int value = 0, reg = 0;
+ unsigned int max_index = 0;
if (chip_name == 0x7531 || chip_name == 0x7988)
max_index = 128;
@@ -437,14 +532,13 @@
printf("Rule_control_tbl_idx:%d\n", tbl_idx);
- if (tbl_idx >= max_index) { /*Check the input parameters is right or not.*/
+ if (tbl_idx >= max_index) { /* Check the input parameters is right or not. */
printf(HELP_ACL_RULE_TBL_ADD);
return;
}
reg = REG_VTCR_ADDR;
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0) {
break;
@@ -459,8 +553,7 @@
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- while (1)
- { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0) {
break;
@@ -470,8 +563,8 @@
void acl_rule_table_add(int argc, char *argv[])
{
- unsigned int vawd1, vawd2;
- unsigned char tbl_idx;
+ unsigned int vawd1 = 0, vawd2 = 0;
+ unsigned char tbl_idx = 0;
tbl_idx = atoi(argv[3]);
vawd1 = strtoul(argv[4], (char **)NULL, 16);
@@ -479,9 +572,10 @@
write_acl_rule_table(tbl_idx, vawd1, vawd2);
}
-void write_rate_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+void write_rate_table(unsigned char tbl_idx, unsigned int vawd1,
+ unsigned int vawd2)
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
unsigned int max_index = 32;
printf("Rule_action_tbl_idx:%d\n", tbl_idx);
@@ -492,7 +586,7 @@
}
reg = REG_VTCR_ADDR;
- while (1) { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -507,7 +601,7 @@
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- while (1) { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -516,8 +610,8 @@
void acl_rate_table_add(int argc, char *argv[])
{
- unsigned int vawd1, vawd2;
- unsigned char tbl_idx;
+ unsigned int vawd1 = 0, vawd2 = 0;
+ unsigned char tbl_idx = 0;
tbl_idx = atoi(argv[3]);
vawd1 = strtoul(argv[4], (char **)NULL, 16);
@@ -526,9 +620,10 @@
write_rate_table(tbl_idx, vawd1, vawd2);
}
-void write_trTCM_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+void write_trTCM_table(unsigned char tbl_idx, unsigned int vawd1,
+ unsigned int vawd2)
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
unsigned int max_index = 32;
printf("trTCM_tbl_idx:%d\n", tbl_idx);
@@ -539,7 +634,7 @@
}
reg = REG_VTCR_ADDR;
- while (1) { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
@@ -554,16 +649,17 @@
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- while (1) { // wait until not busy
+ while (1) { // wait until not busy
reg_read(reg, &value);
if ((value & REG_VTCR_BUSY_MASK) == 0)
break;
}
}
-int acl_parameters_pre_del(int len1, int len2, int argc, char *argv[], int *port)
+int acl_parameters_pre_del(int len1, int len2, int argc, char *argv[],
+ int *port)
{
- int i;
+ int i = 0;
*port = 0;
if (argc < len1) {
@@ -571,10 +667,11 @@
return -1;
}
- if (len2 == 12)
- {
+ if (len2 == 12) {
if (!argv[4] || strlen(argv[4]) != len2) {
- printf("The [%s] format error, should be of length %d\n",argv[4], len2);
+ printf
+ ("The [%s] format error, should be of length %d\n",
+ argv[4], len2);
return -1;
}
}
@@ -586,7 +683,8 @@
for (i = 0; i < 7; i++) {
if (argv[5][i] != '0' && argv[5][i] != '1') {
- printf("portmap format error, should be of combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
return -1;
}
*port += (argv[5][i] - '0') * (1 << i);
@@ -594,31 +692,32 @@
return 0;
}
-void acl_compare_pattern(int ports, int comparion, int base, int word, unsigned char table_index)
+void acl_compare_pattern(int ports, int comparion, int base, int word,
+ unsigned char table_index)
{
- unsigned int value;
+ unsigned int value = 0;
- comparion |= 0xffff0000; //compare mask
+ comparion |= 0xffff0000; //compare mask
- value = ports << 8; //w_port_map
- value |= 0x1 << 19; //enable
- value |= base << 16; //mac header
- value |= word << 1; //word offset
+ value = ports << 8; //w_port_map
+ value |= 0x1 << 19; //enable
+ value |= base << 16; //mac header
+ value |= word << 1; //word offset
write_acl_table(table_index, comparion, value);
}
void acl_mac_add(int argc, char *argv[])
{
- unsigned int value;
- int ports;
+ unsigned int value = 0;
+ int ports = 0;
char tmpstr[5];
int ret;
ret = acl_parameters_pre_del(6, 12, argc, argv, &ports);
if (ret < 0)
return;
- //set pattern
+ /* Set pattern */
strncpy(tmpstr, argv[4], 4);
tmpstr[4] = '\0';
value = strtoul(tmpstr, NULL, 16);
@@ -635,20 +734,20 @@
acl_compare_pattern(ports, value, 0x0, 2, 2);
//set mask
- write_acl_mask_table(0,0x7,0);
+ write_acl_mask_table(0, 0x7, 0);
//set action
- value = 0x7; //drop
- value |= 1 << 28; //acl intterupt enable
- value |= 1 << 27; //acl hit count
- value |= 2 << 24; //acl hit count group index (0~3)
- write_acl_rule_table(0,value,0);
+ value = 0x7; //drop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 2 << 24; //acl hit count group index (0~3)
+ write_acl_rule_table(0, value, 0);
}
void acl_dip_meter(int argc, char *argv[])
{
- unsigned int value, ip_value, meter;
- int ports;
+ unsigned int value = 0, ip_value = 0, meter = 0;
+ int ports = 0;
int ret;
ip_value = 0;
@@ -666,31 +765,31 @@
acl_compare_pattern(ports, value, 0x2, 0x9, 1);
//set mask
- write_acl_mask_table(0,0x3,0);
+ write_acl_mask_table(0, 0x3, 0);
//set action
meter = strtoul(argv[6], NULL, 0);
if (((chip_name == 0x7530) && (meter > 1000000)) ||
- ((chip_name == 0x7531) && (meter > 2500000)) ||
- ((chip_name == 0x7988) && (meter > 4000000))) {
+ ((chip_name == 0x7531) && (meter > 2500000)) ||
+ ((chip_name == 0x7988) && (meter > 4000000))) {
printf("\n**Illegal meter input, and 7530: 0~1000000Kpbs, 7531: 0~2500000Kpbs, 7988: 0~4000000Kpbs**\n");
return;
}
if (((chip_name == 0x7531 || chip_name == 0x7988) && (meter > 1000000))) {
- reg_read(0xc,&value);
+ reg_read(0xc, &value);
value |= 0x1 << 30;
- reg_write(0xC,value);
- printf("AGC: 0x%x\n",value);
- value = meter / 1000; //uint is 1Mbps
+ reg_write(0xC, value);
+ printf("AGC: 0x%x\n", value);
+ value = meter / 1000; //uint is 1Mbps
} else {
- reg_read(0xc,&value);
+ reg_read(0xc, &value);
value &= ~(0x1 << 30);
- reg_write(0xC,value);
- printf("AGC: 0x%x\n",value);
- value = meter >> 6; //uint is 64Kbps
+ reg_write(0xC, value);
+ printf("AGC: 0x%x\n", value);
+ value = meter >> 6; //uint is 64Kbps
}
- value |= 0x1 << 15; //enable rate control
- printf("Acl rate control:0x%x\n",value);
+ value |= 0x1 << 15; //enable rate control
+ printf("Acl rate control:0x%x\n", value);
write_rate_table(0, value, 0);
}
@@ -721,30 +820,30 @@
PIR = strtoul(argv[8], NULL, 0);
PBS = strtoul(argv[9], NULL, 0);
- if (CIR > 65535*64 || CBS > 65535 || PIR > 65535*64 || PBS > 65535) {
+ if (CIR > 65535 * 64 || CBS > 65535 || PIR > 65535 * 64 || PBS > 65535) {
printf("\n**Illegal input parameters**\n");
return;
}
- value = CBS << 16; //bit16~31
- value |= PBS; //bit0~15
- //value |= 1;//valid
+ value = CBS << 16; //bit16~31
+ value |= PBS; //bit0~15
+ //value |= 1;//valid
CIR = CIR >> 6;
PIR = PIR >> 6;
- value2 = CIR << 16; //bit16~31
- value2 |= PIR; //bit0~15
- write_trTCM_table(0,value,value2);
+ value2 = CIR << 16; //bit16~31
+ value2 |= PIR; //bit0~15
+ write_trTCM_table(0, value, value2);
//set pattern
- write_acl_mask_table(0,0x3,0);
+ write_acl_mask_table(0, 0x3, 0);
//set action
- value = 0x1 << (11 + 1); //TrTCM green meter#0 Low drop
- value |= 0x2 << (8 + 1); //TrTCM yellow meter#0 Med drop
- value |= 0x3 << (5 + 1); //TrTCM red meter#0 Hig drop
- value |= 0x1 << 0; //TrTCM drop pcd select
- write_acl_rule_table(0,0,value);
+ value = 0x1 << (11 + 1); //TrTCM green meter#0 Low drop
+ value |= 0x2 << (8 + 1); //TrTCM yellow meter#0 Med drop
+ value |= 0x3 << (5 + 1); //TrTCM red meter#0 Hig drop
+ value |= 0x1 << 0; //TrTCM drop pcd select
+ write_acl_rule_table(0, 0, value);
}
void acl_ethertype(int argc, char *argv[])
@@ -756,21 +855,21 @@
ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
if (ret < 0)
return;
- printf("ports:0x%x\n",ports);
+ printf("ports:0x%x\n", ports);
ethertype = strtoul(argv[4], NULL, 16);
//set pattern
value = ethertype;
acl_compare_pattern(ports, value, 0x0, 0x6, 0);
//set pattern
- write_acl_mask_table(0,0x1,0);
+ write_acl_mask_table(0, 0x1, 0);
//set action(drop)
- value = 0x7; //default. Nodrop
- value |= 1 << 28; //acl intterupt enable
- value |= 1 << 27; //acl hit count
+ value = 0x7; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
- write_acl_rule_table(0,value,0);
+ write_acl_rule_table(0, value, 0);
}
void acl_dip_modify(int argc, char *argv[])
@@ -801,14 +900,14 @@
acl_compare_pattern(ports, value, 0x2, 0x9, 1);
//set pattern
- write_acl_mask_table(0,0x3,0);
+ write_acl_mask_table(0, 0x3, 0);
//set action
- value = 0x0; //default. Nodrop
- value |= 1 << 28; //acl intterupt enable
- value |= 1 << 27; //acl hit count
- value |= priority << 4; //acl UP
- write_acl_rule_table(0,value,0);
+ value = 0x0; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= priority << 4; //acl UP
+ write_acl_rule_table(0, value, 0);
}
void acl_dip_pppoe(int argc, char *argv[])
@@ -832,16 +931,16 @@
acl_compare_pattern(ports, value, 0x2, 0x9, 1);
//set pattern
- write_acl_mask_table(0,0x3,0);
+ write_acl_mask_table(0, 0x3, 0);
//set action
- value = 0x0; //default. Nodrop
- value |= 1 << 28; //acl intterupt enable
- value |= 1 << 27; //acl hit count
- value |= 1 << 20; //pppoe header remove
- value |= 1 << 21; //SA MAC SWAP
- value |= 1 << 22; //DA MAC SWAP
- write_acl_rule_table(0,value,7);
+ value = 0x0; //default. Nodrop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 1 << 20; //pppoe header remove
+ value |= 1 << 21; //SA MAC SWAP
+ value |= 1 << 22; //DA MAC SWAP
+ write_acl_rule_table(0, value, 7);
}
void acl_dip_add(int argc, char *argv[])
@@ -865,20 +964,20 @@
acl_compare_pattern(ports, value, 0x2, 0x9, 1);
//set pattern
- write_acl_mask_table(0,0x3,0);
+ write_acl_mask_table(0, 0x3, 0);
//set action
//value = 0x0; //default
- value = 0x7; //drop
- value |= 1 << 28; //acl intterupt enable
- value |= 1 << 27; //acl hit count
- value |= 2 << 24; //acl hit count group index (0~3)
- write_acl_rule_table(0,value,0);
+ value = 0x7; //drop
+ value |= 1 << 28; //acl intterupt enable
+ value |= 1 << 27; //acl hit count
+ value |= 2 << 24; //acl hit count group index (0~3)
+ write_acl_rule_table(0, value, 0);
}
void acl_l4_add(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
int ports;
int ret;
@@ -891,16 +990,16 @@
acl_compare_pattern(ports, value, 0x5, 0x0, 0);
//set rue mask
- write_acl_mask_table(0,0x1,0);
+ write_acl_mask_table(0, 0x1, 0);
//set action
- value = 0x7; //drop
- //value |= 1;//valid
- write_acl_rule_table(0,value,0);
+ value = 0x7; //drop
+ //value |= 1;//valid
+ write_acl_rule_table(0, value, 0);
}
void acl_sp_add(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
int ports;
int ret;
@@ -912,31 +1011,31 @@
acl_compare_pattern(ports, value, 0x4, 0x0, 0);
//set rue mask
- write_acl_mask_table(0,0x1,0);
+ write_acl_mask_table(0, 0x1, 0);
//set action
- value = 0x7; //drop
- //value |= 1;//valid
- write_acl_rule_table(0,value,0);
+ value = 0x7; //drop
+ //value |= 1;//valid
+ write_acl_rule_table(0, value, 0);
}
void acl_port_enable(int argc, char *argv[])
{
- unsigned int value, reg;
- unsigned char acl_port, acl_en;
+ unsigned int value = 0, reg = 0;
+ unsigned char acl_port = 0, acl_en = 0;
acl_port = atoi(argv[3]);
acl_en = atoi(argv[4]);
printf("acl_port:%d, acl_en:%d\n", acl_port, acl_en);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((acl_port > SWITCH_MAX_PORT) || (acl_en > 1)) {
printf(HELP_ACL_SETPORTEN);
return;
}
- reg = REG_PCR_P0_ADDR + (0x100 * acl_port); // 0x2004[10]
+ reg = REG_PCR_P0_ADDR + (0x100 * acl_port); // 0x2004[10]
reg_read(reg, &value);
value &= (~REG_PORT_ACL_EN_MASK);
value |= (acl_en << REG_PORT_ACL_EN_OFFT);
@@ -948,37 +1047,37 @@
static void dip_dump_internal(int type)
{
unsigned int i, j, value, mac, mac2, value2;
- char tmpstr[16];
+ char tmpstr[16] = { 0 };
int table_size = 0;
int hit_value1 = 0;
int hit_value2 = 0;
- if(type == GENERAL_TABLE) {
+ if (type == GENERAL_TABLE) {
table_size = 0x800;
- reg_write(REG_ATC_ADDR, 0x8104); //dip search command
- } else {
+ reg_write(REG_ATC_ADDR, 0x8104); //dip search command
+ } else {
table_size = 0x40;
- reg_write(REG_ATC_ADDR, 0x811c); //dip search command
+ reg_write(REG_ATC_ADDR, 0x811c); //dip search command
}
- printf("hash port(0:6) rsp_cnt flag timer dip-address ATRD\n");
+ printf
+ ("hash port(0:6) rsp_cnt flag timer dip-address ATRD\n");
for (i = 0; i < table_size; i++) {
- while (1)
- {
+ while (1) {
reg_read(REG_ATC_ADDR, &value);
- if(type == GENERAL_TABLE) {
+ if (type == GENERAL_TABLE) {
hit_value1 = value & (0x1 << 13);
hit_value2 = 1;
- }else {
+ } else {
hit_value1 = value & (0x1 << 13);
hit_value2 = value & (0x1 << 28);
}
- if (hit_value1 && hit_value2 ) { //search_rdy
+ if (hit_value1 && hit_value2) { //search_rdy
reg_read(REG_ATRD_ADDR, &value2);
//printf("REG_ATRD_ADDR=0x%x\n\r",value2);
- printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
- j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ j = (value2 >> 4) & 0xff; //r_port_map
printf("%c", (j & 0x01) ? '1' : '-');
printf("%c", (j & 0x02) ? '1' : '-');
printf("%c", (j & 0x04) ? '1' : '-');
@@ -989,38 +1088,38 @@
reg_read(REG_TSRA2_ADDR, &mac2);
- printf(" 0x%4x", (mac2 & 0xffff)); //RESP_CNT
- printf(" 0x%2x", ((mac2 >> 16) & 0xff)); //RESP_FLAG
- printf(" %3d", ((mac2 >> 24) & 0xff)); //RESP_TIMER
- //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ printf(" 0x%4x", (mac2 & 0xffff)); //RESP_CNT
+ printf(" 0x%2x", ((mac2 >> 16) & 0xff)); //RESP_FLAG
+ printf(" %3d", ((mac2 >> 24) & 0xff)); //RESP_TIMER
+ //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
reg_read(REG_TSRA1_ADDR, &mac);
ip_to_str(tmpstr, mac);
printf(" %s", tmpstr);
- printf(" 0x%8x\n", value2); //ATRD
- //printf("%04x", ((mac2 >> 16) & 0xffff));
- //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
+ printf(" 0x%8x\n", value2); //ATRD
+ //printf("%04x", ((mac2 >> 16) & 0xffff));
+ //printf(" %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
if (value & 0x4000) {
printf("end of table %d\n", i);
return;
}
break;
- }
- else if (value & 0x4000) { //at_table_end
- printf("found the last entry %d (not ready)\n", i);
+ } else if (value & 0x4000) { //at_table_end
+ printf("found the last entry %d (not ready)\n",
+ i);
return;
}
usleep(5000);
}
- if(type == GENERAL_TABLE)
- reg_write(REG_ATC_ADDR, 0x8105); //search for next dip address
+ if (type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8105); //search for next dip address
else
- reg_write(REG_ATC_ADDR, 0x811d); //search for next dip address
+ reg_write(REG_ATC_ADDR, 0x811d); //search for next dip address
usleep(5000);
}
}
-void dip_dump(void)
+void dip_dump(int argc, char *argv[])
{
dip_dump_internal(GENERAL_TABLE);
@@ -1029,7 +1128,7 @@
void dip_add(int argc, char *argv[])
{
unsigned int value = 0;
- unsigned int i, j;
+ unsigned int i = 0, j = 0;
value = 0;
@@ -1049,13 +1148,14 @@
j = 0;
for (i = 0; i < 7; i++) {
if (argv[4][i] != '0' && argv[4][i] != '1') {
- printf("portmap format error, should be of combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
return;
}
j += (argv[4][i] - '0') * (1 << i);
}
- value = j << 4; //w_port_map
- value |= (0x3 << 2); //static
+ value = j << 4; //w_port_map
+ value |= (0x3 << 2); //static
reg_write(REG_ATWD_ADDR, value);
@@ -1063,14 +1163,14 @@
reg_read(REG_ATWD_ADDR, &value);
printf("REG_ATWD_ADDR is 0x%x\n\r", value);
- value = 0x8011; //single w_dip_cmd
+ value = 0x8011; //single w_dip_cmd
reg_write(REG_ATC_ADDR, value);
usleep(1000);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
printf("done.\n");
return;
}
@@ -1092,15 +1192,15 @@
value = 0;
reg_write(REG_ATA2_ADDR, value);
- value = 0; //STATUS=0, delete dip
+ value = 0; //STATUS=0, delete dip
reg_write(REG_ATWD_ADDR, value);
- value = 0x8011; //w_dip_cmd
+ value = 0x8011; //w_dip_cmd
reg_write(REG_ATC_ADDR, value);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
if (argv[1] != NULL)
printf("done.\n");
return;
@@ -1111,12 +1211,12 @@
printf("timeout.\n");
}
-void dip_clear(void)
+void dip_clear(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
- reg_write(REG_ATC_ADDR, 0x8102); //clear all dip
+ reg_write(REG_ATC_ADDR, 0x8102); //clear all dip
usleep(5000);
reg_read(REG_ATC_ADDR, &value);
printf("REG_ATC_ADDR is 0x%x\n\r", value);
@@ -1124,25 +1224,24 @@
static void sip_dump_internal(int type)
{
- unsigned int i, j, value, mac, mac2, value2;
+ unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
int table_size = 0;
int hit_value1 = 0;
int hit_value2 = 0;
- char tmpstr[16];
+ char tmpstr[16] = { 0 };
if (type == GENERAL_TABLE) {
table_size = 0x800;
- reg_write(REG_ATC_ADDR, 0x8204); //sip search command
- }else {
+ reg_write(REG_ATC_ADDR, 0x8204); //sip search command
+ } else {
table_size = 0x40;
- reg_write(REG_ATC_ADDR, 0x822c); //sip search command
+ reg_write(REG_ATC_ADDR, 0x822c); //sip search command
}
printf("hash port(0:6) dip-address sip-address ATRD\n");
for (i = 0; i < table_size; i++) {
- while (1)
- {
+ while (1) {
reg_read(REG_ATC_ADDR, &value);
- if(type == GENERAL_TABLE) {
+ if (type == GENERAL_TABLE) {
hit_value1 = value & (0x1 << 13);
hit_value2 = 1;
} else {
@@ -1150,12 +1249,12 @@
hit_value2 = value & (0x1 << 28);
}
- if (hit_value1 && hit_value2) { //search_rdy
+ if (hit_value1 && hit_value2) { //search_rdy
reg_read(REG_ATRD_ADDR, &value2);
//printf("REG_ATRD_ADDR=0x%x\n\r",value2);
- printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
- j = (value2 >> 4) & 0xff; //r_port_map
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ j = (value2 >> 4) & 0xff; //r_port_map
printf("%c", (j & 0x01) ? '1' : '-');
printf("%c", (j & 0x02) ? '1' : '-');
printf("%c", (j & 0x04) ? '1' : '-');
@@ -1181,42 +1280,42 @@
return;
}
break;
- } else if (value & 0x4000) { //at_table_end
- printf("found the last entry %d (not ready)\n", i);
+ } else if (value & 0x4000) { //at_table_end
+ printf("found the last entry %d (not ready)\n",
+ i);
return;
}
usleep(5000);
}
- if(type == GENERAL_TABLE)
- reg_write(REG_ATC_ADDR, 0x8205); //search for next sip address
- else
- reg_write(REG_ATC_ADDR, 0x822d); //search for next sip address
- usleep(5000);
+ if (type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8205); //search for next sip address
+ else
+ reg_write(REG_ATC_ADDR, 0x822d); //search for next sip address
+ usleep(5000);
}
}
-void sip_dump(void)
+void sip_dump(int argc, char *argv[])
{
sip_dump_internal(GENERAL_TABLE);
}
-
void sip_add(int argc, char *argv[])
{
- unsigned int i, j, value;
+ unsigned int i = 0, j = 0, value = 0;
value = 0;
- str_to_ip(&value, argv[3]); //SIP
+ str_to_ip(&value, argv[3]); //SIP
reg_write(REG_ATA2_ADDR, value);
printf("REG_ATA2_ADDR is 0x%x\n\r", value);
value = 0;
- str_to_ip(&value, argv[4]); //DIP
+ str_to_ip(&value, argv[4]); //DIP
reg_write(REG_ATA1_ADDR, value);
printf("REG_ATA1_ADDR is 0x%x\n\r", value);
@@ -1227,13 +1326,14 @@
j = 0;
for (i = 0; i < 7; i++) {
if (argv[5][i] != '0' && argv[5][i] != '1') {
- printf("portmap format error, should be of combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
return;
}
j += (argv[5][i] - '0') * (1 << i);
}
- value = j << 4; //w_port_map
- value |= (0x3 << 2); //static
+ value = j << 4; //w_port_map
+ value |= (0x3 << 2); //static
reg_write(REG_ATWD_ADDR, value);
@@ -1241,14 +1341,14 @@
reg_read(REG_ATWD_ADDR, &value);
printf("REG_ATWD_ADDR is 0x%x\n\r", value);
- value = 0x8021; //single w_sip_cmd
+ value = 0x8021; //single w_sip_cmd
reg_write(REG_ATC_ADDR, value);
usleep(1000);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
printf("done.\n");
return;
}
@@ -1260,25 +1360,25 @@
void sip_del(int argc, char *argv[])
{
- unsigned int i, value;
+ unsigned int i = 0, value = 0;
value = 0;
str_to_ip(&value, argv[3]);
- reg_write(REG_ATA2_ADDR, value); //SIP
+ reg_write(REG_ATA2_ADDR, value); //SIP
str_to_ip(&value, argv[4]);
- reg_write(REG_ATA1_ADDR, value); //DIP
+ reg_write(REG_ATA1_ADDR, value); //DIP
- value = 0; //STATUS=0, delete sip
+ value = 0; //STATUS=0, delete sip
reg_write(REG_ATWD_ADDR, value);
- value = 0x8021; //w_sip_cmd
+ value = 0x8021; //w_sip_cmd
reg_write(REG_ATC_ADDR, value);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
if (argv[1] != NULL)
printf("done.\n");
return;
@@ -1289,11 +1389,11 @@
printf("timeout.\n");
}
-void sip_clear(void)
+void sip_clear(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
- reg_write(REG_ATC_ADDR, 0x8202); //clear all sip
+ reg_write(REG_ATC_ADDR, 0x8202); //clear all sip
usleep(5000);
reg_read(REG_ATC_ADDR, &value);
printf("REG_ATC_ADDR is 0x%x\n\r", value);
@@ -1301,13 +1401,13 @@
static void table_dump_internal(int type)
{
- unsigned int i, j, value, mac, mac2, value2;
+ unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
int table_size = 0;
int table_end = 0;
int hit_value1 = 0;
int hit_value2 = 0;
- if (type == GENERAL_TABLE){
+ if (type == GENERAL_TABLE) {
table_size = 0x800;
table_end = 0x7FF;
reg_write(REG_ATC_ADDR, 0x8004);
@@ -1316,13 +1416,13 @@
table_end = 0x3F;
reg_write(REG_ATC_ADDR, 0x800C);
}
- printf("hash port(0:6) fid vid age(s) mac-address filter my_mac\n");
+ printf
+ ("hash port(0:6) fid vid age(s) mac-address filter my_mac\n");
for (i = 0; i < table_size; i++) {
- while (1)
- {
+ while (1) {
reg_read(REG_ATC_ADDR, &value);
//printf("ATC = 0x%x\n", value);
- if(type == GENERAL_TABLE) {
+ if (type == GENERAL_TABLE) {
hit_value1 = value & (0x1 << 13);
hit_value2 = 1;
} else {
@@ -1330,10 +1430,11 @@
hit_value2 = value & (0x1 << 28);
}
- if (hit_value1 && hit_value2 && (((value >> 15) & 0x1) == 0)) {
+ if (hit_value1 && hit_value2
+ && (((value >> 15) & 0x1) == 0)) {
printf("%03x: ", (value >> 16) & 0xfff);
reg_read(REG_ATRD_ADDR, &value2);
- j = (value2 >> 4) & 0xff; //r_port_map
+ j = (value2 >> 4) & 0xff; //r_port_map
printf("%c", (j & 0x01) ? '1' : '-');
printf("%c", (j & 0x02) ? '1' : '-');
printf("%c", (j & 0x04) ? '1' : '-');
@@ -1345,49 +1446,52 @@
reg_read(REG_TSRA2_ADDR, &mac2);
- printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
printf(" %4d", (mac2 & 0xfff));
if (((value2 >> 24) & 0xff) == 0xFF)
- printf(" --- "); //r_age_field:static
+ printf(" --- "); //r_age_field:static
else
- printf(" %5d ", (((value2 >> 24) & 0xff)+1)*2); //r_age_field
+ printf(" %5d ", (((value2 >> 24) & 0xff) + 1) * 2); //r_age_field
reg_read(REG_TSRA1_ADDR, &mac);
printf(" %08x", mac);
printf("%04x", ((mac2 >> 16) & 0xffff));
- printf(" %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
- printf(" %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
- if ((value & 0x4000) && (((value >> 16) & 0xfff) == table_end)) {
+ printf(" %c",
+ (((value2 >> 20) & 0x03) ==
+ 0x03) ? 'y' : '-');
+ printf(" %c\n",
+ (((value2 >> 23) & 0x01) ==
+ 0x01) ? 'y' : '-');
+ if ((value & 0x4000)
+ && (((value >> 16) & 0xfff) == table_end)) {
printf("end of table %d\n", i);
return;
}
break;
- }
- else if ((value & 0x4000) && (((value >> 15) & 0x1) == 0) && (((value >> 16) & 0xfff) == table_end)) { //at_table_end
- printf("found the last entry %d (not ready)\n", i);
+ } else if ((value & 0x4000) && (((value >> 15) & 0x1) == 0) && (((value >> 16) & 0xfff) == table_end)) { //at_table_end
+ printf("found the last entry %d (not ready)\n",
+ i);
return;
- }
- else
+ } else
usleep(5);
}
- if(type == GENERAL_TABLE)
- reg_write(REG_ATC_ADDR, 0x8005);//search for next address
- else
- reg_write(REG_ATC_ADDR, 0x800d);//search for next address
+ if (type == GENERAL_TABLE)
+ reg_write(REG_ATC_ADDR, 0x8005); //search for next address
+ else
+ reg_write(REG_ATC_ADDR, 0x800d); //search for next address
usleep(5);
}
}
-void table_dump(void)
+void table_dump(int argc, char *argv[])
{
table_dump_internal(GENERAL_TABLE);
}
-
void table_add(int argc, char *argv[])
{
- unsigned int i, j, value, is_filter, is_mymac;
+ unsigned int i = 0, j = 0, value = 0, is_filter = 0, is_mymac = 0;
char tmpstr[9];
is_filter = (argv[1][0] == 'f') ? 1 : 0;
@@ -1407,7 +1511,7 @@
value = strtoul(tmpstr, NULL, 16);
value = (value << 16);
- value |= (1 << 15); //IVL=1
+ value |= (1 << 15); //IVL=1
if (argc > 4) {
j = strtoul(argv[4], NULL, 0);
@@ -1415,7 +1519,7 @@
printf("wrong vid range, should be within 0~4095\n");
return;
}
- value |= j; //vid
+ value |= j; //vid
}
reg_write(REG_ATA2_ADDR, value);
@@ -1432,12 +1536,13 @@
j = 0;
for (i = 0; i < 7; i++) {
if (argv[3][i] != '0' && argv[3][i] != '1') {
- printf("portmap format error, should be of combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
return;
}
j += (argv[3][i] - '0') * (1 << i);
}
- value = j << 4; //w_port_map
+ value = j << 4; //w_port_map
if (argc > 5) {
j = strtoul(argv[5], NULL, 0);
@@ -1445,11 +1550,11 @@
printf("wrong age range, should be within 1~255\n");
return;
}
- value |= (j << 24); //w_age_field
- value |= (0x1 << 2); //dynamic
+ value |= (j << 24); //w_age_field
+ value |= (0x1 << 2); //dynamic
} else {
- value |= (0xff << 24); //w_age_field
- value |= (0x3 << 2); //static
+ value |= (0xff << 24); //w_age_field
+ value |= (0x3 << 2); //static
}
if (argc > 6) {
@@ -1458,11 +1563,11 @@
printf("wrong eg-tag range, should be within 0~7\n");
return;
}
- value |= (j << 13); //EG_TAG
+ value |= (j << 13); //EG_TAG
}
if (is_filter)
- value |= (7 << 20); //sa_filter
+ value |= (7 << 20); //sa_filter
if (is_mymac)
value |= (1 << 23);
@@ -1473,14 +1578,14 @@
reg_read(REG_ATWD_ADDR, &value);
printf("REG_ATWD_ADDR is 0x%x\n\r", value);
- value = 0x8001; //w_mac_cmd
+ value = 0x8001; //w_mac_cmd
reg_write(REG_ATC_ADDR, value);
usleep(1000);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
printf("done.\n");
return;
}
@@ -1492,7 +1597,7 @@
void table_search_mac_vid(int argc, char *argv[])
{
- unsigned int i, j, value, mac, mac2, value2;
+ unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
char tmpstr[9];
if (!argv[3] || strlen(argv[3]) != 12) {
@@ -1510,26 +1615,26 @@
value = strtoul(tmpstr, NULL, 16);
value = (value << 16);
- value |= (1 << 15); //IVL=1
+ value |= (1 << 15); //IVL=1
j = strtoul(argv[5], NULL, 0);
if (4095 < j) {
printf("wrong vid range, should be within 0~4095\n");
return;
}
- value |= j; //vid
+ value |= j; //vid
reg_write(REG_ATA2_ADDR, value);
//printf("REG_ATA2_ADDR is 0x%x\n\r",value);
- value = 0x8000; //w_mac_cmd
+ value = 0x8000; //w_mac_cmd
reg_write(REG_ATC_ADDR, value);
usleep(1000);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
break;
}
usleep(1000);
@@ -1545,11 +1650,12 @@
}
printf("search done.\n");
- printf("hash port(0:6) fid vid age mac-address filter my_mac\n");
+ printf
+ ("hash port(0:6) fid vid age mac-address filter my_mac\n");
- printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
reg_read(REG_ATRD_ADDR, &value2);
- j = (value2 >> 4) & 0xff; //r_port_map
+ j = (value2 >> 4) & 0xff; //r_port_map
printf("%c", (j & 0x01) ? '1' : '-');
printf("%c", (j & 0x02) ? '1' : '-');
printf("%c", (j & 0x04) ? '1' : '-');
@@ -1561,9 +1667,9 @@
reg_read(REG_TSRA2_ADDR, &mac2);
- printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
printf(" %4d", (mac2 & 0xfff));
- printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
reg_read(REG_TSRA1_ADDR, &mac);
printf(" %08x", mac);
printf("%04x", ((mac2 >> 16) & 0xffff));
@@ -1573,7 +1679,7 @@
void table_search_mac_fid(int argc, char *argv[])
{
- unsigned int i, j, value, mac, mac2, value2;
+ unsigned int i = 0, j = 0, value = 0, mac = 0, mac2 = 0, value2 = 0;
char tmpstr[9];
if (!argv[3] || strlen(argv[3]) != 12) {
@@ -1591,26 +1697,26 @@
value = strtoul(tmpstr, NULL, 16);
value = (value << 16);
- value &= ~(1 << 15); //IVL=0
+ value &= ~(1 << 15); //IVL=0
j = strtoul(argv[5], NULL, 0);
if (7 < j) {
printf("wrong fid range, should be within 0~7\n");
return;
}
- value |= (j << 12); //vid
+ value |= (j << 12); //vid
reg_write(REG_ATA2_ADDR, value);
//printf("REG_ATA2_ADDR is 0x%x\n\r",value);
- value = 0x8000; //w_mac_cmd
+ value = 0x8000; //w_mac_cmd
reg_write(REG_ATC_ADDR, value);
usleep(1000);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
break;
}
usleep(1000);
@@ -1626,11 +1732,12 @@
}
printf("search done.\n");
- printf("hash port(0:6) fid vid age mac-address filter my_mac\n");
+ printf
+ ("hash port(0:6) fid vid age mac-address filter my_mac\n");
- printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
+ printf("%03x: ", (value >> 16) & 0xfff); //hash_addr_lu
reg_read(REG_ATRD_ADDR, &value2);
- j = (value2 >> 4) & 0xff; //r_port_map
+ j = (value2 >> 4) & 0xff; //r_port_map
printf("%c", (j & 0x01) ? '1' : '-');
printf("%c", (j & 0x02) ? '1' : '-');
printf("%c", (j & 0x04) ? '1' : '-');
@@ -1642,9 +1749,9 @@
reg_read(REG_TSRA2_ADDR, &mac2);
- printf(" %2d", (mac2 >> 12) & 0x7); //FID
+ printf(" %2d", (mac2 >> 12) & 0x7); //FID
printf(" %4d", (mac2 & 0xfff));
- printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+ printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
reg_read(REG_TSRA1_ADDR, &mac);
printf(" %08x", mac);
printf("%04x", ((mac2 >> 16) & 0xffff));
@@ -1654,7 +1761,7 @@
void table_del_fid(int argc, char *argv[])
{
- unsigned int i, j, value;
+ unsigned int i = 0, j = 0, value = 0;
char tmpstr[9];
if (!argv[3] || strlen(argv[3]) != 12) {
@@ -1676,20 +1783,20 @@
printf("wrong fid range, should be within 0~7\n");
return;
}
- value |= (j << 12); //fid
+ value |= (j << 12); /* fid */
}
reg_write(REG_ATA2_ADDR, value);
- value = 0; //STATUS=0, delete mac
+ value = 0; /* STATUS=0, delete mac */
reg_write(REG_ATWD_ADDR, value);
- value = 0x8001; //w_mac_cmd
+ value = 0x8001; //w_mac_cmd
reg_write(REG_ATC_ADDR, value);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { /* mac address busy */
if (argv[1] != NULL)
printf("done.\n");
return;
@@ -1702,7 +1809,7 @@
void table_del_vid(int argc, char *argv[])
{
- unsigned int i, j, value;
+ unsigned int i = 0, j = 0, value = 0;
char tmpstr[9];
if (!argv[3] || strlen(argv[3]) != 12) {
@@ -1724,19 +1831,19 @@
printf("wrong fid range, should be within 0~4095\n");
return;
}
- value |= j; //vid
+ value |= j; //vid
value |= 1 << 15;
reg_write(REG_ATA2_ADDR, value);
- value = 0; //STATUS=0, delete mac
+ value = 0; //STATUS=0, delete mac
reg_write(REG_ATWD_ADDR, value);
- value = 0x8001; //w_mac_cmd
+ value = 0x8001; //w_mac_cmd
reg_write(REG_ATC_ADDR, value);
for (i = 0; i < 20; i++) {
reg_read(REG_ATC_ADDR, &value);
- if ((value & 0x8000) == 0) { //mac address busy
+ if ((value & 0x8000) == 0) { //mac address busy
if (argv[1] != NULL)
printf("done.\n");
return;
@@ -1747,9 +1854,10 @@
printf("timeout.\n");
}
-void table_clear(void)
+void table_clear(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
+
reg_write(REG_ATC_ADDR, 0x8002);
usleep(5000);
reg_read(REG_ATC_ADDR, &value);
@@ -1759,8 +1867,8 @@
void set_mirror_to(int argc, char *argv[])
{
- unsigned int value;
- int idx;
+ unsigned int value = 0;
+ int idx = 0;
idx = strtoul(argv[3], NULL, 0);
if (idx < 0 || MAX_PORT < idx) {
@@ -1788,8 +1896,8 @@
void set_mirror_from(int argc, char *argv[])
{
- unsigned int offset, value;
- int idx, mirror;
+ unsigned int offset = 0, value = 0;
+ int idx = 0, mirror = 0;
idx = strtoul(argv[3], NULL, 0);
mirror = strtoul(argv[4], NULL, 0);
@@ -1815,7 +1923,7 @@
void vlan_dump(int argc, char *argv[])
{
- unsigned int i, j, value, value2;
+ unsigned int i = 0, j = 0, value = 0, value2 = 0;
int eg_tag = 0;
if (argc == 4) {
@@ -1824,17 +1932,18 @@
}
if (eg_tag)
- printf(" vid fid portmap s-tag\teg_tag(0:untagged 2:tagged)\n");
+ printf
+ (" vid fid portmap s-tag\teg_tag(0:untagged 2:tagged)\n");
else
printf(" vid fid portmap s-tag\n");
for (i = 1; i < 4095; i++) {
- value = (0x80000000 + i); //r_vid_cmd
+ value = (0x80000000 + i); //r_vid_cmd
reg_write(REG_VTCR_ADDR, value);
for (j = 0; j < 20; j++) {
reg_read(REG_VTCR_ADDR, &value);
- if ((value & 0x80000000) == 0) { //mac address busy
+ if ((value & 0x80000000) == 0) { //mac address busy
break;
}
usleep(1000);
@@ -1881,7 +1990,7 @@
}
printf("\n");
} else {
- /*print 16 vid for reference information*/
+ /*print 16 vid for reference information */
if (i <= 16) {
printf(" %4d ", i);
printf(" %2d ", ((value & 0xe) >> 1));
@@ -1891,7 +2000,6 @@
}
}
-
static long timespec_diff_us(struct timespec start, struct timespec end)
{
struct timespec temp;
@@ -1904,32 +2012,31 @@
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
- /* calculate second part*/
+ /* calculate second part */
duration += temp.tv_sec * 1000000;
- /* calculate ns part*/
+ /* calculate ns part */
duration += temp.tv_nsec >> 10;
return duration;
}
-
void vlan_clear(int argc, char *argv[])
{
- unsigned int value;
- int vid;
+ unsigned int value = 0;
+ int vid = 0;
unsigned long duration_us = 0;
struct timespec start, end;
for (vid = 0; vid < 4096; vid++) {
clock_gettime(CLOCK_REALTIME, &start);
- value = 0; //invalid
+ value = 0; //invalid
reg_write(REG_VAWD1_ADDR, value);
- value = (0x80001000 + vid); //w_vid_cmd
+ value = (0x80001000 + vid); //w_vid_cmd
reg_write(REG_VTCR_ADDR, value);
while (duration_us <= 1000) {
reg_read(REG_VTCR_ADDR, &value);
- if ((value & 0x80000000) == 0) { //table busy
+ if ((value & 0x80000000) == 0) { //table busy
break;
}
clock_gettime(CLOCK_REALTIME, &end);
@@ -1945,7 +2052,7 @@
unsigned int vlan_mem = 0;
unsigned int value = 0;
unsigned int value2 = 0;
- int i, vid, fid;
+ int i = 0, vid = 0, fid = 0;
int stag = 0;
unsigned long eg_con = 0;
unsigned int eg_tag = 0;
@@ -1976,7 +2083,8 @@
vlan_mem = 0;
for (i = 0; i < 8; i++) {
if (argv[5][i] != '0' && argv[5][i] != '1') {
- printf("portmap format error, should be of combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
return;
}
vlan_mem += (argv[5][i] - '0') * (1 << i);
@@ -1986,7 +2094,8 @@
if (argc > 6) {
stag = strtoul(argv[6], NULL, 16);
if (stag < 0 || 0xfff < stag) {
- printf("wrong stag id range, should be within 0~4095\n");
+ printf
+ ("wrong stag id range, should be within 0~4095\n");
return;
}
//printf("STAG is 0x%x\n", stag);
@@ -1994,33 +2103,35 @@
/* set vlan member */
value |= (vlan_mem << 16);
- value |= (1 << 30); //IVL=1
- value |= ((stag & 0xfff) << 4); //stag
- value |= 1; //valid
+ value |= (1 << 30); //IVL=1
+ value |= ((stag & 0xfff) << 4); //stag
+ value |= 1; //valid
if (argc > 7) {
eg_con = strtoul(argv[7], NULL, 2);
eg_con = !!eg_con;
- value |= (eg_con << 29); //eg_con
- value |= (1 << 28); //eg tag control enable
+ value |= (eg_con << 29); //eg_con
+ value |= (1 << 28); //eg tag control enable
}
if (argc > 8 && !eg_con) {
if (strlen(argv[8]) != 8) {
- printf("egtag portmap format error, should be of length 7\n");
+ printf
+ ("egtag portmap format error, should be of length 7\n");
return;
}
for (i = 0; i < 8; i++) {
if (argv[8][i] < '0' || argv[8][i] > '3') {
- printf("egtag portmap format error, should be of combination of 0 or 3\n");
+ printf
+ ("egtag portmap format error, should be of combination of 0 or 3\n");
return;
}
//eg_tag += (argv[8][i] - '0') * (1 << i * 2);
eg_tag |= (argv[8][i] - '0') << (i * 2);
}
- value |= (1 << 28); //eg tag control enable
+ value |= (1 << 28); //eg tag control enable
value2 &= ~(0xffff);
value2 |= eg_tag;
}
@@ -2028,14 +2139,14 @@
reg_write(REG_VAWD2_ADDR, value2);
//printf("VAWD1=0x%08x VAWD2=0x%08x ", value, value2);
- value = (0x80001000 + vid); //w_vid_cmd
+ value = (0x80001000 + vid); //w_vid_cmd
reg_write(REG_VTCR_ADDR, value);
//printf("VTCR=0x%08x\n", value);
for (i = 0; i < 300; i++) {
usleep(1000);
reg_read(REG_VTCR_ADDR, &value);
- if ((value & 0x80000000) == 0) //table busy
+ if ((value & 0x80000000) == 0) //table busy
break;
}
@@ -2047,7 +2158,7 @@
{
unsigned int leaky_en = 0;
unsigned int wan_num = 4;
- unsigned int port, offset, value;
+ unsigned int port = 0, offset = 0, value = 0;
char cmd[80];
int ret;
@@ -2074,8 +2185,7 @@
reg_write(0x2410, value & (~(1 << 3)));
reg_write(REG_ISC_ADDR, 0x01027d01);
}
- }
- else
+ } else
reg_write(REG_ISC_ADDR, 0x10027d60);
reg_write(0x1c, 0x08100810);
@@ -2086,15 +2196,15 @@
reg_write(0x2408, 0xb3ff);
reg_write(0x2608, 0xb3ff);
/* Enable Port ACL
- * reg_write(0x2P04, 0xff0403);
- */
+ * reg_write(0x2P04, 0xff0403);
+ */
for (port = 0; port <= 6; port++) {
offset = 0x2004 + port * 0x100;
reg_read(offset, &value);
reg_write(offset, value | (1 << 10));
}
- /*IGMP query only p4 -> p5*/
+ /*IGMP query only p4 -> p5 */
reg_write(0x94, 0x00ff0002);
if (wan_num == 4)
reg_write(0x98, 0x000a1008);
@@ -2114,7 +2224,7 @@
reg_write(0x98, 0x0);
reg_write(0x90, 0x8000b000);
- /*IGMP p5 -> p4*/
+ /*IGMP p5 -> p4 */
reg_write(0x94, 0x00ff0002);
reg_write(0x98, 0x000a2008);
reg_write(0x90, 0x80005002);
@@ -2128,7 +2238,7 @@
reg_write(0x98, 0x0);
reg_write(0x90, 0x8000b001);
- /*IGMP p0~p3 -> p6*/
+ /*IGMP p0~p3 -> p6 */
reg_write(0x94, 0x00ff0002);
if (wan_num == 4)
reg_write(0x98, 0x000a0f08);
@@ -2142,7 +2252,7 @@
reg_write(0x98, 0x0);
reg_write(0x90, 0x8000b002);
- /*IGMP query only p6 -> p0~p3*/
+ /*IGMP query only p6 -> p0~p3 */
reg_write(0x94, 0x00ff0002);
reg_write(0x98, 0x000a4008);
reg_write(0x90, 0x80005004);
@@ -2159,18 +2269,21 @@
reg_write(0x98, 0x0);
reg_write(0x90, 0x8000b003);
- /*Force eth2 to receive all igmp packets*/
- snprintf(cmd, sizeof(cmd), "echo 2 > /sys/devices/virtual/net/%s/brif/%s/multicast_router", BR_DEVNAME, ETH_DEVNAME);
+ /*Force eth2 to receive all igmp packets */
+ snprintf(cmd, sizeof(cmd),
+ "echo 2 > /sys/devices/virtual/net/%s/brif/%s/multicast_router",
+ BR_DEVNAME, ETH_DEVNAME);
ret = system(cmd);
if (ret)
- printf("Failed to set /sys/devices/virtual/net/%s/brif/%s/multicast_router\n",
- BR_DEVNAME, ETH_DEVNAME);
+ printf
+ ("Failed to set /sys/devices/virtual/net/%s/brif/%s/multicast_router\n",
+ BR_DEVNAME, ETH_DEVNAME);
}
void igmp_disable(int argc, char *argv[])
{
- unsigned int reg_offset, value;
- int port_num;
+ unsigned int reg_offset = 0, value = 0;
+ int port_num = 0;
if (argc < 4) {
printf("insufficient arguments!\n");
@@ -2181,7 +2294,6 @@
printf("wrong port range, should be within 0~6\n");
return;
}
-
//set ISC: IGMP Snooping Control Register (offset: 0x0018)
reg_offset = 0x2008;
reg_offset |= (port_num << 8);
@@ -2192,7 +2304,7 @@
void igmp_enable(int argc, char *argv[])
{
- unsigned int reg_offset, value;
+ unsigned int reg_offset = 0, value = 0;
int port_num;
if (argc < 4) {
@@ -2204,7 +2316,6 @@
printf("wrong port range, should be within 0~6\n");
return;
}
-
//set ISC: IGMP Snooping Control Register (offset: 0x0018)
reg_offset = 0x2008;
reg_offset |= (port_num << 8);
@@ -2212,15 +2323,15 @@
reg_write(reg_offset, value);
}
-void igmp_off()
+void igmp_off(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
//set ISC: IGMP Snooping Control Register (offset: 0x0018)
reg_read(REG_ISC_ADDR, &value);
- value &= ~(1 << 18); //disable
+ value &= ~(1 << 18); //disable
reg_write(REG_ISC_ADDR, value);
- /*restore wan port multicast leaky vlan function: default disabled*/
+ /*restore wan port multicast leaky vlan function: default disabled */
reg_read(0x2010, &value);
reg_write(0x2010, value & (~(1 << 3)));
reg_read(0x2410, &value);
@@ -2229,10 +2340,10 @@
printf("config igmpsnoop off.\n");
}
-int switch_reset(int argc, char *argv[])
+void switch_reset(int argc, char *argv[])
{
if (chip_name == 0x7988)
- return -1;
+ return;
unsigned int value = 0;
/*Software Register Reset and Software System Reset */
@@ -2245,23 +2356,24 @@
printf("GPIO Mode (0x7c0c) select value =0x%x \n", value);
}
printf("Switch Software Reset !!! \n");
- return 0;
}
-int phy_set_fc(int argc, char *argv[])
+void phy_set_fc(int argc, char *argv[])
{
- unsigned int port, pause_capable;
- unsigned int phy_value;
+ unsigned int port = 0, pause_capable = 0;
+ unsigned int phy_value = 0;
port = atoi(argv[3]);
pause_capable = atoi(argv[4]);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (port > MAX_PORT - 2 || pause_capable > 1) {
- printf("Illegal parameter (port:0~4, full_duplex_pause_capable:0|1)\n");
- return -1;
+ printf
+ ("Illegal parameter (port:0~4, full_duplex_pause_capable:0|1)\n");
+ return;
}
printf("port=%d, full_duplex_pause_capable:%d\n", port, pause_capable);
+
mii_mgr_read(port, 4, &phy_value);
printf("read phy_value:0x%x\r\n", phy_value);
phy_value &= (~(0x1 << 10));
@@ -2272,35 +2384,36 @@
}
mii_mgr_write(port, 4, phy_value);
printf("write phy_value:0x%x\r\n", phy_value);
- return 0;
-} /*end phy_set_fc*/
+ return;
+} /*end phy_set_fc */
-int phy_set_an(int argc, char *argv[])
+void phy_set_an(int argc, char *argv[])
{
- unsigned int port, auto_negotiation_en;
- unsigned int phy_value;
+ unsigned int port = 0, auto_negotiation_en = 0;
+ unsigned int phy_value = 0;
port = atoi(argv[3]);
auto_negotiation_en = atoi(argv[4]);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (port > MAX_PORT - 2 || auto_negotiation_en > 1) {
- printf("Illegal parameter (port:0~4, auto_negotiation_en:0|1)\n");
- return -1;
+ printf
+ ("Illegal parameter (port:0~4, auto_negotiation_en:0|1)\n");
+ return;
}
printf("port=%d, auto_negotiation_en:%d\n", port, auto_negotiation_en);
+
mii_mgr_read(port, 0, &phy_value);
printf("read phy_value:0x%x\r\n", phy_value);
phy_value &= (~(1 << 12));
phy_value |= (auto_negotiation_en << 12);
mii_mgr_write(port, 0, phy_value);
printf("write phy_value:0x%x\r\n", phy_value);
- return 0;
-} /*end phy_set_an*/
+} /*end phy_set_an */
-int set_mac_pfc(int argc, char *argv[])
+void set_mac_pfc(int argc, char *argv[])
{
- unsigned int value;
+ unsigned int value = 0;
int port, enable = 0;
port = atoi(argv[3]);
@@ -2308,7 +2421,7 @@
printf("enable: %d\n", enable);
if (port < 0 || port > 6 || enable < 0 || enable > 1) {
printf("Illegal parameter (port:0~6, enable|diable:0|1) \n");
- return -1;
+ return;
}
if (chip_name == 0x7531 || chip_name == 0x7988) {
reg_read(REG_PFC_CTRL_ADDR, &value);
@@ -2316,25 +2429,23 @@
value |= (enable << port);
printf("write reg: %x, value: %x\n", REG_PFC_CTRL_ADDR, value);
reg_write(REG_PFC_CTRL_ADDR, value);
- }
- else
+ } else
printf("\nCommand not support by this chip.\n");
- return 0;
}
-int global_set_mac_fc(int argc, char *argv[])
+void global_set_mac_fc(int argc, char *argv[])
{
unsigned char enable = 0;
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
if (chip_name == 0x7530) {
enable = atoi(argv[3]);
printf("enable: %d\n", enable);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (enable > 1) {
printf(HELP_MACCTL_FC);
- return -1;
+ return;
}
reg_write(0x7000, 0x3);
reg = REG_GFCCR0_ADDR;
@@ -2345,17 +2456,16 @@
reg_write(REG_GFCCR0_ADDR, value);
} else
printf("\r\nCommand not support by this chip.\n");
- return 0;
-} /*end mac_set_fc*/
+} /*end mac_set_fc */
-int qos_sch_select(int argc, char *argv[])
+void qos_sch_select(int argc, char *argv[])
{
- unsigned char port, queue;
+ unsigned char port = 0, queue = 0;
unsigned char type = 0;
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
if (argc < 7)
- return -1;
+ return;
port = atoi(argv[3]);
queue = atoi(argv[4]);
@@ -2363,26 +2473,26 @@
if (port > 6 || queue > 7) {
printf("\n Illegal input parameters\n");
- return -1;
+ return;
}
if ((type != 0 && type != 1 && type != 2)) {
printf(HELP_QOS_TYPE);
- return -1;
+ return;
}
- printf("\r\nswitch qos type: %d.\n",type);
+ printf("\r\nswitch qos type: %d.\n", type);
if (!strncmp(argv[5], "min", 4)) {
if (type == 0) {
- /*min sharper-->round roubin, disable min sharper rate limit*/
+ /*min sharper-->round roubin, disable min sharper rate limit */
reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
reg_read(reg, &value);
value = 0x0;
reg_write(reg, value);
} else if (type == 1) {
- /*min sharper-->sp, disable min sharper rate limit*/
+ /*min sharper-->sp, disable min sharper rate limit */
reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
reg_read(reg, &value);
value = 0x0;
@@ -2390,75 +2500,72 @@
reg_write(reg, value);
} else {
printf("min sharper only support: rr or sp\n");
- return -1;
+ return;
}
} else if (!strncmp(argv[5], "max", 4)) {
if (type == 1) {
- /*max sharper-->sp, disable max sharper rate limit*/
+ /*max sharper-->sp, disable max sharper rate limit */
reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
reg_read(reg, &value);
value = 0x0;
value |= (1 << 31);
reg_write(reg, value);
} else if (type == 2) {
- /*max sharper-->wfq, disable max sharper rate limit*/
+ /*max sharper-->wfq, disable max sharper rate limit */
reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
reg_read(reg, &value);
value = 0x0;
reg_write(reg, value);
} else {
printf("max sharper only support: wfq or sp\n");
- return -1;
+ return;
}
} else {
- printf("\r\nIllegal sharper:%s\n",argv[5]);
- return -1;
+ printf("\r\nIllegal sharper:%s\n", argv[5]);
+ return;
}
- printf("reg:0x%x--value:0x%x\n",reg,value);
-
- return 0;
+ printf("reg:0x%x--value:0x%x\n", reg, value);
}
void get_upw(unsigned int *value, unsigned char base)
{
*value &= (~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
(0x7 << 16) | (0x7 << 20)));
- switch (base)
- {
- case 0: /* port-based 0x2x40[18:16] */
- *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
- (0x2 << 12) | (0x7 << 16) | (0x2 << 20));
- break;
- case 1: /* tagged-based 0x2x40[10:8] */
- *value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
- (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
- break;
- case 2: /* DSCP-based 0x2x40[14:12] */
- *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
- (0x7 << 12) | (0x2 << 16) | (0x2 << 20));
- break;
- case 3: /* acl-based 0x2x40[2:0] */
- *value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
- (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
- break;
- case 4: /* arl-based 0x2x40[22:20] */
- *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
- (0x2 << 12) | (0x2 << 16) | (0x7 << 20));
- break;
- case 5: /* stag-based 0x2x40[6:4] */
- *value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
- (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
- break;
- default:
- break;
+ switch (base) {
+ case 0: /* port-based 0x2x40[18:16] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x7 << 16) | (0x2 << 20));
+ break;
+ case 1: /* tagged-based 0x2x40[10:8] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 2: /* DSCP-based 0x2x40[14:12] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x7 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 3: /* acl-based 0x2x40[2:0] */
+ *value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 4: /* arl-based 0x2x40[22:20] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x7 << 20));
+ break;
+ case 5: /* stag-based 0x2x40[6:4] */
+ *value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ default:
+ break;
}
}
void qos_set_base(int argc, char *argv[])
{
unsigned char base = 0;
- unsigned char port;
- unsigned int value;
+ unsigned char port = 0;
+ unsigned int value = 0;
if (argc < 5)
return;
@@ -2472,13 +2579,12 @@
}
if (port > 6) {
- printf("Illegal port index:%d\n",port);
+ printf("Illegal port index:%d\n", port);
return;
}
printf("\r\nswitch qos base : %d. (port-based:0, tag-based:1,\
- dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n",
- base);
+ dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n", base);
if (chip_name == 0x7530) {
reg_read(0x44, &value);
@@ -2491,7 +2597,7 @@
reg_read(GSW_UPW(port), &value);
get_upw(&value, base);
reg_write(GSW_UPW(port), value);
- printf("reg:0x%x, value: 0x%x\n",GSW_UPW(port),value);
+ printf("reg:0x%x, value: 0x%x\n", GSW_UPW(port), value);
} else {
printf("unknown switch device");
@@ -2501,9 +2607,9 @@
void qos_wfq_set_weight(int argc, char *argv[])
{
- int port, weight[8], i;
- unsigned char queue;
- unsigned int reg, value;
+ int port = 0, weight[8], i = 0;
+ unsigned char queue = 0;
+ unsigned int reg = 0, value = 0;
port = atoi(argv[3]);
@@ -2524,14 +2630,12 @@
}
}
printf("port: %x, q0: %x, q1: %x, q2: %x, q3: %x, \
- q4: %x, q5: %x, q6: %x, q7: %x\n",
- port, weight[0], weight[1], weight[2], weight[3], weight[4],
- weight[5], weight[6], weight[7]);
+ q4: %x, q5: %x, q6: %x, q7: %x\n", port, weight[0], weight[1], weight[2], weight[3], weight[4], weight[5], weight[6], weight[7]);
for (queue = 0; queue < 8; queue++) {
reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
reg_read(reg, &value);
- value &= (~(0xf << 24)); //bit24~27
+ value &= (~(0xf << 24)); //bit24~27
value |= (((weight[queue] - 1) & 0xf) << 24);
printf("reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
@@ -2540,8 +2644,8 @@
void qos_set_portpri(int argc, char *argv[])
{
- unsigned char port, prio;
- unsigned int value;
+ unsigned char port = 0, prio = 0;
+ unsigned int value = 0;
port = atoi(argv[3]);
prio = atoi(argv[4]);
@@ -2560,8 +2664,8 @@
void qos_set_dscppri(int argc, char *argv[])
{
- unsigned char prio, dscp, pim_n, pim_offset;
- unsigned int reg, value;
+ unsigned char prio = 0, dscp = 0, pim_n = 0, pim_offset = 0;
+ unsigned int value = 0, reg = 0;
dscp = atoi(argv[3]);
prio = atoi(argv[4]);
@@ -2583,8 +2687,8 @@
void qos_pri_mapping_queue(int argc, char *argv[])
{
- unsigned char prio, queue, pem_n, port;
- unsigned int reg, value;
+ unsigned char prio = 0, queue = 0, pem_n = 0, port = 0;
+ unsigned int value = 0, reg = 0;
if (argc < 6)
return;
@@ -2597,6 +2701,7 @@
printf(HELP_QOS_PRIO_QMAP);
return;
}
+
if (chip_name == 0x7530) {
pem_n = prio / 2;
reg = pem_n * 0x4 + 0x48;
@@ -2614,34 +2719,33 @@
pem_n = prio / 2;
reg = GSW_PEM(pem_n) + 0x100 * port;
reg_read(reg, &value);
- if (prio % 2) { // 1 1
+ if (prio % 2) { // 1 1
value &= (~(0x7 << 25));
value |= ((queue & 0x7) << 25);
- } else { // 0 0
+ } else { // 0 0
value &= (~(0x7 << 9));
value |= ((queue & 0x7) << 9);
}
reg_write(reg, value);
printf("write reg: %x, value: %x\n", reg, value);
- }
- else {
+ } else {
printf("unknown switch device");
return;
}
}
static int macMT753xVlanSetVid(unsigned char index, unsigned char active,
- unsigned short vid, unsigned char portMap, unsigned char tagPortMap,
- unsigned char ivl_en, unsigned char fid, unsigned short stag)
+ unsigned short vid, unsigned char portMap,
+ unsigned char tagPortMap, unsigned char ivl_en,
+ unsigned char fid, unsigned short stag)
{
unsigned int value = 0;
unsigned int value2 = 0;
- unsigned int reg;
- int i;
+ unsigned int reg = 0;
+ int i = 0;
printf("index: %x, active: %x, vid: %x, portMap: %x, \
- tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n",
- index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
+ tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n", index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
value = (portMap << 16);
value |= (stag << 4);
@@ -2656,22 +2760,22 @@
}
if (value2)
- value |= (1 << 28); // eg_tag
+ value |= (1 << 28); // eg_tag
- reg = 0x98; // VAWD2
+ reg = 0x98; // VAWD2
reg_write(reg, value2);
- reg = 0x94; // VAWD1
+ reg = 0x94; // VAWD1
reg_write(reg, value);
- reg = 0x90; // VTCR
+ reg = 0x90; // VTCR
value = (0x80001000 + vid);
reg_write(reg, value);
- reg = 0x90; // VTCR
+ reg = 0x90; // VTCR
while (1) {
reg_read(reg, &value);
- if ((value & 0x80000000) == 0) //table busy
+ if ((value & 0x80000000) == 0) //table busy
break;
}
@@ -2685,45 +2789,14 @@
index, active, vid, portMap, tagPortMap);
return 0;
-} /*end macMT753xVlanSetVid*/
-/*
-static int macMT753xVlanGetVtbl(unsigned short index)
-{
- unsigned int reg, value, vawd1, vawd2;
-
- reg = 0x90; // VTCR
- value = (0x80000000 + index);
-
- reg_write(reg, value);
-
- reg = 0x90; // VTCR
- while (1) {
- reg_read(reg, &value);
- if ((value & 0x80000000) == 0) //table busy
- break;
- }
-
- reg = 0x94; // VAWD1
- reg_read(reg, &vawd1);
-
- reg = 0x98; // VAWD2
- reg_read(reg, &vawd2);
-
- if (vawd1 & 0x1) {
- fprintf(stderr, "%d.%s vid:%d fid:%d portMap:0x%x \
- tagMap:0x%x stag:0x%x ivl_en:0x%x\r\n",
- index, (vawd1 & 0x1) ? "on" : "off", index, ((vawd1 & 0xe) >> 1),
- (vawd1 & 0xff0000) >> 16, vawd2, (vawd1 & 0xfff0) >> 0x4, (vawd1 >> 30) & 0x1);
- }
- return 0;
-} */ /*end macMT753xVlanGetVtbl*/
+} /*end macMT753xVlanSetVid */
static int macMT753xVlanSetPvid(unsigned char port, unsigned short pvid)
{
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
- /*Parameters is error*/
+ /*Parameters is error */
if (port > 6)
return -1;
@@ -2742,38 +2815,6 @@
printf("SetPVID: port:%d pvid:%d\r\n", port, pvid);
return 0;
}
-/*
-static int macMT753xVlanGetPvid(unsigned char port)
-{
- unsigned int value;
- unsigned int reg;
-
- if (port > 6)
- return -1;
- reg = 0x2014 + (port * 0x100);
- reg_read(reg, &value);
- return (value & 0xfff);
-} */
-/*
-static int macMT753xVlanDisp(void)
-{
- unsigned int i = 0;
- unsigned int reg, value;
-
- reg = 0x2604;
- reg_read(reg, &value);
- value &= 0x30000000;
-
- fprintf(stderr, "VLAN function is %s\n", value ? ETHCMD_ENABLE : ETHCMD_DISABLE);
- fprintf(stderr, "PVID e0:%02d e1:%02d e2:%02d e3:%02d e4:%02d e5:%02d e6:%02d\n",
- macMT753xVlanGetPvid(0), macMT753xVlanGetPvid(1), macMT753xVlanGetPvid(2),
- macMT753xVlanGetPvid(3), macMT753xVlanGetPvid(4), macMT753xVlanGetPvid(5), macMT753xVlanGetPvid(6));
-
- for (i = 0; i < MAX_VID_VALUE; i++)
- macMT753xVlanGetVtbl(i);
-
- return 0;
-}*/ /*end macMT753xVlanDisp*/
void doVlanSetPvid(int argc, char *argv[])
{
@@ -2782,7 +2823,7 @@
port = atoi(argv[3]);
pvid = atoi(argv[4]);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((port >= SWITCH_MAX_PORT) || (pvid > MAX_VID_VALUE)) {
printf(HELP_VLAN_PVID);
return;
@@ -2792,7 +2833,7 @@
printf("port:%d pvid:%d,vlancap: max_port:%d maxvid:%d\r\n",
port, pvid, SWITCH_MAX_PORT, MAX_VID_VALUE);
-} /*end doVlanSetPvid*/
+} /*end doVlanSetPvid */
void doVlanSetVid(int argc, char *argv[])
{
@@ -2810,13 +2851,13 @@
active = atoi(argv[4]);
vid = atoi(argv[5]);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((index >= MAX_VLAN_RULE) || (vid >= 4096) || (active > ACTIVED)) {
printf(HELP_VLAN_VID);
return;
}
- /*CPU Port is always the membership*/
+ /*CPU Port is always the membership */
portMap = atoi(argv[6]);
tagPortMap = atoi(argv[7]);
@@ -2832,21 +2873,21 @@
macMT753xVlanSetVid(index, active, vid, portMap, tagPortMap,
ivl_en, fid, stag);
printf("index:%d active:%d vid:%d\r\n", index, active, vid);
-} /*end doVlanSetVid*/
+} /*end doVlanSetVid */
void doVlanSetAccFrm(int argc, char *argv[])
{
unsigned char port = 0;
unsigned char type = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
port = atoi(argv[3]);
type = atoi(argv[4]);
printf("port: %d, type: %d\n", port, type);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((port > SWITCH_MAX_PORT) || (type > REG_PVC_ACC_FRM_RELMASK)) {
printf(HELP_VLAN_ACC_FRM);
return;
@@ -2859,21 +2900,21 @@
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
-} /*end doVlanSetAccFrm*/
+} /*end doVlanSetAccFrm */
void doVlanSetPortAttr(int argc, char *argv[])
{
unsigned char port = 0;
unsigned char attr = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
port = atoi(argv[3]);
attr = atoi(argv[4]);
printf("port: %x, attr: %x\n", port, attr);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (port > SWITCH_MAX_PORT || attr > 3) {
printf(HELP_VLAN_PORT_ATTR);
return;
@@ -2892,13 +2933,14 @@
{
unsigned char port = 0;
unsigned char mode = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
+
port = atoi(argv[3]);
mode = atoi(argv[4]);
printf("port: %x, mode: %x\n", port, mode);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (port > SWITCH_MAX_PORT || mode > 3) {
printf(HELP_VLAN_PORT_MODE);
return;
@@ -2916,15 +2958,15 @@
{
unsigned char port = 0;
unsigned char eg_tag = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
port = atoi(argv[3]);
eg_tag = atoi(argv[4]);
printf("port: %d, eg_tag: %d\n", port, eg_tag);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PCR_EG_TAG_RELMASK)) {
printf(HELP_VLAN_EGRESS_TAG_PCR);
return;
@@ -2938,21 +2980,21 @@
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
-} /*end doVlanSetEgressTagPCR*/
+} /*end doVlanSetEgressTagPCR */
void doVlanSetEgressTagPVC(int argc, char *argv[])
{
unsigned char port = 0;
unsigned char eg_tag = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
port = atoi(argv[3]);
eg_tag = atoi(argv[4]);
printf("port: %d, eg_tag: %d\n", port, eg_tag);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PVC_EG_TAG_RELMASK)) {
printf(HELP_VLAN_EGRESS_TAG_PVC);
return;
@@ -2965,19 +3007,19 @@
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
-} /*end doVlanSetEgressTagPVC*/
+} /*end doVlanSetEgressTagPVC */
void doArlAging(int argc, char *argv[])
{
unsigned char aging_en = 0;
- unsigned int time = 0, aging_cnt = 0, aging_unit = 0, value, reg;
- ;
+ unsigned int time = 0, aging_cnt = 0, aging_unit = 0, value = 0, reg =
+ 0;
aging_en = atoi(argv[3]);
time = atoi(argv[4]);
printf("aging_en: %x, aging time: %x\n", aging_en, time);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((aging_en != 0 && aging_en != 1) || (time <= 0 || time > 65536)) {
printf(HELP_ARL_AGING);
return;
@@ -3006,16 +3048,16 @@
void doMirrorEn(int argc, char *argv[])
{
- unsigned char mirror_en;
- unsigned char mirror_port;
- unsigned int value, reg;
+ unsigned char mirror_en = 0;
+ unsigned char mirror_port = 0;
+ unsigned int value = 0, reg = 0;
mirror_en = atoi(argv[3]);
mirror_port = atoi(argv[4]);
printf("mirror_en: %d, mirror_port: %d\n", mirror_en, mirror_port);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((mirror_en > 1) || (mirror_port > REG_CFC_MIRROR_PORT_RELMASK)) {
printf(HELP_MIRROR_EN);
return;
@@ -3031,12 +3073,13 @@
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
-} /*end doMirrorEn*/
+} /*end doMirrorEn */
void doMirrorPortBased(int argc, char *argv[])
{
- unsigned char port, port_tx_mir, port_rx_mir, vlan_mis, acl_mir, igmp_mir;
- unsigned int value, reg;
+ unsigned char port = 0, port_tx_mir = 0, port_rx_mir = 0, vlan_mis =
+ 0, acl_mir = 0, igmp_mir = 0;
+ unsigned int value = 0, reg = 0;
port = atoi(argv[3]);
port_tx_mir = atoi(argv[4]);
@@ -3045,20 +3088,28 @@
vlan_mis = atoi(argv[7]);
igmp_mir = atoi(argv[8]);
- printf("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n", port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
+ printf
+ ("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n",
+ port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
//if((port >= vlanCap->max_port_no) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)){
- if ((port >= 7) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)) { // also allow CPU port (port6)
+ if ((port >= 7) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)) { // also allow CPU port (port6)
printf(HELP_MIRROR_PORTBASED);
return;
}
reg = REG_PCR_P0_ADDR + port * 0x100;
reg_read(reg, &value);
- value &= ~(REG_PORT_TX_MIR_MASK | REG_PORT_RX_MIR_MASK | REG_PCR_ACL_MIR_MASK | REG_PCR_VLAN_MIS_MASK);
- value |= (port_tx_mir << REG_PORT_TX_MIR_OFFT) + (port_rx_mir << REG_PORT_RX_MIR_OFFT);
- value |= (acl_mir << REG_PCR_ACL_MIR_OFFT) + (vlan_mis << REG_PCR_VLAN_MIS_OFFT);
+ value &=
+ ~(REG_PORT_TX_MIR_MASK | REG_PORT_RX_MIR_MASK | REG_PCR_ACL_MIR_MASK
+ | REG_PCR_VLAN_MIS_MASK);
+ value |=
+ (port_tx_mir << REG_PORT_TX_MIR_OFFT) +
+ (port_rx_mir << REG_PORT_RX_MIR_OFFT);
+ value |=
+ (acl_mir << REG_PCR_ACL_MIR_OFFT) +
+ (vlan_mis << REG_PCR_VLAN_MIS_OFFT);
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
@@ -3071,15 +3122,15 @@
printf("write reg: %x, value: %x\n", reg, value);
reg_write(reg, value);
-} /*end doMirrorPortBased*/
+} /*end doMirrorPortBased */
void doStp(int argc, char *argv[])
{
unsigned char port = 0;
unsigned char fid = 0;
unsigned char state = 0;
- unsigned int value;
- unsigned int reg;
+ unsigned int value = 0;
+ unsigned int reg = 0;
port = atoi(argv[2]);
fid = atoi(argv[3]);
@@ -3087,7 +3138,7 @@
printf("port: %d, fid: %d, state: %d\n", port, fid, state);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if ((port > MAX_PORT + 1) || (fid > 7) || (state > 3)) {
printf(HELP_STP);
return;
@@ -3102,45 +3153,54 @@
reg_write(reg, value);
}
-int ingress_rate_set(int on_off, unsigned int port, unsigned int bw)
+void _ingress_rate_set(int on_off, int port, int bw)
{
- unsigned int reg, value;
+ unsigned int reg = 0, value = 0;
reg = 0x1800 + (0x100 * port);
value = 0;
- /*token-bucket*/
+ /*token-bucket */
if (on_off == 1) {
if (chip_name == 0x7530) {
if (bw > 1000000) {
- printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",
+ bw);
+ return;
}
- value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0x0f;
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (7 << 8) +
+ (1 << 7) + 0x0f;
} else if (chip_name == 0x7531 || chip_name == 0x7988) {
if ((chip_name == 0x7531) && (bw > 2500000)) {
- printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",
+ bw);
+ return;
}
if ((chip_name == 0x7988) && (bw > 4000000)) {
- printf("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",
+ bw);
+ return;
}
- if (bw/32 >= 65536) //supoort 2.5G case
- value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+ if (bw / 32 >= 65536) //supoort 2.5G case
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
+ (1 << 12) + (7 << 8) + 0xf;
else
- value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
- }
- else
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
+ (7 << 8) + 0xf;
+ } else
printf("unknow chip\n");
}
-
#if leaky_bucket
reg_read(reg, &value);
value &= 0xffff0000;
- if (on_off == 1)
- {
+ if (on_off == 1) {
value |= on_off << 15;
//7530 same as 7531
if (bw < 100) {
@@ -3166,39 +3226,71 @@
reg_read(reg, &value);
value = 0x110104;
reg_write(reg, value);
- return 0;
+
+ if (on_off)
+ printf("switch port=%d, bw=%d\n", port, bw);
+ else
+ printf("switch port=%d ingress rate limit off\n", port);
}
-int egress_rate_set(int on_off, int port, int bw)
+void ingress_rate_set(int argc, char *argv[])
{
- unsigned int reg, value;
+ int on_off = 0, port = 0, bw = 0;
+
+ port = strtoul(argv[3], NULL, 0);
+ if (argv[2][1] == 'n') {
+ bw = strtoul(argv[4], NULL, 0);
+ on_off = 1;
+ } else if (argv[2][1] == 'f') {
+ if (argc != 4)
+ return;
+ on_off = 0;
+ }
+
+ _ingress_rate_set(on_off, port, bw);
+}
+
+void _egress_rate_set(int on_off, int port, int bw)
+{
+ unsigned int value = 0, reg = 0;
reg = 0x1040 + (0x100 * port);
value = 0;
- /*token-bucket*/
+ /*token-bucket */
if (on_off == 1) {
if (chip_name == 0x7530) {
if (bw < 0 || bw > 1000000) {
- printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",
+ bw);
+ return;
}
- value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0xf;
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (7 << 8) +
+ (1 << 7) + 0xf;
} else if (chip_name == 0x7531 || chip_name == 0x7988) {
if ((chip_name == 0x7531) && (bw < 0 || bw > 2500000)) {
- printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",
+ bw);
+ return;
}
if ((chip_name == 0x7988) && (bw < 0 || bw > 4000000)) {
- printf("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",bw);
- return -1;
+ printf
+ ("\n**Charge rate(%d) is larger than line rate(4000000kbps)**\n",
+ bw);
+ return;
}
- if (bw/32 >= 65536) //support 2.5G cases
- value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+ if (bw / 32 >= 65536) //support 2.5G cases
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
+ (1 << 12) + (7 << 8) + 0xf;
else
- value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
- }
- else
+ value =
+ ((bw / 32) << 16) + (1 << 15) + (1 << 14) +
+ (7 << 8) + 0xf;
+ } else
printf("unknow chip\n");
}
reg_write(reg, value);
@@ -3207,7 +3299,28 @@
value &= 0x18;
reg_write(reg, value);
- return 0;
+ if (on_off)
+ printf("switch port=%d, bw=%d\n", port, bw);
+ else
+ printf("switch port=%d egress rate limit off\n", port);
+}
+
+void egress_rate_set(int argc, char *argv[])
+{
+ unsigned int value = 0, reg = 0;
+ int on_off = 0, port = 0, bw = 0;
+
+ port = strtoul(argv[3], NULL, 0);
+ if (argv[2][1] == 'n') {
+ bw = strtoul(argv[4], NULL, 0);
+ on_off = 1;
+ } else if (argv[2][1] == 'f') {
+ if (argc != 4)
+ return;
+ on_off = 0;
+ }
+
+ _egress_rate_set(on_off, port, bw);
}
void rate_control(int argc, char *argv[])
@@ -3223,34 +3336,33 @@
if (port > 6)
return;
- if (dir == 1) //ingress
- ingress_rate_set(1, port, rate);
- else if (dir == 0) //egress
- egress_rate_set(1, port, rate);
+ if (dir == 1) //ingress
+ _ingress_rate_set(1, port, rate);
+ else if (dir == 0) //egress
+ _egress_rate_set(1, port, rate);
else
return;
}
-int collision_pool_enable(int argc, char *argv[])
+void collision_pool_enable(int argc, char *argv[])
{
- unsigned char enable;
- unsigned int value, reg;
+ unsigned char enable = 0;
+ unsigned int value = 0, reg = 0;
enable = atoi(argv[3]);
-
printf("collision pool enable: %d \n", enable);
- /*Check the input parameters is right or not.*/
+ /*Check the input parameters is right or not. */
if (enable > 1) {
printf(HELP_COLLISION_POOL_EN);
- return -1;
+ return;
}
if (chip_name == 0x7531 || chip_name == 0x7988) {
reg = REG_CPGC_ADDR;
- if(enable == 1) {
+ if (enable == 1) {
/* active reset */
reg_read(reg, &value);
value &= (~REG_CPCG_COL_RST_N_MASK);
@@ -3276,7 +3388,7 @@
reg_read(reg, &value);
printf("write reg: %x, value: %x\n", reg, value);
- }else {
+ } else {
/* disable collision pool */
reg_read(reg, &value);
@@ -3303,70 +3415,67 @@
printf("write reg: %x, value: %x\n", reg, value);
}
- }else{
+ } else {
printf("\nCommand not support by this chip.\n");
-}
-
- return 0;
+ }
}
-void collision_pool_mac_dump()
+void collision_pool_mac_dump(int argc, char *argv[])
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
if (chip_name == 0x7531 || chip_name == 0x7988) {
reg = REG_CPGC_ADDR;
reg_read(reg, &value);
- if(value & REG_CPCG_COL_EN_MASK)
+ if (value & REG_CPCG_COL_EN_MASK)
table_dump_internal(COLLISION_TABLE);
else
- printf("\ncollision pool is disabled, please enable it before use this command.\n");
- }else {
+ printf
+ ("\ncollision pool is disabled, please enable it before use this command.\n");
+ } else {
printf("\nCommand not support by this chip.\n");
}
}
-void collision_pool_dip_dump()
+void collision_pool_dip_dump(int argc, char *argv[])
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
if (chip_name == 0x7531 || chip_name == 0x7988) {
reg = REG_CPGC_ADDR;
reg_read(reg, &value);
- if(value & REG_CPCG_COL_EN_MASK)
+ if (value & REG_CPCG_COL_EN_MASK)
dip_dump_internal(COLLISION_TABLE);
else
- printf("\ncollision pool is disabled, please enable it before use this command.\n");
- }else {
+ printf
+ ("\ncollision pool is disabled, please enable it before use this command.\n");
+ } else {
printf("\nCommand not support by this chip.\n");
}
-
-
}
-void collision_pool_sip_dump()
+void collision_pool_sip_dump(int argc, char *argv[])
{
- unsigned int value, reg;
+ unsigned int value = 0, reg = 0;
- if (chip_name == 0x7531 || chip_name == 0x7988) {
+ if (chip_name == 0x7531 || chip_name == 0x7988) {
reg = REG_CPGC_ADDR;
reg_read(reg, &value);
- if(value & REG_CPCG_COL_EN_MASK)
+ if (value & REG_CPCG_COL_EN_MASK)
sip_dump_internal(COLLISION_TABLE);
else
- printf("\ncollision pool is disabled, please enable it before use this command.\n");
- }else {
+ printf
+ ("\ncollision pool is disabled, please enable it before use this command.\n");
+ } else {
printf("\nCommand not support by this chip.\n");
}
-
-
}
void pfc_get_rx_counter(int argc, char *argv[])
{
- int port;
- unsigned int value, reg;
- unsigned int user_pri;
+ int port = 0;
+ unsigned int value = 0, reg = 0;
+ unsigned int user_pri = 0;
port = strtoul(argv[3], NULL, 0);
if (port < 0 || 6 < port) {
@@ -3374,33 +3483,41 @@
return;
}
- if (chip_name == 0x7531 || chip_name == 0x7988) {
- reg= PFC_RX_COUNTER_L(port);
+ if (chip_name == 0x7531 || chip_name == 0x7988) {
+ reg = PFC_RX_COUNTER_L(port);
reg_read(reg, &value);
user_pri = value & 0xff;
- printf("\n port %d rx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=0)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff00) >> 8;
- printf("\n port %d rx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=1)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff0000) >> 16;
- printf("\n port %d rx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=2)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff000000) >> 24;
- printf("\n port %d rx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=3)pause on counter is %d.\n",
+ port, user_pri);
- reg= PFC_RX_COUNTER_H(port);
+ reg = PFC_RX_COUNTER_H(port);
reg_read(reg, &value);
user_pri = value & 0xff;
- printf("\n port %d rx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=4)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff00) >> 8;
- printf("\n port %d rx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=5)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff0000) >> 16;
- printf("\n port %d rx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=6)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff000000) >> 24;
- printf("\n port %d rx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d rx pfc (up=7)pause on counter is %d.\n",
+ port, user_pri);
/* for rx counter could be updated successfully */
reg_read(PMSR_P(port), &value);
reg_read(PMSR_P(port), &value);
- }else {
+ } else {
printf("\nCommand not support by this chip.\n");
}
@@ -3408,9 +3525,9 @@
void pfc_get_tx_counter(int argc, char *argv[])
{
- int port;
- unsigned int value, reg;
- unsigned int user_pri;
+ int port = 0;
+ unsigned int value = 0, reg = 0;
+ unsigned int user_pri = 0;
port = strtoul(argv[3], NULL, 0);
if (port < 0 || 6 < port) {
@@ -3419,83 +3536,99 @@
}
if (chip_name == 0x7531 || chip_name == 0x7988) {
- reg= PFC_TX_COUNTER_L(port);
+ reg = PFC_TX_COUNTER_L(port);
reg_read(reg, &value);
user_pri = value & 0xff;
- printf("\n port %d tx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=0)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff00) >> 8;
- printf("\n port %d tx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=1)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff0000) >> 16;
- printf("\n port %d tx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=2)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff000000) >> 24;
- printf("\n port %d tx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=3)pause on counter is %d.\n",
+ port, user_pri);
- reg= PFC_TX_COUNTER_H(port);
+ reg = PFC_TX_COUNTER_H(port);
reg_read(reg, &value);
user_pri = value & 0xff;
- printf("\n port %d tx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=4)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff00) >> 8;
- printf("\n port %d tx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=5)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff0000) >> 16;
- printf("\n port %d tx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=6)pause on counter is %d.\n",
+ port, user_pri);
user_pri = (value & 0xff000000) >> 24;
- printf("\n port %d tx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+ printf("\n port %d tx pfc (up=7)pause on counter is %d.\n",
+ port, user_pri);
/* for tx counter could be updated successfully */
reg_read(PMSR_P(port), &value);
reg_read(PMSR_P(port), &value);
- }else {
- printf("\nCommand not support by this chip.\n");
+ } else {
+ printf("\nCommand not support by this chip.\n");
}
}
-void read_output_queue_counters()
+void read_output_queue_counters(int argc, char *argv[])
{
- unsigned int port=0;
- unsigned int value, output_queue;
- unsigned int base=0x220;
+ unsigned int port = 0;
+ unsigned int value = 0, output_queue = 0;
+ unsigned int base = 0x220;
for (port = 0; port < 7; port++) {
- reg_write(0x7038, base + (port *4));
+ reg_write(0x7038, base + (port * 4));
reg_read(0x7034, &value);
output_queue = value & 0xff;
- printf("\n port %d output queue 0 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 0 counter is %d.\n", port,
+ output_queue);
output_queue = (value & 0xff00) >> 8;
- printf("\n port %d output queue 1 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 1 counter is %d.\n", port,
+ output_queue);
- reg_write(0x7038, base + (port *4) + 1);
+ reg_write(0x7038, base + (port * 4) + 1);
reg_read(0x7034, &value);
output_queue = value & 0xff;
- printf("\n port %d output queue 2 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 2 counter is %d.\n", port,
+ output_queue);
output_queue = (value & 0xff00) >> 8;
- printf("\n port %d output queue 3 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 3 counter is %d.\n", port,
+ output_queue);
- reg_write(0x7038, base + (port *4) + 2);
+ reg_write(0x7038, base + (port * 4) + 2);
reg_read(0x7034, &value);
output_queue = value & 0xff;
- printf("\n port %d output queue 4 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 4 counter is %d.\n", port,
+ output_queue);
output_queue = (value & 0xff00) >> 8;
- printf("\n port %d output queue 5 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 5 counter is %d.\n", port,
+ output_queue);
- reg_write(0x7038, base + (port *4) + 3);
+ reg_write(0x7038, base + (port * 4) + 3);
reg_read(0x7034, &value);
output_queue = value & 0xff;
- printf("\n port %d output queue 6 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 6 counter is %d.\n", port,
+ output_queue);
output_queue = (value & 0xff00) >> 8;
- printf("\n port %d output queue 7 counter is %d.\n", port,output_queue);
+ printf("\n port %d output queue 7 counter is %d.\n", port,
+ output_queue);
}
}
-void read_free_page_counters()
+void read_free_page_counters(int argc, char *argv[])
{
- unsigned int value;
- unsigned int free_page,free_page_last_read;
- unsigned int fc_free_blk_lothd,fc_free_blk_hithd;
- unsigned int fc_port_blk_thd,fc_port_blk_hi_thd;
- unsigned int queue[8]={0};
+ unsigned int value = 0;
+ unsigned int free_page = 0, free_page_last_read = 0;
+ unsigned int fc_free_blk_lothd = 0, fc_free_blk_hithd = 0;
+ unsigned int fc_port_blk_thd = 0, fc_port_blk_hi_thd = 0;
+ unsigned int queue[8] = { 0 };
if (chip_name == 0x7531 || chip_name == 0x7988) {
- /* get system free page link counter*/
+ /* get system free page link counter */
reg_read(0x1fc0, &value);
free_page = value & 0xFFF;
free_page_last_read = (value & 0xFFF0000) >> 16;
@@ -3512,17 +3645,17 @@
/* get queue flow control waterwark */
reg_read(0x1fe8, &value);
- queue[0]= value & 0x3F;
- queue[1]= (value & 0x3F00) >> 8;
- queue[2]= (value & 0x3F0000) >> 16;
- queue[3]= (value & 0x3F000000) >> 24;
+ queue[0] = value & 0x3F;
+ queue[1] = (value & 0x3F00) >> 8;
+ queue[2] = (value & 0x3F0000) >> 16;
+ queue[3] = (value & 0x3F000000) >> 24;
reg_read(0x1fec, &value);
- queue[4]= value & 0x3F;
- queue[5]= (value & 0x3F00) >> 8;
- queue[6]= (value & 0x3F0000) >> 16;
- queue[7]= (value & 0x3F000000) >> 24;
+ queue[4] = value & 0x3F;
+ queue[5] = (value & 0x3F00) >> 8;
+ queue[6] = (value & 0x3F0000) >> 16;
+ queue[7] = (value & 0x3F000000) >> 24;
} else {
- /* get system free page link counter*/
+ /* get system free page link counter */
reg_read(0x1fc0, &value);
free_page = value & 0x3FF;
free_page_last_read = (value & 0x3FF0000) >> 16;
@@ -3540,50 +3673,61 @@
/* get queue flow control waterwark */
reg_read(0x1fe4, &value);
- queue[0]= value & 0xF;
- queue[1]= (value & 0xF0) >> 4;
- queue[2]= (value & 0xF00) >> 8;
- queue[3]= (value & 0xF000) >>12;
- queue[4]= (value & 0xF0000) >>16;
- queue[5]= (value & 0xF00000) >> 20;
- queue[6]= (value & 0xF000000) >> 24;
- queue[7]= (value & 0xF0000000) >> 28;
+ queue[0] = value & 0xF;
+ queue[1] = (value & 0xF0) >> 4;
+ queue[2] = (value & 0xF00) >> 8;
+ queue[3] = (value & 0xF000) >> 12;
+ queue[4] = (value & 0xF0000) >> 16;
+ queue[5] = (value & 0xF00000) >> 20;
+ queue[6] = (value & 0xF000000) >> 24;
+ queue[7] = (value & 0xF0000000) >> 28;
}
- printf("<===Free Page=======Current=======Last Read access=====> \n ");
- printf(" \n ");
- printf(" page counter %u %u \n ",free_page,free_page_last_read);
- printf(" \n ");
- printf("========================================================= \n ");
- printf("<===Type=======High threshold======Low threshold=========\n ");
- printf(" \n ");
- printf(" system: %u %u \n", fc_free_blk_hithd*2, fc_free_blk_lothd*2);
- printf(" port: %u %u \n", fc_port_blk_hi_thd*2, fc_port_blk_thd*2);
- printf(" queue 0: %u NA \n", queue[0]);
- printf(" queue 1: %u NA \n", queue[1]);
- printf(" queue 2: %u NA \n", queue[2]);
- printf(" queue 3: %u NA \n", queue[3]);
- printf(" queue 4: %u NA \n", queue[4]);
- printf(" queue 5: %u NA \n", queue[5]);
- printf(" queue 6: %u NA \n", queue[6]);
- printf(" queue 7: %u NA \n", queue[7]);
- printf("=========================================================\n ");
+ printf("<===Free Page=======Current=======Last Read access=====>\n");
+ printf("\n");
+ printf(" page counter %u %u\n ",
+ free_page, free_page_last_read);
+ printf("\n ");
+ printf("=========================================================\n");
+ printf("<===Type=======High threshold======Low threshold=========\n");
+ printf("\n ");
+ printf(" system: %u %u\n",
+ fc_free_blk_hithd * 2, fc_free_blk_lothd * 2);
+ printf(" port: %u %u\n",
+ fc_port_blk_hi_thd * 2, fc_port_blk_thd * 2);
+ printf(" queue 0: %u NA\n",
+ queue[0]);
+ printf(" queue 1: %u NA\n",
+ queue[1]);
+ printf(" queue 2: %u NA\n",
+ queue[2]);
+ printf(" queue 3: %u NA\n",
+ queue[3]);
+ printf(" queue 4: %u NA\n",
+ queue[4]);
+ printf(" queue 5: %u NA\n",
+ queue[5]);
+ printf(" queue 6: %u NA\n",
+ queue[6]);
+ printf(" queue 7: %u NA\n",
+ queue[7]);
+ printf("=========================================================\n");
}
void eee_enable(int argc, char *argv[])
{
- unsigned long enable;
- unsigned int value;
- unsigned int eee_cap;
+ unsigned long enable = 0;
+ unsigned int value = 0;
+ unsigned int eee_cap = 0;
unsigned int eee_en_bitmap = 0;
- unsigned long port_map;
+ unsigned long port_map = 0;
long port_num = -1;
- int p;
+ int p = 0;
if (argc < 3)
goto error;
- /*Check the input parameters is right or not.*/
+ /* Check the input parameters is right or not. */
if (!strncmp(argv[2], "enable", 7))
enable = 1;
else if (!strncmp(argv[2], "disable", 8))
@@ -3603,23 +3747,25 @@
port_map = 0;
for (p = 0; p < MAX_PHY_PORT; p++) {
if (argv[3][p] != '0' && argv[3][p] != '1') {
- printf("portmap format error, should be combination of 0 or 1\n");
+ printf
+ ("portmap format error, should be combination of 0 or 1\n");
goto error;
}
port_map |= ((argv[3][p] - '0') << p);
}
} else {
- printf("port_no or portmap format error, should be length of 1 or 5\n");
+ printf
+ ("port_no or portmap format error, should be length of 1 or 5\n");
goto error;
}
} else {
port_map = 0x1f;
}
- eee_cap = (enable)? 6: 0;
+ eee_cap = (enable) ? 6 : 0;
for (p = 0; p < MAX_PHY_PORT; p++) {
/* port_map describe p0p1p2p3p4 from left to rignt */
- if(!!(port_map & (1 << p)))
+ if (!!(port_map & (1 << p)))
mii_mgr_c45_write(p, 0x7, 0x3c, eee_cap);
mii_mgr_c45_read(p, 0x7, 0x3c, &value);
@@ -3642,7 +3788,7 @@
printf("\nCommand not support by this chip.\n");
}
- printf("EEE(802.3az) %s", (enable)? "enable": "disable");
+ printf("EEE(802.3az) %s", (enable) ? "enable" : "disable");
if (argc == 4) {
if (port_num >= 0)
printf(" port%ld", port_num);
@@ -3661,9 +3807,9 @@
void eee_dump(int argc, char *argv[])
{
- unsigned int cap, lp_cap;
+ unsigned int cap = 0, lp_cap = 0;
long port = -1;
- int p;
+ int p = 0;
if (argc > 3) {
if (strlen(argv[3]) > 1) {
@@ -3674,7 +3820,7 @@
port = strtol(argv[3], (char **)NULL, 0);
if (port < 0 || port > MAX_PHY_PORT) {
printf("port# format error, should be 0 to %d\n",
- MAX_PHY_PORT);
+ MAX_PHY_PORT);
return;
}
}
@@ -3716,7 +3862,7 @@
printf("\n");
}
-void read_mib_counters()
+void read_mib_counters(int argc, char *argv[])
{
printf("===================== %8s %8s %8s %8s %8s %8s %8s\n",
"Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
@@ -3760,14 +3906,13 @@
dump_each_port(0x408C);
}
-void clear_mib_counters()
+void clear_mib_counters(int argc, char *argv[])
{
reg_write(0x4fe0, 0xf0);
- read_mib_counters();
+ read_mib_counters(argc, argv);
reg_write(0x4fe0, 0x800000f0);
}
-
void exit_free()
{
free(attres);
diff --git a/recipes-devtools/switch/files/src/switch_fun.h b/recipes-devtools/switch/files/src/switch_fun.h
index 70e4d18..cc16c20 100644
--- a/recipes-devtools/switch/files/src/switch_fun.h
+++ b/recipes-devtools/switch/files/src/switch_fun.h
@@ -6,6 +6,84 @@
#include <stdbool.h>
+void (*pf_chip_func)(int argc, char *argv[]);
+
+struct switch_func_s {
+ void (*pf_table_dump)(int argc, char *argv[]);
+ void (*pf_table_clear)(int argc, char *argv[]);
+ void (*pf_switch_reset)(int argc, char *argv[]);
+ void (*pf_doArlAging)(int argc, char *argv[]);
+ void (*pf_read_mib_counters)(int argc, char *argv[]);
+ void (*pf_clear_mib_counters)(int argc, char *argv[]);
+ void (*pf_read_output_queue_counters)(int argc, char *argv[]);
+ void (*pf_read_free_page_counters)(int argc, char *argv[]);
+ void (*pf_rate_control)(int argc, char *argv[]);
+ void (*pf_igress_rate_set)(int argc, char *argv[]);
+ void (*pf_egress_rate_set)(int argc, char *argv[]);
+ void (*pf_table_add)(int argc, char *argv[]);
+ void (*pf_table_del_fid)(int argc, char *argv[]);
+ void (*pf_table_del_vid)(int argc, char *argv[]);
+ void (*pf_table_search_mac_fid)(int argc, char *argv[]);
+ void (*pf_table_search_mac_vid)(int argc, char *argv[]);
+ void (*pf_global_set_mac_fc)(int argc, char *argv[]);
+ void (*pf_set_mac_pfc)(int argc, char *argv[]);
+ void (*pf_qos_sch_select)(int argc, char *argv[]);
+ void (*pf_qos_set_base)(int argc, char *argv[]);
+ void (*pf_qos_wfq_set_weight)(int argc, char *argv[]);
+ void (*pf_qos_set_portpri)(int argc, char *argv[]);
+ void (*pf_qos_set_dscppri)(int argc, char *argv[]);
+ void (*pf_qos_pri_mapping_queue)(int argc, char *argv[]);
+ void (*pf_doStp)(int argc, char *argv[]);
+ void (*pf_sip_dump)(int argc, char *argv[]);
+ void (*pf_sip_add)(int argc, char *argv[]);
+ void (*pf_sip_del)(int argc, char *argv[]);
+ void (*pf_sip_clear)(int argc, char *argv[]);
+ void (*pf_dip_dump)(int argc, char *argv[]);
+ void (*pf_dip_add)(int argc, char *argv[]);
+ void (*pf_dip_del)(int argc, char *argv[]);
+ void (*pf_dip_clear)(int argc, char *argv[]);
+ void (*pf_set_mirror_to)(int argc, char *argv[]);
+ void (*pf_set_mirror_from)(int argc, char *argv[]);
+ void (*pf_doMirrorEn)(int argc, char *argv[]);
+ void (*pf_doMirrorPortBased)(int argc, char *argv[]);
+ void (*pf_acl_dip_add)(int argc, char *argv[]);
+ void (*pf_acl_dip_modify)(int argc, char *argv[]);
+ void (*pf_acl_dip_pppoe)(int argc, char *argv[]);
+ void (*pf_acl_dip_trtcm)(int argc, char *argv[]);
+ void (*pf_acl_dip_meter)(int argc, char *argv[]);
+ void (*pf_acl_mac_add)(int argc, char *argv[]);
+ void (*pf_acl_ethertype)(int argc, char *argv[]);
+ void (*pf_acl_sp_add)(int argc, char *argv[]);
+ void (*pf_acl_l4_add)(int argc, char *argv[]);
+ void (*pf_acl_port_enable)(int argc, char *argv[]);
+ void (*pf_acl_table_add)(int argc, char *argv[]);
+ void (*pf_acl_mask_table_add)(int argc, char *argv[]);
+ void (*pf_acl_rule_table_add)(int argc, char *argv[]);
+ void (*pf_acl_rate_table_add)(int argc, char *argv[]);
+ void (*pf_vlan_dump)(int argc, char *argv[]);
+ void (*pf_vlan_set)(int argc, char *argv[]);
+ void (*pf_vlan_clear)(int argc, char *argv[]);
+ void (*pf_doVlanSetVid)(int argc, char *argv[]);
+ void (*pf_doVlanSetPvid)(int argc, char *argv[]);
+ void (*pf_doVlanSetAccFrm)(int argc, char *argv[]);
+ void (*pf_doVlanSetPortAttr)(int argc, char *argv[]);
+ void (*pf_doVlanSetPortMode)(int argc, char *argv[]);
+ void (*pf_doVlanSetEgressTagPCR)(int argc, char *argv[]);
+ void (*pf_doVlanSetEgressTagPVC)(int argc, char *argv[]);
+ void (*pf_igmp_on)(int argc, char *argv[]);
+ void (*pf_igmp_off)(int argc, char *argv[]);
+ void (*pf_igmp_enable)(int argc, char *argv[]);
+ void (*pf_igmp_disable)(int argc, char *argv[]);
+ void (*pf_collision_pool_enable)(int argc, char *argv[]);
+ void (*pf_collision_pool_mac_dump)(int argc, char *argv[]);
+ void (*pf_collision_pool_dip_dump)(int argc, char *argv[]);
+ void (*pf_collision_pool_sip_dump)(int argc, char *argv[]);
+ void (*pf_pfc_get_rx_counter)(int argc, char *argv[]);
+ void (*pf_pfc_get_tx_counter)(int argc, char *argv[]);
+ void (*pf_eee_enable)(int argc, char *argv[]);
+ void (*pf_eee_dump)(int argc, char *argv[]);
+};
+
#define MT7530_T10_TEST_CONTROL 0x145
#define MAX_PORT 6
@@ -15,14 +93,18 @@
extern int chip_name;
extern struct mt753x_attr *attres;
extern bool nl_init_flag;
+extern struct switch_func_s mt753x_switch_func;
+extern struct switch_func_s an8855_switch_func;
/*basic operation*/
int reg_read(unsigned int offset, unsigned int *value);
int reg_write(unsigned int offset, unsigned int value);
int mii_mgr_read(unsigned int port_num, unsigned int reg, unsigned int *value);
int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value);
-int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int *value);
-int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value);
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg,
+ unsigned int *value);
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg,
+ unsigned int value);
/*phy setting*/
int phy_dump(int phy_addr);
@@ -50,28 +132,28 @@
void acl_rate_table_add(int argc, char *argv[]);
/*dip table*/
-void dip_dump(void);
+void dip_dump(int argc, char *argv[]);
void dip_add(int argc, char *argv[]);
void dip_del(int argc, char *argv[]);
-void dip_clear(void);
+void dip_clear(int argc, char *argv[]);
/*sip table*/
-void sip_dump(void);
+void sip_dump(int argc, char *argv[]);
void sip_add(int argc, char *argv[]);
void sip_del(int argc, char *argv[]);
-void sip_clear(void);
+void sip_clear(int argc, char *argv[]);
/*stp*/
void doStp(int argc, char *argv[]);
/*mac table*/
-void table_dump(void);
+void table_dump(int argc, char *argv[]);
void table_add(int argc, char *argv[]);
void table_search_mac_vid(int argc, char *argv[]);
void table_search_mac_fid(int argc, char *argv[]);
void table_del_fid(int argc, char *argv[]);
void table_del_vid(int argc, char *argv[]);
-void table_clear(void);
+void table_clear(int argc, char *argv[]);
/*vlan table*/
void vlan_dump(int argc, char *argv[]);
@@ -88,7 +170,7 @@
/*igmp function*/
void igmp_on(int argc, char *argv[]);
-void igmp_off();
+void igmp_off(int argc, char *argv[]);
void igmp_disable(int argc, char *argv[]);
void igmp_enable(int argc, char *argv[]);
@@ -100,11 +182,11 @@
/*rate control*/
void rate_control(int argc, char *argv[]);
-int ingress_rate_set(int on_off, unsigned int port, unsigned int bw);
-int egress_rate_set(int on_off, int port, int bw);
+void ingress_rate_set(int argc, char *argv[]);
+void egress_rate_set(int argc, char *argv[]);
/*QoS*/
-int qos_sch_select(int argc, char *argv[]);
+void qos_sch_select(int argc, char *argv[]);
void qos_set_base(int argc, char *argv[]);
void qos_wfq_set_weight(int argc, char *argv[]);
void qos_set_portpri(int argc, char *argv[]);
@@ -112,32 +194,32 @@
void qos_pri_mapping_queue(int argc, char *argv[]);
/*flow control*/
-int global_set_mac_fc(int argc, char *argv[]);
-int phy_set_fc(int argc, char *argv[]);
-int phy_set_an(int argc, char *argv[]);
+void global_set_mac_fc(int argc, char *argv[]);
+void phy_set_fc(int argc, char *argv[]);
+void phy_set_an(int argc, char *argv[]);
/* collision pool functions */
-int collision_pool_enable(int argc, char *argv[]);
-void collision_pool_mac_dump();
-void collision_pool_dip_dump();
-void collision_pool_sip_dump();
+void collision_pool_enable(int argc, char *argv[]);
+void collision_pool_mac_dump(int argc, char *argv[]);
+void collision_pool_dip_dump(int argc, char *argv[]);
+void collision_pool_sip_dump(int argc, char *argv[]);
/*pfc functions*/
-int set_mac_pfc(int argc, char *argv[]);
+void set_mac_pfc(int argc, char *argv[]);
void pfc_get_rx_counter(int argc, char *argv[]);
void pfc_get_tx_counter(int argc, char *argv[]);
/*switch reset*/
-int switch_reset(int argc, char *argv[]);
+void switch_reset(int argc, char *argv[]);
/* EEE(802.3az) function */
void eee_enable(int argc, char *argv[]);
void eee_dump(int argc, char *argv[]);
-void read_mib_counters();
-void clear_mib_counters();
-void read_output_queue_counters();
-void read_free_page_counters();
+void read_mib_counters(int argc, char *argv[]);
+void clear_mib_counters(int argc, char *argv[]);
+void read_output_queue_counters(int argc, char *argv[]);
+void read_free_page_counters(int argc, char *argv[]);
void phy_crossover(int argc, char *argv[]);
void exit_free();
diff --git a/recipes-devtools/switch/files/src/switch_fun_an8855.c b/recipes-devtools/switch/files/src/switch_fun_an8855.c
new file mode 100644
index 0000000..e5ec490
--- /dev/null
+++ b/recipes-devtools/switch/files/src/switch_fun_an8855.c
@@ -0,0 +1,1804 @@
+/*
+* switch_fun.c: switch function sets
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include "switch_extend.h"
+#include "switch_netlink.h"
+#include "switch_fun.h"
+#include "switch_fun_an8855.h"
+
+#define MAC_STR "%02X%02X%02X%02X%02X%02X"
+#define MAC2STR(m) (m)[0],(m)[1],(m)[2],(m)[3],(m)[4],(m)[5]
+
+const static C8_T *mac_address_forward_control_string[] = {
+ "Default",
+ "CPU include",
+ "CPU exclude",
+ "CPU only",
+ "Drop"
+};
+
+struct switch_func_s an8855_switch_func = {
+ .pf_table_dump = an8855_table_dump,
+ .pf_table_clear = an8855_table_clear,
+ .pf_switch_reset = an8855_switch_reset,
+ .pf_doArlAging = an8855_doArlAging,
+ .pf_read_mib_counters = an8855_read_mib_counters,
+ .pf_clear_mib_counters = an8855_clear_mib_counters,
+ .pf_read_output_queue_counters = an8855_read_output_queue_counters,
+ .pf_read_free_page_counters = an8855_read_free_page_counters,
+ .pf_rate_control = an8855_rate_control,
+ .pf_igress_rate_set = an8855_ingress_rate_set,
+ .pf_egress_rate_set = an8855_egress_rate_set,
+ .pf_table_add = an8855_table_add,
+ .pf_table_del_fid = an8855_table_del_fid,
+ .pf_table_del_vid = an8855_table_del_vid,
+ .pf_table_search_mac_fid = an8855_table_search_mac_fid,
+ .pf_table_search_mac_vid = an8855_table_search_mac_vid,
+ .pf_global_set_mac_fc = an8855_global_set_mac_fc,
+ .pf_set_mac_pfc = an8855_not_supported,
+ .pf_qos_sch_select = an8855_qos_sch_select,
+ .pf_qos_set_base = an8855_qos_set_base,
+ .pf_qos_wfq_set_weight = an8855_qos_wfq_set_weight,
+ .pf_qos_set_portpri = an8855_qos_set_portpri,
+ .pf_qos_set_dscppri = an8855_qos_set_dscppri,
+ .pf_qos_pri_mapping_queue = an8855_qos_pri_mapping_queue,
+ .pf_doStp = an8855_doStp,
+ .pf_sip_dump = an8855_not_supported,
+ .pf_sip_add = an8855_not_supported,
+ .pf_sip_del = an8855_not_supported,
+ .pf_sip_clear = an8855_not_supported,
+ .pf_dip_dump = an8855_not_supported,
+ .pf_dip_add = an8855_not_supported,
+ .pf_dip_del = an8855_not_supported,
+ .pf_dip_clear = an8855_not_supported,
+ .pf_set_mirror_to = an8855_set_mirror_to,
+ .pf_set_mirror_from = an8855_set_mirror_from,
+ .pf_doMirrorEn = an8855_doMirrorEn,
+ .pf_doMirrorPortBased = an8855_doMirrorPortBased,
+ .pf_acl_dip_add = an8855_not_supported,
+ .pf_acl_dip_modify = an8855_not_supported,
+ .pf_acl_dip_pppoe = an8855_not_supported,
+ .pf_acl_dip_trtcm = an8855_not_supported,
+ .pf_acl_dip_meter = an8855_not_supported,
+ .pf_acl_mac_add = an8855_not_supported,
+ .pf_acl_ethertype = an8855_not_supported,
+ .pf_acl_sp_add = an8855_not_supported,
+ .pf_acl_l4_add = an8855_not_supported,
+ .pf_acl_port_enable = an8855_not_supported,
+ .pf_acl_table_add = an8855_not_supported,
+ .pf_acl_mask_table_add = an8855_not_supported,
+ .pf_acl_rule_table_add = an8855_not_supported,
+ .pf_acl_rate_table_add = an8855_not_supported,
+ .pf_vlan_dump = an8855_vlan_dump,
+ .pf_vlan_set = an8855_vlan_set,
+ .pf_vlan_clear = an8855_vlan_clear,
+ .pf_doVlanSetVid = an8855_doVlanSetVid,
+ .pf_doVlanSetPvid = an8855_doVlanSetPvid,
+ .pf_doVlanSetAccFrm = an8855_doVlanSetAccFrm,
+ .pf_doVlanSetPortAttr = an8855_doVlanSetPortAttr,
+ .pf_doVlanSetPortMode = an8855_doVlanSetPortMode,
+ .pf_doVlanSetEgressTagPCR = an8855_doVlanSetEgressTagPCR,
+ .pf_doVlanSetEgressTagPVC = an8855_doVlanSetEgressTagPVC,
+ .pf_igmp_on = an8855_not_supported,
+ .pf_igmp_off = an8855_not_supported,
+ .pf_igmp_enable = an8855_not_supported,
+ .pf_igmp_disable = an8855_not_supported,
+ .pf_collision_pool_enable = an8855_not_supported,
+ .pf_collision_pool_mac_dump = an8855_not_supported,
+ .pf_collision_pool_dip_dump = an8855_not_supported,
+ .pf_collision_pool_sip_dump = an8855_not_supported,
+ .pf_pfc_get_rx_counter = an8855_not_supported,
+ .pf_pfc_get_tx_counter = an8855_not_supported,
+ .pf_eee_enable = an8855_eee_enable,
+ .pf_eee_dump = an8855_eee_dump,
+};
+
+AIR_ERROR_NO_T
+an8855_reg_read(const UI32_T unit, const UI32_T addr_offset, UI32_T * ptr_data)
+{
+ int ret;
+
+ ret = reg_read(addr_offset, ptr_data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+an8855_reg_write(const UI32_T unit, const UI32_T addr_offset, const UI32_T data)
+{
+ int ret;
+
+ ret = reg_write(addr_offset, data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+an8855_phy_cl22_read(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset, UI32_T * ptr_data)
+{
+ int ret;
+
+ ret = mii_mgr_read(port_id, addr_offset, ptr_data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+an8855_phy_cl22_write(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset, const UI32_T data)
+{
+ int ret;
+
+ ret = mii_mgr_write(port_id, addr_offset, data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+an8855_phy_cl45_read(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset, UI32_T * ptr_data)
+{
+ int ret;
+
+ ret = mii_mgr_c45_read(port_id, dev_type, addr_offset, ptr_data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+AIR_ERROR_NO_T
+an8855_phy_cl45_write(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset, const UI32_T data)
+{
+ int ret;
+
+ ret = mii_mgr_c45_write(port_id, dev_type, addr_offset, data);
+ if (ret < 0) {
+ return AIR_E_OTHERS;
+ }
+
+ return AIR_E_OK;
+}
+
+void an8855_not_supported(int argc, char *argv[])
+{
+ printf("Cmd not supported by AN8855.\n");
+}
+
+static AIR_ERROR_NO_T
+_printMacEntry(AIR_MAC_ENTRY_T * mt, UI32_T age_unit, UI8_T count, UI8_T title)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ I32_T i = 0, j = 0;
+ UI8_T first = 0;
+ UI8_T find = 0;
+ if (title) {
+ printf("%-6s%-15s%-5s%-5s%-5s%-10s%-10s%-6s\n",
+ "unit",
+ "mac",
+ "ivl", "vid", "fid", "age-time", "forward", "port");
+ return ret;
+ }
+ for (i = 0; i < count; i++) {
+ printf("%-6d", age_unit);
+ printf(MAC_STR, MAC2STR(mt[i].mac));
+ printf("...");
+ if (mt[i].flags & AIR_L2_MAC_ENTRY_FLAGS_IVL) {
+ printf("%-3s..", "ivl");
+ printf("%-5d", mt[i].cvid);
+ printf("%-5s", ".....");
+ } else {
+ printf("%-3s..", "svl");
+ printf("%-5s", ".....");
+ printf("%-5d", mt[i].fid);
+ }
+ if (mt[i].flags & AIR_L2_MAC_ENTRY_FLAGS_STATIC) {
+ printf("%-7s.", "static");
+ } else {
+ printf("%d sec..", mt[i].timer);
+ }
+ printf("%-10s",
+ mac_address_forward_control_string[mt[i].sa_fwd]);
+ first = 0;
+ find = 0;
+ for (j = (AIR_MAX_NUM_OF_PORTS - 1); j >= 0; j--) {
+ if ((mt[i].port_bitmap[0]) & (1 << j)) {
+ first = j;
+ find = 1;
+ break;
+ }
+ }
+ if (find) {
+ for (j = 0; j < AIR_MAX_NUM_OF_PORTS; j++) {
+ if ((mt[i].port_bitmap[0]) & (1 << j)) {
+ if (j == first)
+ printf("%-2d", j);
+ else
+ printf("%-2d,", j);
+ }
+ }
+ } else
+ printf("no dst port");
+ printf("\n");
+ }
+ return ret;
+}
+
+static AIR_ERROR_NO_T _str2mac(C8_T * str, C8_T * mac)
+{
+ UI32_T i;
+ C8_T tmpstr[3];
+
+ for (i = 0; i < 6; i++) {
+ strncpy(tmpstr, str + (i * 2), 2);
+ tmpstr[2] = '\0';
+ mac[i] = strtoul(tmpstr, NULL, 16);
+ }
+
+ return AIR_E_OK;
+}
+
+static void an8855_table_dump_internal(int type)
+{
+ unsigned char count = 0;
+ unsigned int total_count = 0;
+ unsigned int bucket_size = 0;
+ AIR_ERROR_NO_T ret = 0;
+ AIR_MAC_ENTRY_T *ptr_mt;
+
+ bucket_size = AIR_L2_MAC_SET_NUM;
+ ptr_mt = malloc(sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ if (ptr_mt == NULL) {
+ printf("Error, malloc fail\n\r");
+ return;
+ }
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ _printMacEntry(ptr_mt, 0, count, TRUE);
+ /* get 1st entry of MAC table */
+ ret = air_l2_getMacAddr(0, &count, ptr_mt);
+ switch (ret) {
+ case AIR_E_ENTRY_NOT_FOUND:
+ printf("Not Found!\n");
+ goto DUMP_ERROR;
+ case AIR_E_TIMEOUT:
+ printf("Time Out!\n");
+ goto DUMP_ERROR;
+ case AIR_E_BAD_PARAMETER:
+ printf("Bad Parameter!\n");
+ goto DUMP_ERROR;
+ default:
+ break;
+ }
+ total_count += count;
+ _printMacEntry(ptr_mt, 0, count, FALSE);
+ /* get other entries of MAC table */
+ while (1) {
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T) * bucket_size);
+ ret = air_l2_getNextMacAddr(0, &count, ptr_mt);
+ if (AIR_E_OK != ret) {
+ break;
+ }
+ total_count += count;
+ _printMacEntry(ptr_mt, 0, count, FALSE);
+ }
+ switch (ret) {
+ case AIR_E_TIMEOUT:
+ printf("Time Out!\n");
+ break;
+ case AIR_E_BAD_PARAMETER:
+ printf("Bad Parameter!\n");
+ break;
+ default:
+ printf("Found %u %s\n", total_count,
+ (total_count > 1) ? "entries" : "entry");
+ break;
+ }
+
+DUMP_ERROR:
+ free(ptr_mt);
+ return;
+}
+
+void an8855_table_dump(int argc, char *argv[])
+{
+ an8855_table_dump_internal(GENERAL_TABLE);
+}
+
+void an8855_table_add(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_MAC_ENTRY_T mt;
+ unsigned int i = 0;
+ unsigned int age_time = 0;
+ memset(&mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ if (!argv[2] || strlen(argv[2]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+ ret = _str2mac(argv[2], (C8_T *) mt.mac);
+ if (ret != AIR_E_OK) {
+ printf("Unrecognized command.\n");
+ return;
+ }
+ if (argc > 4) {
+ mt.cvid = strtoul(argv[4], NULL, 0);
+ if (4095 < mt.cvid) {
+ printf("wrong vid range, should be within 0~4095\n");
+ return;
+ }
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ }
+ if (!argv[3] || strlen(argv[3]) != 6) {
+ /*bit0~5, each map port0~port5 */
+ printf("portmap format error, should be of length 6\n");
+ return;
+ }
+ for (i = 0; i < 6; i++) {
+ if (argv[3][i] != '0' && argv[3][i] != '1') {
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ mt.port_bitmap[0] |= ((argv[3][i] - '0') << i);
+ }
+ if (argc > 5) {
+ age_time = strtoul(argv[5], NULL, 0);
+ if (age_time < 1 || 1000000 < age_time) {
+ printf("wrong age range, should be within 1~1000000\n");
+ return;
+ }
+ } else {
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_STATIC;
+ }
+ mt.sa_fwd = AIR_L2_FWD_CTRL_DEFAULT;
+ ret = air_l2_addMacAddr(0, &mt);
+ if (ret == AIR_E_OK) {
+ printf("add mac address done.\n");
+ usleep(5000);
+ if (!(mt.flags & AIR_L2_MAC_ENTRY_FLAGS_STATIC)) {
+ ret = air_l2_setMacAddrAgeOut(0, age_time);
+ if (ret == AIR_E_OK) {
+ printf("set age out time done.\n");
+ } else {
+ printf("set age out time fail.\n");
+ }
+ }
+ } else {
+ printf("add mac address fail.\n");
+ }
+ return;
+}
+
+void an8855_table_search_mac_vid(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ unsigned char count = 0;
+ char tmpstr[9];
+ AIR_MAC_ENTRY_T *ptr_mt;
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+
+ ptr_mt = malloc(sizeof(AIR_MAC_ENTRY_T));
+ if (NULL == ptr_mt) {
+ printf("Error, malloc fail\n");
+ return;
+ }
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ ret = _str2mac(argv[3], (C8_T *) ptr_mt->mac);
+ if (ret != AIR_E_OK) {
+ printf("Unrecognized command.\n");
+ free(ptr_mt);
+ return;
+ }
+
+ /* get mac entry by MAC address & vid */
+ ptr_mt->cvid = strtoul(argv[5], NULL, 0);
+ ptr_mt->flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ if (ptr_mt->cvid > 4095) {
+ printf("wrong vid range, should be within 0~4095\n");
+ free(ptr_mt);
+ return;
+ }
+
+ ret = air_l2_getMacAddr(0, &count, ptr_mt);
+ if (ret == AIR_E_OK) {
+ _printMacEntry(ptr_mt, 0, 1, TRUE);
+ _printMacEntry(ptr_mt, 0, 1, FALSE);
+ } else {
+ printf("\n Not found!\n");
+ }
+ free(ptr_mt);
+ return;
+}
+
+void an8855_table_search_mac_fid(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ unsigned char count = 0;
+ char tmpstr[9];
+ AIR_MAC_ENTRY_T *ptr_mt;
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+
+ ptr_mt = malloc(sizeof(AIR_MAC_ENTRY_T));
+ if (NULL == ptr_mt) {
+ printf("Error, malloc fail\n");
+ return;
+ }
+ memset(ptr_mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ ret = _str2mac(argv[3], (C8_T *) ptr_mt->mac);
+ if (ret != AIR_E_OK) {
+ printf("Unrecognized command.\n");
+ free(ptr_mt);
+ return;
+ }
+
+ /* get mac entry by MAC address & fid */
+ ptr_mt->fid = strtoul(argv[5], NULL, 0);
+ if (ptr_mt->fid > 7) {
+ printf("wrong fid range, should be within 0~7\n");
+ free(ptr_mt);
+ return;
+ }
+
+ ret = air_l2_getMacAddr(0, &count, ptr_mt);
+ if (ret == AIR_E_OK) {
+ _printMacEntry(ptr_mt, 0, 1, TRUE);
+ _printMacEntry(ptr_mt, 0, 1, FALSE);
+ } else {
+ printf("\n Not found!\n");
+ }
+ free(ptr_mt);
+ return;
+}
+
+void an8855_table_del_fid(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ char tmpstr[9];
+ AIR_MAC_ENTRY_T mt;
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+
+ memset(&mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ ret = _str2mac(argv[3], (C8_T *) mt.mac);
+ if (ret != AIR_E_OK) {
+ printf("Unrecognized command.\n");
+ return;
+ }
+
+ /* get mac entry by MAC address & fid */
+ mt.fid = strtoul(argv[5], NULL, 0);
+ if (mt.fid > 7) {
+ printf("wrong fid range, should be within 0~7\n");
+ return;
+ }
+
+ ret = air_l2_delMacAddr(0, &mt);
+ if (ret == AIR_E_OK) {
+ printf("Done.\n");
+ } else {
+ printf("Fail.\n");
+ }
+ return;
+}
+
+void an8855_table_del_vid(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ char tmpstr[9];
+ AIR_MAC_ENTRY_T mt;
+
+ if (!argv[3] || strlen(argv[3]) != 12) {
+ printf("MAC address format error, should be of length 12\n");
+ return;
+ }
+
+ memset(&mt, 0, sizeof(AIR_MAC_ENTRY_T));
+ ret = _str2mac(argv[3], (C8_T *) mt.mac);
+ if (ret != AIR_E_OK) {
+ printf("Unrecognized command.\n");
+ return;
+ }
+
+ /* get mac entry by MAC address & vid */
+ mt.cvid = strtoul(argv[5], NULL, 0);
+ mt.flags |= AIR_L2_MAC_ENTRY_FLAGS_IVL;
+ if (mt.cvid > 4095) {
+ printf("wrong vid range, should be within 0~4095\n");
+ return;
+ }
+
+ ret = air_l2_delMacAddr(0, &mt);
+ if (ret == AIR_E_OK) {
+ printf("Done.\n");
+ } else {
+ printf("Fail.\n");
+ }
+ return;
+}
+
+void an8855_table_clear(int argc, char *argv[])
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+
+ ret = air_l2_clearMacAddr(0);
+ if (ret == AIR_E_OK)
+ printf("Clear MAC Address Table Done.\n");
+ else
+ printf("Clear MAC Address Table Fail.\n");
+ return;
+}
+
+void an8855_set_mirror_to(int argc, char *argv[])
+{
+ int idx;
+ AIR_MIR_SESSION_T session = { 0 };
+
+ idx = strtoul(argv[3], NULL, 0);
+ if (idx < 0 || MAX_PORT < idx) {
+ printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+ return;
+ }
+
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+
+ air_mir_getSession(0, 0, &session);
+ session.dst_port = idx;
+ session.flags |= AIR_MIR_SESSION_FLAGS_ENABLE;
+ air_mir_addSession(0, 0, &session);
+}
+
+void an8855_set_mirror_from(int argc, char *argv[])
+{
+ int idx = 0, mirror = 0;
+ AIR_MIR_SESSION_T session = { 0 };
+
+ idx = _strtoul(argv[3], NULL, 0);
+ mirror = _strtoul(argv[4], NULL, 0);
+
+ if (idx < 0 || MAX_PORT < idx) {
+ printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+ return;
+ }
+
+ if (mirror < 0 || 3 < mirror) {
+ printf("wrong mirror setting, should be within 0~3\n");
+ return;
+ }
+
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+
+ if (mirror & 0x1) { // rx enable
+ session.src_port = idx;
+ air_mir_getMirrorPort(0, 0, &session);
+
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ session.src_port = idx;
+ air_mir_setMirrorPort(0, 0, &session);
+ }
+
+ if (mirror & 0x2) { //tx enable
+ session.src_port = idx;
+ air_mir_getMirrorPort(0, 0, &session);
+
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ session.src_port = idx;
+ air_mir_setMirrorPort(0, 0, &session);
+ }
+}
+
+void an8855_vlan_dump(int argc, char *argv[])
+{
+ AIR_VLAN_ENTRY_T vlan_entry = { 0 };
+ unsigned int i;
+ int eg_tag = 0;
+
+ if (argc == 4) {
+ if (!strncmp(argv[3], "egtag", 6))
+ eg_tag = 1;
+ }
+
+ if (eg_tag)
+ printf
+ (" vid fid portmap s-tag\teg_tag(0:untagged 2:tagged)\n");
+ else
+ printf(" vid fid portmap s-tag\n");
+
+ for (i = 1; i < 4096; i++) {
+ _air_vlan_readEntry(0, i, &vlan_entry);
+
+ if (vlan_entry.valid) {
+ printf(" %4d ", i);
+ printf(" %2d ", vlan_entry.vlan_entry_format.fid);
+ printf(" %c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0000001) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0000010) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0000100) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0001000) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0010000) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b0100000) ? '1' :
+ '-');
+ printf("%c",
+ (vlan_entry.
+ vlan_entry_format.port_mem & 0b1000000) ? '1' :
+ '-');
+ printf(" %4d", vlan_entry.vlan_entry_format.eg_ctrl);
+ if (eg_tag) {
+ printf("\t");
+ if (vlan_entry.vlan_entry_format.eg_con
+ && vlan_entry.
+ vlan_entry_format.eg_ctrl_en) {
+ /* VTAG_EN=1 and EG_CON=1 */
+ printf("CONSISTENT");
+ } else if (vlan_entry.
+ vlan_entry_format.eg_ctrl_en) {
+ /* VTAG_EN=1 */
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 0)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 2)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 4)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 6)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 8)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 10)
+ & 0x3);
+ printf("%d",
+ (vlan_entry.
+ vlan_entry_format.eg_ctrl >> 12)
+ & 0x3);
+ } else {
+ /* VTAG_EN=0 */
+ printf("DISABLED");
+ }
+ }
+ printf("\n");
+ } else {
+ /*print 16 vid for reference information */
+ if (i <= 16) {
+ printf(" %4d ", i);
+ printf(" %2d ",
+ vlan_entry.vlan_entry_format.fid);
+ printf(" invalid\n");
+ }
+ }
+ }
+}
+
+void an8855_vlan_clear(int argc, char *argv[])
+{
+ air_vlan_destroyAll(0, 0);
+}
+
+void an8855_vlan_set(int argc, char *argv[])
+{
+ unsigned int vlan_mem = 0;
+ int i, vid, fid;
+ int stag = 0;
+ unsigned long eg_con = 0;
+ unsigned int eg_tag = 0;
+ AIR_VLAN_ENTRY_T vlan_entry = { 0 };
+
+ if (argc < 5) {
+ printf("insufficient arguments!\n");
+ return;
+ }
+
+ fid = strtoul(argv[3], NULL, 0);
+ if (fid < 0 || fid > 7) {
+ printf("wrong filtering db id range, should be within 0~7\n");
+ return;
+ }
+
+ vid = strtoul(argv[4], NULL, 0);
+ if (vid < 0 || MAX_VID_VALUE < vid) {
+ printf("wrong vlan id range, should be within 0~4095\n");
+ return;
+ }
+
+ if (strlen(argv[5]) != SWITCH_MAX_PORT) {
+ printf("portmap format error, should be of length %d\n",
+ SWITCH_MAX_PORT);
+ return;
+ }
+
+ vlan_mem = 0;
+ for (i = 0; i < SWITCH_MAX_PORT; i++) {
+ if (argv[5][i] != '0' && argv[5][i] != '1') {
+ printf
+ ("portmap format error, should be of combination of 0 or 1\n");
+ return;
+ }
+ vlan_mem += (argv[5][i] - '0') * (1 << i);
+ }
+
+ /* VLAN stag */
+ if (argc > 6) {
+ stag = strtoul(argv[6], NULL, 16);
+ if (stag < 0 || 0xfff < stag) {
+ printf
+ ("wrong stag id range, should be within 0~4095\n");
+ return;
+ }
+ }
+
+ /* set vlan member */
+ vlan_entry.vlan_entry_format.port_mem = vlan_mem;
+ vlan_entry.vlan_entry_format.ivl = 1;
+ vlan_entry.vlan_entry_format.stag = stag;
+ vlan_entry.valid = 1;
+
+ if (argc > 7) {
+ eg_con = strtoul(argv[7], NULL, 2);
+ eg_con = ! !eg_con;
+ vlan_entry.vlan_entry_format.eg_con = eg_con;
+ vlan_entry.vlan_entry_format.eg_ctrl_en = 1;
+ }
+
+ if (argc > 8 && !eg_con) {
+ if (strlen(argv[8]) != SWITCH_MAX_PORT) {
+ printf
+ ("egtag portmap format error, should be of length %d\n",
+ SWITCH_MAX_PORT);
+ return;
+ }
+
+ for (i = 0; i < SWITCH_MAX_PORT; i++) {
+ if (argv[8][i] < '0' || argv[8][i] > '3') {
+ printf
+ ("egtag portmap format error, should be of combination of 0 or 3\n");
+ return;
+ }
+ eg_tag |= (argv[8][i] - '0') << (i * 2);
+ }
+
+ vlan_entry.vlan_entry_format.eg_ctrl_en = 1;
+ vlan_entry.vlan_entry_format.eg_ctrl = eg_tag;
+ }
+
+ _air_vlan_writeEntry(0, vid, &vlan_entry);
+}
+
+void an8855_switch_reset(int argc, char *argv[])
+{
+ air_switch_reset(0);
+}
+
+void an8855_global_set_mac_fc(int argc, char *argv[])
+{
+ unsigned char enable = 0;
+ unsigned int reg = 0, value = 0;
+
+ enable = _strtoul(argv[3], NULL, 10);
+ printf("enable: %d\n", enable);
+
+ /* Check the input parameters is right or not. */
+ if (enable > 1) {
+ printf(HELP_MACCTL_FC);
+ return;
+ }
+ reg_read(0x10207e04, &value);
+ value &= (~(1 << 31));
+ value |= (enable << 31);
+ reg_write(0x10207e04, value);
+} /*end mac_set_fc */
+
+void an8855_qos_sch_select(int argc, char *argv[])
+{
+ unsigned char port, queue;
+ unsigned char type = 0;
+ unsigned int value, reg;
+
+ if (argc < 7)
+ return;
+
+ port = _strtoul(argv[3], NULL, 10);
+ queue = _strtoul(argv[4], NULL, 10);
+ type = _strtoul(argv[6], NULL, 10);
+
+ if (port > 6 || queue > 7) {
+ printf("\n Illegal input parameters\n");
+ return;
+ }
+
+ if ((type != 0 && type != 1 && type != 2)) {
+ printf(HELP_QOS_TYPE);
+ return;
+ }
+
+ printf("\r\nswitch qos type: %d.\n", type);
+
+ if (type == 0) {
+ air_qos_setScheduleAlgo(0, port, queue, AIR_QOS_SCH_MODE_WRR,
+ 1);
+ } else if (type == 1) {
+ air_qos_setScheduleAlgo(0, port, queue, AIR_QOS_SCH_MODE_SP, 1);
+ } else {
+ air_qos_setScheduleAlgo(0, port, queue, AIR_QOS_SCH_MODE_WFQ,
+ 1);
+ }
+}
+
+void an8855_get_upw(unsigned int *value, unsigned char base)
+{
+ *value &= (~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+ (0x7 << 16) | (0x7 << 20)));
+ switch (base) {
+ case 0: /* port-based 0x2x40[18:16] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x7 << 16) | (0x2 << 20));
+ break;
+ case 1: /* tagged-based 0x2x40[10:8] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 2: /* DSCP-based 0x2x40[14:12] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x7 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 3: /* acl-based 0x2x40[2:0] */
+ *value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ case 4: /* arl-based 0x2x40[22:20] */
+ *value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x7 << 20));
+ break;
+ case 5: /* stag-based 0x2x40[6:4] */
+ *value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
+ (0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+ break;
+ default:
+ break;
+ }
+}
+
+void an8855_qos_set_base(int argc, char *argv[])
+{
+ unsigned char base = 0;
+ unsigned char port;
+ unsigned int value;
+
+ if (argc < 5)
+ return;
+
+ port = _strtoul(argv[3], NULL, 10);
+ base = _strtoul(argv[4], NULL, 10);
+
+ if (base > 6) {
+ printf(HELP_QOS_BASE);
+ return;
+ }
+
+ if (port > 6) {
+ printf("Illegal port index:%d\n", port);
+ return;
+ }
+
+ printf("\r\nswitch qos base : %d. (port-based:0, tag-based:1,\
+ dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n", base);
+ reg_read(0x10208030 + 0x200 * port, &value);
+ an8855_get_upw(&value, base);
+ reg_write(0x10208030 + 0x200 * port, value);
+}
+
+void an8855_qos_wfq_set_weight(int argc, char *argv[])
+{
+ int port, weight[8], i;
+ unsigned char queue;
+ unsigned int reg = 0, value = 0;
+
+ port = _strtoul(argv[3], NULL, 10);
+
+ for (i = 0; i < 8; i++) {
+ weight[i] = _strtoul(argv[i + 4], NULL, 10);
+ }
+
+ /* MT7530 total 7 port */
+ if (port < 0 || port > 6) {
+ printf(HELP_QOS_PORT_WEIGHT);
+ return;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (weight[i] < 1 || weight[i] > 16) {
+ printf(HELP_QOS_PORT_WEIGHT);
+ return;
+ }
+ }
+ printf("port: %x, q0: %x, q1: %x, q2: %x, q3: %x, \
+ q4: %x, q5: %x, q6: %x, q7: %x\n", port, weight[0], weight[1], weight[2], weight[3], weight[4], weight[5], weight[6], weight[7]);
+
+ for (queue = 0; queue < 8; queue++) {
+ air_qos_setScheduleAlgo(0, port, queue, AIR_QOS_SCH_MODE_WFQ,
+ weight[queue]);
+ }
+}
+
+void an8855_qos_set_portpri(int argc, char *argv[])
+{
+ unsigned char port = 0, prio = 0;
+ unsigned int value = 0;
+
+ port = _strtoul(argv[3], NULL, 10);
+ prio = _strtoul(argv[4], NULL, 10);
+
+ if (port >= 7 || prio > 7) {
+ printf(HELP_QOS_PORT_PRIO);
+ return;
+ }
+
+ air_qos_setPortPriority(0, port, prio);
+}
+
+void an8855_qos_set_dscppri(int argc, char *argv[])
+{
+ unsigned char prio = 0, dscp = 0, pim_n = 0, pim_offset = 0;
+ unsigned int reg = 0, value = 0;
+
+ dscp = _strtoul(argv[3], NULL, 10);
+ prio = _strtoul(argv[4], NULL, 10);
+
+ if (dscp > 63 || prio > 7) {
+ printf(HELP_QOS_DSCP_PRIO);
+ return;
+ }
+
+ air_qos_setDscp2Pri(0, dscp, prio);
+}
+
+void an8855_qos_pri_mapping_queue(int argc, char *argv[])
+{
+ unsigned char prio = 0, queue = 0, pem_n = 0, port = 0;
+ unsigned int reg = 0, value = 0;
+
+ if (argc < 6)
+ return;
+
+ port = _strtoul(argv[3], NULL, 10);
+ prio = _strtoul(argv[4], NULL, 10);
+ queue = _strtoul(argv[5], NULL, 10);
+
+ if (prio > 7 || queue > 7) {
+ printf(HELP_QOS_PRIO_QMAP);
+ return;
+ }
+
+ air_qos_setPri2Queue(0, prio, queue);
+}
+
+void an8855_doVlanSetPvid(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned short pvid = 0;
+
+ port = _strtoul(argv[3], NULL, 10);
+ pvid = _strtoul(argv[4], NULL, 10);
+ /*Check the input parameters is right or not. */
+ if ((port >= SWITCH_MAX_PORT) || (pvid > MAX_VID_VALUE)) {
+ printf(HELP_VLAN_PVID);
+ return;
+ }
+
+ air_vlan_setPortPVID(0, port, pvid);
+
+ printf("port:%d pvid:%d,vlancap: max_port:%d maxvid:%d\r\n",
+ port, pvid, SWITCH_MAX_PORT, MAX_VID_VALUE);
+} /*end doVlanSetPvid */
+
+void an8855_doVlanSetVid(int argc, char *argv[])
+{
+ unsigned char index = 0;
+ unsigned char active = 0;
+ unsigned char portMap = 0;
+ unsigned char tagPortMap = 0;
+ unsigned short vid = 0;
+
+ unsigned char ivl_en = 0;
+ unsigned char fid = 0;
+ unsigned short stag = 0;
+ int i = 0;
+ AIR_VLAN_ENTRY_T vlan_entry = { 0 };
+
+ index = _strtoul(argv[3], NULL, 10);
+ active = _strtoul(argv[4], NULL, 10);
+ vid = _strtoul(argv[5], NULL, 10);
+
+ /*Check the input parameters is right or not. */
+ if ((index >= MAX_VLAN_RULE) || (vid >= 4096) || (active > ACTIVED)) {
+ printf(HELP_VLAN_VID);
+ return;
+ }
+
+ /*CPU Port is always the membership */
+ portMap = _strtoul(argv[6], NULL, 10);
+ tagPortMap = _strtoul(argv[7], NULL, 10);
+
+ printf("subcmd parameter argc = %d\r\n", argc);
+ if (argc >= 9) {
+ ivl_en = _strtoul(argv[8], NULL, 10);
+ if (argc >= 10) {
+ fid = _strtoul(argv[9], NULL, 10);
+ if (argc >= 11)
+ stag = _strtoul(argv[10], NULL, 10);
+ }
+ }
+
+ printf("index: %x, active: %x, vid: %x, portMap: %x, \
+ tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n", index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
+
+ vlan_entry.valid = ! !active;
+ vlan_entry.vlan_entry_format.port_mem = portMap;
+ /* Total 6 ports */
+ for (i = 0; i < SWITCH_MAX_PORT; i++) {
+ if (tagPortMap & (1 << i))
+ vlan_entry.vlan_entry_format.eg_ctrl |= 0x2 << (i * 2);
+ }
+ vlan_entry.vlan_entry_format.ivl = ! !ivl_en;
+ vlan_entry.vlan_entry_format.fid = fid;
+ vlan_entry.vlan_entry_format.stag = stag;
+
+ _air_vlan_writeEntry(0, vid, &vlan_entry);
+
+ printf("index:%d active:%d vid:%d\r\n", index, active, vid);
+} /*end doVlanSetVid */
+
+void an8855_doVlanSetAccFrm(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char type = 0;
+ AIR_VLAN_ACCEPT_FRAME_TYPE_T type_t = AIR_VLAN_ACCEPT_FRAME_TYPE_ALL;
+
+ port = _strtoul(argv[3], NULL, 10);
+ type = _strtoul(argv[4], NULL, 10);
+
+ printf("port: %d, type: %d\n", port, type);
+
+ /*Check the input parameters is right or not. */
+ if ((port > SWITCH_MAX_PORT) || (type > REG_PVC_ACC_FRM_RELMASK)) {
+ printf(HELP_VLAN_ACC_FRM);
+ return;
+ }
+
+ type_t = (AIR_VLAN_ACCEPT_FRAME_TYPE_T) type;
+ air_vlan_setPortAcceptFrameType(0, port, type_t);
+} /*end doVlanSetAccFrm */
+
+void an8855_doVlanSetPortAttr(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char attr = 0;
+ AIR_VLAN_PORT_ATTR_T attr_t = AIR_VLAN_PORT_ATTR_USER_PORT;
+
+ port = _strtoul(argv[3], NULL, 10);
+ attr = _strtoul(argv[4], NULL, 10);
+
+ printf("port: %x, attr: %x\n", port, attr);
+
+ /*Check the input parameters is right or not. */
+ if (port > SWITCH_MAX_PORT || attr > 3) {
+ printf(HELP_VLAN_PORT_ATTR);
+ return;
+ }
+
+ attr_t = (AIR_VLAN_PORT_ATTR_T) attr;
+ air_vlan_setPortAttr(0, port, attr_t);
+}
+
+void an8855_doVlanSetPortMode(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char mode = 0;
+ AIR_PORT_VLAN_MODE_T mode_t = AIR_PORT_VLAN_MODE_PORT_MATRIX;
+
+ port = _strtoul(argv[3], NULL, 10);
+ mode = _strtoul(argv[4], NULL, 10);
+ printf("port: %x, mode: %x\n", port, mode);
+
+ /*Check the input parameters is right or not. */
+ if (port > SWITCH_MAX_PORT || mode > 3) {
+ printf(HELP_VLAN_PORT_MODE);
+ return;
+ }
+
+ mode_t = (AIR_PORT_VLAN_MODE_T) mode;
+ air_port_setVlanMode(0, port, mode_t);
+}
+
+void an8855_doVlanSetEgressTagPCR(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char eg_tag = 0;
+ AIR_PORT_EGS_TAG_ATTR_T eg_tag_t = AIR_PORT_EGS_TAG_ATTR_UNTAGGED;
+
+ port = _strtoul(argv[3], NULL, 10);
+ eg_tag = _strtoul(argv[4], NULL, 10);
+
+ printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+ /*Check the input parameters is right or not. */
+ if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PCR_EG_TAG_RELMASK)) {
+ printf(HELP_VLAN_EGRESS_TAG_PCR);
+ return;
+ }
+
+ eg_tag_t = (AIR_PORT_EGS_TAG_ATTR_T) eg_tag;
+ air_vlan_setPortEgsTagAttr(0, port, eg_tag_t);
+} /*end doVlanSetEgressTagPCR */
+
+void an8855_doVlanSetEgressTagPVC(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char eg_tag = 0;
+ AIR_IGR_PORT_EG_TAG_ATTR_T eg_tag_t = 0;
+
+ port = _strtoul(argv[3], NULL, 10);
+ eg_tag = _strtoul(argv[4], NULL, 10);
+
+ printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+ /*Check the input parameters is right or not. */
+ if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PVC_EG_TAG_RELMASK)) {
+ printf(HELP_VLAN_EGRESS_TAG_PVC);
+ return;
+ }
+
+ eg_tag_t = (AIR_IGR_PORT_EG_TAG_ATTR_T) eg_tag;
+ air_vlan_setIgrPortTagAttr(0, port, eg_tag_t);
+} /*end doVlanSetEgressTagPVC */
+
+void an8855_doArlAging(int argc, char *argv[])
+{
+ unsigned char aging_en = 0;
+ unsigned int time = 0, port = 0;
+
+ aging_en = _strtoul(argv[3], NULL, 10);
+ time = _strtoul(argv[4], NULL, 10);
+ printf("aging_en: %x, aging time: %x\n", aging_en, time);
+
+ /*Check the input parameters is right or not. */
+ if ((aging_en != 0 && aging_en != 1) || (time <= 0 || time > 65536)) {
+ printf(HELP_ARL_AGING);
+ return;
+ }
+
+ for (port = 0; port < 6; port++) {
+ air_l2_setAgeEnable(0, port, aging_en);
+ }
+
+ air_l2_setMacAddrAgeOut(0, time);
+}
+
+void an8855_doMirrorEn(int argc, char *argv[])
+{
+ unsigned char mirror_en = 0;
+ unsigned char mirror_port = 0;
+ AIR_MIR_SESSION_T session = { 0 };
+
+ mirror_en = _strtoul(argv[3], NULL, 10);
+ mirror_port = _strtoul(argv[4], NULL, 10);
+
+ printf("mirror_en: %d, mirror_port: %d\n", mirror_en, mirror_port);
+
+ /*Check the input parameters is right or not. */
+ if ((mirror_en > 1) || (mirror_port > REG_CFC_MIRROR_PORT_RELMASK)) {
+ printf(HELP_MIRROR_EN);
+ return;
+ }
+
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+
+ if (mirror_en) {
+ session.dst_port = mirror_port;
+ session.flags |= AIR_MIR_SESSION_FLAGS_ENABLE;
+ air_mir_addSession(0, 0, &session);
+ } else {
+ air_mir_delSession(0, 0);
+ }
+
+ air_mir_setSessionAdminMode(0, 0, (int)mirror_en);
+} /*end doMirrorEn */
+
+void an8855_doMirrorPortBased(int argc, char *argv[])
+{
+ unsigned char port = 0, port_tx_mir = 0, port_rx_mir = 0, vlan_mis =
+ 0, acl_mir = 0, igmp_mir = 0;
+ unsigned int reg = 0, value = 0;
+ AIR_MIR_SESSION_T session = { 0 };
+
+ port = _strtoul(argv[3], NULL, 10);
+ port_tx_mir = _strtoul(argv[4], NULL, 10);
+ port_rx_mir = _strtoul(argv[5], NULL, 10);
+ acl_mir = _strtoul(argv[6], NULL, 10);
+ vlan_mis = _strtoul(argv[7], NULL, 10);
+ igmp_mir = _strtoul(argv[8], NULL, 10);
+
+ printf
+ ("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n",
+ port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
+
+ /*Check the input parameters is right or not. */
+ //if((port >= vlanCap->max_port_no) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)){
+ if ((port >= SWITCH_MAX_PORT) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)) { // also allow CPU port (port6)
+ printf(HELP_MIRROR_PORTBASED);
+ return;
+ }
+
+ memset(&session, 0, sizeof(AIR_MIR_SESSION_T));
+ air_mir_getSession(0, 0, &session);
+ session.src_port = port;
+
+ if (port_tx_mir)
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_TX;
+ else
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_TX;
+
+ if (port_rx_mir)
+ session.flags |= AIR_MIR_SESSION_FLAGS_DIR_RX;
+ else
+ session.flags &= ~AIR_MIR_SESSION_FLAGS_DIR_RX;
+
+ air_mir_setMirrorPort(0, 0, &session);
+
+ /*
+
+ not support acl/vlan/igmp mismatch
+
+ */
+} /*end doMirrorPortBased */
+
+void an8855_doStp(int argc, char *argv[])
+{
+ unsigned char port = 0;
+ unsigned char fid = 0;
+ unsigned char state = 0;
+ unsigned int value = 0;
+ unsigned int reg = 0;
+
+ port = _strtoul(argv[2], NULL, 10);
+ fid = _strtoul(argv[3], NULL, 10);
+ state = _strtoul(argv[4], NULL, 10);
+
+ printf("port: %d, fid: %d, state: %d\n", port, fid, state);
+
+ /*Check the input parameters is right or not. */
+ if ((port > 5) || (fid > 16) || (state > 3)) {
+ printf(HELP_STP);
+ return;
+ }
+
+ air_stp_setPortstate(0, port, fid, state);
+}
+
+void _an8855_ingress_rate_set(int on_off, unsigned char port, unsigned int bw)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_QOS_RATE_LIMIT_CFG_T rl = { 0 };
+ if (on_off) {
+ ret =
+ air_qos_setRateLimitEnable(0, port,
+ AIR_QOS_RATE_DIR_INGRESS, TRUE);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set ingress ratelimit eanble fail\n");
+ return;
+ }
+ rl.ingress_cir = bw;
+ rl.flags |= AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_INGRESS;
+ ret = air_qos_setRateLimit(0, port, &rl);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set ingress ratelimit value %d fail\n",
+ bw);
+ return;
+ } else {
+ printf("an8855 set ingress ratelimit value %d ok\n",
+ bw);
+ }
+ } else {
+ ret =
+ air_qos_setRateLimitEnable(0, port,
+ AIR_QOS_RATE_DIR_INGRESS, FALSE);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set ingress ratelimit disable fail\n");
+ return;
+ } else {
+ printf("an8855 set ingress ratelimit disable ok\n");
+ }
+ }
+}
+
+void _an8855_egress_rate_set(int on_off, unsigned char port, unsigned int bw)
+{
+ AIR_ERROR_NO_T ret = AIR_E_OK;
+ AIR_QOS_RATE_LIMIT_CFG_T rl = { 0 };
+ if (on_off) {
+ ret =
+ air_qos_setRateLimitEnable(0, port, AIR_QOS_RATE_DIR_EGRESS,
+ TRUE);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set egress ratelimit eanble fail\n");
+ return;
+ }
+ rl.egress_cir = bw;
+ rl.flags |= AIR_QOS_RATE_LIMIT_CFG_FLAGS_ENABLE_EGRESS;
+ ret = air_qos_setRateLimit(0, port, &rl);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set egress ratelimit value %d fail\n",
+ bw);
+ return;
+ } else {
+ printf("an8855 set egress ratelimit value %d ok\n", bw);
+ }
+ } else {
+ ret =
+ air_qos_setRateLimitEnable(0, port, AIR_QOS_RATE_DIR_EGRESS,
+ FALSE);
+ if (AIR_E_OK != ret) {
+ printf("an8855 set egress ratelimit disable fail\n");
+ return;
+ } else {
+ printf("an8855 set egress ratelimit disable ok\n");
+ }
+ }
+}
+
+void an8855_ingress_rate_set(int argc, char *argv[])
+{
+ int on_off = 0, port, bw = 0;
+
+ port = _strtoul(argv[3], NULL, 0);
+ if (argv[2][1] == 'n') {
+ bw = _strtoul(argv[4], NULL, 0);
+ on_off = 1;
+ } else if (argv[2][1] == 'f') {
+ if (argc != 4) {
+ return;
+ }
+ on_off = 0;
+ }
+
+ _an8855_ingress_rate_set(on_off, port, bw);
+}
+
+void an8855_egress_rate_set(int argc, char *argv[])
+{
+ unsigned int reg = 0, value = 0;
+ int on_off = 0, port = 0, bw = 0;
+
+ port = _strtoul(argv[3], NULL, 0);
+ if (argv[2][1] == 'n') {
+ bw = _strtoul(argv[4], NULL, 0);
+ on_off = 1;
+ } else if (argv[2][1] == 'f') {
+ if (argc != 4) {
+ return;
+ }
+ on_off = 0;
+ }
+
+ _an8855_egress_rate_set(on_off, port, bw);
+}
+
+void an8855_rate_control(int argc, char *argv[])
+{
+ unsigned char dir = 0;
+ unsigned char port = 0;
+ unsigned int rate_cir = 0;
+
+ dir = _strtoul(argv[2], NULL, 10);
+ port = _strtoul(argv[3], NULL, 10);
+ rate_cir = _strtoul(argv[4], NULL, 10);
+
+ if (port > 5) {
+ printf("Error, port %d is bigger than 5\n\r", port);
+ return;
+ }
+ if (rate_cir > 80000) {
+ printf("Error, rate_cir %d is bigger than 80000\n\r", rate_cir);
+ return;
+ }
+
+ if (dir == 1) //ingress
+ _an8855_ingress_rate_set(1, port, rate_cir);
+ else if (dir == 0) //egress
+ _an8855_egress_rate_set(1, port, rate_cir);
+ else
+ printf("Error, dir %d is not 1(ingress) and 0(egress)\n\r",
+ dir);
+}
+
+void an8855_read_output_queue_counters(int argc, char *argv[])
+{
+ unsigned int port = 0;
+ unsigned int value = 0, output_queue = 0;
+
+ for (port = 0; port < 7; port++) {
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x0);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 0 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x1);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 1 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x2);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 2 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x3);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 3 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x4);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 4 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x5);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 5 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x6);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 6 counter is %d.\n", port,
+ output_queue);
+ reg_write(0x10207e48, 0x80000000 | (port << 8) | 0x7);
+ reg_read(0x10207e4c, &output_queue);
+ printf("\n port %d output queue 7 counter is %d.\n", port,
+ output_queue);
+ }
+}
+
+void an8855_read_free_page_counters(int argc, char *argv[])
+{
+ unsigned int value = 0;
+ unsigned int free_page = 0, free_page_min = 0;
+ unsigned int fc_free_blk_lothd = 0, fc_free_blk_hithd = 0;
+ unsigned int fc_port_blk_thd = 0, fc_port_blk_hi_thd = 0;
+ unsigned int queue[8] = { 0 };
+
+ /* get system free page link counter */
+ reg_read(0x10207e00, &value);
+ free_page = value & 0xFFF;
+ free_page_min = (value & 0xFFF0000) >> 16;
+
+ /* get system flow control waterwark */
+ reg_read(0x10207e04, &value);
+ fc_free_blk_lothd = value & 0x3FF;
+ fc_free_blk_hithd = (value & 0x1FF8000) >> 15;
+
+ /* get port flow control waterwark */
+ reg_read(0x10207e08, &value);
+ fc_port_blk_thd = (value & 0xFF00) >> 8;
+ fc_port_blk_hi_thd = (value & 0xFF0000) >> 16;
+
+ /* get queue flow control waterwark */
+ reg_read(0x10207e10, &value);
+ queue[0] = value & 0x3F;
+ queue[1] = (value & 0x3F00) >> 8;
+ queue[2] = (value & 0x3F0000) >> 16;
+ queue[3] = (value & 0x3F000000) >> 24;
+ reg_read(0x10207e0c, &value);
+ queue[4] = value & 0x3F;
+ queue[5] = (value & 0x3F00) >> 8;
+ queue[6] = (value & 0x3F0000) >> 16;
+ queue[7] = (value & 0x3F000000) >> 24;
+
+ printf("<===Free Page=======Current============Minimal=========> \n ");
+ printf(" \n ");
+ printf(" page counter %u %u \n ",
+ free_page, free_page_min);
+ printf(" \n ");
+ printf("========================================================= \n ");
+ printf("<===Type=======High threshold======Low threshold=========\n ");
+ printf(" \n ");
+ printf(" system: %u %u \n",
+ fc_free_blk_hithd * 2, fc_free_blk_lothd * 2);
+ printf(" port: %u %u \n",
+ fc_port_blk_hi_thd * 2, fc_port_blk_thd * 2);
+ printf(" queue 0: %u NA \n",
+ queue[0]);
+ printf(" queue 1: %u NA \n",
+ queue[1]);
+ printf(" queue 2: %u NA \n",
+ queue[2]);
+ printf(" queue 3: %u NA \n",
+ queue[3]);
+ printf(" queue 4: %u NA \n",
+ queue[4]);
+ printf(" queue 5: %u NA \n",
+ queue[5]);
+ printf(" queue 6: %u NA \n",
+ queue[6]);
+ printf(" queue 7: %u NA \n",
+ queue[7]);
+ printf("=========================================================\n ");
+}
+
+void an8855_eee_enable(int argc, char *argv[])
+{
+ unsigned long enable = 0;
+ unsigned int value, mode = 0;
+ unsigned int eee_cap = 0;
+ unsigned int eee_en_bitmap = 0;
+ unsigned long port_map = 0;
+ long port_num = -1;
+ int p = 0;
+
+ if (argc < 3)
+ goto error;
+
+ /* Check the input parameters is right or not. */
+ if (!strncmp(argv[2], "enable", 7))
+ enable = 1;
+ else if (!strncmp(argv[2], "disable", 8))
+ enable = 0;
+ else
+ goto error;
+
+ if (argc > 3) {
+ if (strlen(argv[3]) == 1) {
+ port_num = strtol(argv[3], (char **)NULL, 10);
+ if (port_num < 0 || port_num > MAX_PHY_PORT - 1) {
+ printf("Illegal port index and port:0~4\n");
+ goto error;
+ }
+ port_map = 1 << port_num;
+ } else if (strlen(argv[3]) == 5) {
+ port_map = 0;
+ for (p = 0; p < MAX_PHY_PORT; p++) {
+ if (argv[3][p] != '0' && argv[3][p] != '1') {
+ printf
+ ("portmap format error, should be combination of 0 or 1\n");
+ goto error;
+ }
+ port_map |= ((argv[3][p] - '0') << p);
+ }
+ } else {
+ printf
+ ("port_no or portmap format error, should be length of 1 or 5\n");
+ goto error;
+ }
+ } else {
+ port_map = 0x1f;
+ }
+
+ for (port_num = 0; port_num < MAX_PHY_PORT; port_num++) {
+ if (port_map & (1 << port_num)) {
+ air_port_getPsMode(0, port_num, &mode);
+ if (enable) {
+ mode |= AIR_PORT_PS_EEE;
+ } else {
+ mode &= ~AIR_PORT_PS_EEE;
+ }
+ air_port_setPsMode(0, port_num, mode);
+ }
+ }
+ return;
+
+error:
+ printf(HELP_EEE_EN);
+ return;
+}
+
+void an8855_eee_dump(int argc, char *argv[])
+{
+ unsigned int cap = 0, lp_cap = 0;
+ long port = -1;
+ int p = 0;
+
+ if (argc > 3) {
+ if (strlen(argv[3]) > 1) {
+ printf("port# format error, should be of length 1\n");
+ return;
+ }
+
+ port = strtol(argv[3], (char **)NULL, 0);
+ if (port < 0 || port > MAX_PHY_PORT) {
+ printf("port# format error, should be 0 to %d\n",
+ MAX_PHY_PORT);
+ return;
+ }
+ }
+
+ for (p = 0; p < MAX_PHY_PORT; p++) {
+ if (port >= 0 && p != port)
+ continue;
+
+ mii_mgr_c45_read(p, 0x7, 0x3c, &cap);
+ mii_mgr_c45_read(p, 0x7, 0x3d, &lp_cap);
+ printf("port%d EEE cap=0x%02x, link partner EEE cap=0x%02x",
+ p, cap, lp_cap);
+
+ if (port >= 0 && p == port) {
+ mii_mgr_c45_read(p, 0x3, 0x1, &cap);
+ printf(", st=0x%03x", cap);
+ }
+ printf("\n");
+ }
+}
+
+void an8855_read_mib_counters(int argc, char *argv[])
+{
+ int port = 0;
+ AIR_MIB_CNT_RX_T rx_mib[7];
+ AIR_MIB_CNT_TX_T tx_mib[7];
+
+ printf("===================== %8s %8s %8s %8s %8s %8s %8s\n",
+ "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
+
+ for (port = 0; port < 7; port++) {
+ air_mib_get(0, port, &rx_mib[port], &tx_mib[port]);
+ }
+
+ printf("Tx Drop Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TDPC);
+ }
+ printf("\n");
+ printf("Tx CRC Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TCRC);
+ }
+ printf("\n");
+ printf("Tx Unicast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TUPC);
+ }
+ printf("\n");
+ printf("Tx Multicast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TMPC);
+ }
+ printf("\n");
+ printf("Tx Broadcast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TBPC);
+ }
+ printf("\n");
+ printf("Tx Collision Event :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TCEC);
+ }
+ printf("\n");
+ printf("Tx Pause Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", tx_mib[port].TPPC);
+ }
+ printf("\n");
+ printf("Rx Drop Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RDPC);
+ }
+ printf("\n");
+ printf("Rx Filtering Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RFPC);
+ }
+ printf("\n");
+ printf("Rx Unicast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RUPC);
+ }
+ printf("\n");
+ printf("Rx Multicast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RMPC);
+ }
+ printf("\n");
+ printf("Rx Broadcast Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RBPC);
+ }
+ printf("\n");
+ printf("Rx Alignment Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RAEPC);
+ }
+ printf("\n");
+ printf("Rx CRC Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RCEPC);
+ }
+ printf("\n");
+ printf("Rx Undersize Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RUSPC);
+ }
+ printf("\n");
+ printf("Rx Fragment Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RFEPC);
+ }
+ printf("\n");
+ printf("Rx Oversize Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].ROSPC);
+ }
+ printf("\n");
+ printf("Rx Jabber Error :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RJEPC);
+ }
+ printf("\n");
+ printf("Rx Pause Packet :");
+ for (port = 0; port < 7; port++) {
+ printf("%8u ", rx_mib[port].RPPC);
+ }
+ printf("\n");
+}
+
+void an8855_clear_mib_counters(int argc, char *argv[])
+{
+ air_mib_clear(0);
+}
diff --git a/recipes-devtools/switch/files/src/switch_fun_an8855.h b/recipes-devtools/switch/files/src/switch_fun_an8855.h
new file mode 100644
index 0000000..1d67080
--- /dev/null
+++ b/recipes-devtools/switch/files/src/switch_fun_an8855.h
@@ -0,0 +1,134 @@
+/*
+* switch_fun.h: switch function sets
+*/
+#ifndef SWITCH_FUN_AN8855_H
+#define SWITCH_FUN_AN8855_H
+
+#include "air.h"
+
+AIR_ERROR_NO_T
+an8855_reg_read(const UI32_T unit, const UI32_T addr_offset, UI32_T * ptr_data);
+
+AIR_ERROR_NO_T
+an8855_reg_write(const UI32_T unit,
+ const UI32_T addr_offset, const UI32_T data);
+
+AIR_ERROR_NO_T
+an8855_phy_cl22_read(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset, UI32_T * ptr_data);
+
+AIR_ERROR_NO_T
+an8855_phy_cl22_write(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T addr_offset, const UI32_T data);
+
+AIR_ERROR_NO_T
+an8855_phy_cl45_read(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset, UI32_T * ptr_data);
+
+AIR_ERROR_NO_T
+an8855_phy_cl45_write(const UI32_T unit,
+ const UI32_T port_id,
+ const UI32_T dev_type,
+ const UI32_T addr_offset, const UI32_T data);
+
+/*arl setting*/
+void an8855_doArlAging(int argc, char *argv[]);
+
+void an8855_not_supported(int argc, char *argv[]);
+
+#if 0
+/*acl setting*/
+void an8855_acl_mac_add(int argc, char *argv[]);
+void an8855_acl_dip_meter(int argc, char *argv[]);
+void an8855_acl_dip_trtcm(int argc, char *argv[]);
+void an8855_acl_ethertype(int argc, char *argv[]);
+void an8855_acl_ethertype(int argc, char *argv[]);
+void an8855_acl_dip_modify(int argc, char *argv[]);
+void an8855_acl_dip_pppoe(int argc, char *argv[]);
+void an8855_acl_dip_add(int argc, char *argv[]);
+void an8855_acl_l4_add(int argc, char *argv[]);
+void an8855_acl_sp_add(int argc, char *argv[]);
+
+void an8855_acl_port_enable(int argc, char *argv[]);
+void an8855_acl_table_add(int argc, char *argv[]);
+void an8855_acl_mask_table_add(int argc, char *argv[]);
+void an8855_acl_rule_table_add(int argc, char *argv[]);
+void an8855_acl_rate_table_add(int argc, char *argv[]);
+
+/*dip table*/
+void an8855_dip_dump(void);
+void an8855_dip_add(int argc, char *argv[]);
+void an8855_dip_del(int argc, char *argv[]);
+void an8855_dip_clear(void);
+
+/*sip table*/
+void an8855_sip_dump(void);
+void an8855_sip_add(int argc, char *argv[]);
+void an8855_sip_del(int argc, char *argv[]);
+void an8855_sip_clear(void);
+#endif
+
+/*stp*/
+void an8855_doStp(int argc, char *argv[]);
+
+/*mac table*/
+void an8855_table_dump(int argc, char *argv[]);
+void an8855_table_add(int argc, char *argv[]);
+void an8855_table_search_mac_vid(int argc, char *argv[]);
+void an8855_table_search_mac_fid(int argc, char *argv[]);
+void an8855_table_del_fid(int argc, char *argv[]);
+void an8855_table_del_vid(int argc, char *argv[]);
+void an8855_table_clear(int argc, char *argv[]);
+
+/*vlan table*/
+void an8855_vlan_dump(int argc, char *argv[]);
+void an8855_vlan_clear(int argc, char *argv[]);
+void an8855_vlan_set(int argc, char *argv[]);
+
+void an8855_doVlanSetPvid(int argc, char *argv[]);
+void an8855_doVlanSetVid(int argc, char *argv[]);
+void an8855_doVlanSetAccFrm(int argc, char *argv[]);
+void an8855_doVlanSetPortAttr(int argc, char *argv[]);
+void an8855_doVlanSetPortMode(int argc, char *argv[]);
+void an8855_doVlanSetEgressTagPCR(int argc, char *argv[]);
+void an8855_doVlanSetEgressTagPVC(int argc, char *argv[]);
+
+/*mirror function*/
+void an8855_set_mirror_to(int argc, char *argv[]);
+void an8855_set_mirror_from(int argc, char *argv[]);
+void an8855_doMirrorPortBased(int argc, char *argv[]);
+void an8855_doMirrorEn(int argc, char *argv[]);
+
+/*rate control*/
+void an8855_rate_control(int argc, char *argv[]);
+void an8855_ingress_rate_set(int argc, char *argv[]);
+void an8855_egress_rate_set(int argc, char *argv[]);
+
+/*QoS*/
+void an8855_qos_sch_select(int argc, char *argv[]);
+void an8855_qos_set_base(int argc, char *argv[]);
+void an8855_qos_wfq_set_weight(int argc, char *argv[]);
+void an8855_qos_set_portpri(int argc, char *argv[]);
+void an8855_qos_set_dscppri(int argc, char *argv[]);
+void an8855_qos_pri_mapping_queue(int argc, char *argv[]);
+
+/*flow control*/
+void an8855_global_set_mac_fc(int argc, char *argv[]);
+
+/*switch reset*/
+void an8855_switch_reset(int argc, char *argv[]);
+
+/* EEE(802.3az) function */
+void an8855_eee_enable(int argc, char *argv[]);
+void an8855_eee_dump(int argc, char *argv[]);
+
+void an8855_read_mib_counters(int argc, char *argv[]);
+void an8855_clear_mib_counters(int argc, char *argv[]);
+void an8855_read_output_queue_counters(int argc, char *argv[]);
+void an8855_read_free_page_counters(int argc, char *argv[]);
+
+#endif
diff --git a/recipes-devtools/switch/files/src/switch_ioctl.c b/recipes-devtools/switch/files/src/switch_ioctl.c
index 366079e..f6b97d4 100644
--- a/recipes-devtools/switch/files/src/switch_ioctl.c
+++ b/recipes-devtools/switch/files/src/switch_ioctl.c
@@ -235,24 +235,18 @@
mii.reg_num = 13;
mii.val_in = dev;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
method = RAETH_MII_WRITE;
mii.phy_id = port_num;
mii.reg_num = 14;
mii.val_in = reg;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
method = RAETH_MII_WRITE;
mii.phy_id = port_num;
mii.reg_num = 13;
mii.val_in = (0x6000 | dev);
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
usleep(1000);
@@ -260,8 +254,6 @@
mii.phy_id = port_num;
mii.reg_num = 14;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
close(sk);
*value = mii.val_out;
@@ -291,24 +283,18 @@
mii.reg_num = 13;
mii.val_in = dev;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
method = RAETH_MII_WRITE;
mii.phy_id = port_num;
mii.reg_num = 14;
mii.val_in = reg;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
method = RAETH_MII_WRITE;
mii.phy_id = port_num;
mii.reg_num = 13;
mii.val_in = (0x6000 | dev);
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
usleep(1000);
@@ -317,8 +303,6 @@
mii.reg_num = 14;
mii.val_in = value;
ret = ioctl(sk, method, &ifr);
- if (ret < 0)
- printf("ioctl failed with error %d\n", ret);
close(sk);
diff --git a/recipes-devtools/switch/files/src/switch_netlink.c b/recipes-devtools/switch/files/src/switch_netlink.c
index 90a4a19..397ebe5 100644
--- a/recipes-devtools/switch/files/src/switch_netlink.c
+++ b/recipes-devtools/switch/files/src/switch_netlink.c
@@ -41,10 +41,9 @@
if (gnlh->cmd == MT753X_CMD_REPLY) {
if (attrs[MT753X_ATTR_TYPE_MESG]) {
val->dev_info =
- nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
+ nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
printf("register switch dev:\n%s", val->dev_info);
- }
- else {
+ } else {
fprintf(stderr, "ERROR:No switch dev now\n");
goto done;
}
@@ -65,13 +64,15 @@
if (val->op == 'r') {
if (val->phy_dev != -1)
- NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV,
+ val->phy_dev);
if (val->port_num >= 0)
NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
NLA_PUT_U32(msg, type, val->reg);
} else if (val->op == 'w') {
if (val->phy_dev != -1)
- NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+ NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV,
+ val->phy_dev);
if (val->port_num >= 0)
NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
NLA_PUT_U32(msg, type, val->reg);
@@ -104,15 +105,12 @@
goto done;
}
if (attrs[MT753X_ATTR_TYPE_REG]) {
- val->reg =
- nla_get_u32(attrs[MT753X_ATTR_TYPE_REG]);
+ val->reg = nla_get_u32(attrs[MT753X_ATTR_TYPE_REG]);
}
if (attrs[MT753X_ATTR_TYPE_VAL]) {
- val->value =
- nla_get_u32(attrs[MT753X_ATTR_TYPE_VAL]);
+ val->value = nla_get_u32(attrs[MT753X_ATTR_TYPE_VAL]);
}
- }
- else
+ } else
goto done;
return 0;
@@ -120,7 +118,8 @@
return NL_SKIP;
}
-static int mt753x_request_callback(int cmd, int (*spilt)(struct nl_msg *, void *),
+static int mt753x_request_callback(int cmd,
+ int (*spilt)(struct nl_msg *, void *),
int (*construct)(struct nl_msg *, void *),
void *arg)
{
@@ -130,7 +129,7 @@
int flags = 0;
int err;
- /*Allocate an netllink message buffer*/
+ /* Allocate an netllink message buffer */
msg = nlmsg_alloc();
if (!msg) {
fprintf(stderr, "Failed to allocate netlink message\n");
@@ -145,7 +144,7 @@
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family),
0, flags, cmd, 0);
- /*Fill attaribute of netlink message by construct function*/
+ /* Fill attaribute of netlink message by construct function */
if (construct) {
err = construct(msg, arg);
if (err < 0) {
@@ -154,14 +153,14 @@
}
}
- /*Allocate an new callback handler*/
+ /* Allocate an new callback handler */
callback = nl_cb_alloc(NL_CB_CUSTOM);
if (!callback) {
fprintf(stderr, "Failed to allocate callback handler\n");
exit(1);
}
- /*Send netlink message*/
+ /* Send netlink message */
err = nl_send_auto_complete(user_sock, msg);
if (err < 0) {
fprintf(stderr, "nl_send_auto_complete failied:%d\n", err);
@@ -178,12 +177,12 @@
nl_cb_set(callback, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler,
&finished);
- /*receive message from kernel request*/
+ /* Receive message from kernel request */
err = nl_recvmsgs(user_sock, callback);
if (err < 0)
goto out;
- /*wait until an ACK is received for the latest not yet acknowledge*/
+ /* Wait until an ACK is received for the latest not yet acknowledge */
if (!finished)
err = nl_wait_for_ack(user_sock);
out:
@@ -216,18 +215,18 @@
cache = NULL;
family = NULL;
- /*Allocate an new netlink socket*/
+ /* Allocate an new netlink socket */
user_sock = nl_socket_alloc();
if (!user_sock) {
fprintf(stderr, "Failed to create user socket\n");
goto err;
}
- /*Connetct the genl controller*/
+ /* Connetct the genl controller */
if (genl_connect(user_sock)) {
fprintf(stderr, "Failed to connetct to generic netlink\n");
goto err;
}
- /*Allocate an new nl_cache*/
+ /* Allocate an new nl_cache */
ret = genl_ctrl_alloc_cache(user_sock, &cache);
if (ret < 0) {
fprintf(stderr, "Failed to allocate netlink cache\n");
@@ -237,10 +236,10 @@
if (name == NULL)
return -EINVAL;
- /*Look up generic netlik family by "mt753x" in the provided cache*/
+ /* Look up generic netlik family by "mt753x" in the provided cache */
family = genl_ctrl_search_by_name(cache, name);
if (!family) {
- //fprintf(stderr,"switch(mt753x) API not be prepared\n");
+ /* printf("switch(mt753x) API not be prepared\n"); */
goto err;
}
return 0;
@@ -283,20 +282,19 @@
attr->value = -1;
attr->type = MT753X_ATTR_TYPE_REG;
- switch (op)
- {
- case 'r':
- attr->op = 'r';
- ret = mt753x_request(attr, MT753X_CMD_READ);
- *value = attr->value;
- break;
- case 'w':
- attr->op = 'w';
- attr->value = *value;
- ret = mt753x_request(attr, MT753X_CMD_WRITE);
- break;
- default:
- break;
+ switch (op) {
+ case 'r':
+ attr->op = 'r';
+ ret = mt753x_request(attr, MT753X_CMD_READ);
+ *value = attr->value;
+ break;
+ case 'w':
+ attr->op = 'w';
+ attr->value = *value;
+ ret = mt753x_request(attr, MT753X_CMD_WRITE);
+ break;
+ default:
+ break;
}
return ret;
@@ -354,60 +352,66 @@
{
int ret;
- ret = phy_operate_netlink('w', arg, port_num, phy_dev, phy_addr, &value);
+ ret =
+ phy_operate_netlink('w', arg, port_num, phy_dev, phy_addr, &value);
return ret;
}
void dump_extend_phy_reg(struct mt753x_attr *arg, int port_no, int from,
- int to, int is_local, int page_no)
+ int to, int is_local, int page_no)
{
- unsigned int temp = 0;
- int r31 = 0;
- int i = 0;
+ unsigned int temp = 0;
+ int r31 = 0;
+ int i = 0;
- if (is_local == 0) {
- printf("\n\nGlobal Register Page %d\n",page_no);
- printf("===============");
- r31 |= 0 << 15; //global
- r31 |= ((page_no&0x7) << 12); //page no
- phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
- for (i = 16; i < 32; i++) {
- if(i%8 == 0)
- printf("\n");
- phy_cl22_read_netlink(arg, port_no, i, &temp);
- printf("%02d: %04X ", i, temp);
- }
- } else {
- printf("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
- printf("===============");
- r31 |= 1 << 15; //local
- r31 |= ((page_no&0x7) << 12); //page no
- phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
- for (i = 16; i < 32; i++) {
- if (i%8 == 0) {
- printf("\n");
- }
- phy_cl22_read_netlink(arg, port_no, i, &temp);
- printf("%02d: %04X ",i, temp);
- }
- }
- printf("\n");
+ if (is_local == 0) {
+ printf("\n\nGlobal Register Page %d\n", page_no);
+ printf("===============");
+ r31 |= 0 << 15; /* global */
+ r31 |= ((page_no & 0x7) << 12); /* page no */
+ phy_cl22_write_netlink(arg, port_no, 31, r31); /* select global page x */
+ for (i = 16; i < 32; i++) {
+ if (i % 8 == 0)
+ printf("\n");
+ phy_cl22_read_netlink(arg, port_no, i, &temp);
+ printf("%02d: %04X ", i, temp);
+ }
+ } else {
+ printf("\n\nLocal Register Port %d Page %d\n", port_no,
+ page_no);
+ printf("===============");
+ r31 |= 1 << 15; /* Local */
+ r31 |= ((page_no & 0x7) << 12); /* Page no */
+ phy_cl22_write_netlink(arg, port_no, 31, r31); /* Select global page x */
+ for (i = 16; i < 32; i++) {
+ if (i % 8 == 0)
+ printf("\n");
+ phy_cl22_read_netlink(arg, port_no, i, &temp);
+ printf("%02d: %04X ", i, temp);
+ }
+ }
+ printf("\n");
}
int phy_dump_netlink(struct mt753x_attr *arg, int phy_addr)
{
int i;
int ret;
- unsigned int offset, value;
+ unsigned int offset, value, phy_base = 0;
+
+ if (chip_name == 0x8855)
+ phy_base = 6;
if (phy_addr == 32) {
- /*dump all phy register*/
+ /* Dump all phy register */
for (i = 0; i < 5; i++) {
printf("\n[Port %d]=============", i);
for (offset = 0; offset < 16; offset++) {
if (offset % 8 == 0)
printf("\n");
- ret = phy_cl22_read_netlink(arg, i, offset, &value);
+ ret =
+ phy_cl22_read_netlink(arg, phy_base + i,
+ offset, &value);
printf("%02d: %04X ", offset, value);
}
}
@@ -416,30 +420,32 @@
for (offset = 0; offset < 16; offset++) {
if (offset % 8 == 0)
printf("\n");
- ret = phy_cl22_read_netlink(arg, phy_addr, offset, &value);
+ ret =
+ phy_cl22_read_netlink(arg, phy_addr, offset,
+ &value);
printf("%02d: %04X ", offset, value);
}
}
printf("\n");
- for (offset = 0; offset < 5; offset++) { //global register page 0~4
- if (phy_addr == 32) //dump all phy register
+ for (offset = 0; offset < 5; offset++) { /* Global register page 0~4 */
+ if (phy_addr == 32) /* Dump all phy register */
dump_extend_phy_reg(arg, 0, 16, 31, 0, offset);
else
dump_extend_phy_reg(arg, phy_addr, 16, 31, 0, offset);
}
- if (phy_addr == 32) { //dump all phy register
- for (offset = 0; offset < 5; offset++) { //local register port 0-port4
- dump_extend_phy_reg(arg, offset, 16, 31, 1, 0); //dump local page 0
- dump_extend_phy_reg(arg, offset, 16, 31, 1, 1); //dump local page 1
- dump_extend_phy_reg(arg, offset, 16, 31, 1, 2); //dump local page 2
- dump_extend_phy_reg(arg, offset, 16, 31, 1, 3); //dump local page 3
+ if (phy_addr == 32) { /* Dump all phy register */
+ for (offset = 0; offset < 5; offset++) { /* Local register port 0-port4 */
+ dump_extend_phy_reg(arg, phy_base + offset, 16, 31, 1, 0); /* Dump local page 0 */
+ dump_extend_phy_reg(arg, phy_base + offset, 16, 31, 1, 1); /* Dump local page 1 */
+ dump_extend_phy_reg(arg, phy_base + offset, 16, 31, 1, 2); /* Dump local page 2 */
+ dump_extend_phy_reg(arg, phy_base + offset, 16, 31, 1, 3); /* Dump local page 3 */
}
} else {
- dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 0); //dump local page 0
- dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 1); //dump local page 1
- dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 2); //dump local page 2
- dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 3); //dump local page 3
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 0); /* Dump local page 0 */
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 1); /* Dump local page 1 */
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 2); /* Dump local page 2 */
+ dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 3); /* Dump local page 3 */
}
return ret;
}
diff --git a/recipes-devtools/switch/files/src/switch_netlink.h b/recipes-devtools/switch/files/src/switch_netlink.h
index b3f946e..cb812d5 100644
--- a/recipes-devtools/switch/files/src/switch_netlink.h
+++ b/recipes-devtools/switch/files/src/switch_netlink.h
@@ -9,12 +9,14 @@
#define MT753X_GENL_NAME "mt753x"
#define MT753X_DSA_GENL_NAME "mt753x_dsa"
#define MT753X_GENL_VERSION 0X1
+#define AN8855_GENL_NAME "an8855"
+#define AN8855_DSA_GENL_NAME "an8855_dsa"
/*add your cmd to here*/
enum {
- MT753X_CMD_UNSPEC = 0, /*Reserved*/
- MT753X_CMD_REQUEST, /*user->kernelrequest/get-response*/
- MT753X_CMD_REPLY, /*kernel->user event*/
+ MT753X_CMD_UNSPEC = 0, /*Reserved */
+ MT753X_CMD_REQUEST, /*user->kernelrequest/get-response */
+ MT753X_CMD_REPLY, /*kernel->user event */
MT753X_CMD_READ,
MT753X_CMD_WRITE,
__MT753X_CMD_MAX,
@@ -22,10 +24,9 @@
#define MT753X_CMD_MAX (__MT753X_CMD_MAX - 1)
/*define attar types */
-enum
-{
+enum {
MT753X_ATTR_TYPE_UNSPEC = 0,
- MT753X_ATTR_TYPE_MESG, /*MT753X message*/
+ MT753X_ATTR_TYPE_MESG, /*MT753X message */
MT753X_ATTR_TYPE_PHY,
MT753X_ATTR_TYPE_PHY_DEV,
MT753X_ATTR_TYPE_REG,
@@ -48,6 +49,8 @@
int dev_id;
};
+extern int chip_name;
+
int mt753x_netlink_init(const char *name);
void mt753x_netlink_free(void);
void mt753x_list_swdev(struct mt753x_attr *arg, int cmd);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index 69688ff..4a3ac15 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -299,10 +299,5 @@
file://900-v5.9-0001-dt-bindings-Add-multicolor-class-dt-bindings-documen.patch \
file://900-v5.9-0002-leds-Add-multicolor-ID-to-the-color-ID-list.patch \
file://900-v5.9-0003-leds-add-RGB-color-option-as-that-is-different-from-.patch \
- file://999-2360-v5.16-spi-add-power-control-when-set_cs.patch \
- file://999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch \
- file://999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
- file://999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch;apply=no \
- file://999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch \
file://999-update-uapi-header-files-for-bridger.patch \
"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
index 11b86e3..17e6307 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
@@ -41,5 +41,4 @@
file://910-kobject_uevent.patch \
file://911-kobject_add_broadcast_uevent.patch \
file://921-always-create-console-node-in-initramfs.patch \
- file://999-2540-cmdline-boot-parameters.patch \
"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
index af11131..ccbdcff 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/pending-5.4.inc
@@ -120,7 +120,4 @@
file://834-ledtrig-libata.patch \
file://840-hwrng-bcm2835-set-quality-to-1000.patch \
file://920-mangle_bootargs.patch \
- file://999-2328-mtd-add-nmbm-support.patch \
- file://999-2329-ubi-add-configurable-rootdev.patch \
- file://999-2704-netfilter_optional_tcp_window_check.patch \
"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts
new file mode 100644
index 0000000..3f0bb90
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855-gsw.dts
@@ -0,0 +1,295 @@
+/dts-v1/;
+#include "mt7981.dtsi"
+/ {
+ model = "MediaTek MT7981 RFB";
+ compatible = "mediatek,mt7981-spim-snand-2500wan-an8855-gsw-rfb";
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 \
+ earlycon=uart8250,mmio32,0x11002000";
+ };
+
+ memory {
+ // fpga ddr2: 128MB*2
+ reg = <0 0x40000000 0 0x10000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ reset {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&pio 1 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ nmbm_spim_nand {
+ compatible = "generic,nmbm";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ lower-mtd-device = <&spi_nand>;
+ forced-create;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "BL2";
+ reg = <0x00000 0x0100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x0100000 0x0080000>;
+ };
+
+ factory: partition@180000 {
+ label = "Factory";
+ reg = <0x180000 0x0200000>;
+ };
+
+ partition@380000 {
+ label = "FIP";
+ reg = <0x380000 0x0200000>;
+ };
+
+ partition@580000 {
+ label = "ubi";
+ reg = <0x580000 0x4000000>;
+ };
+ };
+ };
+
+ gsw: gsw@0 {
+ compatible = "airoha,an8855";
+ #mediatek,ethsys = <ðsys>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
+
+ð {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ phy-mode = "2500base-x";
+ phy-handle = <&phy5>;
+ };
+
+ mdio: mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset-gpios = <&pio 14 1>;
+ reset-delay-us = <600>;
+
+ phy5: phy@5 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <5>;
+ };
+ };
+};
+
+&gsw {
+ airoha,mdio = <&mdio>;
+ airoha,portmap = "llllw";
+ airoha,smi-addr = <6>;
+ reset-gpios = <&pio 39 0>;
+ interrupt-parent = <&pio>;
+ interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+
+ port5: port@5 {
+ compatible = "airoha,an8855-port";
+ reg = <5>;
+ phy-mode = "2500base-x";
+ /* airoha,stag-on = <1>; */
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ };
+ };
+};
+
+&hnat {
+ mtketh-wan = "eth1";
+ mtketh-lan = "eth0";
+ mtketh-max-gmac = <2>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_flash_pins>;
+ status = "okay";
+ spi_nand: spi_nand@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <7>;
+ spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+ spi-cal-addrlen = <5>;
+ spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spic_pins>;
+ status = "disabled";
+
+ slb9670: slb9670@0 {
+ compatible = "infineon,slb9670";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <2>;
+ spi-cal-data = /bits/ 8 <0x00 0x1b>;
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&wbsys {
+ mediatek,mtd-eeprom = <&factory 0x0000>;
+ status = "okay";
+ pinctrl-names = "dbdc";
+ pinctrl-0 = <&wf_dbdc_pins>;
+};
+
+&pio {
+
+ i2c_pins: i2c-pins-g0 {
+ mux {
+ function = "i2c";
+ groups = "i2c0_0";
+ };
+ };
+
+ pcm_pins: pcm-pins-g0 {
+ mux {
+ function = "pcm";
+ groups = "pcm";
+ };
+ };
+
+ pwm0_pin: pwm0-pin-g0 {
+ mux {
+ function = "pwm";
+ groups = "pwm0_0";
+ };
+ };
+
+ pwm1_pin: pwm1-pin-g0 {
+ mux {
+ function = "pwm";
+ groups = "pwm1_0";
+ };
+ };
+
+ pwm2_pin: pwm2-pin {
+ mux {
+ function = "pwm";
+ groups = "pwm2";
+ };
+ };
+
+ spi0_flash_pins: spi0-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+
+ conf-pu {
+ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+ };
+
+ conf-pd {
+ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+ };
+ };
+
+ spic_pins: spi1-pins {
+ mux {
+ function = "spi";
+ groups = "spi1_1";
+ };
+ };
+
+ uart1_pins: uart1-pins-g1 {
+ mux {
+ function = "uart";
+ groups = "uart1_1";
+ };
+ };
+
+ uart2_pins: uart2-pins-g1 {
+ mux {
+ function = "uart";
+ groups = "uart2_1";
+ };
+ };
+
+ wf_dbdc_pins: wf_dbdc-pins {
+ mux {
+ function = "eth";
+ groups = "wf0_mode1";
+ };
+ conf {
+ pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4",
+ "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6",
+ "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10",
+ "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ",
+ "WF_CBA_RESETB", "WF_DIG_RESETB";
+ drive-strength = <MTK_DRIVE_4mA>;
+ };
+ };
+};
+
+&xhci {
+ status = "okay";
+};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts
new file mode 100644
index 0000000..4697ef5
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-2500wan-an8855.dts
@@ -0,0 +1,310 @@
+/dts-v1/;
+#include "mt7981.dtsi"
+/ {
+ model = "MediaTek MT7981 RFB";
+ compatible = "mediatek,mt7981-spim-snand-2500wan-an8855-rfb";
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 \
+ earlycon=uart8250,mmio32,0x11002000";
+ };
+
+ memory {
+ // fpga ddr2: 128MB*2
+ reg = <0 0x40000000 0 0x10000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ reset {
+ label = "reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&pio 1 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ nmbm_spim_nand {
+ compatible = "generic,nmbm";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ lower-mtd-device = <&spi_nand>;
+ forced-create;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "BL2";
+ reg = <0x00000 0x0100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x0100000 0x0080000>;
+ };
+
+ factory: partition@180000 {
+ label = "Factory";
+ reg = <0x180000 0x0200000>;
+ };
+
+ partition@380000 {
+ label = "FIP";
+ reg = <0x380000 0x0200000>;
+ };
+
+ partition@580000 {
+ label = "ubi";
+ reg = <0x580000 0x4000000>;
+ };
+ };
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&watchdog {
+ status = "okay";
+};
+
+ð {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ phy-mode = "2500base-x";
+ phy-handle = <&phy5>;
+ };
+
+ mdio: mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reset-gpios = <&pio 14 1>;
+ reset-delay-us = <600>;
+
+ phy5: phy@5 {
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reg = <5>;
+ };
+
+ switch@0 {
+ compatible = "airoha,an8855";
+ reg = <1>;
+ reset-gpios = <&pio 39 0>;
+ changesmiaddr = <6>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan3";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan4";
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "2500base-x";
+
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+ };
+ };
+};
+
+&hnat {
+ mtketh-wan = "eth1";
+ mtketh-lan = "lan";
+ mtketh-max-gmac = <2>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_flash_pins>;
+ status = "okay";
+ spi_nand: spi_nand@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <7>;
+ spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+ spi-cal-addrlen = <5>;
+ spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spic_pins>;
+ status = "disabled";
+
+ slb9670: slb9670@0 {
+ compatible = "infineon,slb9670";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <2>;
+ spi-cal-data = /bits/ 8 <0x00 0x1b>;
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&wbsys {
+ mediatek,mtd-eeprom = <&factory 0x0000>;
+ status = "okay";
+ pinctrl-names = "dbdc";
+ pinctrl-0 = <&wf_dbdc_pins>;
+};
+
+&pio {
+
+ i2c_pins: i2c-pins-g0 {
+ mux {
+ function = "i2c";
+ groups = "i2c0_0";
+ };
+ };
+
+ pcm_pins: pcm-pins-g0 {
+ mux {
+ function = "pcm";
+ groups = "pcm";
+ };
+ };
+
+ pwm0_pin: pwm0-pin-g0 {
+ mux {
+ function = "pwm";
+ groups = "pwm0_0";
+ };
+ };
+
+ pwm1_pin: pwm1-pin-g0 {
+ mux {
+ function = "pwm";
+ groups = "pwm1_0";
+ };
+ };
+
+ pwm2_pin: pwm2-pin {
+ mux {
+ function = "pwm";
+ groups = "pwm2";
+ };
+ };
+
+ spi0_flash_pins: spi0-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+
+ conf-pu {
+ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
+ };
+
+ conf-pd {
+ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO";
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
+ };
+ };
+
+ spic_pins: spi1-pins {
+ mux {
+ function = "spi";
+ groups = "spi1_1";
+ };
+ };
+
+ uart1_pins: uart1-pins-g1 {
+ mux {
+ function = "uart";
+ groups = "uart1_1";
+ };
+ };
+
+ uart2_pins: uart2-pins-g1 {
+ mux {
+ function = "uart";
+ groups = "uart2_1";
+ };
+ };
+
+ wf_dbdc_pins: wf_dbdc-pins {
+ mux {
+ function = "eth";
+ groups = "wf0_mode1";
+ };
+ conf {
+ pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4",
+ "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6",
+ "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10",
+ "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ",
+ "WF_CBA_RESETB", "WF_DIG_RESETB";
+ drive-strength = <MTK_DRIVE_4mA>;
+ };
+ };
+};
+
+&xhci {
+ status = "okay";
+};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index 7e96640..0fd2d47 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -381,6 +381,7 @@
dma-names = "tnl-sync";
fe_mem = <ð>;
+ hnat = <&hnat>;
};
tops-mbox {
@@ -584,6 +585,7 @@
interrupt-names = "ring0", "ring1", "ring2", "ring3";
status = "okay";
eth = <ð>;
+ hnat = <&hnat>;
};
afe: audio-controller@11210000 {
@@ -864,8 +866,7 @@
<&topckgen CK_TOP_NETSYS_SYNC_250M_SEL>,
<&topckgen CK_TOP_NETSYS_PPEFB_250M_SEL>,
<&topckgen CK_TOP_NETSYS_WARP_SEL>,
- <&topckgen CK_TOP_MACSEC_SEL>,
- <&topckgen CK_TOP_NETSYS_TOPS_400M_SEL>;
+ <&topckgen CK_TOP_MACSEC_SEL>;
clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1",
"gp3", "esw", "crypto", "sgmii_tx250m",
"sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m",
@@ -881,24 +882,21 @@
"top_netsys_sync_250m_sel",
"top_netsys_ppefb_250m_sel",
"top_netsys_warp_sel",
- "top_macsec_sel",
- "macsec_bus_clk";
+ "top_macsec_sel";
assigned-clocks = <&topckgen CK_TOP_NETSYS_2X_SEL>,
<&topckgen CK_TOP_NETSYS_GSW_SEL>,
<&topckgen CK_TOP_USXGMII_SBUS_0_SEL>,
<&topckgen CK_TOP_USXGMII_SBUS_1_SEL>,
<&topckgen CK_TOP_SGM_0_SEL>,
<&topckgen CK_TOP_SGM_1_SEL>,
- <&topckgen CK_TOP_MACSEC_SEL>,
- <&topckgen CK_TOP_NETSYS_TOPS_400M_SEL>;
+ <&topckgen CK_TOP_MACSEC_SEL>;
assigned-clock-parents = <&topckgen CK_TOP_CB_NET2_800M>,
<&topckgen CK_TOP_CB_NET1_D4>,
<&topckgen CK_TOP_NET1_D8_D4>,
<&topckgen CK_TOP_NET1_D8_D4>,
<&topckgen CK_TOP_CB_SGM_325M>,
<&topckgen CK_TOP_CB_SGM_325M>,
- <&topckgen CK_TOP_CB_SGM_325M>,
- <&topckgen CK_TOP_CB_NET2_D2>;
+ <&topckgen CK_TOP_CB_SGM_325M>;
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
index b725c38..f3f3692 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_MTK_ICE_DEBUG) += ice_debug/
obj-y += infra_bus_prot/
+obj-y += reset-boot-count/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile
new file mode 100644
index 0000000..a8c3756
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/Makefile
@@ -0,0 +1,2 @@
+
+obj-y := reset-boot-count.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c
new file mode 100644
index 0000000..2b82d89
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/reset-boot-count/reset-boot-count.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2024 MediaTek Inc. All rights reserved.
+ *
+ * Helper for resetting boot count of A/B boot systems
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/arm-smccc.h>
+
+#define RBC "reset_boot_count"
+
+#define MTK_SIP_READ_NONRST_REG 0xC2000550
+#define MTK_SIP_WRITE_NONRST_REG 0xC2000551
+
+static struct proc_dir_entry *rbc_entry;
+
+static bool dual_boot_get_boot_count(u32 *retslot, u32 *retcnt)
+{
+ struct arm_smccc_res res = {0};
+ u32 val, slot;
+ s8 neg, pos;
+
+ arm_smccc_smc(MTK_SIP_READ_NONRST_REG, 0, 0, 0, 0, 0, 0, 0, &res);
+
+ val = (u32)res.a0;
+
+ /* slot: val[31..24] = -slot, val[23..16] = slot */
+ pos = (val >> 16) & 0xff;
+ neg = (val >> 24) & 0xff;
+
+ if (!(pos >= 0 && neg <= 0 && pos + neg == 0)) {
+ pr_debug("slot of boot count is invalid\n");
+ goto err;
+ }
+
+ slot = pos;
+
+ /* count: val[15..8] = -count, val[7..0] = count */
+ pos = val & 0xff;
+ neg = (val >> 8) & 0xff;
+
+ if (!(pos >= 0 && neg <= 0 && pos + neg == 0)) {
+ pr_debug("count of boot count is invalid\n");
+ goto err;
+ }
+
+ if (retslot)
+ *retslot = slot;
+
+ if (retcnt)
+ *retcnt = pos;
+
+ return true;
+
+err:
+ if (retslot)
+ *retslot = 0;
+
+ if (retcnt)
+ *retcnt = 0;
+
+ return false;
+}
+
+static void dual_boot_set_boot_count(u32 slot, u32 count)
+{
+ struct arm_smccc_res res = {0};
+ u32 val;
+ s32 neg;
+
+ if (slot > 127 || count > 127)
+ return;
+
+ neg = -count;
+ val = count | ((neg << 8) & 0xff00);
+
+ neg = -slot;
+ val = val | ((uint32_t)slot << 16) | ((neg << 24) & 0xff000000);
+
+ arm_smccc_smc(MTK_SIP_WRITE_NONRST_REG, 0, val, 0, 0, 0, 0, 0, &res);
+}
+
+static int rbc_display(struct seq_file *seq, void *v)
+{
+ return 0;
+}
+
+static int rbc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rbc_display, inode->i_private);
+}
+
+static ssize_t rbc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *pos)
+{
+ u32 slot;
+
+ dual_boot_get_boot_count(&slot, NULL);
+ dual_boot_set_boot_count(slot, 0);
+
+ pr_info("Boot count reset\n");
+
+ return count;
+}
+
+static const struct file_operations rbc_fops =
+{
+ .open = rbc_open,
+ .read = seq_read,
+ .write = rbc_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init rbc_init(void)
+{
+ rbc_entry = proc_create(RBC, 0200, NULL, &rbc_fops);
+
+ if (!rbc_entry)
+ pr_err("failed to create proc entry " RBC);
+
+ return 0;
+}
+
+static void __exit rbc_exit(void)
+{
+ remove_proc_entry(RBC, NULL);
+}
+
+module_init(rbc_init);
+module_exit(rbc_exit);
+
+MODULE_AUTHOR("Weijie Gao <weijie.gao@mediatek.com>");
+MODULE_DESCRIPTION("Kernel module for resetting boot count of A/B boot systems");
+MODULE_LICENSE("BSD");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig
new file mode 100644
index 0000000..fc00f75
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Kconfig
@@ -0,0 +1,10 @@
+
+config NET_DSA_AN8855
+ tristate "Airoha AN8855 Ethernet switch support"
+ depends on NET_DSA
+ select NET_DSA_TAG_AIROHA
+ help
+ AN8855 support 2.5G speed and managed by SMI interface.
+ This enables support for the Airoha AN8855 Ethernet switch
+ chip.
+ To compile this driver as a module, choose M here.
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile
new file mode 100644
index 0000000..99c99bd
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Airoha AN8855 gigabit switch
+#
+obj-$(CONFIG_NET_DSA_AN8855) += an8855-dsa.o
+an8855-dsa-objs := an8855.o an8855_nl.o an8855_phy.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c
new file mode 100644
index 0000000..b0ba4be
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.c
@@ -0,0 +1,2358 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Airoha AN8855 DSA Switch driver
+ * Copyright (C) 2023 Min Yao <min.yao@airoha.com>
+ */
+#include <linux/etherdevice.h>
+#include <linux/if_bridge.h>
+#include <linux/iopoll.h>
+#include <linux/mdio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phylink.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/gpio/consumer.h>
+#include <net/dsa.h>
+#include <linux/of_address.h>
+
+#include "an8855.h"
+#include "an8855_nl.h"
+
+/* AN8855 driver version */
+#define ARHT_AN8855_DSA_DRIVER_VER "1.0.1-L5.4"
+
+/* String, offset, and register size in bytes if different from 4 bytes */
+static const struct an8855_mib_desc an8855_mib[] = {
+ MIB_DESC(1, 0x00, "TxDrop"),
+ MIB_DESC(1, 0x04, "TxCrcErr"),
+ MIB_DESC(1, 0x08, "TxUnicast"),
+ MIB_DESC(1, 0x0c, "TxMulticast"),
+ MIB_DESC(1, 0x10, "TxBroadcast"),
+ MIB_DESC(1, 0x14, "TxCollision"),
+ MIB_DESC(1, 0x18, "TxSingleCollision"),
+ MIB_DESC(1, 0x1c, "TxMultipleCollision"),
+ MIB_DESC(1, 0x20, "TxDeferred"),
+ MIB_DESC(1, 0x24, "TxLateCollision"),
+ MIB_DESC(1, 0x28, "TxExcessiveCollistion"),
+ MIB_DESC(1, 0x2c, "TxPause"),
+ MIB_DESC(1, 0x30, "TxPktSz64"),
+ MIB_DESC(1, 0x34, "TxPktSz65To127"),
+ MIB_DESC(1, 0x38, "TxPktSz128To255"),
+ MIB_DESC(1, 0x3c, "TxPktSz256To511"),
+ MIB_DESC(1, 0x40, "TxPktSz512To1023"),
+ MIB_DESC(1, 0x44, "TxPktSz1024To1518"),
+ MIB_DESC(1, 0x48, "TxPktSz1519ToMax"),
+ MIB_DESC(2, 0x4c, "TxBytes"),
+ MIB_DESC(1, 0x54, "TxOversizeDrop"),
+ MIB_DESC(2, 0x58, "TxBadPktBytes"),
+ MIB_DESC(1, 0x80, "RxDrop"),
+ MIB_DESC(1, 0x84, "RxFiltering"),
+ MIB_DESC(1, 0x88, "RxUnicast"),
+ MIB_DESC(1, 0x8c, "RxMulticast"),
+ MIB_DESC(1, 0x90, "RxBroadcast"),
+ MIB_DESC(1, 0x94, "RxAlignErr"),
+ MIB_DESC(1, 0x98, "RxCrcErr"),
+ MIB_DESC(1, 0x9c, "RxUnderSizeErr"),
+ MIB_DESC(1, 0xa0, "RxFragErr"),
+ MIB_DESC(1, 0xa4, "RxOverSzErr"),
+ MIB_DESC(1, 0xa8, "RxJabberErr"),
+ MIB_DESC(1, 0xac, "RxPause"),
+ MIB_DESC(1, 0xb0, "RxPktSz64"),
+ MIB_DESC(1, 0xb4, "RxPktSz65To127"),
+ MIB_DESC(1, 0xb8, "RxPktSz128To255"),
+ MIB_DESC(1, 0xbc, "RxPktSz256To511"),
+ MIB_DESC(1, 0xc0, "RxPktSz512To1023"),
+ MIB_DESC(1, 0xc4, "RxPktSz1024To1518"),
+ MIB_DESC(1, 0xc8, "RxPktSz1519ToMax"),
+ MIB_DESC(2, 0xcc, "RxBytes"),
+ MIB_DESC(1, 0xd4, "RxCtrlDrop"),
+ MIB_DESC(1, 0xd8, "RxIngressDrop"),
+ MIB_DESC(1, 0xdc, "RxArlDrop"),
+ MIB_DESC(1, 0xe0, "FlowControlDrop"),
+ MIB_DESC(1, 0xe4, "WredDrop"),
+ MIB_DESC(1, 0xe8, "MirrorDrop"),
+ MIB_DESC(2, 0xec, "RxBadPktBytes"),
+ MIB_DESC(1, 0xf4, "RxsFlowSamplingPktDrop"),
+ MIB_DESC(1, 0xf8, "RxsFlowTotalPktDrop"),
+ MIB_DESC(1, 0xfc, "PortControlDrop"),
+};
+
+static int
+an8855_mii_write(struct an8855_priv *priv, u32 reg, u32 val)
+{
+ struct mii_bus *bus = priv->bus;
+ int ret = 0;
+
+ ret = bus->write(bus, priv->phy_base, 0x1f, 0x4);
+ ret = bus->write(bus, priv->phy_base, 0x10, 0);
+
+ ret = bus->write(bus, priv->phy_base, 0x11, ((reg >> 16) & 0xFFFF));
+ ret = bus->write(bus, priv->phy_base, 0x12, (reg & 0xFFFF));
+
+ ret = bus->write(bus, priv->phy_base, 0x13, ((val >> 16) & 0xFFFF));
+ ret = bus->write(bus, priv->phy_base, 0x14, (val & 0xFFFF));
+
+ ret = bus->write(bus, priv->phy_base, 0x1f, 0);
+ ret = bus->write(bus, priv->phy_base, 0x10, 0);
+
+ if (ret < 0) {
+ dev_err(&bus->dev, "failed to write an8855 register\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static u32
+an8855_mii_read(struct an8855_priv *priv, u32 reg)
+{
+ struct mii_bus *bus = priv->bus;
+ u16 lo, hi;
+ int ret;
+
+ ret = bus->write(bus, priv->phy_base, 0x1f, 0x4);
+ ret = bus->write(bus, priv->phy_base, 0x10, 0);
+
+ ret = bus->write(bus, priv->phy_base, 0x15, ((reg >> 16) & 0xFFFF));
+ ret = bus->write(bus, priv->phy_base, 0x16, (reg & 0xFFFF));
+ if (ret < 0) {
+ dev_err(&bus->dev, "failed to read an8855 register\n");
+ return ret;
+ }
+
+ lo = bus->read(bus, priv->phy_base, 0x18);
+ hi = bus->read(bus, priv->phy_base, 0x17);
+
+ ret = bus->write(bus, priv->phy_base, 0x1f, 0);
+ ret = bus->write(bus, priv->phy_base, 0x10, 0);
+ if (ret < 0) {
+ dev_err(&bus->dev, "failed to read an8855 register\n");
+ return ret;
+ }
+
+ return (hi << 16) | (lo & 0xffff);
+}
+
+void
+an8855_write(struct an8855_priv *priv, u32 reg, u32 val)
+{
+ struct mii_bus *bus = priv->bus;
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+ an8855_mii_write(priv, reg, val);
+
+ mutex_unlock(&bus->mdio_lock);
+}
+
+static u32
+_an8855_read(struct an8855_dummy_poll *p)
+{
+ struct mii_bus *bus = p->priv->bus;
+ u32 val;
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+ val = an8855_mii_read(p->priv, p->reg);
+
+ mutex_unlock(&bus->mdio_lock);
+
+ return val;
+}
+
+u32
+an8855_read(struct an8855_priv *priv, u32 reg)
+{
+ struct an8855_dummy_poll p;
+
+ INIT_AN8855_DUMMY_POLL(&p, priv, reg);
+ return _an8855_read(&p);
+}
+
+static void
+an8855_rmw(struct an8855_priv *priv, u32 reg, u32 mask, u32 set)
+{
+ struct mii_bus *bus = priv->bus;
+ u32 val;
+
+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+ val = an8855_mii_read(priv, reg);
+ val &= ~mask;
+ val |= set;
+ an8855_mii_write(priv, reg, val);
+
+ mutex_unlock(&bus->mdio_lock);
+}
+
+static void
+an8855_set(struct an8855_priv *priv, u32 reg, u32 val)
+{
+ an8855_rmw(priv, reg, 0, val);
+}
+
+static void
+an8855_clear(struct an8855_priv *priv, u32 reg, u32 val)
+{
+ an8855_rmw(priv, reg, val, 0);
+}
+
+static int
+an8855_fdb_cmd(struct an8855_priv *priv, u32 cmd, u32 *rsp)
+{
+ u32 val;
+ int ret;
+ struct an8855_dummy_poll p;
+
+ /* Set the command operating upon the MAC address entries */
+ val = ATC_BUSY | cmd;
+ an8855_write(priv, AN8855_ATC, val);
+
+ INIT_AN8855_DUMMY_POLL(&p, priv, AN8855_ATC);
+ ret = readx_poll_timeout(_an8855_read, &p, val,
+ !(val & ATC_BUSY), 20, 200000);
+ if (ret < 0) {
+ dev_err(priv->dev, "reset timeout\n");
+ return ret;
+ }
+
+ if (rsp)
+ *rsp = val;
+
+ return 0;
+}
+
+static void
+an8855_fdb_read(struct an8855_priv *priv, struct an8855_fdb *fdb)
+{
+ u32 reg[4];
+ int i;
+
+ /* Read from ARL table into an array */
+ for (i = 0; i < 4; i++)
+ reg[i] = an8855_read(priv, AN8855_ATRD0 + (i * 4));
+
+ fdb->live = reg[0] & 0x1;
+ fdb->type = (reg[0] >> 3) & 0x3;
+ fdb->ivl = (reg[0] >> 9) & 0x1;
+ fdb->vid = (reg[0] >> 10) & 0xfff;
+ fdb->fid = (reg[0] >> 25) & 0xf;
+ fdb->aging = (reg[1] >> 3) & 0x1ff;
+ fdb->port_mask = reg[3] & 0xff;
+ fdb->mac[0] = (reg[2] >> MAC_BYTE_0) & MAC_BYTE_MASK;
+ fdb->mac[1] = (reg[2] >> MAC_BYTE_1) & MAC_BYTE_MASK;
+ fdb->mac[2] = (reg[2] >> MAC_BYTE_2) & MAC_BYTE_MASK;
+ fdb->mac[3] = (reg[2] >> MAC_BYTE_3) & MAC_BYTE_MASK;
+ fdb->mac[4] = (reg[1] >> MAC_BYTE_4) & MAC_BYTE_MASK;
+ fdb->mac[5] = (reg[1] >> MAC_BYTE_5) & MAC_BYTE_MASK;
+ fdb->noarp = !!((reg[0] >> 1) & 0x3);
+}
+
+static void
+an8855_fdb_write(struct an8855_priv *priv, u16 vid,
+ u8 port_mask, const u8 *mac, u8 add)
+{
+ u32 reg = 0;
+
+ reg |= mac[3] << MAC_BYTE_3;
+ reg |= mac[2] << MAC_BYTE_2;
+ reg |= mac[1] << MAC_BYTE_1;
+ reg |= mac[0] << MAC_BYTE_0;
+ an8855_write(priv, AN8855_ATA1, reg);
+ reg = 0;
+ reg |= mac[5] << MAC_BYTE_5;
+ reg |= mac[4] << MAC_BYTE_4;
+ an8855_write(priv, AN8855_ATA2, reg);
+ reg = 0;
+ if (add)
+ reg |= 0x1;
+ reg |= 0x1 << 15;
+ reg |= vid << 16;
+ an8855_write(priv, AN8855_ATWD, reg);
+ an8855_write(priv, AN8855_ATWD2, port_mask);
+}
+
+static int
+an8855_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+{
+ return 0;
+}
+
+static void
+an8855_mib_reset(struct dsa_switch *ds)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ an8855_write(priv, AN8855_MIB_CCR, CCR_MIB_FLUSH);
+ an8855_write(priv, AN8855_MIB_CCR, CCR_MIB_ACTIVATE);
+}
+
+static int
+an8855_cl22_read(struct an8855_priv *priv, int port, int regnum)
+{
+ return mdiobus_read_nested(priv->bus, port, regnum);
+}
+
+static int
+an8855_cl22_write(struct an8855_priv *priv, int port, int regnum, u16 val)
+{
+ return mdiobus_write_nested(priv->bus, port, regnum, val);
+}
+
+static int
+an8855_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ port += priv->phy_base;
+ return an8855_cl22_read(ds->priv, port, regnum);
+}
+
+static int
+an8855_phy_write(struct dsa_switch *ds, int port, int regnum,
+ u16 val)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ port += priv->phy_base;
+ return an8855_cl22_write(ds->priv, port, regnum, val);
+}
+
+static int
+an8855_cl45_read(struct an8855_priv *priv, int port, int devad, int regnum)
+{
+ regnum = MII_ADDR_C45 | (devad << 16) | regnum;
+ return mdiobus_read_nested(priv->bus, port, regnum);
+}
+
+static int
+an8855_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum,
+ u16 val)
+{
+ regnum = MII_ADDR_C45 | (devad << 16) | regnum;
+ return mdiobus_write_nested(priv->bus, port, regnum, val);
+}
+
+int
+an8855_phy_cl22_read(struct an8855_priv *priv, int port, int regnum)
+{
+ port += priv->phy_base;
+ return an8855_cl22_read(priv, port, regnum);
+}
+
+int
+an8855_phy_cl22_write(struct an8855_priv *priv, int port, int regnum,
+ u16 val)
+{
+ port += priv->phy_base;
+ return an8855_cl22_write(priv, port, regnum, val);
+}
+
+int
+an8855_phy_cl45_read(struct an8855_priv *priv, int port, int devad, int regnum)
+{
+ port += priv->phy_base;
+ return an8855_cl45_read(priv, port, devad, regnum);
+}
+
+int
+an8855_phy_cl45_write(struct an8855_priv *priv, int port, int devad, int regnum,
+ u16 val)
+{
+ port += priv->phy_base;
+ return an8855_cl45_write(priv, port, devad, regnum, val);
+}
+
+static void
+an8855_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t *data)
+{
+ int i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(an8855_mib); i++)
+ strncpy(data + i * ETH_GSTRING_LEN, an8855_mib[i].name,
+ ETH_GSTRING_LEN);
+}
+
+static void
+an8855_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
+{
+ struct an8855_priv *priv = ds->priv;
+ const struct an8855_mib_desc *mib;
+ u32 reg, i;
+ u64 hi;
+
+ for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) {
+ mib = &an8855_mib[i];
+ reg = AN8855_PORT_MIB_COUNTER(port) + mib->offset;
+
+ data[i] = an8855_read(priv, reg);
+ if (mib->size == 2) {
+ hi = an8855_read(priv, reg + 4);
+ data[i] |= hi << 32;
+ }
+ }
+}
+
+static int
+an8855_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+ return ARRAY_SIZE(an8855_mib);
+}
+
+static int
+an8855_cpu_port_enable(struct dsa_switch *ds, int port)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ /* Setup max capability of CPU port at first */
+ if (priv->info->cpu_port_config)
+ priv->info->cpu_port_config(ds, port);
+
+ /* Enable Airoha header mode on the cpu port */
+ an8855_write(priv, AN8855_PVC_P(port),
+ PORT_SPEC_REPLACE_MODE | PORT_SPEC_TAG);
+
+ /* Unknown multicast frame forwarding to the cpu port */
+ an8855_write(priv, AN8855_UNMF, BIT(port));
+
+ /* Set CPU port number */
+ an8855_rmw(priv, AN8855_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
+
+ /* CPU port gets connected to all user ports of
+ * the switch.
+ */
+ an8855_write(priv, AN8855_PORTMATRIX_P(port),
+ PORTMATRIX_MATRIX(dsa_user_ports(priv->ds)));
+
+ return 0;
+}
+
+static int
+an8855_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ if (!dsa_is_user_port(ds, port))
+ return 0;
+
+ mutex_lock(&priv->reg_mutex);
+
+ /* Allow the user port gets connected to the cpu port and also
+ * restore the port matrix if the port is the member of a certain
+ * bridge.
+ */
+ priv->ports[port].pm |= PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT));
+ priv->ports[port].enable = true;
+ an8855_write(priv, AN8855_PORTMATRIX_P(port), priv->ports[port].pm);
+ an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+
+ mutex_unlock(&priv->reg_mutex);
+
+ return 0;
+}
+
+static void
+an8855_port_disable(struct dsa_switch *ds, int port)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ if (!dsa_is_user_port(ds, port))
+ return;
+
+ mutex_lock(&priv->reg_mutex);
+
+ /* Clear up all port matrix which could be restored in the next
+ * enablement for the port.
+ */
+ priv->ports[port].enable = false;
+ an8855_write(priv, AN8855_PORTMATRIX_P(port), PORTMATRIX_CLR);
+ an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+
+ mutex_unlock(&priv->reg_mutex);
+}
+
+static void
+an8855_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 stp_state;
+
+ if (dsa_is_unused_port(ds, port))
+ return;
+
+ switch (state) {
+ case BR_STATE_DISABLED:
+ stp_state = AN8855_STP_DISABLED;
+ break;
+ case BR_STATE_BLOCKING:
+ stp_state = AN8855_STP_BLOCKING;
+ break;
+ case BR_STATE_LISTENING:
+ stp_state = AN8855_STP_LISTENING;
+ break;
+ case BR_STATE_LEARNING:
+ stp_state = AN8855_STP_LEARNING;
+ break;
+ case BR_STATE_FORWARDING:
+ default:
+ stp_state = AN8855_STP_FORWARDING;
+ break;
+ }
+
+ an8855_rmw(priv, AN8855_SSP_P(port), FID_PST_MASK, stp_state);
+}
+
+static int
+an8855_port_bridge_join(struct dsa_switch *ds, int port,
+ struct net_device *bridge)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 port_bitmap = BIT(AN8855_CPU_PORT);
+ int i;
+
+ mutex_lock(&priv->reg_mutex);
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ /* Add this port to the port matrix of the other ports in the
+ * same bridge. If the port is disabled, port matrix is kept
+ * and not being setup until the port becomes enabled.
+ */
+ if (dsa_is_user_port(ds, i) && i != port) {
+ if (dsa_to_port(ds, i)->bridge_dev != bridge)
+ continue;
+ if (priv->ports[i].enable)
+ an8855_set(priv, AN8855_PORTMATRIX_P(i),
+ PORTMATRIX_MATRIX(BIT(port)));
+ priv->ports[i].pm |= PORTMATRIX_MATRIX(BIT(port));
+
+ port_bitmap |= BIT(i);
+ }
+ }
+
+ /* Add the all other ports to this port matrix. */
+ if (priv->ports[port].enable)
+ an8855_rmw(priv, AN8855_PORTMATRIX_P(port),
+ PORTMATRIX_MASK, PORTMATRIX_MATRIX(port_bitmap));
+ priv->ports[port].pm |= PORTMATRIX_MATRIX(port_bitmap);
+
+ mutex_unlock(&priv->reg_mutex);
+
+ return 0;
+}
+
+static void
+an8855_port_set_vlan_unaware(struct dsa_switch *ds, int port)
+{
+ struct an8855_priv *priv = ds->priv;
+ bool all_user_ports_removed = true;
+ int i;
+
+ /* When a port is removed from the bridge, the port would be set up
+ * back to the default as is at initial boot which is a VLAN-unaware
+ * port.
+ */
+ an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK,
+ AN8855_PORT_MATRIX_MODE);
+ an8855_rmw(priv, AN8855_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+ VLAN_ATTR(AN8855_VLAN_TRANSPARENT) |
+ PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT));
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ if (dsa_is_user_port(ds, i) &&
+ dsa_port_is_vlan_filtering(&ds->ports[i])) {
+ all_user_ports_removed = false;
+ break;
+ }
+ }
+
+ /* CPU port also does the same thing until all user ports belonging to
+ * the CPU port get out of VLAN filtering mode.
+ */
+ if (all_user_ports_removed) {
+ an8855_write(priv, AN8855_PORTMATRIX_P(AN8855_CPU_PORT),
+ PORTMATRIX_MATRIX(dsa_user_ports(priv->ds)));
+ an8855_write(priv, AN8855_PVC_P(AN8855_CPU_PORT),
+ PORT_SPEC_REPLACE_MODE | PORT_SPEC_TAG |
+ PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT));
+ }
+}
+
+static void
+an8855_port_set_vlan_aware(struct dsa_switch *ds, int port)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ /* Trapped into security mode allows packet forwarding through VLAN
+ * table lookup. CPU port is set to fallback mode to let untagged
+ * frames pass through.
+ */
+ if (dsa_is_cpu_port(ds, port))
+ an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK,
+ AN8855_PORT_FALLBACK_MODE);
+ else
+ an8855_rmw(priv, AN8855_PCR_P(port), PCR_PORT_VLAN_MASK,
+ AN8855_PORT_SECURITY_MODE);
+
+ /* Set the port as a user port which is to be able to recognize VID
+ * from incoming packets before fetching entry within the VLAN table.
+ */
+ an8855_rmw(priv, AN8855_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+ VLAN_ATTR(AN8855_VLAN_USER) |
+ PVC_EG_TAG(AN8855_VLAN_EG_DISABLED));
+}
+
+static void
+an8855_port_bridge_leave(struct dsa_switch *ds, int port,
+ struct net_device *bridge)
+{
+ struct an8855_priv *priv = ds->priv;
+ int i;
+
+ mutex_lock(&priv->reg_mutex);
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ /* Remove this port from the port matrix of the other ports
+ * in the same bridge. If the port is disabled, port matrix
+ * is kept and not being setup until the port becomes enabled.
+ */
+ if (dsa_is_user_port(ds, i) && i != port) {
+ if (dsa_to_port(ds, i)->bridge_dev != bridge)
+ continue;
+ if (priv->ports[i].enable)
+ an8855_clear(priv, AN8855_PORTMATRIX_P(i),
+ PORTMATRIX_MATRIX(BIT(port)));
+ priv->ports[i].pm &= PORTMATRIX_MATRIX(BIT(port));
+ }
+ }
+
+ /* Set the cpu port to be the only one in the port matrix of
+ * this port.
+ */
+ if (priv->ports[port].enable)
+ an8855_rmw(priv, AN8855_PORTMATRIX_P(port), PORTMATRIX_MASK,
+ PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT)));
+ priv->ports[port].pm = PORTMATRIX_MATRIX(BIT(AN8855_CPU_PORT));
+
+ mutex_unlock(&priv->reg_mutex);
+}
+
+static int
+an8855_port_fdb_add(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid)
+{
+ struct an8855_priv *priv = ds->priv;
+ int ret;
+ u8 port_mask = BIT(port);
+
+ mutex_lock(&priv->reg_mutex);
+ an8855_fdb_write(priv, vid, port_mask, addr, 1);
+ ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+ mutex_unlock(&priv->reg_mutex);
+
+ return ret;
+}
+
+static int
+an8855_port_fdb_del(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid)
+{
+ struct an8855_priv *priv = ds->priv;
+ int ret;
+ u8 port_mask = BIT(port);
+
+ mutex_lock(&priv->reg_mutex);
+ an8855_fdb_write(priv, vid, port_mask, addr, 0);
+ ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL);
+ mutex_unlock(&priv->reg_mutex);
+
+ return ret;
+}
+
+static int
+an8855_port_fdb_dump(struct dsa_switch *ds, int port,
+ dsa_fdb_dump_cb_t *cb, void *data)
+{
+ struct an8855_priv *priv = ds->priv;
+ struct an8855_fdb _fdb = { 0 };
+ int cnt = 512;
+ int num = 4;
+ int index = 0;
+ bool flag = false;
+ int banks = 0;
+ int i = 0;
+ int ret = 0;
+ u32 rsp = 0;
+
+ mutex_lock(&priv->reg_mutex);
+
+ an8855_write(priv, AN8855_ATWD2, (0x1 << port));
+ ret = an8855_fdb_cmd(priv, ATC_MAT(0xc) | AN8855_FDB_START, &rsp);
+ if (ret < 0)
+ goto err;
+
+ index = (rsp >> ATC_HASH) & ATC_HASH_MASK;
+ if (index == (cnt - 1))
+ flag = true;
+ else
+ flag = false;
+
+ banks = (rsp >> ATC_HIT) & ATC_HIT_MASK;
+ if (banks == 0) {
+ mutex_unlock(&priv->reg_mutex);
+ return 0;
+ }
+ for (i = 0; i < num; i++) {
+ if ((banks >> i) & 0x1) {
+ an8855_write(priv, AN8855_ATRDS, i);
+ udelay(1000);
+ an8855_fdb_read(priv, &_fdb);
+ if (!_fdb.live)
+ continue;
+ if (_fdb.port_mask & BIT(port)) {
+ ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, data);
+ if (ret < 0)
+ continue;
+ }
+ }
+ }
+ while (1) {
+ if (flag == true)
+ break;
+
+ ret =
+ an8855_fdb_cmd(priv, ATC_MAT(0xc) | AN8855_FDB_NEXT, &rsp);
+ index = (rsp >> ATC_HASH) & ATC_HASH_MASK;
+ if (index == (cnt - 1))
+ flag = true;
+ else
+ flag = false;
+
+ banks = (rsp >> ATC_HIT) & ATC_HIT_MASK;
+ if (banks == 0) {
+ mutex_unlock(&priv->reg_mutex);
+ return 0;
+ }
+ for (i = 0; i < num; i++) {
+ if ((banks >> i) & 0x1) {
+ an8855_write(priv, AN8855_ATRDS, i);
+ udelay(1000);
+ an8855_fdb_read(priv, &_fdb);
+ if (!_fdb.live)
+ continue;
+ if (_fdb.port_mask & BIT(port)) {
+ ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp,
+ data);
+ if (ret < 0)
+ continue;
+ }
+ }
+ }
+ }
+
+err:
+ mutex_unlock(&priv->reg_mutex);
+ return 0;
+}
+
+static int
+an8855_vlan_cmd(struct an8855_priv *priv, enum an8855_vlan_cmd cmd, u16 vid)
+{
+ struct an8855_dummy_poll p;
+ u32 val;
+ int ret;
+
+ if (vid > 0xFFF) {
+ dev_err(priv->dev, "vid number invalid\n");
+ return -EINVAL;
+ }
+
+ val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
+ an8855_write(priv, AN8855_VTCR, val);
+
+ INIT_AN8855_DUMMY_POLL(&p, priv, AN8855_VTCR);
+ ret = readx_poll_timeout(_an8855_read, &p, val,
+ !(val & VTCR_BUSY), 20, 200000);
+ if (ret < 0) {
+ dev_err(priv->dev, "poll timeout\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+an8855_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+{
+ if (vlan_filtering) {
+ /* The port is being kept as VLAN-unaware port when bridge is
+ * set up with vlan_filtering not being set, Otherwise, the
+ * port and the corresponding CPU port is required the setup
+ * for becoming a VLAN-aware port.
+ */
+ an8855_port_set_vlan_aware(ds, port);
+ an8855_port_set_vlan_aware(ds, AN8855_CPU_PORT);
+ } else {
+ an8855_port_set_vlan_unaware(ds, port);
+ }
+
+ return 0;
+}
+
+static int
+an8855_port_vlan_prepare(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan)
+{
+ /* nothing needed */
+ return 0;
+}
+
+static void
+an8855_hw_vlan_add(struct an8855_priv *priv, struct an8855_hw_vlan_entry *entry)
+{
+ u8 new_members;
+ u32 val;
+
+ new_members = entry->old_members | BIT(entry->port) |
+ BIT(AN8855_CPU_PORT);
+
+ /* Validate the entry with independent learning, create egress tag per
+ * VLAN and joining the port as one of the port members.
+ */
+ val =
+ an8855_read(priv,
+ AN8855_VARD0) & (ETAG_CTRL_MASK << PORT_EG_CTRL_SHIFT);
+ val |= (IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID);
+ an8855_write(priv, AN8855_VAWD0, val);
+ an8855_write(priv, AN8855_VAWD1, 0);
+
+ /* Decide whether adding tag or not for those outgoing packets from the
+ * port inside the VLAN.
+ */
+ val =
+ entry->untagged ? AN8855_VLAN_EGRESS_UNTAG : AN8855_VLAN_EGRESS_TAG;
+ an8855_rmw(priv, AN8855_VAWD0,
+ ETAG_CTRL_P_MASK(entry->port) << PORT_EG_CTRL_SHIFT,
+ ETAG_CTRL_P(entry->port, val) << PORT_EG_CTRL_SHIFT);
+
+ /* CPU port is always taken as a tagged port for serving more than one
+ * VLANs across and also being applied with egress type stack mode for
+ * that VLAN tags would be appended after hardware special tag used as
+ * DSA tag.
+ */
+ an8855_rmw(priv, AN8855_VAWD0,
+ ETAG_CTRL_P_MASK(AN8855_CPU_PORT) << PORT_EG_CTRL_SHIFT,
+ ETAG_CTRL_P(AN8855_CPU_PORT,
+ AN8855_VLAN_EGRESS_STACK) << PORT_EG_CTRL_SHIFT);
+}
+
+static void
+an8855_hw_vlan_del(struct an8855_priv *priv, struct an8855_hw_vlan_entry *entry)
+{
+ u8 new_members;
+ u32 val;
+
+ new_members = entry->old_members & ~BIT(entry->port);
+
+ val = an8855_read(priv, AN8855_VARD0);
+ if (!(val & VLAN_VALID)) {
+ dev_err(priv->dev, "Cannot be deleted due to invalid entry\n");
+ return;
+ }
+
+ /* If certain member apart from CPU port is still alive in the VLAN,
+ * the entry would be kept valid. Otherwise, the entry is got to be
+ * disabled.
+ */
+ if (new_members && new_members != BIT(AN8855_CPU_PORT)) {
+ val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID;
+ an8855_write(priv, AN8855_VAWD0, val);
+ } else {
+ an8855_write(priv, AN8855_VAWD0, 0);
+ an8855_write(priv, AN8855_VAWD1, 0);
+ }
+}
+
+static void
+an8855_hw_vlan_update(struct an8855_priv *priv, u16 vid,
+ struct an8855_hw_vlan_entry *entry,
+ an8855_vlan_op vlan_op)
+{
+ u32 val;
+
+ /* Fetch entry */
+ an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid);
+
+ val = an8855_read(priv, AN8855_VARD0);
+
+ entry->old_members = (val >> PORT_MEM_SHFT) & PORT_MEM_MASK;
+
+ /* Manipulate entry */
+ vlan_op(priv, entry);
+
+ /* Flush result to hardware */
+ an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid);
+}
+
+static void
+an8855_port_vlan_add(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan)
+{
+ bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ struct an8855_hw_vlan_entry new_entry;
+ struct an8855_priv *priv = ds->priv;
+ u16 vid;
+
+ mutex_lock(&priv->reg_mutex);
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ an8855_hw_vlan_entry_init(&new_entry, port, untagged);
+ an8855_hw_vlan_update(priv, vid, &new_entry,
+ an8855_hw_vlan_add);
+ }
+
+ if (pvid) {
+ an8855_rmw(priv, AN8855_PVID_P(port), G0_PORT_VID_MASK,
+ G0_PORT_VID(vlan->vid_end));
+ priv->ports[port].pvid = vlan->vid_end;
+ }
+
+ mutex_unlock(&priv->reg_mutex);
+}
+
+static int
+an8855_port_vlan_del(struct dsa_switch *ds, int port,
+ const struct switchdev_obj_port_vlan *vlan)
+{
+ struct an8855_hw_vlan_entry target_entry;
+ struct an8855_priv *priv = ds->priv;
+ u16 vid, pvid;
+
+ mutex_lock(&priv->reg_mutex);
+
+ pvid = priv->ports[port].pvid;
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ an8855_hw_vlan_entry_init(&target_entry, port, 0);
+ an8855_hw_vlan_update(priv, vid, &target_entry,
+ an8855_hw_vlan_del);
+
+ /* PVID is being restored to the default whenever the PVID port
+ * is being removed from the VLAN.
+ */
+ if (pvid == vid)
+ pvid = G0_PORT_VID_DEF;
+ }
+
+ an8855_rmw(priv, AN8855_PVID_P(port), G0_PORT_VID_MASK, pvid);
+ priv->ports[port].pvid = pvid;
+
+ mutex_unlock(&priv->reg_mutex);
+
+ return 0;
+}
+
+static int an8855_port_mirror_add(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror,
+ bool ingress)
+{
+ struct an8855_priv *priv = ds->priv;
+ int monitor_port;
+ u32 val;
+
+ /* Check for existent entry */
+ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
+ return -EEXIST;
+
+ val = an8855_read(priv, AN8855_MIR);
+
+ /* AN8855 supports 4 monitor port, but only use first group */
+ monitor_port = AN8855_MIRROR_PORT_GET(val);
+ if (val & AN8855_MIRROR_EN && monitor_port != mirror->to_local_port)
+ return -EEXIST;
+
+ val |= AN8855_MIRROR_EN;
+ val &= ~AN8855_MIRROR_MASK;
+ val |= AN8855_MIRROR_PORT_SET(mirror->to_local_port);
+ an8855_write(priv, AN8855_MIR, val);
+
+ val = an8855_read(priv, AN8855_PCR_P(port));
+ if (ingress) {
+ val |= PORT_RX_MIR;
+ priv->mirror_rx |= BIT(port);
+ } else {
+ val |= PORT_TX_MIR;
+ priv->mirror_tx |= BIT(port);
+ }
+ an8855_write(priv, AN8855_PCR_P(port), val);
+
+ return 0;
+}
+
+static void an8855_port_mirror_del(struct dsa_switch *ds, int port,
+ struct dsa_mall_mirror_tc_entry *mirror)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 val;
+
+ val = an8855_read(priv, AN8855_PCR_P(port));
+ if (mirror->ingress) {
+ val &= ~PORT_RX_MIR;
+ priv->mirror_rx &= ~BIT(port);
+ } else {
+ val &= ~PORT_TX_MIR;
+ priv->mirror_tx &= ~BIT(port);
+ }
+ an8855_write(priv, AN8855_PCR_P(port), val);
+
+ if (!priv->mirror_rx && !priv->mirror_tx) {
+ val = an8855_read(priv, AN8855_MIR);
+ val &= ~AN8855_MIRROR_EN;
+ an8855_write(priv, AN8855_MIR, val);
+ }
+}
+
+static enum dsa_tag_protocol
+air_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ if (port != AN8855_CPU_PORT) {
+ dev_warn(priv->dev, "port not matched with tagging CPU port\n");
+ return DSA_TAG_PROTO_NONE;
+ } else {
+ return DSA_TAG_PROTO_ARHT;
+ }
+}
+
+static int
+setup_unused_ports(struct dsa_switch *ds, u32 pm)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 egtag_mask = 0;
+ u32 egtag_val = 0;
+ int i;
+
+ if (!pm)
+ return 0;
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ if (!dsa_is_unused_port(ds, i))
+ continue;
+
+ /* Setup MAC port with maximum capability. */
+ if (i == 5)
+ if (priv->info->cpu_port_config)
+ priv->info->cpu_port_config(ds, i);
+
+ an8855_rmw(priv, AN8855_PORTMATRIX_P(i), PORTMATRIX_MASK,
+ AN8855_PORTMATRIX_P(pm));
+ an8855_rmw(priv, AN8855_PCR_P(i), PCR_PORT_VLAN_MASK,
+ AN8855_PORT_SECURITY_MODE);
+ egtag_mask |= ETAG_CTRL_P_MASK(i);
+ egtag_val |= ETAG_CTRL_P(i, AN8855_VLAN_EGRESS_UNTAG);
+ }
+
+ /* Add unused ports to VLAN2 group for using IVL fdb. */
+ an8855_write(priv, AN8855_VAWD0,
+ IVL_MAC | VTAG_EN | PORT_MEM(pm) | VLAN_VALID);
+ an8855_rmw(priv, AN8855_VAWD0, egtag_mask << PORT_EG_CTRL_SHIFT,
+ egtag_val << PORT_EG_CTRL_SHIFT);
+ an8855_write(priv, AN8855_VAWD1, 0);
+ an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, AN8855_RESERVED_VLAN);
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ if (!dsa_is_unused_port(ds, i))
+ continue;
+
+ an8855_rmw(priv, AN8855_PVID_P(i), G0_PORT_VID_MASK,
+ G0_PORT_VID(AN8855_RESERVED_VLAN));
+ an8855_rmw(priv, AN8855_SSP_P(i), FID_PST_MASK,
+ AN8855_STP_FORWARDING);
+
+ dev_dbg(ds->dev, "Add unused port%d to reserved VLAN%d group\n",
+ i, AN8855_RESERVED_VLAN);
+ }
+
+ return 0;
+}
+
+static int
+an8855_setup(struct dsa_switch *ds)
+{
+ struct an8855_priv *priv = ds->priv;
+ struct an8855_dummy_poll p;
+ u32 unused_pm = 0;
+ u32 val, id;
+ int ret, i;
+
+ /* Reset whole chip through gpio pin or memory-mapped registers for
+ * different type of hardware
+ */
+ gpiod_set_value_cansleep(priv->reset, 0);
+ usleep_range(100000, 150000);
+ gpiod_set_value_cansleep(priv->reset, 1);
+ usleep_range(100000, 150000);
+
+ /* Waiting for AN8855 got to stable */
+ INIT_AN8855_DUMMY_POLL(&p, priv, 0x1000009c);
+ ret = readx_poll_timeout(_an8855_read, &p, val, val != 0, 20, 1000000);
+ if (ret < 0) {
+ dev_err(priv->dev, "reset timeout\n");
+ return ret;
+ }
+
+ id = an8855_read(priv, AN8855_CREV);
+ if (id != AN8855_ID) {
+ dev_err(priv->dev, "chip %x can't be supported\n", id);
+ return -ENODEV;
+ }
+
+ /* Reset the switch through internal reset */
+ an8855_write(priv, AN8855_RST_CTRL, SYS_CTRL_SYS_RST);
+ usleep_range(100000, 110000);
+
+ /* change gphy smi address */
+ if (priv->phy_base_new > 0) {
+ an8855_write(priv, RG_GPHY_SMI_ADDR, priv->phy_base_new);
+ priv->phy_base = priv->phy_base_new;
+ }
+
+ /* Let phylink decide the interface later. */
+ priv->p5_interface = PHY_INTERFACE_MODE_NA;
+
+ /* BPDU to CPU port */
+ //an8855_rmw(priv, AN8855_CFC, AN8855_CPU_PMAP_MASK,
+ // BIT(AN8855_CPU_PORT));
+ an8855_rmw(priv, AN8855_BPC, AN8855_BPDU_PORT_FW_MASK,
+ AN8855_BPDU_CPU_ONLY);
+
+ /* Enable and reset MIB counters */
+ an8855_mib_reset(ds);
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ /* Disable forwarding by default on all ports */
+ an8855_rmw(priv, AN8855_PORTMATRIX_P(i), PORTMATRIX_MASK,
+ PORTMATRIX_CLR);
+ if (dsa_is_unused_port(ds, i))
+ unused_pm |= BIT(i);
+ else if (dsa_is_cpu_port(ds, i))
+ an8855_cpu_port_enable(ds, i);
+ else
+ an8855_port_disable(ds, i);
+ /* Enable consistent egress tag */
+ an8855_rmw(priv, AN8855_PVC_P(i), PVC_EG_TAG_MASK,
+ PVC_EG_TAG(AN8855_VLAN_EG_CONSISTENT));
+ }
+
+ an8855_phy_setup(ds);
+
+ /* Group and enable unused ports as a standalone dumb switch. */
+ setup_unused_ports(ds, unused_pm);
+
+ ds->configure_vlan_while_not_filtering = true;
+
+ /* Flush the FDB table */
+ ret = an8855_fdb_cmd(priv, AN8855_FDB_FLUSH, NULL);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static bool
+an8855_phy_supported(struct dsa_switch *ds, int port,
+ const struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ switch (port) {
+ case 0: /* Internal phy */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (state->interface != PHY_INTERFACE_MODE_GMII)
+ goto unsupported;
+ break;
+ case 5:
+ if (state->interface != PHY_INTERFACE_MODE_SGMII
+ && state->interface != PHY_INTERFACE_MODE_RGMII
+ && state->interface != PHY_INTERFACE_MODE_2500BASEX)
+ goto unsupported;
+ break;
+ default:
+ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
+ port);
+ goto unsupported;
+ }
+
+ return true;
+
+unsupported:
+ return false;
+}
+
+static bool
+an8855_phy_mode_supported(struct dsa_switch *ds, int port,
+ const struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->phy_mode_supported(ds, port, state);
+}
+
+static int
+an8855_rgmii_setup(struct an8855_priv *priv, u32 port,
+ phy_interface_t interface,
+ struct phy_device *phydev)
+{
+ return 0;
+}
+
+static void
+an8855_sgmii_validate(struct an8855_priv *priv, int port,
+ unsigned long *supported)
+{
+ switch (port) {
+ case 5:
+ phylink_set(supported, 1000baseX_Full);
+ phylink_set(supported, 2500baseX_Full);
+ }
+}
+
+static void
+an8855_sgmii_link_up_force(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex)
+{
+ /* For adjusting speed and duplex of SGMII force mode. */
+ if (interface != PHY_INTERFACE_MODE_SGMII ||
+ phylink_autoneg_inband(mode))
+ return;
+}
+
+static bool
+an8855_is_mac_port(u32 port)
+{
+ return (port == 5);
+}
+
+static int
+an8855_set_hsgmii_mode(struct an8855_priv *priv)
+{
+ u32 val = 0;
+
+ /* PLL */
+ val = an8855_read(priv, QP_DIG_MODE_CTRL_1);
+ val &= ~(0x3 << 2);
+ val |= (0x1 << 2);
+ an8855_write(priv, QP_DIG_MODE_CTRL_1, val);
+
+ /* PLL - LPF */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0x3 << 0);
+ val |= (0x1 << 0);
+ val &= ~(0x7 << 2);
+ val |= (0x5 << 2);
+ val &= ~BITS(6, 7);
+ val &= ~(0x7 << 8);
+ val |= (0x3 << 8);
+ val |= BIT(29);
+ val &= ~BITS(12, 13);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - ICO */
+ val = an8855_read(priv, PLL_CTRL_4);
+ val |= BIT(2);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~BIT(14);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - CHP */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0xf << 16);
+ val |= (0x6 << 16);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - PFD */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0x3 << 20);
+ val |= (0x1 << 20);
+ val &= ~(0x3 << 24);
+ val |= (0x1 << 24);
+ val &= ~BIT(26);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - POSTDIV */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val |= BIT(22);
+ val &= ~BIT(27);
+ val &= ~BIT(28);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - SDM */
+ val = an8855_read(priv, PLL_CTRL_4);
+ val &= ~BITS(3, 4);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~BIT(30);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ val = an8855_read(priv, SS_LCPLL_PWCTL_SETTING_2);
+ val &= ~(0x3 << 16);
+ val |= (0x1 << 16);
+ an8855_write(priv, SS_LCPLL_PWCTL_SETTING_2, val);
+
+ an8855_write(priv, SS_LCPLL_TDC_FLT_2, 0x7a000000);
+ an8855_write(priv, SS_LCPLL_TDC_PCW_1, 0x7a000000);
+
+ val = an8855_read(priv, SS_LCPLL_TDC_FLT_5);
+ val &= ~BIT(24);
+ an8855_write(priv, SS_LCPLL_TDC_FLT_5, val);
+
+ val = an8855_read(priv, PLL_CK_CTRL_0);
+ val &= ~BIT(8);
+ an8855_write(priv, PLL_CK_CTRL_0, val);
+
+ /* PLL - SS */
+ val = an8855_read(priv, PLL_CTRL_3);
+ val &= ~BITS(0, 15);
+ an8855_write(priv, PLL_CTRL_3, val);
+
+ val = an8855_read(priv, PLL_CTRL_4);
+ val &= ~BITS(0, 1);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_3);
+ val &= ~BITS(16, 31);
+ an8855_write(priv, PLL_CTRL_3, val);
+
+ /* PLL - TDC */
+ val = an8855_read(priv, PLL_CK_CTRL_0);
+ val &= ~BIT(9);
+ an8855_write(priv, PLL_CK_CTRL_0, val);
+
+ val = an8855_read(priv, RG_QP_PLL_SDM_ORD);
+ val |= BIT(3);
+ val |= BIT(4);
+ an8855_write(priv, RG_QP_PLL_SDM_ORD, val);
+
+ val = an8855_read(priv, RG_QP_RX_DAC_EN);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ an8855_write(priv, RG_QP_RX_DAC_EN, val);
+
+ /* TCL Disable (only for Co-SIM) */
+ val = an8855_read(priv, PON_RXFEDIG_CTRL_0);
+ val &= ~BIT(12);
+ an8855_write(priv, PON_RXFEDIG_CTRL_0, val);
+
+ /* TX Init */
+ val = an8855_read(priv, RG_QP_TX_MODE_16B_EN);
+ val &= ~BIT(0);
+ val &= ~(0xffff << 16);
+ val |= (0x4 << 16);
+ an8855_write(priv, RG_QP_TX_MODE_16B_EN, val);
+
+ /* RX Control */
+ val = an8855_read(priv, RG_QP_RXAFE_RESERVE);
+ val |= BIT(11);
+ an8855_write(priv, RG_QP_RXAFE_RESERVE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_LPF_MJV_LIM);
+ val &= ~(0x3 << 4);
+ val |= (0x1 << 4);
+ an8855_write(priv, RG_QP_CDR_LPF_MJV_LIM, val);
+
+ val = an8855_read(priv, RG_QP_CDR_LPF_SETVALUE);
+ val &= ~(0xf << 25);
+ val |= (0x1 << 25);
+ val &= ~(0x7 << 29);
+ val |= (0x3 << 29);
+ an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x1f << 8);
+ val |= (0xf << 8);
+ an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~(0x3f << 0);
+ val |= (0x19 << 0);
+ val &= ~BIT(6);
+ an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF);
+ val &= ~(0x7f << 6);
+ val |= (0x21 << 6);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ val &= ~BIT(13);
+ an8855_write(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~BIT(30);
+ an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x7 << 24);
+ val |= (0x4 << 24);
+ an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_read(priv, PLL_CTRL_0);
+ val |= BIT(0);
+ an8855_write(priv, PLL_CTRL_0, val);
+
+ val = an8855_read(priv, RX_CTRL_26);
+ val &= ~BIT(23);
+ val |= BIT(26);
+ an8855_write(priv, RX_CTRL_26, val);
+
+ val = an8855_read(priv, RX_DLY_0);
+ val &= ~(0xff << 0);
+ val |= (0x6f << 0);
+ val |= BITS(8, 13);
+ an8855_write(priv, RX_DLY_0, val);
+
+ val = an8855_read(priv, RX_CTRL_42);
+ val &= ~(0x1fff << 0);
+ val |= (0x150 << 0);
+ an8855_write(priv, RX_CTRL_42, val);
+
+ val = an8855_read(priv, RX_CTRL_2);
+ val &= ~(0x1fff << 16);
+ val |= (0x150 << 16);
+ an8855_write(priv, RX_CTRL_2, val);
+
+ val = an8855_read(priv, PON_RXFEDIG_CTRL_9);
+ val &= ~(0x7 << 0);
+ val |= (0x1 << 0);
+ an8855_write(priv, PON_RXFEDIG_CTRL_9, val);
+
+ val = an8855_read(priv, RX_CTRL_8);
+ val &= ~(0xfff << 16);
+ val |= (0x200 << 16);
+ val &= ~(0x7fff << 14);
+ val |= (0xfff << 14);
+ an8855_write(priv, RX_CTRL_8, val);
+
+ /* Frequency memter */
+ val = an8855_read(priv, RX_CTRL_5);
+ val &= ~(0xfffff << 10);
+ val |= (0x10 << 10);
+ an8855_write(priv, RX_CTRL_5, val);
+
+ val = an8855_read(priv, RX_CTRL_6);
+ val &= ~(0xfffff << 0);
+ val |= (0x64 << 0);
+ an8855_write(priv, RX_CTRL_6, val);
+
+ val = an8855_read(priv, RX_CTRL_7);
+ val &= ~(0xfffff << 0);
+ val |= (0x2710 << 0);
+ an8855_write(priv, RX_CTRL_7, val);
+
+ /* PCS Init */
+ val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Rate Adaption */
+ val = an8855_read(priv, RATE_ADP_P0_CTRL_0);
+ val &= ~BIT(31);
+ an8855_write(priv, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val);
+
+ /* Disable AN */
+ val = an8855_read(priv, SGMII_REG_AN0);
+ val &= ~BIT(12);
+ an8855_write(priv, SGMII_REG_AN0, val);
+
+ /* Force Speed */
+ val = an8855_read(priv, SGMII_STS_CTRL_0);
+ val |= BIT(2);
+ val |= BITS(4, 5);
+ an8855_write(priv, SGMII_STS_CTRL_0, val);
+
+ /* bypass flow control to MAC */
+ an8855_write(priv, MSG_RX_LIK_STS_0, 0x01010107);
+ an8855_write(priv, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return 0;
+}
+
+static int
+an8855_sgmii_setup(struct an8855_priv *priv, int mode)
+{
+ u32 val = 0;
+
+ /* PMA Init */
+ /* PLL */
+ val = an8855_read(priv, QP_DIG_MODE_CTRL_1);
+ val &= ~BITS(2, 3);
+ an8855_write(priv, QP_DIG_MODE_CTRL_1, val);
+
+ /* PLL - LPF */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0x3 << 0);
+ val |= (0x1 << 0);
+ val &= ~(0x7 << 2);
+ val |= (0x5 << 2);
+ val &= ~BITS(6, 7);
+ val &= ~(0x7 << 8);
+ val |= (0x3 << 8);
+ val |= BIT(29);
+ val &= ~BITS(12, 13);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - ICO */
+ val = an8855_read(priv, PLL_CTRL_4);
+ val |= BIT(2);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~BIT(14);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - CHP */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0xf << 16);
+ val |= (0x4 << 16);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - PFD */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~(0x3 << 20);
+ val |= (0x1 << 20);
+ val &= ~(0x3 << 24);
+ val |= (0x1 << 24);
+ val &= ~BIT(26);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - POSTDIV */
+ val = an8855_read(priv, PLL_CTRL_2);
+ val |= BIT(22);
+ val &= ~BIT(27);
+ val &= ~BIT(28);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ /* PLL - SDM */
+ val = an8855_read(priv, PLL_CTRL_4);
+ val &= ~BITS(3, 4);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_2);
+ val &= ~BIT(30);
+ an8855_write(priv, PLL_CTRL_2, val);
+
+ val = an8855_read(priv, SS_LCPLL_PWCTL_SETTING_2);
+ val &= ~(0x3 << 16);
+ val |= (0x1 << 16);
+ an8855_write(priv, SS_LCPLL_PWCTL_SETTING_2, val);
+
+ an8855_write(priv, SS_LCPLL_TDC_FLT_2, 0x48000000);
+ an8855_write(priv, SS_LCPLL_TDC_PCW_1, 0x48000000);
+
+ val = an8855_read(priv, SS_LCPLL_TDC_FLT_5);
+ val &= ~BIT(24);
+ an8855_write(priv, SS_LCPLL_TDC_FLT_5, val);
+
+ val = an8855_read(priv, PLL_CK_CTRL_0);
+ val &= ~BIT(8);
+ an8855_write(priv, PLL_CK_CTRL_0, val);
+
+ /* PLL - SS */
+ val = an8855_read(priv, PLL_CTRL_3);
+ val &= ~BITS(0, 15);
+ an8855_write(priv, PLL_CTRL_3, val);
+
+ val = an8855_read(priv, PLL_CTRL_4);
+ val &= ~BITS(0, 1);
+ an8855_write(priv, PLL_CTRL_4, val);
+
+ val = an8855_read(priv, PLL_CTRL_3);
+ val &= ~BITS(16, 31);
+ an8855_write(priv, PLL_CTRL_3, val);
+
+ /* PLL - TDC */
+ val = an8855_read(priv, PLL_CK_CTRL_0);
+ val &= ~BIT(9);
+ an8855_write(priv, PLL_CK_CTRL_0, val);
+
+ val = an8855_read(priv, RG_QP_PLL_SDM_ORD);
+ val |= BIT(3);
+ val |= BIT(4);
+ an8855_write(priv, RG_QP_PLL_SDM_ORD, val);
+
+ val = an8855_read(priv, RG_QP_RX_DAC_EN);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ an8855_write(priv, RG_QP_RX_DAC_EN, val);
+
+ /* PLL - TCL Disable (only for Co-SIM) */
+ val = an8855_read(priv, PON_RXFEDIG_CTRL_0);
+ val &= ~BIT(12);
+ an8855_write(priv, PON_RXFEDIG_CTRL_0, val);
+
+ /* TX Init */
+ val = an8855_read(priv, RG_QP_TX_MODE_16B_EN);
+ val &= ~BIT(0);
+ val &= ~BITS(16, 31);
+ an8855_write(priv, RG_QP_TX_MODE_16B_EN, val);
+
+ /* RX Init */
+ val = an8855_read(priv, RG_QP_RXAFE_RESERVE);
+ val |= BIT(11);
+ an8855_write(priv, RG_QP_RXAFE_RESERVE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_LPF_MJV_LIM);
+ val &= ~(0x3 << 4);
+ val |= (0x2 << 4);
+ an8855_write(priv, RG_QP_CDR_LPF_MJV_LIM, val);
+
+ val = an8855_read(priv, RG_QP_CDR_LPF_SETVALUE);
+ val &= ~(0xf << 25);
+ val |= (0x1 << 25);
+ val &= ~(0x7 << 29);
+ val |= (0x6 << 29);
+ an8855_write(priv, RG_QP_CDR_LPF_SETVALUE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x1f << 8);
+ val |= (0xc << 8);
+ an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~(0x3f << 0);
+ val |= (0x19 << 0);
+ val &= ~BIT(6);
+ an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF);
+ val &= ~(0x7f << 6);
+ val |= (0x21 << 6);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ val &= ~BIT(13);
+ an8855_write(priv, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~BIT(30);
+ an8855_write(priv, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_read(priv, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x7 << 24);
+ val |= (0x4 << 24);
+ an8855_write(priv, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_read(priv, PLL_CTRL_0);
+ val |= BIT(0);
+ an8855_write(priv, PLL_CTRL_0, val);
+
+ val = an8855_read(priv, RX_CTRL_26);
+ val &= ~BIT(23);
+ if (mode == SGMII_MODE_AN)
+ val |= BIT(26);
+
+ an8855_write(priv, RX_CTRL_26, val);
+
+ val = an8855_read(priv, RX_DLY_0);
+ val &= ~(0xff << 0);
+ val |= (0x6f << 0);
+ val |= BITS(8, 13);
+ an8855_write(priv, RX_DLY_0, val);
+
+ val = an8855_read(priv, RX_CTRL_42);
+ val &= ~(0x1fff << 0);
+ val |= (0x150 << 0);
+ an8855_write(priv, RX_CTRL_42, val);
+
+ val = an8855_read(priv, RX_CTRL_2);
+ val &= ~(0x1fff << 16);
+ val |= (0x150 << 16);
+ an8855_write(priv, RX_CTRL_2, val);
+
+ val = an8855_read(priv, PON_RXFEDIG_CTRL_9);
+ val &= ~(0x7 << 0);
+ val |= (0x1 << 0);
+ an8855_write(priv, PON_RXFEDIG_CTRL_9, val);
+
+ val = an8855_read(priv, RX_CTRL_8);
+ val &= ~(0xfff << 16);
+ val |= (0x200 << 16);
+ val &= ~(0x7fff << 0);
+ val |= (0xfff << 0);
+ an8855_write(priv, RX_CTRL_8, val);
+
+ /* Frequency memter */
+ val = an8855_read(priv, RX_CTRL_5);
+ val &= ~(0xfffff << 10);
+ val |= (0x28 << 10);
+ an8855_write(priv, RX_CTRL_5, val);
+
+ val = an8855_read(priv, RX_CTRL_6);
+ val &= ~(0xfffff << 0);
+ val |= (0x64 << 0);
+ an8855_write(priv, RX_CTRL_6, val);
+
+ val = an8855_read(priv, RX_CTRL_7);
+ val &= ~(0xfffff << 0);
+ val |= (0x2710 << 0);
+ an8855_write(priv, RX_CTRL_7, val);
+
+ if (mode == SGMII_MODE_FORCE) {
+ /* PCS Init */
+ val = an8855_read(priv, QP_DIG_MODE_CTRL_0);
+ val &= ~BIT(0);
+ val &= ~BITS(4, 5);
+ an8855_write(priv, QP_DIG_MODE_CTRL_0, val);
+
+ val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Rate Adaption - GMII path config. */
+ val = an8855_read(priv, RG_AN_SGMII_MODE_FORCE);
+ val |= BIT(0);
+ val &= ~BITS(4, 5);
+ an8855_write(priv, RG_AN_SGMII_MODE_FORCE, val);
+
+ val = an8855_read(priv, SGMII_STS_CTRL_0);
+ val |= BIT(2);
+ val &= ~(0x3 << 4);
+ val |= (0x2 << 4);
+ an8855_write(priv, SGMII_STS_CTRL_0, val);
+
+ val = an8855_read(priv, SGMII_REG_AN0);
+ val &= ~BIT(12);
+ an8855_write(priv, SGMII_REG_AN0, val);
+
+ val = an8855_read(priv, PHY_RX_FORCE_CTRL_0);
+ val |= BIT(4);
+ an8855_write(priv, PHY_RX_FORCE_CTRL_0, val);
+
+ val = an8855_read(priv, RATE_ADP_P0_CTRL_0);
+ val &= ~BITS(0, 3);
+ val |= BIT(28);
+ an8855_write(priv, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val);
+ } else {
+ /* PCS Init */
+ val = an8855_read(priv, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_write(priv, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Set AN Ability - Interrupt */
+ val = an8855_read(priv, SGMII_REG_AN_FORCE_CL37);
+ val |= BIT(0);
+ an8855_write(priv, SGMII_REG_AN_FORCE_CL37, val);
+
+ val = an8855_read(priv, SGMII_REG_AN_13);
+ val &= ~(0x3f << 0);
+ val |= (0xb << 0);
+ val |= BIT(8);
+ an8855_write(priv, SGMII_REG_AN_13, val);
+
+ /* Rate Adaption - GMII path config. */
+ val = an8855_read(priv, SGMII_REG_AN0);
+ val |= BIT(12);
+ an8855_write(priv, SGMII_REG_AN0, val);
+
+ val = an8855_read(priv, MII_RA_AN_ENABLE);
+ val |= BIT(0);
+ an8855_write(priv, MII_RA_AN_ENABLE, val);
+
+ val = an8855_read(priv, RATE_ADP_P0_CTRL_0);
+ val |= BIT(28);
+ an8855_write(priv, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_read(priv, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_write(priv, RG_RATE_ADAPT_CTRL_0, val);
+
+ /* Only for Co-SIM */
+
+ /* AN Speed up (Only for Co-SIM) */
+
+ /* Restart AN */
+ val = an8855_read(priv, SGMII_REG_AN0);
+ val |= BIT(9);
+ val |= BIT(15);
+ an8855_write(priv, SGMII_REG_AN0, val);
+ }
+
+ /* bypass flow control to MAC */
+ an8855_write(priv, MSG_RX_LIK_STS_0, 0x01010107);
+ an8855_write(priv, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return 0;
+}
+
+static int
+an8855_sgmii_setup_mode_force(struct an8855_priv *priv, u32 port,
+ phy_interface_t interface)
+{
+ return an8855_sgmii_setup(priv, SGMII_MODE_FORCE);
+}
+
+static int
+an8855_sgmii_setup_mode_an(struct an8855_priv *priv, int port,
+ phy_interface_t interface)
+{
+ return an8855_sgmii_setup(priv, SGMII_MODE_AN);
+}
+
+static int
+an8855_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+{
+ struct an8855_priv *priv = ds->priv;
+ struct phy_device *phydev;
+ const struct dsa_port *dp;
+
+ if (!an8855_is_mac_port(port)) {
+ dev_err(priv->dev, "port %d is not a MAC port\n", port);
+ return -EINVAL;
+ }
+
+ switch (interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ dp = dsa_to_port(ds, port);
+ phydev = (dp->slave) ? dp->slave->phydev : NULL;
+ return an8855_rgmii_setup(priv, port, interface, phydev);
+ case PHY_INTERFACE_MODE_SGMII:
+ return an8855_sgmii_setup_mode_an(priv, port, interface);
+ case PHY_INTERFACE_MODE_2500BASEX:
+ if (phylink_autoneg_inband(mode))
+ return -EINVAL;
+ return an8855_set_hsgmii_mode(priv);
+ default:
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+}
+
+static int
+an8855_sw_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->mac_port_config(ds, port, mode, state->interface);
+}
+
+static void
+an8855_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 mcr_cur, mcr_new;
+
+ if (!an8855_phy_mode_supported(ds, port, state))
+ goto unsupported;
+
+ switch (port) {
+ case 0: /* Internal phy */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (state->interface != PHY_INTERFACE_MODE_GMII)
+ goto unsupported;
+ break;
+ case 5:
+ if (priv->p5_interface == state->interface)
+ break;
+
+ if (an8855_sw_mac_config(ds, port, mode, state) < 0)
+ goto unsupported;
+
+ priv->p5_interface = state->interface;
+ break;
+ default:
+unsupported:
+ dev_err(ds->dev, "%s: unsupported %s port: %i\n",
+ __func__, phy_modes(state->interface), port);
+ return;
+ }
+
+ if (phylink_autoneg_inband(mode) &&
+ state->interface != PHY_INTERFACE_MODE_SGMII) {
+ dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
+ __func__);
+ return;
+ }
+
+ mcr_cur = an8855_read(priv, AN8855_PMCR_P(port));
+ mcr_new = mcr_cur;
+ mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
+ mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
+ PMCR_BACKPR_EN | AN8855_FORCE_MODE;
+
+ if (mcr_new != mcr_cur)
+ an8855_write(priv, AN8855_PMCR_P(port), mcr_new);
+}
+
+static void
+an8855_phylink_mac_link_down(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ an8855_clear(priv, AN8855_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+}
+
+static void
+an8855_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface,
+ struct phy_device *phydev,
+ int speed, int duplex,
+ bool tx_pause, bool rx_pause)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 mcr;
+
+ mcr = an8855_read(priv, AN8855_PMCR_P(port));
+ mcr |= PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
+ mcr &=
+ ~(PMCR_FORCE_FDX | PMCR_SPEED_MASK | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
+
+ if (interface == PHY_INTERFACE_MODE_RGMII
+ || interface == PHY_INTERFACE_MODE_SGMII) {
+ speed = SPEED_1000;
+ duplex = DUPLEX_FULL;
+ } else if (interface == PHY_INTERFACE_MODE_2500BASEX) {
+ speed = SPEED_2500;
+ duplex = DUPLEX_FULL;
+ }
+
+ switch (speed) {
+ case SPEED_2500:
+ mcr |= PMCR_FORCE_SPEED_2500;
+ break;
+ case SPEED_1000:
+ mcr |= PMCR_FORCE_SPEED_1000;
+ if (priv->eee_enable & BIT(port))
+ mcr |= PMCR_FORCE_EEE1G;
+ break;
+ case SPEED_100:
+ mcr |= PMCR_FORCE_SPEED_100;
+ if (priv->eee_enable & BIT(port))
+ mcr |= PMCR_FORCE_EEE100;
+ break;
+ }
+ if (duplex == DUPLEX_FULL) {
+ mcr |= PMCR_FORCE_FDX;
+ if (tx_pause)
+ mcr |= PMCR_TX_FC_EN;
+ if (rx_pause)
+ mcr |= PMCR_RX_FC_EN;
+ }
+
+ an8855_write(priv, AN8855_PMCR_P(port), mcr);
+}
+
+static int
+an8855_cpu_port_config(struct dsa_switch *ds, int port)
+{
+ struct an8855_priv *priv = ds->priv;
+ phy_interface_t interface = PHY_INTERFACE_MODE_NA;
+ int speed;
+
+ switch (port) {
+ case 5:
+ interface = PHY_INTERFACE_MODE_2500BASEX;
+
+ priv->p5_interface = interface;
+ break;
+ };
+ if (interface == PHY_INTERFACE_MODE_NA)
+ dev_err(priv->dev, "invalid interface\n");
+
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ speed = SPEED_2500;
+ else
+ speed = SPEED_1000;
+
+ an8855_mac_config(ds, port, MLO_AN_FIXED, interface);
+ an8855_write(priv, AN8855_PMCR_P(port),
+ PMCR_CPU_PORT_SETTING(priv->id));
+ an8855_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
+ speed, DUPLEX_FULL, true, true);
+
+ return 0;
+}
+
+static void
+an8855_mac_port_validate(struct dsa_switch *ds, int port,
+ unsigned long *supported)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ an8855_sgmii_validate(priv, port, supported);
+}
+
+static void
+an8855_phylink_validate(struct dsa_switch *ds, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = {0,};
+
+ if (state->interface != PHY_INTERFACE_MODE_NA &&
+ !an8855_phy_mode_supported(ds, port, state)) {
+ linkmode_zero(supported);
+ return;
+ }
+
+ phylink_set_port_modes(mask);
+
+ if (state->interface != PHY_INTERFACE_MODE_TRGMII
+ || state->interface != PHY_INTERFACE_MODE_USXGMII
+ || state->interface != PHY_INTERFACE_MODE_10GKR
+ || !phy_interface_mode_is_8023z(state->interface)) {
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ phylink_set(mask, Autoneg);
+ }
+
+ /* This switch only supports 1G full-duplex. */
+ if (state->interface != PHY_INTERFACE_MODE_MII)
+ phylink_set(mask, 1000baseT_Full);
+
+ priv->info->mac_port_validate(ds, port, mask);
+
+ phylink_set(mask, Pause);
+ phylink_set(mask, Asym_Pause);
+
+ linkmode_and(supported, supported, mask);
+ linkmode_and(state->advertising, state->advertising, mask);
+
+ /* We can only operate at 2500BaseX or 1000BaseX. If requested
+ * to advertise both, only report advertising at 2500BaseX.
+ */
+ phylink_helper_basex_speed(state);
+}
+
+static int
+an8855_get_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_eee *e)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 eeecr, pmsr, ckgcr;
+
+ e->eee_enabled = !!(priv->eee_enable & BIT(port));
+
+ if (e->eee_enabled) {
+ eeecr = an8855_read(priv, AN8855_PMEEECR_P(port));
+ e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN);
+ ckgcr = an8855_read(priv, AN8855_CKGCR);
+ e->tx_lpi_timer =
+ ((ckgcr & LPI_TXIDLE_THD_MASK) >> LPI_TXIDLE_THD) / 500;
+ pmsr = an8855_read(priv, AN8855_PMSR_P(port));
+ e->eee_active = e->eee_enabled
+ && !!(pmsr & (PMSR_EEE1G | PMSR_EEE100M));
+ } else {
+ e->tx_lpi_enabled = 0;
+ e->tx_lpi_timer = 0;
+ e->eee_active = 0;
+ }
+ return 0;
+}
+
+static int
+an8855_set_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_eee *e)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 eeecr;
+
+ if (e->eee_enabled) {
+ priv->eee_enable |= BIT(port);
+ eeecr = an8855_read(priv, AN8855_PMEEECR_P(port));
+ eeecr &= ~LPI_MODE_EN;
+ if (e->tx_lpi_enabled)
+ eeecr |= LPI_MODE_EN;
+ an8855_write(priv, AN8855_PMEEECR_P(port), eeecr);
+ } else {
+ priv->eee_enable &= ~(BIT(port));
+ eeecr = an8855_read(priv, AN8855_PMEEECR_P(port));
+ eeecr &= ~LPI_MODE_EN;
+ an8855_write(priv, AN8855_PMEEECR_P(port), eeecr);
+ }
+
+ return 0;
+}
+
+static int
+an8855_phylink_mac_link_state(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 pmsr;
+
+ if (port < 0 || port >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ pmsr = an8855_read(priv, AN8855_PMSR_P(port));
+
+ state->link = (pmsr & PMSR_LINK);
+ state->an_complete = state->link;
+ state->duplex = !!(pmsr & PMSR_DPX);
+
+ switch (pmsr & PMSR_SPEED_MASK) {
+ case PMSR_SPEED_10:
+ state->speed = SPEED_10;
+ break;
+ case PMSR_SPEED_100:
+ state->speed = SPEED_100;
+ break;
+ case PMSR_SPEED_1000:
+ state->speed = SPEED_1000;
+ break;
+ case PMSR_SPEED_2500:
+ state->speed = SPEED_2500;
+ break;
+ default:
+ state->speed = SPEED_UNKNOWN;
+ break;
+ }
+
+ state->pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX);
+ if (pmsr & PMSR_RX_FC)
+ state->pause |= MLO_PAUSE_RX;
+ if (pmsr & PMSR_TX_FC)
+ state->pause |= MLO_PAUSE_TX;
+
+ return 1;
+}
+
+static int
+an8855_sw_phylink_mac_link_state(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->mac_port_get_state(ds, port, state);
+}
+
+static int
+an8855_sw_setup(struct dsa_switch *ds)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->sw_setup(ds);
+}
+
+static int
+an8855_sw_phy_read(struct dsa_switch *ds, int port, int regnum)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->phy_read(ds, port, regnum);
+}
+
+static int
+an8855_sw_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->phy_write(ds, port, regnum, val);
+}
+
+static const struct dsa_switch_ops an8855_switch_ops = {
+ .get_tag_protocol = air_get_tag_protocol,
+ .setup = an8855_sw_setup,
+ .get_strings = an8855_get_strings,
+ .phy_read = an8855_sw_phy_read,
+ .phy_write = an8855_sw_phy_write,
+ .get_ethtool_stats = an8855_get_ethtool_stats,
+ .get_sset_count = an8855_get_sset_count,
+ .port_enable = an8855_port_enable,
+ .port_disable = an8855_port_disable,
+ .port_stp_state_set = an8855_stp_state_set,
+ .port_bridge_join = an8855_port_bridge_join,
+ .port_bridge_leave = an8855_port_bridge_leave,
+ .port_fdb_add = an8855_port_fdb_add,
+ .port_fdb_del = an8855_port_fdb_del,
+ .port_fdb_dump = an8855_port_fdb_dump,
+ .port_vlan_filtering = an8855_port_vlan_filtering,
+ .port_vlan_prepare = an8855_port_vlan_prepare,
+ .port_vlan_add = an8855_port_vlan_add,
+ .port_vlan_del = an8855_port_vlan_del,
+ .port_mirror_add = an8855_port_mirror_add,
+ .port_mirror_del = an8855_port_mirror_del,
+ .phylink_validate = an8855_phylink_validate,
+ .phylink_mac_link_state = an8855_sw_phylink_mac_link_state,
+ .phylink_mac_config = an8855_phylink_mac_config,
+ .phylink_mac_link_down = an8855_phylink_mac_link_down,
+ .phylink_mac_link_up = an8855_phylink_mac_link_up,
+ .get_mac_eee = an8855_get_mac_eee,
+ .set_mac_eee = an8855_set_mac_eee,
+};
+
+static const struct an8855_dev_info an8855_table[] = {
+ [ID_AN8855] = {
+ .id = ID_AN8855,
+ .sw_setup = an8855_setup,
+ .phy_read = an8855_phy_read,
+ .phy_write = an8855_phy_write,
+ .pad_setup = an8855_pad_setup,
+ .cpu_port_config = an8855_cpu_port_config,
+ .phy_mode_supported = an8855_phy_supported,
+ .mac_port_validate = an8855_mac_port_validate,
+ .mac_port_get_state = an8855_phylink_mac_link_state,
+ .mac_port_config = an8855_mac_config,
+ },
+};
+
+static const struct of_device_id an8855_of_match[] = {
+ {.compatible = "airoha,an8855", .data = &an8855_table[ID_AN8855],
+ },
+ { /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, an8855_of_match);
+
+static int
+an8855_probe(struct mdio_device *mdiodev)
+{
+ struct an8855_priv *priv;
+ struct device_node *dn;
+ struct device_node *switch_node = NULL;
+ int ret;
+
+ dn = mdiodev->dev.of_node;
+
+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->ds = dsa_switch_alloc(&mdiodev->dev, AN8855_NUM_PORTS);
+ if (!priv->ds)
+ return -ENOMEM;
+
+ /* Get the hardware identifier from the devicetree node.
+ * We will need it for some of the clock and regulator setup.
+ */
+ priv->info = of_device_get_match_data(&mdiodev->dev);
+ if (!priv->info)
+ return -EINVAL;
+
+ /* Sanity check if these required device operations are filled
+ * properly.
+ */
+ if (!priv->info->sw_setup || !priv->info->pad_setup ||
+ !priv->info->phy_read || !priv->info->phy_write ||
+ !priv->info->phy_mode_supported ||
+ !priv->info->mac_port_validate ||
+ !priv->info->mac_port_get_state || !priv->info->mac_port_config)
+ return -EINVAL;
+
+ dev_info(&mdiodev->dev, "Airoha AN8855 DSA driver, version %s\n",
+ ARHT_AN8855_DSA_DRIVER_VER);
+ priv->phy_base = AN8855_GPHY_SMI_ADDR_DEFAULT;
+ priv->id = priv->info->id;
+
+ priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(priv->reset)) {
+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(priv->reset);
+ }
+
+ switch_node = of_find_node_by_name(NULL, "switch0");
+ if (switch_node) {
+ priv->base = of_iomap(switch_node, 0);
+ if (priv->base == NULL) {
+ dev_err(&mdiodev->dev, "of_iomap failed\n");
+ return -ENOMEM;
+ }
+ }
+
+ ret = of_property_read_u32(dn, "changesmiaddr", &priv->phy_base_new);
+ if ((ret < 0) || (priv->phy_base_new > 0x1f))
+ priv->phy_base_new = -1;
+
+ priv->bus = mdiodev->bus;
+ priv->dev = &mdiodev->dev;
+ priv->ds->priv = priv;
+ priv->ds->ops = &an8855_switch_ops;
+ mutex_init(&priv->reg_mutex);
+ dev_set_drvdata(&mdiodev->dev, priv);
+
+ ret = dsa_register_switch(priv->ds);
+ if (ret) {
+ if (priv->base)
+ iounmap(priv->base);
+
+ return ret;
+ }
+ an8855_nl_init(&priv);
+
+ return 0;
+}
+
+static void
+an8855_remove(struct mdio_device *mdiodev)
+{
+ struct an8855_priv *priv = dev_get_drvdata(&mdiodev->dev);
+
+ dsa_unregister_switch(priv->ds);
+ mutex_destroy(&priv->reg_mutex);
+
+ if (priv->base)
+ iounmap(priv->base);
+
+ an8855_nl_exit();
+}
+
+static struct mdio_driver an8855_mdio_driver = {
+ .probe = an8855_probe,
+ .remove = an8855_remove,
+ .mdiodrv.driver = {
+ .name = "an8855",
+ .of_match_table = an8855_of_match,
+ },
+};
+
+mdio_module_driver(an8855_mdio_driver);
+
+MODULE_AUTHOR("Min Yao <min.yao@airoha.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 Switch");
+MODULE_VERSION(ARHT_AN8855_DSA_DRIVER_VER);
+MODULE_LICENSE("GPL");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h
new file mode 100644
index 0000000..531d9be
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855.h
@@ -0,0 +1,580 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef __AN8855_H
+#define __AN8855_H
+
+#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
+
+#define AN8855_NUM_PORTS 6
+#define AN8855_CPU_PORT 5
+#define AN8855_NUM_FDB_RECORDS 2048
+#define AN8855_ALL_MEMBERS 0x3f
+#define AN8855_RESERVED_VLAN 2
+#define AN8855_GPHY_SMI_ADDR_DEFAULT 1
+
+enum an8855_id {
+ ID_AN8855 = 0,
+};
+
+enum sgmii_mode {
+ SGMII_MODE_AN,
+ SGMII_MODE_FORCE,
+};
+
+/* Registers to mac forward control for unknown frames */
+#define AN8855_MFC 0x10200010
+#define CPU_EN BIT(15)
+#define CPU_PORT(x) ((x) << 8)
+#define CPU_MASK (0x9f << 8)
+
+#define AN8855_UNUF 0x102000b4
+#define AN8855_UNMF 0x102000b8
+#define AN8855_BCF 0x102000bc
+
+/* Registers for mirror port control */
+#define AN8855_MIR 0x102000cc
+#define AN8855_MIRROR_EN BIT(7)
+#define AN8855_MIRROR_MASK (0x1f)
+#define AN8855_MIRROR_PORT_GET(x) ((x) & AN8855_MIRROR_MASK)
+#define AN8855_MIRROR_PORT_SET(x) ((x) & AN8855_MIRROR_MASK)
+
+/* Registers for BPDU and PAE frame control*/
+#define AN8855_BPC 0x102000D0
+#define AN8855_BPDU_PORT_FW_MASK GENMASK(2, 0)
+
+enum an8855_bpdu_port_fw {
+ AN8855_BPDU_FOLLOW_MFC,
+ AN8855_BPDU_CPU_EXCLUDE = 4,
+ AN8855_BPDU_CPU_INCLUDE = 5,
+ AN8855_BPDU_CPU_ONLY = 6,
+ AN8855_BPDU_DROP = 7,
+};
+
+/* Registers for address table access */
+#define AN8855_ATA1 0x10200304
+#define AN8855_ATA2 0x10200308
+
+/* Register for address table write data */
+#define AN8855_ATWD 0x10200324
+#define AN8855_ATWD2 0x10200328
+
+/* Register for address table control */
+#define AN8855_ATC 0x10200300
+#define ATC_BUSY BIT(31)
+#define ATC_INVALID ~BIT(30)
+#define ATC_HASH 16
+#define ATC_HASH_MASK 0x1ff
+#define ATC_HIT 12
+#define ATC_HIT_MASK 0xf
+#define ATC_MAT(x) (((x) & 0x1f) << 7)
+#define ATC_MAT_MACTAB ATC_MAT(1)
+
+enum an8855_fdb_cmds {
+ AN8855_FDB_READ = 0,
+ AN8855_FDB_WRITE = 1,
+ AN8855_FDB_FLUSH = 2,
+ AN8855_FDB_START = 4,
+ AN8855_FDB_NEXT = 5,
+};
+
+/* Registers for table search read address */
+#define AN8855_ATRDS 0x10200330
+#define AN8855_ATRD0 0x10200334
+#define CVID 10
+#define CVID_MASK 0xfff
+
+enum an8855_fdb_type {
+ AN8855_MAC_TB_TY_MAC = 0,
+ AN8855_MAC_TB_TY_DIP = 1,
+ AN8855_MAC_TB_TY_DIP_SIP = 2,
+};
+
+#define AN8855_ATRD1 0x10200338
+#define MAC_BYTE_4 24
+#define MAC_BYTE_5 16
+#define AGE_TIMER 3
+#define AGE_TIMER_MASK 0x1ff
+
+#define AN8855_ATRD2 0x1020033c
+#define MAC_BYTE_0 24
+#define MAC_BYTE_1 16
+#define MAC_BYTE_2 8
+#define MAC_BYTE_3 0
+#define MAC_BYTE_MASK 0xff
+
+#define AN8855_ATRD3 0x10200340
+#define PORT_MAP 4
+#define PORT_MAP_MASK 0xff
+
+/* Register for vlan table control */
+#define AN8855_VTCR 0x10200600
+#define VTCR_BUSY BIT(31)
+#define VTCR_FUNC(x) (((x) & 0xf) << 12)
+#define VTCR_VID ((x) & 0xfff)
+
+enum an8855_vlan_cmd {
+ /* Read/Write the specified VID entry from VAWD register based
+ * on VID.
+ */
+ AN8855_VTCR_RD_VID = 0,
+ AN8855_VTCR_WR_VID = 1,
+};
+
+/* Register for setup vlan write data */
+#define AN8855_VAWD0 0x10200604
+
+/* Independent VLAN Learning */
+#define IVL_MAC BIT(5)
+/* Per VLAN Egress Tag Control */
+#define VTAG_EN BIT(10)
+/* Egress Tag Control */
+#define PORT_EG_CTRL_SHIFT 12
+/* VLAN Member Control */
+#define PORT_MEM_SHFT 26
+#define PORT_MEM_MASK 0x7f
+#define PORT_MEM(x) (((x) & PORT_MEM_MASK) << PORT_MEM_SHFT)
+/* VLAN Entry Valid */
+#define VLAN_VALID BIT(0)
+
+#define AN8855_VAWD1 0x10200608
+#define PORT_STAG BIT(1)
+/* Egress Tag Control */
+#define ETAG_CTRL_P(p, x) (((x) & 0x3) << ((p) << 1))
+#define ETAG_CTRL_P_MASK(p) ETAG_CTRL_P(p, 3)
+#define ETAG_CTRL_MASK (0x3FFF)
+
+#define AN8855_VARD0 0x10200618
+
+enum an8855_vlan_egress_attr {
+ AN8855_VLAN_EGRESS_UNTAG = 0,
+ AN8855_VLAN_EGRESS_TAG = 2,
+ AN8855_VLAN_EGRESS_STACK = 3,
+};
+
+/* Register for port STP state control */
+#define AN8855_SSP_P(x) (0x10208000 + ((x) * 0x200))
+#define FID_PST(x) ((x) & 0x3)
+#define FID_PST_MASK FID_PST(0x3)
+
+enum an8855_stp_state {
+ AN8855_STP_DISABLED = 0,
+ AN8855_STP_BLOCKING = 1,
+ AN8855_STP_LISTENING = 1,
+ AN8855_STP_LEARNING = 2,
+ AN8855_STP_FORWARDING = 3
+};
+
+/* Register for port control */
+#define AN8855_PCR_P(x) (0x10208004 + ((x) * 0x200))
+#define PORT_TX_MIR BIT(20)
+#define PORT_RX_MIR BIT(16)
+#define PORT_VLAN(x) ((x) & 0x3)
+
+enum an8855_port_mode {
+ /* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */
+ AN8855_PORT_MATRIX_MODE = PORT_VLAN(0),
+
+ /* Fallback Mode: Forward received frames with ingress ports that do
+ * not belong to the VLAN member. Frames whose VID is not listed on
+ * the VLAN table are forwarded by the PCR_MATRIX members.
+ */
+ AN8855_PORT_FALLBACK_MODE = PORT_VLAN(1),
+
+ /* Security Mode: Discard any frame due to ingress membership
+ * violation or VID missed on the VLAN table.
+ */
+ AN8855_PORT_SECURITY_MODE = PORT_VLAN(3),
+};
+
+#define PORT_PRI(x) (((x) & 0x7) << 24)
+#define EG_TAG(x) (((x) & 0x3) << 28)
+#define PCR_PORT_VLAN_MASK PORT_VLAN(3)
+
+/* Register for port security control */
+#define AN8855_PSC_P(x) (0x1020800c + ((x) * 0x200))
+#define SA_DIS BIT(4)
+
+/* Register for port vlan control */
+#define AN8855_PVC_P(x) (0x10208010 + ((x) * 0x200))
+#define PORT_SPEC_REPLACE_MODE BIT(11)
+#define PORT_SPEC_TAG BIT(5)
+#define PVC_EG_TAG(x) (((x) & 0x7) << 8)
+#define PVC_EG_TAG_MASK PVC_EG_TAG(7)
+#define VLAN_ATTR(x) (((x) & 0x3) << 6)
+#define VLAN_ATTR_MASK VLAN_ATTR(3)
+
+#define AN8855_PORTMATRIX_P(x) (0x10208044 + ((x) * 0x200))
+#define PORTMATRIX_MATRIX(x) ((x) & 0x3f)
+#define PORTMATRIX_MASK PORTMATRIX_MATRIX(0x3f)
+#define PORTMATRIX_CLR PORTMATRIX_MATRIX(0)
+
+enum an8855_vlan_port_eg_tag {
+ AN8855_VLAN_EG_DISABLED = 0,
+ AN8855_VLAN_EG_CONSISTENT = 1,
+};
+
+enum an8855_vlan_port_attr {
+ AN8855_VLAN_USER = 0,
+ AN8855_VLAN_TRANSPARENT = 3,
+};
+
+/* Register for port PVID */
+#define AN8855_PVID_P(x) (0x10208048 + ((x) * 0x200))
+#define G0_PORT_VID(x) (((x) & 0xfff) << 0)
+#define G0_PORT_VID_MASK G0_PORT_VID(0xfff)
+#define G0_PORT_VID_DEF G0_PORT_VID(1)
+
+/* Register for port MAC control register */
+#define AN8855_PMCR_P(x) (0x10210000 + ((x) * 0x200))
+#define PMCR_IFG_XMIT(x) (((x) & 0x3) << 20)
+#define PMCR_EXT_PHY BIT(19)
+#define PMCR_MAC_MODE BIT(18)
+#define PMCR_FORCE_MODE BIT(31)
+#define PMCR_TX_EN BIT(16)
+#define PMCR_RX_EN BIT(15)
+#define PMCR_BACKOFF_EN BIT(12)
+#define PMCR_BACKPR_EN BIT(11)
+#define PMCR_FORCE_EEE2P5G BIT(8)
+#define PMCR_FORCE_EEE1G BIT(7)
+#define PMCR_FORCE_EEE100 BIT(6)
+#define PMCR_TX_FC_EN BIT(5)
+#define PMCR_RX_FC_EN BIT(4)
+#define PMCR_FORCE_SPEED_2500 (0x3 << 28)
+#define PMCR_FORCE_SPEED_1000 (0x2 << 28)
+#define PMCR_FORCE_SPEED_100 (0x1 << 28)
+#define PMCR_FORCE_FDX BIT(25)
+#define PMCR_FORCE_LNK BIT(24)
+#define PMCR_SPEED_MASK BITS(28, 30)
+#define AN8855_FORCE_LNK BIT(31)
+#define AN8855_FORCE_MODE (AN8855_FORCE_LNK)
+#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | \
+ PMCR_RX_EN | PMCR_FORCE_SPEED_2500 | \
+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
+ PMCR_FORCE_FDX | PMCR_FORCE_LNK)
+#define PMCR_CPU_PORT_SETTING(id) (AN8855_FORCE_MODE | \
+ PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
+ PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \
+ PMCR_TX_EN | PMCR_RX_EN | \
+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
+ PMCR_FORCE_SPEED_2500 | \
+ PMCR_FORCE_FDX | PMCR_FORCE_LNK)
+
+#define AN8855_PMSR_P(x) (0x10210010 + (x) * 0x200)
+#define PMSR_EEE1G BIT(7)
+#define PMSR_EEE100M BIT(6)
+#define PMSR_RX_FC BIT(5)
+#define PMSR_TX_FC BIT(4)
+#define PMSR_SPEED_2500 (0x3 << 28)
+#define PMSR_SPEED_1000 (0x2 << 28)
+#define PMSR_SPEED_100 (0x1 << 28)
+#define PMSR_SPEED_10 (0x0 << 28)
+#define PMSR_SPEED_MASK BITS(28, 30)
+#define PMSR_DPX BIT(25)
+#define PMSR_LINK BIT(24)
+
+#define AN8855_PMEEECR_P(x) (0x10210004 + (x) * 0x200)
+#define WAKEUP_TIME_2500(x) ((x & 0xFF) << 16)
+#define WAKEUP_TIME_1000(x) ((x & 0xFF) << 8)
+#define WAKEUP_TIME_100(x) ((x & 0xFF) << 0)
+#define LPI_MODE_EN BIT(31)
+#define AN8855_PMEEECR2_P(x) (0x10210008 + (x) * 0x200)
+#define WAKEUP_TIME_5000(x) ((x & 0xFF) << 0)
+
+#define AN8855_CKGCR (0x10213e1c)
+#define LPI_TXIDLE_THD 14
+#define LPI_TXIDLE_THD_MASK BITS(14, 31)
+
+/* Register for MIB */
+#define AN8855_PORT_MIB_COUNTER(x) (0x10214000 + (x) * 0x200)
+#define AN8855_MIB_CCR 0x10213e30
+#define CCR_MIB_ENABLE BIT(31)
+#define CCR_RX_OCT_CNT_GOOD BIT(7)
+#define CCR_RX_OCT_CNT_BAD BIT(6)
+#define CCR_TX_OCT_CNT_GOOD BIT(5)
+#define CCR_TX_OCT_CNT_BAD BIT(4)
+#define CCR_RX_OCT_CNT_GOOD_2 BIT(3)
+#define CCR_RX_OCT_CNT_BAD_2 BIT(2)
+#define CCR_TX_OCT_CNT_GOOD_2 BIT(1)
+#define CCR_TX_OCT_CNT_BAD_2 BIT(0)
+#define CCR_MIB_FLUSH (CCR_RX_OCT_CNT_GOOD | \
+ CCR_RX_OCT_CNT_BAD | \
+ CCR_TX_OCT_CNT_GOOD | \
+ CCR_TX_OCT_CNT_BAD | \
+ CCR_RX_OCT_CNT_GOOD_2 | \
+ CCR_RX_OCT_CNT_BAD_2 | \
+ CCR_TX_OCT_CNT_GOOD_2 | \
+ CCR_TX_OCT_CNT_BAD_2)
+#define CCR_MIB_ACTIVATE (CCR_MIB_ENABLE | \
+ CCR_RX_OCT_CNT_GOOD | \
+ CCR_RX_OCT_CNT_BAD | \
+ CCR_TX_OCT_CNT_GOOD | \
+ CCR_TX_OCT_CNT_BAD | \
+ CCR_RX_OCT_CNT_GOOD_2 | \
+ CCR_RX_OCT_CNT_BAD_2 | \
+ CCR_TX_OCT_CNT_GOOD_2 | \
+ CCR_TX_OCT_CNT_BAD_2)
+
+/* AN8855 SGMII register group */
+#define AN8855_SGMII_REG_BASE 0x10220000
+#define AN8855_SGMII_REG(p, r) (AN8855_SGMII_REG_BASE + \
+ ((p) - 5) * 0x1000 + (r))
+
+/* Register forSGMII PCS_CONTROL_1 */
+#define AN8855_PCS_CONTROL_1(p) AN8855_SGMII_REG(p, 0x00)
+#define AN8855_SGMII_AN_ENABLE BIT(12)
+#define AN8855_SGMII_AN_RESTART BIT(9)
+
+/* Register for system reset */
+#define AN8855_RST_CTRL 0x100050c0
+#define SYS_CTRL_SYS_RST BIT(31)
+
+/* Register for hw trap status */
+#define AN8855_HWTRAP 0x1000009c
+
+#define AN8855_CREV 0x10005000
+#define AN8855_ID 0x8855
+
+#define SCU_BASE 0x10000000
+#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0)
+
+#define HSGMII_AN_CSR_BASE 0x10220000
+#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000)
+#define SGMII_REG_AN_13 (HSGMII_AN_CSR_BASE + 0x034)
+#define SGMII_REG_AN_FORCE_CL37 (HSGMII_AN_CSR_BASE + 0x060)
+
+#define HSGMII_CSR_PCS_BASE 0x10220000
+#define RG_HSGMII_PCS_CTROL_1 (HSGMII_CSR_PCS_BASE + 0xa00)
+#define RG_AN_SGMII_MODE_FORCE (HSGMII_CSR_PCS_BASE + 0xa24)
+
+#define MULTI_SGMII_CSR_BASE 0x10224000
+#define SGMII_STS_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x018)
+#define MSG_RX_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x100)
+#define MSG_RX_LIK_STS_0 (MULTI_SGMII_CSR_BASE + 0x514)
+#define MSG_RX_LIK_STS_2 (MULTI_SGMII_CSR_BASE + 0x51c)
+#define PHY_RX_FORCE_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x520)
+
+#define XFI_CSR_PCS_BASE 0x10225000
+#define RG_USXGMII_AN_CONTROL_0 (XFI_CSR_PCS_BASE + 0xbf8)
+
+#define MULTI_PHY_RA_CSR_BASE 0x10226000
+#define RG_RATE_ADAPT_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x000)
+#define RATE_ADP_P0_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x100)
+#define MII_RA_AN_ENABLE (MULTI_PHY_RA_CSR_BASE + 0x300)
+
+#define QP_DIG_CSR_BASE 0x1022a000
+#define QP_CK_RST_CTRL_4 (QP_DIG_CSR_BASE + 0x310)
+#define QP_DIG_MODE_CTRL_0 (QP_DIG_CSR_BASE + 0x324)
+#define QP_DIG_MODE_CTRL_1 (QP_DIG_CSR_BASE + 0x330)
+
+#define SERDES_WRAPPER_BASE 0x1022c000
+#define USGMII_CTRL_0 (SERDES_WRAPPER_BASE + 0x000)
+
+#define QP_PMA_TOP_BASE 0x1022e000
+#define PON_RXFEDIG_CTRL_0 (QP_PMA_TOP_BASE + 0x100)
+#define PON_RXFEDIG_CTRL_9 (QP_PMA_TOP_BASE + 0x124)
+
+#define SS_LCPLL_PWCTL_SETTING_2 (QP_PMA_TOP_BASE + 0x208)
+#define SS_LCPLL_TDC_FLT_2 (QP_PMA_TOP_BASE + 0x230)
+#define SS_LCPLL_TDC_FLT_5 (QP_PMA_TOP_BASE + 0x23c)
+#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248)
+#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320)
+#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324)
+#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400)
+#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408)
+#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c)
+#define PLL_CTRL_4 (QP_PMA_TOP_BASE + 0x410)
+#define PLL_CK_CTRL_0 (QP_PMA_TOP_BASE + 0x414)
+#define RX_DLY_0 (QP_PMA_TOP_BASE + 0x614)
+#define RX_CTRL_2 (QP_PMA_TOP_BASE + 0x630)
+#define RX_CTRL_5 (QP_PMA_TOP_BASE + 0x63c)
+#define RX_CTRL_6 (QP_PMA_TOP_BASE + 0x640)
+#define RX_CTRL_7 (QP_PMA_TOP_BASE + 0x644)
+#define RX_CTRL_8 (QP_PMA_TOP_BASE + 0x648)
+#define RX_CTRL_26 (QP_PMA_TOP_BASE + 0x690)
+#define RX_CTRL_42 (QP_PMA_TOP_BASE + 0x6d0)
+
+#define QP_ANA_CSR_BASE 0x1022f000
+#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00)
+#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04)
+#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c)
+#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14)
+#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18)
+#define RG_QP_CDR_PR_KBAND_DIV_PCIE (QP_ANA_CSR_BASE + 0x1c)
+#define RG_QP_CDR_FORCE_IBANDLPF_R_OFF (QP_ANA_CSR_BASE + 0x20)
+#define RG_QP_TX_MODE_16B_EN (QP_ANA_CSR_BASE + 0x28)
+#define RG_QP_PLL_IPLL_DIG_PWR_SEL (QP_ANA_CSR_BASE + 0x3c)
+#define RG_QP_PLL_SDM_ORD (QP_ANA_CSR_BASE + 0x40)
+
+#define ETHER_SYS_BASE 0x1028c800
+#define RG_GPHY_AFE_PWD (ETHER_SYS_BASE + 0x40)
+#define RG_GPHY_SMI_ADDR (ETHER_SYS_BASE + 0x48)
+
+#define MIB_DESC(_s, _o, _n) \
+ { \
+ .size = (_s), \
+ .offset = (_o), \
+ .name = (_n), \
+ }
+
+struct an8855_mib_desc {
+ unsigned int size;
+ unsigned int offset;
+ const char *name;
+};
+
+struct an8855_fdb {
+ u16 vid;
+ u8 port_mask;
+ u8 aging;
+ u8 mac[6];
+ bool noarp;
+ u8 live;
+ u8 type;
+ u8 fid;
+ u8 ivl;
+};
+
+/* struct an8855_port - This is the main data structure for holding the state
+ * of the port.
+ * @enable: The status used for show port is enabled or not.
+ * @pm: The matrix used to show all connections with the port.
+ * @pvid: The VLAN specified is to be considered a PVID at ingress. Any
+ * untagged frames will be assigned to the related VLAN.
+ * @vlan_filtering: The flags indicating whether the port that can recognize
+ * VLAN-tagged frames.
+ */
+struct an8855_port {
+ bool enable;
+ u32 pm;
+ u16 pvid;
+};
+
+/* struct an8855_info - This is the main data structure for holding the specific
+ * part for each supported device
+ * @sw_setup: Holding the handler to a device initialization
+ * @phy_read: Holding the way reading PHY port
+ * @phy_write: Holding the way writing PHY port
+ * @pad_setup: Holding the way setting up the bus pad for a certain
+ * MAC port
+ * @phy_mode_supported: Check if the PHY type is being supported on a certain
+ * port
+ * @mac_port_validate: Holding the way to set addition validate type for a
+ * certan MAC port
+ * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain
+ * MAC port
+ * @mac_port_config: Holding the way setting up the PHY attribute to a
+ * certain MAC port
+ * @mac_pcs_an_restart Holding the way restarting PCS autonegotiation for a
+ * certain MAC port
+ * @mac_pcs_link_up: Holding the way setting up the PHY attribute to the pcs
+ * of the certain MAC port
+ */
+struct an8855_dev_info {
+ enum an8855_id id;
+
+ int (*sw_setup)(struct dsa_switch *ds);
+ int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
+ int (*phy_write)(struct dsa_switch *ds, int port, int regnum,
+ u16 val);
+ int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
+ int (*cpu_port_config)(struct dsa_switch *ds, int port);
+ bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
+ const struct phylink_link_state *state);
+ void (*mac_port_validate)(struct dsa_switch *ds, int port,
+ unsigned long *supported);
+ int (*mac_port_get_state)(struct dsa_switch *ds, int port,
+ struct phylink_link_state *state);
+ int (*mac_port_config)(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface);
+ void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port);
+};
+
+/* struct an8855_priv - This is the main data structure for holding the state
+ * of the driver
+ * @dev: The device pointer
+ * @ds: The pointer to the dsa core structure
+ * @bus: The bus used for the device and built-in PHY
+ * @rstc: The pointer to reset control used by MCM
+ * @core_pwr: The power supplied into the core
+ * @io_pwr: The power supplied into the I/O
+ * @reset: The descriptor for GPIO line tied to its reset pin
+ * @mcm: Flag for distinguishing if standalone IC or module
+ * coupling
+ * @ports: Holding the state among ports
+ * @reg_mutex: The lock for protecting among process accessing
+ * registers
+ * @p6_interface Holding the current port 6 interface
+ * @p5_intf_sel: Holding the current port 5 interface select
+ */
+struct an8855_priv {
+ struct device *dev;
+ struct dsa_switch *ds;
+ struct mii_bus *bus;
+ struct reset_control *rstc;
+ struct regulator *core_pwr;
+ struct regulator *io_pwr;
+ struct gpio_desc *reset;
+ void __iomem *base;
+ const struct an8855_dev_info *info;
+ unsigned int phy_base;
+ int phy_base_new;
+ unsigned int id;
+ phy_interface_t p5_interface;
+ unsigned int p5_intf_sel;
+ u8 mirror_rx;
+ u8 mirror_tx;
+ u8 eee_enable;
+
+ struct an8855_port ports[AN8855_NUM_PORTS];
+ /* protect among processes for registers access */
+ struct mutex reg_mutex;
+};
+
+struct an8855_hw_vlan_entry {
+ int port;
+ u8 old_members;
+ bool untagged;
+};
+
+static inline void an8855_hw_vlan_entry_init(struct an8855_hw_vlan_entry *e,
+ int port, bool untagged)
+{
+ e->port = port;
+ e->untagged = untagged;
+}
+
+typedef void (*an8855_vlan_op) (struct an8855_priv *,
+ struct an8855_hw_vlan_entry *);
+
+struct an8855_hw_stats {
+ const char *string;
+ u16 reg;
+ u8 sizeof_stat;
+};
+
+struct an8855_dummy_poll {
+ struct an8855_priv *priv;
+ u32 reg;
+};
+
+static inline void INIT_AN8855_DUMMY_POLL(struct an8855_dummy_poll *p,
+ struct an8855_priv *priv, u32 reg)
+{
+ p->priv = priv;
+ p->reg = reg;
+}
+
+int an8855_phy_setup(struct dsa_switch *ds);
+u32 an8855_read(struct an8855_priv *priv, u32 reg);
+void an8855_write(struct an8855_priv *priv, u32 reg, u32 val);
+int an8855_phy_cl22_read(struct an8855_priv *priv, int port, int regnum);
+int an8855_phy_cl22_write(struct an8855_priv *priv, int port,
+ int regnum, u16 val);
+int an8855_phy_cl45_read(struct an8855_priv *priv, int port, int devad,
+ int regnum);
+int an8855_phy_cl45_write(struct an8855_priv *priv, int port, int devad,
+ int regnum, u16 val);
+#endif /* __AN8855_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c
new file mode 100644
index 0000000..b80ce6f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <net/genetlink.h>
+#include <linux/of_mdio.h>
+#include <linux/phylink.h>
+#include <net/dsa.h>
+
+#include "an8855.h"
+#include "an8855_nl.h"
+
+struct an8855_nl_cmd_item {
+ enum an8855_cmd cmd;
+ bool require_dev;
+ int (*process)(struct genl_info *info);
+ u32 nr_required_attrs;
+ const enum an8855_attr *required_attrs;
+};
+
+struct an8855_priv *an8855_sw_priv;
+
+static DEFINE_MUTEX(an8855_devs_lock);
+
+void
+an8855_put(void)
+{
+ mutex_unlock(&an8855_devs_lock);
+}
+
+void
+an8855_lock(void)
+{
+ mutex_lock(&an8855_devs_lock);
+}
+
+static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info);
+
+static const struct nla_policy an8855_nl_cmd_policy[] = {
+ [AN8855_ATTR_TYPE_MESG] = {.type = NLA_STRING},
+ [AN8855_ATTR_TYPE_PHY] = {.type = NLA_S32},
+ [AN8855_ATTR_TYPE_REG] = {.type = NLA_S32},
+ [AN8855_ATTR_TYPE_VAL] = {.type = NLA_S32},
+ [AN8855_ATTR_TYPE_DEV_NAME] = {.type = NLA_S32},
+ [AN8855_ATTR_TYPE_DEV_ID] = {.type = NLA_S32},
+ [AN8855_ATTR_TYPE_DEVAD] = {.type = NLA_S32},
+};
+
+static const struct genl_ops an8855_nl_ops[] = {
+ {
+ .cmd = AN8855_CMD_REQUEST,
+ .doit = an8855_nl_response,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = AN8855_CMD_READ,
+ .doit = an8855_nl_response,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = AN8855_CMD_WRITE,
+ .doit = an8855_nl_response,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+static struct genl_family an8855_nl_family = {
+ .name = AN8855_DSA_GENL_NAME,
+ .version = AN8855_GENL_VERSION,
+ .maxattr = AN8855_NR_ATTR_TYPE,
+ .ops = an8855_nl_ops,
+ .n_ops = ARRAY_SIZE(an8855_nl_ops),
+ .policy = an8855_nl_cmd_policy,
+};
+
+static int
+an8855_nl_prepare_reply(struct genl_info *info, u8 cmd,
+ struct sk_buff **skbp)
+{
+ struct sk_buff *msg;
+ void *reply;
+
+ if (!info)
+ return -EINVAL;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ /* Construct send-back message header */
+ reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &an8855_nl_family, 0, cmd);
+ if (!reply) {
+ nlmsg_free(msg);
+ return -EINVAL;
+ }
+
+ *skbp = msg;
+ return 0;
+}
+
+static int
+an8855_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
+{
+ struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
+ void *reply = genlmsg_data(genlhdr);
+
+ /* Finalize a generic netlink message (update message header) */
+ genlmsg_end(skb, reply);
+
+ /* reply to a request */
+ return genlmsg_reply(skb, info);
+}
+
+static s32
+an8855_nl_get_s32(struct genl_info *info, enum an8855_attr attr,
+ s32 defval)
+{
+ struct nlattr *na;
+
+ na = info->attrs[attr];
+ if (na)
+ return nla_get_s32(na);
+
+ return defval;
+}
+
+static int
+an8855_nl_get_u32(struct genl_info *info, enum an8855_attr attr,
+ u32 *val)
+{
+ struct nlattr *na;
+
+ na = info->attrs[attr];
+ if (na) {
+ *val = nla_get_u32(na);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+an8855_nl_reply_read(struct genl_info *info)
+{
+ struct sk_buff *rep_skb = NULL;
+ s32 phy, devad, reg;
+ int value;
+ int ret = 0;
+
+ phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
+ devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
+ reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
+
+ if (reg < 0)
+ goto err;
+
+ ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb);
+ if (ret < 0)
+ goto err;
+ if (phy >= 0) {
+ if (devad < 0)
+ value = an8855_phy_cl22_read(an8855_sw_priv, phy, reg);
+ else
+ value = an8855_phy_cl45_read(an8855_sw_priv, phy,
+ devad, reg);
+ } else
+ value = an8855_read(an8855_sw_priv, reg);
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
+ if (ret < 0)
+ goto err;
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
+ if (ret < 0)
+ goto err;
+
+ return an8855_nl_send_reply(rep_skb, info);
+
+err:
+ if (rep_skb)
+ nlmsg_free(rep_skb);
+
+ return ret;
+}
+
+static int
+an8855_nl_reply_write(struct genl_info *info)
+{
+ struct sk_buff *rep_skb = NULL;
+ s32 phy, devad, reg;
+ u32 value;
+ int ret = 0;
+
+ phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
+ devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
+ reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
+
+ if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
+ goto err;
+
+ if (reg < 0)
+ goto err;
+
+ ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
+ if (ret < 0)
+ goto err;
+ if (phy >= 0) {
+ if (devad < 0)
+ an8855_phy_cl22_write(an8855_sw_priv, phy, reg, value);
+ else
+ an8855_phy_cl45_write(an8855_sw_priv, phy, devad, reg,
+ value);
+ } else
+ an8855_write(an8855_sw_priv, reg, value);
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
+ if (ret < 0)
+ goto err;
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
+ if (ret < 0)
+ goto err;
+
+ return an8855_nl_send_reply(rep_skb, info);
+
+err:
+ if (rep_skb)
+ nlmsg_free(rep_skb);
+
+ return ret;
+}
+
+static const enum an8855_attr an8855_nl_cmd_read_attrs[] = {
+ AN8855_ATTR_TYPE_REG
+};
+
+static const enum an8855_attr an8855_nl_cmd_write_attrs[] = {
+ AN8855_ATTR_TYPE_REG,
+ AN8855_ATTR_TYPE_VAL
+};
+
+static const struct an8855_nl_cmd_item an8855_nl_cmds[] = {
+ {
+ .cmd = AN8855_CMD_READ,
+ .require_dev = true,
+ .process = an8855_nl_reply_read,
+ .required_attrs = an8855_nl_cmd_read_attrs,
+ .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_read_attrs),
+ },
+ {
+ .cmd = AN8855_CMD_WRITE,
+ .require_dev = true,
+ .process = an8855_nl_reply_write,
+ .required_attrs = an8855_nl_cmd_write_attrs,
+ .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_write_attrs),
+ }
+};
+
+static int
+an8855_nl_response(struct sk_buff *skb, struct genl_info *info)
+{
+ struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
+ const struct an8855_nl_cmd_item *cmditem = NULL;
+ u32 sat_req_attrs = 0;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(an8855_nl_cmds); i++) {
+ if (hdr->cmd == an8855_nl_cmds[i].cmd) {
+ cmditem = &an8855_nl_cmds[i];
+ break;
+ }
+ }
+
+ if (!cmditem) {
+ pr_info("an8855-nl: unknown cmd %u\n", hdr->cmd);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cmditem->nr_required_attrs; i++) {
+ if (info->attrs[cmditem->required_attrs[i]])
+ sat_req_attrs++;
+ }
+
+ if (sat_req_attrs != cmditem->nr_required_attrs) {
+ pr_info("an8855-nl: missing required attr(s) for cmd %u\n",
+ hdr->cmd);
+ return -EINVAL;
+ }
+
+ ret = cmditem->process(info);
+
+ an8855_put();
+
+ return ret;
+}
+
+int
+an8855_nl_init(struct an8855_priv **priv)
+{
+ int ret;
+
+ pr_info("an8855-nl: genl_register_family_with_ops\n");
+
+ an8855_sw_priv = *priv;
+ ret = genl_register_family(&an8855_nl_family);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void
+an8855_nl_exit(void)
+{
+ an8855_sw_priv = NULL;
+ genl_unregister_family(&an8855_nl_family);
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h
new file mode 100644
index 0000000..f8a462d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_nl.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_NL_H_
+#define _AN8855_NL_H_
+
+#define AN8855_DSA_GENL_NAME "an8855_dsa"
+#define AN8855_GENL_VERSION 0x1
+
+enum an8855_cmd {
+ AN8855_CMD_UNSPEC = 0,
+ AN8855_CMD_REQUEST,
+ AN8855_CMD_REPLY,
+ AN8855_CMD_READ,
+ AN8855_CMD_WRITE,
+
+ __AN8855_CMD_MAX,
+};
+
+enum an8855_attr {
+ AN8855_ATTR_TYPE_UNSPEC = 0,
+ AN8855_ATTR_TYPE_MESG,
+ AN8855_ATTR_TYPE_PHY,
+ AN8855_ATTR_TYPE_DEVAD,
+ AN8855_ATTR_TYPE_REG,
+ AN8855_ATTR_TYPE_VAL,
+ AN8855_ATTR_TYPE_DEV_NAME,
+ AN8855_ATTR_TYPE_DEV_ID,
+
+ __AN8855_ATTR_TYPE_MAX,
+};
+
+#define AN8855_NR_ATTR_TYPE (__AN8855_ATTR_TYPE_MAX - 1)
+
+#ifdef __KERNEL__
+int an8855_nl_init(struct an8855_priv **priv);
+void an8855_nl_exit(void);
+#endif /* __KERNEL__ */
+
+#endif /* _AN8855_NL_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c
new file mode 100644
index 0000000..5499312
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Common part for Airoha AN8855 gigabit switch
+ *
+ * Copyright (C) 2023 Airoha Inc. All Rights Reserved.
+ *
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/kernel.h>
+#include <net/dsa.h>
+#include "an8855.h"
+#include "an8855_phy.h"
+
+#define AN8855_NUM_PHYS 5
+
+static u32
+an8855_phy_read_dev_reg(struct dsa_switch *ds, u32 port_num,
+ u32 dev_addr, u32 reg_addr)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 phy_val;
+ u32 addr;
+
+ addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
+ phy_val = priv->info->phy_read(ds, port_num, addr);
+
+ return phy_val;
+}
+
+static void
+an8855_phy_write_dev_reg(struct dsa_switch *ds, u32 port_num,
+ u32 dev_addr, u32 reg_addr, u32 write_data)
+{
+ struct an8855_priv *priv = ds->priv;
+ u32 addr;
+
+ addr = MII_ADDR_C45 | (dev_addr << 16) | (reg_addr & 0xffff);
+
+ priv->info->phy_write(ds, port_num, addr, write_data);
+}
+
+static void
+an8855_switch_phy_write(struct dsa_switch *ds, u32 port_num,
+ u32 reg_addr, u32 write_data)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ priv->info->phy_write(ds, port_num, reg_addr, write_data);
+}
+
+static u32
+an8855_switch_phy_read(struct dsa_switch *ds, u32 port_num,
+ u32 reg_addr)
+{
+ struct an8855_priv *priv = ds->priv;
+
+ return priv->info->phy_read(ds, port_num, reg_addr);
+}
+
+static void
+an8855_phy_setting(struct dsa_switch *ds)
+{
+ struct an8855_priv *priv = ds->priv;
+ int i;
+ u32 val;
+
+ /* Release power down */
+ an8855_write(priv, RG_GPHY_AFE_PWD, 0x0);
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ /* Enable HW auto downshift */
+ an8855_switch_phy_write(ds, i, 0x1f, 0x1);
+ val = an8855_switch_phy_read(ds, i, PHY_EXT_REG_14);
+ val |= PHY_EN_DOWN_SHFIT;
+ an8855_switch_phy_write(ds, i, PHY_EXT_REG_14, val);
+ an8855_switch_phy_write(ds, i, 0x1f, 0x0);
+
+ /* Enable Asymmetric Pause Capability */
+ val = an8855_switch_phy_read(ds, i, MII_ADVERTISE);
+ val |= ADVERTISE_PAUSE_ASYM;
+ an8855_switch_phy_write(ds, i, MII_ADVERTISE, val);
+ }
+}
+
+static void
+an8855_low_power_setting(struct dsa_switch *ds)
+{
+ int port, addr;
+
+ for (port = 0; port < AN8855_NUM_PHYS; port++) {
+ an8855_phy_write_dev_reg(ds, port, 0x1e, 0x11, 0x0f00);
+ an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3c, 0x0000);
+ an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3d, 0x0000);
+ an8855_phy_write_dev_reg(ds, port, 0x1e, 0x3e, 0x0000);
+ an8855_phy_write_dev_reg(ds, port, 0x1e, 0xc6, 0x53aa);
+ }
+
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x268, 0x07f1);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x269, 0x2111);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26a, 0x0000);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26b, 0x0074);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26e, 0x00f6);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x26f, 0x6666);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x271, 0x2c02);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x272, 0x0c22);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x700, 0x0001);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x701, 0x0803);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x702, 0x01b6);
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, 0x703, 0x2111);
+
+ an8855_phy_write_dev_reg(ds, 1, 0x1f, 0x700, 0x0001);
+
+ for (addr = 0x200; addr <= 0x230; addr += 2)
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x2020);
+
+ for (addr = 0x201; addr <= 0x231; addr += 2)
+ an8855_phy_write_dev_reg(ds, 0, 0x1f, addr, 0x0020);
+}
+
+static void
+an8855_eee_setting(struct dsa_switch *ds, u32 port)
+{
+ /* Disable EEE */
+ an8855_phy_write_dev_reg(ds, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
+}
+
+int
+an8855_phy_setup(struct dsa_switch *ds)
+{
+ int ret = 0;
+ int i;
+
+ an8855_phy_setting(ds);
+
+ for (i = 0; i < AN8855_NUM_PHYS; i++)
+ an8855_eee_setting(ds, i);
+
+ return ret;
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h
new file mode 100644
index 0000000..63a03bb
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/dsa/airoha/an8855/an8855_phy.h
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Common part for Airoha AN8855 gigabit switch
+ *
+ * Copyright (C) 2023 Airoha Inc. All Rights Reserved.
+ *
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_PHY_H_
+#define _AN8855_PHY_H_
+
+#include <linux/bitops.h>
+
+/*phy calibration use*/
+#define DEV_1E 0x1E
+/*global device 0x1f, always set P0*/
+#define DEV_1F 0x1F
+
+/************IEXT/REXT CAL***************/
+/* bits range: for example BITS(16,23) = 0xFF0000*/
+#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
+#define ANACAL_INIT 0x01
+#define ANACAL_ERROR 0xFD
+#define ANACAL_SATURATION 0xFE
+#define ANACAL_FINISH 0xFF
+#define ANACAL_PAIR_A 0
+#define ANACAL_PAIR_B 1
+#define ANACAL_PAIR_C 2
+#define ANACAL_PAIR_D 3
+#define DAC_IN_0V 0x00
+#define DAC_IN_2V 0xf0
+#define TX_AMP_OFFSET_0MV 0x20
+#define TX_AMP_OFFSET_VALID_BITS 6
+
+#define R0 0
+#define PHY0 0
+#define PHY1 1
+#define PHY2 2
+#define PHY3 3
+#define PHY4 4
+#define ANA_TEST_MODE BITS(8, 15)
+#define TST_TCLK_SEL BITs(6, 7)
+#define ANA_TEST_VGA_RG 0x100
+
+#define FORCE_MDI_CROSS_OVER BITS(3, 4)
+#define T10_TEST_CTL_RG 0x145
+#define RG_185 0x185
+#define RG_TX_SLEW BIT(0)
+#define ANA_CAL_0 0xdb
+#define RG_CAL_CKINV BIT(12)
+#define RG_ANA_CALEN BIT(8)
+#define RG_REXT_CALEN BIT(4)
+#define RG_ZCALEN_A BIT(0)
+#define ANA_CAL_1 0xdc
+#define RG_ZCALEN_B BIT(12)
+#define RG_ZCALEN_C BIT(8)
+#define RG_ZCALEN_D BIT(4)
+#define RG_TXVOS_CALEN BIT(0)
+#define ANA_CAL_6 0xe1
+#define RG_CAL_REFSEL BIT(4)
+#define RG_CAL_COMP_PWD BIT(0)
+#define ANA_CAL_5 0xe0
+#define RG_REXT_TRIM BITs(8, 13)
+#define RG_ZCAL_CTRL BITs(0, 5)
+#define RG_17A 0x17a
+#define AD_CAL_COMP_OUT BIT(8)
+#define RG_17B 0x17b
+#define AD_CAL_CLK bit(0)
+#define RG_17C 0x17c
+#define DA_CALIN_FLAG bit(0)
+/************R50 CAL****************************/
+#define RG_174 0x174
+#define RG_R50OHM_RSEL_TX_A_EN BIT[15]
+#define CR_R50OHM_RSEL_TX_A BITS[8:14]
+#define RG_R50OHM_RSEL_TX_B_EN BIT[7]
+#define CR_R50OHM_RSEL_TX_B BITS[6:0]
+#define RG_175 0x175
+#define RG_R50OHM_RSEL_TX_C_EN BITS[15]
+#define CR_R50OHM_RSEL_TX_C BITS[8:14]
+#define RG_R50OHM_RSEL_TX_D_EN BIT[7]
+#define CR_R50OHM_RSEL_TX_D BITS[0:6]
+/**********TX offset Calibration***************************/
+#define RG_95 0x96
+#define BYPASS_TX_OFFSET_CAL BIT(15)
+#define RG_3E 0x3e
+#define BYPASS_PD_TXVLD_A BIT(15)
+#define BYPASS_PD_TXVLD_B BIT(14)
+#define BYPASS_PD_TXVLD_C BIT(13)
+#define BYPASS_PD_TXVLD_D BIT(12)
+#define BYPASS_PD_TX_10M BIT(11)
+#define POWER_DOWN_TXVLD_A BIT(7)
+#define POWER_DOWN_TXVLD_B BIT(6)
+#define POWER_DOWN_TXVLD_C BIT(5)
+#define POWER_DOWN_TXVLD_D BIT(4)
+#define POWER_DOWN_TX_10M BIT(3)
+#define RG_DD 0xdd
+#define RG_TXG_CALEN_A BIT(12)
+#define RG_TXG_CALEN_B BIT(8)
+#define RG_TXG_CALEN_C BIT(4)
+#define RG_TXG_CALEN_D BIT(0)
+#define RG_17D 0x17D
+#define FORCE_DASN_DAC_IN0_A BIT(15)
+#define DASN_DAC_IN0_A BITS(0, 9)
+#define RG_17E 0x17E
+#define FORCE_DASN_DAC_IN0_B BIT(15)
+#define DASN_DAC_IN0_B BITS(0, 9)
+#define RG_17F 0x17F
+
+#define FORCE_DASN_DAC_IN0_C BIT(15)
+#define DASN_DAC_IN0_C BITS(0, 9)
+#define RG_180 0x180
+#define FORCE_DASN_DAC_IN0_D BIT(15)
+#define DASN_DAC_IN0_D BITS(0, 9)
+
+#define RG_181 0x181
+#define FORCE_DASN_DAC_IN1_A BIT(15)
+#define DASN_DAC_IN1_A BITS(0, 9)
+#define RG_182 0x182
+#define FORCE_DASN_DAC_IN1_B BIT(15)
+#define DASN_DAC_IN1_B BITS(0, 9)
+#define RG_183 0x183
+#define FORCE_DASN_DAC_IN1_C BIT(15)
+#define DASN_DAC_IN1_C BITS(0, 9)
+#define RG_184 0x184
+#define FORCE_DASN_DAC_IN1_D BIT(15)
+#define DASN_DAC_IN1_D BITS(0, 9)
+#define RG_172 0x172
+#define CR_TX_AMP_OFFSET_A BITS(8, 13)
+#define CR_TX_AMP_OFFSET_B BITS(0, 5)
+#define RG_173 0x173
+#define CR_TX_AMP_OFFSET_C BITS(8, 13)
+#define CR_TX_AMP_OFFSET_D BITS(0, 5)
+/**********TX Amp Calibration ***************************/
+#define RG_12 0x12
+#define DA_TX_I2MPB_A_GBE BITS(10, 15)
+#define RG_17 0x17
+#define DA_TX_I2MPB_B_GBE BITS(8, 13)
+#define RG_19 0x19
+#define DA_TX_I2MPB_C_GBE BITS(8, 13)
+#define RG_21 0x21
+#define DA_TX_I2MPB_D_GBE BITS(8, 13)
+#define TX_AMP_MAX 0x3f
+#define TX_AMP_MAX_OFFSET 0xb
+#define TX_AMP_HIGHEST_TS ((TX_AMP_MAX) + 3)
+#define TX_AMP_LOWEST_TS (0 - 3)
+#define TX_AMP_HIGH_TS (TX_AMP_MAX)
+#define TX_AMP_LOW_TS 0
+
+/* PHY Extend Register 0x14 bitmap of define */
+#define PHY_EXT_REG_14 0x14
+
+/* Fields of PHY_EXT_REG_14 */
+#define PHY_EN_DOWN_SHFIT BIT(4)
+
+/* PHY Extend Register 0x17 bitmap of define */
+#define PHY_EXT_REG_17 0x17
+
+/* Fields of PHY_EXT_REG_17 */
+#define PHY_LINKDOWN_POWER_SAVING_EN BIT(4)
+
+/* PHY PMA Register 0x17 bitmap of define */
+#define SLV_DSP_READY_TIME_S 15
+#define SLV_DSP_READY_TIME_M (0xff << SLV_DSP_READY_TIME_S)
+
+/* PHY PMA Register 0x18 bitmap of define */
+#define ENABLE_RANDOM_UPDATE_TRIGGER BIT(8)
+
+/* PHY EEE Register bitmap of define */
+#define PHY_DEV07 0x07
+#define PHY_DEV07_REG_03C 0x3c
+
+/* PHY DEV 0x1e Register bitmap of define */
+#define PHY_DEV1E 0x1e
+#define PHY_DEV1F 0x1f
+
+/* Proprietory Control Register of Internal Phy device 0x1e */
+#define PHY_TX_MLT3_BASE 0x0
+#define PHY_DEV1E_REG_13 0x13
+#define PHY_DEV1E_REG_14 0x14
+#define PHY_DEV1E_REG_41 0x41
+#define PHY_DEV1E_REG_A6 0xa6
+#define RXADC_CONTROL_3 0xc2
+#define PHY_DEV1E_REG_0C6 0xc6
+#define RXADC_LDO_CONTROL_2 0xd3
+#define PHY_DEV1E_REG_0FE 0xfe
+#define PHY_DEV1E_REG_123 0x123
+#define PHY_DEV1E_REG_189 0x189
+#define PHY_DEV1E_REG_234 0x234
+
+/* Proprietory Control Register of Internal Phy device 0x1f */
+#define PHY_DEV1F_REG_44 0x44
+#define PHY_DEV1F_REG_268 0x268
+#define PHY_DEV1F_REG_269 0x269
+#define PHY_DEV1F_REG_26A 0x26A
+#define TXVLD_DA_271 0x271
+#define TXVLD_DA_272 0x272
+#define TXVLD_DA_273 0x273
+
+/* Fields of PHY_DEV1E_REG_0C6 */
+#define PHY_POWER_SAVING_S 8
+#define PHY_POWER_SAVING_M 0x300
+#define PHY_POWER_SAVING_TX 0x0
+
+/* Fields of PHY_DEV1E_REG_189 */
+#define DESCRAMBLER_CLEAR_EN 0x1
+
+/* Fields of PHY_DEV1E_REG_234 */
+#define TR_OPEN_LOOP_EN BIT(0)
+
+/* Internal GPHY Page Control Register */
+#define PHY_CL22_PAGE_CTRL 0x1f
+#define PHY_TR_PAGE 0x52b5
+
+/* Internal GPHY Token Ring Access Registers */
+#define PHY_TR_CTRL 0x10
+#define PHY_TR_LOW_DATA 0x11
+#define PHY_TR_HIGH_DATA 0x12
+
+/* Fields of PHY_TR_CTRL */
+#define PHY_TR_PKT_XMT_STA BIT(15)
+#define PHY_TR_WR_S 13
+#define PHY_TR_CH_ADDR_S 11
+#define PHY_TR_NODE_ADDR_S 7
+#define PHY_TR_DATA_ADDR_S 1
+
+enum phy_tr_wr {
+ PHY_TR_WRITE = 0,
+ PHY_TR_READ = 1,
+};
+
+/* Helper macro for GPHY Token Ring Access */
+#define PHY_TR_LOW_VAL(x) ((x) & 0xffff)
+#define PHY_TR_HIGH_VAL(x) (((x) & 0xff0000) >> 16)
+
+/* Token Ring Channels */
+#define PMA_CH 0x1
+#define DSP_CH 0x2
+
+/* Token Ring Nodes */
+#define PMA_NOD 0xf
+#define DSP_NOD 0xd
+
+/* Token Ring register range */
+enum tr_pma_reg_addr {
+ PMA_MIN = 0x0,
+ PMA_01 = 0x1,
+ PMA_17 = 0x17,
+ PMA_18 = 0x18,
+ PMA_MAX = 0x3d,
+};
+
+enum tr_dsp_reg_addr {
+ DSP_MIN = 0x0,
+ DSP_06 = 0x6,
+ DSP_08 = 0x8,
+ DSP_0f = 0xf,
+ DSP_10 = 0x10,
+ DSP_MAX = 0x3e,
+};
+#endif /* _AN8855_REGS_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 49c123b..bd4aac7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -258,7 +258,7 @@
"top_eth_xgmii_sel", "top_eth_mii_sel", "top_netsys_sel",
"top_netsys_500m_sel", "top_netsys_pao_2x_sel",
"top_netsys_sync_250m_sel", "top_netsys_ppefb_250m_sel",
- "top_netsys_warp_sel", "top_macsec_sel", "macsec_bus_clk",
+ "top_netsys_warp_sel", "top_macsec_sel",
};
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -967,10 +967,28 @@
pr_info("%s fsm invalid", __func__);
}
-static void mtk_pse_port_link_set(struct mtk_mac *mac, bool up)
+static void mtk_pse_port_link_set(struct mtk_mac *mac, bool up,
+ phy_interface_t interface)
{
u32 fe_glo_cfg, val = 0;
+ if (!up && interface == PHY_INTERFACE_MODE_XGMII) {
+ void __iomem *base;
+
+ base = ioremap(0x0F0CFB00, SZ_4K);
+ if (base) {
+ /* wait for internal 2.5G PHY to turn off */
+ usleep_range(100, 1000);
+ /* enable the XGMAC clock for 10 msecs to
+ * flush the packets.
+ */
+ writel(readl(base) | BIT(9), base);
+ usleep_range(10000, 11000);
+ writel(readl(base) & ~BIT(9), base);
+ iounmap(base);
+ }
+ }
+
fe_glo_cfg = mtk_r32(mac->hw, MTK_FE_GLO_CFG(mac->id));
switch (mac->id) {
case MTK_GMAC1_ID:
@@ -1002,7 +1020,7 @@
unsigned int id;
u32 mcr, sts;
- mtk_pse_port_link_set(mac, false);
+ mtk_pse_port_link_set(mac, false, interface);
if (mac->type == MTK_GDM_TYPE) {
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK);
@@ -1140,6 +1158,8 @@
if (duplex == DUPLEX_FULL ||
interface == PHY_INTERFACE_MODE_SGMII)
mcr |= MAC_MCR_FORCE_DPX;
+ else if (interface == PHY_INTERFACE_MODE_GMII)
+ mcr |= MAC_MCR_PRMBL_LMT_EN;
/* Configure pause modes -
* phylink will avoid these for half duplex
@@ -1184,7 +1204,7 @@
mcr &= ~(XMAC_MCR_TRX_DISABLE);
mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id));
}
- mtk_pse_port_link_set(mac, true);
+ mtk_pse_port_link_set(mac, true, interface);
}
static void mtk_validate(struct phylink_config *config,
@@ -4383,6 +4403,7 @@
mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
/* GDM and CDM Threshold */
+ mtk_w32(eth, 0x00000004, MTK_CDM2_THRES);
mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index c32a0ee..355b745 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -175,6 +175,7 @@
/* GDM and CDM Threshold */
#define MTK_GDM2_THRES 0x1530
+#define MTK_CDM2_THRES 0x1534
#define MTK_CDMW0_THRES 0x164c
#define MTK_CDMW1_THRES 0x1650
#define MTK_CDME0_THRES 0x1654
@@ -745,6 +746,7 @@
#define MAC_MCR_FORCE_MODE BIT(15)
#define MAC_MCR_TX_EN BIT(14)
#define MAC_MCR_RX_EN BIT(13)
+#define MAC_MCR_PRMBL_LMT_EN BIT(10)
#define MAC_MCR_BACKOFF_EN BIT(9)
#define MAC_MCR_BACKPR_EN BIT(8)
#define MAC_MCR_FORCE_EEE1000 BIT(7)
@@ -1192,7 +1194,6 @@
MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL,
MTK_CLK_TOP_NETSYS_WARP_SEL,
MTK_CLK_TOP_MACSEC_SEL,
- MTK_CLK_TOP_NETSYS_TOPS_400M_SEL,
MTK_CLK_MAX
};
@@ -1277,8 +1278,7 @@
BIT(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \
BIT(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \
BIT(MTK_CLK_TOP_NETSYS_WARP_SEL) | \
- BIT(MTK_CLK_TOP_MACSEC_SEL) | \
- BIT(MTK_CLK_TOP_NETSYS_TOPS_400M_SEL))
+ BIT(MTK_CLK_TOP_MACSEC_SEL))
enum mtk_dev_state {
MTK_HW_INIT,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index a0c22b5..e5d7240 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -419,6 +419,7 @@
hnat_priv->data->version == MTK_HNAT_V3) {
writel(0xcb777, hnat_priv->ppe_base[ppe_id] + PPE_DFT_CPORT1);
writel(0x7f, hnat_priv->ppe_base[ppe_id] + PPE_SBW_CTRL);
+ cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, SP_CMP_EN, 1);
}
if (hnat_priv->data->version == MTK_HNAT_V3) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 0ecdb25..ead9e1f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -188,6 +188,7 @@
#define TTL0_DRP (0x1 << 4) /* RW */
#define MCAST_TB_EN (0x1 << 7) /* RW */
#define MCAST_HASH (0x3 << 12) /* RW */
+#define SP_CMP_EN (0x1 << 25) /* RW */
#define MC_P3_PPSE (0xf << 12) /* RW */
#define MC_P2_PPSE (0xf << 8) /* RW */
@@ -1091,8 +1092,13 @@
#define entry_hnat_is_bound(e) (e->bfib1.state == BIND)
#define entry_hnat_state(e) (e->bfib1.state)
-#define skb_hnat_is_hashed(skb) \
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define skb_hnat_is_hashed(skb) \
+ (skb_hnat_entry(skb) != 0x7fff && skb_hnat_entry(skb) < hnat_priv->foe_etry_num)
+#else
+#define skb_hnat_is_hashed(skb) \
(skb_hnat_entry(skb) != 0x3fff && skb_hnat_entry(skb) < hnat_priv->foe_etry_num)
+#endif
#define FROM_GE_LAN_GRP(skb) (FROM_GE_LAN(skb) | FROM_GE_LAN2(skb))
#define FROM_GE_LAN(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN)
#define FROM_GE_LAN2(skb) (skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 54ec897..c36a174 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -227,6 +227,8 @@
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x02002800);
ndelay(1020);
+ regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
+ 0x20000000);
/* Setup DA default value */
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
0x00000020);
@@ -337,6 +339,8 @@
regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
0x02002800);
ndelay(1020);
+ regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
+ 0x20000000);
/* Setup DA default value */
regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
0x00000020);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig
new file mode 100644
index 0000000..654aa37
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Kconfig
@@ -0,0 +1,8 @@
+
+config AN8855_GSW
+ tristate "Driver for the Airoha AN8855 switch"
+ help
+ Airoha AN8855 devices and swconfig driver code,
+ Provide swconfig command for basic switch operation.
+ AN8855 support 2.5G speed and managed by SMI interface.
+ To compile this driver as a module, choose M here.
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile
new file mode 100644
index 0000000..5c24bda
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for Airoha AN8855 gigabit switch
+#
+
+obj-$(CONFIG_AN8855_GSW) += an8855.o
+
+an8855-$(CONFIG_SWCONFIG) += an8855_swconfig.o
+
+an8855-y += an8855_mdio.o an8855.o \
+ an8855_common.o an8855_vlan.o an8855_nl.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c
new file mode 100644
index 0000000..f3db8b8
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.c
@@ -0,0 +1,913 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
+
+#include "an8855.h"
+#include "an8855_regs.h"
+
+/* AN8855 registers */
+#define SCU_BASE 0x10000000
+#define RG_RGMII_TXCK_C (SCU_BASE + 0x1d0)
+
+#define HSGMII_AN_CSR_BASE 0x10220000
+#define SGMII_REG_AN0 (HSGMII_AN_CSR_BASE + 0x000)
+#define SGMII_REG_AN_13 (HSGMII_AN_CSR_BASE + 0x034)
+#define SGMII_REG_AN_FORCE_CL37 (HSGMII_AN_CSR_BASE + 0x060)
+
+#define HSGMII_CSR_PCS_BASE 0x10220000
+#define RG_HSGMII_PCS_CTROL_1 (HSGMII_CSR_PCS_BASE + 0xa00)
+#define RG_AN_SGMII_MODE_FORCE (HSGMII_CSR_PCS_BASE + 0xa24)
+
+#define MULTI_SGMII_CSR_BASE 0x10224000
+#define SGMII_STS_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x018)
+#define MSG_RX_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x100)
+#define MSG_RX_LIK_STS_0 (MULTI_SGMII_CSR_BASE + 0x514)
+#define MSG_RX_LIK_STS_2 (MULTI_SGMII_CSR_BASE + 0x51c)
+#define PHY_RX_FORCE_CTRL_0 (MULTI_SGMII_CSR_BASE + 0x520)
+
+#define XFI_CSR_PCS_BASE 0x10225000
+#define RG_USXGMII_AN_CONTROL_0 (XFI_CSR_PCS_BASE + 0xbf8)
+
+#define MULTI_PHY_RA_CSR_BASE 0x10226000
+#define RG_RATE_ADAPT_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x000)
+#define RATE_ADP_P0_CTRL_0 (MULTI_PHY_RA_CSR_BASE + 0x100)
+#define MII_RA_AN_ENABLE (MULTI_PHY_RA_CSR_BASE + 0x300)
+
+#define QP_DIG_CSR_BASE 0x1022a000
+#define QP_CK_RST_CTRL_4 (QP_DIG_CSR_BASE + 0x310)
+#define QP_DIG_MODE_CTRL_0 (QP_DIG_CSR_BASE + 0x324)
+#define QP_DIG_MODE_CTRL_1 (QP_DIG_CSR_BASE + 0x330)
+
+#define SERDES_WRAPPER_BASE 0x1022c000
+#define USGMII_CTRL_0 (SERDES_WRAPPER_BASE + 0x000)
+
+#define QP_PMA_TOP_BASE 0x1022e000
+#define PON_RXFEDIG_CTRL_0 (QP_PMA_TOP_BASE + 0x100)
+#define PON_RXFEDIG_CTRL_9 (QP_PMA_TOP_BASE + 0x124)
+
+#define SS_LCPLL_PWCTL_SETTING_2 (QP_PMA_TOP_BASE + 0x208)
+#define SS_LCPLL_TDC_FLT_2 (QP_PMA_TOP_BASE + 0x230)
+#define SS_LCPLL_TDC_FLT_5 (QP_PMA_TOP_BASE + 0x23c)
+#define SS_LCPLL_TDC_PCW_1 (QP_PMA_TOP_BASE + 0x248)
+#define INTF_CTRL_8 (QP_PMA_TOP_BASE + 0x320)
+#define INTF_CTRL_9 (QP_PMA_TOP_BASE + 0x324)
+#define PLL_CTRL_0 (QP_PMA_TOP_BASE + 0x400)
+#define PLL_CTRL_2 (QP_PMA_TOP_BASE + 0x408)
+#define PLL_CTRL_3 (QP_PMA_TOP_BASE + 0x40c)
+#define PLL_CTRL_4 (QP_PMA_TOP_BASE + 0x410)
+#define PLL_CK_CTRL_0 (QP_PMA_TOP_BASE + 0x414)
+#define RX_DLY_0 (QP_PMA_TOP_BASE + 0x614)
+#define RX_CTRL_2 (QP_PMA_TOP_BASE + 0x630)
+#define RX_CTRL_5 (QP_PMA_TOP_BASE + 0x63c)
+#define RX_CTRL_6 (QP_PMA_TOP_BASE + 0x640)
+#define RX_CTRL_7 (QP_PMA_TOP_BASE + 0x644)
+#define RX_CTRL_8 (QP_PMA_TOP_BASE + 0x648)
+#define RX_CTRL_26 (QP_PMA_TOP_BASE + 0x690)
+#define RX_CTRL_42 (QP_PMA_TOP_BASE + 0x6d0)
+
+#define QP_ANA_CSR_BASE 0x1022f000
+#define RG_QP_RX_DAC_EN (QP_ANA_CSR_BASE + 0x00)
+#define RG_QP_RXAFE_RESERVE (QP_ANA_CSR_BASE + 0x04)
+#define RG_QP_CDR_LPF_MJV_LIM (QP_ANA_CSR_BASE + 0x0c)
+#define RG_QP_CDR_LPF_SETVALUE (QP_ANA_CSR_BASE + 0x14)
+#define RG_QP_CDR_PR_CKREF_DIV1 (QP_ANA_CSR_BASE + 0x18)
+#define RG_QP_CDR_PR_KBAND_DIV_PCIE (QP_ANA_CSR_BASE + 0x1c)
+#define RG_QP_CDR_FORCE_IBANDLPF_R_OFF (QP_ANA_CSR_BASE + 0x20)
+#define RG_QP_TX_MODE_16B_EN (QP_ANA_CSR_BASE + 0x28)
+#define RG_QP_PLL_IPLL_DIG_PWR_SEL (QP_ANA_CSR_BASE + 0x3c)
+#define RG_QP_PLL_SDM_ORD (QP_ANA_CSR_BASE + 0x40)
+
+#define ETHER_SYS_BASE 0x1028c800
+#define RG_P5MUX_MODE (ETHER_SYS_BASE + 0x00)
+#define RG_FORCE_CKDIR_SEL (ETHER_SYS_BASE + 0x04)
+#define RG_SWITCH_MODE (ETHER_SYS_BASE + 0x08)
+#define RG_FORCE_MAC5_SB (ETHER_SYS_BASE + 0x2c)
+#define RG_GPHY_AFE_PWD (ETHER_SYS_BASE + 0x40)
+#define RG_GPHY_SMI_ADDR (ETHER_SYS_BASE + 0x48)
+#define CSR_RMII (ETHER_SYS_BASE + 0x70)
+
+/* PHY EEE Register bitmap of define */
+#define PHY_DEV07 0x07
+#define PHY_DEV07_REG_03C 0x3c
+
+/* PHY Extend Register 0x14 bitmap of define */
+#define PHY_EXT_REG_14 0x14
+
+/* Fields of PHY_EXT_REG_14 */
+#define PHY_EN_DOWN_SHFIT BIT(4)
+
+/* Unique fields of PMCR for AN8855 */
+#define FORCE_TX_FC BIT(4)
+#define FORCE_RX_FC BIT(5)
+#define FORCE_DPX BIT(25)
+#define FORCE_SPD BITS(28, 30)
+#define FORCE_LNK BIT(24)
+#define FORCE_MODE BIT(31)
+
+#define CHIP_ID 0x10005000
+#define CHIP_REV 0x10005004
+
+static int an8855_set_hsgmii_mode(struct gsw_an8855 *gsw)
+{
+ u32 val = 0;
+
+ /* PLL */
+ val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1);
+ val &= ~(0x3 << 2);
+ val |= (0x1 << 2);
+ an8855_reg_write(gsw, QP_DIG_MODE_CTRL_1, val);
+
+ /* PLL - LPF */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0x3 << 0);
+ val |= (0x1 << 0);
+ val &= ~(0x7 << 2);
+ val |= (0x5 << 2);
+ val &= ~BITS(6, 7);
+ val &= ~(0x7 << 8);
+ val |= (0x3 << 8);
+ val |= BIT(29);
+ val &= ~BITS(12, 13);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - ICO */
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val |= BIT(2);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~BIT(14);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - CHP */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0xf << 16);
+ val |= (0x6 << 16);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - PFD */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0x3 << 20);
+ val |= (0x1 << 20);
+ val &= ~(0x3 << 24);
+ val |= (0x1 << 24);
+ val &= ~BIT(26);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - POSTDIV */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val |= BIT(22);
+ val &= ~BIT(27);
+ val &= ~BIT(28);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - SDM */
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val &= ~BITS(3, 4);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ val = an8855_reg_read(gsw, SS_LCPLL_PWCTL_SETTING_2);
+ val &= ~(0x3 << 16);
+ val |= (0x1 << 16);
+ an8855_reg_write(gsw, SS_LCPLL_PWCTL_SETTING_2, val);
+
+ an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_2, 0x7a000000);
+ an8855_reg_write(gsw, SS_LCPLL_TDC_PCW_1, 0x7a000000);
+
+ val = an8855_reg_read(gsw, SS_LCPLL_TDC_FLT_5);
+ val &= ~BIT(24);
+ an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_5, val);
+
+ val = an8855_reg_read(gsw, PLL_CK_CTRL_0);
+ val &= ~BIT(8);
+ an8855_reg_write(gsw, PLL_CK_CTRL_0, val);
+
+ /* PLL - SS */
+ val = an8855_reg_read(gsw, PLL_CTRL_3);
+ val &= ~BITS(0, 15);
+ an8855_reg_write(gsw, PLL_CTRL_3, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val &= ~BITS(0, 1);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_3);
+ val &= ~BITS(16, 31);
+ an8855_reg_write(gsw, PLL_CTRL_3, val);
+
+ /* PLL - TDC */
+ val = an8855_reg_read(gsw, PLL_CK_CTRL_0);
+ val &= ~BIT(9);
+ an8855_reg_write(gsw, PLL_CK_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_QP_PLL_SDM_ORD);
+ val |= BIT(3);
+ val |= BIT(4);
+ an8855_reg_write(gsw, RG_QP_PLL_SDM_ORD, val);
+
+ val = an8855_reg_read(gsw, RG_QP_RX_DAC_EN);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ an8855_reg_write(gsw, RG_QP_RX_DAC_EN, val);
+
+ /* TCL Disable (only for Co-SIM) */
+ val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_0);
+ val &= ~BIT(12);
+ an8855_reg_write(gsw, PON_RXFEDIG_CTRL_0, val);
+
+ /* TX Init */
+ val = an8855_reg_read(gsw, RG_QP_TX_MODE_16B_EN);
+ val &= ~BIT(0);
+ val &= ~(0xffff << 16);
+ val |= (0x4 << 16);
+ an8855_reg_write(gsw, RG_QP_TX_MODE_16B_EN, val);
+
+ /* RX Control */
+ val = an8855_reg_read(gsw, RG_QP_RXAFE_RESERVE);
+ val |= BIT(11);
+ an8855_reg_write(gsw, RG_QP_RXAFE_RESERVE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_LPF_MJV_LIM);
+ val &= ~(0x3 << 4);
+ val |= (0x1 << 4);
+ an8855_reg_write(gsw, RG_QP_CDR_LPF_MJV_LIM, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_LPF_SETVALUE);
+ val &= ~(0xf << 25);
+ val |= (0x1 << 25);
+ val &= ~(0x7 << 29);
+ val |= (0x3 << 29);
+ an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x1f << 8);
+ val |= (0xf << 8);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~(0x3f << 0);
+ val |= (0x19 << 0);
+ val &= ~BIT(6);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF);
+ val &= ~(0x7f << 6);
+ val |= (0x21 << 6);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ val &= ~BIT(13);
+ an8855_reg_write(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x7 << 24);
+ val |= (0x4 << 24);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_0);
+ val |= BIT(0);
+ an8855_reg_write(gsw, PLL_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_26);
+ val &= ~BIT(23);
+ val |= BIT(26);
+ an8855_reg_write(gsw, RX_CTRL_26, val);
+
+ val = an8855_reg_read(gsw, RX_DLY_0);
+ val &= ~(0xff << 0);
+ val |= (0x6f << 0);
+ val |= BITS(8, 13);
+ an8855_reg_write(gsw, RX_DLY_0, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_42);
+ val &= ~(0x1fff << 0);
+ val |= (0x150 << 0);
+ an8855_reg_write(gsw, RX_CTRL_42, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_2);
+ val &= ~(0x1fff << 16);
+ val |= (0x150 << 16);
+ an8855_reg_write(gsw, RX_CTRL_2, val);
+
+ val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_9);
+ val &= ~(0x7 << 0);
+ val |= (0x1 << 0);
+ an8855_reg_write(gsw, PON_RXFEDIG_CTRL_9, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_8);
+ val &= ~(0xfff << 16);
+ val |= (0x200 << 16);
+ val &= ~(0x7fff << 14);
+ val |= (0xfff << 14);
+ an8855_reg_write(gsw, RX_CTRL_8, val);
+
+ /* Frequency memter */
+ val = an8855_reg_read(gsw, RX_CTRL_5);
+ val &= ~(0xfffff << 10);
+ val |= (0x10 << 10);
+ an8855_reg_write(gsw, RX_CTRL_5, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_6);
+ val &= ~(0xfffff << 0);
+ val |= (0x64 << 0);
+ an8855_reg_write(gsw, RX_CTRL_6, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_7);
+ val &= ~(0xfffff << 0);
+ val |= (0x2710 << 0);
+ an8855_reg_write(gsw, RX_CTRL_7, val);
+
+ /* PCS Init */
+ val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Rate Adaption */
+ val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0);
+ val &= ~BIT(31);
+ an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val);
+
+ /* Disable AN */
+ val = an8855_reg_read(gsw, SGMII_REG_AN0);
+ val &= ~BIT(12);
+ an8855_reg_write(gsw, SGMII_REG_AN0, val);
+
+ /* Force Speed */
+ val = an8855_reg_read(gsw, SGMII_STS_CTRL_0);
+ val |= BIT(2);
+ val |= BITS(4, 5);
+ an8855_reg_write(gsw, SGMII_STS_CTRL_0, val);
+
+ /* bypass flow control to MAC */
+ an8855_reg_write(gsw, MSG_RX_LIK_STS_0, 0x01010107);
+ an8855_reg_write(gsw, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return 0;
+}
+
+static int an8855_sgmii_setup(struct gsw_an8855 *gsw, int mode)
+{
+ u32 val = 0;
+
+ /* PMA Init */
+ /* PLL */
+ val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_1);
+ val &= ~BITS(2, 3);
+ an8855_reg_write(gsw, QP_DIG_MODE_CTRL_1, val);
+
+ /* PLL - LPF */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0x3 << 0);
+ val |= (0x1 << 0);
+ val &= ~(0x7 << 2);
+ val |= (0x5 << 2);
+ val &= ~BITS(6, 7);
+ val &= ~(0x7 << 8);
+ val |= (0x3 << 8);
+ val |= BIT(29);
+ val &= ~BITS(12, 13);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - ICO */
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val |= BIT(2);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~BIT(14);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - CHP */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0xf << 16);
+ val |= (0x4 << 16);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - PFD */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~(0x3 << 20);
+ val |= (0x1 << 20);
+ val &= ~(0x3 << 24);
+ val |= (0x1 << 24);
+ val &= ~BIT(26);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - POSTDIV */
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val |= BIT(22);
+ val &= ~BIT(27);
+ val &= ~BIT(28);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ /* PLL - SDM */
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val &= ~BITS(3, 4);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_2);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, PLL_CTRL_2, val);
+
+ val = an8855_reg_read(gsw, SS_LCPLL_PWCTL_SETTING_2);
+ val &= ~(0x3 << 16);
+ val |= (0x1 << 16);
+ an8855_reg_write(gsw, SS_LCPLL_PWCTL_SETTING_2, val);
+
+ an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_2, 0x48000000);
+ an8855_reg_write(gsw, SS_LCPLL_TDC_PCW_1, 0x48000000);
+
+ val = an8855_reg_read(gsw, SS_LCPLL_TDC_FLT_5);
+ val &= ~BIT(24);
+ an8855_reg_write(gsw, SS_LCPLL_TDC_FLT_5, val);
+
+ val = an8855_reg_read(gsw, PLL_CK_CTRL_0);
+ val &= ~BIT(8);
+ an8855_reg_write(gsw, PLL_CK_CTRL_0, val);
+
+ /* PLL - SS */
+ val = an8855_reg_read(gsw, PLL_CTRL_3);
+ val &= ~BITS(0, 15);
+ an8855_reg_write(gsw, PLL_CTRL_3, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_4);
+ val &= ~BITS(0, 1);
+ an8855_reg_write(gsw, PLL_CTRL_4, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_3);
+ val &= ~BITS(16, 31);
+ an8855_reg_write(gsw, PLL_CTRL_3, val);
+
+ /* PLL - TDC */
+ val = an8855_reg_read(gsw, PLL_CK_CTRL_0);
+ val &= ~BIT(9);
+ an8855_reg_write(gsw, PLL_CK_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_QP_PLL_SDM_ORD);
+ val |= BIT(3);
+ val |= BIT(4);
+ an8855_reg_write(gsw, RG_QP_PLL_SDM_ORD, val);
+
+ val = an8855_reg_read(gsw, RG_QP_RX_DAC_EN);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ an8855_reg_write(gsw, RG_QP_RX_DAC_EN, val);
+
+ /* PLL - TCL Disable (only for Co-SIM) */
+ val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_0);
+ val &= ~BIT(12);
+ an8855_reg_write(gsw, PON_RXFEDIG_CTRL_0, val);
+
+ /* TX Init */
+ val = an8855_reg_read(gsw, RG_QP_TX_MODE_16B_EN);
+ val &= ~BIT(0);
+ val &= ~BITS(16, 31);
+ an8855_reg_write(gsw, RG_QP_TX_MODE_16B_EN, val);
+
+ /* RX Init */
+ val = an8855_reg_read(gsw, RG_QP_RXAFE_RESERVE);
+ val |= BIT(11);
+ an8855_reg_write(gsw, RG_QP_RXAFE_RESERVE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_LPF_MJV_LIM);
+ val &= ~(0x3 << 4);
+ val |= (0x2 << 4);
+ an8855_reg_write(gsw, RG_QP_CDR_LPF_MJV_LIM, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_LPF_SETVALUE);
+ val &= ~(0xf << 25);
+ val |= (0x1 << 25);
+ val &= ~(0x7 << 29);
+ val |= (0x6 << 29);
+ an8855_reg_write(gsw, RG_QP_CDR_LPF_SETVALUE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x1f << 8);
+ val |= (0xc << 8);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~(0x3f << 0);
+ val |= (0x19 << 0);
+ val &= ~BIT(6);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF);
+ val &= ~(0x7f << 6);
+ val |= (0x21 << 6);
+ val &= ~(0x3 << 16);
+ val |= (0x2 << 16);
+ val &= ~BIT(13);
+ an8855_reg_write(gsw, RG_QP_CDR_FORCE_IBANDLPF_R_OFF, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_KBAND_DIV_PCIE, val);
+
+ val = an8855_reg_read(gsw, RG_QP_CDR_PR_CKREF_DIV1);
+ val &= ~(0x7 << 24);
+ val |= (0x4 << 24);
+ an8855_reg_write(gsw, RG_QP_CDR_PR_CKREF_DIV1, val);
+
+ val = an8855_reg_read(gsw, PLL_CTRL_0);
+ val |= BIT(0);
+ an8855_reg_write(gsw, PLL_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_26);
+ val &= ~BIT(23);
+ if (mode == SGMII_MODE_AN)
+ val |= BIT(26);
+
+ an8855_reg_write(gsw, RX_CTRL_26, val);
+
+ val = an8855_reg_read(gsw, RX_DLY_0);
+ val &= ~(0xff << 0);
+ val |= (0x6f << 0);
+ val |= BITS(8, 13);
+ an8855_reg_write(gsw, RX_DLY_0, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_42);
+ val &= ~(0x1fff << 0);
+ val |= (0x150 << 0);
+ an8855_reg_write(gsw, RX_CTRL_42, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_2);
+ val &= ~(0x1fff << 16);
+ val |= (0x150 << 16);
+ an8855_reg_write(gsw, RX_CTRL_2, val);
+
+ val = an8855_reg_read(gsw, PON_RXFEDIG_CTRL_9);
+ val &= ~(0x7 << 0);
+ val |= (0x1 << 0);
+ an8855_reg_write(gsw, PON_RXFEDIG_CTRL_9, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_8);
+ val &= ~(0xfff << 16);
+ val |= (0x200 << 16);
+ val &= ~(0x7fff << 0);
+ val |= (0xfff << 0);
+ an8855_reg_write(gsw, RX_CTRL_8, val);
+
+ /* Frequency memter */
+ val = an8855_reg_read(gsw, RX_CTRL_5);
+ val &= ~(0xfffff << 10);
+ val |= (0x28 << 10);
+ an8855_reg_write(gsw, RX_CTRL_5, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_6);
+ val &= ~(0xfffff << 0);
+ val |= (0x64 << 0);
+ an8855_reg_write(gsw, RX_CTRL_6, val);
+
+ val = an8855_reg_read(gsw, RX_CTRL_7);
+ val &= ~(0xfffff << 0);
+ val |= (0x2710 << 0);
+ an8855_reg_write(gsw, RX_CTRL_7, val);
+
+ if (mode == SGMII_MODE_FORCE) {
+ /* PCS Init */
+ val = an8855_reg_read(gsw, QP_DIG_MODE_CTRL_0);
+ val &= ~BIT(0);
+ val &= ~BITS(4, 5);
+ an8855_reg_write(gsw, QP_DIG_MODE_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Rate Adaption - GMII path config. */
+ val = an8855_reg_read(gsw, RG_AN_SGMII_MODE_FORCE);
+ val |= BIT(0);
+ val &= ~BITS(4, 5);
+ an8855_reg_write(gsw, RG_AN_SGMII_MODE_FORCE, val);
+
+ val = an8855_reg_read(gsw, SGMII_STS_CTRL_0);
+ val |= BIT(2);
+ val &= ~(0x3 << 4);
+ val |= (0x2 << 4);
+ an8855_reg_write(gsw, SGMII_STS_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, SGMII_REG_AN0);
+ val &= ~BIT(12);
+ an8855_reg_write(gsw, SGMII_REG_AN0, val);
+
+ val = an8855_reg_read(gsw, PHY_RX_FORCE_CTRL_0);
+ val |= BIT(4);
+ an8855_reg_write(gsw, PHY_RX_FORCE_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0);
+ val &= ~BITS(0, 3);
+ val |= BIT(28);
+ an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val);
+ } else {
+ /* PCS Init */
+ val = an8855_reg_read(gsw, RG_HSGMII_PCS_CTROL_1);
+ val &= ~BIT(30);
+ an8855_reg_write(gsw, RG_HSGMII_PCS_CTROL_1, val);
+
+ /* Set AN Ability - Interrupt */
+ val = an8855_reg_read(gsw, SGMII_REG_AN_FORCE_CL37);
+ val |= BIT(0);
+ an8855_reg_write(gsw, SGMII_REG_AN_FORCE_CL37, val);
+
+ val = an8855_reg_read(gsw, SGMII_REG_AN_13);
+ val &= ~(0x3f << 0);
+ val |= (0xb << 0);
+ val |= BIT(8);
+ an8855_reg_write(gsw, SGMII_REG_AN_13, val);
+
+ /* Rate Adaption - GMII path config. */
+ val = an8855_reg_read(gsw, SGMII_REG_AN0);
+ val |= BIT(12);
+ an8855_reg_write(gsw, SGMII_REG_AN0, val);
+
+ val = an8855_reg_read(gsw, MII_RA_AN_ENABLE);
+ val |= BIT(0);
+ an8855_reg_write(gsw, MII_RA_AN_ENABLE, val);
+
+ val = an8855_reg_read(gsw, RATE_ADP_P0_CTRL_0);
+ val |= BIT(28);
+ an8855_reg_write(gsw, RATE_ADP_P0_CTRL_0, val);
+
+ val = an8855_reg_read(gsw, RG_RATE_ADAPT_CTRL_0);
+ val |= BIT(0);
+ val |= BIT(4);
+ val |= BITS(26, 27);
+ an8855_reg_write(gsw, RG_RATE_ADAPT_CTRL_0, val);
+
+ /* Only for Co-SIM */
+
+ /* AN Speed up (Only for Co-SIM) */
+
+ /* Restart AN */
+ val = an8855_reg_read(gsw, SGMII_REG_AN0);
+ val |= BIT(9);
+ val |= BIT(15);
+ an8855_reg_write(gsw, SGMII_REG_AN0, val);
+ }
+
+ /* bypass flow control to MAC */
+ an8855_reg_write(gsw, MSG_RX_LIK_STS_0, 0x01010107);
+ an8855_reg_write(gsw, MSG_RX_LIK_STS_2, 0x00000EEF);
+
+ return 0;
+}
+
+static int an8855_set_port_rmii(struct gsw_an8855 *gsw)
+{
+ an8855_reg_write(gsw, RG_P5MUX_MODE, 0x301);
+ an8855_reg_write(gsw, RG_FORCE_CKDIR_SEL, 0x101);
+ an8855_reg_write(gsw, RG_SWITCH_MODE, 0x101);
+ an8855_reg_write(gsw, RG_FORCE_MAC5_SB, 0x1010101);
+ an8855_reg_write(gsw, CSR_RMII, 0x420102);
+ an8855_reg_write(gsw, RG_RGMII_TXCK_C, 0x1100910);
+ return 0;
+}
+
+static int an8855_set_port_rgmii(struct gsw_an8855 *gsw)
+{
+ an8855_reg_write(gsw, RG_FORCE_MAC5_SB, 0x20101);
+ return 0;
+}
+
+static int an8855_mac_port_setup(struct gsw_an8855 *gsw, u32 port,
+ struct an8855_port_cfg *port_cfg)
+{
+ u32 pmcr;
+
+ if (port != 5) {
+ dev_info(gsw->dev, "port %d is not a MAC port\n", port);
+ return -EINVAL;
+ }
+
+ if (port_cfg->enabled) {
+ pmcr = an8855_reg_read(gsw, PMCR(5));
+
+ switch (port_cfg->phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ pmcr &= ~FORCE_SPD;
+ pmcr |= FORCE_MODE | (MAC_SPD_100 << 28) | FORCE_DPX
+ | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC;
+ an8855_set_port_rmii(gsw);
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ pmcr &= ~FORCE_SPD;
+ pmcr |= FORCE_MODE | (MAC_SPD_1000 << 28) | FORCE_DPX
+ | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC;
+ an8855_set_port_rgmii(gsw);
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ if (port_cfg->force_link) {
+ pmcr &= ~FORCE_SPD;
+ pmcr |= FORCE_MODE | (MAC_SPD_1000 << 28)
+ | FORCE_DPX | FORCE_LNK | FORCE_TX_FC
+ | FORCE_RX_FC;
+ an8855_sgmii_setup(gsw, SGMII_MODE_FORCE);
+ } else
+ an8855_sgmii_setup(gsw, SGMII_MODE_AN);
+ break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ pmcr &= ~FORCE_SPD;
+ pmcr |= FORCE_MODE | (MAC_SPD_2500 << 28) | FORCE_DPX
+ | FORCE_LNK | FORCE_TX_FC | FORCE_RX_FC;
+ an8855_set_hsgmii_mode(gsw);
+ break;
+ default:
+ dev_info(gsw->dev, "%s is not supported by port %d\n",
+ phy_modes(port_cfg->phy_mode), port);
+ }
+
+ if (port_cfg->force_link)
+ an8855_reg_write(gsw, PMCR(port), pmcr);
+ }
+
+ return 0;
+}
+
+static int an8855_sw_detect(struct gsw_an8855 *gsw, struct chip_rev *crev)
+{
+ u32 id, rev;
+
+ id = an8855_reg_read(gsw, CHIP_ID);
+ rev = an8855_reg_read(gsw, CHIP_REV);
+ if (id == AN8855) {
+ if (crev) {
+ crev->rev = rev;
+ crev->name = "AN8855";
+ }
+
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+static void an8855_phy_setting(struct gsw_an8855 *gsw)
+{
+ int i;
+ u32 val;
+
+ /* Release power down */
+ an8855_reg_write(gsw, RG_GPHY_AFE_PWD, 0x0);
+
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ /* Enable HW auto downshift */
+ gsw->mii_write(gsw, i, 0x1f, 0x1);
+ val = gsw->mii_read(gsw, i, PHY_EXT_REG_14);
+ val |= PHY_EN_DOWN_SHFIT;
+ gsw->mii_write(gsw, i, PHY_EXT_REG_14, val);
+ gsw->mii_write(gsw, i, 0x1f, 0x0);
+
+ /* Enable Asymmetric Pause Capability */
+ val = gsw->mii_read(gsw, i, MII_ADVERTISE);
+ val |= ADVERTISE_PAUSE_ASYM;
+ gsw->mii_write(gsw, i, MII_ADVERTISE, val);
+ }
+}
+
+static void an8855_low_power_setting(struct gsw_an8855 *gsw)
+{
+ int port, addr;
+
+ for (port = 0; port < AN8855_NUM_PHYS; port++) {
+ gsw->mmd_write(gsw, port, 0x1e, 0x11, 0x0f00);
+ gsw->mmd_write(gsw, port, 0x1e, 0x3c, 0x0000);
+ gsw->mmd_write(gsw, port, 0x1e, 0x3d, 0x0000);
+ gsw->mmd_write(gsw, port, 0x1e, 0x3e, 0x0000);
+ gsw->mmd_write(gsw, port, 0x1e, 0xc6, 0x53aa);
+ }
+
+ gsw->mmd_write(gsw, 0, 0x1f, 0x268, 0x07f1);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x269, 0x2111);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x26a, 0x0000);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x26b, 0x0074);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x26e, 0x00f6);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x26f, 0x6666);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x271, 0x2c02);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x272, 0x0c22);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x700, 0x0001);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x701, 0x0803);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x702, 0x01b6);
+ gsw->mmd_write(gsw, 0, 0x1f, 0x703, 0x2111);
+
+ gsw->mmd_write(gsw, 1, 0x1f, 0x700, 0x0001);
+
+ for (addr = 0x200; addr <= 0x230; addr += 2)
+ gsw->mmd_write(gsw, 0, 0x1f, addr, 0x2020);
+
+ for (addr = 0x201; addr <= 0x231; addr += 2)
+ gsw->mmd_write(gsw, 0, 0x1f, addr, 0x0020);
+}
+
+static void an8855_eee_setting(struct gsw_an8855 *gsw, u32 port)
+{
+ /* Disable EEE */
+ gsw->mmd_write(gsw, port, PHY_DEV07, PHY_DEV07_REG_03C, 0);
+}
+
+static int an8855_sw_init(struct gsw_an8855 *gsw)
+{
+ int i;
+ u32 val;
+
+ gsw->phy_base = gsw->smi_addr & AN8855_SMI_ADDR_MASK;
+
+ gsw->mii_read = an8855_mii_read;
+ gsw->mii_write = an8855_mii_write;
+ gsw->mmd_read = an8855_mmd_read;
+ gsw->mmd_write = an8855_mmd_write;
+
+ /* Force MAC link down before reset */
+ an8855_reg_write(gsw, PMCR(5), FORCE_MODE);
+
+ /* Switch soft reset */
+ an8855_reg_write(gsw, SYS_CTRL, SW_SYS_RST);
+ usleep_range(100000, 110000);
+
+ /* change gphy smi address */
+ if (gsw->new_smi_addr != gsw->smi_addr) {
+ an8855_reg_write(gsw, RG_GPHY_SMI_ADDR, gsw->new_smi_addr);
+ gsw->smi_addr = gsw->new_smi_addr;
+ gsw->phy_base = gsw->new_smi_addr;
+ }
+
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ val = gsw->mii_read(gsw, i, MII_BMCR);
+ val |= BMCR_ISOLATE;
+ gsw->mii_write(gsw, i, MII_BMCR, val);
+ }
+
+ an8855_mac_port_setup(gsw, 5, &gsw->port5_cfg);
+
+ /* Global mac control settings */
+ val = an8855_reg_read(gsw, GMACCR);
+ val |= (15 << MAX_RX_JUMBO_S) | RX_PKT_LEN_MAX_JUMBO;
+ an8855_reg_write(gsw, GMACCR, val);
+
+ val = an8855_reg_read(gsw, CKGCR);
+ val &= ~(CKG_LNKDN_GLB_STOP | CKG_LNKDN_PORT_STOP);
+ an8855_reg_write(gsw, CKGCR, val);
+ return 0;
+}
+
+static int an8855_sw_post_init(struct gsw_an8855 *gsw)
+{
+ int i;
+ u32 val;
+
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ val = gsw->mii_read(gsw, i, MII_BMCR);
+ val &= ~BMCR_ISOLATE;
+ gsw->mii_write(gsw, i, MII_BMCR, val);
+ }
+
+ an8855_phy_setting(gsw);
+
+ for (i = 0; i < AN8855_NUM_PHYS; i++)
+ an8855_eee_setting(gsw, i);
+
+ /* PHY restart AN*/
+ for (i = 0; i < AN8855_NUM_PHYS; i++)
+ gsw->mii_write(gsw, i, MII_BMCR, 0x1240);
+
+ return 0;
+}
+
+struct an8855_sw_id an8855_id = {
+ .model = AN8855,
+ .detect = an8855_sw_detect,
+ .init = an8855_sw_init,
+ .post_init = an8855_sw_post_init
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Min Yao <min.yao@airoha.com>");
+MODULE_DESCRIPTION("Driver for Airoha AN8855 Gigabit Switch");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h
new file mode 100644
index 0000000..883ba6e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_H_
+#define _AN8855_H_
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/of_mdio.h>
+#include <linux/workqueue.h>
+#include <linux/gpio/consumer.h>
+#include <linux/phy.h>
+
+#ifdef CONFIG_SWCONFIG
+#include <linux/switch.h>
+#endif
+
+#include "an8855_vlan.h"
+
+#define AN8855_DFL_CPU_PORT 5
+#define AN8855_NUM_PHYS 5
+#define AN8855_DFL_SMI_ADDR 0x1
+#define AN8855_SMI_ADDR_MASK 0x1f
+
+struct gsw_an8855;
+
+enum an8855_model {
+ AN8855 = 0x8855,
+};
+
+enum sgmii_mode {
+ SGMII_MODE_AN,
+ SGMII_MODE_FORCE,
+};
+
+struct an8855_port_cfg {
+ struct device_node *np;
+ phy_interface_t phy_mode;
+ u32 enabled: 1;
+ u32 force_link: 1;
+ u32 speed: 2;
+ u32 duplex: 1;
+ bool stag_on;
+};
+
+struct gsw_an8855 {
+ u32 id;
+
+ struct device *dev;
+ struct mii_bus *host_bus;
+ u32 smi_addr;
+ u32 new_smi_addr;
+ u32 phy_base;
+
+ enum an8855_model model;
+ const char *name;
+
+ struct an8855_port_cfg port5_cfg;
+
+ int phy_link_sts;
+
+ int irq;
+ int reset_pin;
+ struct work_struct irq_worker;
+
+#ifdef CONFIG_SWCONFIG
+ struct switch_dev swdev;
+ u32 cpu_port;
+#endif
+
+ int global_vlan_enable;
+ struct an8855_vlan_entry vlan_entries[AN8855_NUM_VLANS];
+ struct an8855_port_entry port_entries[AN8855_NUM_PORTS];
+
+ int (*mii_read)(struct gsw_an8855 *gsw, int phy, int reg);
+ void (*mii_write)(struct gsw_an8855 *gsw, int phy, int reg, u16 val);
+
+ int (*mmd_read)(struct gsw_an8855 *gsw, int addr, int devad, u16 reg);
+ void (*mmd_write)(struct gsw_an8855 *gsw, int addr, int devad, u16 reg,
+ u16 val);
+
+ struct list_head list;
+};
+
+struct chip_rev {
+ const char *name;
+ u32 rev;
+};
+
+struct an8855_sw_id {
+ enum an8855_model model;
+ int (*detect)(struct gsw_an8855 *gsw, struct chip_rev *crev);
+ int (*init)(struct gsw_an8855 *gsw);
+ int (*post_init)(struct gsw_an8855 *gsw);
+};
+
+extern struct list_head an8855_devs;
+extern struct an8855_sw_id an8855_id;
+
+struct gsw_an8855 *an8855_get_gsw(u32 id);
+struct gsw_an8855 *an8855_get_first_gsw(void);
+void an8855_put_gsw(void);
+void an8855_lock_gsw(void);
+
+u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg);
+void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val);
+
+int an8855_mii_read(struct gsw_an8855 *gsw, int phy, int reg);
+void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val);
+
+int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg);
+void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg,
+ u16 val);
+
+void an8855_irq_worker(struct work_struct *work);
+void an8855_irq_enable(struct gsw_an8855 *gsw);
+
+#endif /* _AN8855_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c
new file mode 100644
index 0000000..c01b5c4
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_common.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "an8855.h"
+#include "an8855_regs.h"
+
+void an8855_irq_enable(struct gsw_an8855 *gsw)
+{
+ u32 val;
+ int i;
+
+ /* Record initial PHY link status */
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ val = gsw->mii_read(gsw, i, MII_BMSR);
+ if (val & BMSR_LSTATUS)
+ gsw->phy_link_sts |= BIT(i);
+ }
+
+ val = BIT(AN8855_NUM_PHYS) - 1;
+ an8855_reg_write(gsw, SYS_INT_EN, val);
+
+ val = an8855_reg_read(gsw, INT_MASK);
+ val |= INT_SYS_BIT;
+ an8855_reg_write(gsw, INT_MASK, val);
+}
+
+static void display_port_link_status(struct gsw_an8855 *gsw, u32 port)
+{
+ u32 pmsr, speed_bits;
+ const char *speed;
+
+ pmsr = an8855_reg_read(gsw, PMSR(port));
+
+ speed_bits = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S;
+
+ switch (speed_bits) {
+ case MAC_SPD_10:
+ speed = "10Mbps";
+ break;
+ case MAC_SPD_100:
+ speed = "100Mbps";
+ break;
+ case MAC_SPD_1000:
+ speed = "1Gbps";
+ break;
+ case MAC_SPD_2500:
+ speed = "2.5Gbps";
+ break;
+ default:
+ dev_info(gsw->dev, "Invalid speed\n");
+ return;
+ }
+
+ if (pmsr & MAC_LNK_STS) {
+ dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
+ port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
+ } else {
+ dev_info(gsw->dev, "Port %d Link is Down\n", port);
+ }
+}
+
+void an8855_irq_worker(struct work_struct *work)
+{
+ struct gsw_an8855 *gsw;
+ u32 sts, physts, laststs;
+ int i;
+
+ gsw = container_of(work, struct gsw_an8855, irq_worker);
+
+ sts = an8855_reg_read(gsw, SYS_INT_STS);
+
+ /* Check for changed PHY link status */
+ for (i = 0; i < AN8855_NUM_PHYS; i++) {
+ if (!(sts & PHY_LC_INT(i)))
+ continue;
+
+ laststs = gsw->phy_link_sts & BIT(i);
+ physts = !!(gsw->mii_read(gsw, i, MII_BMSR) & BMSR_LSTATUS);
+ physts <<= i;
+
+ if (physts ^ laststs) {
+ gsw->phy_link_sts ^= BIT(i);
+ display_port_link_status(gsw, i);
+ }
+ }
+
+ an8855_reg_write(gsw, SYS_INT_STS, sts);
+
+ enable_irq(gsw->irq);
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c
new file mode 100644
index 0000000..920240d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_mdio.c
@@ -0,0 +1,491 @@
+// SPDX-License-Identifian8855_gsw_ider: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+#include <linux/hrtimer.h>
+#include <linux/mii.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+#include <linux/of_irq.h>
+#include <linux/phy.h>
+
+#include "an8855.h"
+#include "an8855_swconfig.h"
+#include "an8855_regs.h"
+#include "an8855_nl.h"
+
+/* AN8855 driver version */
+#define ARHT_AN8855_SWCFG_DRIVER_VER "1.0.1-L5.4"
+
+static u32 an8855_gsw_id;
+struct list_head an8855_devs;
+static DEFINE_MUTEX(an8855_devs_lock);
+
+static struct an8855_sw_id *an8855_sw_ids[] = {
+ &an8855_id,
+};
+
+u32 an8855_reg_read(struct gsw_an8855 *gsw, u32 reg)
+{
+ u32 high, low;
+
+ mutex_lock(&gsw->host_bus->mdio_lock);
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4);
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x15,
+ ((reg >> 16) & 0xFFFF));
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x16,
+ (reg & 0xFFFF));
+
+ low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x18);
+ high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x17);
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
+
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+
+ return (high << 16) | (low & 0xffff);
+}
+
+void an8855_reg_write(struct gsw_an8855 *gsw, u32 reg, u32 val)
+{
+ mutex_lock(&gsw->host_bus->mdio_lock);
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x4);
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x11,
+ ((reg >> 16) & 0xFFFF));
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x12,
+ (reg & 0xFFFF));
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x13,
+ ((val >> 16) & 0xFFFF));
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x14,
+ (val & 0xFFFF));
+
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, 0x0);
+ gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, 0x0);
+
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+}
+
+int an8855_mii_read(struct gsw_an8855 *gsw, int phy, int reg)
+{
+ int val;
+
+ if (phy < AN8855_NUM_PHYS)
+ phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK;
+
+ mutex_lock(&gsw->host_bus->mdio_lock);
+ val = gsw->host_bus->read(gsw->host_bus, phy, reg);
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+
+ return val;
+}
+
+void an8855_mii_write(struct gsw_an8855 *gsw, int phy, int reg, u16 val)
+{
+ if (phy < AN8855_NUM_PHYS)
+ phy = (gsw->phy_base + phy) & AN8855_SMI_ADDR_MASK;
+
+ mutex_lock(&gsw->host_bus->mdio_lock);
+ gsw->host_bus->write(gsw->host_bus, phy, reg, val);
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+}
+
+int an8855_mmd_read(struct gsw_an8855 *gsw, int addr, int devad, u16 reg)
+{
+ int val;
+ u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
+
+ if (addr < AN8855_NUM_PHYS)
+ addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
+
+ mutex_lock(&gsw->host_bus->mdio_lock);
+ val = gsw->host_bus->read(gsw->host_bus, addr, regnum);
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+
+ return val;
+}
+
+void an8855_mmd_write(struct gsw_an8855 *gsw, int addr, int devad, u16 reg,
+ u16 val)
+{
+ u32 regnum = MII_ADDR_C45 | (devad << 16) | reg;
+
+ if (addr < AN8855_NUM_PHYS)
+ addr = (gsw->phy_base + addr) & AN8855_SMI_ADDR_MASK;
+
+ mutex_lock(&gsw->host_bus->mdio_lock);
+ gsw->host_bus->write(gsw->host_bus, addr, regnum, val);
+ mutex_unlock(&gsw->host_bus->mdio_lock);
+}
+
+static inline int an8855_get_duplex(const struct device_node *np)
+{
+ return of_property_read_bool(np, "full-duplex");
+}
+
+static void an8855_load_port_cfg(struct gsw_an8855 *gsw)
+{
+ struct device_node *port_np;
+ struct device_node *fixed_link_node;
+ struct an8855_port_cfg *port_cfg;
+ u32 port;
+
+ for_each_child_of_node(gsw->dev->of_node, port_np) {
+ if (!of_device_is_compatible(port_np, "airoha,an8855-port"))
+ continue;
+
+ if (!of_device_is_available(port_np))
+ continue;
+
+ if (of_property_read_u32(port_np, "reg", &port))
+ continue;
+
+ switch (port) {
+ case 5:
+ port_cfg = &gsw->port5_cfg;
+ break;
+ default:
+ continue;
+ }
+
+ if (port_cfg->enabled) {
+ dev_info(gsw->dev, "duplicated node for port%d\n",
+ port_cfg->phy_mode);
+ continue;
+ }
+
+ port_cfg->np = port_np;
+
+ port_cfg->phy_mode = of_get_phy_mode(port_np);
+ if (port_cfg->phy_mode < 0) {
+ dev_info(gsw->dev, "incorrect phy-mode %d\n", port);
+ continue;
+ }
+
+ fixed_link_node = of_get_child_by_name(port_np, "fixed-link");
+ if (fixed_link_node) {
+ u32 speed;
+
+ port_cfg->force_link = 1;
+ port_cfg->duplex = an8855_get_duplex(fixed_link_node);
+
+ if (of_property_read_u32(fixed_link_node, "speed",
+ &speed)) {
+ speed = 0;
+ continue;
+ }
+
+ of_node_put(fixed_link_node);
+
+ switch (speed) {
+ case 10:
+ port_cfg->speed = MAC_SPD_10;
+ break;
+ case 100:
+ port_cfg->speed = MAC_SPD_100;
+ break;
+ case 1000:
+ port_cfg->speed = MAC_SPD_1000;
+ break;
+ case 2500:
+ port_cfg->speed = MAC_SPD_2500;
+ break;
+
+ default:
+ dev_info(gsw->dev, "incorrect speed %d\n",
+ speed);
+ continue;
+ }
+ }
+
+ port_cfg->stag_on =
+ of_property_read_bool(port_cfg->np, "airoha,stag-on");
+ port_cfg->enabled = 1;
+ }
+}
+
+static void an8855_add_gsw(struct gsw_an8855 *gsw)
+{
+ mutex_lock(&an8855_devs_lock);
+ gsw->id = an8855_gsw_id++;
+ INIT_LIST_HEAD(&gsw->list);
+ list_add_tail(&gsw->list, &an8855_devs);
+ mutex_unlock(&an8855_devs_lock);
+}
+
+static void an8855_remove_gsw(struct gsw_an8855 *gsw)
+{
+ mutex_lock(&an8855_devs_lock);
+ list_del(&gsw->list);
+ mutex_unlock(&an8855_devs_lock);
+}
+
+struct gsw_an8855 *an8855_get_gsw(u32 id)
+{
+ struct gsw_an8855 *dev;
+
+ mutex_lock(&an8855_devs_lock);
+
+ list_for_each_entry(dev, &an8855_devs, list) {
+ if (dev->id == id)
+ return dev;
+ }
+
+ mutex_unlock(&an8855_devs_lock);
+
+ return NULL;
+}
+
+struct gsw_an8855 *an8855_get_first_gsw(void)
+{
+ struct gsw_an8855 *dev;
+
+ mutex_lock(&an8855_devs_lock);
+
+ list_for_each_entry(dev, &an8855_devs, list)
+ return dev;
+
+ mutex_unlock(&an8855_devs_lock);
+
+ return NULL;
+}
+
+void an8855_put_gsw(void)
+{
+ mutex_unlock(&an8855_devs_lock);
+}
+
+void an8855_lock_gsw(void)
+{
+ mutex_lock(&an8855_devs_lock);
+}
+
+static int an8855_hw_reset(struct gsw_an8855 *gsw)
+{
+ struct device_node *np = gsw->dev->of_node;
+ int ret;
+
+ gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
+ if (gsw->reset_pin < 0) {
+ dev_info(gsw->dev, "No reset pin of switch\n");
+ return 0;
+ }
+
+ ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "an8855-reset");
+ if (ret) {
+ dev_info(gsw->dev, "Failed to request gpio %d\n",
+ gsw->reset_pin);
+ return ret;
+ }
+
+ gpio_direction_output(gsw->reset_pin, 0);
+ usleep_range(100000, 150000);
+ gpio_set_value(gsw->reset_pin, 1);
+ usleep_range(100000, 150000);
+
+ return 0;
+}
+
+static irqreturn_t an8855_irq_handler(int irq, void *dev)
+{
+ struct gsw_an8855 *gsw = dev;
+
+ disable_irq_nosync(gsw->irq);
+
+ schedule_work(&gsw->irq_worker);
+
+ return IRQ_HANDLED;
+}
+
+static int an8855_probe(struct platform_device *pdev)
+{
+ struct gsw_an8855 *gsw;
+ struct an8855_sw_id *sw;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *mdio;
+ struct mii_bus *mdio_bus;
+ int ret = -EINVAL;
+ struct chip_rev rev;
+ struct an8855_mapping *map;
+ int i;
+
+ mdio = of_parse_phandle(np, "airoha,mdio", 0);
+ if (!mdio)
+ return -EINVAL;
+
+ mdio_bus = of_mdio_find_bus(mdio);
+ if (!mdio_bus)
+ return -EPROBE_DEFER;
+
+ gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_an8855), GFP_KERNEL);
+ if (!gsw)
+ return -ENOMEM;
+
+ gsw->host_bus = mdio_bus;
+ gsw->dev = &pdev->dev;
+
+ dev_info(gsw->dev, "AN8855 Driver Version=%s\n",
+ ARHT_AN8855_SWCFG_DRIVER_VER);
+
+ /* Switch hard reset */
+ if (an8855_hw_reset(gsw)) {
+ dev_info(&pdev->dev, "reset switch fail.\n");
+ goto fail;
+ }
+
+ /* Fetch the SMI address first */
+ gsw->smi_addr = AN8855_DFL_SMI_ADDR;
+ if (of_property_read_u32(np, "airoha,smi-addr", &gsw->new_smi_addr))
+ gsw->new_smi_addr = AN8855_DFL_SMI_ADDR;
+
+ /* Get LAN/WAN port mapping */
+ map = an8855_find_mapping(np);
+ if (map) {
+ an8855_apply_mapping(gsw, map);
+ gsw->global_vlan_enable = 1;
+ dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
+ }
+
+ /* Load MAC port configurations */
+ an8855_load_port_cfg(gsw);
+
+ /* Check for valid switch and then initialize */
+ an8855_gsw_id = 0;
+ for (i = 0; i < ARRAY_SIZE(an8855_sw_ids); i++) {
+ if (!an8855_sw_ids[i]->detect(gsw, &rev)) {
+ sw = an8855_sw_ids[i];
+
+ gsw->name = rev.name;
+ gsw->model = sw->model;
+
+ dev_info(gsw->dev, "Switch is Airoha %s rev %d",
+ gsw->name, rev.rev);
+
+ /* Initialize the switch */
+ ret = sw->init(gsw);
+ if (ret)
+ goto fail;
+
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(an8855_sw_ids)) {
+ dev_err(gsw->dev, "No an8855 switch found\n");
+ goto fail;
+ }
+
+ gsw->irq = platform_get_irq(pdev, 0);
+ if (gsw->irq >= 0) {
+ ret = devm_request_irq(gsw->dev, gsw->irq, an8855_irq_handler,
+ 0, dev_name(gsw->dev), gsw);
+ if (ret) {
+ dev_err(gsw->dev, "Failed to request irq %d\n",
+ gsw->irq);
+ goto fail;
+ }
+
+ INIT_WORK(&gsw->irq_worker, an8855_irq_worker);
+ }
+
+ platform_set_drvdata(pdev, gsw);
+
+ an8855_add_gsw(gsw);
+
+ an8855_gsw_nl_init();
+
+ an8855_swconfig_init(gsw);
+
+ if (sw->post_init)
+ sw->post_init(gsw);
+
+ if (gsw->irq >= 0)
+ an8855_irq_enable(gsw);
+
+ return 0;
+
+fail:
+ devm_kfree(&pdev->dev, gsw);
+
+ return ret;
+}
+
+static int an8855_remove(struct platform_device *pdev)
+{
+ struct gsw_an8855 *gsw = platform_get_drvdata(pdev);
+
+ if (gsw->irq >= 0)
+ cancel_work_sync(&gsw->irq_worker);
+
+ if (gsw->reset_pin >= 0)
+ devm_gpio_free(&pdev->dev, gsw->reset_pin);
+
+#ifdef CONFIG_SWCONFIG
+ an8855_swconfig_destroy(gsw);
+#endif
+
+ an8855_gsw_nl_exit();
+
+ an8855_remove_gsw(gsw);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id an8855_ids[] = {
+ {.compatible = "airoha,an8855"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, an8855_ids);
+
+static struct platform_driver an8855_driver = {
+ .probe = an8855_probe,
+ .remove = an8855_remove,
+ .driver = {
+ .name = "an8855",
+ .of_match_table = an8855_ids,
+ },
+};
+
+static int __init an8855_init(void)
+{
+ int ret;
+
+ INIT_LIST_HEAD(&an8855_devs);
+ ret = platform_driver_register(&an8855_driver);
+
+ return ret;
+}
+
+module_init(an8855_init);
+
+static void __exit an8855_exit(void)
+{
+ platform_driver_unregister(&an8855_driver);
+}
+
+module_exit(an8855_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Min Yao <min.yao@airoha.com>");
+MODULE_VERSION(ARHT_AN8855_SWCFG_DRIVER_VER);
+MODULE_DESCRIPTION("Driver for Airoha AN8855 Gigabit Switch");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c
new file mode 100644
index 0000000..37e3dad
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <net/genetlink.h>
+
+#include "an8855.h"
+#include "an8855_nl.h"
+
+struct an8855_nl_cmd_item {
+ enum an8855_cmd cmd;
+ bool require_dev;
+ int (*process)(struct genl_info *info, struct gsw_an8855 *gsw);
+ u32 nr_required_attrs;
+ const enum an8855_attr *required_attrs;
+};
+
+static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info);
+
+static const struct nla_policy an8855_nl_cmd_policy[] = {
+ [AN8855_ATTR_TYPE_MESG] = { .type = NLA_STRING },
+ [AN8855_ATTR_TYPE_PHY] = { .type = NLA_S32 },
+ [AN8855_ATTR_TYPE_REG] = { .type = NLA_S32 },
+ [AN8855_ATTR_TYPE_VAL] = { .type = NLA_S32 },
+ [AN8855_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
+ [AN8855_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
+ [AN8855_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
+};
+
+static const struct genl_ops an8855_nl_ops[] = {
+ {
+ .cmd = AN8855_CMD_REQUEST,
+ .doit = an8855_nl_response,
+// .policy = an8855_nl_cmd_policy,
+ .flags = GENL_ADMIN_PERM,
+ }, {
+ .cmd = AN8855_CMD_READ,
+ .doit = an8855_nl_response,
+// .policy = an8855_nl_cmd_policy,
+ .flags = GENL_ADMIN_PERM,
+ }, {
+ .cmd = AN8855_CMD_WRITE,
+ .doit = an8855_nl_response,
+// .policy = an8855_nl_cmd_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+static struct genl_family an8855_nl_family = {
+ .name = AN8855_GENL_NAME,
+ .version = AN8855_GENL_VERSION,
+ .maxattr = AN8855_NR_ATTR_TYPE,
+ .ops = an8855_nl_ops,
+ .n_ops = ARRAY_SIZE(an8855_nl_ops),
+ .policy = an8855_nl_cmd_policy,
+};
+
+static int an8855_nl_list_devs(char *buff, int size)
+{
+ struct gsw_an8855 *gsw;
+ int len, total = 0;
+ char buf[80];
+
+ memset(buff, 0, size);
+
+ an8855_lock_gsw();
+
+ list_for_each_entry(gsw, &an8855_devs, list) {
+ len = snprintf(buf, sizeof(buf),
+ "id: %d, model: %s, node: %s\n",
+ gsw->id, gsw->name, gsw->dev->of_node->name);
+ if (len == strlen(buf)) {
+ if (size - total > 0)
+ strncat(buff, buf, size - total);
+ total += len;
+ }
+ }
+
+ an8855_put_gsw();
+
+ return total;
+}
+
+static int an8855_nl_prepare_reply(struct genl_info *info, u8 cmd,
+ struct sk_buff **skbp)
+{
+ struct sk_buff *msg;
+ void *reply;
+
+ if (!info)
+ return -EINVAL;
+
+ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ /* Construct send-back message header */
+ reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &an8855_nl_family, 0, cmd);
+ if (!reply) {
+ nlmsg_free(msg);
+ return -EINVAL;
+ }
+
+ *skbp = msg;
+ return 0;
+}
+
+static int an8855_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
+{
+ struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
+ void *reply = genlmsg_data(genlhdr);
+
+ /* Finalize a generic netlink message (update message header) */
+ genlmsg_end(skb, reply);
+
+ /* reply to a request */
+ return genlmsg_reply(skb, info);
+}
+
+static s32 an8855_nl_get_s32(struct genl_info *info, enum an8855_attr attr,
+ s32 defval)
+{
+ struct nlattr *na;
+
+ na = info->attrs[attr];
+ if (na)
+ return nla_get_s32(na);
+
+ return defval;
+}
+
+static int an8855_nl_get_u32(struct genl_info *info, enum an8855_attr attr,
+ u32 *val)
+{
+ struct nlattr *na;
+
+ na = info->attrs[attr];
+ if (na) {
+ *val = nla_get_u32(na);
+ return 0;
+ }
+
+ return -1;
+}
+
+static struct gsw_an8855 *an8855_nl_parse_find_gsw(struct genl_info *info)
+{
+ struct gsw_an8855 *gsw;
+ struct nlattr *na;
+ int gsw_id;
+
+ na = info->attrs[AN8855_ATTR_TYPE_DEV_ID];
+ if (na) {
+ gsw_id = nla_get_s32(na);
+ if (gsw_id >= 0)
+ gsw = an8855_get_gsw(gsw_id);
+ else
+ gsw = an8855_get_first_gsw();
+ } else {
+ gsw = an8855_get_first_gsw();
+ }
+
+ return gsw;
+}
+
+static int an8855_nl_get_swdevs(struct genl_info *info, struct gsw_an8855 *gsw)
+{
+ struct sk_buff *rep_skb = NULL;
+ char dev_info[512];
+ int ret;
+
+ ret = an8855_nl_list_devs(dev_info, sizeof(dev_info) - 1);
+ if (!ret) {
+ pr_info("No switch registered\n");
+ return -EINVAL;
+ }
+
+ ret = an8855_nl_prepare_reply(info, AN8855_CMD_REPLY, &rep_skb);
+ if (ret < 0)
+ goto err;
+
+ ret = nla_put_string(rep_skb, AN8855_ATTR_TYPE_MESG, dev_info);
+ if (ret < 0)
+ goto err;
+
+ return an8855_nl_send_reply(rep_skb, info);
+
+err:
+ if (rep_skb)
+ nlmsg_free(rep_skb);
+
+ return ret;
+}
+
+static int an8855_nl_reply_read(struct genl_info *info, struct gsw_an8855 *gsw)
+{
+ struct sk_buff *rep_skb = NULL;
+ s32 phy, devad, reg;
+ int value;
+ int ret = 0;
+
+ phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
+ devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
+ reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
+
+ if (reg < 0)
+ goto err;
+
+ ret = an8855_nl_prepare_reply(info, AN8855_CMD_READ, &rep_skb);
+ if (ret < 0)
+ goto err;
+
+ if (phy >= 0) {
+ if (devad < 0)
+ value = gsw->mii_read(gsw, phy, reg);
+ else
+ value = gsw->mmd_read(gsw, phy, devad, reg);
+ } else {
+ value = an8855_reg_read(gsw, reg);
+ }
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
+ if (ret < 0)
+ goto err;
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
+ if (ret < 0)
+ goto err;
+
+ return an8855_nl_send_reply(rep_skb, info);
+
+err:
+ if (rep_skb)
+ nlmsg_free(rep_skb);
+
+ return ret;
+}
+
+static int an8855_nl_reply_write(struct genl_info *info, struct gsw_an8855 *gsw)
+{
+ struct sk_buff *rep_skb = NULL;
+ s32 phy, devad, reg;
+ u32 value;
+ int ret = 0;
+
+ phy = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_PHY, -1);
+ devad = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_DEVAD, -1);
+ reg = an8855_nl_get_s32(info, AN8855_ATTR_TYPE_REG, -1);
+
+ if (an8855_nl_get_u32(info, AN8855_ATTR_TYPE_VAL, &value))
+ goto err;
+
+ if (reg < 0)
+ goto err;
+
+ ret = an8855_nl_prepare_reply(info, AN8855_CMD_WRITE, &rep_skb);
+ if (ret < 0)
+ goto err;
+
+ if (phy >= 0) {
+ if (devad < 0)
+ gsw->mii_write(gsw, phy, reg, value);
+ else
+ gsw->mmd_write(gsw, phy, devad, reg, value);
+ } else {
+ an8855_reg_write(gsw, reg, value);
+ }
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_REG, reg);
+ if (ret < 0)
+ goto err;
+
+ ret = nla_put_s32(rep_skb, AN8855_ATTR_TYPE_VAL, value);
+ if (ret < 0)
+ goto err;
+
+ return an8855_nl_send_reply(rep_skb, info);
+
+err:
+ if (rep_skb)
+ nlmsg_free(rep_skb);
+
+ return ret;
+}
+
+static const enum an8855_attr an8855_nl_cmd_read_attrs[] = {
+ AN8855_ATTR_TYPE_REG
+};
+
+static const enum an8855_attr an8855_nl_cmd_write_attrs[] = {
+ AN8855_ATTR_TYPE_REG,
+ AN8855_ATTR_TYPE_VAL
+};
+
+static const struct an8855_nl_cmd_item an8855_nl_cmds[] = {
+ {
+ .cmd = AN8855_CMD_REQUEST,
+ .require_dev = false,
+ .process = an8855_nl_get_swdevs
+ }, {
+ .cmd = AN8855_CMD_READ,
+ .require_dev = true,
+ .process = an8855_nl_reply_read,
+ .required_attrs = an8855_nl_cmd_read_attrs,
+ .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_read_attrs),
+ }, {
+ .cmd = AN8855_CMD_WRITE,
+ .require_dev = true,
+ .process = an8855_nl_reply_write,
+ .required_attrs = an8855_nl_cmd_write_attrs,
+ .nr_required_attrs = ARRAY_SIZE(an8855_nl_cmd_write_attrs),
+ }
+};
+
+static int an8855_nl_response(struct sk_buff *skb, struct genl_info *info)
+{
+ struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
+ const struct an8855_nl_cmd_item *cmditem = NULL;
+ struct gsw_an8855 *gsw = NULL;
+ u32 sat_req_attrs = 0;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(an8855_nl_cmds); i++) {
+ if (hdr->cmd == an8855_nl_cmds[i].cmd) {
+ cmditem = &an8855_nl_cmds[i];
+ break;
+ }
+ }
+
+ if (!cmditem) {
+ pr_info("an8855-nl: unknown cmd %u\n", hdr->cmd);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cmditem->nr_required_attrs; i++) {
+ if (info->attrs[cmditem->required_attrs[i]])
+ sat_req_attrs++;
+ }
+
+ if (sat_req_attrs != cmditem->nr_required_attrs) {
+ pr_info("an8855-nl: missing required attr(s) for cmd %u\n",
+ hdr->cmd);
+ return -EINVAL;
+ }
+
+ if (cmditem->require_dev) {
+ gsw = an8855_nl_parse_find_gsw(info);
+ if (!gsw) {
+ pr_info("an8855-nl: failed to find switch dev\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = cmditem->process(info, gsw);
+
+ an8855_put_gsw();
+
+ return ret;
+}
+
+int an8855_gsw_nl_init(void)
+{
+ int ret;
+
+ ret = genl_register_family(&an8855_nl_family);
+ if (ret) {
+ pr_info("an8855-nl: genl_register_family_with_ops failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+void an8855_gsw_nl_exit(void)
+{
+ genl_unregister_family(&an8855_nl_family);
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h
new file mode 100644
index 0000000..b00df75
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_nl.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_NL_H_
+#define _AN8855_NL_H_
+
+#define AN8855_GENL_NAME "an8855"
+#define AN8855_GENL_VERSION 0x1
+
+enum an8855_cmd {
+ AN8855_CMD_UNSPEC = 0,
+ AN8855_CMD_REQUEST,
+ AN8855_CMD_REPLY,
+ AN8855_CMD_READ,
+ AN8855_CMD_WRITE,
+
+ __AN8855_CMD_MAX,
+};
+
+enum an8855_attr {
+ AN8855_ATTR_TYPE_UNSPEC = 0,
+ AN8855_ATTR_TYPE_MESG,
+ AN8855_ATTR_TYPE_PHY,
+ AN8855_ATTR_TYPE_DEVAD,
+ AN8855_ATTR_TYPE_REG,
+ AN8855_ATTR_TYPE_VAL,
+ AN8855_ATTR_TYPE_DEV_NAME,
+ AN8855_ATTR_TYPE_DEV_ID,
+
+ __AN8855_ATTR_TYPE_MAX,
+};
+
+#define AN8855_NR_ATTR_TYPE (__AN8855_ATTR_TYPE_MAX - 1)
+
+#ifdef __KERNEL__
+int an8855_gsw_nl_init(void);
+void an8855_gsw_nl_exit(void);
+#endif /* __KERNEL__ */
+
+#endif /* _AN8855_NL_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h
new file mode 100644
index 0000000..9dbfaeb
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_regs.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_REGS_H_
+#define _AN8855_REGS_H_
+
+#include <linux/bitops.h>
+
+#define BITS(m, n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
+
+/* Values of Egress TAG Control */
+#define ETAG_CTRL_UNTAG 0
+#define ETAG_CTRL_TAG 2
+#define ETAG_CTRL_SWAP 1
+#define ETAG_CTRL_STACK 3
+
+#define VTCR 0x10200600
+#define VAWD0 0x10200604
+#define VAWD1 0x10200608
+#define VARD0 0x10200618
+#define VARD1 0x1020061C
+
+/* Fields of VTCR */
+#define VTCR_BUSY BIT(31)
+#define VTCR_FUNC_S 12
+#define VTCR_FUNC_M 0xf000
+#define VTCR_VID_S 0
+#define VTCR_VID_M 0xfff
+
+/* Values of VTCR_FUNC */
+#define VTCR_READ_VLAN_ENTRY 0
+#define VTCR_WRITE_VLAN_ENTRY 1
+
+/* VLAN entry fields */
+#define IVL_MAC BIT(5)
+#define EG_CON BIT(11)
+#define VTAG_EN BIT(10)
+#define PORT_MEM_S 26
+#define PORT_MEM_M 0xfc000000
+#define VENTRY_VALID BIT(0)
+#define ETAG_M 0x3fff000
+#define PORT_ETAG_S(p) (((p) * 2) + 12)
+#define PORT_ETAG_M 0x03
+
+#define PORT_CTRL_BASE 0x10208000
+#define PORT_CTRL_PORT_OFFSET 0x200
+#define PORT_CTRL_REG(p, r) (PORT_CTRL_BASE + \
+ (p) * PORT_CTRL_PORT_OFFSET + (r))
+#define PCR(p) PORT_CTRL_REG(p, 0x04)
+#define PVC(p) PORT_CTRL_REG(p, 0x10)
+#define PORTMATRIX(p) PORT_CTRL_REG(p, 0x44)
+#define PVID(p) PORT_CTRL_REG(p, 0x48)
+
+#define GRP_PORT_VID_M 0xfff
+
+/* Values of PORT_VLAN */
+#define PORT_MATRIX_MODE 0
+#define FALLBACK_MODE 1
+#define CHECK_MODE 2
+#define SECURITY_MODE 3
+
+/* Fields of PVC */
+#define STAG_VPID_S 16
+#define STAG_VPID_M 0xffff0000
+#define VLAN_ATTR_S 6
+#define VLAN_ATTR_M 0xc0
+#define PVC_STAG_REPLACE BIT(11)
+#define PVC_PORT_STAG BIT(5)
+
+/* Values of VLAN_ATTR */
+#define VA_USER_PORT 0
+#define VA_STACK_PORT 1
+#define VA_TRANSLATION_PORT 2
+#define VA_TRANSPARENT_PORT 3
+
+#define PORT_MATRIX_M ((1 << AN8855_NUM_PORTS) - 1)
+
+#define PORT_MAC_CTRL_BASE 0x10210000
+#define PORT_MAC_CTRL_PORT_OFFSET 0x200
+#define PORT_MAC_CTRL_REG(p, r) (PORT_MAC_CTRL_BASE + \
+ (p) * PORT_MAC_CTRL_PORT_OFFSET + (r))
+#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00)
+#define PMSR(p) PORT_MAC_CTRL_REG(p, 0x10)
+
+#define GMACCR (PORT_MAC_CTRL_BASE + 0x30e0)
+
+#define MAX_RX_JUMBO_S 2
+#define MAX_RX_JUMBO_M 0x3c
+#define MAX_RX_PKT_LEN_S 0
+#define MAX_RX_PKT_LEN_M 0x3
+
+/* Values of MAX_RX_PKT_LEN */
+#define RX_PKT_LEN_1518 0
+#define RX_PKT_LEN_1536 1
+#define RX_PKT_LEN_1522 2
+#define RX_PKT_LEN_MAX_JUMBO 3
+
+/* Fields of PMSR */
+#define EEE1G_STS BIT(7)
+#define EEE100_STS BIT(6)
+#define RX_FC_STS BIT(5)
+#define TX_FC_STS BIT(4)
+#define MAC_SPD_STS_S 28
+#define MAC_SPD_STS_M 0x70000000
+#define MAC_DPX_STS BIT(25)
+#define MAC_LNK_STS BIT(24)
+
+/* Values of MAC_SPD_STS */
+#define MAC_SPD_10 0
+#define MAC_SPD_100 1
+#define MAC_SPD_1000 2
+#define MAC_SPD_2500 3
+
+#define MIB_COUNTER_BASE 0x10214000
+#define MIB_COUNTER_PORT_OFFSET 0x200
+#define MIB_COUNTER_REG(p, r) (MIB_COUNTER_BASE + \
+ (p) * MIB_COUNTER_PORT_OFFSET + (r))
+#define STATS_TDPC 0x00
+#define STATS_TCRC 0x04
+#define STATS_TUPC 0x08
+#define STATS_TMPC 0x0C
+#define STATS_TBPC 0x10
+#define STATS_TCEC 0x14
+#define STATS_TSCEC 0x18
+#define STATS_TMCEC 0x1C
+#define STATS_TDEC 0x20
+#define STATS_TLCEC 0x24
+#define STATS_TXCEC 0x28
+#define STATS_TPPC 0x2C
+#define STATS_TL64PC 0x30
+#define STATS_TL65PC 0x34
+#define STATS_TL128PC 0x38
+#define STATS_TL256PC 0x3C
+#define STATS_TL512PC 0x40
+#define STATS_TL1024PC 0x44
+#define STATS_TL1519PC 0x48
+#define STATS_TOC 0x4C
+#define STATS_TODPC 0x54
+#define STATS_TOC2 0x58
+
+#define STATS_RDPC 0x80
+#define STATS_RFPC 0x84
+#define STATS_RUPC 0x88
+#define STATS_RMPC 0x8C
+#define STATS_RBPC 0x90
+#define STATS_RAEPC 0x94
+#define STATS_RCEPC 0x98
+#define STATS_RUSPC 0x9C
+#define STATS_RFEPC 0xA0
+#define STATS_ROSPC 0xA4
+#define STATS_RJEPC 0xA8
+#define STATS_RPPC 0xAC
+#define STATS_RL64PC 0xB0
+#define STATS_RL65PC 0xB4
+#define STATS_RL128PC 0xB8
+#define STATS_RL256PC 0xBC
+#define STATS_RL512PC 0xC0
+#define STATS_RL1024PC 0xC4
+#define STATS_RL1519PC 0xC8
+#define STATS_ROC 0xCC
+#define STATS_RDPC_CTRL 0xD4
+#define STATS_RDPC_ING 0xD8
+#define STATS_RDPC_ARL 0xDC
+#define STATS_RDPC_FC 0xE0
+#define STATS_RDPC_WRED 0xE4
+#define STATS_RDPC_MIR 0xE8
+#define STATS_ROC2 0xEC
+#define STATS_RSFSPC 0xF4
+#define STATS_RSFTPC 0xF8
+#define STATS_RXCDPC 0xFC
+
+#define SYS_CTRL 0x100050C0
+#define SW_SYS_RST BIT(31)
+
+#define INT_MASK 0x100050F0
+#define INT_SYS_BIT BIT(15)
+
+#define SYS_INT_EN 0x1021C010
+#define SYS_INT_STS 0x1021C014
+#define PHY_LC_INT(p) BIT(p)
+
+#define CKGCR (0x10213E1C)
+#define CKG_LNKDN_GLB_STOP (0x01)
+#define CKG_LNKDN_PORT_STOP (0x02)
+#endif /* _AN8855_REGS_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c
new file mode 100644
index 0000000..e796582
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/if.h>
+#include <linux/list.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/netlink.h>
+#include <linux/bitops.h>
+#include <net/genetlink.h>
+#include <linux/delay.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/lockdep.h>
+#include <linux/workqueue.h>
+#include <linux/of_device.h>
+
+#include "an8855.h"
+#include "an8855_swconfig.h"
+#include "an8855_regs.h"
+
+#define AN8855_PORT_MIB_TXB_ID 19 /* TxByte */
+#define AN8855_PORT_MIB_RXB_ID 40 /* RxByte */
+
+#define MIB_DESC(_s, _o, _n) \
+ { \
+ .size = (_s), \
+ .offset = (_o), \
+ .name = (_n), \
+ }
+
+struct an8855_mib_desc {
+ unsigned int size;
+ unsigned int offset;
+ const char *name;
+};
+
+static const struct an8855_mib_desc an8855_mibs[] = {
+ MIB_DESC(1, STATS_TDPC, "TxDrop"),
+ MIB_DESC(1, STATS_TCRC, "TxCRC"),
+ MIB_DESC(1, STATS_TUPC, "TxUni"),
+ MIB_DESC(1, STATS_TMPC, "TxMulti"),
+ MIB_DESC(1, STATS_TBPC, "TxBroad"),
+ MIB_DESC(1, STATS_TCEC, "TxCollision"),
+ MIB_DESC(1, STATS_TSCEC, "TxSingleCol"),
+ MIB_DESC(1, STATS_TMCEC, "TxMultiCol"),
+ MIB_DESC(1, STATS_TDEC, "TxDefer"),
+ MIB_DESC(1, STATS_TLCEC, "TxLateCol"),
+ MIB_DESC(1, STATS_TXCEC, "TxExcCol"),
+ MIB_DESC(1, STATS_TPPC, "TxPause"),
+ MIB_DESC(1, STATS_TL64PC, "Tx64Byte"),
+ MIB_DESC(1, STATS_TL65PC, "Tx65Byte"),
+ MIB_DESC(1, STATS_TL128PC, "Tx128Byte"),
+ MIB_DESC(1, STATS_TL256PC, "Tx256Byte"),
+ MIB_DESC(1, STATS_TL512PC, "Tx512Byte"),
+ MIB_DESC(1, STATS_TL1024PC, "Tx1024Byte"),
+ MIB_DESC(1, STATS_TL1519PC, "Tx1519Byte"),
+ MIB_DESC(2, STATS_TOC, "TxByte"),
+ MIB_DESC(1, STATS_TODPC, "TxOverSize"),
+ MIB_DESC(2, STATS_TOC2, "SecondaryTxByte"),
+ MIB_DESC(1, STATS_RDPC, "RxDrop"),
+ MIB_DESC(1, STATS_RFPC, "RxFiltered"),
+ MIB_DESC(1, STATS_RUPC, "RxUni"),
+ MIB_DESC(1, STATS_RMPC, "RxMulti"),
+ MIB_DESC(1, STATS_RBPC, "RxBroad"),
+ MIB_DESC(1, STATS_RAEPC, "RxAlignErr"),
+ MIB_DESC(1, STATS_RCEPC, "RxCRC"),
+ MIB_DESC(1, STATS_RUSPC, "RxUnderSize"),
+ MIB_DESC(1, STATS_RFEPC, "RxFragment"),
+ MIB_DESC(1, STATS_ROSPC, "RxOverSize"),
+ MIB_DESC(1, STATS_RJEPC, "RxJabber"),
+ MIB_DESC(1, STATS_RPPC, "RxPause"),
+ MIB_DESC(1, STATS_RL64PC, "Rx64Byte"),
+ MIB_DESC(1, STATS_RL65PC, "Rx65Byte"),
+ MIB_DESC(1, STATS_RL128PC, "Rx128Byte"),
+ MIB_DESC(1, STATS_RL256PC, "Rx256Byte"),
+ MIB_DESC(1, STATS_RL512PC, "Rx512Byte"),
+ MIB_DESC(1, STATS_RL1024PC, "Rx1024Byte"),
+ MIB_DESC(2, STATS_ROC, "RxByte"),
+ MIB_DESC(1, STATS_RDPC_CTRL, "RxCtrlDrop"),
+ MIB_DESC(1, STATS_RDPC_ING, "RxIngDrop"),
+ MIB_DESC(1, STATS_RDPC_ARL, "RxARLDrop"),
+ MIB_DESC(1, STATS_RDPC_FC, "RxFCDrop"),
+ MIB_DESC(1, STATS_RDPC_WRED, "RxWREDDrop"),
+ MIB_DESC(1, STATS_RDPC_MIR, "RxMIRDrop"),
+ MIB_DESC(2, STATS_ROC2, "SecondaryRxByte"),
+ MIB_DESC(1, STATS_RSFSPC, "RxsFlowSampling"),
+ MIB_DESC(1, STATS_RSFTPC, "RxsFlowTotal"),
+ MIB_DESC(1, STATS_RXCDPC, "RxPortDrop"),
+};
+
+enum {
+ /* Global attributes. */
+ AN8855_ATTR_ENABLE_VLAN,
+};
+
+static int an8855_get_vlan_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ val->value.i = gsw->global_vlan_enable;
+
+ return 0;
+}
+
+static int an8855_set_vlan_enable(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ gsw->global_vlan_enable = val->value.i != 0;
+
+ return 0;
+}
+
+static int an8855_get_port_pvid(struct switch_dev *dev, int port, int *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ if (port >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ *val = an8855_reg_read(gsw, PVID(port));
+ *val &= GRP_PORT_VID_M;
+
+ return 0;
+}
+
+static int an8855_set_port_pvid(struct switch_dev *dev, int port, int pvid)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ if (port >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ if (pvid < AN8855_MIN_VID || pvid > AN8855_MAX_VID)
+ return -EINVAL;
+
+ gsw->port_entries[port].pvid = pvid;
+
+ return 0;
+}
+
+static int an8855_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ u32 member;
+ u32 etags;
+ int i;
+
+ val->len = 0;
+
+ if (val->port_vlan >= AN8855_NUM_VLANS)
+ return -EINVAL;
+
+ an8855_vlan_ctrl(gsw, VTCR_READ_VLAN_ENTRY, val->port_vlan);
+
+ member = an8855_reg_read(gsw, VARD0);
+ member &= PORT_MEM_M;
+ member >>= PORT_MEM_S;
+ member |= ((an8855_reg_read(gsw, VARD1) & 0x1) << 6);
+
+ etags = an8855_reg_read(gsw, VARD0) & ETAG_M;
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ struct switch_port *p;
+ int etag;
+
+ if (!(member & BIT(i)))
+ continue;
+
+ p = &val->value.ports[val->len++];
+ p->id = i;
+
+ etag = (etags >> PORT_ETAG_S(i)) & PORT_ETAG_M;
+
+ if (etag == ETAG_CTRL_TAG)
+ p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED);
+ else if (etag != ETAG_CTRL_UNTAG)
+ dev_info(gsw->dev,
+ "vlan egress tag control neither untag nor tag.\n");
+ }
+
+ return 0;
+}
+
+static int an8855_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ u8 member = 0;
+ u8 etags = 0;
+ int i;
+
+ if (val->port_vlan >= AN8855_NUM_VLANS ||
+ val->len > AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ for (i = 0; i < val->len; i++) {
+ struct switch_port *p = &val->value.ports[i];
+
+ if (p->id >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ member |= BIT(p->id);
+
+ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED))
+ etags |= BIT(p->id);
+ }
+
+ gsw->vlan_entries[val->port_vlan].member = member;
+ gsw->vlan_entries[val->port_vlan].etags = etags;
+
+ return 0;
+}
+
+static int an8855_set_vid(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ int vlan;
+ u16 vid;
+
+ vlan = val->port_vlan;
+ vid = (u16)val->value.i;
+
+ if (vlan < 0 || vlan >= AN8855_NUM_VLANS)
+ return -EINVAL;
+
+ if (vid > AN8855_MAX_VID)
+ return -EINVAL;
+
+ gsw->vlan_entries[vlan].vid = vid;
+ return 0;
+}
+
+static int an8855_get_vid(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ val->value.i = val->port_vlan;
+ return 0;
+}
+
+static int an8855_get_port_link(struct switch_dev *dev, int port,
+ struct switch_port_link *link)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ u32 speed, pmsr;
+
+ if (port < 0 || port >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ pmsr = an8855_reg_read(gsw, PMSR(port));
+
+ link->link = pmsr & MAC_LNK_STS;
+ link->duplex = pmsr & MAC_DPX_STS;
+ speed = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S;
+
+ switch (speed) {
+ case MAC_SPD_10:
+ link->speed = SWITCH_PORT_SPEED_10;
+ break;
+ case MAC_SPD_100:
+ link->speed = SWITCH_PORT_SPEED_100;
+ break;
+ case MAC_SPD_1000:
+ link->speed = SWITCH_PORT_SPEED_1000;
+ break;
+ case MAC_SPD_2500:
+ /* TODO: swconfig has no support for 2500 now */
+ link->speed = SWITCH_PORT_SPEED_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
+
+static int an8855_set_port_link(struct switch_dev *dev, int port,
+ struct switch_port_link *link)
+{
+#ifndef MODULE
+ if (port >= AN8855_NUM_PHYS)
+ return -EINVAL;
+
+ return switch_generic_set_link(dev, port, link);
+#else
+ return -ENOTSUPP;
+#endif
+}
+
+static u64 get_mib_counter(struct gsw_an8855 *gsw, int i, int port)
+{
+ unsigned int offset;
+ u64 lo, hi, hi2;
+
+ offset = an8855_mibs[i].offset;
+
+ if (an8855_mibs[i].size == 1)
+ return an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
+
+ do {
+ hi = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
+ lo = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset));
+ hi2 = an8855_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4));
+ } while (hi2 != hi);
+
+ return (hi << 32) | lo;
+}
+
+static int an8855_get_port_mib(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ static char buf[4096];
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ int i, len = 0;
+
+ if (val->port_vlan >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "Port %d MIB counters\n", val->port_vlan);
+
+ for (i = 0; i < ARRAY_SIZE(an8855_mibs); ++i) {
+ u64 counter;
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%-11s: ", an8855_mibs[i].name);
+ counter = get_mib_counter(gsw, i, val->port_vlan);
+ len += snprintf(buf + len, sizeof(buf) - len, "%llu\n",
+ counter);
+ }
+
+ val->value.s = buf;
+ val->len = len;
+ return 0;
+}
+
+static int an8855_get_port_stats(struct switch_dev *dev, int port,
+ struct switch_port_stats *stats)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ if (port < 0 || port >= AN8855_NUM_PORTS)
+ return -EINVAL;
+
+ stats->tx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_TXB_ID, port);
+ stats->rx_bytes = get_mib_counter(gsw, AN8855_PORT_MIB_RXB_ID, port);
+
+ return 0;
+}
+
+static void an8855_port_isolation(struct gsw_an8855 *gsw)
+{
+ int i;
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++)
+ an8855_reg_write(gsw, PORTMATRIX(i),
+ BIT(gsw->cpu_port));
+
+ an8855_reg_write(gsw, PORTMATRIX(gsw->cpu_port), PORT_MATRIX_M);
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ u32 pvc_mode = 0x8100 << STAG_VPID_S;
+
+ if (gsw->port5_cfg.stag_on && i == 5)
+ pvc_mode |= PVC_PORT_STAG | PVC_STAG_REPLACE;
+ else
+ pvc_mode |= (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
+
+ an8855_reg_write(gsw, PVC(i), pvc_mode);
+ }
+}
+
+static int an8855_apply_config(struct switch_dev *dev)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ if (!gsw->global_vlan_enable) {
+ an8855_port_isolation(gsw);
+ return 0;
+ }
+
+ an8855_apply_vlan_config(gsw);
+
+ return 0;
+}
+
+static int an8855_reset_switch(struct switch_dev *dev)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+ int i;
+
+ memset(gsw->port_entries, 0, sizeof(gsw->port_entries));
+ memset(gsw->vlan_entries, 0, sizeof(gsw->vlan_entries));
+
+ /* set default vid of each vlan to the same number of vlan, so the vid
+ * won't need be set explicitly.
+ */
+ for (i = 0; i < AN8855_NUM_VLANS; i++)
+ gsw->vlan_entries[i].vid = i;
+
+ return 0;
+}
+
+static int an8855_phy_read16(struct switch_dev *dev, int addr, u8 reg,
+ u16 *value)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ *value = gsw->mii_read(gsw, addr, reg);
+
+ return 0;
+}
+
+static int an8855_phy_write16(struct switch_dev *dev, int addr, u8 reg,
+ u16 value)
+{
+ struct gsw_an8855 *gsw = container_of(dev, struct gsw_an8855, swdev);
+
+ gsw->mii_write(gsw, addr, reg, value);
+
+ return 0;
+}
+
+static const struct switch_attr an8855_global[] = {
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "enable_vlan",
+ .description = "VLAN mode (1:enabled)",
+ .max = 1,
+ .id = AN8855_ATTR_ENABLE_VLAN,
+ .get = an8855_get_vlan_enable,
+ .set = an8855_set_vlan_enable,
+ }
+};
+
+static const struct switch_attr an8855_port[] = {
+ {
+ .type = SWITCH_TYPE_STRING,
+ .name = "mib",
+ .description = "Get MIB counters for port",
+ .get = an8855_get_port_mib,
+ .set = NULL,
+ },
+};
+
+static const struct switch_attr an8855_vlan[] = {
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "vid",
+ .description = "VLAN ID (0-4094)",
+ .set = an8855_set_vid,
+ .get = an8855_get_vid,
+ .max = 4094,
+ },
+};
+
+static const struct switch_dev_ops an8855_swdev_ops = {
+ .attr_global = {
+ .attr = an8855_global,
+ .n_attr = ARRAY_SIZE(an8855_global),
+ },
+ .attr_port = {
+ .attr = an8855_port,
+ .n_attr = ARRAY_SIZE(an8855_port),
+ },
+ .attr_vlan = {
+ .attr = an8855_vlan,
+ .n_attr = ARRAY_SIZE(an8855_vlan),
+ },
+ .get_vlan_ports = an8855_get_vlan_ports,
+ .set_vlan_ports = an8855_set_vlan_ports,
+ .get_port_pvid = an8855_get_port_pvid,
+ .set_port_pvid = an8855_set_port_pvid,
+ .get_port_link = an8855_get_port_link,
+ .set_port_link = an8855_set_port_link,
+ .get_port_stats = an8855_get_port_stats,
+ .apply_config = an8855_apply_config,
+ .reset_switch = an8855_reset_switch,
+ .phy_read16 = an8855_phy_read16,
+ .phy_write16 = an8855_phy_write16,
+};
+
+int an8855_swconfig_init(struct gsw_an8855 *gsw)
+{
+ struct device_node *np = gsw->dev->of_node;
+ struct switch_dev *swdev;
+ int ret;
+
+ if (of_property_read_u32(np, "airoha,cpuport", &gsw->cpu_port))
+ gsw->cpu_port = AN8855_DFL_CPU_PORT;
+
+ swdev = &gsw->swdev;
+
+ swdev->name = gsw->name;
+ swdev->alias = gsw->name;
+ swdev->cpu_port = gsw->cpu_port;
+ swdev->ports = AN8855_NUM_PORTS;
+ swdev->vlans = AN8855_NUM_VLANS;
+ swdev->ops = &an8855_swdev_ops;
+
+ ret = register_switch(swdev, NULL);
+ if (ret) {
+ dev_notice(gsw->dev, "Failed to register switch %s\n",
+ swdev->name);
+ return ret;
+ }
+
+ an8855_apply_config(swdev);
+
+ return 0;
+}
+
+void an8855_swconfig_destroy(struct gsw_an8855 *gsw)
+{
+ unregister_switch(&gsw->swdev);
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h
new file mode 100644
index 0000000..4c8f2bf
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_swconfig.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ * Author: Min Yao <min.yao@airoha.com>
+ */
+
+#ifndef _AN8855_SWCONFIG_H_
+#define _AN8855_SWCONFIG_H_
+
+#ifdef CONFIG_SWCONFIG
+#include <linux/switch.h>
+#include "an8855.h"
+
+int an8855_swconfig_init(struct gsw_an8855 *gsw);
+void an8855_swconfig_destroy(struct gsw_an8855 *gsw);
+#else
+static inline int an8855_swconfig_init(struct gsw_an8855 *gsw)
+{
+ an8855_apply_vlan_config(gsw);
+
+ return 0;
+}
+
+static inline void an8855_swconfig_destroy(struct gsw_an8855 *gsw)
+{
+}
+#endif
+
+#endif /* _AN8855_SWCONFIG_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c
new file mode 100644
index 0000000..6ef8c99
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.c
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ */
+
+#include "an8855.h"
+#include "an8855_regs.h"
+
+struct an8855_mapping an8855_def_mapping[] = {
+ {
+ .name = "llllw",
+ .pvids = { 1, 1, 1, 1, 2, 1 },
+ .members = { 0, 0x2f, 0x30 },
+ .etags = { 0, 0, 0x20 },
+ .vids = { 0, 1, 2 },
+ }, {
+ .name = "wllll",
+ .pvids = { 2, 1, 1, 1, 1, 1 },
+ .members = { 0, 0x3e, 0x21 },
+ .etags = { 0, 0, 0x20 },
+ .vids = { 0, 1, 2 },
+ }, {
+ .name = "lwlll",
+ .pvids = { 1, 2, 1, 1, 1, 1 },
+ .members = { 0, 0x3d, 0x22 },
+ .etags = { 0, 0, 0x20 },
+ .vids = { 0, 1, 2 },
+ }, {
+ .name = "lllll",
+ .pvids = { 1, 1, 1, 1, 1, 1 },
+ .members = { 0, 0x3f },
+ .etags = { 0, 0 },
+ .vids = { 0, 1 },
+ },
+};
+
+void an8855_vlan_ctrl(struct gsw_an8855 *gsw, u32 cmd, u32 val)
+{
+ int i;
+
+ an8855_reg_write(gsw, VTCR,
+ VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
+ (val & VTCR_VID_M));
+
+ for (i = 0; i < 300; i++) {
+ u32 val = an8855_reg_read(gsw, VTCR);
+
+ if ((val & VTCR_BUSY) == 0)
+ break;
+
+ usleep_range(1000, 1100);
+ }
+
+ if (i == 300)
+ dev_info(gsw->dev, "vtcr timeout\n");
+}
+
+static void an8855_write_vlan_entry(struct gsw_an8855 *gsw, int vlan, u16 vid,
+ u8 ports, u8 etags)
+{
+ int port;
+ u32 val;
+
+ /* vlan port membership */
+ if (ports) {
+ val = IVL_MAC | VTAG_EN | VENTRY_VALID
+ | ((ports << PORT_MEM_S) & PORT_MEM_M);
+ /* egress mode */
+ for (port = 0; port < AN8855_NUM_PORTS; port++) {
+ if (etags & BIT(port))
+ val |= (ETAG_CTRL_TAG << PORT_ETAG_S(port));
+ else
+ val |= (ETAG_CTRL_UNTAG << PORT_ETAG_S(port));
+ }
+ an8855_reg_write(gsw, VAWD0, val);
+ } else {
+ an8855_reg_write(gsw, VAWD0, 0);
+ }
+
+ if (ports & 0x40)
+ an8855_reg_write(gsw, VAWD1, 0x1);
+ else
+ an8855_reg_write(gsw, VAWD1, 0x0);
+
+ /* write to vlan table */
+ an8855_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
+}
+
+void an8855_apply_vlan_config(struct gsw_an8855 *gsw)
+{
+ int i, j;
+ u8 tag_ports;
+ u8 untag_ports;
+ u32 val;
+
+ /* set all ports as security mode */
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ val = an8855_reg_read(gsw, PCR(i));
+ an8855_reg_write(gsw, PCR(i), val | SECURITY_MODE);
+ an8855_reg_write(gsw, PORTMATRIX(i), PORT_MATRIX_M);
+ }
+
+ /* check if a port is used in tag/untag vlan egress mode */
+ tag_ports = 0;
+ untag_ports = 0;
+
+ for (i = 0; i < AN8855_NUM_VLANS; i++) {
+ u8 member = gsw->vlan_entries[i].member;
+ u8 etags = gsw->vlan_entries[i].etags;
+
+ if (!member)
+ continue;
+
+ for (j = 0; j < AN8855_NUM_PORTS; j++) {
+ if (!(member & BIT(j)))
+ continue;
+
+ if (etags & BIT(j))
+ tag_ports |= 1u << j;
+ else
+ untag_ports |= 1u << j;
+ }
+ }
+
+ /* set all untag-only ports as transparent and the rest as user port */
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ u32 pvc_mode = 0x8100 << STAG_VPID_S;
+
+ if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
+ pvc_mode = (0x8100 << STAG_VPID_S) |
+ (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
+
+ if (gsw->port5_cfg.stag_on && i == 5)
+ pvc_mode = (u32)((0x8100 << STAG_VPID_S) | PVC_PORT_STAG
+ | PVC_STAG_REPLACE);
+
+ an8855_reg_write(gsw, PVC(i), pvc_mode);
+ }
+
+ /* first clear the switch vlan table */
+ for (i = 0; i < AN8855_NUM_VLANS; i++)
+ an8855_write_vlan_entry(gsw, i, i, 0, 0);
+
+ /* now program only vlans with members to avoid
+ * clobbering remapped entries in later iterations
+ */
+ for (i = 0; i < AN8855_NUM_VLANS; i++) {
+ u16 vid = gsw->vlan_entries[i].vid;
+ u8 member = gsw->vlan_entries[i].member;
+ u8 etags = gsw->vlan_entries[i].etags;
+
+ if (member)
+ an8855_write_vlan_entry(gsw, i, vid, member, etags);
+ }
+
+ /* Port Default PVID */
+ for (i = 0; i < AN8855_NUM_PORTS; i++) {
+ int vlan = gsw->port_entries[i].pvid;
+ u16 pvid = 0;
+ u32 val;
+
+ if (vlan < AN8855_NUM_VLANS && gsw->vlan_entries[vlan].member)
+ pvid = gsw->vlan_entries[vlan].vid;
+
+ val = an8855_reg_read(gsw, PVID(i));
+ val &= ~GRP_PORT_VID_M;
+ val |= pvid;
+ an8855_reg_write(gsw, PVID(i), val);
+ }
+}
+
+struct an8855_mapping *an8855_find_mapping(struct device_node *np)
+{
+ const char *map;
+ int i;
+
+ if (of_property_read_string(np, "airoha,portmap", &map))
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(an8855_def_mapping); i++)
+ if (!strcmp(map, an8855_def_mapping[i].name))
+ return &an8855_def_mapping[i];
+
+ return NULL;
+}
+
+void an8855_apply_mapping(struct gsw_an8855 *gsw, struct an8855_mapping *map)
+{
+ int i = 0;
+
+ for (i = 0; i < AN8855_NUM_PORTS; i++)
+ gsw->port_entries[i].pvid = map->pvids[i];
+
+ for (i = 0; i < AN8855_NUM_VLANS; i++) {
+ gsw->vlan_entries[i].member = map->members[i];
+ gsw->vlan_entries[i].etags = map->etags[i];
+ gsw->vlan_entries[i].vid = map->vids[i];
+ }
+}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h
new file mode 100644
index 0000000..d2cd68a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/airoha/an8855/an8855_vlan.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Airoha Inc.
+ */
+
+#ifndef _AN8855_VLAN_H_
+#define _AN8855_VLAN_H_
+
+#define AN8855_NUM_PORTS 6
+#define AN8855_NUM_VLANS 4095
+#define AN8855_MAX_VID 4095
+#define AN8855_MIN_VID 0
+
+struct gsw_an8855;
+
+struct an8855_port_entry {
+ u16 pvid;
+};
+
+struct an8855_vlan_entry {
+ u16 vid;
+ u8 member;
+ u8 etags;
+};
+
+struct an8855_mapping {
+ char *name;
+ u16 pvids[AN8855_NUM_PORTS];
+ u8 members[AN8855_NUM_VLANS];
+ u8 etags[AN8855_NUM_VLANS];
+ u16 vids[AN8855_NUM_VLANS];
+};
+
+extern struct an8855_mapping an8855_defaults[];
+
+void an8855_vlan_ctrl(struct gsw_an8855 *gsw, u32 cmd, u32 val);
+void an8855_apply_vlan_config(struct gsw_an8855 *gsw);
+struct an8855_mapping *an8855_find_mapping(struct device_node *np);
+void an8855_apply_mapping(struct gsw_an8855 *gsw, struct an8855_mapping *map);
+#endif /* _AN8855_VLAN_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/net/dsa/tag_arht.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/net/dsa/tag_arht.c
new file mode 100644
index 0000000..60ca986
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/net/dsa/tag_arht.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Airoha DSA Tag support
+ * Copyright (C) 2023 Min Yao <min.yao@airoha.com>
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+
+#include "dsa_priv.h"
+
+#define AIR_HDR_LEN 4
+#define AIR_HDR_XMIT_UNTAGGED 0
+#define AIR_HDR_XMIT_TAGGED_TPID_8100 1
+#define AIR_HDR_XMIT_TAGGED_TPID_88A8 2
+#define AIR_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0)
+#define AIR_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0)
+
+static struct sk_buff *air_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+ u8 xmit_tpid;
+ u8 *air_tag;
+ unsigned char *dest = eth_hdr(skb)->h_dest;
+
+ /* Build the special tag after the MAC Source Address. If VLAN header
+ * is present, it's required that VLAN header and special tag is
+ * being combined. Only in this way we can allow the switch can parse
+ * the both special and VLAN tag at the same time and then look up VLAN
+ * table with VID.
+ */
+ switch (skb->protocol) {
+ case htons(ETH_P_8021Q):
+ xmit_tpid = AIR_HDR_XMIT_TAGGED_TPID_8100;
+ break;
+ case htons(ETH_P_8021AD):
+ xmit_tpid = AIR_HDR_XMIT_TAGGED_TPID_88A8;
+ break;
+ default:
+ if (skb_cow_head(skb, AIR_HDR_LEN) < 0)
+ return NULL;
+
+ xmit_tpid = AIR_HDR_XMIT_UNTAGGED;
+ skb_push(skb, AIR_HDR_LEN);
+ memmove(skb->data, skb->data + AIR_HDR_LEN, 2 * ETH_ALEN);
+ }
+
+ air_tag = skb->data + 2 * ETH_ALEN;
+
+ /* Mark tag attribute on special tag insertion to notify hardware
+ * whether that's a combined special tag with 802.1Q header.
+ */
+ air_tag[0] = xmit_tpid;
+ air_tag[1] = (1 << dp->index) & AIR_HDR_XMIT_DP_BIT_MASK;
+
+ /* Tag control information is kept for 802.1Q */
+ if (xmit_tpid == AIR_HDR_XMIT_UNTAGGED) {
+ air_tag[2] = 0;
+ air_tag[3] = 0;
+ }
+
+ return skb;
+}
+
+static struct sk_buff *air_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+ int port;
+ __be16 *phdr, hdr;
+ unsigned char *dest = eth_hdr(skb)->h_dest;
+ bool is_multicast_skb = is_multicast_ether_addr(dest) &&
+ !is_broadcast_ether_addr(dest);
+
+ if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+ hdr = ntohs(skb->vlan_proto);
+ skb->vlan_proto = 0;
+ skb->vlan_tci = 0;
+ } else {
+ if (unlikely(!pskb_may_pull(skb, AIR_HDR_LEN)))
+ return NULL;
+
+ /* The AIR header is added by the switch between src addr
+ * and ethertype at this point, skb->data points to 2 bytes
+ * after src addr so header should be 2 bytes right before.
+ */
+ phdr = (__be16 *)(skb->data - 2);
+ hdr = ntohs(*phdr);
+
+ /* Remove AIR tag and recalculate checksum. */
+ skb_pull_rcsum(skb, AIR_HDR_LEN);
+
+ memmove(skb->data - ETH_HLEN,
+ skb->data - ETH_HLEN - AIR_HDR_LEN,
+ 2 * ETH_ALEN);
+ }
+
+ /* Get source port information */
+ port = (hdr & AIR_HDR_RECV_SOURCE_PORT_MASK);
+
+ skb->dev = dsa_master_find_slave(dev, 0, port);
+ if (!skb->dev)
+ return NULL;
+
+ /* Only unicast or broadcast frames are offloaded */
+ if (likely(!is_multicast_skb))
+ skb->offload_fwd_mark = 1;
+
+ return skb;
+}
+
+static int air_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+ int *offset)
+{
+ *offset = 4;
+ *proto = ((__be16 *)skb->data)[1];
+
+ return 0;
+}
+
+static const struct dsa_device_ops air_netdev_ops = {
+ .name = "air",
+ .proto = DSA_TAG_PROTO_ARHT,
+ .xmit = air_tag_xmit,
+ .rcv = air_tag_rcv,
+ .flow_dissect = air_tag_flow_dissect,
+ .overhead = AIR_HDR_LEN,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_AIR);
+
+module_dsa_tag_driver(air_netdev_ops);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
index 1ba25be..4a9bfae 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
@@ -1,14 +1,14 @@
-From b80c745d2b90b30558e4f5b12060af956ae8e76d Mon Sep 17 00:00:00 2001
+From 35623475d9eb8522756b0b4833c95a31a0ceb10b Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 18 Sep 2023 10:52:27 +0800
-Subject: [PATCH 02/22] mt7622 backport nf hw offload framework and upstream
+Subject: [PATCH 01/24] mt7622 backport nf hw offload framework and upstream
hnat plus xt-FLOWOFFLOAD update v2
---
drivers/net/ethernet/mediatek/Makefile | 3 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 25 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 19 +-
- drivers/net/ethernet/mediatek/mtk_ppe.c | 510 +++++++
+ drivers/net/ethernet/mediatek/mtk_ppe.c | 514 +++++++
drivers/net/ethernet/mediatek/mtk_ppe.h | 288 ++++
.../net/ethernet/mediatek/mtk_ppe_debugfs.c | 214 +++
.../net/ethernet/mediatek/mtk_ppe_offload.c | 535 ++++++++
@@ -46,7 +46,7 @@
net/netfilter/nf_flow_table_ip.c | 447 +++---
net/netfilter/nf_flow_table_offload.c | 1199 +++++++++++++++++
net/netfilter/xt_FLOWOFFLOAD.c | 800 +++++++++++
- 41 files changed, 4995 insertions(+), 435 deletions(-)
+ 41 files changed, 4999 insertions(+), 435 deletions(-)
mode change 100644 => 100755 drivers/net/ethernet/mediatek/Makefile
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.c
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -76,10 +76,10 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
old mode 100644
new mode 100755
-index c4bea4d..9c85e16
+index 37fd338..20b2943
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -3573,6 +3573,7 @@ static int mtk_open(struct net_device *dev)
+@@ -4001,6 +4001,7 @@ static int mtk_open(struct net_device *dev)
u32 id = mtk_mac2xgmii_id(eth, mac->id);
int err, i;
struct device_node *phy_node;
@@ -87,7 +87,7 @@
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
if (err) {
-@@ -3650,7 +3651,10 @@ static int mtk_open(struct net_device *dev)
+@@ -4085,7 +4086,10 @@ static int mtk_open(struct net_device *dev)
regmap_write(eth->sgmii->pcs[id].regmap,
SGMSYS_QPHY_PWR_STATE_CTRL, 0);
@@ -99,7 +99,7 @@
return 0;
}
-@@ -3730,6 +3734,9 @@ static int mtk_stop(struct net_device *dev)
+@@ -4172,6 +4176,9 @@ static int mtk_stop(struct net_device *dev)
mtk_dma_free(eth);
@@ -109,7 +109,7 @@
return 0;
}
-@@ -4576,6 +4583,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+@@ -5081,6 +5088,7 @@ static const struct net_device_ops mtk_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mtk_poll_controller,
#endif
@@ -117,7 +117,7 @@
};
static void mux_poll(struct work_struct *work)
-@@ -5161,6 +5169,17 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5711,6 +5719,17 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
@@ -135,7 +135,7 @@
for (i = 0; i < MTK_MAX_DEVS; i++) {
if (!eth->netdev[i])
continue;
-@@ -5254,6 +5273,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5811,6 +5830,7 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -143,7 +143,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5271,6 +5291,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5828,6 +5848,7 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -151,7 +151,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5289,6 +5310,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5846,6 +5867,7 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -159,7 +159,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5306,6 +5328,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5863,6 +5885,7 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -170,7 +170,7 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
old mode 100644
new mode 100755
-index 8a9b615..a87e46d
+index 26a99d1..4d3a63c
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -15,6 +15,8 @@
@@ -182,7 +182,7 @@
#define MTK_QDMA_PAGE_SIZE 2048
#define MTK_MAX_RX_LENGTH 1536
-@@ -44,7 +46,8 @@
+@@ -47,7 +49,8 @@
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_SG | NETIF_F_TSO | \
NETIF_F_TSO6 | \
@@ -192,7 +192,7 @@
#define MTK_SET_FEATURES (NETIF_F_LRO | \
NETIF_F_HW_VLAN_CTAG_RX)
#define MTK_HW_FEATURES_MT7628 (NETIF_F_SG | NETIF_F_RXCSUM)
-@@ -127,6 +130,7 @@
+@@ -134,6 +137,7 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -200,7 +200,7 @@
#define MTK_GDMA_DROP_ALL 0x7777
/* GDM Egress Control Register */
-@@ -617,6 +621,12 @@
+@@ -661,6 +665,12 @@
#define RX_DMA_TCI(_x) ((_x) & (VLAN_PRIO_MASK | VLAN_VID_MASK))
#define RX_DMA_VPID(_x) (((_x) >> 16) & 0xffff)
@@ -213,7 +213,7 @@
/* QDMA descriptor rxd4 */
#define RX_DMA_L4_VALID BIT(24)
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
-@@ -1651,6 +1661,7 @@ struct mtk_soc_data {
+@@ -1712,6 +1722,7 @@ struct mtk_soc_data {
u64 caps;
u64 required_clks;
bool required_pctl;
@@ -221,7 +221,7 @@
netdev_features_t hw_features;
bool has_sram;
struct {
-@@ -1847,6 +1858,9 @@ struct mtk_eth {
+@@ -1912,6 +1923,9 @@ struct mtk_eth {
int ip_align;
spinlock_t syscfg0_lock;
struct timer_list mtk_dma_monitor_timer;
@@ -231,7 +231,7 @@
};
/* struct mtk_mac - the structure that holds the info about the MACs of the
-@@ -1927,6 +1941,9 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+@@ -1993,6 +2007,9 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
void mtk_usxgmii_link_poll(struct work_struct *work);
@@ -243,7 +243,7 @@
#endif /* MTK_ETH_H */
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
new file mode 100644
-index 0000000..27b5be5
+index 0000000..6965d98
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -0,0 +1,514 @@
@@ -1967,10 +1967,10 @@
+
+#endif
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
-index 078c0f4..f8a98d8 100644
+index 555ba50..25dcff2 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
-@@ -1378,12 +1378,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
+@@ -1380,12 +1380,34 @@ static void ppp_dev_priv_destructor(struct net_device *dev)
ppp_destroy_interface(ppp);
}
@@ -2043,10 +2043,10 @@
static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index 631d158..ef44d9a 100644
+index 1c1ab37..44842a2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
-@@ -838,6 +838,59 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+@@ -843,6 +843,59 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
struct sk_buff *skb,
struct net_device *sb_dev);
@@ -2106,7 +2106,7 @@
enum tc_setup_type {
TC_SETUP_QDISC_MQPRIO,
TC_SETUP_CLSU32,
-@@ -853,6 +906,7 @@ enum tc_setup_type {
+@@ -858,6 +911,7 @@ enum tc_setup_type {
TC_SETUP_ROOT_QDISC,
TC_SETUP_QDISC_GRED,
TC_SETUP_QDISC_TAPRIO,
@@ -2114,7 +2114,7 @@
};
/* These structures hold the attributes of bpf state that are being passed
-@@ -1248,6 +1302,8 @@ struct tlsdev_ops;
+@@ -1253,6 +1307,8 @@ struct tlsdev_ops;
* Get devlink port instance associated with a given netdev.
* Called with a reference on the netdevice and devlink locks only,
* rtnl_lock is not held.
@@ -2123,7 +2123,7 @@
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
-@@ -1445,6 +1501,8 @@ struct net_device_ops {
+@@ -1450,6 +1506,8 @@ struct net_device_ops {
int (*ndo_xsk_wakeup)(struct net_device *dev,
u32 queue_id, u32 flags);
struct devlink_port * (*ndo_get_devlink_port)(struct net_device *dev);
@@ -2132,7 +2132,7 @@
};
/**
-@@ -2670,6 +2728,8 @@ void dev_remove_offload(struct packet_offload *po);
+@@ -2689,6 +2747,8 @@ void dev_remove_offload(struct packet_offload *po);
int dev_get_iflink(const struct net_device *dev);
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
@@ -2210,7 +2210,7 @@
-
#endif /* _NF_CONNTRACK_IPV6_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
-index 90690e3..ce0bc3e 100644
+index 90690e3..38a8d3f 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -105,6 +105,8 @@ struct nf_conn {
@@ -2222,7 +2222,7 @@
};
static inline struct nf_conn *
-@@ -279,6 +279,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
+@@ -279,6 +281,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
!nf_ct_is_dying(ct);
}
@@ -2264,7 +2264,7 @@
int nf_conntrack_acct_init(void);
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index 68d7fc9..feac793 100644
+index 68d7fc9..7374cb2 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -8,31 +8,101 @@
@@ -2370,7 +2370,7 @@
struct flow_offload_tuple {
union {
-@@ -52,13 +120,30 @@ struct flow_offload_tuple {
+@@ -52,13 +122,30 @@ struct flow_offload_tuple {
u8 l3proto;
u8 l4proto;
@@ -2406,7 +2406,7 @@
};
};
-@@ -67,52 +152,140 @@ struct flow_offload_tuple_rhash {
+@@ -67,52 +154,140 @@ struct flow_offload_tuple_rhash {
struct flow_offload_tuple tuple;
};
@@ -2569,7 +2569,7 @@
struct flow_ports {
__be16 source, dest;
-@@ -126,4 +299,41 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+@@ -126,4 +301,41 @@ unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
#define MODULE_ALIAS_NF_FLOWTABLE(family) \
MODULE_ALIAS("nf-flowtable-" __stringify(family))
@@ -2685,10 +2685,10 @@
+
+#endif /* _XT_FLOWOFFLOAD_H */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
-index 0a3a167..6112266 100644
+index dd7e09e..c373f1d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
-@@ -747,6 +747,26 @@ static int vlan_dev_get_iflink(const struct net_device *dev)
+@@ -771,6 +771,26 @@ static int vlan_dev_get_iflink(const struct net_device *dev)
return real_dev->ifindex;
}
@@ -2715,7 +2715,7 @@
static const struct ethtool_ops vlan_ethtool_ops = {
.get_link_ksettings = vlan_ethtool_get_link_ksettings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
-@@ -785,6 +805,7 @@ static const struct net_device_ops vlan_netdev_ops = {
+@@ -809,6 +829,7 @@ static const struct net_device_ops vlan_netdev_ops = {
#endif
.ndo_fix_features = vlan_dev_fix_features,
.ndo_get_iflink = vlan_dev_get_iflink,
@@ -2724,10 +2724,10 @@
static void vlan_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
-index 501f77f..0940b44 100644
+index ab201d5..deec45b 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
-@@ -377,6 +377,54 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
+@@ -385,6 +385,54 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
return br_del_if(br, slave_dev);
}
@@ -2782,7 +2782,7 @@
static const struct ethtool_ops br_ethtool_ops = {
.get_drvinfo = br_getinfo,
.get_link = ethtool_op_get_link,
-@@ -410,6 +458,7 @@ static const struct net_device_ops br_netdev_ops = {
+@@ -418,6 +466,7 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_bridge_setlink = br_setlink,
.ndo_bridge_dellink = br_dellink,
.ndo_features_check = passthru_features_check,
@@ -2895,10 +2895,10 @@
struct bridge_vlan_info *p_vinfo)
{
diff --git a/net/core/dev.c b/net/core/dev.c
-index 54cc544..a117bd0 100644
+index ef7362b..5bade26 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
-@@ -639,6 +639,52 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+@@ -722,6 +722,52 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
@@ -2952,7 +2952,7 @@
* __dev_get_by_name - find a device by its name
* @net: the applicable net namespace
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
-index e2b91b3..2dfaa1e 100644
+index cd5b354..2ea9ec1 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1031,14 +1031,32 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
@@ -3042,7 +3042,7 @@
tristate "Netfilter IPv4 packet duplication to alternate destination"
depends on !NF_CONNTRACK || NF_CONNTRACK
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 8231a7a..7176d7f 100644
+index 816275b..671f767 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -607,7 +607,7 @@ int ip6_forward(struct sk_buff *skb)
@@ -3181,7 +3181,7 @@
obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
-index f6ab6f4..f689e19 100644
+index 706d180..65d16ef 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -864,9 +864,8 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
@@ -6086,7 +6086,7 @@
+}
diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
new file mode 100644
-index 0000000..2cab008
+index 0000000..e4c7db9
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -0,0 +1,800 @@
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-dts-netsys2-wed-changes.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-dts-netsys2-wed-changes.patch
index eacae85..213c69e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-dts-netsys2-wed-changes.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3002-dts-netsys2-wed-changes.patch
@@ -1,19 +1,37 @@
-From be48305fd2e3ecd9a9853f2ae11fb9432e40b299 Mon Sep 17 00:00:00 2001
+From f99c7b63e766c2ff8851a8ba6ff77f3d8bfef0d5 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 18 Sep 2023 10:55:08 +0800
-Subject: [PATCH 03/22] dts mt7986 wed changes
+Subject: [PATCH 02/24] dts netsys2 wed changes
---
- arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 33 ++++++++---------------
- arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 33 ++++++++---------------
- 2 files changed, 22 insertions(+), 44 deletions(-)
+ .../boot/dts/mediatek/mt7981-spim-nor-rfb.dts | 8 -----
+ arch/arm64/boot/dts/mediatek/mt7981.dtsi | 21 ++++--------
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 33 +++++++------------
+ arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 33 +++++++------------
+ 4 files changed, 28 insertions(+), 67 deletions(-)
-diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index e43c306..e5d4e12 100644
---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-@@ -58,32 +58,20 @@
- };
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
+index 3fa55a0..f5c70a4 100755
+--- a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
+@@ -211,11 +211,3 @@
+ &xhci {
+ status = "okay";
+ };
+-
+-&wed {
+- dy_txbm_enable = "true";
+- dy_txbm_budget = <8>;
+- txbm_init_sz = <8>;
+- txbm_max_sz = <32>;
+- status = "okay";
+-};
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+index 91415e4..283421a 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+@@ -90,22 +90,12 @@
+ #io-channel-cells = <1>;
};
- wed: wed@15010000 {
@@ -24,49 +42,34 @@
- reg = <0 0x15010000 0 0x1000>,
- <0 0x15011000 0 0x1000>;
+ wed0: wed@15010000 {
-+ compatible = "mediatek,mt7986-wed",
++ compatible = "mediatek,mt7981-wed",
+ "syscon";
+ reg = <0 0x15010000 0 0x1000>;
interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- };
-
-- wed2: wed2@15011000 {
-- compatible = "mediatek,wed2";
-- wed_num = <2>;
-- reg = <0 0x15010000 0 0x1000>,
-- <0 0x15011000 0 0x1000>;
-+ wed1: wed@15011000 {
-+ compatible = "mediatek,mt7986-wed",
-+ "syscon";
-+ reg = <0 0x15011000 0 0x1000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- wdma: wdma@15104800 {
- compatible = "mediatek,wed-wdma";
- reg = <0 0x15104800 0 0x400>,
- <0 0x15104c00 0 0x400>;
-+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
};
ap2woccif: ap2woccif@151A5000 {
-@@ -507,6 +495,7 @@
- <&topckgen CK_TOP_CB_SGM_325M>;
+@@ -423,6 +413,7 @@
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
-+ mediatek,wed = <&wed0>, <&wed1>;
+ mediatek,infracfg = <&topmisc>;
++ mediatek,wed = <&wed0>;
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index 21d8357..2d2207f 100644
---- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+index 2c7e171..3a4f279 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -58,32 +58,20 @@
};
};
@@ -110,7 +113,7 @@
};
ap2woccif: ap2woccif@151A5000 {
-@@ -409,6 +397,7 @@
+@@ -494,6 +482,7 @@
<&topckgen CK_TOP_CB_SGM_325M>;
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
@@ -118,12 +121,12 @@
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index ccaf0ad0..b2f53b13 100644
---- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-@@ -90,22 +90,12 @@
- #io-channel-cells = <1>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+index 26f093b..ce884f0 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+@@ -58,32 +58,20 @@
+ };
};
- wed: wed@15010000 {
@@ -134,46 +137,45 @@
- reg = <0 0x15010000 0 0x1000>,
- <0 0x15011000 0 0x1000>;
+ wed0: wed@15010000 {
-+ compatible = "mediatek,mt7981-wed",
++ compatible = "mediatek,mt7986-wed",
+ "syscon";
+ reg = <0 0x15010000 0 0x1000>;
interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+- wed2: wed2@15011000 {
+- compatible = "mediatek,wed2";
+- wed_num = <2>;
+- reg = <0 0x15010000 0 0x1000>,
+- <0 0x15011000 0 0x1000>;
++ wed1: wed@15011000 {
++ compatible = "mediatek,mt7986-wed",
++ "syscon";
++ reg = <0 0x15011000 0 0x1000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- wdma: wdma@15104800 {
- compatible = "mediatek,wed-wdma";
- reg = <0 0x15104800 0 0x400>,
- <0 0x15104c00 0 0x400>;
-+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
};
ap2woccif: ap2woccif@151A5000 {
-@@ -423,6 +413,7 @@
+@@ -408,6 +396,7 @@
+ <&topckgen CK_TOP_CB_SGM_325M>;
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
- mediatek,infracfg = <&topmisc>;
-+ mediatek,wed = <&wed0>;
++ mediatek,wed = <&wed0>, <&wed1>;
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-index 3fa55a07..f5c70a4e 100755
---- a/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
-@@ -211,11 +211,3 @@
- &xhci {
- status = "okay";
- };
--
--&wed {
-- dy_txbm_enable = "true";
-- dy_txbm_budget = <8>;
-- txbm_init_sz = <8>;
-- txbm_max_sz = <32>;
-- status = "okay";
--};
--
2.18.0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
index 16c04b5..a60b6ce 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3003-add-wed.patch
@@ -1,7 +1,7 @@
-From cdb36beeb6725bcef3faad499c017c26bc17fd4a Mon Sep 17 00:00:00 2001
+From b895d23fa63dd712191b6d223fe6c41682c7d375 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 10:56:21 +0800
-Subject: [PATCH 04/22] add wed
+Subject: [PATCH 03/24] add wed
---
arch/arm64/boot/dts/mediatek/mt7622.dtsi | 32 +-
@@ -13,7 +13,7 @@
drivers/net/ethernet/mediatek/mtk_ppe.h | 89 +-
.../net/ethernet/mediatek/mtk_ppe_debugfs.c | 4 +-
.../net/ethernet/mediatek/mtk_ppe_offload.c | 167 +++-
- drivers/net/ethernet/mediatek/mtk_wed.c | 876 ++++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed.c | 881 ++++++++++++++++++
drivers/net/ethernet/mediatek/mtk_wed.h | 135 +++
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 175 ++++
drivers/net/ethernet/mediatek/mtk_wed_ops.c | 8 +
@@ -21,7 +21,7 @@
include/linux/netdevice.h | 7 +
include/linux/soc/mediatek/mtk_wed.h | 131 +++
net/core/dev.c | 4 +
- 17 files changed, 2207 insertions(+), 103 deletions(-)
+ 17 files changed, 2212 insertions(+), 103 deletions(-)
mode change 100755 => 100644 drivers/net/ethernet/mediatek/Kconfig
mode change 100755 => 100644 drivers/net/ethernet/mediatek/Makefile
mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -134,7 +134,7 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
old mode 100755
new mode 100644
-index 9c85e16..88b38e2
+index 20b2943..8d15399
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -21,11 +21,13 @@
@@ -151,7 +151,7 @@
#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
#include "mtk_hnat/nf_hnat_mtk.h"
-@@ -2191,6 +2193,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2356,6 +2358,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
struct net_device *netdev = NULL;
dma_addr_t dma_addr = DMA_MAPPING_ERROR;
u64 addr64 = 0;
@@ -159,7 +159,7 @@
int mac = 0;
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
-@@ -2282,6 +2285,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2444,6 +2447,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
@@ -177,7 +177,7 @@
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
if (trxd.rxd3 & RX_DMA_VTAG_V2)
-@@ -3735,7 +3749,7 @@ static int mtk_stop(struct net_device *dev)
+@@ -4177,7 +4191,7 @@ static int mtk_stop(struct net_device *dev)
mtk_dma_free(eth);
if (eth->soc->offload_version)
@@ -186,7 +186,7 @@
return 0;
}
-@@ -5044,6 +5058,22 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5560,6 +5574,22 @@ static int mtk_probe(struct platform_device *pdev)
}
}
@@ -208,8 +208,8 @@
+
if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
-
-@@ -5170,10 +5200,11 @@ static int mtk_probe(struct platform_device *pdev)
+ eth->irq_pdma[i] = platform_get_irq(pdev, i);
+@@ -5720,10 +5750,11 @@ static int mtk_probe(struct platform_device *pdev)
}
if (eth->soc->offload_version) {
@@ -227,10 +227,10 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
old mode 100755
new mode 100644
-index a87e46d..15337d3
+index 4d3a63c..00cfe3b
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -578,6 +578,9 @@
+@@ -615,6 +615,9 @@
#define RX_DMA_SPORT_MASK 0x7
#define RX_DMA_SPORT_MASK_V2 0xf
@@ -240,7 +240,7 @@
/* QDMA descriptor txd4 */
#define TX_DMA_CHKSUM (0x7 << 29)
#define TX_DMA_TSO BIT(28)
-@@ -1859,7 +1862,7 @@ struct mtk_eth {
+@@ -1924,7 +1927,7 @@ struct mtk_eth {
spinlock_t syscfg0_lock;
struct timer_list mtk_dma_monitor_timer;
@@ -252,7 +252,7 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
old mode 100644
new mode 100755
-index 27b5be5..86741bf
+index 6965d98..eeaec1b
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -6,9 +6,22 @@
@@ -1262,10 +1262,10 @@
return rhashtable_init(ð->flow_table, &mtk_flow_ht_params);
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
new file mode 100644
-index 0000000..ea1cbdf
+index 0000000..affa704
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -0,0 +1,876 @@
+@@ -0,0 +1,881 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
+
@@ -1413,16 +1413,17 @@
+
+ for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
+ u32 txd_size;
++ u32 ctrl;
+
+ txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
+
-+ desc->buf0 = buf_phys;
-+ desc->buf1 = buf_phys + txd_size;
-+ desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
-+ txd_size) |
-+ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
-+ MTK_WED_BUF_SIZE - txd_size) |
-+ MTK_WDMA_DESC_CTRL_LAST_SEG1;
++ desc->buf0 = cpu_to_le32(buf_phys);
++ desc->buf1 = cpu_to_le32(buf_phys + txd_size);
++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++ MTK_WED_BUF_SIZE - txd_size) |
++ MTK_WDMA_DESC_CTRL_LAST_SEG1;
++ desc->ctrl = cpu_to_le32(ctrl);
+ desc->info = 0;
+ desc++;
+
@@ -1453,12 +1454,14 @@
+
+ for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
+ void *page = page_list[page_idx++];
++ dma_addr_t buf_addr;
+
+ if (!page)
+ break;
+
-+ dma_unmap_page(dev->hw->dev, desc[i].buf0,
-+ PAGE_SIZE, DMA_BIDIRECTIONAL);
++ buf_addr = le32_to_cpu(desc[i].buf0);
++ dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++ DMA_BIDIRECTIONAL);
+ __free_page(page);
+ }
+
@@ -1917,7 +1920,7 @@
+ * WDMA RX.
+ */
+
-+ BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
++ BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
+
+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE))
+ return -ENOMEM;
@@ -2082,7 +2085,7 @@
+ return;
+
+ regs = syscon_regmap_lookup_by_phandle(np, NULL);
-+ if (!regs)
++ if (IS_ERR(regs))
+ return;
+
+ rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops);
@@ -2093,6 +2096,8 @@
+ goto unlock;
+
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
++ if (!hw)
++ goto unlock;
+ hw->node = np;
+ hw->regs = regs;
+ hw->eth = eth;
@@ -2736,10 +2741,10 @@
+
+#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index ef44d9a..59a3e96 100644
+index 44842a2..5305384 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
-@@ -844,6 +844,7 @@ enum net_device_path_type {
+@@ -849,6 +849,7 @@ enum net_device_path_type {
DEV_PATH_BRIDGE,
DEV_PATH_PPPOE,
DEV_PATH_DSA,
@@ -2747,7 +2752,7 @@
};
struct net_device_path {
-@@ -869,6 +870,12 @@ struct net_device_path {
+@@ -874,6 +875,12 @@ struct net_device_path {
int port;
u16 proto;
} dsa;
@@ -2898,10 +2903,10 @@
+
+#endif
diff --git a/net/core/dev.c b/net/core/dev.c
-index a117bd0..1b6d42b 100644
+index 5bade26..0775e8d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
-@@ -675,6 +675,10 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+@@ -758,6 +758,10 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
if (WARN_ON_ONCE(last_dev == ctx.dev))
return -1;
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
index d613ce8..9f22f37 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3004-ethernet-update-ppe-from-netsys1-to-netsys2.patch
@@ -1,51 +1,50 @@
-From 3562f05aedc6c2d793b34b3ee3eb78e8352804c8 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Mon, 18 Sep 2023 10:58:32 +0800
-Subject: [PATCH 05/22] ethernet update ppe from mt7622 to mt7986
+From 07a3ac0ae724c4df67316e01b03432d8ee9f4229 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Mon, 18 Mar 2024 17:56:01 +0800
+Subject: [PATCH 04/24] ethernet update ppe from netsys1 to netsys2
---
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 ++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++-
drivers/net/ethernet/mediatek/mtk_ppe.c | 29 +++++++++--
drivers/net/ethernet/mediatek/mtk_ppe.h | 51 +++++++++++++++++++
.../net/ethernet/mediatek/mtk_ppe_offload.c | 8 +++
drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 10 ++++
- 6 files changed, 113 insertions(+), 6 deletions(-)
+ 6 files changed, 112 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 88b38e2..bfda873 100644
+index ffaa515..9262227 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2285,16 +2285,27 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2447,16 +2447,20 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
-- hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
-+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2;
-+#else
-+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
-+#endif
- if (hash != MTK_RXD4_FOE_ENTRY) {
- hash = jhash_1word(hash, 0);
- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);
- }
-
-+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
++ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2;
+ reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
-+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
-+ mtk_ppe_check_skb(eth->ppe, skb,
-+ trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2);
++ if (hash != MTK_RXD5_FOE_ENTRY_V2)
++ skb_set_hash(skb, jhash_1word(hash, 0), PKT_HASH_TYPE_L4);
+#else
+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
+- if (hash != MTK_RXD4_FOE_ENTRY) {
+- hash = jhash_1word(hash, 0);
+- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);
+- }
+-
reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4);
- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
- mtk_ppe_check_skb(eth->ppe, skb,
- trxd.rxd4 & MTK_RXD4_FOE_ENTRY);
++ if (hash != MTK_RXD4_FOE_ENTRY)
++ skb_set_hash(skb, jhash_1word(hash, 0), PKT_HASH_TYPE_L4);
+#endif
++
+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
+- mtk_ppe_check_skb(eth->ppe, skb,
+- trxd.rxd4 & MTK_RXD4_FOE_ENTRY);
++ mtk_ppe_check_skb(eth->ppe, skb, hash);
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
-@@ -5396,6 +5407,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -5957,6 +5961,7 @@ static const struct mtk_soc_data mt7986_data = {
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -54,10 +53,10 @@
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma_v2),
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 15337d3..a385df5 100644
+index 41daeb2..910baaf 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -130,7 +130,7 @@
+@@ -137,7 +137,7 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -66,7 +65,7 @@
#define MTK_GDMA_DROP_ALL 0x7777
/* GDM Egress Control Register */
-@@ -630,6 +630,11 @@
+@@ -680,6 +680,11 @@
#define MTK_RXD4_SRC_PORT GENMASK(21, 19)
#define MTK_RXD4_ALG GENMASK(31, 22)
@@ -79,7 +78,7 @@
#define RX_DMA_L4_VALID BIT(24)
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 86741bf..ef8acbc 100755
+index eeaec1b..e195fb3 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -122,7 +122,7 @@ static u32 mtk_ppe_hash_entry(struct mtk_foe_entry *e)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
index 8d605e0..5ff363b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3005-flow-offload-add-mkhnat-dual-ppe-new-v2.patch
@@ -1,25 +1,25 @@
-From 806bb7d1a0a44a92101c506564a41dc6c4b68fd0 Mon Sep 17 00:00:00 2001
+From 01556d88ad11f0d096d2816b2a69999994e1740f Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Tue, 26 Dec 2023 16:31:34 +0800
-Subject: [PATCH 06/22] flow-offload-add-mkhnat-dual-ppe-new-v2
+Date: Mon, 18 Mar 2024 16:26:28 +0800
+Subject: [PATCH 05/24] flow-offload-add-mkhnat-dual-ppe-new-v2
---
arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 1 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 58 ++++++++++++++-----
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 14 ++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 50 ++++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 14 ++++--
drivers/net/ethernet/mediatek/mtk_ppe.c | 5 +-
drivers/net/ethernet/mediatek/mtk_ppe.h | 7 ++-
- .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 27 ++++++---
- .../net/ethernet/mediatek/mtk_ppe_offload.c | 48 +++++++++++----
+ .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 27 +++++++---
+ .../net/ethernet/mediatek/mtk_ppe_offload.c | 48 ++++++++++++++----
include/linux/netdevice.h | 4 ++
- 8 files changed, 124 insertions(+), 40 deletions(-)
+ 8 files changed, 119 insertions(+), 37 deletions(-)
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_ppe_offload.c
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index e5d4e12..0c54e12 100644
+index 3a4f279..d70151b 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-@@ -496,6 +496,7 @@
+@@ -483,6 +483,7 @@
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
mediatek,wed = <&wed0>, <&wed1>;
@@ -28,31 +28,19 @@
#address-cells = <1>;
#size-cells = <0>;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index bfda873..ee5e0c6 100644
+index 2fb67e0..7eeddb3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2276,14 +2276,16 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
-
- #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
- reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
-- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
-- mtk_ppe_check_skb(eth->ppe, skb,
-+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
-+ mtk_ppe_check_skb(eth->ppe[0], skb,
- trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2);
-+ }
- #else
- reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4);
-- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
-- mtk_ppe_check_skb(eth->ppe, skb,
-+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
-+ mtk_ppe_check_skb(eth->ppe[0], skb,
- trxd.rxd4 & MTK_RXD4_FOE_ENTRY);
-+ }
+@@ -2464,7 +2464,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
#endif
+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
+- mtk_ppe_check_skb(eth->ppe, skb, hash);
++ mtk_ppe_check_skb(eth->ppe[0], skb, hash);
+
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
-@@ -3676,8 +3683,12 @@ static int mtk_open(struct net_device *dev)
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
+@@ -4112,8 +4112,12 @@ static int mtk_open(struct net_device *dev)
regmap_write(eth->sgmii->pcs[id].regmap,
SGMSYS_QPHY_PWR_STATE_CTRL, 0);
@@ -67,7 +55,7 @@
mtk_gdm_config(eth, mac->id, gdm_config);
-@@ -3759,8 +3770,10 @@ static int mtk_stop(struct net_device *dev)
+@@ -4202,8 +4206,10 @@ static int mtk_stop(struct net_device *dev)
mtk_dma_free(eth);
@@ -80,7 +68,7 @@
return 0;
}
-@@ -5211,15 +5224,35 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5762,15 +5768,35 @@ static int mtk_probe(struct platform_device *pdev)
}
if (eth->soc->offload_version) {
@@ -124,10 +112,10 @@
for (i = 0; i < MTK_MAX_DEVS; i++) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index a385df5..783166d 100644
+index 910baaf..3995608 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -130,7 +130,12 @@
+@@ -137,7 +137,12 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -141,7 +129,7 @@
#define MTK_GDMA_DROP_ALL 0x7777
/* GDM Egress Control Register */
-@@ -1867,7 +1872,8 @@ struct mtk_eth {
+@@ -1936,7 +1941,8 @@ struct mtk_eth {
spinlock_t syscfg0_lock;
struct timer_list mtk_dma_monitor_timer;
@@ -151,7 +139,7 @@
struct rhashtable flow_table;
};
-@@ -1949,9 +1955,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
+@@ -2019,9 +2025,11 @@ int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r);
int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range);
void mtk_usxgmii_link_poll(struct work_struct *work);
@@ -165,7 +153,7 @@
+int mtk_ppe_debugfs_init(struct mtk_eth *eth);
#endif /* MTK_ETH_H */
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index ef8acbc..96c15b3 100755
+index e195fb3..c9ee505 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -696,7 +696,7 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
@@ -449,10 +437,10 @@
return rhashtable_init(ð->flow_table, &mtk_flow_ht_params);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index 59a3e96..0967dc2 100644
+index 5305384..b2abebe 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
-@@ -1311,6 +1311,8 @@ struct tlsdev_ops;
+@@ -1316,6 +1316,8 @@ struct tlsdev_ops;
* rtnl_lock is not held.
* int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);
* Get the forwarding path to reach the real device from the HW destination address
@@ -461,7 +449,7 @@
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
-@@ -1510,6 +1512,8 @@ struct net_device_ops {
+@@ -1515,6 +1517,8 @@ struct net_device_ops {
struct devlink_port * (*ndo_get_devlink_port)(struct net_device *dev);
int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
struct net_device_path *path);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
index 5cfedfc..5197d21 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
@@ -1,23 +1,23 @@
-From d76914437a405265b298b7b01235a7304634c567 Mon Sep 17 00:00:00 2001
+From 56e9bf306919ffb33d45951541d908cd7d21c081 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 18 Sep 2023 11:01:55 +0800
-Subject: [PATCH] add-wed-tx-support-for-mt7986
+Subject: [PATCH 06/24] add-wed-tx-support-for-netsys2
---
arch/arm64/boot/dts/mediatek/mt7981.dtsi | 1 +
- arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 2 +
- arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 2 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +
- drivers/net/ethernet/mediatek/mtk_wed.c | 498 +++++++++++++-----
- drivers/net/ethernet/mediatek/mtk_wed.h | 18 +-
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 6 +-
+ arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 6 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 41 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 -
+ drivers/net/ethernet/mediatek/mtk_wed.c | 525 +++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed.h | 21 +-
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 3 +
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 130 ++++-
- include/linux/soc/mediatek/mtk_wed.h | 23 +
- 10 files changed, 549 insertions(+), 150 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 111 +++-
+ include/linux/soc/mediatek/mtk_wed.h | 21 +-
+ 10 files changed, 575 insertions(+), 163 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index e1b9b2c..3e0d2c0 100644
+index 283421a..cb8f4e1 100644
--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
@@ -96,6 +96,7 @@
@@ -29,7 +29,7 @@
ap2woccif: ap2woccif@151A5000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index 7e3101c..e9756bd 100644
+index d70151b..9c288fc 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -64,6 +64,7 @@
@@ -48,8 +48,26 @@
};
ap2woccif: ap2woccif@151A5000 {
+@@ -482,6 +484,7 @@
+ <&topckgen CK_TOP_CB_SGM_325M>;
+ mediatek,ethsys = <ðsys>;
+ mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++ mediatek,wed-pcie = <&wed_pcie>;
+ mediatek,wed = <&wed0>, <&wed1>;
+ mtketh-ppe-num = <2>;
+ #reset-cells = <1>;
+@@ -549,7 +552,8 @@
+ };
+
+ wed_pcie: wed_pcie@10003000 {
+- compatible = "mediatek,wed_pcie";
++ compatible = "mediatek,wed_pcie",
++ "syscon";
+ reg = <0 0x10003000 0 0x10>;
+ };
+
diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index a780cfb..eafe314 100644
+index ce884f0..02feaa9 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -64,6 +64,7 @@
@@ -68,11 +86,29 @@
};
ap2woccif: ap2woccif@151A5000 {
+@@ -396,6 +398,7 @@
+ <&topckgen CK_TOP_CB_SGM_325M>;
+ mediatek,ethsys = <ðsys>;
+ mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++ mediatek,wed-pcie = <&wed_pcie>;
+ mediatek,wed = <&wed0>, <&wed1>;
+ #reset-cells = <1>;
+ #address-cells = <1>;
+@@ -462,7 +465,8 @@
+ };
+
+ wed_pcie: wed_pcie@10003000 {
+- compatible = "mediatek,wed_pcie";
++ compatible = "mediatek,wed_pcie",
++ "syscon";
+ reg = <0 0x10003000 0 0x10>;
+ };
+
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 3685926..51fe4b3 100644
+index 07209f0..268c9e7 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5091,6 +5091,7 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5476,6 +5476,7 @@ static int mtk_probe(struct platform_device *pdev)
{
struct device_node *mac_np, *mux_np;
struct mtk_eth *eth;
@@ -80,8 +116,8 @@
int err, i;
eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL);
-@@ -5111,13 +5112,12 @@ static int mtk_probe(struct platform_device *pdev)
- return PTR_ERR(eth->sram_base);
+@@ -5498,13 +5499,12 @@ static int mtk_probe(struct platform_device *pdev)
+ eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET;
}
- if(eth->soc->has_sram) {
@@ -93,49 +129,66 @@
+ if (unlikely(!res))
+ return -EINVAL;
+
-+ if(eth->soc->has_sram)
++ if (eth->soc->has_sram)
eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET;
- }
mtk_get_hwver(eth);
+@@ -5593,20 +5593,25 @@ static int mtk_probe(struct platform_device *pdev)
+ }
+ }
+
-@@ -5213,12 +5213,15 @@ static int mtk_probe(struct platform_device *pdev)
- MTK_WDMA1_BASE
- };
- void __iomem *wdma;
-+ u32 wdma_phy;
+- for (i = 0;; i++) {
+- struct device_node *np = of_parse_phandle(pdev->dev.of_node,
+- "mediatek,wed", i);
+- static const u32 wdma_regs[] = {
+- MTK_WDMA0_BASE,
+- MTK_WDMA1_BASE
+- };
+- void __iomem *wdma;
++ if (eth->soc->offload_version) {
++ for (i = 0;; i++) {
++ struct device_node *np;
++ phys_addr_t wdma_phy;
++ u32 wdma_base;
- if (!np || i >= ARRAY_SIZE(wdma_regs))
- break;
+- if (!np || i >= ARRAY_SIZE(wdma_regs))
+- break;
++ if (i >= ARRAY_SIZE(eth->soc->reg_map->wdma_base))
++ break;
- wdma = eth->base + wdma_regs[i];
+- wdma = eth->base + wdma_regs[i];
- mtk_wed_add_hw(np, eth, wdma, i);
-+ wdma_phy = res->start + wdma_regs[i];
++ np = of_parse_phandle(pdev->dev.of_node,
++ "mediatek,wed", i);
++ if (!np)
++ break;
+
-+ mtk_wed_add_hw(np, eth, wdma, wdma_phy, i);
++ wdma_base = eth->soc->reg_map->wdma_base[i];
++ wdma_phy = res ? res->start + wdma_base : 0;
++ mtk_wed_add_hw(np, eth, eth->base + wdma_base,
++ wdma_phy, i);
++ }
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index b714c27..e9d88f1 100644
+index a00583f..9099dea 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -593,8 +593,13 @@
+@@ -620,9 +620,6 @@
#define RX_DMA_SPORT_MASK 0x7
#define RX_DMA_SPORT_MASK_V2 0xf
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WDMA0_BASE 0x4800
-+#define MTK_WDMA1_BASE 0x4c00
-+#else
- #define MTK_WDMA0_BASE 0x2800
- #define MTK_WDMA1_BASE 0x2c00
-+#endif
-
+-#define MTK_WDMA0_BASE 0x2800
+-#define MTK_WDMA1_BASE 0x2c00
+-
/* QDMA descriptor txd4 */
#define TX_DMA_CHKSUM (0x7 << 29)
+ #define TX_DMA_TSO BIT(28)
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index ea1cbdf..948f013 100644
+index affa704..02e06a8 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -18,15 +18,6 @@
@@ -154,37 +207,44 @@
static struct mtk_wed_hw *hw_list[2];
static DEFINE_MUTEX(hw_lock);
-@@ -80,14 +71,19 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
- static struct mtk_wed_hw *
+@@ -81,11 +72,31 @@ static struct mtk_wed_hw *
mtk_wed_assign(struct mtk_wed_device *dev)
{
-- struct mtk_wed_hw *hw;
+ struct mtk_wed_hw *hw;
+ int i;
+
-+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
-+ struct mtk_wed_hw *hw = hw_list[i];
++ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
++ hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
++ if (!hw)
++ return NULL;
+
-+ if (!hw || hw->wed_dev)
-+ continue;
++ if (!hw->wed_dev)
++ goto out;
++
++ if (hw->version == 1)
++ return NULL;
++
++ /* MT7986 WED devices do not have any pcie slot restrictions */
++ }
++ /* MT7986 PCIE or AXI */
++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
++ hw = hw_list[i];
++ if (hw && !hw->wed_dev)
++ goto out;
++ }
- hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
- if (!hw || hw->wed_dev)
- return NULL;
-+ hw->wed_dev = dev;
-+ return hw;
-+ }
-
-- hw->wed_dev = dev;
-- return hw;
+ return NULL;
- }
- static int
-@@ -96,19 +92,27 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- struct mtk_wdma_desc *desc;
++out:
+ hw->wed_dev = dev;
+ return hw;
+ }
+@@ -97,11 +108,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
dma_addr_t desc_phys;
void **page_list;
-+ u32 last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG1;
int token = dev->wlan.token_start;
- int ring_size;
- int n_pages;
@@ -193,130 +253,65 @@
+ int i;
+
+
-+ if (dev->ver == MTK_WED_V1) {
++ if (dev->hw->version == 1)
+ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
-+ } else {
++ else
+ ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
+ MTK_WED_WDMA_RING_SIZE * 2;
-+ last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG0;
-+ }
- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
- if (!page_list)
- return -ENOMEM;
-
-- dev->buf_ring.size = ring_size;
-+ dev->buf_ring.size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
- dev->buf_ring.pages = page_list;
+@@ -151,10 +167,17 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-@@ -154,7 +158,7 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- txd_size) |
- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
- MTK_WED_BUF_SIZE - txd_size) |
-- MTK_WDMA_DESC_CTRL_LAST_SEG1;
-+ last_seg;
+ desc->buf0 = cpu_to_le32(buf_phys);
+ desc->buf1 = cpu_to_le32(buf_phys + txd_size);
+- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
+- MTK_WED_BUF_SIZE - txd_size) |
+- MTK_WDMA_DESC_CTRL_LAST_SEG1;
++
++ if (dev->hw->version == 1)
++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++ MTK_WED_BUF_SIZE - txd_size) |
++ MTK_WDMA_DESC_CTRL_LAST_SEG1;
++ else
++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
++ MTK_WED_BUF_SIZE - txd_size) |
++ MTK_WDMA_DESC_CTRL_LAST_SEG0;
+ desc->ctrl = cpu_to_le32(ctrl);
desc->info = 0;
desc++;
-
-@@ -202,12 +206,12 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
- }
-
- static void
--mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
-+mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
- {
+@@ -210,7 +233,7 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
if (!ring->desc)
return;
- dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc),
-+ dma_free_coherent(dev->hw->dev, ring->size * sizeof(*ring->desc) * scale,
++ dma_free_coherent(dev->hw->dev, ring->size * ring->desc_size,
ring->desc, ring->desc_phys);
}
-@@ -217,9 +221,69 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- int i;
+@@ -230,6 +253,9 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ {
+ u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
- for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
-- mtk_wed_free_ring(dev, &dev->tx_ring[i]);
-+ mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-- mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
-+ mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
-+}
-+
-+static void
-+mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
-+{
-+ u32 wdma_mask;
-+
-+ wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
-+
-+ /* wed control cr set */
-+ wed_set(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-+ MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
-+ MTK_WED_CTRL_WED_TX_BM_EN |
-+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-+
-+ if (dev->ver == MTK_WED_V1) {
-+ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
-+ MTK_WED_PCIE_INT_TRIGGER_STATUS);
-+
-+ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
-+ MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
-+ MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
-+
-+ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+ } else {
-+ /* initail tx interrupt trigger */
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
-+ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
-+ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_TX1_DONE_EN |
-+ MTK_WED_WPDMA_INT_CTRL_TX1_DONE_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX0_DONE_TRIG,
-+ dev->wlan.tx_tbit[0]) |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
-+ dev->wlan.tx_tbit[1]));
++ if (dev->hw->version == 1)
++ mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
+
-+ /* initail txfree interrupt trigger */
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
-+ MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
-+ MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
-+ dev->wlan.txfree_tbit));
-+ }
-+ /* initail wdma interrupt agent */
-+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
-+ if (dev->ver == MTK_WED_V1) {
-+ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
-+ } else {
-+ wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
-+ wed_set(dev, MTK_WED_WDMA_INT_CTRL,
-+ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
-+
-+ }
-+
-+ wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-+ wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
-+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
-+ wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
- }
+ if (!dev->hw->num_flows)
+ mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
- static void
-@@ -234,10 +298,95 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+@@ -237,10 +263,57 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
wed_r32(dev, MTK_WED_EXT_INT_MASK);
}
+static void
-+mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
++mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
+{
-+ if (en) {
++ if (enable) {
+ wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
+ wed_w32(dev, MTK_WED_TXP_DW1,
+ FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
@@ -328,43 +323,6 @@
+}
+
+static void
-+mtk_wed_dma_enable(struct mtk_wed_device *dev)
-+{
-+ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+
-+ wed_set(dev, MTK_WED_GLO_CFG,
-+ MTK_WED_GLO_CFG_TX_DMA_EN |
-+ MTK_WED_GLO_CFG_RX_DMA_EN);
-+ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+
-+ wdma_set(dev, MTK_WDMA_GLO_CFG,
-+ MTK_WDMA_GLO_CFG_TX_DMA_EN |
-+ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
-+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
-+
-+ if (dev->ver == MTK_WED_V1) {
-+ wdma_set(dev, MTK_WDMA_GLO_CFG,
-+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
-+ } else {
-+ wed_set(dev, MTK_WED_WPDMA_CTRL,
-+ MTK_WED_WPDMA_CTRL_SDL1_FIXED);
-+
-+ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-+
-+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
-+ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
-+ }
-+}
-+
-+static void
+mtk_wed_dma_disable(struct mtk_wed_device *dev)
+{
+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
@@ -383,7 +341,7 @@
+ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0);
+
-+ if (dev->ver == MTK_WED_V1) {
++ if (dev->hw->version == 1) {
+ regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
+ wdma_m32(dev, MTK_WDMA_GLO_CFG,
+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0);
@@ -391,6 +349,8 @@
+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++
++ mtk_wed_set_512_support (dev, false)
+ }
+}
+
@@ -400,13 +360,10 @@
- regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
+ mtk_wed_dma_disable(dev);
+
-+ if (dev->ver > MTK_WED_V1)
-+ mtk_wed_set_512_support(dev, false);
-+
mtk_wed_set_ext_int(dev, false);
wed_clr(dev, MTK_WED_CTRL,
-@@ -245,26 +394,18 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+@@ -248,26 +321,18 @@ mtk_wed_stop(struct mtk_wed_device *dev)
MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
MTK_WED_CTRL_WED_TX_BM_EN |
MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
@@ -435,7 +392,7 @@
struct mtk_wed_hw *hw = dev->hw;
mutex_lock(&hw_lock);
-@@ -279,11 +420,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -282,11 +347,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mtk_wed_free_buffer(dev);
mtk_wed_free_tx_rings(dev);
@@ -444,7 +401,7 @@
- BIT(hw->index), BIT(hw->index));
+ if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
+ wlan_node = dev->wlan.pci_dev->dev.of_node;
-+ if (of_dma_is_coherent(wlan_node))
++ if (of_dma_is_coherent(wlan_node) && hw->hifsys)
+ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ BIT(hw->index), BIT(hw->index));
+ }
@@ -454,31 +411,25 @@
hw->eth->dma_dev != hw->eth->dev)
mtk_eth_set_dma_device(hw->eth, hw->eth->dev);
-@@ -294,15 +438,87 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -297,14 +365,76 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mutex_unlock(&hw_lock);
}
++#define PCIE_BASE_ADDR0 0x11280000
+static void
+mtk_wed_bus_init(struct mtk_wed_device *dev)
+{
-+#define PCIE_BASE_ADDR0 0x11280000
-+
-+ if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
-+ struct device_node *node;
-+ void __iomem * base_addr;
-+ u32 value = 0;
++ switch (dev->wlan.bus_type) {
++ case MTK_BUS_TYPE_PCIE: {
++ struct device_node *np = dev->hw->eth->dev->of_node;
++ struct regmap *regs;
+
-+ node = of_parse_phandle(dev->hw->node, "mediatek,wed_pcie", 0);
-+ if (!node) {
-+ pr_err("%s: no wed_pcie node\n", __func__);
-+ return;
-+ }
-+
-+ base_addr = of_iomap(node, 0);
++ regs = syscon_regmap_lookup_by_phandle(np,
++ "mediatek,wed-pcie");
++ if (IS_ERR(regs))
++ break;
+
-+ value = readl(base_addr);
-+ value |= BIT(0);
-+ writel(value, base_addr);
++ regmap_update_bits(regs, 0, BIT(0), BIT(0));
+
+ wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
+ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
@@ -489,40 +440,40 @@
+ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
+ wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
+
-+ value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-+ value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
+ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
+ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
+
-+ value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-+ value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
-+
+ /* pcie interrupt status trigger register */
+ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
+ wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+
+ /* pola setting */
-+ value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
+ wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
-+ } else if (dev->wlan.bus_type == MTK_BUS_TYPE_AXI) {
++ break;
++ }
++ case MTK_BUS_TYPE_AXI:
+ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
+ MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
++ break;
++ default:
++ break;
+ }
-+ return;
+}
+
+static void
+mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+{
-+ if (dev->ver > MTK_WED_V1) {
++ if (dev->hw->version == 1) {
++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
++ } else {
++ mtk_wed_bus_init(dev);
++
+ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int);
+ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
-+ } else {
-+ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
+ }
+}
+
@@ -534,21 +485,16 @@
mtk_wed_stop(dev);
mtk_wed_reset(dev, MTK_WED_RESET_WED);
-
-+ if (dev->ver > MTK_WED_V1)
-+ mtk_wed_bus_init(dev);
-+
+ mtk_wed_set_wpdma(dev);
-+
+
mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
- MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-@@ -311,30 +527,54 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -314,14 +444,30 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
- wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_INFO_PRERES);
-+ if (dev->ver == MTK_WED_V1) {
++ if (dev->hw->version == 1) {
+ u32 offset;
+ offset = dev->hw->index ? 0x04000400 : 0;
+ wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
@@ -557,7 +503,8 @@
- offset = dev->hw->index ? 0x04000400 : 0;
- wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
- wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
-+ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index));
++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++ MTK_PCIE_BASE(dev->hw->index));
+ } else {
+ wed_w32(dev, MTK_WED_WDMA_CFG_BASE, dev->hw->wdma_phy);
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_ETH_DMAD_FMT);
@@ -579,44 +526,62 @@
}
static void
- mtk_wed_hw_init(struct mtk_wed_device *dev)
- {
-+ int size = dev->buf_ring.size;
-+ int rev_size = MTK_WED_TX_RING_SIZE / 2;
-+ int thr = 1;
-+
- if (dev->init_done)
- return;
+@@ -332,46 +478,79 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
dev->init_done = true;
mtk_wed_set_ext_int(dev, false);
-+
-+ if (dev->ver > MTK_WED_V1) {
-+ size = MTK_WED_WDMA_RING_SIZE * 2 + dev->buf_ring.size;
-+ rev_size = size;
-+ thr = 0;
-+ }
-+
- wed_w32(dev, MTK_WED_TX_BM_CTRL,
- MTK_WED_TX_BM_CTRL_PAUSE |
+- wed_w32(dev, MTK_WED_TX_BM_CTRL,
+- MTK_WED_TX_BM_CTRL_PAUSE |
- FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
- dev->buf_ring.size / 128) |
- FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
- MTK_WED_TX_RING_SIZE / 256));
-+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
-+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
-@@ -347,28 +587,38 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+- wed_w32(dev, MTK_WED_TX_BM_TKID,
+- FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+- dev->wlan.token_start) |
+- FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+- dev->wlan.token_start + dev->wlan.nbuf - 1));
+-
wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
- wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+- wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
- FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
-+ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr) |
- MTK_WED_TX_BM_DYN_THR_HI);
-
-+ if (dev->ver > MTK_WED_V1) {
+- MTK_WED_TX_BM_DYN_THR_HI);
++ if (dev->hw->version == 1) {
++ wed_w32(dev, MTK_WED_TX_BM_CTRL,
++ MTK_WED_TX_BM_CTRL_PAUSE |
++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
++ dev->buf_ring.size / 128) |
++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
++ MTK_WED_TX_RING_SIZE / 256));
++ wed_w32(dev, MTK_WED_TX_BM_TKID,
++ FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++ dev->wlan.token_start) |
++ FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++ dev->wlan.token_start +
++ dev->wlan.nbuf - 1));
++ wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
++ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
++ MTK_WED_TX_BM_DYN_THR_HI);
++ } else {
++ wed_w32(dev, MTK_WED_TX_BM_CTRL,
++ MTK_WED_TX_BM_CTRL_PAUSE |
++ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
++ dev->buf_ring.size / 128) |
++ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
++ dev->buf_ring.size / 128));
++ wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
++ FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++ dev->wlan.token_start) |
++ FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++ dev->wlan.token_start +
++ dev->wlan.nbuf - 1));
++ wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
++ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) |
++ MTK_WED_TX_BM_DYN_THR_HI_V2);
+ wed_w32(dev, MTK_WED_TX_TKID_CTRL,
+ MTK_WED_TX_TKID_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
@@ -627,21 +592,27 @@
+ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
+ MTK_WED_TX_TKID_DYN_THR_HI);
+ }
+
mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
- wed_set(dev, MTK_WED_CTRL,
- MTK_WED_CTRL_WED_TX_BM_EN |
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
--
- wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
-+ if (dev->ver > MTK_WED_V1)
++ if (dev->hw->version == 1)
++ wed_set(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_WED_TX_BM_EN |
++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
++ else
+ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+
+ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
}
static void
-mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size)
-+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size)
{
++ void *head = (void *)ring->desc;
int i;
for (i = 0; i < size; i++) {
@@ -649,136 +620,228 @@
- desc[i].ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
- desc[i].buf1 = 0;
- desc[i].info = 0;
++ struct mtk_wdma_desc *desc;
++ desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size);
+ desc->buf0 = 0;
+ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
+ desc->buf1 = 0;
+ desc->info = 0;
-+ desc += scale;
}
}
-@@ -424,7 +674,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- if (!desc)
+@@ -422,12 +601,10 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++) {
+- struct mtk_wdma_desc *desc = dev->tx_ring[i].desc;
+-
+- if (!desc)
++ if (!dev->tx_ring[i].desc)
continue;
- mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE);
-+ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver);
++ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE);
}
if (mtk_wed_poll_busy(dev))
-@@ -481,16 +731,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -484,16 +661,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
static int
mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
- int size)
-+ int size, int scale)
++ int size, u32 desc_size)
{
- ring->desc = dma_alloc_coherent(dev->hw->dev,
+- ring->desc = dma_alloc_coherent(dev->hw->dev,
- size * sizeof(*ring->desc),
-+ size * sizeof(*ring->desc) * scale,
++ ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size,
&ring->desc_phys, GFP_KERNEL);
if (!ring->desc)
return -ENOMEM;
++ ring->desc_size = desc_size;
ring->size = size;
- mtk_wed_ring_reset(ring->desc, size);
-+ mtk_wed_ring_reset(ring->desc, size, scale);
++ mtk_wed_ring_reset(ring, size);
return 0;
}
-@@ -500,7 +750,7 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -501,9 +678,10 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+ static int
+ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
{
++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE))
-+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, dev->ver))
++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size))
return -ENOMEM;
wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
-@@ -521,60 +771,36 @@ static void
- mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+@@ -521,43 +699,63 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ }
+
+ static void
+-mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
{
- u32 wdma_mask;
+- u32 wdma_mask;
- u32 val;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- if (!dev->tx_wdma[i].desc)
- mtk_wed_wdma_ring_setup(dev, i, 16);
-
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+- if (!dev->tx_wdma[i].desc)
+- mtk_wed_wdma_ring_setup(dev, i, 16);
+-
- wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
+-
+- mtk_wed_hw_init(dev);
++ u32 wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
- mtk_wed_hw_init(dev);
++ /* wed control cr set */
+ wed_set(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_WDMA_INT_AGENT_EN |
+ MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
+ MTK_WED_CTRL_WED_TX_BM_EN |
+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-- wed_set(dev, MTK_WED_CTRL,
-- MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-- MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
-- MTK_WED_CTRL_WED_TX_BM_EN |
-- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
--
- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, MTK_WED_PCIE_INT_TRIGGER_STATUS);
--
++ if (dev->hw->version == 1) {
++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
++ MTK_WED_PCIE_INT_TRIGGER_STATUS);
+
- wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
- MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
- MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
-+ mtk_wed_set_int(dev, irq_mask);
-
+-
- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
--
-- wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
++ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER,
++ MTK_WED_WPDMA_INT_TRIGGER_RX_DONE |
++ MTK_WED_WPDMA_INT_TRIGGER_TX_DONE);
+
++ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
++ } else {
++ /* initail tx interrupt trigger */
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
++ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
++ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
++ MTK_WED_WPDMA_INT_CTRL_TX1_DONE_EN |
++ MTK_WED_WPDMA_INT_CTRL_TX1_DONE_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX0_DONE_TRIG,
++ dev->wlan.tx_tbit[0]) |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
++ dev->wlan.tx_tbit[1]));
++
++ /* initail txfree interrupt trigger */
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
++ MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
++ MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
++ dev->wlan.txfree_tbit));
++
++ wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
++ wed_set(dev, MTK_WED_WDMA_INT_CTRL,
++ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
++ }
++ /* initail wdma interrupt agent */
+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
- wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
--
-- wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-- wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
-- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
-- wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
-+ mtk_wed_set_ext_int(dev, true);
+ wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
+ wdma_w32(dev, MTK_WDMA_INT_GRP2, wdma_mask);
+-
+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
+ wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
++}
++
++static void
++mtk_wed_dma_enable(struct mtk_wed_device *dev)
++{
++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-- wed_set(dev, MTK_WED_GLO_CFG,
-- MTK_WED_GLO_CFG_TX_DMA_EN |
-- MTK_WED_GLO_CFG_RX_DMA_EN);
-- wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
-- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-- wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-- MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+ if (dev->ver == MTK_WED_V1) {
-+ u32 val;
+ wed_set(dev, MTK_WED_GLO_CFG,
+ MTK_WED_GLO_CFG_TX_DMA_EN |
+@@ -568,16 +766,57 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-- mtk_wed_set_ext_int(dev, true);
++ wdma_set(dev, MTK_WDMA_GLO_CFG,
++ MTK_WDMA_GLO_CFG_TX_DMA_EN |
++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
++
++ if (dev->hw->version == 1) {
++ wdma_set(dev, MTK_WDMA_GLO_CFG,
++ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
++ } else {
++ wed_set(dev, MTK_WED_WPDMA_CTRL,
++ MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++
++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++
++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
++ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++ }
++}
++
++static void
++mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++{
++ u32 wdma_mask;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
++ if (!dev->tx_wdma[i].desc)
++ mtk_wed_wdma_ring_setup(dev, i, 16);
++
++
++ mtk_wed_hw_init(dev);
++ mtk_wed_configure_irq(dev, irq_mask);
++
+ mtk_wed_set_ext_int(dev, true);
- val = dev->wlan.wpdma_phys |
- MTK_PCIE_MIRROR_MAP_EN |
- FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
-+ val = dev->wlan.wpdma_phys |
-+ MTK_PCIE_MIRROR_MAP_EN |
-+ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
- if (dev->hw->index)
- val |= BIT(1);
- val |= BIT(0);
- regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
-+ if (dev->hw->index)
-+ val |= BIT(1);
-+ val |= BIT(0);
++ if (dev->hw->version == 1) {
++ u32 val;
++
++ val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
++ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
+
++ val |= BIT(0) | (BIT(1) * !!dev->hw->index);
+ regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
+ } else {
+ mtk_wed_set_512_support(dev, true);
+ }
-
++
+ mtk_wed_dma_enable(dev);
dev->running = true;
}
+@@ -586,20 +825,19 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ __releases(RCU)
+ {
+ struct mtk_wed_hw *hw;
++ struct device *device;
+ int ret = 0;
+
-@@ -588,15 +814,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
"mtk_wed_attach without holding the RCU read lock");
- if (pci_domain_nr(dev->wlan.pci_dev->bus) > 1 ||
-- !try_module_get(THIS_MODULE))
++ if ((dev->wlan.bus_type == MTK_WED_BUS_PCIE &&
++ pci_domain_nr(dev->wlan.pci_dev->bus) > 1) ||
+ !try_module_get(THIS_MODULE))
- ret = -ENODEV;
-+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
rcu_read_unlock();
@@ -789,55 +852,48 @@
mutex_lock(&hw_lock);
hw = mtk_wed_assign(dev);
-@@ -606,8 +828,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -609,8 +847,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
goto out;
}
- dev_info(&dev->wlan.pci_dev->dev, "attaching wed device %d\n", hw->index);
-
++ device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
++ &dev->wlan.pci_dev->dev
++ : &dev->wlan.platform_dev->dev;
++ dev_info(device, "attaching wed device %d version %d\n",
++ hw->index, hw->version);
dev->hw = hw;
dev->dev = hw->dev;
dev->irq = hw->irq;
-@@ -617,6 +837,9 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- of_dma_is_coherent(hw->eth->dev->of_node))
- mtk_eth_set_dma_device(hw->eth, hw->dev);
-
-+ dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
-+ wed_r32(dev, MTK_WED_REV_ID));
-+
- ret = mtk_wed_buffer_alloc(dev);
- if (ret) {
- mtk_wed_detach(dev);
-@@ -624,7 +847,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -627,7 +868,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
}
mtk_wed_hw_init_early(dev);
- regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP, BIT(hw->index), 0);
+
-+ if (dev->ver == MTK_WED_V1)
++ if (hw->hifsys)
+ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ BIT(hw->index), 0);
out:
mutex_unlock(&hw_lock);
-@@ -651,7 +877,7 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+@@ -654,7 +898,8 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
- BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
+ BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE))
-+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1))
++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
++ sizeof(*ring->desc)))
return -ENOMEM;
if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-@@ -678,21 +904,24 @@ static int
+@@ -681,21 +926,21 @@ static int
mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
{
struct mtk_wed_ring *ring = &dev->txfree_ring;
- int i;
-+ int i, idx = 1;
-+
-+ if(dev->ver > MTK_WED_V1)
-+ idx = 0;
++ int i, index = dev->hw->version == 1;
/*
* For txfree event handling, the same DMA ring is shared between WED
@@ -845,7 +901,7 @@
* WED
*/
- ring->reg_base = MTK_WED_RING_RX(1);
-+ ring->reg_base = MTK_WED_RING_RX(idx);
++ ring->reg_base = MTK_WED_RING_RX(index);
ring->wpdma = regs;
for (i = 0; i < 12; i += 4) {
@@ -853,22 +909,43 @@
- wed_w32(dev, MTK_WED_RING_RX(1) + i, val);
- wed_w32(dev, MTK_WED_WPDMA_RING_RX(1) + i, val);
-+ wed_w32(dev, MTK_WED_RING_RX(idx) + i, val);
-+ wed_w32(dev, MTK_WED_WPDMA_RING_RX(idx) + i, val);
++ wed_w32(dev, MTK_WED_RING_RX(index) + i, val);
++ wed_w32(dev, MTK_WED_WPDMA_RING_RX(index) + i, val);
}
return 0;
-@@ -780,7 +1009,8 @@ void mtk_wed_flow_remove(int index)
+@@ -783,7 +1028,9 @@ void mtk_wed_flow_remove(int index)
}
void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- void __iomem *wdma, int index)
-+ void __iomem *wdma, u32 wdma_phy, int index)
++ void __iomem *wdma, phys_addr_t wdma_phy,
++ int index)
+
{
static const struct mtk_wed_ops wed_ops = {
.attach = mtk_wed_attach,
-@@ -830,21 +1060,27 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -809,16 +1056,16 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+
+ pdev = of_find_device_by_node(np);
+ if (!pdev)
+- return;
++ goto err_of_node_put;
+
+ get_device(&pdev->dev);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+- return;
++ goto err_put_device;
+
+ regs = syscon_regmap_lookup_by_phandle(np, NULL);
+ if (IS_ERR(regs))
+- return;
++ goto err_put_device;
+
+ rcu_assign_pointer(mtk_soc_wed_ops, &wed_ops);
+
+@@ -835,27 +1082,42 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
hw->eth = eth;
hw->dev = &pdev->dev;
hw->wdma = wdma;
@@ -883,16 +960,17 @@
- kfree(hw);
- goto unlock;
- }
-
-- if (!index) {
-- regmap_write(hw->mirror, 0, 0);
-- regmap_write(hw->mirror, 4, 0);
-+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
++ hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
++
++ if (hw->version == 1) {
+ hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
+ "mediatek,pcie-mirror");
+ hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
+ "mediatek,hifsys");
-+
+
+- if (!index) {
+- regmap_write(hw->mirror, 0, 0);
+- regmap_write(hw->mirror, 4, 0);
+ if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) {
+ kfree(hw);
+ goto unlock;
@@ -907,8 +985,30 @@
mtk_wed_hw_add_debugfs(hw);
hw_list[index] = hw;
+
++ mutex_unlock(&hw_lock);
++
++ return;
++
+ unlock:
+ mutex_unlock(&hw_lock);
++err_put_device:
++ put_device(&pdev->dev);
++err_of_node_put:
++ of_node_put(np);
+ }
+
+ void mtk_wed_exit(void)
+@@ -876,6 +1138,7 @@ void mtk_wed_exit(void)
+ hw_list[i] = NULL;
+ debugfs_remove(hw->debugfs_dir);
+ put_device(hw->dev);
++ of_node_put(hw->node);
+ kfree(hw);
+ }
+ }
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 981ec61..9b17b74 100644
+index 981ec61..c9a20e4 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
@@ -8,6 +8,19 @@
@@ -931,20 +1031,27 @@
struct mtk_eth;
-@@ -23,6 +36,7 @@ struct mtk_wed_hw {
+@@ -18,11 +31,13 @@ struct mtk_wed_hw {
+ struct regmap *hifsys;
+ struct device *dev;
+ void __iomem *wdma;
++ phys_addr_t wdma_phy;
+ struct regmap *mirror;
+ struct dentry *debugfs_dir;
struct mtk_wed_device *wed_dev;
u32 debugfs_reg;
u32 num_flows;
-+ u32 wdma_phy;
++ u8 version;
char dirname[5];
int irq;
int index;
-@@ -101,14 +115,14 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+@@ -101,14 +116,16 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
}
void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- void __iomem *wdma, int index);
-+ void __iomem *wdma, u32 wdma_phy, int index);
++ void __iomem *wdma, phys_addr_t wdma_phy,
++ int index);
void mtk_wed_exit(void);
int mtk_wed_flow_add(int index);
void mtk_wed_flow_remove(int index);
@@ -952,7 +1059,8 @@
static inline void
mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- void __iomem *wdma, int index)
-+ void __iomem *wdma, u32 wdma_phy, int index)
++ void __iomem *wdma, phys_addr_t wdma_phy,
++ int index)
{
}
static inline void
@@ -971,26 +1079,18 @@
struct mtk_wed_hw *hw = s->private;
struct mtk_wed_device *dev = hw->wed_dev;
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 0a0465e..a9b9e2a 100644
+index 0a0465e..e66acda 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -4,9 +4,15 @@
- #ifndef __MTK_WED_REGS_H
+@@ -5,6 +5,7 @@
#define __MTK_WED_REGS_H
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(13, 0)
-+#define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(14)
-+#define MTK_WDMA_DESC_CTRL_BURST BIT(15)
-+#else
#define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0)
++#define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0)
#define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15)
#define MTK_WDMA_DESC_CTRL_BURST BIT(16)
-+#endif
#define MTK_WDMA_DESC_CTRL_LEN0 GENMASK(29, 16)
- #define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30)
- #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31)
-@@ -18,6 +24,14 @@ struct mtk_wdma_desc {
+@@ -18,6 +19,14 @@ struct mtk_wdma_desc {
__le32 info;
} __packed __aligned(4);
@@ -1005,7 +1105,7 @@
#define MTK_WED_RESET 0x008
#define MTK_WED_RESET_TX_BM BIT(0)
#define MTK_WED_RESET_TX_FREE_AGENT BIT(4)
-@@ -41,6 +55,7 @@ struct mtk_wdma_desc {
+@@ -41,6 +50,7 @@ struct mtk_wdma_desc {
#define MTK_WED_CTRL_RESERVE_EN BIT(12)
#define MTK_WED_CTRL_RESERVE_BUSY BIT(13)
#define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
@@ -1013,7 +1113,7 @@
#define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
#define MTK_WED_EXT_INT_STATUS 0x020
-@@ -49,6 +64,10 @@ struct mtk_wdma_desc {
+@@ -49,6 +59,10 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID BIT(4)
#define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH BIT(8)
#define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH BIT(9)
@@ -1024,7 +1124,7 @@
#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12)
#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
-@@ -57,16 +76,23 @@ struct mtk_wdma_desc {
+@@ -57,16 +71,23 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN BIT(19)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_BM_DMAD_COHERENT BIT(20)
#define MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR BIT(21)
@@ -1051,36 +1151,21 @@
#define MTK_WED_EXT_INT_MASK 0x028
-@@ -80,10 +106,6 @@ struct mtk_wdma_desc {
-
+@@ -81,6 +102,7 @@ struct mtk_wdma_desc {
#define MTK_WED_TX_BM_BASE 0x084
--#define MTK_WED_TX_BM_TKID 0x088
--#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
--#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
--
- #define MTK_WED_TX_BM_BUF_LEN 0x08c
+ #define MTK_WED_TX_BM_TKID 0x088
++#define MTK_WED_TX_BM_TKID_V2 0x0c8
+ #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
+ #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
- #define MTK_WED_TX_BM_INTF 0x09c
-@@ -93,9 +115,38 @@ struct mtk_wdma_desc {
- #define MTK_WED_TX_BM_INTF_TKID_READ BIT(29)
+@@ -94,7 +116,25 @@ struct mtk_wdma_desc {
#define MTK_WED_TX_BM_DYN_THR 0x0a0
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_TX_BM_DYN_THR_LO GENMASK(8, 0)
-+#define MTK_WED_TX_BM_DYN_THR_HI GENMASK(24, 16)
-+
-+#define MTK_WED_TX_BM_TKID 0x0c8
-+#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
-+#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
-+#else
#define MTK_WED_TX_BM_DYN_THR_LO GENMASK(6, 0)
++#define MTK_WED_TX_BM_DYN_THR_LO_V2 GENMASK(8, 0)
#define MTK_WED_TX_BM_DYN_THR_HI GENMASK(22, 16)
-
-+#define MTK_WED_TX_BM_TKID 0x088
-+#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
-+#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
-+#endif
++#define MTK_WED_TX_BM_DYN_THR_HI_V2 GENMASK(24, 16)
+
+#define MTK_WED_TX_TKID_CTRL 0x0c0
+#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM GENMASK(6, 0)
@@ -1097,11 +1182,10 @@
+#define MTK_WED_TXDP_CTRL 0x130
+#define MTK_WED_TXDP_DW9_OVERWR BIT(9)
+#define MTK_WED_RX_BM_TKID_MIB 0x1cc
-+
+
#define MTK_WED_INT_STATUS 0x200
#define MTK_WED_INT_MASK 0x204
-
-@@ -125,6 +176,7 @@ struct mtk_wdma_desc {
+@@ -125,6 +165,7 @@ struct mtk_wdma_desc {
#define MTK_WED_RESET_IDX_RX GENMASK(17, 16)
#define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4)
@@ -1109,7 +1193,7 @@
#define MTK_WED_RING_TX(_n) (0x300 + (_n) * 0x10)
-@@ -139,6 +191,19 @@ struct mtk_wdma_desc {
+@@ -139,6 +180,19 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY BIT(1)
#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN BIT(2)
#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY BIT(3)
@@ -1129,7 +1213,7 @@
#define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE GENMASK(5, 4)
#define MTK_WED_WPDMA_GLO_CFG_TX_WB_DDONE BIT(6)
#define MTK_WED_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7)
-@@ -152,24 +217,54 @@ struct mtk_wdma_desc {
+@@ -152,24 +206,54 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY BIT(26)
#define MTK_WED_WPDMA_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MTK_WED_WPDMA_GLO_CFG_OMIT_TX_INFO BIT(28)
@@ -1185,7 +1269,7 @@
#define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4)
#define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4)
-@@ -203,14 +298,22 @@ struct mtk_wdma_desc {
+@@ -203,14 +287,22 @@ struct mtk_wdma_desc {
#define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16)
#define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24)
@@ -1209,7 +1293,7 @@
#define MTK_WED_WDMA_RX_MIB(_n) (0xae0 + (_n) * 4)
#define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4)
-@@ -221,14 +324,21 @@ struct mtk_wdma_desc {
+@@ -221,14 +313,21 @@ struct mtk_wdma_desc {
#define MTK_WED_RING_OFS_CPU_IDX 0x08
#define MTK_WED_RING_OFS_DMA_IDX 0x0c
@@ -1233,21 +1317,14 @@
#define MTK_WDMA_INT_MASK 0x228
#define MTK_WDMA_INT_MASK_TX_DONE GENMASK(3, 0)
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 7e00cca..ffd547a 100644
+index 7e00cca..4db70b0 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -8,6 +8,19 @@
+@@ -8,12 +8,19 @@
#define MTK_WED_TX_QUEUES 2
+enum {
-+ MTK_NO_WED,
-+ MTK_WED_V1,
-+ MTK_WED_V2,
-+ MTK_WED_VMAX
-+};
-+
-+enum {
+ MTK_BUS_TYPE_PCIE,
+ MTK_BUS_TYPE_AXI,
+ MTK_BUS_TYPE_MAX
@@ -1256,20 +1333,24 @@
struct mtk_wed_hw;
struct mtk_wdma_desc;
-@@ -28,6 +41,7 @@ struct mtk_wed_device {
- bool init_done, running;
- int wdma_idx;
- int irq;
-+ u8 ver;
+ struct mtk_wed_ring {
+ struct mtk_wdma_desc *desc;
+ dma_addr_t desc_phys;
++ u32 desc_size;
+ int size;
+
+ u32 reg_base;
+@@ -42,9 +49,21 @@ struct mtk_wed_device {
- struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
- struct mtk_wed_ring txfree_ring;
-@@ -43,8 +57,17 @@ struct mtk_wed_device {
/* filled by driver: */
struct {
- struct pci_dev *pci_dev;
+- struct pci_dev *pci_dev;
++ union {
++ struct platform_device *platform_dev;
++ struct pci_dev *pci_dev;
++ };
++ enum mtk_wed_bus_tye bus_type;
+ void __iomem *base;
-+ u32 bus_type;
u32 wpdma_phys;
+ u32 wpdma_int;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-add-wed-tx-wds-support-for-netsys2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-add-wed-tx-wds-support-for-netsys2.patch
index aaa6c48..d8c1c8c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-add-wed-tx-wds-support-for-netsys2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3007-add-wed-tx-wds-support-for-netsys2.patch
@@ -1,20 +1,20 @@
-From 396ce749479219467ea3f1123d5e9a303e5051ec Mon Sep 17 00:00:00 2001
+From 7c68ae1b991064bc0904313c56b83d2f3e03ccd7 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:03:33 +0800
-Subject: [PATCH 08/22] add-wed-tx-wds-support-for-mt7986
+Subject: [PATCH 07/24] add-wed-tx-wds-support-for-netsys2
---
- drivers/net/ethernet/mediatek/mtk_wed.c | 8 +++++++-
+ drivers/net/ethernet/mediatek/mtk_wed.c | 6 ++++--
drivers/net/ethernet/mediatek/mtk_wed_regs.h | 1 +
include/linux/soc/mediatek/mtk_wed.h | 3 +++
- 3 files changed, 11 insertions(+), 1 deletion(-)
+ 3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 0588e32..23e3dc5 100644
+index 02e06a8..ea8b2db 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -797,7 +797,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- val |= BIT(0);
+@@ -813,7 +813,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ val |= BIT(0) | (BIT(1) * !!dev->hw->index);
regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
} else {
- mtk_wed_set_512_support(dev, true);
@@ -22,31 +22,24 @@
}
mtk_wed_dma_enable(dev);
-@@ -809,6 +809,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- __releases(RCU)
- {
- struct mtk_wed_hw *hw;
-+ u16 ver;
- int ret = 0;
+@@ -869,9 +869,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
-@@ -839,6 +840,11 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ mtk_wed_hw_init_early(dev);
- dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
- wed_r32(dev, MTK_WED_REV_ID));
-+ if (dev->ver > MTK_WED_V1)
-+ ver = FIELD_GET(MTK_WED_REV_ID_MINOR,
-+ wed_r32(dev, MTK_WED_REV_ID));
-+
-+ dev->rev_id = ((dev->ver << 28) | ver << 16);
+- if (hw->hifsys)
++ if (hw->version == 1)
+ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ BIT(hw->index), 0);
++ else
++ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
- ret = mtk_wed_buffer_alloc(dev);
- if (ret) {
+ out:
+ mutex_unlock(&hw_lock);
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index a9b9e2a..14e0e21 100644
+index e66acda..e797e9d 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -31,6 +31,7 @@ struct mtk_wdma_desc {
+@@ -26,6 +26,7 @@ struct mtk_wdma_desc {
#define MTK_WED_REV_ID 0x000
#define MTK_WED_REV_ID_MAJOR GENMASK(7, 0)
#endif
@@ -55,18 +48,18 @@
#define MTK_WED_RESET 0x008
#define MTK_WED_RESET_TX_BM BIT(0)
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index ffd547a..e914cb4 100644
+index 4db70b0..00036f9 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -42,6 +42,7 @@ struct mtk_wed_device {
+@@ -35,6 +35,7 @@ struct mtk_wed_device {
+ bool init_done, running;
int wdma_idx;
int irq;
- u8 ver;
+ u32 rev_id;
struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
struct mtk_wed_ring txfree_ring;
-@@ -72,6 +73,8 @@ struct mtk_wed_device {
+@@ -68,6 +69,8 @@ struct mtk_wed_device {
u16 token_start;
unsigned int nbuf;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-rx-support-for-netsys2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-rx-support-for-netsys2.patch
index 7efa9df..fd64dcf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-rx-support-for-netsys2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3008-add-wed-rx-support-for-netsys2.patch
@@ -1,24 +1,25 @@
-From d35f304a7d0ec9612064a41b98338d9f712fbb48 Mon Sep 17 00:00:00 2001
+From fad15885ddf2f138ed3ec652b4fcd0cbdf54bf4e Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:04:53 +0800
-Subject: [PATCH 09/22] add-wed-rx-support-for-mt7896
+Subject: [PATCH 08/24] add-wed-rx-support-for-netsys2
---
+ arch/arm64/boot/dts/mediatek/mt7981.dtsi | 23 +-
arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 42 +-
arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 42 +-
drivers/net/ethernet/mediatek/Makefile | 2 +-
- drivers/net/ethernet/mediatek/mtk_wed.c | 639 ++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_wed.c | 645 ++++++++++++++++--
drivers/net/ethernet/mediatek/mtk_wed.h | 51 ++
drivers/net/ethernet/mediatek/mtk_wed_ccif.c | 133 ++++
drivers/net/ethernet/mediatek/mtk_wed_ccif.h | 45 ++
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 90 +++
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 586 ++++++++++++++++
- drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 96 +++
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 144 +++-
- drivers/net/ethernet/mediatek/mtk_wed_wo.c | 564 ++++++++++++++++
- drivers/net/ethernet/mediatek/mtk_wed_wo.h | 324 +++++++++
- include/linux/soc/mediatek/mtk_wed.h | 126 +++-
- 14 files changed, 2801 insertions(+), 83 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 604 ++++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 97 +++
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 143 +++-
+ drivers/net/ethernet/mediatek/mtk_wed_wo.c | 564 +++++++++++++++
+ drivers/net/ethernet/mediatek/mtk_wed_wo.h | 325 +++++++++
+ include/linux/soc/mediatek/mtk_wed.h | 114 +++-
+ 15 files changed, 2822 insertions(+), 98 deletions(-)
create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.c
create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ccif.h
create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_mcu.c
@@ -26,8 +27,52 @@
create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.c
create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_wo.h
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+index cb8f4e1..39b99d8 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+@@ -97,26 +97,29 @@
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ mediatek,wed_pcie = <&wed_pcie>;
++ mediatek,ap2woccif = <&ap2woccif0>;
++ mediatek,wocpu_ilm = <&wocpu0_ilm>;
++ mediatek,wocpu_dlm = <&wocpu0_dlm>;
++ mediatek,wocpu_boot = <&cpu_boot>;
++ mediatek,wocpu_emi = <&wocpu0_emi>;
++ mediatek,wocpu_data = <&wocpu_data>;
+ };
+
+- ap2woccif: ap2woccif@151A5000 {
+- compatible = "mediatek,ap2woccif";
+- reg = <0 0x151A5000 0 0x1000>,
+- <0 0x151AD000 0 0x1000>;
++ ap2woccif0: ap2woccif@151A5000 {
++ compatible = "mediatek,ap2woccif", "syscon";
++ reg = <0 0x151A5000 0 0x1000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
+- };
++ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
++ };
+
+ wocpu0_ilm: wocpu0_ilm@151E0000 {
+ compatible = "mediatek,wocpu0_ilm";
+ reg = <0 0x151E0000 0 0x8000>;
+ };
+
+- wocpu_dlm: wocpu_dlm@151E8000 {
++ wocpu0_dlm: wocpu_dlm@151E8000 {
+ compatible = "mediatek,wocpu_dlm";
+- reg = <0 0x151E8000 0 0x2000>,
+- <0 0x151F8000 0 0x2000>;
++ reg = <0 0x151E8000 0 0x2000>;
+
+ resets = <ðsysrst 0>;
+ reset-names = "wocpu_rst";
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index 3ff8994..c5dc5e8 100644
+index 9c288fc..e6f50d5 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -65,6 +65,12 @@
@@ -98,7 +143,7 @@
resets = <ðsysrst 0>;
reset-names = "wocpu_rst";
diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index 043e509..bfd2a02 100644
+index 02feaa9..3bacadc 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -65,6 +65,12 @@
@@ -168,50 +213,6 @@
resets = <ðsysrst 0>;
reset-names = "wocpu_rst";
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index d34943e7..512fb5d6 100644
---- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-@@ -97,26 +97,29 @@
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- mediatek,wed_pcie = <&wed_pcie>;
-+ mediatek,ap2woccif = <&ap2woccif0>;
-+ mediatek,wocpu_ilm = <&wocpu0_ilm>;
-+ mediatek,wocpu_dlm = <&wocpu0_dlm>;
-+ mediatek,wocpu_boot = <&cpu_boot>;
-+ mediatek,wocpu_emi = <&wocpu0_emi>;
-+ mediatek,wocpu_data = <&wocpu_data>;
- };
-
-- ap2woccif: ap2woccif@151A5000 {
-- compatible = "mediatek,ap2woccif";
-- reg = <0 0x151A5000 0 0x1000>,
-- <0 0x151AD000 0 0x1000>;
-+ ap2woccif0: ap2woccif@151A5000 {
-+ compatible = "mediatek,ap2woccif", "syscon";
-+ reg = <0 0x151A5000 0 0x1000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
-- };
-+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-
- wocpu0_ilm: wocpu0_ilm@151E0000 {
- compatible = "mediatek,wocpu0_ilm";
- reg = <0 0x151E0000 0 0x8000>;
- };
-
-- wocpu_dlm: wocpu_dlm@151E8000 {
-+ wocpu0_dlm: wocpu_dlm@151E8000 {
- compatible = "mediatek,wocpu_dlm";
-- reg = <0 0x151E8000 0 0x2000>,
-- <0 0x151F8000 0 0x2000>;
-+ reg = <0 0x151E8000 0 0x2000>;
-
- resets = <ðsysrst 0>;
- reset-names = "wocpu_rst";
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
index 4090132..fdbb90f 100644
--- a/drivers/net/ethernet/mediatek/Makefile
@@ -224,10 +225,10 @@
+obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o mtk_wed_wo.o mtk_wed_mcu.o mtk_wed_ccif.o
obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 23e3dc5..4b2f1a2 100644
+index ea8b2db..ad9f3d5 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -13,11 +13,19 @@
+@@ -13,10 +13,13 @@
#include <linux/debugfs.h>
#include <linux/iopoll.h>
#include <linux/soc/mediatek/mtk_wed.h>
@@ -236,19 +237,12 @@
#include "mtk_wed_regs.h"
#include "mtk_wed.h"
#include "mtk_ppe.h"
--
+#include "mtk_wed_mcu.h"
+#include "mtk_wed_wo.h"
-+
-+struct wo_cmd_ring {
-+ u32 q_base;
-+ u32 cnt;
-+ u32 unit;
-+};
+
static struct mtk_wed_hw *hw_list[2];
static DEFINE_MUTEX(hw_lock);
-
-@@ -51,6 +59,56 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
+@@ -51,12 +54,65 @@ wdma_set(struct mtk_wed_device *dev, u32 reg, u32 mask)
wdma_m32(dev, reg, 0, mask);
}
@@ -258,92 +252,107 @@
+ wdma_m32(dev, reg, mask, 0);
+}
+
+ static u32
+ mtk_wed_read_reset(struct mtk_wed_device *dev)
+ {
+ return wed_r32(dev, MTK_WED_RESET);
+ }
+
+static u32
+mtk_wdma_read_reset(struct mtk_wed_device *dev)
+{
+ return wdma_r32(dev, MTK_WDMA_GLO_CFG);
+}
+
-+static void
++static int
+mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+{
-+ u32 status;
-+ u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
-+ int i;
++ u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
++ int i, ret;
+
+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
-+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-+ !(status & mask), 0, 1000))
-+ WARN_ON_ONCE(1);
++ ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
++ !(status & mask), 0, 1000)
++ if (ret)
++ dev_err(dev->hw->dev, "rx reset failed \n");
+
-+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
-+ if (!dev->rx_wdma[i].desc) {
-+ wdma_w32(dev, MTK_WDMA_RING_RX(i) +
-+ MTK_WED_RING_OFS_CPU_IDX, 0);
++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
++ if (!dev->rx_wdma[i].desc)
++ continue;
++
++ wdma_w32(dev,
++ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
+ }
+}
+
+static void
+mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+{
-+ u32 status;
-+ u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
++ u32 status, mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
+ int i;
+
+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
+ if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
+ !(status & mask), 0, 1000))
-+ WARN_ON_ONCE(1);
++ dev_err(dev->hw->dev, "tx reset failed \n");
+
-+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+ if (!dev->tx_wdma[i].desc) {
-+ wdma_w32(dev, MTK_WDMA_RING_TX(i) +
-+ MTK_WED_RING_OFS_CPU_IDX, 0);
++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) {
++ if (!dev->tx_wdma[i].desc)
++ continue;
++
++ wdma_w32(dev,
++ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
+ }
+}
+
- static u32
- mtk_wed_read_reset(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
{
-@@ -68,6 +126,52 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
+@@ -68,6 +124,58 @@ mtk_wed_reset(struct mtk_wed_device *dev, u32 mask)
WARN_ON_ONCE(1);
}
++static u32
++mtk_wed_wo_read_status(struct mtk_wed_device *dev)
++{
++ return wed_r32(dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_WO_STATUS);
++}
++
+static void
+mtk_wed_wo_reset(struct mtk_wed_device *dev)
+{
+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
+ u8 state = WO_STATE_DISABLE;
-+ u8 state_done = WOIF_DISABLE_DONE;
+ void __iomem *reg;
-+ u32 value;
-+ unsigned long timeout = jiffies + WOCPU_TIMEOUT;
++ u32 val;
+
+ mtk_wdma_tx_reset(dev);
+
+ mtk_wed_reset(dev, MTK_WED_RESET_WED);
+
-+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+ &state, sizeof(state), false);
++ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++ MTK_WED_WO_CMD_CHANGE_STATE, &state,
++ sizeof(state), false);
+
-+ do {
-+ value = wed_r32(dev, MTK_WED_SCR0 + 4 * WED_DUMMY_CR_WO_STATUS);
-+ } while (value != state_done && !time_after(jiffies, timeout));
++ if (readx_poll_timeout(mtk_wed_wo_read_status, dev, val,
++ val == WOIF_DISABLE_DONE,
++ 100, WOCPU_TIMEOUT))
++ dev_err(dev->hw->dev, "failed to disable wed-wo\n");
+
+ reg = ioremap(WOCPU_MCUSYS_RESET_ADDR, 4);
-+ value = readl((void *)reg);
++ val = readl((void *)reg);
+ switch(dev->hw->index) {
+ case 0:
-+ value |= WOCPU_WO0_MCUSYS_RESET_MASK;
-+ writel(value, (void *)reg);
-+ value &= ~WOCPU_WO0_MCUSYS_RESET_MASK;
-+ writel(value, (void *)reg);
++ val |= WOCPU_WO0_MCUSYS_RESET_MASK;
++ writel(val, (void *)reg);
++ val &= ~WOCPU_WO0_MCUSYS_RESET_MASK;
++ writel(val, (void *)reg);
+ break;
+ case 1:
-+ value |= WOCPU_WO1_MCUSYS_RESET_MASK;
-+ writel(value, (void *)reg);
-+ value &= ~WOCPU_WO1_MCUSYS_RESET_MASK;
-+ writel(value, (void *)reg);
++ val |= WOCPU_WO1_MCUSYS_RESET_MASK;
++ writel(val, (void *)reg);
++ val &= ~WOCPU_WO1_MCUSYS_RESET_MASK;
++ writel(val, (void *)reg);
+ break;
+ default:
+ dev_err(dev->hw->dev, "wrong mtk_wed%d\n",
@@ -358,21 +367,58 @@
static struct mtk_wed_hw *
mtk_wed_assign(struct mtk_wed_device *dev)
{
-@@ -178,7 +282,7 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -102,7 +210,7 @@ mtk_wed_assign(struct mtk_wed_device *dev)
+ }
+
+ static int
+-mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
++mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ {
+ struct mtk_wdma_desc *desc;
+ dma_addr_t desc_phys;
+@@ -124,16 +232,16 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
+ if (!page_list)
+ return -ENOMEM;
+
+- dev->buf_ring.size = ring_size;
+- dev->buf_ring.pages = page_list;
++ dev->tx_buf_ring.size = ring_size;
++ dev->tx_buf_ring.pages = page_list;
+
+ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+ &desc_phys, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+- dev->buf_ring.desc = desc;
+- dev->buf_ring.desc_phys = desc_phys;
++ dev->tx_buf_ring.desc = desc;
++ dev->tx_buf_ring.desc_phys = desc_phys;
+
+ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+ dma_addr_t page_phys, buf_phys;
+@@ -194,11 +302,11 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
+ }
+
+ static void
+-mtk_wed_free_buffer(struct mtk_wed_device *dev)
++mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
{
- struct mtk_wdma_desc *desc = dev->buf_ring.desc;
- void **page_list = dev->buf_ring.pages;
+- struct mtk_wdma_desc *desc = dev->buf_ring.desc;
+- void **page_list = dev->buf_ring.pages;
- int page_idx;
++ struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc;
++ void **page_list = dev->tx_buf_ring.pages;
+ int ring_size, page_idx;
int i;
if (!page_list)
-@@ -187,7 +291,14 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -207,7 +315,14 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
if (!desc)
goto free_pagelist;
- for (i = 0, page_idx = 0; i < dev->buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
-+ if (dev->ver == MTK_WED_V1) {
++ if (dev->hw->version == 1) {
+ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
+ } else {
+ ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
@@ -381,201 +427,141 @@
+
+ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
void *page = page_list[page_idx++];
+ dma_addr_t buf_addr;
- if (!page)
-@@ -198,13 +309,49 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
+@@ -220,13 +335,64 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
__free_page(page);
}
- dma_free_coherent(dev->hw->dev, dev->buf_ring.size * sizeof(*desc),
+- desc, dev->buf_ring.desc_phys);
+ dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
- desc, dev->buf_ring.desc_phys);
++ desc, dev->tx_buf_ring.desc_phys);
free_pagelist:
kfree(page_list);
}
+static int
-+mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
++mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
+{
+ struct mtk_rxbm_desc *desc;
+ dma_addr_t desc_phys;
-+ int ring_size;
+
-+ ring_size = dev->wlan.rx_nbuf;
-+ dev->rx_buf_ring.size = ring_size;
-+ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
++ dev->rx_buf_ring.size = dev->wlan.rx_nbuf;
++ desc = dma_alloc_coherent(dev->hw->dev,
++ dev->wlan.rx_nbuf * sizeof(*desc),
+ &desc_phys, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ dev->rx_buf_ring.desc = desc;
+ dev->rx_buf_ring.desc_phys = desc_phys;
-+
+ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt);
++
+ return 0;
+}
+
+static void
-+mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
++mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
+{
+ struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
-+ int ring_size = dev->rx_buf_ring.size;
+
+ if (!desc)
+ return;
+
+ dev->wlan.release_rx_buf(dev);
+
-+ dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
++ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc),
+ desc, dev->rx_buf_ring.desc_phys);
+}
+
++static void
++mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev)
++{
++ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD,
++ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size));
++
++ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
++
++ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
++ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt));
++
++ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH,
++ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
++
++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++}
++
static void
- mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
+ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
{
-@@ -226,13 +373,22 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
+@@ -237,6 +403,13 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
+ ring->desc, ring->desc_phys);
}
+static void
+mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
+{
-+ mtk_wed_free_rx_bm(dev);
-+ mtk_wed_free_ring(dev, &dev->rro.rro_ring, 1);
++ mtk_wed_free_rx_buffer(dev);
++ mtk_wed_free_ring(dev, &dev->rro.ring);
+}
+
static void
- mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
+ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
{
- u32 wdma_mask;
-
- wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
--
-+ if (dev->ver > MTK_WED_V1)
-+ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
-+ GENMASK(1, 0));
- /* wed control cr set */
- wed_set(dev, MTK_WED_CTRL,
- MTK_WED_CTRL_WDMA_INT_AGENT_EN |
-@@ -251,7 +407,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
- } else {
-- /* initail tx interrupt trigger */
-+
- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
- MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
- MTK_WED_WPDMA_INT_CTRL_TX0_DONE_CLR |
-@@ -262,22 +418,30 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX1_DONE_TRIG,
- dev->wlan.tx_tbit[1]));
+@@ -244,8 +417,8 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
-- /* initail txfree interrupt trigger */
- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX_FREE,
- MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN |
- MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_CLR |
- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
- dev->wlan.txfree_tbit));
-+
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
-+ MTK_WED_WPDMA_INT_CTRL_RX0_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_RX1_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
-+ dev->wlan.rx_tbit[0]) |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
-+ dev->wlan.rx_tbit[1]));
- }
-- /* initail wdma interrupt agent */
- wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
- if (dev->ver == MTK_WED_V1) {
- wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
- } else {
- wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
- wed_set(dev, MTK_WED_WDMA_INT_CTRL,
-- FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
--
-+ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,
-+ dev->wdma_idx));
- }
+ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
+ mtk_wed_free_ring(dev, &dev->tx_ring[i]);
+- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+- mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
++ mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
+ }
- wdma_w32(dev, MTK_WDMA_INT_MASK, wdma_mask);
-@@ -312,6 +476,40 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
+ static void
+@@ -277,6 +450,39 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
}
}
++#define MTK_WFMDA_RX_DMA_EN BIT(2)
+static void
+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
+{
-+#define MTK_WFMDA_RX_DMA_EN BIT(2)
++ u32 val;
++ int i;
+
-+ int timeout = 3;
-+ u32 cur_idx, regs;
++ if(!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED))
++ return;
+
-+ do {
-+ regs = MTK_WED_WPDMA_RING_RX_DATA(idx) +
-+ MTK_WED_RING_OFS_CPU_IDX;
-+ cur_idx = wed_r32(dev, regs);
++ for (i = 0; i < 3; i++) {
++ u32 cur_idx;
++
++ cur_idx = wed_r32(dev,
++ MTK_WED_WPDMA_RING_RX_DATA(idx) +
++ MTK_WED_RING_OFS_CPU_IDX);
+ if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
+ break;
+
+ usleep_range(100000, 200000);
-+ timeout--;
-+ } while (timeout > 0);
-+
-+ if (timeout) {
-+ unsigned int val;
-+
-+ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
-+ dev->wlan.phy_base);
-+ val |= MTK_WFMDA_RX_DMA_EN;
++ }
+
-+ wifi_w32(dev, dev->wlan.wpdma_rx_glo -
-+ dev->wlan.phy_base, val);
-+ } else {
++ if (i == 3) {
+ dev_err(dev->hw->dev, "mtk_wed%d: rx dma enable failed!\n",
+ dev->hw->index);
++ return;
+ }
++
++ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) |
++ MTK_WFMDA_RX_DMA_EN;
++ wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val);
+}
+
static void
- mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ mtk_wed_dma_disable(struct mtk_wed_device *dev)
{
-@@ -336,9 +534,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- wdma_set(dev, MTK_WDMA_GLO_CFG,
- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
- } else {
-+ int idx = 0;
-+
- wed_set(dev, MTK_WED_WPDMA_CTRL,
- MTK_WED_WPDMA_CTRL_SDL1_FIXED);
-
-+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
-+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-+
- wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-@@ -346,6 +550,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
- MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
-+
-+ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
-+ MTK_WED_WPDMA_RX_D_RX_DRV_EN |
-+ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
-+ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
-+ 0x2));
-+
-+ for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++)
-+ mtk_wed_check_wfdma_rx_fill(dev, idx);
- }
- }
-
-@@ -363,19 +576,23 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+@@ -291,22 +497,26 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
MTK_WED_GLO_CFG_TX_DMA_EN |
MTK_WED_GLO_CFG_RX_DMA_EN);
@@ -586,7 +572,7 @@
- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES, 0);
+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
- if (dev->ver == MTK_WED_V1) {
+ if (dev->hw->version == 1) {
regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
- wdma_m32(dev, MTK_WDMA_GLO_CFG,
- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES, 0);
@@ -596,125 +582,169 @@
wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+-
+- mtk_wed_set_512_support (dev, false)
+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
+ MTK_WED_WPDMA_RX_D_RX_DRV_EN);
+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
}
++
++ mtk_wed_set_512_support (dev, false);
}
-@@ -383,10 +600,12 @@ static void
- mtk_wed_stop(struct mtk_wed_device *dev)
- {
- mtk_wed_dma_disable(dev);
-+ mtk_wed_set_512_support(dev, false);
-
-- if (dev->ver > MTK_WED_V1)
-- mtk_wed_set_512_support(dev, false);
--
-+ if (dev->ver > MTK_WED_V1) {
-+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
-+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
-+ }
- mtk_wed_set_ext_int(dev, false);
-
- wed_clr(dev, MTK_WED_CTRL,
-@@ -395,6 +614,11 @@ mtk_wed_stop(struct mtk_wed_device *dev)
- MTK_WED_CTRL_WED_TX_BM_EN |
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-
-+ if (dev->ver > MTK_WED_V1) {
-+ wed_clr(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WED_RX_BM_EN);
-+ }
-+
- wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
- wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
+ static void
+@@ -327,6 +537,14 @@ mtk_wed_stop(struct mtk_wed_device *dev)
wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-@@ -417,10 +641,21 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
++
++ if (dev->hw->version == 1)
++ return;
++
++ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
++ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++
+ }
+
+ static void
+@@ -344,10 +562,23 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mtk_wed_reset(dev, MTK_WED_RESET_WED);
-+ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
-+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
-+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+- mtk_wed_free_buffer(dev);
++ if (mtk_wed_get_rx_capa(dev)) {
++ wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
++ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
++ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
++ }
+
- mtk_wed_free_buffer(dev);
++ mtk_wed_free_tx_buffer(dev);
mtk_wed_free_tx_rings(dev);
-+ if (dev->ver > MTK_WED_V1) {
+
+- if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
++ if (mtk_wed_get_rx_capa(dev)) {
+ mtk_wed_wo_reset(dev);
+ mtk_wed_free_rx_rings(dev);
+ mtk_wed_wo_exit(hw);
++ mtk_wdma_rx_reset(dev);
+ }
+
-+ mtk_wdma_rx_reset(dev);
-
-- if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
+ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
wlan_node = dev->wlan.pci_dev->dev.of_node;
- if (of_dma_is_coherent(wlan_node))
+ if (of_dma_is_coherent(wlan_node) && hw->hifsys)
regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
-@@ -443,7 +678,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+@@ -370,7 +601,7 @@ static void
+ mtk_wed_bus_init(struct mtk_wed_device *dev)
{
- #define PCIE_BASE_ADDR0 0x11280000
-
-- if (dev->wlan.bus_type == MTK_BUS_TYPE_PCIE) {
-+ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
- struct device_node *node;
- void __iomem * base_addr;
- u32 value = 0;
-@@ -477,7 +712,6 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
- value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
-
-- /* pcie interrupt status trigger register */
- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
- wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+ switch (dev->wlan.bus_type) {
+- case MTK_BUS_TYPE_PCIE: {
++ case MTK_WED_BUS_PCIE: {
+ struct device_node *np = dev->hw->eth->dev->of_node;
+ struct regmap *regs;
-@@ -485,7 +719,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
- wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+@@ -402,7 +633,7 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
-- } else if (dev->wlan.bus_type == MTK_BUS_TYPE_AXI) {
-+ } else if (dev->wlan.bus_type == MTK_WED_BUS_AXI) {
+ break;
+ }
+- case MTK_BUS_TYPE_AXI:
++ case MTK_WED_BUS_AXI:
wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
-@@ -501,6 +735,9 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+@@ -424,6 +655,8 @@ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
-+
+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
+ wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx);
- } else {
- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
}
-@@ -549,24 +786,92 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
- FIELD_PREP(MTK_WED_WDMA_OFST1_RX_CTRL,
- MTK_WDMA_RING_RX(0)));
- }
-+}
+ }
-+static void
-+mtk_wed_rx_bm_hw_init(struct mtk_wed_device *dev)
+@@ -470,6 +703,141 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+
+ }
+
++static int
++mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
++ int size)
+{
-+ wed_w32(dev, MTK_WED_RX_BM_RX_DMAD,
-+ FIELD_PREP(MTK_WED_RX_BM_RX_DMAD_SDL0, dev->wlan.rx_size));
++ ring->desc = dma_alloc_coherent(dev->hw->dev,
++ size * sizeof(*ring->desc),
++ &ring->desc_phys, GFP_KERNEL);
++ if (!ring->desc)
++ return -ENOMEM;
+
-+ wed_w32(dev, MTK_WED_RX_BM_BASE, dev->rx_buf_ring.desc_phys);
++ ring->desc_size = sizeof(*ring->desc);
++ ring->size = size;
++ memset(ring->desc, 0, size);
+
-+ wed_w32(dev, MTK_WED_RX_BM_INIT_PTR, MTK_WED_RX_BM_INIT_SW_TAIL |
-+ FIELD_PREP(MTK_WED_RX_BM_SW_TAIL, dev->wlan.rx_npkt));
++ return 0;
++}
+
-+ wed_w32(dev, MTK_WED_RX_BM_DYN_ALLOC_TH,
-+ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
++#define MTK_WED_MIOD_COUNT (MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT)
++static int
++mtk_wed_rro_alloc(struct mtk_wed_device *dev)
++{
++ struct device_node *np, *node = dev->hw->node;
++ struct mtk_wed_ring *ring;
++ struct resource res;
++ int ret;
+
-+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
- }
-
- static void
--mtk_wed_hw_init(struct mtk_wed_device *dev)
++ np = of_parse_phandle(node, "mediatek,wocpu_dlm", 0);
++ if (!np)
++ return -ENODEV;
++
++ ret = of_address_to_resource(np, 0, &res);
++ if (ret)
++ return ret;
++
++ dev->rro.rro_desc = ioremap(res.start, resource_size(&res));
++
++ ring = &dev->rro.ring;
++
++ dev->rro.miod_phys = res.start;
++ dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys;
++
++ if (mtk_wed_rro_ring_alloc(dev, ring, MTK_WED_RRO_QUE_CNT))
++ return -ENOMEM;
++
++ return 0;
++}
++
++static int
++mtk_wed_rro_cfg(struct mtk_wed_device *dev)
++{
++ struct mtk_wed_wo *wo = dev->hw->wed_wo;
++ struct {
++ struct {
++ __le32 base;
++ __le32 cnt;
++ __le32 unit;
++ } ring[2];
++
++ __le32 wed;
++ u8 version;
++ } req = {
++ .ring[0] = {
++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE),
++ .cnt = cpu_to_le32(MTK_WED_MIOD_CNT),
++ .unit = cpu_to_le32(MTK_WED_MIOD_ENTRY_CNT),
++ },
++ .ring[1] = {
++ .base = cpu_to_le32(MTK_WED_WOCPU_VIEW_MIOD_BASE +
++ MTK_WED_MIOD_COUNT),
++ .cnt = cpu_to_le32(MTK_WED_FB_CMD_CNT),
++ .unit = cpu_to_le32(4),
++ },
++ };
++
++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
++ &req, sizeof(req), true);
++}
++
++static void
+mtk_wed_rro_hw_init(struct mtk_wed_device *dev)
+{
+ wed_w32(dev, MTK_WED_RROQM_MIOD_CFG,
@@ -723,19 +753,19 @@
+ FIELD_PREP(MTK_WED_RROQM_MIOD_ENTRY_DW,
+ MTK_WED_MIOD_ENTRY_CNT >> 2));
+
-+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_desc_phys);
++ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL0, dev->rro.miod_phys);
+
+ wed_w32(dev, MTK_WED_RROQM_MIOD_CTRL1,
+ FIELD_PREP(MTK_WED_RROQM_MIOD_CNT, MTK_WED_MIOD_CNT));
+
-+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_desc_phys);
++ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL0, dev->rro.fdbk_phys);
+
+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL1,
+ FIELD_PREP(MTK_WED_RROQM_FDBK_CNT, MTK_WED_FB_CMD_CNT));
+
+ wed_w32(dev, MTK_WED_RROQM_FDBK_CTRL2, 0);
+
-+ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.rro_ring.desc_phys);
++ wed_w32(dev, MTK_WED_RROQ_BASE_L, dev->rro.ring.desc_phys);
+
+ wed_set(dev, MTK_WED_RROQM_RST_IDX,
+ MTK_WED_RROQM_RST_IDX_MIOD |
@@ -753,12 +783,12 @@
+{
+ wed_w32(dev, MTK_WED_RESET, MTK_WED_RESET_RX_ROUTE_QM);
+
-+ do {
-+ udelay(100);
++ for (;;) {
++ usleep_range(100, 200);
+
+ if (!(wed_r32(dev, MTK_WED_RESET) & MTK_WED_RESET_RX_ROUTE_QM))
+ break;
-+ } while (1);
++ }
+
+ /* configure RX_ROUTE_QM */
+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
@@ -771,85 +801,109 @@
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
+}
+
-+static void
-+mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_hw_init(struct mtk_wed_device *dev)
{
- int size = dev->buf_ring.size;
- int rev_size = MTK_WED_TX_RING_SIZE / 2;
- int thr = 1;
+@@ -479,7 +847,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ dev->init_done = true;
+ mtk_wed_set_ext_int(dev, false);
-- if (dev->init_done)
-- return;
--
-- dev->init_done = true;
-- mtk_wed_set_ext_int(dev, false);
--
- if (dev->ver > MTK_WED_V1) {
-- size = MTK_WED_WDMA_RING_SIZE * 2 + dev->buf_ring.size;
-+ size = MTK_WED_WDMA_RING_SIZE * ARRAY_SIZE(dev->tx_wdma) +
-+ dev->buf_ring.size;
- rev_size = size;
- thr = 0;
- }
-@@ -609,13 +914,46 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
++ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys);
+
+ wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
+
+@@ -487,7 +855,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ MTK_WED_TX_BM_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+- dev->buf_ring.size / 128) |
++ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ MTK_WED_TX_RING_SIZE / 256));
+ wed_w32(dev, MTK_WED_TX_BM_TKID,
+@@ -503,9 +871,9 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ MTK_WED_TX_BM_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+- dev->buf_ring.size / 128) |
++ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+- dev->buf_ring.size / 128));
++ dev->tx_buf_ring.size / 128));
+ wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
+ FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+ dev->wlan.token_start) |
+@@ -518,9 +886,9 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ wed_w32(dev, MTK_WED_TX_TKID_CTRL,
+ MTK_WED_TX_TKID_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
+- dev->buf_ring.size / 128) |
++ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
+- dev->buf_ring.size / 128));
++ dev->tx_buf_ring.size / 128));
+ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
+ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
+ MTK_WED_TX_TKID_DYN_THR_HI);
+@@ -528,27 +896,42 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+
+ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
+
+- if (dev->hw->version == 1)
++ if (dev->hw->version == 1) {
+ wed_set(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_WED_TX_BM_EN |
+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+- else
++ } else {
+ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
++ /* rx hw init*/
++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
++ MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
++
++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
++
++ mtk_wed_rx_buffer_hw_init(dev);
++ mtk_wed_rro_hw_init(dev);
++ mtk_wed_route_qm_hw_init(dev);
++ }
+
+ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
}
static void
--mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale)
-+mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
+-mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size)
++mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
{
-+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
-+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
-+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
-+
-+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
-+
-+ mtk_wed_rx_bm_hw_init(dev);
-+ mtk_wed_rro_hw_init(dev);
-+ mtk_wed_route_qm_hw_init(dev);
-+}
-+
-+static void
-+mtk_wed_hw_init(struct mtk_wed_device *dev)
-+{
-+ if (dev->init_done)
-+ return;
-+
-+ dev->init_done = true;
-+ mtk_wed_set_ext_int(dev, false);
-+ mtk_wed_tx_hw_init(dev);
-+ if (dev->ver > MTK_WED_V1)
-+ mtk_wed_rx_hw_init(dev);
-+}
-+
-+static void
-+mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
-+{
-+ __le32 ctrl;
+ void *head = (void *)ring->desc;
int i;
-+ if (tx)
-+ ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
-+ else
-+ ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST);
-+
for (i = 0; i < size; i++) {
+ struct mtk_wdma_desc *desc;
++
+ desc = (struct mtk_wdma_desc *)(head + i * ring->desc_size);
desc->buf0 = 0;
- desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
-+ desc->ctrl = ctrl;
++ if (tx)
++ desc->ctrl = cpu_to_le32(MTK_WDMA_DESC_CTRL_DMA_DONE);
++ else
++ desc->ctrl = cpu_to_le32(MTK_WFDMA_DESC_CTRL_TO_HOST);
desc->buf1 = 0;
desc->info = 0;
- desc += scale;
-@@ -674,7 +1012,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- if (!desc)
+ }
+@@ -604,7 +987,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ if (!dev->tx_ring[i].desc)
continue;
-- mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver);
-+ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver, true);
+- mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE);
++ mtk_wed_ring_reset(&dev->tx_ring[i], MTK_WED_TX_RING_SIZE,
++ true);
}
if (mtk_wed_poll_busy(dev))
-@@ -692,6 +1030,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -622,6 +1006,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
@@ -858,38 +912,21 @@
if (busy) {
mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
-@@ -729,9 +1069,24 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
-
- }
+@@ -661,7 +1047,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
-+static int
-+mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
-+ int size)
-+{
-+ ring->desc = dma_alloc_coherent(dev->hw->dev,
-+ size * sizeof(*ring->desc),
-+ &ring->desc_phys, GFP_KERNEL);
-+ if (!ring->desc)
-+ return -ENOMEM;
-+
-+ ring->size = size;
-+ memset(ring->desc, 0, size);
-+ return 0;
-+}
-+
static int
mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
-- int size, int scale)
-+ int size, int scale, bool tx)
+- int size, u32 desc_size)
++ int size, u32 desc_size, bool tx)
{
- ring->desc = dma_alloc_coherent(dev->hw->dev,
- size * sizeof(*ring->desc) * scale,
-@@ -740,17 +1095,18 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
- return -ENOMEM;
+ ring->desc = dma_alloc_coherent(dev->hw->dev, size * desc_size,
+ &ring->desc_phys, GFP_KERNEL);
+@@ -670,18 +1056,23 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+ ring->desc_size = desc_size;
ring->size = size;
-- mtk_wed_ring_reset(ring->desc, size, scale);
-+ mtk_wed_ring_reset(ring->desc, size, scale, tx);
+- mtk_wed_ring_reset(ring, size);
++ mtk_wed_ring_reset(ring, size, tx);
return 0;
}
@@ -898,25 +935,36 @@
-mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
{
- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
+ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
++ struct mtk_wed_ring *wdma;
-- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, dev->ver))
-+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+ dev->ver, true))
+- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size))
++ if (idx >= ARRAY_SIZE(dev->rx_wdma))
++ return -EINVAL;
++
++ wdma = &dev->rx_wdma[idx];
++ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size,
++ true))
return -ENOMEM;
wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
-@@ -767,22 +1123,143 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -698,6 +1089,62 @@ mtk_wed_wdma_ring_setup(struct mtk_wed_device *dev, int idx, int size)
return 0;
}
+static int
+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+{
-+ struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
++ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
++ struct mtk_wed_ring *wdma;
+
++ if (idx >= ARRAY_SIZE(dev->tx_wdma))
++ return -EINVAL;
++
++ wdma = &dev->tx_wdma[idx];
+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+ dev->ver, true))
++ desc_size, true))
+ return -ENOMEM;
+
+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
@@ -928,136 +976,117 @@
+ wdma_w32(dev,
+ MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
+
-+ if (idx == 0) {
-+ wed_w32(dev, MTK_WED_WDMA_RING_TX
-+ + MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-+ wed_w32(dev, MTK_WED_WDMA_RING_TX
-+ + MTK_WED_RING_OFS_COUNT, size);
-+ wed_w32(dev, MTK_WED_WDMA_RING_TX
-+ + MTK_WED_RING_OFS_CPU_IDX, 0);
-+ wed_w32(dev, MTK_WED_WDMA_RING_TX
-+ + MTK_WED_RING_OFS_DMA_IDX, 0);
++ if (!idx) {
++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE,
++ wdma->desc_phys);
++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_COUNT,
++ size);
++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_CPU_IDX,
++ 0);
++ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_DMA_IDX,
++ 0);
+ }
+
+ return 0;
+}
+
-+static int
-+mtk_wed_rro_alloc(struct mtk_wed_device *dev)
++static void
++mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
++ u32 reason, u32 hash)
+{
-+ struct device_node *np, *node = dev->hw->node;
-+ struct mtk_wed_ring *ring;
-+ struct resource res;
-+ int ret;
-+
-+ np = of_parse_phandle(node, "mediatek,wocpu_dlm", 0);
-+ if (!np)
-+ return -ENODEV;
-+
-+ ret = of_address_to_resource(np, 0, &res);
-+ if (ret)
-+ return ret;
-+
-+ dev->rro.rro_desc = ioremap(res.start, resource_size(&res));
-+
-+ ring = &dev->rro.rro_ring;
-+
-+ dev->rro.miod_desc_phys = res.start;
-+
-+ dev->rro.mcu_view_miod = MTK_WED_WOCPU_VIEW_MIOD_BASE;
-+ dev->rro.fdbk_desc_phys = MTK_WED_MIOD_ENTRY_CNT * MTK_WED_MIOD_CNT
-+ + dev->rro.miod_desc_phys;
-+
-+ if (mtk_wed_rro_ring_alloc(dev, ring, MTK_WED_RRO_QUE_CNT))
-+ return -ENOMEM;
-+
-+ return 0;
-+}
++ struct mtk_eth *eth = dev->hw->eth;
++ struct ethhdr *eh;
+
-+static int
-+mtk_wed_rro_cfg(struct mtk_wed_device *dev)
-+{
-+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+ struct {
-+ struct wo_cmd_ring ring[2];
++ if (!skb)
++ return;
+
-+ u32 wed;
-+ u8 ver;
-+ } req = {
-+ .ring = {
-+ [0] = {
-+ .q_base = dev->rro.mcu_view_miod,
-+ .cnt = MTK_WED_MIOD_CNT,
-+ .unit = MTK_WED_MIOD_ENTRY_CNT,
-+ },
-+ [1] = {
-+ .q_base = dev->rro.mcu_view_miod +
-+ MTK_WED_MIOD_ENTRY_CNT *
-+ MTK_WED_MIOD_CNT,
-+ .cnt = MTK_WED_FB_CMD_CNT,
-+ .unit = 4,
-+ },
-+ },
-+ .wed = 0,
-+ };
++ if (reason != MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
++ return;
+
-+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
-+ &req, sizeof(req), true);
++ skb_set_mac_header(skb, 0);
++ eh = eth_hdr(skb);
++ skb->protocol = eh->h_proto;
++ mtk_ppe_check_skb(eth->ppe[dev->hw->index], skb, hash);
+}
+
-+static int
-+mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
-+{
-+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+
-+ if (dev->ver == MTK_WED_V1)
-+ return 0;
+ static void
+ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ {
+@@ -720,6 +1167,8 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+
+ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
+ } else {
++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
++ GENMASK(1, 0));
+ /* initail tx interrupt trigger */
+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
+ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
+@@ -738,6 +1187,16 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
+ dev->wlan.txfree_tbit));
+
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
++ MTK_WED_WPDMA_INT_CTRL_RX0_EN |
++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
++ MTK_WED_WPDMA_INT_CTRL_RX1_EN |
++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
++ dev->wlan.rx_tbit[0]) |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
++ dev->wlan.rx_tbit[1]));
+
-+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
-+}
+ wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
+ wed_set(dev, MTK_WED_WDMA_INT_CTRL,
+ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
+@@ -775,9 +1234,15 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ wdma_set(dev, MTK_WDMA_GLO_CFG,
+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+ } else {
++ int i;
+
-+static void
-+mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
-+ u32 reason, u32 hash)
-+{
-+ int idx = dev->hw->index;
-+ struct mtk_eth *eth = dev->hw->eth;
-+ struct ethhdr *eh;
+ wed_set(dev, MTK_WED_WPDMA_CTRL,
+ MTK_WED_WPDMA_CTRL_SDL1_FIXED);
+
++ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
+
-+ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
-+ if (!skb)
-+ return;
+ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+@@ -785,18 +1250,26 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
+ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
+
-+ skb_set_mac_header(skb, 0);
-+ eh = eth_hdr(skb);
-+ skb->protocol = eh->h_proto;
-+ mtk_ppe_check_skb(eth->ppe[idx], skb, hash);
-+ }
-+}
++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++ MTK_WED_WPDMA_RX_D_RX_DRV_EN |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
++ 0x2));
+
++ for (i = 0; i < MTK_WED_RX_QUEUES; i++)
++ mtk_wed_check_wfdma_rx_fill(dev, i);
+ }
+ }
+
static void
mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
{
- u32 wdma_mask;
-- int i;
-+ int i, ret;
+ int i;
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- if (!dev->tx_wdma[i].desc)
+- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+- if (!dev->tx_wdma[i].desc)
- mtk_wed_wdma_ring_setup(dev, i, 16);
--
++ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
++ if (!dev->rx_wdma[i].desc)
+ mtk_wed_wdma_rx_ring_setup(dev, i, 16);
- mtk_wed_hw_init(dev);
-
- mtk_wed_set_int(dev, irq_mask);
--
--
- mtk_wed_set_ext_int(dev, true);
- if (dev->ver == MTK_WED_V1) {
-@@ -797,8 +1274,20 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- val |= BIT(0);
+ mtk_wed_hw_init(dev);
+@@ -813,9 +1286,22 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ val |= BIT(0) | (BIT(1) * !!dev->hw->index);
regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
} else {
- mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
@@ -1070,75 +1099,83 @@
+ wed_r32(dev, MTK_WED_EXT_INT_MASK1);
+ wed_r32(dev, MTK_WED_EXT_INT_MASK2);
+
-+ ret = mtk_wed_rro_cfg(dev);
-+ if (ret)
++ if (mtk_wed_rro_cfg(dev))
+ return;
++
}
-+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
++ mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
++
mtk_wed_dma_enable(dev);
dev->running = true;
-@@ -809,6 +1298,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- __releases(RCU)
- {
- struct mtk_wed_hw *hw;
-+ struct device *device;
- u16 ver;
- int ret = 0;
-
-@@ -829,6 +1319,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- goto out;
+ }
+@@ -844,7 +1330,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ if (!hw) {
+ module_put(THIS_MODULE);
+ ret = -ENODEV;
+- goto out;
++ goto unlock;
}
-+ device = dev->wlan.bus_type == MTK_WED_BUS_PCIE
-+ ? &dev->wlan.pci_dev->dev
-+ : &dev->wlan.platform_dev->dev;
-+ dev_info(device, "attaching wed device %d version %d\n",
-+ hw->index, hw->ver);
-+
- dev->hw = hw;
+ device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
+@@ -856,26 +1342,40 @@ mtk_wed_attach(struct mtk_wed_device *dev)
dev->dev = hw->dev;
dev->irq = hw->irq;
-@@ -847,9 +1343,17 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- dev->rev_id = ((dev->ver << 28) | ver << 16);
+ dev->wdma_idx = hw->index;
++ dev->version = hw->version;
+
+ if (hw->eth->dma_dev == hw->eth->dev &&
+ of_dma_is_coherent(hw->eth->dev->of_node))
+ mtk_eth_set_dma_device(hw->eth, hw->dev);
- ret = mtk_wed_buffer_alloc(dev);
+- ret = mtk_wed_buffer_alloc(dev);
- if (ret) {
- mtk_wed_detach(dev);
-- goto out;
++ ret = mtk_wed_tx_buffer_alloc(dev);
+ if (ret)
-+ goto error;
+ goto out;
+- }
+
-+ if (dev->ver > MTK_WED_V1) {
-+ ret = mtk_wed_rx_bm_alloc(dev);
++ if (mtk_wed_get_rx_capa(dev)) {
++ ret = mtk_wed_rx_buffer_alloc(dev);
+ if (ret)
-+ goto error;
++ goto out;
+
+ ret = mtk_wed_rro_alloc(dev);
+ if (ret)
-+ goto error;
- }
++ goto out;
++ }
mtk_wed_hw_init_early(dev);
-@@ -857,7 +1361,12 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- if (dev->ver == MTK_WED_V1)
+
+- if (hw->version == 1)
++ if (hw->version == 1) {
regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
BIT(hw->index), 0);
-+ else
+- else
++ } else {
+ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
+ ret = mtk_wed_wo_init(hw);
++ }
-+error:
+ out:
+ if (ret)
+ mtk_wed_detach(dev);
- out:
++unlock:
mutex_unlock(&hw_lock);
-@@ -883,10 +1392,10 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ return ret;
+@@ -898,13 +1398,14 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ * WDMA RX.
+ */
- BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
+- BUG_ON(idx >= ARRAY_SIZE(dev->tx_ring));
++ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring)))
++ return -EINVAL;
-- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1))
-+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1, true))
+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
+- sizeof(*ring->desc)))
++ sizeof(*ring->desc), true))
return -ENOMEM;
- if (mtk_wed_wdma_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
@@ -1146,7 +1183,7 @@
return -ENOMEM;
ring->reg_base = MTK_WED_RING_TX(idx);
-@@ -933,6 +1442,35 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -948,6 +1449,37 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
return 0;
}
@@ -1155,10 +1192,11 @@
+{
+ struct mtk_wed_ring *ring = &dev->rx_ring[idx];
+
-+ BUG_ON(idx > ARRAY_SIZE(dev->rx_ring));
-+
++ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring)))
++ return -EINVAL;
+
-+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, 1, false))
++ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
++ sizeof(*ring->desc), false))
+ return -ENOMEM;
+
+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
@@ -1166,6 +1204,7 @@
+
+ ring->reg_base = MTK_WED_RING_RX_DATA(idx);
+ ring->wpdma = regs;
++ ring->flags |= MTK_WED_RING_CONFIGURED;
+
+ /* WPDMA -> WED */
+ wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
@@ -1182,16 +1221,17 @@
static u32
mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
{
-@@ -1022,6 +1560,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1037,7 +1569,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ static const struct mtk_wed_ops wed_ops = {
.attach = mtk_wed_attach,
.tx_ring_setup = mtk_wed_tx_ring_setup,
- .txfree_ring_setup = mtk_wed_txfree_ring_setup,
+ .rx_ring_setup = mtk_wed_rx_ring_setup,
-+ .msg_update = mtk_wed_send_msg,
+ .txfree_ring_setup = mtk_wed_txfree_ring_setup,
++ .msg_update = mtk_wed_mcu_msg_update,
.start = mtk_wed_start,
.stop = mtk_wed_stop,
.reset_dma = mtk_wed_reset_dma,
-@@ -1030,6 +1570,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -1046,6 +1580,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
.irq_get = mtk_wed_irq_get,
.irq_set_mask = mtk_wed_irq_set_mask,
.detach = mtk_wed_detach,
@@ -1199,24 +1239,8 @@
};
struct device_node *eth_np = eth->dev->of_node;
struct platform_device *pdev;
-@@ -1069,6 +1610,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- hw->wdma_phy = wdma_phy;
- hw->index = index;
- hw->irq = irq;
-+ hw->ver = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
-
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
- hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
-@@ -1085,6 +1627,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- regmap_write(hw->mirror, 0, 0);
- regmap_write(hw->mirror, 4, 0);
- }
-+ hw->ver = MTK_WED_V1;
- }
-
- mtk_wed_hw_add_debugfs(hw);
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 9b17b74..8ef5253 100644
+index c9a20e4..1bfd96f 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
@@ -13,6 +13,7 @@
@@ -1236,29 +1260,22 @@
+#define MTK_WED_RRO_QUE_CNT 8192
+#define MTK_WED_MIOD_ENTRY_CNT 128
+
-+#define MODULE_ID_WO 1
++#define MTK_WED_MODULE_ID_WO 1
struct mtk_eth;
+struct mtk_wed_wo;
struct mtk_wed_hw {
struct device_node *node;
-@@ -34,12 +42,14 @@ struct mtk_wed_hw {
+@@ -35,6 +43,7 @@ struct mtk_wed_hw {
struct regmap *mirror;
struct dentry *debugfs_dir;
struct mtk_wed_device *wed_dev;
+ struct mtk_wed_wo *wed_wo;
u32 debugfs_reg;
u32 num_flows;
- u32 wdma_phy;
- char dirname[5];
- int irq;
- int index;
-+ u32 ver;
- };
-
- struct mtk_wdma_info {
-@@ -66,6 +76,18 @@ wed_r32(struct mtk_wed_device *dev, u32 reg)
+ u8 version;
+@@ -67,6 +76,18 @@ wed_r32(struct mtk_wed_device *dev, u32 reg)
return val;
}
@@ -1277,8 +1294,8 @@
static inline void
wdma_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
{
-@@ -114,6 +136,23 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
- writel(val, dev->txfree_ring.wpdma + reg);
+@@ -97,6 +118,24 @@ wpdma_tx_w32(struct mtk_wed_device *dev, int ring, u32 reg, u32 val)
+ writel(val, dev->tx_ring[ring].wpdma + reg);
}
+static inline u32
@@ -1298,10 +1315,11 @@
+
+ writel(val, dev->rx_ring[ring].wpdma + reg);
+}
- void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- void __iomem *wdma, u32 wdma_phy, int index);
- void mtk_wed_exit(void);
-@@ -146,4 +185,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
++
+ static inline u32
+ wpdma_txfree_r32(struct mtk_wed_device *dev, u32 reg)
+ {
+@@ -149,4 +188,16 @@ static inline void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
}
#endif
@@ -1509,7 +1527,7 @@
+
+#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-index f420f18..4a9e684 100644
+index f420f18..7d8be99 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
@@ -2,6 +2,7 @@
@@ -1645,16 +1663,16 @@
debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
+ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
-+ if (hw->ver != MTK_WED_V1) {
++ if (hw->version != 1) {
+ wed_wo_mcu_debugfs(hw, dir);
+ }
}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
new file mode 100644
-index 0000000..96e30a3
+index 0000000..be63406
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -0,0 +1,590 @@
+@@ -0,0 +1,604 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/skbuff.h>
@@ -1743,6 +1761,20 @@
+ return ret;
+}
+
++int
++mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len)
++{
++ struct mtk_wed_wo *wo = dev->hw->wed_wo;
++
++ if (dev->hw->version == 1)
++ return 0;
++
++ if (WARN_ON(!wo))
++ return -ENODEV;
++
++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, id, data, len, true);
++}
++
+void mtk_wed_mcu_rx_event(struct mtk_wed_wo *wo,
+ struct sk_buff *skb)
+{
@@ -1804,7 +1836,7 @@
+ req.arg0 = (u32)exp->phys;
+ req.arg1 = (u32)exp->log_size;
+
-+ return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_EXCEPTION_INIT,
++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_EXCEPTION_INIT,
+ &req, sizeof(req), false);
+
+free:
@@ -2030,7 +2062,7 @@
+ hdr->length = cpu_to_le16(skb->len);
+ hdr->uni_id = seq;
+
-+ if (to_id == MODULE_ID_WO)
++ if (to_id == MTK_WED_MODULE_ID_WO)
+ hdr->flag |= WARP_CMD_FLAG_FROM_TO_WO;
+
+ if (wait_resp && wait_seq)
@@ -2225,7 +2257,7 @@
+ return count;
+ }
+
-+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, (void *)msgbuf, sizeof(struct wo_cmd_query), wait);
++ mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, cmd_id, (void *)msgbuf, sizeof(struct wo_cmd_query), wait);
+
+ return count;
+
@@ -2247,7 +2279,7 @@
+
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
new file mode 100644
-index 0000000..19e1199
+index 0000000..dbb17ae
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
@@ -0,0 +1,97 @@
@@ -2349,19 +2381,18 @@
+
+#endif
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 14e0e21..31871f7 100644
+index e797e9d..a79305f 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -4,6 +4,8 @@
+@@ -4,6 +4,7 @@
#ifndef __MTK_WED_REGS_H
#define __MTK_WED_REGS_H
+#define MTK_WFDMA_DESC_CTRL_TO_HOST BIT(8)
-+
- #if defined(CONFIG_MEDIATEK_NETSYS_V2)
- #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(13, 0)
- #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(14)
-@@ -16,6 +18,7 @@
+ #define MTK_WDMA_DESC_CTRL_LEN1 GENMASK(14, 0)
+ #define MTK_WDMA_DESC_CTRL_LEN1_V2 GENMASK(13, 0)
+ #define MTK_WDMA_DESC_CTRL_LAST_SEG1 BIT(15)
+@@ -11,6 +12,7 @@
#define MTK_WDMA_DESC_CTRL_LEN0 GENMASK(29, 16)
#define MTK_WDMA_DESC_CTRL_LAST_SEG0 BIT(30)
#define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31)
@@ -2369,7 +2400,7 @@
struct mtk_wdma_desc {
__le32 buf0;
-@@ -42,6 +45,8 @@ struct mtk_wdma_desc {
+@@ -37,6 +39,8 @@ struct mtk_wdma_desc {
#define MTK_WED_RESET_WED_TX_DMA BIT(12)
#define MTK_WED_RESET_WDMA_RX_DRV BIT(17)
#define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
@@ -2378,7 +2409,7 @@
#define MTK_WED_RESET_WED BIT(31)
#define MTK_WED_CTRL 0x00c
-@@ -53,8 +58,12 @@ struct mtk_wdma_desc {
+@@ -48,8 +52,12 @@ struct mtk_wdma_desc {
#define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
#define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
#define MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY BIT(11)
@@ -2393,7 +2424,7 @@
#define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
#define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25)
#define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
-@@ -69,8 +78,8 @@ struct mtk_wdma_desc {
+@@ -64,8 +72,8 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH BIT(10)
#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH BIT(11)
#endif
@@ -2404,7 +2435,7 @@
#define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17)
#define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18)
-@@ -87,8 +96,8 @@ struct mtk_wdma_desc {
+@@ -82,8 +90,8 @@ struct mtk_wdma_desc {
#define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
@@ -2415,7 +2446,7 @@
MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
-@@ -96,6 +105,8 @@ struct mtk_wdma_desc {
+@@ -91,6 +99,8 @@ struct mtk_wdma_desc {
MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
#define MTK_WED_EXT_INT_MASK 0x028
@@ -2424,7 +2455,7 @@
#define MTK_WED_STATUS 0x060
#define MTK_WED_STATUS_TX GENMASK(15, 8)
-@@ -183,6 +194,9 @@ struct mtk_wdma_desc {
+@@ -172,6 +182,9 @@ struct mtk_wdma_desc {
#define MTK_WED_RING_RX(_n) (0x400 + (_n) * 0x10)
@@ -2434,7 +2465,7 @@
#define MTK_WED_WPDMA_INT_TRIGGER 0x504
#define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1)
#define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4)
-@@ -239,13 +253,19 @@ struct mtk_wdma_desc {
+@@ -228,13 +241,19 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_INT_CTRL_TX 0x530
#define MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN BIT(0)
@@ -2455,7 +2486,7 @@
#define MTK_WED_WPDMA_INT_CTRL_TX_FREE 0x538
#define MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_EN BIT(0)
-@@ -270,13 +290,40 @@ struct mtk_wdma_desc {
+@@ -259,13 +278,40 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4)
#define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4)
@@ -2496,7 +2527,7 @@
#define MTK_WED_WDMA_GLO_CFG_RX_DRV_EN BIT(2)
#define MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY BIT(3)
#define MTK_WED_WDMA_GLO_CFG_BT_SIZE GENMASK(5, 4)
-@@ -320,6 +367,20 @@ struct mtk_wdma_desc {
+@@ -309,6 +355,20 @@ struct mtk_wdma_desc {
#define MTK_WED_WDMA_RX_RECYCLE_MIB(_n) (0xae8 + (_n) * 4)
#define MTK_WED_WDMA_RX_PROCESSED_MIB(_n) (0xaf0 + (_n) * 4)
@@ -2517,7 +2548,7 @@
#define MTK_WED_RING_OFS_BASE 0x00
#define MTK_WED_RING_OFS_COUNT 0x04
#define MTK_WED_RING_OFS_CPU_IDX 0x08
-@@ -330,12 +391,13 @@ struct mtk_wdma_desc {
+@@ -319,12 +379,13 @@ struct mtk_wdma_desc {
#define MTK_WDMA_GLO_CFG 0x204
#define MTK_WDMA_GLO_CFG_TX_DMA_EN BIT(0)
@@ -2532,7 +2563,7 @@
#define MTK_WDMA_RESET_IDX 0x208
#define MTK_WDMA_RESET_IDX_TX GENMASK(3, 0)
#define MTK_WDMA_RESET_IDX_RX GENMASK(17, 16)
-@@ -359,4 +421,70 @@ struct mtk_wdma_desc {
+@@ -348,4 +409,70 @@ struct mtk_wdma_desc {
/* DMA channel mapping */
#define HIFSYS_DMA_AG_MAP 0x008
@@ -3175,10 +3206,10 @@
+}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
new file mode 100644
-index 0000000..548b38e
+index 0000000..b24fef3
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-@@ -0,0 +1,324 @@
+@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> */
+
@@ -3499,23 +3530,31 @@
+ return val;
+}
+
++int mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len);
+int mtk_wed_wo_init(struct mtk_wed_hw *hw);
+void mtk_wed_wo_exit(struct mtk_wed_hw *hw);
+#endif
+
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index e914cb4..e8fca31 100644
+index 00036f9..658f392 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -6,7 +6,39 @@
- #include <linux/regmap.h>
+@@ -7,26 +7,73 @@
#include <linux/pci.h>
-+#define WED_WO_STA_REC 0x6
-+
#define MTK_WED_TX_QUEUES 2
+#define MTK_WED_RX_QUEUES 2
-+
+
+-enum {
+- MTK_BUS_TYPE_PCIE,
+- MTK_BUS_TYPE_AXI,
+- MTK_BUS_TYPE_MAX
+-};
++#define WED_WO_STA_REC 0x6
+
+ struct mtk_wed_hw;
+ struct mtk_wdma_desc;
+
+enum mtk_wed_wo_cmd {
+ MTK_WED_WO_CMD_WED_CFG,
+ MTK_WED_WO_CMD_WED_RX_STAT,
@@ -3544,45 +3583,29 @@
+ MTK_WED_WO_CMD_CCIF_RING_DUMP,
+ MTK_WED_WO_CMD_WED_END
+};
-
- enum {
- MTK_NO_WED,
-@@ -15,10 +47,9 @@ enum {
- MTK_WED_VMAX
- };
-
--enum {
-- MTK_BUS_TYPE_PCIE,
-- MTK_BUS_TYPE_AXI,
-- MTK_BUS_TYPE_MAX
-+enum mtk_wed_bus_tye {
-+ MTK_WED_BUS_PCIE,
-+ MTK_WED_BUS_AXI,
- };
-
- struct mtk_wed_hw;
-@@ -33,6 +64,33 @@ struct mtk_wed_ring {
- void __iomem *wpdma;
- };
-
++
+struct mtk_rxbm_desc {
+ __le32 buf0;
+ __le32 token;
+} __packed __aligned(4);
+
-+struct dma_buf {
-+ int size;
-+ void **pages;
-+ struct mtk_wdma_desc *desc;
-+ dma_addr_t desc_phys;
-+};
-+
-+struct dma_entry {
-+ int size;
-+ struct mtk_rxbm_desc *desc;
-+ dma_addr_t desc_phys;
++enum mtk_wed_bus_tye{
++ MTK_WED_BUS_PCIE,
++ MTK_WED_BUS_AXI,
+};
+
++#define MTK_WED_RING_CONFIGURED BIT(0)
+ struct mtk_wed_ring {
+ struct mtk_wdma_desc *desc;
+ dma_addr_t desc_phys;
+ u32 desc_size;
+ int size;
++ u32 flags;
+
+ u32 reg_base;
+ void __iomem *wpdma;
+ };
+
+struct mtk_wed_wo_rx_stats {
+ __le16 wlan_idx;
+ __le16 tid;
@@ -3595,42 +3618,49 @@
struct mtk_wed_device {
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
const struct mtk_wed_ops *ops;
-@@ -47,37 +105,64 @@ struct mtk_wed_device {
+@@ -35,18 +82,37 @@ struct mtk_wed_device {
+ bool init_done, running;
+ int wdma_idx;
+ int irq;
++ u8 version;
++
++ /* used by wlan driver */
+ u32 rev_id;
+
struct mtk_wed_ring tx_ring[MTK_WED_TX_QUEUES];
++ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
struct mtk_wed_ring txfree_ring;
struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES];
-+ struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
+ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
-+
-+ struct dma_buf buf_ring;
struct {
int size;
-- void **pages;
-- struct mtk_wdma_desc *desc;
-+ struct page_frag_cache rx_page;
-+ struct mtk_rxbm_desc *desc;
+ void **pages;
+ struct mtk_wdma_desc *desc;
dma_addr_t desc_phys;
- } buf_ring;
-+ } rx_buf_ring;
++ } tx_buf_ring;
++
++ struct {
++ int size;
++ struct page_frag_cache rx_page;
++ struct mtk_rxbm_desc *desc;
++ dma_addr_t desc_phys;
++ } rx_buf_ring;
+
+ struct {
-+ struct mtk_wed_ring rro_ring;
++ struct mtk_wed_ring ring;
+ void __iomem *rro_desc;
-+ dma_addr_t miod_desc_phys;
-+ dma_addr_t fdbk_desc_phys;
-+ u32 mcu_view_miod;
++ dma_addr_t miod_phys;
++ dma_addr_t fdbk_phys;
+ } rro;
/* filled by driver: */
struct {
-- struct pci_dev *pci_dev;
-+ union {
-+ struct platform_device *platform_dev;
-+ struct pci_dev *pci_dev;
-+ };
+@@ -56,24 +122,35 @@ struct mtk_wed_device {
+ };
+ enum mtk_wed_bus_tye bus_type;
void __iomem *base;
- u32 bus_type;
+ u32 phy_base;
u32 wpdma_phys;
@@ -3656,35 +3686,30 @@
u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
int (*offload_enable)(struct mtk_wed_device *wed);
void (*offload_disable)(struct mtk_wed_device *wed);
-+ u32 (*init_rx_buf)(struct mtk_wed_device *wed,
-+ int pkt_num);
++ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size);
+ void (*release_rx_buf)(struct mtk_wed_device *wed);
+ void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
+ struct mtk_wed_wo_rx_stats *stats);
} wlan;
#endif
};
-@@ -88,6 +173,10 @@ struct mtk_wed_ops {
+@@ -82,9 +159,15 @@ struct mtk_wed_ops {
+ int (*attach)(struct mtk_wed_device *dev);
+ int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
void __iomem *regs);
++ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++ void __iomem *regs);
int (*txfree_ring_setup)(struct mtk_wed_device *dev,
void __iomem *regs);
-+ int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+ void __iomem *regs);
+ int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
+ void *data, int len);
void (*detach)(struct mtk_wed_device *dev);
-
- void (*stop)(struct mtk_wed_device *dev);
-@@ -99,6 +188,8 @@ struct mtk_wed_ops {
-
- u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
- void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
+ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
+ u32 reason, u32 hash);
- };
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -123,6 +214,16 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
+ void (*stop)(struct mtk_wed_device *dev);
+ void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
+@@ -119,6 +202,16 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
return ret;
}
@@ -3692,7 +3717,7 @@
+mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+{
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+ return dev->ver != 1;
++ return dev->version != 1;
+#else
+ return false;
+#endif
@@ -3701,37 +3726,26 @@
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
#define mtk_wed_device_active(_dev) !!(_dev)->ops
#define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
-@@ -131,6 +232,10 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
- (_dev)->ops->tx_ring_setup(_dev, _ring, _regs)
- #define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
- (_dev)->ops->txfree_ring_setup(_dev, _regs)
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
-+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
-+ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
- #define mtk_wed_device_reg_read(_dev, _reg) \
- (_dev)->ops->reg_read(_dev, _reg)
- #define mtk_wed_device_reg_write(_dev, _reg, _val) \
-@@ -139,6 +244,8 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
+@@ -135,6 +228,12 @@ mtk_wed_device_attach(struct mtk_wed_device *dev)
(_dev)->ops->irq_get(_dev, _mask)
#define mtk_wed_device_irq_set_mask(_dev, _mask) \
(_dev)->ops->irq_set_mask(_dev, _mask)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
++ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
+#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
+ (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
++ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
#else
static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
{
-@@ -148,10 +255,13 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_start(_dev, _mask) do {} while (0)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV
- #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
- #define mtk_wed_device_reg_read(_dev, _reg) 0
+@@ -148,6 +247,9 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
#define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
#define mtk_wed_device_irq_get(_dev, _mask) 0
#define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
+#define mtk_wed_device_ppe_check(_dev, _hash) do {} while (0)
++#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
#endif
#endif
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-ser-support.patch
index c53746f..2aa0131 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-ser-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3009-add-wed-ser-support.patch
@@ -1,21 +1,21 @@
-From de9cc10d4e2d5aad4801dc92fb37c42478a4ab68 Mon Sep 17 00:00:00 2001
+From 7f1319357888271ea4aeeda81723b19a8f5ef2c0 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:05:45 +0800
-Subject: [PATCH 10/22] add-wed-ser-support
+Subject: [PATCH] add-wed-ser-support
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +
- drivers/net/ethernet/mediatek/mtk_wed.c | 361 ++++++++++++++-----
- drivers/net/ethernet/mediatek/mtk_wed.h | 11 +
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 12 +
- include/linux/soc/mediatek/mtk_wed.h | 27 +-
- 5 files changed, 320 insertions(+), 99 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_wed.c | 391 ++++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed.h | 10 +
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 9 +
+ include/linux/soc/mediatek/mtk_wed.h | 25 +-
+ 5 files changed, 342 insertions(+), 101 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 2cab49a..c1399c5 100644
+index 268c9e7..a24b223 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -4158,6 +4158,9 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4619,6 +4619,9 @@ static void mtk_pending_work(struct work_struct *work)
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
continue;
@@ -25,7 +25,7 @@
if (mtk_reset_flag == MTK_FE_STOP_TRAFFIC) {
pr_info("send MTK_FE_STOP_TRAFFIC event\n");
call_netdevice_notifiers(MTK_FE_STOP_TRAFFIC,
-@@ -4183,6 +4186,7 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4644,6 +4647,7 @@ static void mtk_pending_work(struct work_struct *work)
pr_warn("wait for MTK_FE_START_RESET\n");
}
rtnl_lock();
@@ -33,7 +33,7 @@
break;
}
-@@ -4221,6 +4225,9 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4682,6 +4686,9 @@ static void mtk_pending_work(struct work_struct *work)
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
continue;
@@ -43,7 +43,7 @@
if (mtk_reset_flag == MTK_FE_STOP_TRAFFIC) {
pr_info("send MTK_FE_START_TRAFFIC event\n");
call_netdevice_notifiers(MTK_FE_START_TRAFFIC,
-@@ -4230,6 +4237,7 @@ static void mtk_pending_work(struct work_struct *work)
+@@ -4691,6 +4698,7 @@ static void mtk_pending_work(struct work_struct *work)
call_netdevice_notifiers(MTK_FE_RESET_DONE,
eth->netdev[i]);
}
@@ -52,7 +52,7 @@
eth->netdev[i]);
break;
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 4b2f1a2..ae31412 100644
+index ad9f3d5..b993f0e 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -13,8 +13,10 @@
@@ -66,60 +66,52 @@
#include "mtk_wed_regs.h"
#include "mtk_wed.h"
#include "mtk_ppe.h"
-@@ -71,23 +73,27 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
- return wdma_r32(dev, MTK_WDMA_GLO_CFG);
- }
-
--static void
-+static int
- mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- {
- u32 status;
- u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
-- int i;
-+ int busy, i;
+@@ -80,10 +82,13 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
-- if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-- !(status & mask), 0, 1000))
-- WARN_ON_ONCE(1);
-+ busy = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-+ !(status & mask), 0, 10000);
-+
+ ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
+- !(status & mask), 0, 1000)
++ !(status & mask), 0, 10000);
+ if (ret)
+ dev_err(dev->hw->dev, "rx reset failed \n");
+
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-
- for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
- if (!dev->rx_wdma[i].desc) {
- wdma_w32(dev, MTK_WDMA_RING_RX(i) +
- MTK_WED_RING_OFS_CPU_IDX, 0);
++
+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
+ if (!dev->rx_wdma[i].desc)
+ continue;
+@@ -91,6 +96,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ wdma_w32(dev,
+ MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
}
+
-+ return busy;
++ return ret;
}
static void
-@@ -99,14 +105,14 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+@@ -101,16 +108,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
- !(status & mask), 0, 1000))
+ !(status & mask), 0, 10000))
- WARN_ON_ONCE(1);
+ dev_err(dev->hw->dev, "tx reset failed \n");
+- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) {
+- if (!dev->tx_wdma[i].desc)
+- continue;
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-- if (!dev->tx_wdma[i].desc) {
-- wdma_w32(dev, MTK_WDMA_RING_TX(i) +
-- MTK_WED_RING_OFS_CPU_IDX, 0);
+
++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
+ wdma_w32(dev,
+ MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
- }
-+ wdma_w32(dev, MTK_WDMA_RING_TX(i) +
-+ MTK_WED_RING_OFS_CPU_IDX, 0);
}
- static u32
-@@ -172,6 +178,51 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
+ static void
+@@ -176,6 +182,59 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
iounmap((void *)reg);
}
@@ -131,9 +123,13 @@
+
+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+ struct mtk_wed_hw *hw = hw_list[i];
-+ struct mtk_wed_device *dev = hw->wed_dev;
++ struct mtk_wed_device *dev;
+ int err;
+
++ if (!hw)
++ break;
++
++ dev = hw->wed_dev;
+ if (!dev || !dev->wlan.reset)
+ continue;
+
@@ -156,8 +152,12 @@
+
+ for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+ struct mtk_wed_hw *hw = hw_list[i];
-+ struct mtk_wed_device *dev = hw->wed_dev;
++ struct mtk_wed_device *dev;
+
++ if (!hw)
++ break;
++
++ dev = hw->wed_dev;
+ if (!dev || !dev->wlan.reset_complete)
+ continue;
+
@@ -171,123 +171,134 @@
static struct mtk_wed_hw *
mtk_wed_assign(struct mtk_wed_device *dev)
{
-@@ -505,8 +556,8 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
- wifi_w32(dev, dev->wlan.wpdma_rx_glo -
- dev->wlan.phy_base, val);
- } else {
+@@ -473,8 +532,8 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
+ }
+
+ if (i == 3) {
- dev_err(dev->hw->dev, "mtk_wed%d: rx dma enable failed!\n",
- dev->hw->index);
+ dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
+ dev->hw->index, idx);
+ return;
}
- }
-@@ -557,7 +608,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
- 0x2));
-
-- for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++)
-+ for (idx = 0; idx < dev->hw->ring_num; idx++)
- mtk_wed_check_wfdma_rx_fill(dev, idx);
- }
- }
-@@ -594,36 +645,45 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
- wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
- }
-+
-+ mtk_wed_set_512_support(dev, false);
- }
-
+@@ -522,16 +581,8 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
static void
mtk_wed_stop(struct mtk_wed_device *dev)
{
- mtk_wed_dma_disable(dev);
-- mtk_wed_set_512_support(dev, false);
-
- if (dev->ver > MTK_WED_V1) {
- wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
- wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
- }
mtk_wed_set_ext_int(dev, false);
-+ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
-+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
-+ wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-+ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
-+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
-+}
-+
-+static void
+- wed_clr(dev, MTK_WED_CTRL,
+- MTK_WED_CTRL_WDMA_INT_AGENT_EN |
+- MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
+- MTK_WED_CTRL_WED_TX_BM_EN |
+- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+-
+ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
+ wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
+@@ -543,39 +594,49 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+
+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
+ wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
+- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
+-
+ }
+
+ static void
+-mtk_wed_detach(struct mtk_wed_device *dev)
+mtk_wed_deinit(struct mtk_wed_device *dev)
-+{
+ {
+- struct device_node *wlan_node;
+- struct mtk_wed_hw *hw = dev->hw;
+ mtk_wed_stop(dev);
+ mtk_wed_dma_disable(dev);
-+
- wed_clr(dev, MTK_WED_CTRL,
- MTK_WED_CTRL_WDMA_INT_AGENT_EN |
- MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
- MTK_WED_CTRL_WED_TX_BM_EN |
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-- if (dev->ver > MTK_WED_V1) {
-- wed_clr(dev, MTK_WED_CTRL,
-- MTK_WED_CTRL_WED_RX_BM_EN);
-- }
-+ if (dev->hw->ver == 1)
+- mutex_lock(&hw_lock);
++ wed_clr(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_WDMA_INT_AGENT_EN |
++ MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
++ MTK_WED_CTRL_WED_TX_BM_EN |
++ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+
+- mtk_wed_stop(dev);
++ if (dev->hw->version == 1)
+ return;
-- wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
-- wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
-- wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
-- wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
-- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
+- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+ wed_clr(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_RX_ROUTE_QM_EN |
+ MTK_WED_CTRL_WED_RX_BM_EN |
+ MTK_WED_CTRL_RX_RRO_QM_EN);
- }
-
- static void
-@@ -634,16 +694,13 @@ mtk_wed_detach(struct mtk_wed_device *dev)
++}
- mutex_lock(&hw_lock);
+- mtk_wed_reset(dev, MTK_WED_RESET_WED);
++static void
++__mtk_wed_detach(struct mtk_wed_device *dev)
++{
++ struct device_node *wlan_node;
++ struct mtk_wed_hw *hw = dev->hw;
-- mtk_wed_stop(dev);
+- if (mtk_wed_get_rx_capa(dev)) {
+- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
+- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+- }
+ mtk_wed_deinit(dev);
-- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
-- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+ mtk_wdma_rx_reset(dev);
-
- mtk_wed_reset(dev, MTK_WED_RESET_WED);
-
-- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
-- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
-- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-+ mtk_wdma_tx_reset(dev);
-
- mtk_wed_free_buffer(dev);
++ mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ mtk_wed_free_tx_buffer(dev);
mtk_wed_free_tx_rings(dev);
-@@ -653,8 +710,6 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- mtk_wed_wo_exit(hw);
+
+ if (mtk_wed_get_rx_capa(dev)) {
+- mtk_wed_wo_reset(dev);
++ if(hw->wed_wo)
++ mtk_wed_wo_reset(dev);
+ mtk_wed_free_rx_rings(dev);
+- mtk_wed_wo_exit(hw);
+- mtk_wdma_rx_reset(dev);
++ if(hw->wed_wo)
++ mtk_wed_wo_exit(hw);
++ mtk_wdma_tx_reset(dev);
}
-- mtk_wdma_rx_reset(dev);
--
if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
- wlan_node = dev->wlan.pci_dev->dev.of_node;
- if (of_dma_is_coherent(wlan_node))
-@@ -748,7 +803,7 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+@@ -593,6 +654,13 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ module_put(THIS_MODULE);
+
+ hw->wed_dev = NULL;
++}
++
++static void
++mtk_wed_detach(struct mtk_wed_device *dev)
++{
++ mutex_lock(&hw_lock);
++ __mtk_wed_detach(dev);
+ mutex_unlock(&hw_lock);
+ }
+
+@@ -665,7 +733,7 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
{
u32 mask, set;
- mtk_wed_stop(dev);
+ mtk_wed_deinit(dev);
mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ mtk_wed_set_wpdma(dev);
- if (dev->ver > MTK_WED_V1)
-@@ -961,44 +1016,127 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
+@@ -715,7 +783,6 @@ mtk_wed_rro_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+
+ ring->desc_size = sizeof(*ring->desc);
+ ring->size = size;
+- memset(ring->desc, 0, size);
+
+ return 0;
+ }
+@@ -938,44 +1005,140 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
}
static u32
@@ -314,7 +325,7 @@
-
- if (wed_r32(dev, MTK_WED_CTRL) &
- (MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY))
-+ if (wed_r32(dev, reg) & mask)
++ if (wed_r32(dev, reg) & mask)
return true;
return false;
@@ -334,21 +345,24 @@
+ timeout, false, dev, reg, mask);
}
-+static void
++static int
+mtk_wed_rx_reset(struct mtk_wed_device *dev)
+{
+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
-+ u8 state = WO_STATE_SER_RESET;
-+ bool busy = false;
-+ int i;
++ u8 val = WO_STATE_SER_RESET;
++ int i, ret;
+
-+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+ &state, sizeof(state), true);
++ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++ MTK_WED_WO_CMD_CHANGE_STATE, &val,
++ sizeof(val), true);
++
++ if (ret)
++ return ret;
+
+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
-+ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
-+ if (busy) {
++ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
++ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
+ } else {
@@ -368,9 +382,9 @@
+
+ /* reset rro qm */
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN);
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_RX_RRO_QM_BUSY);
-+ if (busy) {
++ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_RX_RRO_QM_BUSY);
++ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM);
+ } else {
+ wed_set(dev, MTK_WED_RROQM_RST_IDX,
@@ -381,9 +395,9 @@
+
+ /* reset route qm */
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
-+ if (busy) {
++ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
++ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
+ } else {
+ wed_set(dev, MTK_WED_RTQM_GLO_CFG,
@@ -400,66 +414,73 @@
+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
+
+ /* reset wed rx dma */
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
-+ MTK_WED_GLO_CFG_RX_DMA_BUSY);
++ ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
++ MTK_WED_GLO_CFG_RX_DMA_BUSY);
+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN);
-+ if (busy) {
++ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA);
+ } else {
-+ wed_set(dev, MTK_WED_RESET_IDX,
-+ MTK_WED_RESET_IDX_RX);
++ struct mtk_eth *eth = dev->hw->eth;
++
++ if(MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
++ wed_set(dev, MTK_WED_RESET_IDX,
++ MTK_WED_RESET_IDX_RX_V2);
++ else
++ wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX);
+ wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ }
+
+ /* reset rx bm */
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
+ mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WED_RX_BM_BUSY);
++ MTK_WED_CTRL_WED_RX_BM_BUSY);
+ mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
+
+ /* wo change to enable state */
-+ state = WO_STATE_ENABLE;
-+ mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-+ &state, sizeof(state), true);
++ val = WO_STATE_ENABLE;
++ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++ MTK_WED_WO_CMD_CHANGE_STATE, &val,
++ sizeof(val), true);
++
++ if (ret)
++ return ret;
+
+ /* wed_rx_ring_reset */
+ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) {
-+ struct mtk_wdma_desc *desc = dev->rx_ring[i].desc;
-+
-+ if (!desc)
++ if (!dev->rx_ring[i].desc)
+ continue;
+
-+ mtk_wed_ring_reset(desc, MTK_WED_RX_RING_SIZE, 1, false);
++ mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE,
++ false);
+ }
+
-+ mtk_wed_free_rx_bm(dev);
++ mtk_wed_free_rx_buffer(dev);
++
++ return 0;
+}
+
+
static void
mtk_wed_reset_dma(struct mtk_wed_device *dev)
{
-@@ -1012,25 +1150,28 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- if (!desc)
- continue;
-
-- mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, dev->ver, true);
-+ mtk_wed_ring_reset(desc, MTK_WED_TX_RING_SIZE, 1, true);
+@@ -991,22 +1154,25 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ true);
}
- if (mtk_wed_poll_busy(dev))
- busy = mtk_wed_check_busy(dev);
+ /* 1.Reset WED Tx DMA */
+ wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN);
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_BUSY);
++ busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
++ MTK_WED_GLO_CFG_TX_DMA_BUSY);
if (busy) {
mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA);
} else {
- wed_w32(dev, MTK_WED_RESET_IDX,
+- wed_w32(dev, MTK_WED_RESET_IDX,
- MTK_WED_RESET_IDX_TX |
- MTK_WED_RESET_IDX_RX);
-+ MTK_WED_RESET_IDX_TX);
++ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX);
wed_w32(dev, MTK_WED_RESET_IDX, 0);
}
@@ -470,138 +491,153 @@
- mtk_wdma_rx_reset(dev);
+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-+ busy = !!(busy ||
-+ mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
-+ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
++ if (!busy)
++ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
++ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY);
if (busy) {
mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
-@@ -1047,15 +1188,30 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+@@ -1023,6 +1189,9 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE);
}
+ /* 3. Reset WED WPDMA Tx Driver Engine */
-+ wed_clr(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+
for (i = 0; i < 100; i++) {
val = wed_r32(dev, MTK_WED_TX_BM_INTF);
if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
- break;
+@@ -1030,8 +1199,21 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
}
--
+
mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
-+
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN);
mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
+ /* 4. Reset WED WPDMA Tx Driver Engine */
+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
++
+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
+
-+ busy = !!(busy ||
-+ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
++ if(!busy)
++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY);
++
if (busy) {
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
-@@ -1065,6 +1221,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- MTK_WED_WPDMA_RESET_IDX_TX |
- MTK_WED_WPDMA_RESET_IDX_RX);
+@@ -1043,6 +1225,16 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0);
-+ if (dev->ver > MTK_WED_V1) {
-+ wed_w32(dev, MTK_WED_RESET_IDX,
-+ MTK_WED_RESET_WPDMA_IDX_RX);
-+ wed_w32(dev, MTK_WED_RESET_IDX, 0);
-+ }
-+ }
-+
-+ if (dev->ver > MTK_WED_V1) {
-+ dev->init_done = false;
-+ mtk_wed_rx_reset(dev);
}
++ dev->init_done = false;
++ if (dev->hw->version == 1)
++ return;
++
++ if (!busy) {
++ wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX);
++ wed_w32(dev, MTK_WED_RESET_IDX, 0);
++ }
++
++ mtk_wed_rx_reset(dev);
}
-@@ -1101,13 +1267,15 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
+
+ static int
+@@ -1062,7 +1254,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
}
static int
-mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
-+mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
-+ int idx, int size, bool reset)
++mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
++ bool reset)
{
- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
+ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ struct mtk_wed_ring *wdma;
+@@ -1071,8 +1264,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ return -EINVAL;
-- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-- dev->ver, true))
-- return -ENOMEM;
-+ if(!reset)
-+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+ dev->ver, true))
-+ return -ENOMEM;
+ wdma = &dev->rx_wdma[idx];
+- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size,
+- true))
++ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
++ desc_size, true))
+ return -ENOMEM;
wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
- wdma->desc_phys);
-@@ -1124,13 +1292,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+@@ -1090,7 +1283,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
}
static int
-mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
-+mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
-+ int idx, int size, bool reset)
++mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
++ bool reset)
{
- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
+ u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ struct mtk_wed_ring *wdma;
+@@ -1099,8 +1293,8 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
+ return -EINVAL;
+ wdma = &dev->tx_wdma[idx];
- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-- dev->ver, true))
-- return -ENOMEM;
-+ if (!reset)
-+ if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-+ dev->ver, true))
-+ return -ENOMEM;
+- desc_size, true))
++ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
++ desc_size, true))
+ return -ENOMEM;
wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
- wdma->desc_phys);
-@@ -1140,7 +1310,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
- MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0);
+@@ -1112,6 +1306,9 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
wdma_w32(dev,
MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
--
+
+ if (reset)
-+ mtk_wed_ring_reset(wdma->desc, MTK_WED_WDMA_RING_SIZE,
-+ dev->ver, true);
- if (idx == 0) {
- wed_w32(dev, MTK_WED_WDMA_RING_TX
- + MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-@@ -1253,9 +1425,12 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
++ mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true);
++
+ if (!idx) {
+ wed_w32(dev, MTK_WED_WDMA_RING_TX + MTK_WED_RING_OFS_BASE,
+ wdma->desc_phys);
+@@ -1267,9 +1464,12 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
{
- int i, ret;
+ int i;
-+ if (dev->ver > MTK_WED_V1)
-+ ret = mtk_wed_rx_bm_alloc(dev);
++ if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev))
++ return;
+
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- if (!dev->tx_wdma[i].desc)
+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
+ if (!dev->rx_wdma[i].desc)
- mtk_wed_wdma_rx_ring_setup(dev, i, 16);
+ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
+
mtk_wed_hw_init(dev);
+@@ -1278,10 +1478,9 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ mtk_wed_set_ext_int(dev, true);
+
+ if (dev->hw->version == 1) {
+- u32 val;
+-
+- val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
+- FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID, dev->hw->index);
++ u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
++ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID,
++ dev->hw->index);
-@@ -1347,10 +1522,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- goto error;
+ val |= BIT(0) | (BIT(1) * !!dev->hw->index);
+ regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
+@@ -1353,10 +1552,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ goto out;
- if (dev->ver > MTK_WED_V1) {
-- ret = mtk_wed_rx_bm_alloc(dev);
+ if (mtk_wed_get_rx_capa(dev)) {
+- ret = mtk_wed_rx_buffer_alloc(dev);
- if (ret)
-- goto error;
+- goto out;
-
ret = mtk_wed_rro_alloc(dev);
if (ret)
- goto error;
-@@ -1358,6 +1529,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ goto out;
+@@ -1364,6 +1559,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
mtk_wed_hw_init_early(dev);
@@ -609,10 +645,23 @@
+ init_completion(&dev->wlan_reset_done);
+ atomic_set(&dev->fe_reset, 0);
+
- if (dev->ver == MTK_WED_V1)
+ if (hw->version == 1) {
regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
BIT(hw->index), 0);
-@@ -1374,7 +1549,8 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+@@ -1373,8 +1572,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ }
+
+ out:
+- if (ret)
+- mtk_wed_detach(dev);
++ if (ret) {
++ dev_err(dev->hw->dev, "failed to attach wed device\n");
++ __mtk_wed_detach(dev);
++ }
+ unlock:
+ mutex_unlock(&hw_lock);
+
+@@ -1382,7 +1583,8 @@ mtk_wed_attach(struct mtk_wed_device *dev)
}
static int
@@ -622,65 +671,52 @@
{
struct mtk_wed_ring *ring = &dev->tx_ring[idx];
-@@ -1392,10 +1568,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+@@ -1401,11 +1603,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
+ if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring)))
+ return -EINVAL;
- BUG_ON(idx > ARRAY_SIZE(dev->tx_ring));
-
-- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE, 1, true))
-- return -ENOMEM;
-+ if (!reset)
-+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
-+ 1, true))
-+ return -ENOMEM;
+- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
+- sizeof(*ring->desc), true))
++ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
++ sizeof(*ring->desc), true))
+ return -ENOMEM;
- if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-+ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
++ if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE,
++ reset))
return -ENOMEM;
ring->reg_base = MTK_WED_RING_TX(idx);
-@@ -1443,21 +1621,24 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+@@ -1450,18 +1653,20 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
}
static int
-mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
-+ int idx, void __iomem *regs, bool reset)
++mtk_wed_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs,
++ bool reset)
{
struct mtk_wed_ring *ring = &dev->rx_ring[idx];
- BUG_ON(idx > ARRAY_SIZE(dev->rx_ring));
+ if (WARN_ON(idx >= ARRAY_SIZE(dev->rx_ring)))
+ return -EINVAL;
-+ if (!reset)
-+ if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
-+ 1, false))
-+ return -ENOMEM;
+- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
+- sizeof(*ring->desc), false))
++ if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE,
++ sizeof(*ring->desc), false))
+ return -ENOMEM;
-- if (mtk_wed_ring_alloc(dev, ring, MTK_WED_RX_RING_SIZE, 1, false))
-- return -ENOMEM;
--
- if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
-+ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
++ if (mtk_wed_wdma_tx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE,
++ reset))
return -ENOMEM;
ring->reg_base = MTK_WED_RING_RX_DATA(idx);
- ring->wpdma = regs;
-+ dev->hw->ring_num = idx + 1;
-
- /* WPDMA -> WED */
- wpdma_rx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 8ef5253..490873c 100644
+index 1bfd96f..2ce1a5b 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
-@@ -47,6 +47,7 @@ struct mtk_wed_hw {
- u32 num_flows;
- u32 wdma_phy;
- char dirname[5];
-+ int ring_num;
- int irq;
- int index;
- u32 ver;
-@@ -158,6 +159,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+@@ -160,6 +160,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
void mtk_wed_exit(void);
int mtk_wed_flow_add(int index);
void mtk_wed_flow_remove(int index);
@@ -690,7 +726,7 @@
#else
static inline void
mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
-@@ -175,6 +179,13 @@ static inline int mtk_wed_flow_add(int index)
+@@ -178,6 +181,13 @@ static inline int mtk_wed_flow_add(int index)
static inline void mtk_wed_flow_remove(int index)
{
}
@@ -705,10 +741,10 @@
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 31871f7..403a36b 100644
+index a79305f..645b8b1 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -38,11 +38,15 @@ struct mtk_wdma_desc {
+@@ -32,11 +32,15 @@ struct mtk_wdma_desc {
#define MTK_WED_RESET 0x008
#define MTK_WED_RESET_TX_BM BIT(0)
@@ -724,20 +760,16 @@
#define MTK_WED_RESET_WDMA_RX_DRV BIT(17)
#define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
#define MTK_WED_RESET_RX_RRO_QM BIT(20)
-@@ -185,7 +189,12 @@ struct mtk_wdma_desc {
-
+@@ -174,6 +178,8 @@ struct mtk_wdma_desc {
#define MTK_WED_RESET_IDX 0x20c
#define MTK_WED_RESET_IDX_TX GENMASK(3, 0)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_RESET_IDX_RX GENMASK(7, 6)
-+#else
#define MTK_WED_RESET_IDX_RX GENMASK(17, 16)
-+#endif
++#define MTK_WED_RESET_IDX_RX_V2 GENMASK(7, 6)
+#define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30)
#define MTK_WED_TX_MIB(_n) (0x2a0 + (_n) * 4)
#define MTK_WED_RX_MIB(_n) (0x2e0 + (_n) * 4)
-@@ -299,6 +308,9 @@ struct mtk_wdma_desc {
+@@ -287,6 +293,9 @@ struct mtk_wdma_desc {
#define MTK_WED_WPDMA_RX_D_GLO_CFG 0x75c
#define MTK_WED_WPDMA_RX_D_RX_DRV_EN BIT(0)
@@ -748,10 +780,10 @@
#define MTK_WED_WPDMA_RX_D_RXD_READ_LEN GENMASK(31, 24)
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index e8fca31..98ed390 100644
+index 658f392..6772ea8 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -163,18 +163,23 @@ struct mtk_wed_device {
+@@ -151,16 +151,21 @@ struct mtk_wed_device {
void (*release_rx_buf)(struct mtk_wed_device *wed);
void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
struct mtk_wed_wo_rx_stats *stats);
@@ -769,60 +801,60 @@
int (*tx_ring_setup)(struct mtk_wed_device *dev, int ring,
- void __iomem *regs);
+ void __iomem *regs, bool reset);
- int (*txfree_ring_setup)(struct mtk_wed_device *dev,
- void __iomem *regs);
int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-- void __iomem *regs);
+- void __iomem *regs);
+ void __iomem *regs, bool reset);
+ int (*txfree_ring_setup)(struct mtk_wed_device *dev,
+ void __iomem *regs);
int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- void *data, int len);
- void (*detach)(struct mtk_wed_device *dev);
-@@ -228,12 +233,13 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+@@ -216,8 +221,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
#define mtk_wed_device_active(_dev) !!(_dev)->ops
#define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
#define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask)
-#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) \
- (_dev)->ops->tx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \
-+ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset)
++ (_dev)->ops->tx_ring_setup(_dev, _ring, _regs, _reset)
#define mtk_wed_device_txfree_ring_setup(_dev, _regs) \
(_dev)->ops->txfree_ring_setup(_dev, _regs)
--#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
-- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
-+ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset)
- #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
- (_dev)->ops->msg_update(_dev, _id, _msg, _len)
#define mtk_wed_device_reg_read(_dev, _reg) \
-@@ -244,6 +250,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+@@ -228,12 +233,14 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
(_dev)->ops->irq_get(_dev, _mask)
#define mtk_wed_device_irq_set_mask(_dev, _mask) \
(_dev)->ops->irq_set_mask(_dev, _mask)
-+#define mtk_wed_device_dma_reset(_dev) \
-+ (_dev)->ops->reset_dma(_dev)
+-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) \
+- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
++ (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, reset)
#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
(_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
+ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
++#define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
++#define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
#else
-@@ -253,14 +261,15 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -241,15 +248,17 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
}
#define mtk_wed_device_detach(_dev) do {} while (0)
#define mtk_wed_device_start(_dev, _mask) do {} while (0)
-#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_stop(_dev) do {} while (0)
+#define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
#define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
--#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
--#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
-+#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
#define mtk_wed_device_reg_read(_dev, _reg) 0
#define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
#define mtk_wed_device_irq_get(_dev, _mask) 0
#define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
-+#define mtk_wed_device_dma_reset(_dev) do {} while (0)
+-#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs) -ENODEV
++#define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
#define mtk_wed_device_ppe_check(_dev, _hash) do {} while (0)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
++#define mtk_wed_device_stop(_dev) do {} while (0)
++#define mtk_wed_device_dma_reset(_dev) do {} while (0)
#endif
+ #endif
--
2.18.0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
index b547328..18c6d2a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3010-ethernet-update-ppe-backward-compatible-two-way-hash.patch
@@ -1,7 +1,7 @@
-From 84fd451dd7379943e6957e9ceb749be4d6c41540 Mon Sep 17 00:00:00 2001
+From 7feee53fdfd481fc2beb02739ccd0e87f1c96b7a Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:07:14 +0800
-Subject: [PATCH 11/22] ethernet-update-ppe-backward-compatible-two-way-hash
+Subject: [PATCH 10/24] ethernet-update-ppe-backward-compatible-two-way-hash
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 ++++++++-
@@ -11,10 +11,10 @@
4 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index c1399c5..bd622d3 100644
+index a24b223..e8837b6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5252,7 +5252,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5799,7 +5799,8 @@ static int mtk_probe(struct platform_device *pdev)
for (i = 0; i < eth->ppe_num; i++) {
eth->ppe[i] = mtk_ppe_init(eth,
@@ -24,7 +24,7 @@
if (!eth->ppe[i]) {
err = -ENOMEM;
goto err_free_dev;
-@@ -5359,6 +5360,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5913,6 +5914,7 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -32,7 +32,7 @@
.offload_version = 2,
.rss_num = 0,
.txrx = {
-@@ -5377,6 +5379,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5931,6 +5933,7 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -40,7 +40,7 @@
.offload_version = 2,
.rss_num = 0,
.txrx = {
-@@ -5396,6 +5399,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5950,6 +5953,7 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -48,7 +48,7 @@
.offload_version = 2,
.rss_num = 0,
.txrx = {
-@@ -5414,6 +5418,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5968,6 +5972,7 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -56,7 +56,7 @@
.offload_version = 2,
.rss_num = 0,
.txrx = {
-@@ -5451,6 +5456,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6005,6 +6010,7 @@ static const struct mtk_soc_data mt7986_data = {
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -64,7 +64,7 @@
.offload_version = 2,
.rss_num = 4,
.txrx = {
-@@ -5470,6 +5476,8 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6024,6 +6030,8 @@ static const struct mtk_soc_data mt7981_data = {
.required_clks = MT7981_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -74,10 +74,10 @@
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma_v2),
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 960b979..68b8ab1 100644
+index 9099dea..b4f04e2 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1679,6 +1679,7 @@ struct mtk_soc_data {
+@@ -1732,6 +1732,7 @@ struct mtk_soc_data {
u64 caps;
u64 required_clks;
bool required_pctl;
@@ -86,7 +86,7 @@
netdev_features_t hw_features;
bool has_sram;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 96c15b3..4da7e7a 100755
+index c9ee505..569bf34 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -88,7 +88,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
index c516fd6..6a2a6f6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
@@ -1,7 +1,7 @@
-From 77bdae190ded4dfafa80dfaf04a77018e33e233c Mon Sep 17 00:00:00 2001
+From 4eaba588e0c730d6188f5f1b667a55d1b9ca0fe6 Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:09:23 +0800
-Subject: [PATCH 12/22] flow-offload-add-mtkhnat-flow-accounting
+Subject: [PATCH 11/24] flow-offload-add-mtkhnat-flow-accounting
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 +-
@@ -15,10 +15,10 @@
8 files changed, 191 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index bd622d3..9d8ce07 100644
+index e8837b6..9cd306d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5253,7 +5253,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5800,7 +5800,8 @@ static int mtk_probe(struct platform_device *pdev)
for (i = 0; i < eth->ppe_num; i++) {
eth->ppe[i] = mtk_ppe_init(eth,
eth->base + MTK_ETH_PPE_BASE + i * 0x400,
@@ -28,7 +28,7 @@
if (!eth->ppe[i]) {
err = -ENOMEM;
goto err_free_dev;
-@@ -5360,6 +5361,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5914,6 +5915,7 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -36,7 +36,7 @@
.hash_way = 2,
.offload_version = 2,
.rss_num = 0,
-@@ -5379,6 +5381,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5933,6 +5935,7 @@ static const struct mtk_soc_data mt7621_data = {
.required_clks = MT7621_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -44,7 +44,7 @@
.hash_way = 2,
.offload_version = 2,
.rss_num = 0,
-@@ -5399,6 +5402,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5953,6 +5956,7 @@ static const struct mtk_soc_data mt7622_data = {
.required_clks = MT7622_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -52,7 +52,7 @@
.hash_way = 2,
.offload_version = 2,
.rss_num = 0,
-@@ -5418,6 +5422,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5972,6 +5976,7 @@ static const struct mtk_soc_data mt7623_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.has_sram = false,
@@ -60,7 +60,7 @@
.hash_way = 2,
.offload_version = 2,
.rss_num = 0,
-@@ -5438,6 +5443,7 @@ static const struct mtk_soc_data mt7629_data = {
+@@ -5992,6 +5997,7 @@ static const struct mtk_soc_data mt7629_data = {
.required_clks = MT7629_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -68,7 +68,7 @@
.rss_num = 0,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
-@@ -5456,6 +5462,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6010,6 +6016,7 @@ static const struct mtk_soc_data mt7986_data = {
.required_clks = MT7986_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -76,7 +76,7 @@
.hash_way = 4,
.offload_version = 2,
.rss_num = 4,
-@@ -5476,6 +5483,7 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6030,6 +6037,7 @@ static const struct mtk_soc_data mt7981_data = {
.required_clks = MT7981_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -84,7 +84,7 @@
.hash_way = 4,
.offload_version = 2,
.rss_num = 4,
-@@ -5513,6 +5521,7 @@ static const struct mtk_soc_data rt5350_data = {
+@@ -6067,6 +6075,7 @@ static const struct mtk_soc_data rt5350_data = {
.required_clks = MT7628_CLKS_BITMAP,
.required_pctl = false,
.has_sram = false,
@@ -93,10 +93,10 @@
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 68b8ab1..101c233 100644
+index b4f04e2..5f90765 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1683,6 +1683,7 @@ struct mtk_soc_data {
+@@ -1736,6 +1736,7 @@ struct mtk_soc_data {
u8 offload_version;
netdev_features_t hw_features;
bool has_sram;
@@ -105,7 +105,7 @@
u32 txd_size;
u32 rxd_size;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 4da7e7a..f55a95c 100755
+index 569bf34..94e03b2 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_ppe *ppe)
@@ -446,10 +446,10 @@
#define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
#define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)
diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
-index 2cab008..1defb15 100644
+index e4c7db9..aae37f5 100644
--- a/net/netfilter/xt_FLOWOFFLOAD.c
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -766,7 +766,7 @@ static int __init xt_flowoffload_tg_init(void)
+@@ -772,7 +772,7 @@ static int __init xt_flowoffload_tg_init(void)
if (ret)
goto cleanup;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
index d51f24f..4110b83 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3012-flow-offload-add-mtkhnat-qdma-qos.patch
@@ -1,19 +1,19 @@
-From 9e21d6fa97e93cb2ba9b923810666ddaf7a981ee Mon Sep 17 00:00:00 2001
+From 0247c9d63f56bbe34f4205f986957b5036a9a4d8 Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:11:03 +0800
-Subject: [PATCH 13/22] flow-offload-add-mtkhnat-qdma-qos
+Subject: [PATCH 12/24] flow-offload-add-mtkhnat-qdma-qos
---
drivers/net/ethernet/mediatek/Makefile | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 ++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 50 ++
drivers/net/ethernet/mediatek/mtk_ppe.c | 48 +-
drivers/net/ethernet/mediatek/mtk_ppe.h | 4 +
.../net/ethernet/mediatek/mtk_ppe_offload.c | 28 +-
.../net/ethernet/mediatek/mtk_qdma_debugfs.c | 439 ++++++++++++++++++
include/net/flow_offload.h | 1 +
net/netfilter/nf_flow_table_offload.c | 4 +-
- 9 files changed, 593 insertions(+), 6 deletions(-)
+ 9 files changed, 581 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
@@ -30,10 +30,10 @@
ifdef CONFIG_DEBUG_FS
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 9d8ce07..0f6613b 100644
+index 9cd306d..1660fd9 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5266,6 +5266,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5813,6 +5813,8 @@ static int mtk_probe(struct platform_device *pdev)
}
mtk_ppe_debugfs_init(eth);
@@ -42,7 +42,7 @@
}
for (i = 0; i < MTK_MAX_DEVS; i++) {
-@@ -5371,6 +5373,7 @@ static const struct mtk_soc_data mt2701_data = {
+@@ -5925,6 +5927,7 @@ static const struct mtk_soc_data mt2701_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -50,7 +50,7 @@
},
};
-@@ -5391,6 +5394,7 @@ static const struct mtk_soc_data mt7621_data = {
+@@ -5945,6 +5948,7 @@ static const struct mtk_soc_data mt7621_data = {
.rxd_size = sizeof(struct mtk_rx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -58,7 +58,7 @@
},
};
-@@ -5412,6 +5416,7 @@ static const struct mtk_soc_data mt7622_data = {
+@@ -5966,6 +5970,7 @@ static const struct mtk_soc_data mt7622_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -66,7 +66,7 @@
},
};
-@@ -5432,6 +5437,7 @@ static const struct mtk_soc_data mt7623_data = {
+@@ -5986,6 +5991,7 @@ static const struct mtk_soc_data mt7623_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -74,7 +74,7 @@
},
};
-@@ -5472,6 +5478,7 @@ static const struct mtk_soc_data mt7986_data = {
+@@ -6026,6 +6032,7 @@ static const struct mtk_soc_data mt7986_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -82,7 +82,7 @@
},
};
-@@ -5493,6 +5500,7 @@ static const struct mtk_soc_data mt7981_data = {
+@@ -6047,6 +6054,7 @@ static const struct mtk_soc_data mt7981_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -90,7 +90,7 @@
},
};
-@@ -5511,6 +5519,7 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -6065,6 +6073,7 @@ static const struct mtk_soc_data mt7988_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT_V2,
@@ -98,7 +98,7 @@
},
};
-@@ -5529,6 +5538,7 @@ static const struct mtk_soc_data rt5350_data = {
+@@ -6083,6 +6092,7 @@ static const struct mtk_soc_data rt5350_data = {
.rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = MTK_TX_DMA_BUF_SHIFT,
@@ -107,10 +107,10 @@
};
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 101c233..7ea380e 100644
+index 5f90765..02ca0b2 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -458,6 +471,9 @@
+@@ -487,6 +487,9 @@
#define FC_THRES_DROP_EN (7 << 16)
#define FC_THRES_MIN 0x4444
@@ -120,7 +120,7 @@
/* QDMA Interrupt Status Register */
#define MTK_QDMA_INT_STATUS (QDMA_BASE + 0x218)
#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-@@ -494,6 +510,11 @@
+@@ -530,6 +533,11 @@
/* QDMA Interrupt Mask Register */
#define MTK_QDMA_HRED2 (QDMA_BASE + 0x244)
@@ -132,7 +132,7 @@
/* QDMA TX Forward CPU Pointer Register */
#define MTK_QTX_CTX_PTR (QDMA_BASE +0x300)
-@@ -521,6 +542,14 @@
+@@ -557,6 +565,14 @@
/* QDMA FQ Free Page Buffer Length Register */
#define MTK_QDMA_FQ_BLEN (QDMA_BASE +0x32c)
@@ -147,7 +147,7 @@
/* WDMA Registers */
#define MTK_WDMA_CTX_PTR(x) (WDMA_BASE(x) + 0x8)
#define MTK_WDMA_DTX_PTR(x) (WDMA_BASE(x) + 0xC)
-@@ -1690,6 +1719,7 @@ struct mtk_soc_data {
+@@ -1743,6 +1759,7 @@ struct mtk_soc_data {
u32 rx_dma_l4_valid;
u32 dma_max_len;
u32 dma_len_offset;
@@ -155,7 +155,7 @@
} txrx;
};
-@@ -1879,6 +1909,7 @@ struct mtk_eth {
+@@ -1936,6 +1953,7 @@ struct mtk_eth {
spinlock_t syscfg0_lock;
struct timer_list mtk_dma_monitor_timer;
@@ -163,7 +163,7 @@
u8 ppe_num;
struct mtk_ppe *ppe[MTK_MAX_PPE_NUM];
struct rhashtable flow_table;
-@@ -1936,6 +1967,36 @@ extern const struct of_device_id of_mtk_match[];
+@@ -1994,6 +2012,36 @@ extern const struct of_device_id of_mtk_match[];
extern u32 mtk_hwlro_stats_ebl;
extern u32 dbg_show_level;
@@ -200,7 +200,7 @@
/* read the hardware status register */
void mtk_stats_update_mac(struct mtk_mac *mac);
-@@ -1969,4 +2028,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+@@ -2027,4 +2075,6 @@ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
int mtk_ppe_debugfs_init(struct mtk_eth *eth);
@@ -208,7 +208,7 @@
+int mtk_qdma_debugfs_init(struct mtk_eth *eth);
#endif /* MTK_ETH_H */
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index f55a95c..6d6c1e4 100755
+index 94e03b2..8388f65 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -128,7 +128,7 @@ static void mtk_ppe_cache_enable(struct mtk_ppe *ppe, bool enable)
@@ -366,7 +366,7 @@
return err;
diff --git a/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
new file mode 100644
-index 0000000..3a7c585
+index 0000000..d76b3c5
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/mtk_qdma_debugfs.c
@@ -0,0 +1,439 @@
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-ovs-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-ovs-support.patch
index a164d1a..5220a63 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-ovs-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3013-flow-offload-ovs-support.patch
@@ -1,7 +1,7 @@
-From 842a435bd21807447504a387e5ebb8071b0db93f Mon Sep 17 00:00:00 2001
+From f3112e335a7f95aeb3d834962de813baadc1f620 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Mon, 18 Sep 2023 11:11:41 +0800
-Subject: [PATCH 14/22] flow-offload-ovs-support
+Subject: [PATCH 13/24] flow-offload-ovs-support
---
net/openvswitch/vport-internal_dev.c | 46 ++++++++++++++++++++++++++++
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
index 89e664f..a23233f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
@@ -1,7 +1,7 @@
-From 120baca4e8b019d03c8d1a29012cea911629247a Mon Sep 17 00:00:00 2001
+From 552ae5e27e936eb74dd563485ab77f40b96a61a5 Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:13:51 +0800
-Subject: [PATCH 15/22] update-net-bridge-for-bridger
+Subject: [PATCH 14/24] update-net-bridge-for-bridger
---
include/net/switchdev.h | 2 +
@@ -1805,10 +1805,10 @@
+ return false;
+}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index da1ef00..b896f71 100644
+index 4eed989..de75eb2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
-@@ -1998,6 +1998,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -2004,6 +2004,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
goto cont;
if (idx < s_idx)
goto cont;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
index bedf09e..b6c0d41 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
@@ -1,44 +1,31 @@
-From 5481f7ecbd3cfffd8234bc8e952a6e07f42de76c Mon Sep 17 00:00:00 2001
+From aaac91720ca1fd7679896286eac2b014e7150fca Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Tue, 21 Nov 2023 16:42:01 +0800
-Subject: [PATCH 16/22] ethernet-update-ppe-from-netsys2-to-netsys3
+Date: Mon, 18 Mar 2024 16:35:07 +0800
+Subject: [PATCH 15/24] ethernet-update-ppe-from-netsys2-to-netsys3
---
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +++-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++--
drivers/net/ethernet/mediatek/mtk_ppe.c | 35 ++++++++++++++---
drivers/net/ethernet/mediatek/mtk_ppe.h | 38 ++++++++++++++++---
.../net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++-
drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 7 ++++
- 6 files changed, 85 insertions(+), 22 deletions(-)
+ 6 files changed, 82 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 850bc4f..8910d40 100644
+index 952bf51..f477ff3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2248,17 +2248,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2447,7 +2447,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
-#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
-- hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2;
+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2;
- #else
-- hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
-+ hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
- #endif
- if (hash != MTK_RXD4_FOE_ENTRY) {
- hash = jhash_1word(hash, 0);
- skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);
- }
-
--#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
-+#if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2;
reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
- for (i = 0; i < eth->ppe_num; i++) {
-@@ -5290,7 +5290,8 @@ static int mtk_probe(struct platform_device *pdev)
+ if (hash != MTK_RXD5_FOE_ENTRY_V2) {
+@@ -5798,7 +5798,8 @@ static int mtk_probe(struct platform_device *pdev)
for (i = 0; i < eth->ppe_num; i++) {
eth->ppe[i] = mtk_ppe_init(eth,
@@ -48,7 +35,7 @@
2, eth->soc->hash_way, i,
eth->soc->has_accounting);
if (!eth->ppe[i]) {
-@@ -5557,6 +5558,9 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -6065,6 +6066,9 @@ static const struct mtk_soc_data mt7988_data = {
.required_clks = MT7988_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
@@ -59,10 +46,10 @@
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma_v2),
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 9c77f14..c7d36c5 100644
+index 58547af..9c46ac1 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -134,9 +134,10 @@
+@@ -137,9 +137,10 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -74,7 +61,7 @@
#else
#define MTK_GDMA_TO_PPE0 0x4444
#endif
-@@ -1978,14 +1979,14 @@ extern u32 dbg_show_level;
+@@ -2018,14 +2019,14 @@ extern u32 dbg_show_level;
static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
{
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
index 121db94..14639c4 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3016-mediatek-ethernet-add-wifi2wifi-offload-support.patch
@@ -1,21 +1,21 @@
-From d3183ad9ed0a8a35047a37f30d85f920a729897c Mon Sep 17 00:00:00 2001
+From 743b10e8e2a17c904f27cf78d46aea64193fc41c Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:16:18 +0800
-Subject: [PATCH 17/22] mediatek-ethernet-add-wifi2wifi-offload-support
+Subject: [PATCH 16/24] mediatek-ethernet-add-wifi2wifi-offload-support
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
.../net/ethernet/mediatek/mtk_ppe_offload.c | 35 +++++++++++++------
drivers/net/ethernet/mediatek/mtk_wed.c | 13 +++++++
- include/linux/soc/mediatek/mtk_wed.h | 6 +++-
- 4 files changed, 45 insertions(+), 11 deletions(-)
+ include/linux/soc/mediatek/mtk_wed.h | 5 +++
+ 4 files changed, 45 insertions(+), 10 deletions(-)
mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe_offload.c
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 23c5f49..ee89b4c 100644
+index f9dda59..88d2f46 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -2027,6 +2027,8 @@ void mtk_usxgmii_link_poll(struct work_struct *work);
+@@ -2072,6 +2072,8 @@ void mtk_usxgmii_link_poll(struct work_struct *work);
int mtk_eth_offload_init(struct mtk_eth *eth, int id);
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data);
@@ -100,15 +100,15 @@
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index ae31412..3e760f7 100644
+index 5dd1182..68eedd3 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -1733,6 +1733,18 @@ void mtk_wed_flow_remove(int index)
+@@ -1766,6 +1766,18 @@ void mtk_wed_flow_remove(int index)
mutex_unlock(&hw_lock);
}
+static int mtk_wed_eth_setup_tc(struct mtk_wed_device *wed, struct net_device *dev,
-+ int type, void *type_data)
++ int type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_BLOCK:
@@ -120,9 +120,9 @@
+}
+
void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- void __iomem *wdma, u32 wdma_phy, int index)
-
-@@ -1751,6 +1763,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ void __iomem *wdma, phys_addr_t wdma_phy,
+ int index)
+@@ -1785,6 +1797,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
.irq_get = mtk_wed_irq_get,
.irq_set_mask = mtk_wed_irq_set_mask,
.detach = mtk_wed_detach,
@@ -131,36 +131,35 @@
};
struct device_node *eth_np = eth->dev->of_node;
diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 98ed390..27cf284 100644
+index 6772ea8..470beb2 100644
--- a/include/linux/soc/mediatek/mtk_wed.h
+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -183,7 +183,8 @@ struct mtk_wed_ops {
- int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- void *data, int len);
+@@ -173,6 +173,8 @@ struct mtk_wed_ops {
void (*detach)(struct mtk_wed_device *dev);
--
+ void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
+ u32 reason, u32 hash);
+ int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
-+ int type, void *type_data);
++ int type, void *type_data);
+
void (*stop)(struct mtk_wed_device *dev);
void (*start)(struct mtk_wed_device *dev, u32 irq_mask);
- void (*reset_dma)(struct mtk_wed_device *dev);
-@@ -232,6 +233,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- #define mtk_wed_device_active(_dev) !!(_dev)->ops
- #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
+@@ -241,6 +243,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ (_dev)->ops->msg_update(_dev, _id, _msg, _len)
+ #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
+#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
+ (_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
- #define mtk_wed_device_start(_dev, _mask) (_dev)->ops->start(_dev, _mask)
- #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) \
-@@ -270,6 +273,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_irq_get(_dev, _mask) 0
- #define mtk_wed_device_irq_set_mask(_dev, _mask) do {} while (0)
+ #else
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -259,6 +263,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
+ #define mtk_wed_device_stop(_dev) do {} while (0)
#define mtk_wed_device_dma_reset(_dev) do {} while (0)
+#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
- #define mtk_wed_device_ppe_check(_dev, _hash) do {} while (0)
#endif
+ #endif
--
2.18.0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-flow-offload-add-mtkhnat-dscp.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-flow-offload-add-mtkhnat-dscp.patch
index 478a7a9..070bb7c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-flow-offload-add-mtkhnat-dscp.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3017-flow-offload-add-mtkhnat-dscp.patch
@@ -1,7 +1,7 @@
-From 3e4d44d8da90b9ba20abc5cec255d92b67e3fb00 Mon Sep 17 00:00:00 2001
+From 8c918e858df4b7cb12ea185acf23e83bae883cd2 Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 11:17:24 +0800
-Subject: [PATCH 18/22] flow-offload-add-mtkhnat-dscp
+Subject: [PATCH 17/24] flow-offload-add-mtkhnat-dscp
---
drivers/net/ethernet/mediatek/mtk_ppe.c | 11 +++++++
@@ -13,10 +13,10 @@
6 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 446acca..384e811 100755
+index 184e29d..0e9c0bd 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -435,6 +435,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+@@ -446,6 +446,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
return 0;
}
@@ -84,10 +84,10 @@
err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index feac793..97a277d 100644
+index 7374cb2..d5dd3fe 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
-@@ -36,6 +36,7 @@ struct nf_flow_key {
+@@ -38,6 +38,7 @@ struct nf_flow_key {
};
struct flow_dissector_key_tcp tcp;
struct flow_dissector_key_ports tp;
@@ -95,7 +95,7 @@
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
struct nf_flow_match {
-@@ -145,6 +146,7 @@ struct flow_offload_tuple {
+@@ -147,6 +148,7 @@ struct flow_offload_tuple {
u8 h_dest[ETH_ALEN];
} out;
};
@@ -132,7 +132,7 @@
}
diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
-index 1defb15..d4aecab 100644
+index aae37f5..5364a32 100644
--- a/net/netfilter/xt_FLOWOFFLOAD.c
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
@@ -49,6 +49,35 @@ static DEFINE_SPINLOCK(hooks_lock);
@@ -171,7 +171,7 @@
static unsigned int
xt_flowoffload_net_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
-@@ -617,6 +646,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+@@ -623,6 +652,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
if (flow_offload_route_init(flow, &route) < 0)
goto err_flow_add;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-flow-offload-add-mtkhnat-netlink.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-flow-offload-add-mtkhnat-netlink.patch
index 3bb7e7a..ff6f58f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-flow-offload-add-mtkhnat-netlink.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3018-flow-offload-add-mtkhnat-netlink.patch
@@ -1,7 +1,7 @@
-From 6bda18f107acbf04f01c18ad5964be6f7404d3cf Mon Sep 17 00:00:00 2001
+From 122cb2a2ae7ececd20412083b5bb9bfd6f9c8d26 Mon Sep 17 00:00:00 2001
From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 18 Sep 2023 13:14:08 +0800
-Subject: [PATCH 19/22] flow-offload-add-mtkhnat-netlink
+Subject: [PATCH 18/24] flow-offload-add-mtkhnat-netlink
---
include/net/netfilter/nf_flow_table.h | 1 +
@@ -14,10 +14,10 @@
create mode 100644 net/netfilter/nf_flow_table_netlink.c
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
-index 97a277d..3490d90 100644
+index d5dd3fe..f2bce73 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
-@@ -277,6 +277,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
+@@ -279,6 +279,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
void nf_flow_table_free(struct nf_flowtable *flow_table);
void flow_offload_teardown(struct flow_offload *flow);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch
new file mode 100644
index 0000000..9307157
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3019-mtk-wed-add-wed3-support.patch
@@ -0,0 +1,3873 @@
+From da90def8adfa6139e8710c282a41024cfc4b23b3 Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Mon, 18 Sep 2023 13:21:15 +0800
+Subject: [PATCH] mtk:wed:add wed3 support
+
+---
+ arch/arm64/boot/dts/mediatek/mt7988.dtsi | 152 +-
+ .../dts/mediatek/mt7988a-dsa-10g-spim-nor.dts | 16 +-
+ .../dts/mediatek/mt7988d-dsa-10g-spim-nor.dts | 16 +-
+ drivers/net/ethernet/mediatek/mtk_ppe.c | 17 +-
+ drivers/net/ethernet/mediatek/mtk_ppe.h | 2 +-
+ .../net/ethernet/mediatek/mtk_ppe_offload.c | 9 +-
+ drivers/net/ethernet/mediatek/mtk_wed.c | 1228 +++++++++++++----
+ drivers/net/ethernet/mediatek/mtk_wed.h | 73 +-
+ .../net/ethernet/mediatek/mtk_wed_debugfs.c | 584 +++++++-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 40 +-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 7 +-
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 353 ++++-
+ include/linux/netdevice.h | 7 +
+ include/linux/soc/mediatek/mtk_wed.h | 77 +-
+ 14 files changed, 2161 insertions(+), 420 deletions(-)
+ mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+index 7e96640..3368240 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+@@ -193,44 +193,49 @@
+ status = "disabled";
+ };
+
+- wed: wed@15010000 {
+- compatible = "mediatek,wed";
+- wed_num = <3>;
+- /* add this property for wed get the pci slot number. */
+- pci_slot_map = <0>, <1>, <2>;
+- reg = <0 0x15010000 0 0x2000>,
+- <0 0x15012000 0 0x2000>,
+- <0 0x15014000 0 0x2000>;
++ wed0: wed@15010000 {
++ compatible = "mediatek,mt7988-wed",
++ "syscon";
++ reg = <0 0x15010000 0 0x2000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+- };
+-
+- wed2: wed2@15012000 {
+- compatible = "mediatek,wed2";
+- wed_num = <3>;
+- /* add this property for wed get the pci slot number. */
+- reg = <0 0x15010000 0 0x2000>,
+- <0 0x15012000 0 0x2000>,
+- <0 0x15014000 0 0x2000>;
++ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
++ mediatek,wed_pcie = <&wed_pcie>;
++ mediatek,ap2woccif = <&ap2woccif0>;
++ mediatek,wocpu_ilm = <&wocpu0_ilm>;
++ mediatek,wocpu_dlm = <&wocpu0_dlm>;
++ mediatek,wocpu_boot = <&cpu0_boot>;
++ mediatek,wocpu_emi = <&wocpu0_emi>;
++ mediatek,wocpu_data = <&wocpu_data>;
++ };
++
++ wed1: wed@15012000 {
++ compatible = "mediatek,mt7988-wed",
++ "syscon";
++ reg = <0 0x15012000 0 0x2000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+- };
+-
+- wed3: wed3@15014000 {
+- compatible = "mediatek,wed3";
+- wed_num = <3>;
+- /* add this property for wed get the pci slot number. */
+- reg = <0 0x15010000 0 0x2000>,
+- <0 0x15012000 0 0x2000>,
+- <0 0x15014000 0 0x2000>;
++ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
++ mediatek,wed_pcie = <&wed_pcie>;
++ mediatek,ap2woccif = <&ap2woccif1>;
++ mediatek,wocpu_ilm = <&wocpu1_ilm>;
++ mediatek,wocpu_dlm = <&wocpu1_dlm>;
++ mediatek,wocpu_boot = <&cpu1_boot>;
++ mediatek,wocpu_emi = <&wocpu1_emi>;
++ mediatek,wocpu_data = <&wocpu_data>;
++ };
++
++ wed2: wed@15014000 {
++ compatible = "mediatek,mt7988-wed",
++ "syscon";
++ reg = <0 0x15014000 0 0x2000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
++ mediatek,wed_pcie = <&wed_pcie>;
++ mediatek,ap2woccif = <&ap2woccif2>;
++ mediatek,wocpu_ilm = <&wocpu2_ilm>;
++ mediatek,wocpu_dlm = <&wocpu2_dlm>;
++ mediatek,wocpu_boot = <&cpu2_boot>;
++ mediatek,wocpu_emi = <&wocpu2_emi>;
++ mediatek,wocpu_data = <&wocpu_data>;
+ };
+
+ wdma: wdma@15104800 {
+@@ -240,15 +245,25 @@
+ <0 0x15105000 0 0x400>;
+ };
+
+- ap2woccif: ap2woccif@151A5000 {
+- compatible = "mediatek,ap2woccif";
+- reg = <0 0x151A5000 0 0x1000>,
+- <0 0x152A5000 0 0x1000>,
+- <0 0x153A5000 0 0x1000>;
++ ap2woccif0: ap2woccif@151A5000 {
++ compatible = "mediatek,ap2woccif", "syscon";
++ reg = <0 0x151A5000 0 0x1000>;
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ ap2woccif1: ap2woccif@152A5000 {
++ compatible = "mediatek,ap2woccif", "syscon";
++ reg = <0 0x152A5000 0 0x1000>;
+ interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ ap2woccif2: ap2woccif@153A5000 {
++ compatible = "mediatek,ap2woccif", "syscon";
++ reg = <0 0x153A5000 0 0x1000>;
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wocpu0_ilm: wocpu0_ilm@151E0000 {
+@@ -256,31 +271,53 @@
+ reg = <0 0x151E0000 0 0x8000>;
+ };
+
+- wocpu1_ilm: wocpu1_ilm@152E0000 {
+- compatible = "mediatek,wocpu1_ilm";
++ wocpu1_ilm: wocpu_ilm@152E0000 {
++ compatible = "mediatek,wocpu_ilm";
+ reg = <0 0x152E0000 0 0x8000>;
+ };
+
+- wocpu2_ilm: wocpu2_ilm@153E0000 {
+- compatible = "mediatek,wocpu2_ilm";
+- reg = <0 0x153E0000 0 0x8000>;
++ wocpu2_ilm: wocpu_ilm@153E0000 {
++ compatible = "mediatek,wocpu_ilm";
++ reg = <0 0x153E0000 0 0x8000>;
++ };
++
++ wocpu0_dlm: wocpu_dlm@151E8000 {
++ compatible = "mediatek,wocpu_dlm";
++ reg = <0 0x151E8000 0 0x2000>;
++
++ resets = <ðsysrst 0>;
++ reset-names = "wocpu_rst";
++ };
++
++ wocpu1_dlm: wocpu_dlm@0x152E8000 {
++ compatible = "mediatek,wocpu_dlm";
++ reg = <0 0x152E8000 0 0x2000>;
++
++ resets = <ðsysrst 0>;
++ reset-names = "wocpu_rst";
+ };
+
+- wocpu_dlm: wocpu_dlm@151E8000 {
++ wocpu2_dlm: wocpu_dlm@0x153E8000 {
+ compatible = "mediatek,wocpu_dlm";
+- reg = <0 0x151E8000 0 0x2000>,
+- <0 0x152E8000 0 0x2000>,
+- <0 0x153E8000 0 0x2000>;
++ reg = <0 0x153E8000 0 0x2000>;
+
+ resets = <ðsysrst 0>;
+ reset-names = "wocpu_rst";
+ };
+
+- cpu_boot: wocpu_boot@15194000 {
+- compatible = "mediatek,wocpu_boot";
+- reg = <0 0x15194000 0 0x1000>,
+- <0 0x15294000 0 0x1000>,
+- <0 0x15394000 0 0x1000>;
++ cpu0_boot: wocpu_boot@15194000 {
++ compatible = "mediatek,wocpu0_boot";
++ reg = <0 0x15194000 0 0x1000>;
++ };
++
++ cpu1_boot: wocpu_boot@15294000 {
++ compatible = "mediatek,wocpu1_boot";
++ reg = <0 0x15294000 0 0x1000>;
++ };
++
++ cpu2_boot: wocpu_boot@15394000 {
++ compatible = "mediatek,wocpu2_boot";
++ reg = <0 0x15394000 0 0x1000>;
+ };
+
+ reserved-memory {
+@@ -901,6 +938,7 @@
+ <&topckgen CK_TOP_CB_NET2_D2>;
+ mediatek,ethsys = <ðsys>;
+ mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
++ mediatek,wed = <&wed0>, <&wed1>, <&wed2>;
+ mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
+ mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
+ mediatek,xfi_pll = <&xfi_pll>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+index a22af29..9169188 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+@@ -372,9 +372,23 @@
+ status = "okay";
+ };
+
+-&wed {
++&wed0 {
+ dy_txbm_enable = "true";
+ dy_txbm_budge = <8>;
+ txbm_init_sz = <10>;
+ status = "okay";
+ };
++
++&wed1 {
++ dy_txbm_enable = "true";
++ dy_txbm_budge = <8>;
++ txbm_init_sz = <10>;
++ status = "okay";
++};
++
++&wed2 {
++ dy_txbm_enable = "true";
++ dy_txbm_budge = <8>;
++ txbm_init_sz = <10>;
++ status = "okay";
++};
+\ No newline at end of file
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+index effcfd8..30e4846 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+@@ -382,9 +382,23 @@
+ status = "okay";
+ };
+
+-&wed {
++&wed0 {
+ dy_txbm_enable = "true";
+ dy_txbm_budge = <8>;
+ txbm_init_sz = <10>;
+ status = "okay";
+ };
++
++&wed1 {
++ dy_txbm_enable = "true";
++ dy_txbm_budge = <8>;
++ txbm_init_sz = <10>;
++ status = "okay";
++};
++
++&wed2 {
++ dy_txbm_enable = "true";
++ dy_txbm_budge = <8>;
++ txbm_init_sz = <10>;
++ status = "okay";
++};
+\ No newline at end of file
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+old mode 100755
+new mode 100644
+index 0e9c0bd..ae0acd5
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -9,6 +9,7 @@
+ #include <linux/if_ether.h>
+ #include <linux/if_vlan.h>
+ #include <net/dsa.h>
++#include <net/route.h>
+ #include "mtk_eth_soc.h"
+ #include "mtk_ppe.h"
+ #include "mtk_ppe_regs.h"
+@@ -407,7 +408,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
+ }
+
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+- int bss, int wcid)
++ int bss, int wcid, bool amsdu_en)
+ {
+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
+ u32 *ib2 = mtk_foe_entry_ib2(entry);
+@@ -419,6 +420,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+
+ l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
+ FIELD_PREP(MTK_FOE_WINFO_BSS, bss);
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ l2->winfo_pao = FIELD_PREP(MTK_FOE_WINFO_PAO_AMSDU_EN, amsdu_en);
++#endif
+ #else
+ if (wdma_idx)
+ *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
+@@ -454,6 +458,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
+ *ib2 &= ~MTK_FOE_IB2_DSCP;
+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
++
++ if (*ib2 & MTK_FOE_IB2_WDMA_WINFO &&
++ l2->winfo_pao & MTK_FOE_WINFO_PAO_AMSDU_EN) {
++ u8 tid = (dscp >> 5) & 0xf;
++
++ l2->winfo_pao |= FIELD_PREP(MTK_FOE_WINFO_PAO_TID, tid);
++ }
++#endif
++
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
+index 2a8b6ef..66c7f10 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
+@@ -428,7 +428,7 @@ int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
+ int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
+ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+- int bss, int wcid);
++ int bss, int wcid, bool amsdu_en);
+ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
+ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
+ bool mtk_foe_entry_match(struct mtk_foe_entry *entry, struct mtk_foe_entry *data);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index 95174b7..2d432f2 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -112,6 +112,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
+ info->queue = path.mtk_wdma.queue;
+ info->bss = path.mtk_wdma.bss;
+ info->wcid = path.mtk_wdma.wcid;
++ info->amsdu = path.mtk_wdma.amsdu;
+
+ return 0;
+ }
+@@ -193,13 +194,15 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
+
+ if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
+ mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
+- info.wcid);
++ info.wcid, info.amsdu);
+ pse_port = PSE_PPE0_PORT;
+ #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
+ if (info.wdma_idx == 0)
+ pse_port = PSE_WDMA0_PORT;
+ else if (info.wdma_idx == 1)
+ pse_port = PSE_WDMA1_PORT;
++ else if (info.wdma_idx == 2)
++ pse_port = PSE_WDMA2_PORT;
+ else
+ return -EOPNOTSUPP;
+ #endif
+@@ -481,8 +484,6 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ if (data.pppoe.num == 1)
+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
+
+- mtk_foe_entry_set_dscp(&foe, dscp);
+-
+ mtk_foe_entry_set_sp(eth->ppe[ppe_index], &foe);
+
+ err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
+@@ -490,6 +491,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ if (err)
+ return err;
+
++ mtk_foe_entry_set_dscp(&foe, dscp);
++
+ if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
+ return err;
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index a7d2166..92df014 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -23,9 +23,45 @@
+ #include "mtk_wed_mcu.h"
+ #include "mtk_wed_wo.h"
+
+-static struct mtk_wed_hw *hw_list[2];
++#define MTK_WED_AMSDU_BUF_SIZE (PAGE_SIZE << 4)
++#define MTK_WED_AMSDU_NPAGES 32
++
++static struct mtk_wed_hw *hw_list[3];
+ static DEFINE_MUTEX(hw_lock);
+
++static const struct mtk_wed_soc_data mt7622_data = {
++ .regmap = {
++ .tx_bm_tkid = 0x088,
++ .wpdma_rx_ring0 = 0x770,
++ .reset_idx_tx_mask = GENMASK(3, 0),
++ .reset_idx_rx_mask = GENMASK(17, 16),
++ },
++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc),
++ .wdma_desc_size = sizeof(struct mtk_wdma_desc),
++};
++
++static const struct mtk_wed_soc_data mt7986_data = {
++ .regmap = {
++ .tx_bm_tkid = 0x0c8,
++ .wpdma_rx_ring0 = 0x770,
++ .reset_idx_tx_mask = GENMASK(1, 0),
++ .reset_idx_rx_mask = GENMASK(7, 6),
++ },
++ .tx_ring_desc_size = sizeof(struct mtk_wdma_desc),
++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc),
++};
++
++static const struct mtk_wed_soc_data mt7988_data = {
++ .regmap = {
++ .tx_bm_tkid = 0x0c8,
++ .wpdma_rx_ring0 = 0x7d0,
++ .reset_idx_tx_mask = GENMASK(1, 0),
++ .reset_idx_rx_mask = GENMASK(7, 6),
++ },
++ .tx_ring_desc_size = sizeof(struct mtk_wed_bm_desc),
++ .wdma_desc_size = 2 * sizeof(struct mtk_wdma_desc),
++};
++
+ static void
+ wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val)
+ {
+@@ -74,6 +110,26 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
+ return wdma_r32(dev, MTK_WDMA_GLO_CFG);
+ }
+
++static u32
++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++ if (wed_r32(dev, reg) & mask)
++ return true;
++
++ return false;
++}
++
++static int
++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++ int sleep = 1000;
++ int timeout = 100 * sleep;
++ u32 val;
++
++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
++ timeout, false, dev, reg, mask);
++}
++
+ static int
+ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ {
+@@ -238,71 +294,171 @@ void mtk_wed_fe_reset_complete(void)
+ static struct mtk_wed_hw *
+ mtk_wed_assign(struct mtk_wed_device *dev)
+ {
+- struct mtk_wed_hw *hw;
+ int i;
+
+- if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
+- hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
+- if (!hw)
+- return NULL;
++ for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
++ struct mtk_wed_hw *hw = hw_list[i];
+
+- if (!hw->wed_dev)
+- goto out;
++ if (!hw || hw->wed_dev)
++ continue;
+
+- if (hw->version == 1)
+- return NULL;
++ hw->wed_dev = dev;
++ hw->pci_base = MTK_WED_PCIE_BASE;
+
+- /* MT7986 WED devices do not have any pcie slot restrictions */
+- }
+- /* MT7986 PCIE or AXI */
+- for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+- hw = hw_list[i];
+- if (hw && !hw->wed_dev)
+- goto out;
++ return hw;
+ }
+
+ return NULL;
++}
+
+-out:
+- hw->wed_dev = dev;
+- return hw;
++static int
++mtk_wed_amsdu_buffer_alloc(struct mtk_wed_device *dev)
++{
++ struct mtk_wed_hw *hw = dev->hw;
++ struct mtk_wed_amsdu *wed_amsdu;
++ int i;
++
++ if (!mtk_wed_is_v3_or_greater(hw))
++ return 0;
++
++ wed_amsdu = devm_kcalloc(hw->dev, MTK_WED_AMSDU_NPAGES,
++ sizeof(*wed_amsdu), GFP_KERNEL);
++ if (!wed_amsdu)
++ return -ENOMEM;
++
++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
++ void *ptr;
++
++ /* each segment is 64K */
++ ptr = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
++ __GFP_ZERO | __GFP_COMP |
++ GFP_DMA32,
++ get_order(MTK_WED_AMSDU_BUF_SIZE));
++ if (!ptr)
++ goto error;
++
++ wed_amsdu[i].txd = ptr;
++ wed_amsdu[i].txd_phy = dma_map_single(hw->dev, ptr,
++ MTK_WED_AMSDU_BUF_SIZE,
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(hw->dev, wed_amsdu[i].txd_phy))
++ goto error;
++ }
++ dev->hw->wed_amsdu = wed_amsdu;
++
++ return 0;
++
++error:
++ for (i--; i >= 0; i--)
++ dma_unmap_single(hw->dev, wed_amsdu[i].txd_phy,
++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
++ return -ENOMEM;
++}
++
++
++static void
++mtk_wed_amsdu_free_buffer(struct mtk_wed_device *dev)
++{
++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
++ int i;
++
++ if (!wed_amsdu)
++ return;
++
++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++) {
++ dma_unmap_single(dev->hw->dev, wed_amsdu[i].txd_phy,
++ MTK_WED_AMSDU_BUF_SIZE, DMA_TO_DEVICE);
++ free_pages((unsigned long)wed_amsdu[i].txd,
++ get_order(MTK_WED_AMSDU_BUF_SIZE));
++ }
++}
++
++static int
++mtk_wed_amsdu_init(struct mtk_wed_device *dev)
++{
++ struct mtk_wed_amsdu *wed_amsdu = dev->hw->wed_amsdu;
++ int i, ret;
++
++ if (!wed_amsdu)
++ return 0;
++
++ for (i = 0; i < MTK_WED_AMSDU_NPAGES; i++)
++ wed_w32(dev, MTK_WED_AMSDU_HIFTXD_BASE_L(i),
++ wed_amsdu[i].txd_phy);
++
++ /* init all sta parameter */
++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO_INIT, MTK_WED_AMSDU_STA_RMVL |
++ MTK_WED_AMSDU_STA_WTBL_HDRT_MODE |
++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_LEN,
++ dev->wlan.amsdu_max_len >> 8) |
++ FIELD_PREP(MTK_WED_AMSDU_STA_MAX_AMSDU_NUM,
++ dev->wlan.amsdu_max_subframes));
++
++ wed_w32(dev, MTK_WED_AMSDU_STA_INFO, MTK_WED_AMSDU_STA_INFO_DO_INIT);
++
++ ret = mtk_wed_poll_busy(dev, MTK_WED_AMSDU_STA_INFO,
++ MTK_WED_AMSDU_STA_INFO_DO_INIT);
++ if (ret) {
++ dev_err(dev->hw->dev, "amsdu initialization failed\n");
++ return ret;
++ }
++
++ /* init partial amsdu offload txd src */
++ wed_set(dev, MTK_WED_AMSDU_HIFTXD_CFG,
++ FIELD_PREP(MTK_WED_AMSDU_HIFTXD_SRC, dev->hw->index));
++
++ /* init qmem */
++ wed_set(dev, MTK_WED_AMSDU_PSE, MTK_WED_AMSDU_PSE_RESET);
++ ret = mtk_wed_poll_busy(dev, MTK_WED_MON_AMSDU_QMEM_STS1, BIT(29));
++ if (ret) {
++ pr_info("%s: amsdu qmem initialization failed\n", __func__);
++ return ret;
++ }
++
++ /* eagle E1 PCIE1 tx ring 22 flow control issue */
++ if (dev->wlan.id == 0x7991)
++ wed_clr(dev, MTK_WED_AMSDU_FIFO, MTK_WED_AMSDU_IS_PRIOR0_RING);
++
++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++
++ return 0;
+ }
+
+ static int
+ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ {
+- struct mtk_wdma_desc *desc;
+- dma_addr_t desc_phys;
+- void **page_list;
++ u32 desc_size = dev->hw->soc->tx_ring_desc_size;
++ int i, page_idx = 0, n_pages, ring_size;
+ int token = dev->wlan.token_start;
+- int ring_size, n_pages, page_idx;
+- int i;
+-
++ struct mtk_wed_buf *page_list;
++ dma_addr_t desc_phys;
++ void *desc_ptr;
+
+- if (dev->hw->version == 1)
++ if (!mtk_wed_is_v3_or_greater(dev->hw)) {
+ ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
+- else
+- ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
+- MTK_WED_WDMA_RING_SIZE * 2;
+-
+- n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
++ dev->tx_buf_ring.size = ring_size;
++ } else {
++ dev->tx_buf_ring.size = MTK_WED_TX_BM_DMA_SIZE;
++ ring_size = MTK_WED_TX_BM_PKT_CNT;
++ }
++ n_pages = dev->tx_buf_ring.size / MTK_WED_BUF_PER_PAGE;
+
+ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
+ if (!page_list)
+ return -ENOMEM;
+
+- dev->tx_buf_ring.size = ring_size;
+ dev->tx_buf_ring.pages = page_list;
+
+- desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+- &desc_phys, GFP_KERNEL);
+- if (!desc)
++ desc_ptr = dma_alloc_coherent(dev->hw->dev,
++ dev->tx_buf_ring.size * desc_size,
++ &desc_phys, GFP_KERNEL);
++ if (!desc_ptr)
+ return -ENOMEM;
+
+- dev->tx_buf_ring.desc = desc;
++ dev->tx_buf_ring.desc = desc_ptr;
+ dev->tx_buf_ring.desc_phys = desc_phys;
+
+- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
++ for (i = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+ dma_addr_t page_phys, buf_phys;
+ struct page *page;
+ void *buf;
+@@ -319,7 +475,8 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ return -ENOMEM;
+ }
+
+- page_list[page_idx++] = page;
++ page_list[page_idx].p = page;
++ page_list[page_idx++].phy_addr = page_phys;
+ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+
+@@ -327,28 +484,31 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ buf_phys = page_phys;
+
+ for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
+- u32 txd_size;
+- u32 ctrl;
+-
+- txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
++ struct mtk_wdma_desc *desc = desc_ptr;
+
+ desc->buf0 = cpu_to_le32(buf_phys);
+- desc->buf1 = cpu_to_le32(buf_phys + txd_size);
+-
+- if (dev->hw->version == 1)
+- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
+- MTK_WED_BUF_SIZE - txd_size) |
+- MTK_WDMA_DESC_CTRL_LAST_SEG1;
+- else
+- ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size) |
+- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
+- MTK_WED_BUF_SIZE - txd_size) |
+- MTK_WDMA_DESC_CTRL_LAST_SEG0;
+- desc->ctrl = cpu_to_le32(ctrl);
+- desc->info = 0;
+- desc++;
+-
++ if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++ u32 txd_size, ctrl;
++
++ txd_size = dev->wlan.init_buf(buf, buf_phys,
++ token++);
++ desc->buf1 = cpu_to_le32(buf_phys + txd_size);
++ ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0, txd_size);
++ if (mtk_wed_is_v1(dev->hw))
++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG1 |
++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
++ MTK_WED_BUF_SIZE - txd_size);
++ else
++ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 |
++ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
++ MTK_WED_BUF_SIZE - txd_size);
++ desc->ctrl = cpu_to_le32(ctrl);
++ desc->info = 0;
++ } else {
++ desc->ctrl = cpu_to_le32(token << 16);
++ }
++
++ desc_ptr += desc_size;
+ buf += MTK_WED_BUF_SIZE;
+ buf_phys += MTK_WED_BUF_SIZE;
+ }
+@@ -363,48 +523,107 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
+ {
+- struct mtk_wdma_desc *desc = dev->tx_buf_ring.desc;
+- void **page_list = dev->tx_buf_ring.pages;
+- int ring_size, page_idx;
+- int i;
++ struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages;
++ struct mtk_wed_hw *hw = dev->hw;
++ int i, page_idx = 0;
+
+ if (!page_list)
+ return;
+
+- if (!desc)
++ if (!dev->tx_buf_ring.desc)
+ goto free_pagelist;
+
+- if (dev->hw->version == 1) {
+- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
+- } else {
+- ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
+- MTK_WED_WDMA_RING_SIZE * 2;
+- }
+-
+- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
+- void *page = page_list[page_idx++];
+- dma_addr_t buf_addr;
++ for (i = 0; i < dev->tx_buf_ring.size; i += MTK_WED_BUF_PER_PAGE) {
++ dma_addr_t page_phy = page_list[page_idx].phy_addr;
++ void *page = page_list[page_idx++].p;
+
+ if (!page)
+ break;
+
+- buf_addr = le32_to_cpu(desc[i].buf0);
+- dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++ dma_unmap_page(dev->hw->dev, page_phy, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ __free_page(page);
+ }
+
+- dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
+- desc, dev->tx_buf_ring.desc_phys);
++ dma_free_coherent(dev->hw->dev,
++ dev->tx_buf_ring.size * hw->soc->tx_ring_desc_size,
++ dev->tx_buf_ring.desc,
++ dev->tx_buf_ring.desc_phys);
+
+ free_pagelist:
+ kfree(page_list);
+ }
+
++static int
++mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev)
++{
++ int n_pages = MTK_WED_RX_PG_BM_CNT / MTK_WED_RX_PAGE_BUF_PER_PAGE;
++ struct mtk_wed_buf *page_list;
++ struct mtk_wed_bm_desc *desc;
++ dma_addr_t desc_phys;
++ int i, page_idx = 0;
++
++ if (!dev->wlan.hw_rro)
++ return 0;
++
++ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
++ if (!page_list)
++ return -ENOMEM;
++
++ dev->hw_rro.size = dev->wlan.rx_nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
++ dev->hw_rro.pages = page_list;
++
++ desc = dma_alloc_coherent(dev->hw->dev,
++ dev->wlan.rx_nbuf * sizeof(*desc),
++ &desc_phys, GFP_KERNEL);
++ if (!desc)
++ return -ENOMEM;
++
++ dev->hw_rro.desc = desc;
++ dev->hw_rro.desc_phys = desc_phys;
++
++ for (i = 0, page_idx = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
++ dma_addr_t page_phys, buf_phys;
++ struct page *page;
++ void *buf;
++ int s;
++
++ page = __dev_alloc_pages(GFP_KERNEL, 0);
++ if (!page)
++ return -ENOMEM;
++
++ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE,
++ DMA_BIDIRECTIONAL);
++ if (dma_mapping_error(dev->hw->dev, page_phys)) {
++ __free_page(page);
++ return -ENOMEM;
++ }
++
++ page_list[page_idx].p= page;
++ page_list[page_idx++].phy_addr= page_phys;
++ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
++ DMA_BIDIRECTIONAL);
++
++ buf = page_to_virt(page);
++ buf_phys = page_phys;
++ for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) {
++ desc->buf0 = cpu_to_le32(buf_phys);
++ desc++;
++ buf += MTK_WED_PAGE_BUF_SIZE;
++ buf_phys += MTK_WED_PAGE_BUF_SIZE;
++ }
++
++ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE,
++ DMA_BIDIRECTIONAL);
++ }
++
++ return 0;
++}
++
+ static int
+ mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
+ {
+- struct mtk_rxbm_desc *desc;
++ struct mtk_wed_bm_desc *desc;
+ dma_addr_t desc_phys;
+
+ dev->rx_buf_ring.size = dev->wlan.rx_nbuf;
+@@ -418,13 +637,48 @@ mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
+ dev->rx_buf_ring.desc_phys = desc_phys;
+ dev->wlan.init_rx_buf(dev, dev->wlan.rx_npkt);
+
+- return 0;
++ return mtk_wed_hwrro_buffer_alloc(dev);
++}
++
++static void
++mtk_wed_hwrro_free_buffer(struct mtk_wed_device *dev)
++{
++ struct mtk_wed_buf *page_list = dev->hw_rro.pages;
++ struct mtk_wed_bm_desc *desc = dev->hw_rro.desc;
++ int i, page_idx = 0;
++
++ if (!dev->wlan.hw_rro)
++ return;
++
++ if (!page_list)
++ return;
++
++ if (!desc)
++ goto free_pagelist;
++
++ for (i = 0; i < MTK_WED_RX_PG_BM_CNT; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
++ dma_addr_t buf_addr = page_list[page_idx].phy_addr;
++ void *page = page_list[page_idx++].p;
++
++ if (!page)
++ break;
++
++ dma_unmap_page(dev->hw->dev, buf_addr, PAGE_SIZE,
++ DMA_BIDIRECTIONAL);
++ __free_page(page);
++ }
++
++ dma_free_coherent(dev->hw->dev, dev->hw_rro.size * sizeof(*desc),
++ desc, dev->hw_rro.desc_phys);
++
++free_pagelist:
++ kfree(page_list);
+ }
+
+ static void
+ mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
+ {
+- struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
++ struct mtk_wed_bm_desc *desc = dev->rx_buf_ring.desc;
+
+ if (!desc)
+ return;
+@@ -433,6 +687,28 @@ mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
+
+ dma_free_coherent(dev->hw->dev, dev->rx_buf_ring.size * sizeof(*desc),
+ desc, dev->rx_buf_ring.desc_phys);
++
++ mtk_wed_hwrro_free_buffer(dev);
++}
++
++static void
++mtk_wed_hwrro_init(struct mtk_wed_device *dev)
++{
++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
++ return;
++
++ wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM,
++ FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128));
++
++ wed_w32(dev, MTK_WED_RRO_PG_BM_BASE, dev->hw_rro.desc_phys);
++
++ wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR,
++ MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX |
++ FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX,
++ MTK_WED_RX_PG_BM_CNT));
++
++ /* enable rx_page_bm to fetch dmad */
++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
+ }
+
+ static void
+@@ -450,6 +726,8 @@ mtk_wed_rx_buffer_hw_init(struct mtk_wed_device *dev)
+ FIELD_PREP(MTK_WED_RX_BM_DYN_ALLOC_TH_H, 0xffff));
+
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
++
++ mtk_wed_hwrro_init(dev);
+ }
+
+ static void
+@@ -465,6 +743,16 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
+ static void
+ mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
+ {
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++)
++ if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
++ mtk_wed_free_ring(dev, &dev->rx_ring[i]);
++
++ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
++ if ((dev->tx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
++ mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
++
+ mtk_wed_free_rx_buffer(dev);
+ mtk_wed_free_ring(dev, &dev->rro.ring);
+ }
+@@ -475,9 +763,12 @@ mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
+- mtk_wed_free_ring(dev, &dev->tx_ring[i]);
++ if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
++ mtk_wed_free_ring(dev, &dev->tx_ring[i]);
++
+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
+- mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
++ if ((dev->rx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
++ mtk_wed_free_ring(dev, &dev->rx_wdma[i]);
+ }
+
+ static void
+@@ -485,8 +776,20 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ {
+ u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
+
+- if (dev->hw->version == 1)
++ switch (dev->hw->version) {
++ case 1:
+ mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
++ break;
++ case 2:
++ mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 |
++ MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 |
++ MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT |
++ MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR;
++ break;
++ case 3:
++ mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
++ break;
++ }
+
+ if (!dev->hw->num_flows)
+ mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
+@@ -498,6 +801,9 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
+ static void
+ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
+ {
++ if (!mtk_wed_is_v2(dev->hw))
++ return;
++
+ if (enable) {
+ wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
+ wed_w32(dev, MTK_WED_TXP_DW1,
+@@ -509,22 +815,15 @@ mtk_wed_set_512_support(struct mtk_wed_device *dev, bool enable)
+ }
+ }
+
+-#define MTK_WFMDA_RX_DMA_EN BIT(2)
+-static void
+-mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
++static int
++mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev,
++ struct mtk_wed_ring *ring)
+ {
+- u32 val;
+ int i;
+
+- if(!(dev->rx_ring[idx].flags & MTK_WED_RING_CONFIGURED))
+- return;
+-
+ for (i = 0; i < 3; i++) {
+- u32 cur_idx;
++ u32 cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX);
+
+- cur_idx = wed_r32(dev,
+- MTK_WED_WPDMA_RING_RX_DATA(idx) +
+- MTK_WED_RING_OFS_CPU_IDX);
+ if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
+ break;
+
+@@ -532,14 +831,12 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
+ }
+
+ if (i == 3) {
+- dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
+- dev->hw->index, idx);
+- return;
++ dev_err(dev->hw->dev, "mtk_wed%d: dma enable failed!\n",
++ dev->hw->index);
++ return -ETIMEDOUT;
+ }
+
+- val = wifi_r32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base) |
+- MTK_WFMDA_RX_DMA_EN;
+- wifi_w32(dev, dev->wlan.wpdma_rx_glo - dev->wlan.phy_base, val);
++ return 0;
+ }
+
+ static void
+@@ -561,7 +858,7 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ regmap_write(dev->hw->mirror, dev->hw->index * 4, 0);
+ wdma_clr(dev, MTK_WDMA_GLO_CFG,
+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+@@ -573,9 +870,17 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+ MTK_WED_WPDMA_RX_D_RX_DRV_EN);
+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++
++ if (mtk_wed_is_v3_or_greater(dev->hw) &&
++ mtk_wed_get_rx_capa(dev)) {
++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG,
++ MTK_WDMA_PREF_TX_CFG_PREF_EN);
++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG,
++ MTK_WDMA_PREF_RX_CFG_PREF_EN);
++ }
+ }
+
+- mtk_wed_set_512_support (dev, false);
++ mtk_wed_set_512_support(dev, false);
+ }
+
+ static void
+@@ -589,7 +894,7 @@ mtk_wed_stop(struct mtk_wed_device *dev)
+ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+
+- if (dev->hw->version == 1)
++ if (!mtk_wed_get_rx_capa(dev))
+ return;
+
+ wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
+@@ -608,13 +913,21 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
+ MTK_WED_CTRL_WED_TX_BM_EN |
+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+
+- if (dev->hw->version == 1)
++ if (mtk_wed_is_v1(dev->hw))
+ return;
+
+ wed_clr(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_RX_ROUTE_QM_EN |
+ MTK_WED_CTRL_WED_RX_BM_EN |
+ MTK_WED_CTRL_RX_RRO_QM_EN);
++
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_AMSDU);
++ wed_clr(dev, MTK_WED_PCIE_INT_CTRL,
++ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER);
++ }
+ }
+
+ static void
+@@ -627,6 +940,8 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
+
+ mtk_wdma_rx_reset(dev);
+ mtk_wed_reset(dev, MTK_WED_RESET_WED);
++ mtk_wed_amsdu_free_buffer(dev);
++ mtk_wdma_tx_reset(dev);
+ mtk_wed_free_tx_buffer(dev);
+ mtk_wed_free_tx_rings(dev);
+
+@@ -636,7 +951,6 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
+ mtk_wed_free_rx_rings(dev);
+ if(hw->wed_wo)
+ mtk_wed_wo_exit(hw);
+- mtk_wdma_tx_reset(dev);
+ }
+
+ if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
+@@ -664,21 +978,36 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+ mutex_unlock(&hw_lock);
+ }
+
+-#define PCIE_BASE_ADDR0 0x11280000
+ static void
+ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ {
+ switch (dev->wlan.bus_type) {
+ case MTK_WED_BUS_PCIE: {
+ struct device_node *np = dev->hw->eth->dev->of_node;
+- struct regmap *regs;
+
+- regs = syscon_regmap_lookup_by_phandle(np,
+- "mediatek,wed-pcie");
+- if (IS_ERR(regs))
+- break;
++ if (mtk_wed_is_v2(dev->hw)) {
++ struct regmap *regs;
++ regs = syscon_regmap_lookup_by_phandle(np,
++ "mediatek,wed-pcie");
++ if (IS_ERR(regs))
++ break;
++
++ regmap_update_bits(regs, 0, BIT(0), BIT(0));
++ }
+
+- regmap_update_bits(regs, 0, BIT(0), BIT(0));
++ if (dev->wlan.msi) {
++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM,
++ dev->hw->pci_base | 0xc08);
++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++ dev->hw->pci_base | 0xc04);
++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8));
++ } else {
++ wed_w32(dev, MTK_WED_PCIE_CFG_INTM,
++ dev->hw->pci_base | 0x180);
++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
++ dev->hw->pci_base | 0x184);
++ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
++ }
+
+ wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
+ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
+@@ -686,19 +1015,9 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ /* pcie interrupt control: pola/source selection */
+ wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
+- FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
+- wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
+-
+- wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
+- wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
+-
+- /* pcie interrupt status trigger register */
+- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
+- wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+-
+- /* pola setting */
+- wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+- MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
++ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER |
++ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL,
++ dev->hw->index));
+ break;
+ }
+ case MTK_WED_BUS_AXI:
+@@ -714,45 +1033,71 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_set_wpdma(struct mtk_wed_device *dev)
+ {
+- if (dev->hw->version == 1) {
+- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
+- } else {
+- mtk_wed_bus_init(dev);
++ int i;
+
+- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int);
+- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
+- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
+- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
+- wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
+- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx);
++ if (mtk_wed_is_v1(dev->hw)) {
++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
++ return;
+ }
++
++ mtk_wed_bus_init(dev);
++
++ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int);
++ wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
++ wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
++
++ if (!mtk_wed_get_rx_capa(dev))
++ return;
++
++ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
++ wed_w32(dev, dev->hw->soc->regmap.wpdma_rx_ring0, dev->wlan.wpdma_rx[0]);
++
++ if (dev->wlan.wpdma_rx[1])
++ wed_w32(dev, MTK_WED_WPDMA_RX_RING1, dev->wlan.wpdma_rx[1]);
++
++ if (!dev->wlan.hw_rro)
++ return;
++
++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]);
++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]);
++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++)
++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i),
++ dev->wlan.wpdma_rx_pg + i * 0x10);
+ }
+
+ static void
+ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
+ {
+- u32 mask, set;
++ u32 set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2);
++ u32 mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE;
+
+ mtk_wed_deinit(dev);
+ mtk_wed_reset(dev, MTK_WED_RESET_WED);
+ mtk_wed_set_wpdma(dev);
+
+- mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
+- MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
+- MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
+- set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
+- MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
+- MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
++ if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++ mask |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
++ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
++ set |= MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
++ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
++ }
+ wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ u32 offset;
++
+ offset = dev->hw->index ? 0x04000400 : 0;
++
++ wdma_set(dev, MTK_WDMA_GLO_CFG,
++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES |
++ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
++
+ wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
+ wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
+
+- wed_w32(dev, MTK_WED_PCIE_CFG_BASE,
+- MTK_PCIE_BASE(dev->hw->index));
++ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, MTK_PCIE_BASE(dev->hw->index));
+ } else {
+ wed_w32(dev, MTK_WED_WDMA_CFG_BASE, dev->hw->wdma_phy);
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_ETH_DMAD_FMT);
+@@ -844,7 +1189,8 @@ mtk_wed_rro_cfg(struct mtk_wed_device *dev)
+ },
+ };
+
+- return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO, MTK_WED_WO_CMD_WED_CFG,
++ return mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
++ MTK_WED_WO_CMD_WED_CFG,
+ &req, sizeof(req), true);
+ }
+
+@@ -895,11 +1241,18 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
+ }
+
+ /* configure RX_ROUTE_QM */
+- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
+- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
+- wed_set(dev, MTK_WED_RTQM_GLO_CFG,
+- FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
+- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++ if (mtk_wed_is_v2(dev->hw)) {
++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
++ wed_set(dev, MTK_WED_RTQM_GLO_CFG,
++ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT,
++ 0x3 + dev->hw->index));
++ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
++ } else {
++ wed_set(dev, MTK_WED_RTQM_ENQ_CFG0,
++ FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT,
++ 0x3 + dev->hw->index));
++ }
+
+ /* enable RX_ROUTE_QM */
+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
+@@ -918,35 +1271,26 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+
+ wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ MTK_WED_TX_BM_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ MTK_WED_TX_RING_SIZE / 256));
+- wed_w32(dev, MTK_WED_TX_BM_TKID,
+- FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+- dev->wlan.token_start) |
+- FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+- dev->wlan.token_start +
+- dev->wlan.nbuf - 1));
+ wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, 1) |
+ MTK_WED_TX_BM_DYN_THR_HI);
+- } else {
++ } else if (mtk_wed_is_v2(dev->hw)) {
+ wed_w32(dev, MTK_WED_TX_BM_CTRL,
+ MTK_WED_TX_BM_CTRL_PAUSE |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM,
+ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM,
+ dev->tx_buf_ring.size / 128));
+- wed_w32(dev, MTK_WED_TX_BM_TKID_V2,
+- FIELD_PREP(MTK_WED_TX_BM_TKID_START,
+- dev->wlan.token_start) |
+- FIELD_PREP(MTK_WED_TX_BM_TKID_END,
+- dev->wlan.token_start +
+- dev->wlan.nbuf - 1));
++ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
++ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
++ MTK_WED_TX_TKID_DYN_THR_HI);
+ wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
+ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO_V2, 0) |
+ MTK_WED_TX_BM_DYN_THR_HI_V2);
+@@ -956,32 +1300,73 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
+ dev->tx_buf_ring.size / 128) |
+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
+ dev->tx_buf_ring.size / 128));
+- wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
+- FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
+- MTK_WED_TX_TKID_DYN_THR_HI);
+ }
+
++ wed_w32(dev, dev->hw->soc->regmap.tx_bm_tkid,
++ FIELD_PREP(MTK_WED_TX_BM_TKID_START,
++ dev->wlan.token_start) |
++ FIELD_PREP(MTK_WED_TX_BM_TKID_END,
++ dev->wlan.token_start + dev->wlan.nbuf - 1));
++
+ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ /* switch to new bm architecture */
++ wed_clr(dev, MTK_WED_TX_BM_CTRL,
++ MTK_WED_TX_BM_CTRL_LEGACY_EN);
++
++ wed_w32(dev, MTK_WED_TX_TKID_CTRL,
++ MTK_WED_TX_TKID_CTRL_PAUSE |
++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3,
++ dev->wlan.nbuf / 128) |
++ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3,
++ dev->wlan.nbuf / 128));
++ /* return SKBID + SDP back to bm */
++ wed_set(dev, MTK_WED_TX_TKID_CTRL,
++ MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
++
++ wed_w32(dev, MTK_WED_TX_BM_INIT_PTR,
++ MTK_WED_TX_BM_PKT_CNT |
++ MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
++ }
++
++ if (mtk_wed_is_v1(dev->hw)) {
+ wed_set(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_WED_TX_BM_EN |
+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+- } else {
+- wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+- /* rx hw init*/
++ } else if (mtk_wed_get_rx_capa(dev)) {
++ /* rx hw init */
+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
+
+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
+
++ /* reset prefetch index of ring */
++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++
++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
++ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
++
++ /* reset prefetch FIFO of ring */
++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG,
++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR |
++ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR);
++ wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0);
++
+ mtk_wed_rx_buffer_hw_init(dev);
+ mtk_wed_rro_hw_init(dev);
+ mtk_wed_route_qm_hw_init(dev);
+ }
+
+ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
++ if (!mtk_wed_is_v1(dev->hw))
++ wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
+ }
+
+ static void
+@@ -1099,13 +1484,8 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA);
+ } else {
+- struct mtk_eth *eth = dev->hw->eth;
+-
+- if(MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+- wed_set(dev, MTK_WED_RESET_IDX,
+- MTK_WED_RESET_IDX_RX_V2);
+- else
+- wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX);
++ wed_set(dev, MTK_WED_RESET_IDX,
++ dev->hw->soc->regmap.reset_idx_rx_mask);
+ wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ }
+
+@@ -1162,7 +1542,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ if (busy) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA);
+ } else {
+- wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX);
++ wed_w32(dev, MTK_WED_RESET_IDX,
++ dev->hw->soc->regmap.reset_idx_tx_mask);
+ wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ }
+
+@@ -1226,7 +1607,7 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ }
+
+ dev->init_done = false;
+- if (dev->hw->version == 1)
++ if (mtk_wed_is_v1(dev->hw))
+ return;
+
+ if (!busy) {
+@@ -1257,7 +1638,6 @@ static int
+ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ bool reset)
+ {
+- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ struct mtk_wed_ring *wdma;
+
+ if (idx >= ARRAY_SIZE(dev->rx_wdma))
+@@ -1265,9 +1645,11 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+
+ wdma = &dev->rx_wdma[idx];
+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
+- desc_size, true))
++ dev->hw->soc->wdma_desc_size, true))
+ return -ENOMEM;
+
++ wdma->flags |= MTK_WED_RING_CONFIGURED;
++
+ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
+ wdma->desc_phys);
+ wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT,
+@@ -1286,7 +1668,6 @@ static int
+ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+ bool reset)
+ {
+- u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
+ struct mtk_wed_ring *wdma;
+
+ if (idx >= ARRAY_SIZE(dev->tx_wdma))
+@@ -1294,9 +1675,29 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
+
+ wdma = &dev->tx_wdma[idx];
+ if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
+- desc_size, true))
++ dev->hw->soc->wdma_desc_size, true))
+ return -ENOMEM;
+
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ struct mtk_wdma_desc *desc = wdma->desc;
++ int i;
++
++ for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) {
++ desc->buf0 = 0;
++ desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
++ desc->buf1 = 0;
++ desc->info = MTK_WDMA_TXD0_DESC_INFO_DMA_DONE;
++ desc++;
++ desc->buf0 = 0;
++ desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
++ desc->buf1 = 0;
++ desc->info = MTK_WDMA_TXD1_DESC_INFO_DMA_DONE;
++ desc++;
++ }
++ }
++
++ wdma->flags |= MTK_WED_RING_CONFIGURED;
++
+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
+ wdma->desc_phys);
+ wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
+@@ -1354,7 +1755,7 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ MTK_WED_CTRL_WED_TX_BM_EN |
+ MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
+ MTK_WED_PCIE_INT_TRIGGER_STATUS);
+
+@@ -1364,8 +1765,9 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+
+ wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
+ } else {
+- wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
+- GENMASK(1, 0));
++ if (mtk_wed_is_v3_or_greater(dev->hw))
++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN);
++
+ /* initail tx interrupt trigger */
+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
+ MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
+@@ -1384,19 +1786,25 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
+ dev->wlan.txfree_tbit));
+
+- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
+- MTK_WED_WPDMA_INT_CTRL_RX0_EN |
+- MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
+- MTK_WED_WPDMA_INT_CTRL_RX1_EN |
+- MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
+- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
+- dev->wlan.rx_tbit[0]) |
+- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
+- dev->wlan.rx_tbit[1]));
++ if (mtk_wed_get_rx_capa(dev)) {
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
++ MTK_WED_WPDMA_INT_CTRL_RX0_EN |
++ MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
++ MTK_WED_WPDMA_INT_CTRL_RX1_EN |
++ MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
++ dev->wlan.rx_tbit[0]) |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
++ dev->wlan.rx_tbit[1]));
++
++ wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
++ GENMASK(1, 0));
++ }
+
+ wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
+ wed_set(dev, MTK_WED_WDMA_INT_CTRL,
+- FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,dev->wdma_idx));
++ FIELD_PREP(MTK_WED_WDMA_INT_POLL_SRC_SEL,
++ dev->wdma_idx));
+ }
+ /* initail wdma interrupt agent */
+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
+@@ -1407,58 +1815,295 @@ mtk_wed_configure_irq(struct mtk_wed_device *dev, u32 irq_mask)
+ wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
+ }
+
++#define MTK_WFMDA_RX_DMA_EN BIT(2)
+ static void
+ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ {
+- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
+- MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
++ int i;
++
++ if (!mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
++ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
++ wdma_set(dev, MTK_WDMA_GLO_CFG,
++ MTK_WDMA_GLO_CFG_TX_DMA_EN |
++ MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
++ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
++ wed_set(dev, MTK_WED_WPDMA_CTRL, MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++ } else {
++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN |
++ MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR);
++ wdma_set(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
++ }
+
+ wed_set(dev, MTK_WED_GLO_CFG,
+ MTK_WED_GLO_CFG_TX_DMA_EN |
+ MTK_WED_GLO_CFG_RX_DMA_EN);
+- wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
+- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
++
+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
+
+- wdma_set(dev, MTK_WDMA_GLO_CFG,
+- MTK_WDMA_GLO_CFG_TX_DMA_EN |
+- MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
+- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
+-
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ wdma_set(dev, MTK_WDMA_GLO_CFG,
+ MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
+- } else {
+- int i;
++ return;
++ }
+
+- wed_set(dev, MTK_WED_WPDMA_CTRL,
+- MTK_WED_WPDMA_CTRL_SDL1_FIXED);
++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
+
+- wed_set(dev, MTK_WED_WDMA_GLO_CFG,
+- MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
+- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) |
++ FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8));
++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_DDONE2_EN);
++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
+
+ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
+- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
+- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST);
++ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK |
++ MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
+
+- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
+- MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
+- MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++ wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++ wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++ }
+
+- wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
+- MTK_WED_WPDMA_RX_D_RX_DRV_EN |
+- FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
+- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
+- 0x2));
++ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
++ MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
++ MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
++
++ if (!mtk_wed_get_rx_capa(dev))
++ return;
+
+- for (i = 0; i < MTK_WED_RX_QUEUES; i++)
+- mtk_wed_check_wfdma_rx_fill(dev, i);
++ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
++ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
++ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
++
++ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN);
++ wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
++ MTK_WED_WPDMA_RX_D_RX_DRV_EN |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL, 0x2));
++
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++ MTK_WED_WPDMA_RX_D_PREF_EN |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) |
++ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8));
++
++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
++ wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++ wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++ }
++
++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) {
++ struct mtk_wed_ring *ring = &dev->rx_ring[i];
++ u32 val;
++
++ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++ continue;
++
++ if(mtk_wed_check_wfdma_rx_fill(dev, ring)) {
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: rx(%d) dma enable failed!\n",
++ dev->hw->index, i);
++ continue;
++ }
++
++ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
++ dev->wlan.phy_base) | MTK_WFMDA_RX_DMA_EN;
++
++ wifi_w32(dev,
++ dev->wlan.wpdma_rx_glo - dev->wlan.phy_base,
++ val);
++
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: rx(%d) dma enable successful!\n",
++ dev->hw->index, i);
+ }
+ }
+
++static void
++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
++{
++ int i;
++
++ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
++ wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
++
++ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
++ return;
++
++ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++ MTK_WED_RRO_MSDU_PG_DRV_CLR);
++
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX,
++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN |
++ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR |
++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN |
++ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG,
++ dev->wlan.rro_rx_tbit[0]) |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG,
++ dev->wlan.rro_rx_tbit[1]));
++
++ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG,
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN |
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR |
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN |
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR |
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN |
++ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG,
++ dev->wlan.rx_pg_tbit[0]) |
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG,
++ dev->wlan.rx_pg_tbit[1])|
++ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG,
++ dev->wlan.rx_pg_tbit[2]));
++
++ /*
++ * RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after
++ * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken
++ */
++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++ MTK_WED_RRO_MSDU_PG_DRV_EN);
++
++ for (i = 0; i < MTK_WED_RX_QUEUES; i++) {
++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[i];
++
++ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++ continue;
++
++ if (mtk_wed_check_wfdma_rx_fill(dev, ring))
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: rx_rro_ring(%d) init failed!\n",
++ dev->hw->index, i);
++ }
++
++ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++){
++ struct mtk_wed_ring *ring = &dev->rx_page_ring[i];
++
++ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
++ continue;
++
++ if (mtk_wed_check_wfdma_rx_fill(dev, ring))
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: rx_page_ring(%d) init failed!\n",
++ dev->hw->index, i);
++ }
++}
++
++static void
++mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
++{
++ struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
++
++ ring->wpdma = regs;
++
++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE,
++ readl(regs));
++ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT,
++ readl(regs + MTK_WED_RING_OFS_COUNT));
++
++ ring->flags |= MTK_WED_RING_CONFIGURED;
++}
++
++static void
++mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
++{
++ struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
++
++ ring->wpdma = regs;
++
++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE,
++ readl(regs));
++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT,
++ readl(regs + MTK_WED_RING_OFS_COUNT));
++
++ ring->flags |= MTK_WED_RING_CONFIGURED;
++}
++
++static int
++mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
++{
++ struct mtk_wed_ring *ring = &dev->ind_cmd_ring;
++ u32 val = readl(regs + MTK_WED_RING_OFS_COUNT);
++ int i = 0, count = 0;
++
++ ring->wpdma = regs;
++
++ if (readl(regs) & 0xf)
++ pr_info("%s(): address is not 16-byte alignment\n", __func__);
++
++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE,
++ readl(regs) & 0xfffffff0);
++
++ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT,
++ readl(regs + MTK_WED_RING_OFS_COUNT));
++
++ /* ack sn cr */
++ wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base +
++ dev->wlan.ind_cmd.ack_sn_addr);
++ wed_w32(dev, MTK_WED_RRO_CFG1,
++ FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ,
++ dev->wlan.ind_cmd.win_size) |
++ FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID,
++ dev->wlan.ind_cmd.particular_sid));
++
++ /* particular session addr element */
++ wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0,
++ dev->wlan.ind_cmd.particular_se_phys);
++
++ for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) {
++ wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA,
++ dev->wlan.ind_cmd.addr_elem_phys[i] >> 4);
++ wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
++ MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f));
++
++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
++ while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) && count++ < 100)
++ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
++
++ if (count >= 100)
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: write ba session base failed!\n",
++ dev->hw->index);
++ }
++
++ /* pn check init */
++ for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) {
++ wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M,
++ MTK_WED_PN_CHECK_IS_FIRST);
++
++ wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR |
++ FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i));
++
++ count = 0;
++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
++ while (!(val & MTK_WED_PN_CHECK_WR_RDY) && count++ < 100)
++ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
++
++ if (count >= 100)
++ dev_err(dev->hw->dev,
++ "mtk_wed%d: session(%d) init failed!\n",
++ dev->hw->index, i);
++ }
++
++ wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN);
++ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
++
++ return 0;
++}
++
+ static void
+ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ {
+@@ -1471,20 +2116,29 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ if (!dev->rx_wdma[i].desc)
+ mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
+
++ if (dev->wlan.hw_rro) {
++ for (i = 0; i < ARRAY_SIZE(dev->rx_page_ring); i++) {
++ u32 count = MTK_WED_RRO_MSDU_PG_CTRL0(i) +
++ MTK_WED_RING_OFS_COUNT;
++
++ if (!wed_r32(dev, count))
++ wed_w32(dev, count, 1);
++ }
++ }
+
+ mtk_wed_hw_init(dev);
+ mtk_wed_configure_irq(dev, irq_mask);
+
+ mtk_wed_set_ext_int(dev, true);
+
+- if (dev->hw->version == 1) {
++ if (mtk_wed_is_v1(dev->hw)) {
+ u32 val = dev->wlan.wpdma_phys | MTK_PCIE_MIRROR_MAP_EN |
+ FIELD_PREP(MTK_PCIE_MIRROR_MAP_WED_ID,
+ dev->hw->index);
+
+ val |= BIT(0) | (BIT(1) * !!dev->hw->index);
+ regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
+- } else {
++ } else if (mtk_wed_get_rx_capa(dev)) {
+ /* driver set mid ready and only once */
+ wed_w32(dev, MTK_WED_EXT_INT_MASK1,
+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
+@@ -1494,12 +2148,19 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
+ wed_r32(dev, MTK_WED_EXT_INT_MASK1);
+ wed_r32(dev, MTK_WED_EXT_INT_MASK2);
+
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_w32(dev, MTK_WED_EXT_INT_MASK3,
++ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
++ wed_r32(dev, MTK_WED_EXT_INT_MASK3);
++ }
++
+ if (mtk_wed_rro_cfg(dev))
+ return;
+
+ }
+
+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
++ mtk_wed_amsdu_init(dev);
+
+ mtk_wed_dma_enable(dev);
+ dev->running = true;
+@@ -1516,9 +2177,7 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
+ "mtk_wed_attach without holding the RCU read lock");
+
+- if ((dev->wlan.bus_type == MTK_WED_BUS_PCIE &&
+- pci_domain_nr(dev->wlan.pci_dev->bus) > 1) ||
+- !try_module_get(THIS_MODULE))
++ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ rcu_read_unlock();
+@@ -1537,11 +2196,13 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ : &dev->wlan.platform_dev->dev;
+ dev_info(device, "attaching wed device %d version %d\n",
+ hw->index, hw->version);
++
+ dev->hw = hw;
+ dev->dev = hw->dev;
+ dev->irq = hw->irq;
+ dev->wdma_idx = hw->index;
+ dev->version = hw->version;
++ dev->hw->pci_base = mtk_wed_get_pci_base(dev);
+
+ if (hw->eth->dma_dev == hw->eth->dev &&
+ of_dma_is_coherent(hw->eth->dev->of_node))
+@@ -1551,6 +2212,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ if (ret)
+ goto out;
+
++ ret = mtk_wed_amsdu_buffer_alloc(dev);
++ if (ret)
++ goto out;
++
+ if (mtk_wed_get_rx_capa(dev)) {
+ ret = mtk_wed_rro_alloc(dev);
+ if (ret)
+@@ -1563,13 +2228,14 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ init_completion(&dev->wlan_reset_done);
+ atomic_set(&dev->fe_reset, 0);
+
+- if (hw->version == 1) {
++ if (mtk_wed_is_v1(hw))
+ regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+ BIT(hw->index), 0);
+- } else {
++ else
+ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
++
++ if (mtk_wed_get_rx_capa(dev))
+ ret = mtk_wed_wo_init(hw);
+- }
+
+ out:
+ if (ret) {
+@@ -1613,6 +2279,24 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
+
+ ring->reg_base = MTK_WED_RING_TX(idx);
+ ring->wpdma = regs;
++ ring->flags |= MTK_WED_RING_CONFIGURED;
++
++ if (mtk_wed_is_v3_or_greater(dev->hw) && idx == 1) {
++ /* reset prefetch index */
++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++ /* reset prefetch FIFO */
++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
++ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
++ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
++ }
+
+ /* WED -> WPDMA */
+ wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
+@@ -1632,7 +2316,7 @@ static int
+ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
+ {
+ struct mtk_wed_ring *ring = &dev->txfree_ring;
+- int i, index = dev->hw->version == 1;
++ int i, index = mtk_wed_is_v1(dev->hw);
+
+ /*
+ * For txfree event handling, the same DMA ring is shared between WED
+@@ -1692,9 +2376,13 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
+
+ val = wed_r32(dev, MTK_WED_EXT_INT_STATUS);
+ wed_w32(dev, MTK_WED_EXT_INT_STATUS, val);
+- val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
+- if (!dev->hw->num_flows)
+- val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ val &= MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
++ } else {
++ val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
++ if (!dev->hw->num_flows)
++ val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
++ }
+ if (val && net_ratelimit())
+ pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val);
+
+@@ -1718,19 +2406,20 @@ mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask)
+ int mtk_wed_flow_add(int index)
+ {
+ struct mtk_wed_hw *hw = hw_list[index];
+- int ret;
++ int ret = 0;
+
+- if (!hw || !hw->wed_dev)
+- return -ENODEV;
++ mutex_lock(&hw_lock);
+
+- if (hw->num_flows) {
+- hw->num_flows++;
+- return 0;
++ if (!hw || !hw->wed_dev) {
++ ret = -ENODEV;
++ goto out;
+ }
+
+- mutex_lock(&hw_lock);
+- if (!hw->wed_dev) {
+- ret = -ENODEV;
++ if (!hw->wed_dev->wlan.offload_enable)
++ goto out;
++
++ if (hw->num_flows) {
++ hw->num_flows++;
+ goto out;
+ }
+
+@@ -1749,14 +2438,15 @@ void mtk_wed_flow_remove(int index)
+ {
+ struct mtk_wed_hw *hw = hw_list[index];
+
+- if (!hw)
+- return;
++ mutex_lock(&hw_lock);
+
+- if (--hw->num_flows)
+- return;
++ if (!hw || !hw->wed_dev)
++ goto out;
+
+- mutex_lock(&hw_lock);
+- if (!hw->wed_dev)
++ if (!hw->wed_dev->wlan.offload_disable)
++ goto out;
++
++ if (--hw->num_flows)
+ goto out;
+
+ hw->wed_dev->wlan.offload_disable(hw->wed_dev);
+@@ -1799,6 +2489,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ .detach = mtk_wed_detach,
+ .setup_tc = mtk_wed_eth_setup_tc,
+ .ppe_check = mtk_wed_ppe_check,
++ .start_hw_rro = mtk_wed_start_hw_rro,
++ .rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup,
++ .msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup,
++ .ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup,
+ };
+ struct device_node *eth_np = eth->dev->of_node;
+ struct platform_device *pdev;
+@@ -1840,14 +2534,22 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ hw->wdma_phy = wdma_phy;
+ hw->index = index;
+ hw->irq = irq;
+- hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
++ hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) ?
++ 3 : MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
+
+- if (hw->version == 1) {
++ switch (hw->version) {
++ case 2:
++ hw->soc = &mt7986_data;
++ break;
++ case 3:
++ hw->soc = &mt7988_data;
++ break;
++ default:
++ case 1:
+ hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
+- "mediatek,pcie-mirror");
++ "mediatek,pcie-mirror");
+ hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
+- "mediatek,hifsys");
+-
++ "mediatek,hifsys");
+ if (IS_ERR(hw->mirror) || IS_ERR(hw->hifsys)) {
+ kfree(hw);
+ goto unlock;
+@@ -1857,8 +2559,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ regmap_write(hw->mirror, 0, 0);
+ regmap_write(hw->mirror, 4, 0);
+ }
++ hw->soc = &mt7622_data;
++ break;
+ }
+-
++
+ mtk_wed_hw_add_debugfs(hw);
+
+ hw_list[index] = hw;
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
+index 2ce1a5b..f5e30ce 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed.h
+@@ -8,12 +8,18 @@
+ #include <linux/debugfs.h>
+ #include <linux/regmap.h>
+ #include <linux/netdevice.h>
++
++#include "mtk_wed_regs.h"
++
+ #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000)
+
+-#define MTK_WED_PKT_SIZE 1900
++#define MTK_WED_PKT_SIZE 1920//1900
+ #define MTK_WED_BUF_SIZE 2048
++#define MTK_WED_PAGE_BUF_SIZE 128
+ #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048)
++#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128)
+ #define MTK_WED_RX_RING_SIZE 1536
++#define MTK_WED_RX_PG_BM_CNT 8192
+
+ #define MTK_WED_TX_RING_SIZE 2048
+ #define MTK_WED_WDMA_RING_SIZE 512
+@@ -27,12 +33,27 @@
+ #define MTK_WED_RRO_QUE_CNT 8192
+ #define MTK_WED_MIOD_ENTRY_CNT 128
+
++#define MTK_WED_TX_BM_DMA_SIZE 65536
++#define MTK_WED_TX_BM_PKT_CNT 32768
++
+ #define MTK_WED_MODULE_ID_WO 1
+
+ struct mtk_eth;
+ struct mtk_wed_wo;
+
++struct mtk_wed_soc_data {
++ struct {
++ u32 tx_bm_tkid;
++ u32 wpdma_rx_ring0;
++ u32 reset_idx_tx_mask;
++ u32 reset_idx_rx_mask;
++ } regmap;
++ u32 tx_ring_desc_size;
++ u32 wdma_desc_size;
++};
++
+ struct mtk_wed_hw {
++ const struct mtk_wed_soc_data *soc;
+ struct device_node *node;
+ struct mtk_eth *eth;
+ struct regmap *regs;
+@@ -44,12 +65,15 @@ struct mtk_wed_hw {
+ struct dentry *debugfs_dir;
+ struct mtk_wed_device *wed_dev;
+ struct mtk_wed_wo *wed_wo;
++ struct mtk_wed_amsdu *wed_amsdu;
++ u32 pci_base;
+ u32 debugfs_reg;
+ u32 num_flows;
+ u8 version;
+ char dirname[5];
+ int irq;
+ int index;
++ int token_id;
+ };
+
+ struct mtk_wdma_info {
+@@ -57,9 +81,41 @@ struct mtk_wdma_info {
+ u8 queue;
+ u16 wcid;
+ u8 bss;
++ u32 usr_info;
++ u8 tid;
++ u8 is_fixedrate;
++ u8 is_prior;
++ u8 is_sp;
++ u8 hf;
++ u8 amsdu;
++};
++
++struct mtk_wed_amsdu {
++ void *txd;
++ dma_addr_t txd_phy;
+ };
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
++static inline bool mtk_wed_is_v1(struct mtk_wed_hw *hw)
++{
++ return hw->version == 1;
++}
++
++static inline bool mtk_wed_is_v2(struct mtk_wed_hw *hw)
++{
++ return hw->version == 2;
++}
++
++static inline bool mtk_wed_is_v3(struct mtk_wed_hw *hw)
++{
++ return hw->version == 3;
++}
++
++static inline bool mtk_wed_is_v3_or_greater(struct mtk_wed_hw *hw)
++{
++ return hw->version > 2;
++}
++
+ static inline void
+ wed_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+ {
+@@ -154,6 +210,21 @@ wpdma_txfree_w32(struct mtk_wed_device *dev, u32 reg, u32 val)
+ writel(val, dev->txfree_ring.wpdma + reg);
+ }
+
++static inline u32 mtk_wed_get_pci_base(struct mtk_wed_device *dev)
++{
++ if (!mtk_wed_is_v3_or_greater(dev->hw))
++ return MTK_WED_PCIE_BASE;
++
++ switch (dev->hw->index) {
++ case 1:
++ return MTK_WED_PCIE_BASE1;
++ case 2:
++ return MTK_WED_PCIE_BASE2;
++ default:
++ return MTK_WED_PCIE_BASE0;
++ }
++}
++
+ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
+ void __iomem *wdma, phys_addr_t wdma_phy,
+ int index);
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+index 7d8be99..69fe29b 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
+@@ -11,9 +11,11 @@ struct reg_dump {
+ u16 offset;
+ u8 type;
+ u8 base;
++ u32 mask;
+ };
+
+ enum {
++ DUMP_TYPE_END,
+ DUMP_TYPE_STRING,
+ DUMP_TYPE_WED,
+ DUMP_TYPE_WDMA,
+@@ -23,8 +25,11 @@ enum {
+ DUMP_TYPE_WED_RRO,
+ };
+
++#define DUMP_END() { .type = DUMP_TYPE_END }
+ #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
+ #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
++#define DUMP_REG_MASK(_reg, _mask) { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask }
++
+ #define DUMP_RING(_prefix, _base, ...) \
+ { _prefix " BASE", _base, __VA_ARGS__ }, \
+ { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \
+@@ -32,6 +37,7 @@ enum {
+ { _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
+
+ #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
++#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask)
+ #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
+
+ #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
+@@ -52,36 +58,49 @@ print_reg_val(struct seq_file *s, const char *name, u32 val)
+
+ static void
+ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
+- const struct reg_dump *regs, int n_regs)
++ const struct reg_dump **regs)
+ {
+- const struct reg_dump *cur;
++ const struct reg_dump **cur_o = regs, *cur;
++ bool newline = false;
+ u32 val;
+
+- for (cur = regs; cur < ®s[n_regs]; cur++) {
+- switch (cur->type) {
+- case DUMP_TYPE_STRING:
+- seq_printf(s, "%s======== %s:\n",
+- cur > regs ? "\n" : "",
+- cur->name);
+- continue;
+- case DUMP_TYPE_WED:
+- case DUMP_TYPE_WED_RRO:
+- val = wed_r32(dev, cur->offset);
+- break;
+- case DUMP_TYPE_WDMA:
+- val = wdma_r32(dev, cur->offset);
+- break;
+- case DUMP_TYPE_WPDMA_TX:
+- val = wpdma_tx_r32(dev, cur->base, cur->offset);
+- break;
+- case DUMP_TYPE_WPDMA_TXFREE:
+- val = wpdma_txfree_r32(dev, cur->offset);
+- break;
+- case DUMP_TYPE_WPDMA_RX:
+- val = wpdma_rx_r32(dev, cur->base, cur->offset);
+- break;
++ while (*cur_o) {
++ cur = *cur_o;
++
++ while (cur->type != DUMP_TYPE_END) {
++ switch (cur->type) {
++ case DUMP_TYPE_STRING:
++ seq_printf(s, "%s======== %s:\n",
++ newline ? "\n" : "",
++ cur->name);
++ newline = true;
++ cur++;
++ continue;
++ case DUMP_TYPE_WED:
++ case DUMP_TYPE_WED_RRO:
++ val = wed_r32(dev, cur->offset);
++ break;
++ case DUMP_TYPE_WDMA:
++ val = wdma_r32(dev, cur->offset);
++ break;
++ case DUMP_TYPE_WPDMA_TX:
++ val = wpdma_tx_r32(dev, cur->base, cur->offset);
++ break;
++ case DUMP_TYPE_WPDMA_TXFREE:
++ val = wpdma_txfree_r32(dev, cur->offset);
++ break;
++ case DUMP_TYPE_WPDMA_RX:
++ val = wpdma_rx_r32(dev, cur->base, cur->offset);
++ break;
++ }
++
++ if (cur->mask)
++ val = (cur->mask & val) >> (ffs(cur->mask) - 1);
++
++ print_reg_val(s, cur->name, val);
++ cur++;
+ }
+- print_reg_val(s, cur->name, val);
++ cur_o++;
+ }
+ }
+
+@@ -89,7 +108,7 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
+ static int
+ wed_txinfo_show(struct seq_file *s, void *data)
+ {
+- static const struct reg_dump regs[] = {
++ static const struct reg_dump regs_common[] = {
+ DUMP_STR("WED TX"),
+ DUMP_WED(WED_TX_MIB(0)),
+ DUMP_WED_RING(WED_RING_TX(0)),
+@@ -128,16 +147,32 @@ wed_txinfo_show(struct seq_file *s, void *data)
+ DUMP_WDMA_RING(WDMA_RING_RX(0)),
+ DUMP_WDMA_RING(WDMA_RING_RX(1)),
+
+- DUMP_STR("TX FREE"),
++ DUMP_STR("WED TX FREE"),
+ DUMP_WED(WED_RX_MIB(0)),
++ DUMP_WED_RING(WED_RING_RX(0)),
++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)),
++
++ DUMP_WED(WED_RX_MIB(1)),
++ DUMP_WED_RING(WED_RING_RX(1)),
++ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)),
++ DUMP_STR("WED_WPDMA TX FREE"),
++ DUMP_WED_RING(WED_WPDMA_RING_RX(0)),
++ DUMP_WED_RING(WED_WPDMA_RING_RX(1)),
++ DUMP_END(),
++ };
++
++ static const struct reg_dump *regs[] = {
++ ®s_common[0],
++ NULL,
+ };
++
+ struct mtk_wed_hw *hw = s->private;
+ struct mtk_wed_device *dev = hw->wed_dev;
+
+ if (!dev)
+ return 0;
+
+- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
++ dump_wed_regs(s, dev, regs);
+
+ return 0;
+ }
+@@ -146,7 +181,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
+ static int
+ wed_rxinfo_show(struct seq_file *s, void *data)
+ {
+- static const struct reg_dump regs[] = {
++ static const struct reg_dump regs_common[] = {
+ DUMP_STR("WPDMA RX"),
+ DUMP_WPDMA_RX_RING(0),
+ DUMP_WPDMA_RX_RING(1),
+@@ -164,7 +199,7 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ DUMP_WED_RING(WED_RING_RX_DATA(0)),
+ DUMP_WED_RING(WED_RING_RX_DATA(1)),
+
+- DUMP_STR("WED RRO"),
++ DUMP_STR("WED WO RRO"),
+ DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
+ DUMP_WED(WED_RROQM_MID_MIB),
+ DUMP_WED(WED_RROQM_MOD_MIB),
+@@ -175,16 +210,6 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
+ DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
+
+- DUMP_STR("WED Route QM"),
+- DUMP_WED(WED_RTQM_R2H_MIB(0)),
+- DUMP_WED(WED_RTQM_R2Q_MIB(0)),
+- DUMP_WED(WED_RTQM_Q2H_MIB(0)),
+- DUMP_WED(WED_RTQM_R2H_MIB(1)),
+- DUMP_WED(WED_RTQM_R2Q_MIB(1)),
+- DUMP_WED(WED_RTQM_Q2H_MIB(1)),
+- DUMP_WED(WED_RTQM_Q2N_MIB),
+- DUMP_WED(WED_RTQM_Q2B_MIB),
+- DUMP_WED(WED_RTQM_PFDBK_MIB),
+
+ DUMP_STR("WED WDMA TX"),
+ DUMP_WED(WED_WDMA_TX_MIB),
+@@ -205,15 +230,99 @@ wed_rxinfo_show(struct seq_file *s, void *data)
+ DUMP_WED(WED_RX_BM_INTF2),
+ DUMP_WED(WED_RX_BM_INTF),
+ DUMP_WED(WED_RX_BM_ERR_STS),
++ DUMP_END()
++ };
++
++ static const struct reg_dump regs_v2[] = {
++ DUMP_STR("WED Route QM"),
++ DUMP_WED(WED_RTQM_R2H_MIB(0)),
++ DUMP_WED(WED_RTQM_R2Q_MIB(0)),
++ DUMP_WED(WED_RTQM_Q2H_MIB(0)),
++ DUMP_WED(WED_RTQM_R2H_MIB(1)),
++ DUMP_WED(WED_RTQM_R2Q_MIB(1)),
++ DUMP_WED(WED_RTQM_Q2H_MIB(1)),
++ DUMP_WED(WED_RTQM_Q2N_MIB),
++ DUMP_WED(WED_RTQM_Q2B_MIB),
++ DUMP_WED(WED_RTQM_PFDBK_MIB),
++
++ DUMP_END()
++ };
++
++ static const struct reg_dump regs_v3[] = {
++ DUMP_STR("WED RX RRO DATA"),
++ DUMP_WED_RING(WED_RRO_RX_D_RX(0)),
++ DUMP_WED_RING(WED_RRO_RX_D_RX(1)),
++
++ DUMP_STR("WED RX MSDU PAGE"),
++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)),
++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)),
++ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)),
++
++ DUMP_STR("WED RX IND CMD"),
++ DUMP_WED(WED_IND_CMD_RX_CTRL1),
++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT),
++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX),
++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX),
++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT),
++ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT),
++ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0,
++ WED_IND_CMD_PREFETCH_FREE_CNT),
++ DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID),
++
++ DUMP_STR("WED ADDR ELEM"),
++ DUMP_WED(WED_ADDR_ELEM_CFG0),
++ DUMP_WED_MASK(WED_ADDR_ELEM_CFG1,
++ WED_ADDR_ELEM_PREFETCH_FREE_CNT),
++
++ DUMP_STR("WED Route QM"),
++ DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT),
++ DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT),
++ DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT),
++ DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT),
++ DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT),
++ DUMP_WED(WED_RTQM_ENQ_ERR_CNT),
++
++ DUMP_WED(WED_RTQM_DEQ_DMAD_CNT),
++ DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT),
++ DUMP_WED(WED_RTQM_DEQ_PKT_CNT),
++ DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT),
++ DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT),
++ DUMP_WED(WED_RTQM_DEQ_ERR_CNT),
++
++ DUMP_END()
++ };
++
++ static const struct reg_dump *regs_new_v2[] = {
++ ®s_common[0],
++ ®s_v2[0],
++ NULL,
++ };
++
++ static const struct reg_dump *regs_new_v3[] = {
++ ®s_common[0],
++ ®s_v3[0],
++ NULL,
+ };
+
+ struct mtk_wed_hw *hw = s->private;
+ struct mtk_wed_device *dev = hw->wed_dev;
++ const struct reg_dump **regs;
+
+ if (!dev)
+ return 0;
+
+- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
++ switch(dev->hw->version) {
++ case 2:
++ regs = regs_new_v2;
++ break;
++ case 3:
++ regs = regs_new_v3;
++ break;
++ default:
++ return 0;
++ }
++
++ dump_wed_regs(s, dev, regs);
+
+ return 0;
+ }
+@@ -248,6 +357,381 @@ mtk_wed_reg_get(void *data, u64 *val)
+ DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
+ "0x%08llx\n");
+
++static int
++wed_token_txd_show(struct seq_file *s, void *data)
++{
++ struct mtk_wed_hw *hw = s->private;
++ struct mtk_wed_device *dev = hw->wed_dev;
++ struct mtk_wed_buf *page_list = dev->tx_buf_ring.pages;
++ int token = dev->wlan.token_start;
++ u32 val = hw->token_id, size = 1;
++ int page_idx = (val - token) / 2;
++ int i;
++
++ if (val < token) {
++ size = val;
++ page_idx = 0;
++ }
++
++ for (i = 0; i < size; i += MTK_WED_BUF_PER_PAGE) {
++ void *page = page_list[page_idx++].p;
++ void *buf;
++ int j;
++
++ if (!page)
++ break;
++
++ buf = page_to_virt(page);
++
++ for (j = 0; j < MTK_WED_BUF_PER_PAGE; j++) {
++ printk("[TXD]:token id = %d\n", token + 2 * (page_idx - 1) + j);
++ print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, (u8 *)buf, 128, false);
++ seq_printf(s, "\n");
++
++ buf += MTK_WED_BUF_SIZE;
++ }
++ }
++
++ return 0;
++}
++
++DEFINE_SHOW_ATTRIBUTE(wed_token_txd);
++
++static int
++wed_amsdu_show(struct seq_file *s, void *data)
++{
++ static const struct reg_dump regs_common[] = {
++ DUMP_STR("WED AMDSU INFO"),
++ DUMP_WED(WED_MON_AMSDU_FIFO_DMAD),
++
++ DUMP_STR("WED AMDSU ENG0 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(0)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(0)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(0)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(0)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(0)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(0),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(0),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG1 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(1)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(1)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(1)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(1)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(1)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(1),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(1),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG2 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(2)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(2)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(2)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(2)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(2)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(2),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(2),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG3 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(3)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(3)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(3)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(3)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(3)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(3),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(3),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG4 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(4)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(4)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(4)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(4)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(4)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(4),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG5 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(5)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(5)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(5)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(5)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(5)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(5),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(5),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG6 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(6)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(6)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(6)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(6)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(6)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(6),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(6),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG7 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(7)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(7)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(7)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(7)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(7)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(7),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(7),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(4),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED AMDSU ENG8 INFO"),
++ DUMP_WED(WED_MON_AMSDU_ENG_DMAD(8)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QFPL(8)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENI(8)),
++ DUMP_WED(WED_MON_AMSDU_ENG_QENO(8)),
++ DUMP_WED(WED_MON_AMSDU_ENG_MERG(8)),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8),
++ WED_AMSDU_ENG_MAX_PL_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT8(8),
++ WED_AMSDU_ENG_MAX_QGPP_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++ WED_AMSDU_ENG_CUR_ENTRY),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++ WED_AMSDU_ENG_MAX_BUF_MERGED),
++ DUMP_WED_MASK(WED_MON_AMSDU_ENG_CNT9(8),
++ WED_AMSDU_ENG_MAX_MSDU_MERGED),
++
++ DUMP_STR("WED QMEM INFO"),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_FQ_CNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(0), WED_AMSDU_QMEM_SP_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID0_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(1), WED_AMSDU_QMEM_TID1_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID2_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(2), WED_AMSDU_QMEM_TID3_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID4_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(3), WED_AMSDU_QMEM_TID5_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID6_QCNT),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_CNT(4), WED_AMSDU_QMEM_TID7_QCNT),
++
++ DUMP_STR("WED QMEM HEAD INFO"),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_FQ_HEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(0), WED_AMSDU_QMEM_SP_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID0_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(1), WED_AMSDU_QMEM_TID1_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID2_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(2), WED_AMSDU_QMEM_TID3_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID4_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(3), WED_AMSDU_QMEM_TID5_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID6_QHEAD),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(4), WED_AMSDU_QMEM_TID7_QHEAD),
++
++ DUMP_STR("WED QMEM TAIL INFO"),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_FQ_TAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(5), WED_AMSDU_QMEM_SP_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID0_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(6), WED_AMSDU_QMEM_TID1_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID2_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(7), WED_AMSDU_QMEM_TID3_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID4_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(8), WED_AMSDU_QMEM_TID5_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID6_QTAIL),
++ DUMP_WED_MASK(WED_MON_AMSDU_QMEM_PTR(9), WED_AMSDU_QMEM_TID7_QTAIL),
++
++ DUMP_STR("WED HIFTXD MSDU INFO"),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(1)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(2)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(3)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(4)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(5)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(6)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(7)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(8)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(9)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(10)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(11)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(12)),
++ DUMP_WED(WED_MON_AMSDU_HIFTXD_FETCH_MSDU(13)),
++ };
++
++ static const struct reg_dump *regs[] = {
++ ®s_common[0],
++ NULL,
++ };
++ struct mtk_wed_hw *hw = s->private;
++ struct mtk_wed_device *dev = hw->wed_dev;
++
++ if (!dev)
++ return 0;
++
++ dump_wed_regs(s, dev, regs);
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_amsdu);
++
++static int
++wed_rtqm_show(struct seq_file *s, void *data)
++{
++ static const struct reg_dump regs_common[] = {
++ DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"),
++ DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT),
++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT),
++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT),
++
++
++ DUMP_STR("WED Route QM IGRS1(Legacy)"),
++ DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT),
++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT),
++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT),
++
++ DUMP_STR("WED Route QM IGRS2(RRO3.0)"),
++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT),
++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT),
++
++ DUMP_STR("WED Route QM IGRS3(DEBUG)"),
++ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT),
++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)),
++ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)),
++ DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT),
++
++ DUMP_END()
++ };
++
++ static const struct reg_dump *regs[] = {
++ ®s_common[0],
++ NULL,
++ };
++ struct mtk_wed_hw *hw = s->private;
++ struct mtk_wed_device *dev = hw->wed_dev;
++
++ if (!dev)
++ return 0;
++
++ dump_wed_regs(s, dev, regs);
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_rtqm);
++
++
++static int
++wed_rro_show(struct seq_file *s, void *data)
++{
++ static const struct reg_dump regs_common[] = {
++ DUMP_STR("RRO/IND CMD CNT"),
++ DUMP_WED(WED_RX_IND_CMD_CNT(1)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(2)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(3)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(4)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(5)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(6)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(7)),
++ DUMP_WED(WED_RX_IND_CMD_CNT(8)),
++ DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9),
++ WED_IND_CMD_MAGIC_CNT_FAIL_CNT),
++
++ DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)),
++ DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1),
++ WED_ADDR_ELEM_SIG_FAIL_CNT),
++ DUMP_WED(WED_RX_MSDU_PG_CNT(1)),
++ DUMP_WED(WED_RX_MSDU_PG_CNT(2)),
++ DUMP_WED(WED_RX_MSDU_PG_CNT(3)),
++ DUMP_WED(WED_RX_MSDU_PG_CNT(4)),
++ DUMP_WED(WED_RX_MSDU_PG_CNT(5)),
++ DUMP_WED_MASK(WED_RX_PN_CHK_CNT,
++ WED_PN_CHK_FAIL_CNT),
++
++ DUMP_END()
++ };
++
++ static const struct reg_dump *regs[] = {
++ ®s_common[0],
++ NULL,
++ };
++ struct mtk_wed_hw *hw = s->private;
++ struct mtk_wed_device *dev = hw->wed_dev;
++
++ if (!dev)
++ return 0;
++
++ dump_wed_regs(s, dev, regs);
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(wed_rro);
++
+ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+ {
+ struct dentry *dir;
+@@ -261,8 +745,20 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
+ debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
+ debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
+ debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
+- debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
+- if (hw->version != 1) {
++ debugfs_create_u32("token_id", 0600, dir, &hw->token_id);
++ debugfs_create_file_unsafe("token_txd", 0600, dir, hw, &wed_token_txd_fops);
++
++ if (!mtk_wed_is_v1(hw)) {
++ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw,
++ &wed_rxinfo_fops);
+ wed_wo_mcu_debugfs(hw, dir);
++ if (mtk_wed_is_v3_or_greater(hw)) {
++ debugfs_create_file_unsafe("amsdu", 0400, dir, hw,
++ &wed_amsdu_fops);
++ debugfs_create_file_unsafe("rtqm", 0400, dir, hw,
++ &wed_rtqm_fops);
++ debugfs_create_file_unsafe("rro", 0400, dir, hw,
++ &wed_rro_fops);
++ }
+ }
+ }
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+index be63406..18d1fb1 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+@@ -91,7 +91,7 @@ mtk_wed_mcu_msg_update(struct mtk_wed_device *dev, int id, void *data, int len)
+ {
+ struct mtk_wed_wo *wo = dev->hw->wed_wo;
+
+- if (dev->hw->version == 1)
++ if (!mtk_wed_get_rx_capa(dev))
+ return 0;
+
+ if (WARN_ON(!wo))
+@@ -248,7 +248,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ u8 reserved1[15];
+ } __packed *region;
+
+- char *mcu;
++ char *fw_name;
+ const struct mtk_wed_fw_trailer *hdr;
+ static u8 shared[MAX_REGION_SIZE] = {0};
+ const struct firmware *fw;
+@@ -256,13 +256,24 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ u32 ofs = 0;
+ u32 boot_cr, val;
+
+- if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed"))
+- mcu = MT7981_FIRMWARE_WO;
+- else
+- mcu = wo->hw->index ? MT7986_FIRMWARE_WO_2 :
+- MT7986_FIRMWARE_WO_1;
++ switch (wo->hw->version) {
++ case 2:
++ if (of_device_is_compatible(wo->hw->node,
++ "mediatek,mt7981-wed"))
++ fw_name = MT7981_FIRMWARE_WO;
++ else
++ fw_name = wo->hw->index ? MT7986_FIRMWARE_WO1
++ : MT7986_FIRMWARE_WO0;
++ break;
++ case 3:
++ fw_name = wo->hw->index ? MT7988_FIRMWARE_WO1
++ : MT7988_FIRMWARE_WO0;
++ break;
++ default:
++ return -EINVAL;
++ }
+
+- ret = request_firmware(&fw, mcu, wo->hw->dev);
++ ret = request_firmware(&fw, fw_name, wo->hw->dev);
+ if (ret)
+ return ret;
+
+@@ -307,8 +318,11 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+ }
+
+ /* write the start address */
+- boot_cr = wo->hw->index ?
+- WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
++ if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)
++ boot_cr = WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR;
++ else
++ boot_cr = WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
++
+ wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
+
+ /* wo firmware reset */
+@@ -316,8 +330,10 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+
+ val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
+
+- val |= wo->hw->index ? WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK :
+- WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
++ if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)
++ val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK;
++ else
++ val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
+
+ wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+index dbb17ae..6d4c9a7 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+@@ -17,8 +17,11 @@
+ #define WARP_ALREADY_DONE_STATUS (1)
+
+ #define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin"
+-#define MT7986_FIRMWARE_WO_1 "mediatek/mt7986_wo_0.bin"
+-#define MT7986_FIRMWARE_WO_2 "mediatek/mt7986_wo_1.bin"
++#define MT7986_FIRMWARE_WO0 "mediatek/mt7986_wo_0.bin"
++#define MT7986_FIRMWARE_WO1 "mediatek/mt7986_wo_1.bin"
++#define MT7988_FIRMWARE_WO0 "mediatek/mtk_wo_0.bin"
++#define MT7988_FIRMWARE_WO1 "mediatek/mtk_wo_1.bin"
++#define MT7988_FIRMWARE_WO2 "mediatek/mtk_wo_2.bin"
+
+ #define WOCPU_EMI_DEV_NODE "mediatek,wocpu_emi"
+ #define WOCPU_ILM_DEV_NODE "mediatek,wocpu_ilm"
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+index 645b8b1..0af264d 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+@@ -14,6 +14,9 @@
+ #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31)
+ #define MTK_WED_RX_BM_TOKEN GENMASK(31, 16)
+
++#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE BIT(29)
++#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE BIT(31)
++
+ struct mtk_wdma_desc {
+ __le32 buf0;
+ __le32 ctrl;
+@@ -45,6 +48,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
+ #define MTK_WED_RESET_RX_RRO_QM BIT(20)
+ #define MTK_WED_RESET_RX_ROUTE_QM BIT(21)
++#define MTK_WED_RESET_TX_AMSDU BIT(22)
+ #define MTK_WED_RESET_WED BIT(31)
+
+ #define MTK_WED_CTRL 0x00c
+@@ -52,6 +56,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1)
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2)
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3)
++#define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5)
++#define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6)
++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU BIT(7)
+ #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8)
+ #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
+ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
+@@ -62,9 +69,14 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15)
+ #define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16)
+ #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17)
++#define MTK_WED_CTRL_TX_TKID_ALI_EN BIT(20)
++#define MTK_WED_CTRL_TX_TKID_ALI_BUSY BIT(21)
++#define MTK_WED_CTRL_TX_AMSDU_EN BIT(22)
++#define MTK_WED_CTRL_TX_AMSDU_BUSY BIT(23)
+ #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
+ #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25)
+ #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
++#define MTK_WED_CTRL_FLD_MIB_RD_CLR BIT(28)
+
+ #define MTK_WED_EXT_INT_STATUS 0x020
+ #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0)
+@@ -72,12 +84,10 @@ struct mtk_wdma_desc {
+ #define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID BIT(4)
+ #define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH BIT(8)
+ #define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH BIT(9)
+-#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+-#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH BIT(10)
+-#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH BIT(11)
+-#endif
+-#define MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY BIT(12)
+-#define MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER BIT(13)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 BIT(10)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 BIT(11)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12)
++#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17)
+ #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18)
+@@ -94,17 +104,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
+ MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
+ MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
+- MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY | \
+- MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER | \
+ MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
+ MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
+ MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
+- MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR | \
+- MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
++ MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR)
+
+ #define MTK_WED_EXT_INT_MASK 0x028
+ #define MTK_WED_EXT_INT_MASK1 0x02c
+ #define MTK_WED_EXT_INT_MASK2 0x030
++#define MTK_WED_EXT_INT_MASK3 0x034
+
+ #define MTK_WED_STATUS 0x060
+ #define MTK_WED_STATUS_TX GENMASK(15, 8)
+@@ -112,12 +120,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_BM_CTRL 0x080
+ #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0)
+ #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16)
++#define MTK_WED_TX_BM_CTRL_LEGACY_EN BIT(26)
++#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT BIT(27)
+ #define MTK_WED_TX_BM_CTRL_PAUSE BIT(28)
+
+ #define MTK_WED_TX_BM_BASE 0x084
++#define MTK_WED_TX_BM_INIT_PTR 0x088
++#define MTK_WED_TX_BM_SW_TAIL_IDX GENMASK(16, 0)
++#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX BIT(16)
+
+-#define MTK_WED_TX_BM_TKID 0x088
+-#define MTK_WED_TX_BM_TKID_V2 0x0c8
+ #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
+ #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
+
+@@ -140,6 +151,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16)
+ #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28)
+
++#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0)
++#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16)
++
+ #define MTK_WED_TX_TKID_DYN_THR 0x0e0
+ #define MTK_WED_TX_TKID_DYN_THR_LO GENMASK(6, 0)
+ #define MTK_WED_TX_TKID_DYN_THR_HI GENMASK(22, 16)
+@@ -205,12 +219,15 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC BIT(5)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC BIT(6)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC BIT(7)
+-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(18, 16)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(15, 12)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4 BIT(18)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT BIT(19)
+-#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20)
++#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK BIT(20)
+ #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR BIT(21)
+ #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP BIT(24)
++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST BIT(25)
+ #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV BIT(28)
++#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK BIT(30)
+
+ /* CONFIG_MEDIATEK_NETSYS_V1 */
+ #define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE GENMASK(5, 4)
+@@ -273,9 +290,11 @@ struct mtk_wdma_desc {
+ #define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16)
+
+ #define MTK_WED_PCIE_INT_CTRL 0x57c
+-#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20)
++#define MTK_WED_PCIE_INT_CTRL_POLL_EN GENMASK(13, 12)
+ #define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16)
+-#define MTK_WED_PCIE_INT_CTRL_POLL_EN GENMASK(13, 12)
++#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20)
++#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER BIT(21)
++
+ #define MTK_WED_WPDMA_CFG_BASE 0x580
+ #define MTK_WED_WPDMA_CFG_INT_MASK 0x584
+ #define MTK_WED_WPDMA_CFG_TX 0x588
+@@ -304,20 +323,50 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24)
+
+ #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c
+-#define MTK_WED_WPDMA_RX_RING 0x770
++#if defined(CONFIG_MEDIATEK_NETSYS_V2)
++#define MTK_WED_WPDMA_RX_RING0 0x770
++#else
++#define MTK_WED_WPDMA_RX_RING0 0x7d0
++#endif
++#define MTK_WED_WPDMA_RX_RING1 0x7d8
+
+ #define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4)
+ #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4)
+ #define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c
+
++#define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4
++#define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8)
++#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16)
++
++#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX 0x7b8
++#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR BIT(15)
++
++#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX 0x7bc
++
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG 0x7c0
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR BIT(16)
++
+ #define MTK_WED_WDMA_RING_TX 0x800
+
+ #define MTK_WED_WDMA_TX_MIB 0x810
+
+-
+ #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10)
+ #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4)
+
++#define MTK_WED_WDMA_RX_PREF_CFG 0x950
++#define MTK_WED_WDMA_RX_PREF_EN BIT(0)
++#define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8)
++#define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16)
++#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24)
++#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25)
++#define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26)
++
++#define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C
++#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0)
++#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR BIT(16)
++
+ #define MTK_WED_WDMA_GLO_CFG 0xa04
+ #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0)
+ #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1)
+@@ -350,6 +399,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16)
+
+ #define MTK_WED_WDMA_INT_CTRL 0xa2c
++#define MTK_WED_WDMA_INT_POLL_PRD GENMASK(7, 0)
+ #define MTK_WED_WDMA_INT_POLL_SRC_SEL GENMASK(17, 16)
+
+ #define MTK_WED_WDMA_CFG_BASE 0xaa0
+@@ -369,7 +419,7 @@ struct mtk_wdma_desc {
+
+ #define MTK_WED_RX_BM_BASE 0xd84
+ #define MTK_WED_RX_BM_INIT_PTR 0xd88
+-#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0)
++#define MTK_WED_RX_BM_SW_TAIL GENMASK(15, 0)
+ #define MTK_WED_RX_BM_INIT_SW_TAIL BIT(16)
+
+ #define MTK_WED_RX_PTR 0xd8c
+@@ -411,6 +461,18 @@ struct mtk_wdma_desc {
+ #define MTK_WDMA_INT_GRP1 0x250
+ #define MTK_WDMA_INT_GRP2 0x254
+
++#define MTK_WDMA_PREF_TX_CFG 0x2d0
++#define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0)
++
++#define MTK_WDMA_PREF_RX_CFG 0x2dc
++#define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0)
++
++#define MTK_WDMA_WRBK_TX_CFG 0x300
++#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30)
++
++#define MTK_WDMA_WRBK_RX_CFG 0x344
++#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30)
++
+ #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0)
+ #define MTK_PCIE_MIRROR_MAP_EN BIT(0)
+ #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1)
+@@ -419,11 +481,36 @@ struct mtk_wdma_desc {
+ #define HIFSYS_DMA_AG_MAP 0x008
+
+ #define MTK_WED_RTQM_GLO_CFG 0xb00
+-#define MTK_WED_RTQM_BUSY BIT(1)
+-#define MTK_WED_RTQM_Q_RST BIT(2)
++#define MTK_WED_RTQM_BUSY BIT(1)
++#define MTK_WED_RTQM_Q_RST BIT(2)
+ #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5)
+ #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20)
+
++#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c
++#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28
++#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n) (0xb2c + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS0_FDROP_CNT 0xb34
++
++
++#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT 0xb44
++#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n) (0xb48 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT 0xb50
++#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n) (0xb54 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS1_FDROP_CNT 0xb5c
++
++#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT 0xb6c
++#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n) (0xb70 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT 0xb78
++#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n) (0xb7c + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS2_FDROP_CNT 0xb84
++
++#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT 0xb94
++#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n) (0xb98 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT 0xba0
++#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n) (0xba4 + (_n) * 0x4)
++#define MTK_WED_RTQM_IGRS3_FDROP_CNT 0xbac
++
+ #define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4)
+ #define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4)
+ #define MTK_WED_RTQM_Q2N_MIB 0xb80
+@@ -432,21 +519,39 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RTQM_Q2B_MIB 0xb8c
+ #define MTK_WED_RTQM_PFDBK_MIB 0xb90
+
++#define MTK_WED_RTQM_ENQ_CFG0 0xbb8
++#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT GENMASK(15, 12)
++
++#define MTK_WED_RTQM_FDROP_MIB 0xb84
++#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT 0xbbc
++#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT 0xbc0
++#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT 0xbc4
++#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT 0xbc8
++#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT 0xbcc
++#define MTK_WED_RTQM_ENQ_ERR_CNT 0xbd0
++
++#define MTK_WED_RTQM_DEQ_DMAD_CNT 0xbd8
++#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT 0xbdc
++#define MTK_WED_RTQM_DEQ_PKT_CNT 0xbe0
++#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT 0xbe4
++#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT 0xbe8
++#define MTK_WED_RTQM_DEQ_ERR_CNT 0xbec
++
+ #define MTK_WED_RROQM_GLO_CFG 0xc04
+ #define MTK_WED_RROQM_RST_IDX 0xc08
+-#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0)
+-#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4)
++#define MTK_WED_RROQM_RST_IDX_MIOD BIT(0)
++#define MTK_WED_RROQM_RST_IDX_FDBK BIT(4)
+
+ #define MTK_WED_RROQM_MIOD_CTRL0 0xc40
+ #define MTK_WED_RROQM_MIOD_CTRL1 0xc44
+-#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0)
++#define MTK_WED_RROQM_MIOD_CNT GENMASK(11, 0)
+
+ #define MTK_WED_RROQM_MIOD_CTRL2 0xc48
+ #define MTK_WED_RROQM_MIOD_CTRL3 0xc4c
+
+ #define MTK_WED_RROQM_FDBK_CTRL0 0xc50
+ #define MTK_WED_RROQM_FDBK_CTRL1 0xc54
+-#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0)
++#define MTK_WED_RROQM_FDBK_CNT GENMASK(11, 0)
+
+ #define MTK_WED_RROQM_FDBK_CTRL2 0xc58
+
+@@ -454,7 +559,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RROQ_BASE_H 0xc84
+
+ #define MTK_WED_RROQM_MIOD_CFG 0xc8c
+-#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0)
++#define MTK_WED_RROQM_MIOD_MID_DW GENMASK(5, 0)
+ #define MTK_WED_RROQM_MIOD_MOD_DW GENMASK(13, 8)
+ #define MTK_WED_RROQM_MIOD_ENTRY_DW GENMASK(22, 16)
+
+@@ -468,20 +573,206 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RROQM_FDBK_ANC_MIB 0xce8
+ #define MTK_WED_RROQM_FDBK_ANC2H_MIB 0xcec
+
+-#define MTK_WED_RX_BM_RX_DMAD 0xd80
++#define MTK_WED_RX_BM_RX_DMAD 0xd80
+ #define MTK_WED_RX_BM_BASE 0xd84
+ #define MTK_WED_RX_BM_INIT_PTR 0xd88
+-#define MTK_WED_RX_BM_PTR 0xd8c
+-#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16)
++#define MTK_WED_RX_BM_PTR 0xd8c
+ #define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0)
++#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16)
+
+-#define MTK_WED_RX_BM_BLEN 0xd90
++#define MTK_WED_RX_BM_BLEN 0xd90
+ #define MTK_WED_RX_BM_STS 0xd94
+ #define MTK_WED_RX_BM_INTF2 0xd98
+ #define MTK_WED_RX_BM_INTF 0xd9c
+ #define MTK_WED_RX_BM_ERR_STS 0xda8
+
+-#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000
++#define MTK_RRO_IND_CMD_SIGNATURE 0xe00
++#define MTK_RRO_IND_CMD_DMA_IDX GENMASK(11, 0)
++#define MTK_RRO_IND_CMD_MAGIC_CNT GENMASK(30, 28)
++
++#define MTK_WED_IND_CMD_RX_CTRL0 0xe04
++#define MTK_WED_IND_CMD_PROC_IDX GENMASK(11, 0)
++#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT GENMASK(19, 16)
++#define MTK_WED_IND_CMD_MAGIC_CNT GENMASK(30, 28)
++
++#define MTK_WED_IND_CMD_RX_CTRL1 0xe08
++#define MTK_WED_IND_CMD_RX_CTRL2 0xe0c
++#define MTK_WED_IND_CMD_MAX_CNT GENMASK(11, 0)
++#define MTK_WED_IND_CMD_BASE_M GENMASK(19, 16)
++
++#define MTK_WED_RRO_CFG0 0xe10
++#define MTK_WED_RRO_CFG1 0xe14
++#define MTK_WED_RRO_CFG1_MAX_WIN_SZ GENMASK(31, 29)
++#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M GENMASK(19, 16)
++#define MTK_WED_RRO_CFG1_PARTICL_SE_ID GENMASK(11, 0)
++
++#define MTK_WED_ADDR_ELEM_CFG0 0xe18
++#define MTK_WED_ADDR_ELEM_CFG1 0xe1c
++#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT GENMASK(19, 16)
++
++#define MTK_WED_ADDR_ELEM_TBL_CFG 0xe20
++#define MTK_WED_ADDR_ELEM_TBL_OFFSET GENMASK(6, 0)
++#define MTK_WED_ADDR_ELEM_TBL_RD_RDY BIT(28)
++#define MTK_WED_ADDR_ELEM_TBL_WR_RDY BIT(29)
++#define MTK_WED_ADDR_ELEM_TBL_RD BIT(30)
++#define MTK_WED_ADDR_ELEM_TBL_WR BIT(31)
++
++#define MTK_WED_RADDR_ELEM_TBL_WDATA 0xe24
++#define MTK_WED_RADDR_ELEM_TBL_RDATA 0xe28
++
++#define MTK_WED_PN_CHECK_CFG 0xe30
++#define MTK_WED_PN_CHECK_SE_ID GENMASK(11, 0)
++#define MTK_WED_PN_CHECK_RD_RDY BIT(28)
++#define MTK_WED_PN_CHECK_WR_RDY BIT(29)
++#define MTK_WED_PN_CHECK_RD BIT(30)
++#define MTK_WED_PN_CHECK_WR BIT(31)
++
++#define MTK_WED_PN_CHECK_WDATA_M 0xe38
++#define MTK_WED_PN_CHECK_IS_FIRST BIT(17)
++
++#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n) (0xe44 + (_n) * 0x8)
++
++#define MTK_WED_RRO_MSDU_PG_RING2_CFG 0xe58
++#define MTK_WED_RRO_MSDU_PG_DRV_CLR BIT(26)
++#define MTK_WED_RRO_MSDU_PG_DRV_EN BIT(31)
++
++#define MTK_WED_RRO_MSDU_PG_CTRL0(_n) (0xe5c + (_n) * 0xc)
++#define MTK_WED_RRO_MSDU_PG_CTRL1(_n) (0xe60 + (_n) * 0xc)
++#define MTK_WED_RRO_MSDU_PG_CTRL2(_n) (0xe64 + (_n) * 0xc)
++
++#define MTK_WED_RRO_RX_D_RX(_n) (0xe80 + (_n) * 0x10)
++
++#define MTK_WED_RRO_RX_MAGIC_CNT BIT(13)
++
++#define MTK_WED_RRO_RX_D_CFG(_n) (0xea0 + (_n) * 0x4)
++#define MTK_WED_RRO_RX_D_DRV_CLR BIT(26)
++#define MTK_WED_RRO_RX_D_DRV_EN BIT(31)
++
++#define MTK_WED_RRO_PG_BM_RX_DMAM 0xeb0
++#define MTK_WED_RRO_PG_BM_RX_SDL0 GENMASK(13, 0)
++
++#define MTK_WED_RRO_PG_BM_BASE 0xeb4
++#define MTK_WED_RRO_PG_BM_INIT_PTR 0xeb8
++#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX GENMASK(15, 0)
++#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX BIT(16)
++
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX 0xeec
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN BIT(0)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR BIT(1)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG GENMASK(6, 2)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN BIT(8)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR BIT(9)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG GENMASK(14, 10)
++
++#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG 0xef4
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN BIT(0)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR BIT(1)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG GENMASK(6, 2)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN BIT(8)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR BIT(9)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG GENMASK(14, 10)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN BIT(16)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17)
++#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18)
++
++#define MTK_WED_RX_IND_CMD_CNT0 0xf20
++#define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31)
++
++#define MTK_WED_RX_IND_CMD_CNT(_n) (0xf20 + (_n) * 0x4)
++#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT GENMASK(15, 0)
++
++#define MTK_WED_RX_ADDR_ELEM_CNT(_n) (0xf48 + (_n) * 0x4)
++#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT GENMASK(15, 0)
++#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT GENMASK(31, 16)
++#define MTK_WED_ADDR_ELEM_ACKSN_CNT GENMASK(27, 0)
++
++#define MTK_WED_RX_MSDU_PG_CNT(_n) (0xf5c + (_n) * 0x4)
++
++#define MTK_WED_RX_PN_CHK_CNT 0xf70
++#define MTK_WED_PN_CHK_FAIL_CNT GENMASK(15, 0)
++
++#define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000
+ #define MTK_WED_PCIE_INT_MASK 0x0
+
++#define MTK_WED_AMSDU_FIFO 0x1800
++#define MTK_WED_AMSDU_IS_PRIOR0_RING BIT(10)
++
++#define MTK_WED_AMSDU_STA_INFO 0x01810
++#define MTK_WED_AMSDU_STA_INFO_DO_INIT BIT(0)
++#define MTK_WED_AMSDU_STA_INFO_SET_INIT BIT(1)
++
++#define MTK_WED_AMSDU_STA_INFO_INIT 0x01814
++#define MTK_WED_AMSDU_STA_WTBL_HDRT_MODE BIT(0)
++#define MTK_WED_AMSDU_STA_RMVL BIT(1)
++#define MTK_WED_AMSDU_STA_MAX_AMSDU_LEN GENMASK(7, 2)
++#define MTK_WED_AMSDU_STA_MAX_AMSDU_NUM GENMASK(11, 8)
++
++#define MTK_WED_AMSDU_HIFTXD_BASE_L(_n) (0x1980 + (_n) * 0x4)
++
++#define MTK_WED_AMSDU_PSE 0x1910
++#define MTK_WED_AMSDU_PSE_RESET BIT(16)
++
++#define MTK_WED_AMSDU_HIFTXD_CFG 0x1968
++#define MTK_WED_AMSDU_HIFTXD_SRC GENMASK(16, 15)
++
++#define MTK_WED_MON_AMSDU_FIFO_DMAD 0x1a34
++
++#define MTK_WED_MON_AMSDU_ENG_DMAD(_n) (0x1a80 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QFPL(_n) (0x1a84 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QENI(_n) (0x1a88 + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_QENO(_n) (0x1a8c + (_n) * 0x50)
++#define MTK_WED_MON_AMSDU_ENG_MERG(_n) (0x1a90 + (_n) * 0x50)
++
++#define MTK_WED_MON_AMSDU_ENG_CNT8(_n) (0x1a94 + (_n) * 0x50)
++#define MTK_WED_AMSDU_ENG_MAX_QGPP_CNT GENMASK(10, 0)
++#define MTK_WED_AMSDU_ENG_MAX_PL_CNT GENMASK(27, 16)
++
++#define MTK_WED_MON_AMSDU_ENG_CNT9(_n) (0x1a98 + (_n) * 0x50)
++#define MTK_WED_AMSDU_ENG_CUR_ENTRY GENMASK(10, 0)
++#define MTK_WED_AMSDU_ENG_MAX_BUF_MERGED GENMASK(20, 16)
++#define MTK_WED_AMSDU_ENG_MAX_MSDU_MERGED GENMASK(28, 24)
++
++#define MTK_WED_MON_AMSDU_QMEM_STS1 0x1e04
++
++#define MTK_WED_MON_AMSDU_QMEM_CNT(_n) (0x1e0c + (_n) * 0x4)
++#define MTK_WED_AMSDU_QMEM_FQ_CNT GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QCNT GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QCNT GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QCNT GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QCNT GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QCNT GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QCNT GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QCNT GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QCNT GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QCNT GENMASK(11, 0)
++
++#define MTK_WED_MON_AMSDU_QMEM_PTR(_n) (0x1e20 + (_n) * 0x4)
++#define MTK_WED_AMSDU_QMEM_FQ_HEAD GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QHEAD GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QHEAD GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QHEAD GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QHEAD GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QHEAD GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QHEAD GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QHEAD GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QHEAD GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QHEAD GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_FQ_TAIL GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_SP_QTAIL GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID0_QTAIL GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID1_QTAIL GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID2_QTAIL GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID3_QTAIL GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID4_QTAIL GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID5_QTAIL GENMASK(11, 0)
++#define MTK_WED_AMSDU_QMEM_TID6_QTAIL GENMASK(27, 16)
++#define MTK_WED_AMSDU_QMEM_TID7_QTAIL GENMASK(11, 0)
++
++#define MTK_WED_MON_AMSDU_HIFTXD_FETCH_MSDU(_n) (0x1ec4 + (_n) * 0x4)
++
++#define MTK_WED_PCIE_BASE 0x11280000
++
++#define MTK_WED_PCIE_BASE0 0x11300000
++#define MTK_WED_PCIE_BASE1 0x11310000
++#define MTK_WED_PCIE_BASE2 0x11290000
+ #endif
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index b2abebe..a9e455d 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -880,6 +880,13 @@ struct net_device_path {
+ u8 queue;
+ u16 wcid;
+ u8 bss;
++ u32 usr_info;
++ u8 tid;
++ u8 is_fixedrate;
++ u8 is_prior;
++ u8 is_sp;
++ u8 hf;
++ u8 amsdu;
+ } mtk_wdma;
+ };
+ };
+diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
+index 470beb2..e81e41f 100644
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -5,9 +5,12 @@
+ #include <linux/rcupdate.h>
+ #include <linux/regmap.h>
+ #include <linux/pci.h>
++#include <linux/skbuff.h>
++#include <linux/iopoll.h>
+
+ #define MTK_WED_TX_QUEUES 2
+ #define MTK_WED_RX_QUEUES 2
++#define MTK_WED_RX_PAGE_QUEUES 3
+
+ #define WED_WO_STA_REC 0x6
+
+@@ -43,7 +46,7 @@ enum mtk_wed_wo_cmd {
+ MTK_WED_WO_CMD_WED_END
+ };
+
+-struct mtk_rxbm_desc {
++struct mtk_wed_bm_desc {
+ __le32 buf0;
+ __le32 token;
+ } __packed __aligned(4);
+@@ -74,6 +77,11 @@ struct mtk_wed_wo_rx_stats {
+ __le32 rx_drop_cnt;
+ };
+
++struct mtk_wed_buf {
++ void *p;
++ dma_addr_t phy_addr;
++};
++
+ struct mtk_wed_device {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ const struct mtk_wed_ops *ops;
+@@ -92,10 +100,13 @@ struct mtk_wed_device {
+ struct mtk_wed_ring txfree_ring;
+ struct mtk_wed_ring tx_wdma[MTK_WED_TX_QUEUES];
+ struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
++ struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES];
++ struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES];
++ struct mtk_wed_ring ind_cmd_ring;
+
+ struct {
+ int size;
+- void **pages;
++ struct mtk_wed_buf *pages;
+ struct mtk_wdma_desc *desc;
+ dma_addr_t desc_phys;
+ } tx_buf_ring;
+@@ -103,7 +114,7 @@ struct mtk_wed_device {
+ struct {
+ int size;
+ struct page_frag_cache rx_page;
+- struct mtk_rxbm_desc *desc;
++ struct mtk_wed_bm_desc *desc;
+ dma_addr_t desc_phys;
+ } rx_buf_ring;
+
+@@ -114,6 +125,13 @@ struct mtk_wed_device {
+ dma_addr_t fdbk_phys;
+ } rro;
+
++ struct {
++ int size;
++ struct mtk_wed_buf *pages;
++ struct mtk_wed_bm_desc *desc;
++ dma_addr_t desc_phys;
++ } hw_rro;
++
+ /* filled by driver: */
+ struct {
+ union {
+@@ -123,6 +141,7 @@ struct mtk_wed_device {
+ enum mtk_wed_bus_tye bus_type;
+ void __iomem *base;
+ u32 phy_base;
++ u32 id;
+
+ u32 wpdma_phys;
+ u32 wpdma_int;
+@@ -130,10 +149,14 @@ struct mtk_wed_device {
+ u32 wpdma_tx;
+ u32 wpdma_txfree;
+ u32 wpdma_rx_glo;
+- u32 wpdma_rx;
++ u32 wpdma_rx[MTK_WED_RX_QUEUES];
++ u32 wpdma_rx_rro[MTK_WED_RX_QUEUES];
++ u32 wpdma_rx_pg;
+
+ u8 tx_tbit[MTK_WED_TX_QUEUES];
+ u8 rx_tbit[MTK_WED_RX_QUEUES];
++ u8 rro_rx_tbit[MTK_WED_RX_QUEUES];
++ u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES];
+ u8 txfree_tbit;
+
+ u16 token_start;
+@@ -141,8 +164,22 @@ struct mtk_wed_device {
+ unsigned int rx_nbuf;
+ unsigned int rx_npkt;
+ unsigned int rx_size;
++ unsigned int amsdu_max_len;
+
+ bool wcid_512;
++ bool hw_rro;
++ bool msi;
++
++ u8 amsdu_max_subframes;
++
++ struct {
++ u8 se_group_nums;
++ u16 win_size;
++ u16 particular_sid;
++ u32 ack_sn_addr;
++ dma_addr_t particular_se_phys;
++ dma_addr_t addr_elem_phys[1024];
++ } ind_cmd;
+
+ u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
+ int (*offload_enable)(struct mtk_wed_device *wed);
+@@ -185,6 +222,13 @@ struct mtk_wed_ops {
+
+ u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
++ void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask);
++ void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++ void __iomem *regs);
++ void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
++ void __iomem *regs);
++ int (*ind_rx_ring_setup)(struct mtk_wed_device *dev,
++ void __iomem *regs);
+ };
+
+ extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
+@@ -213,12 +257,25 @@ static inline bool
+ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ {
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ if (dev->version == 3)
++ return dev->wlan.hw_rro;
++
+ return dev->version != 1;
+ #else
+ return false;
+ #endif
+ }
+
++static inline bool
++mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev)
++{
++#ifdef CONFIG_NET_MEDIATEK_SOC_WED
++ return dev->version == 3;
++#else
++ return false;
++#endif
++}
++
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ #define mtk_wed_device_active(_dev) !!(_dev)->ops
+ #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
+@@ -245,6 +302,14 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
+ (_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
++#define mtk_wed_device_start_hw_rro(_dev, _mask) \
++ (_dev)->ops->start_hw_rro(_dev, _mask)
++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
++ (_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
++ (_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs)
++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \
++ (_dev)->ops->ind_rx_ring_setup(_dev, _regs)
+ #else
+ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ {
+@@ -264,6 +329,10 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_stop(_dev) do {} while (0)
+ #define mtk_wed_device_dma_reset(_dev) do {} while (0)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
++#define mtk_wed_device_start_hw_rro(_dev, _mask) do {} while (0)
++#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
++#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) -ENODEV
++#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) -ENODEV
+ #endif
+
+ #endif
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3020-mtk-wed-add-wed3-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3020-mtk-wed-add-wed3-ser-support.patch
new file mode 100644
index 0000000..7423a6e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3020-mtk-wed-add-wed3-ser-support.patch
@@ -0,0 +1,697 @@
+From 67a20e07982e9c43d299679f75fd81638271fc63 Mon Sep 17 00:00:00 2001
+From: mtk27745 <rex.lu@mediatek.com>
+Date: Mon, 18 Sep 2023 13:22:44 +0800
+Subject: [PATCH 2/6] mtk wed add wed3 ser support
+
+---
+ drivers/net/ethernet/mediatek/mtk_wed.c | 339 ++++++++++++++++---
+ drivers/net/ethernet/mediatek/mtk_wed_regs.h | 68 +++-
+ include/linux/soc/mediatek/mtk_wed.h | 8 +-
+ 3 files changed, 367 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index 4b32a82..02c156a 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -110,24 +110,88 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
+ return wdma_r32(dev, MTK_WDMA_GLO_CFG);
+ }
+
+-static u32
+-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++static void
++mtk_wdma_v3_rx_reset(struct mtk_wed_device *dev)
+ {
+- if (wed_r32(dev, reg) & mask)
+- return true;
+-
+- return false;
+-}
++ u32 status;
+
+-static int
+-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+- int sleep = 1000;
+- int timeout = 100 * sleep;
+- u32 val;
++ if (!mtk_wed_is_v3_or_greater(dev->hw))
++ return;
+
+- return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
+- timeout, false, dev, reg, mask);
++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG))
++ dev_err(dev->hw->dev, "rx reset failed\n");
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG))
++ dev_err(dev->hw->dev, "rx reset failed\n");
++
++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG))
++ dev_err(dev->hw->dev, "rx reset failed\n");
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG))
++ dev_err(dev->hw->dev, "rx reset failed\n");
++
++ /* prefetch FIFO */
++ wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
++ wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
++ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
++ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
++
++ /* core FIFO */
++ wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG,
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
++ wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG,
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
++ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
++
++ /* writeback FIFO */
++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0),
++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1),
++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++
++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0),
++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1),
++ MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
++
++ /* prefetch ring status */
++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG,
++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG,
++ MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
++
++ /* writeback ring status */
++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG,
++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG,
++ MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
+ }
+
+ static int
+@@ -142,6 +206,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ if (ret)
+ dev_err(dev->hw->dev, "rx reset failed \n");
+
++ mtk_wdma_v3_rx_reset(dev);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+
+@@ -156,6 +221,101 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
+ return ret;
+ }
+
++static u32
++mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++ return !!(wed_r32(dev, reg) & mask);
++}
++
++static int
++mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
++{
++ int sleep = 15000;
++ int timeout = 100 * sleep;
++ u32 val;
++
++ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
++ timeout, false, dev, reg, mask);
++}
++
++static void
++mtk_wdma_v3_tx_reset(struct mtk_wed_device *dev)
++{
++ u32 status;
++
++ if (!mtk_wed_is_v3_or_greater(dev->hw))
++ return;
++
++ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
++ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_PREF_TX_CFG))
++ dev_err(dev->hw->dev, "tx reset failed\n");
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_PREF_RX_CFG))
++ dev_err(dev->hw->dev, "tx reset failed\n");
++
++ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
++ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_WRBK_TX_CFG))
++ dev_err(dev->hw->dev, "tx reset failed\n");
++
++ if (read_poll_timeout(wdma_r32, status,
++ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY),
++ 0, 10000, false, dev, MTK_WDMA_WRBK_RX_CFG))
++ dev_err(dev->hw->dev, "tx reset failed\n");
++
++ /* prefetch FIFO */
++ wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
++ wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
++ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
++ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
++
++ /* core FIFO */
++ wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG,
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
++ wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG,
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
++ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
++
++ /* writeback FIFO */
++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0),
++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1),
++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++
++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0),
++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1),
++ MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
++
++ /* prefetch ring status */
++ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG,
++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG,
++ MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
++
++ /* writeback ring status */
++ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG,
++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
++ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG,
++ MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
++}
++
+ static void
+ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+ {
+@@ -167,6 +327,7 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
+ !(status & mask), 0, 10000))
+ dev_err(dev->hw->dev, "tx reset failed \n");
+
++ mtk_wdma_v3_tx_reset(dev);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
+ wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
+
+@@ -1389,25 +1550,6 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
+ }
+ }
+
+-static u32
+-mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+- if (wed_r32(dev, reg) & mask)
+- return true;
+-
+- return false;
+-}
+-
+-static int
+-mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
+-{
+- int sleep = 1000;
+- int timeout = 100 * sleep;
+- u32 val;
+-
+- return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
+- timeout, false, dev, reg, mask);
+-}
+
+ static int
+ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+@@ -1423,13 +1565,32 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ if (ret)
+ return ret;
+
++ if (dev->wlan.hw_rro) {
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS,
++ MTK_WED_RX_IND_CMD_BUSY);
++ mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG);
++ }
++
+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
+ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
+ MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
++ if (!ret && mtk_wed_is_v3_or_greater(dev->hw))
++ ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++ MTK_WED_WPDMA_RX_D_PREF_BUSY);
+ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
+ } else {
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ /*1.a. Disable Prefetch HW*/
++ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, MTK_WED_WPDMA_RX_D_PREF_EN);
++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
++ MTK_WED_WPDMA_RX_D_PREF_BUSY);
++ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
++ MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL);
++ }
++
+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
+ MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
+@@ -1457,15 +1618,36 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
+ }
+
++ if (dev->wlan.hw_rro) {
++ /* Disable RRO MSDU Page Drv */
++ wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
++
++ /* Disable RRO Data Drv */
++ wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
++
++ /* RRO MSDU Page Drv Reset */
++ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
++ mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++ MTK_WED_RRO_MSDU_PG_DRV_CLR);
++
++ /* RRO Data Drv Reset */
++ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_CLR);
++ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2),
++ MTK_WED_RRO_RX_D_DRV_CLR);
++ }
++
+ /* reset route qm */
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
+ ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
+ if (ret) {
+ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
++ } else if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ wed_set(dev, MTK_WED_RTQM_RST, BIT(0));
++ wed_clr(dev, MTK_WED_RTQM_RST, BIT(0));
++ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
+ } else {
+- wed_set(dev, MTK_WED_RTQM_GLO_CFG,
+- MTK_WED_RTQM_Q_RST);
++ wed_set(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
+ }
+
+ /* reset tx wdma */
+@@ -1473,8 +1655,12 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+
+ /* reset tx wdma drv */
+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
+- mtk_wed_poll_busy(dev, MTK_WED_CTRL,
+- MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
++ if (mtk_wed_is_v3_or_greater(dev->hw))
++ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS,
++ MTK_WED_WPDMA_STATUS_TX_DRV);
++ else
++ mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
+
+ /* reset wed rx dma */
+@@ -1495,6 +1681,14 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
+ MTK_WED_CTRL_WED_RX_BM_BUSY);
+ mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
+
++ if (dev->wlan.hw_rro) {
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
++ mtk_wed_poll_busy(dev, MTK_WED_CTRL,
++ MTK_WED_CTRL_WED_RX_PG_BM_BUSY);
++ wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
++ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
++ }
++
+ /* wo change to enable state */
+ val = WO_STATE_ENABLE;
+ ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
+@@ -1549,16 +1743,55 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+
+ /* 2. Reset WDMA Rx DMA/Driver_Engine */
+ busy = !!mtk_wdma_rx_reset(dev);
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ val = MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE |
++ wed_r32(dev, MTK_WED_WDMA_GLO_CFG);
++ val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN;
++ wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val);
++ } else {
++ wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
++ MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
++ }
+
+- wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
+ if (!busy)
+ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
+ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY);
++ if (!busy && mtk_wed_is_v3_or_greater(dev->hw))
++ busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_BUSY);
+
+ if (busy) {
+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
+ mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
+ } else {
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ /*1.a. Disable Prefetch HW*/
++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_EN);
++ mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_BUSY);
++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_DDONE2_EN);
++
++ /* reset prefetch index */
++ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
++ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
++ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
++
++ /* reset prefetch FIFO */
++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
++ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
++ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
++ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
++
++ /*2. Reset dma index*/
++ wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
++ MTK_WED_WDMA_RESET_IDX_RX_ALL);
++ }
+ wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
+ MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV);
+ wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
+@@ -1574,8 +1807,13 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
+
+ for (i = 0; i < 100; i++) {
+- val = wed_r32(dev, MTK_WED_TX_BM_INTF);
+- if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
++ if (mtk_wed_is_v1(dev->hw))
++ val = FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP,
++ wed_r32(dev, MTK_WED_TX_BM_INTF));
++ else
++ val = FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP,
++ wed_r32(dev, MTK_WED_TX_TKID_INTF));
++ if (val == 0x40)
+ break;
+ }
+
+@@ -1599,6 +1837,8 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
+ mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV);
++ if (mtk_wed_is_v3_or_greater(dev->hw))
++ wed_w32(dev, MTK_WED_RX1_CTRL2, 0);
+ } else {
+ wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
+ MTK_WED_WPDMA_RESET_IDX_TX |
+@@ -1615,7 +1855,14 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
+ wed_w32(dev, MTK_WED_RESET_IDX, 0);
+ }
+
+- mtk_wed_rx_reset(dev);
++ if (mtk_wed_is_v3_or_greater(dev->hw)) {
++ /* reset amsdu engine */
++ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_AMSDU_EN);
++ mtk_wed_reset(dev, MTK_WED_RESET_TX_AMSDU);
++ }
++
++ if (mtk_wed_get_rx_capa(dev))
++ mtk_wed_rx_reset(dev);
+ }
+
+ static int
+@@ -1932,7 +2179,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
+ }
+
+ static void
+-mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
++mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask, bool reset)
+ {
+ int i;
+
+@@ -1942,6 +2189,12 @@ mtk_wed_start_hw_rro(struct mtk_wed_device *dev, u32 irq_mask)
+ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hw_rro)
+ return;
+
++ if (reset) {
++ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
++ MTK_WED_RRO_MSDU_PG_DRV_EN);
++ return;
++ }
++
+ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
+ MTK_WED_RRO_MSDU_PG_DRV_CLR);
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+index 0af264d..1ee0fe1 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
+@@ -36,6 +36,8 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RESET 0x008
+ #define MTK_WED_RESET_TX_BM BIT(0)
+ #define MTK_WED_RESET_RX_BM BIT(1)
++#define MTK_WED_RESET_RX_PG_BM BIT(2)
++#define MTK_WED_RESET_RRO_RX_TO_PG BIT(3)
+ #define MTK_WED_RESET_TX_FREE_AGENT BIT(4)
+ #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8)
+ #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9)
+@@ -58,7 +60,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3)
+ #define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5)
+ #define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6)
+-#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU BIT(7)
++#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY BIT(7)
+ #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8)
+ #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
+ #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
+@@ -117,6 +119,10 @@ struct mtk_wdma_desc {
+ #define MTK_WED_STATUS 0x060
+ #define MTK_WED_STATUS_TX GENMASK(15, 8)
+
++#define MTK_WED_WPDMA_STATUS 0x068
++#define MTK_WED_WPDMA_STATUS_TX_DRV GENMASK(15, 8)
++
++
+ #define MTK_WED_TX_BM_CTRL 0x080
+ #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0)
+ #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16)
+@@ -154,6 +160,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM_V3 GENMASK(7, 0)
+ #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM_V3 GENMASK(23, 16)
+
++#define MTK_WED_TX_TKID_INTF 0x0dc
++#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP GENMASK(25, 16)
++
+ #define MTK_WED_TX_TKID_DYN_THR 0x0e0
+ #define MTK_WED_TX_TKID_DYN_THR_LO GENMASK(6, 0)
+ #define MTK_WED_TX_TKID_DYN_THR_HI GENMASK(22, 16)
+@@ -205,6 +214,7 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10)
+
+ #define MTK_WED_SCR0 0x3c0
++#define MTK_WED_RX1_CTRL2 0x418
+ #define MTK_WED_WPDMA_INT_TRIGGER 0x504
+ #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1)
+ #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4)
+@@ -320,6 +330,7 @@ struct mtk_wdma_desc {
+
+ #define MTK_WED_WPDMA_RX_D_RST_IDX 0x760
+ #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16)
++#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL BIT(20)
+ #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24)
+
+ #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c
+@@ -336,6 +347,7 @@ struct mtk_wdma_desc {
+
+ #define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4
+ #define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0)
++#define MTK_WED_WPDMA_RX_D_PREF_BUSY BIT(1)
+ #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8)
+ #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16)
+
+@@ -357,11 +369,13 @@ struct mtk_wdma_desc {
+
+ #define MTK_WED_WDMA_RX_PREF_CFG 0x950
+ #define MTK_WED_WDMA_RX_PREF_EN BIT(0)
++#define MTK_WED_WDMA_RX_PREF_BUSY BIT(1)
+ #define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8)
+ #define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16)
+ #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24)
+ #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25)
+ #define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26)
++#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY BIT(27)
+
+ #define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C
+ #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0)
+@@ -390,6 +404,7 @@ struct mtk_wdma_desc {
+
+ #define MTK_WED_WDMA_RESET_IDX 0xa08
+ #define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16)
++#define MTK_WED_WDMA_RESET_IDX_RX_ALL BIT(20)
+ #define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24)
+
+ #define MTK_WED_WDMA_INT_CLR 0xa24
+@@ -458,21 +473,66 @@ struct mtk_wdma_desc {
+ #define MTK_WDMA_INT_MASK_RX_DELAY BIT(30)
+ #define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31)
+
++#define MTK_WDMA_XDMA_TX_FIFO_CFG 0x238
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR BIT(0)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR BIT(4)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR BIT(8)
++#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR BIT(12)
++
++#define MTK_WDMA_XDMA_RX_FIFO_CFG 0x23c
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR BIT(0)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR BIT(4)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR BIT(8)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR BIT(12)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR BIT(15)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR BIT(18)
++#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR BIT(21)
++
++
++
+ #define MTK_WDMA_INT_GRP1 0x250
+ #define MTK_WDMA_INT_GRP2 0x254
+
+ #define MTK_WDMA_PREF_TX_CFG 0x2d0
+ #define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0)
++#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY BIT(1)
+
+ #define MTK_WDMA_PREF_RX_CFG 0x2dc
+ #define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0)
++#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY BIT(1)
++
++#define MTK_WDMA_PREF_RX_FIFO_CFG 0x2e0
++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR BIT(0)
++#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR BIT(16)
++
++#define MTK_WDMA_PREF_TX_FIFO_CFG 0x2d4
++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR BIT(0)
++#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR BIT(16)
++
++#define MTK_WDMA_PREF_SIDX_CFG 0x2e4
++#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0)
++#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4)
+
+ #define MTK_WDMA_WRBK_TX_CFG 0x300
++#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY BIT(0)
+ #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30)
+
++#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n) (0x304 + (_n) * 0x4)
++#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR BIT(0)
++
++
+ #define MTK_WDMA_WRBK_RX_CFG 0x344
++#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY BIT(0)
+ #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30)
+
++#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n) (0x348 + (_n) * 0x4)
++#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR BIT(0)
++
++
++#define MTK_WDMA_WRBK_SIDX_CFG 0x388
++#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0)
++#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4)
++
+ #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0)
+ #define MTK_PCIE_MIRROR_MAP_EN BIT(0)
+ #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1)
+@@ -486,6 +546,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5)
+ #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20)
+
++#define MTK_WED_RTQM_RST 0xb04
++
++
+ #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c
+ #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4)
+ #define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28
+@@ -675,6 +738,9 @@ struct mtk_wdma_desc {
+ #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17)
+ #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18)
+
++#define MTK_WED_RRO_RX_HW_STS 0xf00
++#define MTK_WED_RX_IND_CMD_BUSY GENMASK(31, 0)
++
+ #define MTK_WED_RX_IND_CMD_CNT0 0xf20
+ #define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31)
+
+diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
+index e81e41f..83a4b8b 100644
+--- a/include/linux/soc/mediatek/mtk_wed.h
++++ b/include/linux/soc/mediatek/mtk_wed.h
+@@ -222,7 +222,7 @@ struct mtk_wed_ops {
+
+ u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
+ void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
+- void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask);
++ void (*start_hw_rro)(struct mtk_wed_device *dev, u32 irq_mask, bool reset);
+ void (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
+ void __iomem *regs);
+ void (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
+@@ -302,8 +302,8 @@ mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev)
+ #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) \
+ (_dev)->ops->setup_tc(_dev, _ndev, _type, _data)
+-#define mtk_wed_device_start_hw_rro(_dev, _mask) \
+- (_dev)->ops->start_hw_rro(_dev, _mask)
++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) \
++ (_dev)->ops->start_hw_rro(_dev, _mask, _reset)
+ #define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
+ (_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
+ #define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
+@@ -329,7 +329,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
+ #define mtk_wed_device_stop(_dev) do {} while (0)
+ #define mtk_wed_device_dma_reset(_dev) do {} while (0)
+ #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
+-#define mtk_wed_device_start_hw_rro(_dev, _mask) do {} while (0)
++#define mtk_wed_device_start_hw_rro(_dev, _mask, _reset) do {} while (0)
+ #define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
+ #define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) -ENODEV
+ #define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) -ENODEV
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
new file mode 100644
index 0000000..d3747af
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
@@ -0,0 +1,140 @@
+From f83c601c7b525c0adedcf1f5e8041acd350c7e2d Mon Sep 17 00:00:00 2001
+From: Sujuan Chen <sujuan.chen@mediatek.com>
+Date: Mon, 18 Sep 2023 13:23:56 +0800
+Subject: [PATCH] mtk: wed: add dma mask limitation and GFP_DMA32 for board >=
+ 4GB dram
+
+---
+ drivers/net/ethernet/mediatek/mtk_wed.c | 16 +++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 4 ++--
+ drivers/net/ethernet/mediatek/mtk_wed_wo.c | 4 ++--
+ drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 +
+ 4 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index 5eeb3ed..094bc94 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -625,7 +625,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ void *buf;
+ int s;
+
+- page = __dev_alloc_pages(GFP_KERNEL, 0);
++ page = __dev_alloc_pages(GFP_KERNEL | GFP_DMA32, 0);
+ if (!page)
+ return -ENOMEM;
+
+@@ -646,10 +646,11 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+
+ for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
+ struct mtk_wdma_desc *desc = desc_ptr;
++ u32 ctrl;
+
+ desc->buf0 = cpu_to_le32(buf_phys);
+ if (!mtk_wed_is_v3_or_greater(dev->hw)) {
+- u32 txd_size, ctrl;
++ u32 txd_size;
+
+ txd_size = dev->wlan.init_buf(buf, buf_phys,
+ token++);
+@@ -663,11 +664,11 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
+ ctrl |= MTK_WDMA_DESC_CTRL_LAST_SEG0 |
+ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1_V2,
+ MTK_WED_BUF_SIZE - txd_size);
+- desc->ctrl = cpu_to_le32(ctrl);
+ desc->info = 0;
+ } else {
+- desc->ctrl = cpu_to_le32(token << 16);
++ ctrl = token << 16 | TX_DMA_SDP1(buf_phys);
+ }
++ desc->ctrl = cpu_to_le32(ctrl);
+
+ desc_ptr += desc_size;
+ buf += MTK_WED_BUF_SIZE;
+@@ -749,7 +750,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev)
+ void *buf;
+ int s;
+
+- page = __dev_alloc_pages(GFP_KERNEL, 0);
++ page = __dev_alloc_pages(GFP_KERNEL | GFP_DMA32, 0);
+ if (!page)
+ return -ENOMEM;
+
+@@ -769,6 +770,7 @@ mtk_wed_hwrro_buffer_alloc(struct mtk_wed_device *dev)
+ buf_phys = page_phys;
+ for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) {
+ desc->buf0 = cpu_to_le32(buf_phys);
++ desc->token = cpu_to_le32(RX_DMA_SDP1(buf_phys));
+ desc++;
+ buf += MTK_WED_PAGE_BUF_SIZE;
+ buf_phys += MTK_WED_PAGE_BUF_SIZE;
+@@ -2457,6 +2459,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
+ dev->version = hw->version;
+ dev->hw->pci_base = mtk_wed_get_pci_base(dev);
+
++ ret = dma_set_mask_and_coherent(hw->dev, DMA_BIT_MASK(32));
++ if (ret)
++ return ret;
++
+ if (hw->eth->dma_dev == hw->eth->dev &&
+ of_dma_is_coherent(hw->eth->dev->of_node))
+ mtk_eth_set_dma_device(hw->eth, hw->dev);
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+index 18d1fb1..a88061c 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+@@ -145,7 +145,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
+ }req;
+
+ exp->log_size = EXCEPTION_LOG_SIZE;
+- exp->log = kmalloc(exp->log_size, GFP_ATOMIC);
++ exp->log = page_frag_alloc(&wo->page, exp->log_size, GFP_ATOMIC | GFP_DMA32);
+ if (!exp->log)
+ return -ENOMEM;
+
+@@ -165,7 +165,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
+ &req, sizeof(req), false);
+
+ free:
+- kfree(exp->log);
++ skb_free_frag(exp->log);
+ return -ENOMEM;
+ }
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
+index 54b7787..e991d20 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
+@@ -88,7 +88,7 @@ woif_q_rx_fill(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool rx)
+ page = &q->rx_page;
+
+ while (q->queued < q->ndesc) {
+- buf = page_frag_alloc(page, len, GFP_ATOMIC);
++ buf = page_frag_alloc(page, len, GFP_ATOMIC | GFP_DMA32);
+ if (!buf)
+ break;
+
+@@ -555,7 +555,7 @@ void mtk_wed_wo_exit(struct mtk_wed_hw *hw)
+
+ if (wo->exp.log) {
+ dma_unmap_single(wo->hw->dev, wo->exp.phys, wo->exp.log_size, DMA_FROM_DEVICE);
+- kfree(wo->exp.log);
++ skb_free_frag(wo->exp.log);
+ }
+
+ wo->hw = NULL;
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
+index b24fef3..5afa6de 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h
++++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
+@@ -193,6 +193,7 @@ struct mtk_wed_wo {
+ const struct wed_wo_drv_ops *drv_ops;
+ const struct wed_wo_mcu_ops *mcu_ops;
+ const struct wed_wo_queue_ops *queue_ops;
++ struct page_frag_cache page;
+
+ struct net_device napi_dev;
+ spinlock_t rx_lock;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
similarity index 70%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
index cd6c8ca..c96eaa8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3022-mediatek-ethernet-add-multiple-ppe-allocati.patch
@@ -1,20 +1,21 @@
-From f80b9b330efd9d675c7c548c5af459792037ca99 Mon Sep 17 00:00:00 2001
+From e917fdd9042787edd43e4070c3480baf0dfb8d33 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Tue, 26 Dec 2023 16:46:16 +0800
-Subject: [PATCH] 999-3022-mediatek-ethernet-add-multiple-ppe-allocatiion.patch
+Date: Mon, 18 Mar 2024 16:57:13 +0800
+Subject: [PATCH 22/24]
+ 999-3022-mediatek-ethernet-add-multiple-ppe-allocatiion.patch
---
arch/arm64/boot/dts/mediatek/mt7988.dtsi | 1 +
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 19 +++++++++++++++++--
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++
- .../net/ethernet/mediatek/mtk_ppe_offload.c | 10 ++++++++++
- 4 files changed, 31 insertions(+), 2 deletions(-)
+ .../net/ethernet/mediatek/mtk_ppe_offload.c | 10 +++++++++
+ 4 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-index 44a2f1b..cf50542 100644
+index 4a1a446..57b27f8 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-@@ -949,6 +949,7 @@
+@@ -942,6 +942,7 @@
mediatek,infracfg = <&topmisc>;
mediatek,toprgu = <&watchdog>;
mediatek,hwver = <&hwver>;
@@ -23,10 +24,10 @@
#address-cells = <1>;
#size-cells = <0>;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 4cdfead..9009960 100644
+index 291afdc..c0f4ade 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2170,6 +2170,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2349,6 +2349,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
u8 *data, *new_data;
struct mtk_rx_dma_v2 *rxd, trxd;
int done = 0;
@@ -34,17 +35,20 @@
if (unlikely(!ring))
goto rx_done;
-@@ -2277,7 +2278,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
- #if defined(CONFIG_MEDIATEK_NETSYS_RX_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
- reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
-- mtk_ppe_check_skb(eth->ppe[0], skb,
-+ i = eth->mac[mac]->ppe_idx;
-+ mtk_ppe_check_skb(eth->ppe[i], skb,
- trxd.rxd5 & MTK_RXD5_FOE_ENTRY_V2);
+@@ -2463,8 +2464,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
}
- #else
-@@ -3781,7 +3783,19 @@ static int mtk_open(struct net_device *dev)
+ #endif
+
+- if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
+- mtk_ppe_check_skb(eth->ppe[0], skb, hash);
++ if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
++ i = eth->mac[mac]->ppe_idx;
++ mtk_ppe_check_skb(eth->ppe[i], skb, hash);
++ }
+
+ if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2)) {
+@@ -4113,7 +4116,19 @@ static int mtk_open(struct net_device *dev)
SGMSYS_QPHY_PWR_STATE_CTRL, 0);
if (eth->soc->offload_version) {
@@ -65,7 +69,7 @@
for (i = 0; i < eth->ppe_num; i++)
mtk_ppe_start(eth->ppe[i]);
-@@ -4748,6 +4762,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+@@ -5129,6 +5144,7 @@ static const struct net_device_ops mtk_netdev_ops = {
.ndo_poll_controller = mtk_poll_controller,
#endif
.ndo_setup_tc = mtk_eth_setup_tc,
@@ -74,10 +78,10 @@
static void mux_poll(struct work_struct *work)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 12ffb3c..1bf335c 100644
+index 8454361..d958aec 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1945,6 +1945,7 @@ struct mtk_mac {
+@@ -1978,6 +1978,7 @@ struct mtk_mac {
phy_interface_t interface;
unsigned int mode;
unsigned int type;
@@ -85,7 +89,7 @@
int speed;
struct device_node *of_node;
struct phylink *phylink;
-@@ -2045,6 +2046,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -2079,6 +2080,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data);
int mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f,
struct mtk_eth *eth);
@@ -95,10 +99,10 @@
u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-index 339359e..8f721ba 100644
+index 402f1e3..3bfbec8 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -693,6 +693,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -828,6 +828,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
similarity index 76%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
index 31d8b89..d0ad23e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3023-mtk-ppe-dispatch-short-packets-to-high-prio.patch
@@ -1,29 +1,34 @@
-From 8306aa4c52abf96af2c229762207369f279c89e2 Mon Sep 17 00:00:00 2001
+From e8a6054c824c5c65abd501bfd7437a3d7c5f2751 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Date: Tue, 28 Nov 2023 13:25:03 +0800
-Subject: [PATCH] 999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ
+Subject: [PATCH 23/24]
+ mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ
---
drivers/net/ethernet/mediatek/mtk_ppe.c | 27 +++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 16aec2e..1e2b96e 100644
+index ae0acd5..547b5a0 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -451,6 +451,28 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+@@ -451,6 +451,31 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
return 0;
}
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+void mtk_foe_entry_adjust_qid(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
+{
+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(&entry->data);
+ u32 *ib2 = mtk_foe_entry_ib2(&entry->data);
+ u8 qid;
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ if (l2->tport_id != 1)
+ return;
++#else
++ if (!(*ib2 & MTK_FOE_IB2_PSE_QOS))
++ return;
++#endif
+
+ qid = FIELD_GET(MTK_FOE_IB2_QID, *ib2);
+ /* To enhance performance in the unbalanced PHY rate test,
@@ -35,23 +40,19 @@
+ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, qid);
+ }
+}
-+#endif
+
int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
{
u32 *ib2 = mtk_foe_entry_ib2(entry);
-@@ -790,6 +812,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
+@@ -790,6 +815,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
continue;
}
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+ if (skb && skb->len < 100)
+ mtk_foe_entry_adjust_qid(ppe, entry);
-+#endif
+
entry->hash = hash;
__mtk_foe_entry_commit(ppe, &entry->data, hash);
found = true;
--
2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3024-dts-88d-option-type-2-support.patch
similarity index 83%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3024-dts-88d-option-type-2-support.patch
index 9084982..9125b94 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3025-dts-88d-option-type-2-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3024-dts-88d-option-type-2-support.patch
@@ -1,7 +1,7 @@
-From a344727c9d91c162839e7283aeac281f88f30e8a Mon Sep 17 00:00:00 2001
+From b294202119468041b6f4b6651f968c9d2a0adcc2 Mon Sep 17 00:00:00 2001
From: Rex Lu <rex.lu@mediatek.com>
Date: Mon, 22 Jan 2024 13:50:29 +0800
-Subject: [PATCH] dts 88d option type 2 support
+Subject: [PATCH 24/24] dts 88d option type 2 support
Signed-off-by: Rex Lu <rex.lu@mediatek.com>
---
@@ -10,10 +10,10 @@
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
-index 5513d04..7619009 100644
+index 8ebcbaf..df15051 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
-@@ -569,6 +569,7 @@
+@@ -572,6 +572,7 @@
mt7996@0,0 {
reg = <0x0000 0 0 0 0>;
device_type = "pci";
@@ -22,10 +22,10 @@
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
-index 4cab1ae..b98efb9 100644
+index d4f96c8..c27ffa6 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
-@@ -546,6 +546,7 @@
+@@ -547,6 +547,7 @@
mt7996@0,0 {
reg = <0x0000 0 0 0 0>;
device_type = "pci";
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
index 8626ee4..488fa22 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
@@ -3,6 +3,7 @@
CONFIG_AIROHA_EN8801SC_PHY=y
# CONFIG_AIROHA_EN8811H_PHY is not set
# CONFIG_AIROHA_AN8801_PHY is not set
+# CONFIG_AN8855_GSW is not set
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
@@ -355,7 +356,9 @@
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
+# CONFIG_NET_DSA_AN8855 is not set
CONFIG_NET_DSA_MT7530=y
+# CONFIG_NET_DSA_TAG_ARHT is not set
CONFIG_NET_DSA_TAG_MTK=y
CONFIG_NET_FLOW_LIMIT=y
# CONFIG_NET_MEDIATEK_HNAT is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index 714ff5d..8241edf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -3,11 +3,12 @@
# CONFIG_AIROHA_EN8801SC_PHY is not set
# CONFIG_AIROHA_EN8811H_PHY is not set
# CONFIG_AIROHA_AN8801_PHY is not set
+# CONFIG_AN8855_GSW is not set
CONFIG_AQUANTIA_PHY=y
CONFIG_AQUANTIA_PHY_FW_DOWNLOAD=y
CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG=y
# CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE is not set
-CONFIG_AQUANTIA_PHY_FW_FILE="Rhe-05.06-Candidate9-AQR_Mediatek_23B_P5_ID45824_LCLVER1.cld"
+CONFIG_AQUANTIA_PHY_FW_FILE="AQR-G4_v5.7.0-AQR_EVB_Generic_X3410_StdCfg_MDISwap_USX_ID46316_VER2140.cld"
CONFIG_AQUANTIA_PHY_MIB=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
@@ -325,7 +326,9 @@
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
+# CONFIG_NET_DSA_AN8855 is not set
CONFIG_NET_DSA_MT7530=y
+# CONFIG_NET_DSA_TAG_ARHT is not set
CONFIG_NET_DSA_TAG_MTK=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_MEDIATEK_SOC=y
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1021-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2700-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1021-v5.7-iopoll-introduce-read_poll_timeout-macro.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2360-v5.16-spi-add-power-control-when-set_cs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1400-v5.16-spi-add-power-control-when-set_cs.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2360-v5.16-spi-add-power-control-when-set_cs.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1400-v5.16-spi-add-power-control-when-set_cs.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1702-v6.4-backport-mediatek-ge-and-mediatek-ge-soc.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2703-net-phy-backport-v5.4-mediatek-ge-and-v6.4-mediatek-ge-soc.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1702-v6.4-backport-mediatek-ge-and-mediatek-ge-soc.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2328-mtd-add-nmbm-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2328-mtd-add-nmbm-support.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2328-mtd-add-nmbm-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2328-mtd-add-nmbm-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2329-ubi-add-configurable-rootdev.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2329-ubi-add-configurable-rootdev.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2329-ubi-add-configurable-rootdev.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2329-ubi-add-configurable-rootdev.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2344-mtd-spinand-Add-support-fudanmicro.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2344-mtd-spinand-Add-support-fudanmicro.patch
new file mode 100644
index 0000000..34d249e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2344-mtd-spinand-Add-support-fudanmicro.patch
@@ -0,0 +1,141 @@
+Index: linux-5.4.260/drivers/mtd/nand/spi/core.c
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/core.c
++++ linux-5.4.260/drivers/mtd/nand/spi/core.c
+@@ -755,6 +755,7 @@ static const struct nand_ops spinand_ops
+
+ static const struct spinand_manufacturer *spinand_manufacturers[] = {
+ &etron_spinand_manufacturer,
++ &fudan_spinand_manufacturer,
+ &gigadevice_spinand_manufacturer,
+ ¯onix_spinand_manufacturer,
+ µn_spinand_manufacturer,
+Index: linux-5.4.260/drivers/mtd/nand/spi/Makefile
+===================================================================
+--- linux-5.4.260.orig/drivers/mtd/nand/spi/Makefile
++++ linux-5.4.260/drivers/mtd/nand/spi/Makefile
+@@ -1,3 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o etron.o
++spinand-objs := core.o etron.o fudanmicro.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+Index: linux-5.4.260/include/linux/mtd/spinand.h
+===================================================================
+--- linux-5.4.260.orig/include/linux/mtd/spinand.h
++++ linux-5.4.260/include/linux/mtd/spinand.h
+@@ -239,6 +239,7 @@ struct spinand_manufacturer {
+
+ /* SPI NAND manufacturers */
+ extern const struct spinand_manufacturer etron_spinand_manufacturer;
++extern const struct spinand_manufacturer fudan_spinand_manufacturer;
+ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
+ extern const struct spinand_manufacturer macronix_spinand_manufacturer;
+ extern const struct spinand_manufacturer micron_spinand_manufacturer;
+Index: linux-5.4.260/drivers/mtd/nand/spi/fudanmicro.c
+===================================================================
+--- /dev/null
++++ linux-5.4.260/drivers/mtd/nand/spi/fudanmicro.c
+@@ -0,0 +1,103 @@
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mtd/spinand.h>
++
++#define SPINAND_MFR_FUDAN 0xA1
++
++#define FM25S01B_STATUS_ECC_MASK (7 << 4)
++#define STATUS_ECC_1_3_BITFLIPS (1 << 4)
++#define STATUS_ECC_4_6_BITFLIPS (3 << 4)
++#define STATUS_ECC_7_8_BITFLIPS (5 << 4)
++
++static SPINAND_OP_VARIANTS(read_cache_variants,
++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(write_cache_variants,
++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
++ SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_variants,
++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
++ SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++static int fm25s01b_ooblayout_ecc(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section)
++ return -ERANGE;
++
++ region->offset = 64;
++ region->length = 64;
++
++ return 0;
++}
++
++static int fm25s01b_ooblayout_free(struct mtd_info *mtd, int section,
++ struct mtd_oob_region *region)
++{
++ if (section > 3)
++ return -ERANGE;
++
++ region->offset = (16 * section) + 4;
++ region->length = 12;
++
++ return 0;
++}
++
++static const struct mtd_ooblayout_ops fm25s01b_ooblayout = {
++ .ecc = fm25s01b_ooblayout_ecc,
++ .free = fm25s01b_ooblayout_free,
++};
++
++static int fm25s01b_ecc_get_status(struct spinand_device *spinand,
++ u8 status)
++{
++ switch (status & FM25S01B_STATUS_ECC_MASK) {
++ case STATUS_ECC_NO_BITFLIPS:
++ return 0;
++
++ case STATUS_ECC_UNCOR_ERROR:
++ return -EBADMSG;
++
++ case STATUS_ECC_1_3_BITFLIPS:
++ return 3;
++
++ case STATUS_ECC_4_6_BITFLIPS:
++ return 6;
++
++ case STATUS_ECC_7_8_BITFLIPS:
++ return 8;
++
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++
++static const struct spinand_info fudan_spinand_table[] = {
++ SPINAND_INFO("FM25s01B",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
++ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ SPINAND_HAS_QE_BIT,
++ SPINAND_ECCINFO(&fm25s01b_ooblayout,
++ fm25s01b_ecc_get_status)),
++};
++
++static const struct spinand_manufacturer_ops fudan_spinand_manuf_ops = {
++};
++
++const struct spinand_manufacturer fudan_spinand_manufacturer = {
++ .id = SPINAND_MFR_FUDAN,
++ .name = "FUDAN Micron",
++ .chips = fudan_spinand_table,
++ .nchips = ARRAY_SIZE(fudan_spinand_table),
++ .ops = &fudan_spinand_manuf_ops,
++};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch
similarity index 95%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch
index eadc288..a160814 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/999-2540-cmdline-boot-parameters.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2540-cmdline-boot-parameters.patch
@@ -27,7 +27,7 @@
index 000000000..3dfe828bc
--- /dev/null
+++ b/kernel/boot_param.c
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+* Copyright (C) 2022 MediaTek Inc. All rights reserved.
@@ -40,9 +40,12 @@
+
+#define BOOT_PARAM_STR_MAX_LEN 256
+
-+static bool dual_boot;
++bool dual_boot;
+module_param(dual_boot, bool, 0444);
+
++static bool reset_boot_count;
++module_param(reset_boot_count, bool, 0444);
++
+static bool no_split_rootfs_data;
+module_param(no_split_rootfs_data, bool, 0444);
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch
index 350e7d3..48b94cd 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2550-dual-image-mount-rootfs.patch
@@ -22,19 +22,6 @@
return;
#endif
#ifdef CONFIG_BLOCK
-diff --git a/kernel/boot_param.c b/kernel/boot_param.c
-index 3dfe828bc..cc0b2b8b0 100644
---- a/kernel/boot_param.c
-+++ b/kernel/boot_param.c
-@@ -10,7 +10,7 @@
-
- #define BOOT_PARAM_STR_MAX_LEN 256
-
--static bool dual_boot;
-+bool dual_boot;
- module_param(dual_boot, bool, 0444);
-
- static bool no_split_rootfs_data;
--
2.34.1
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2700-netfilter_optional_tcp_window_check.patch
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2700-netfilter_optional_tcp_window_check.patch
index 0aea6d3..62a81d1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/pending-5.4/999-2704-netfilter_optional_tcp_window_check.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2700-netfilter_optional_tcp_window_check.patch
@@ -2,7 +2,7 @@
From: Sam Shih <sam.shih@mediatek.com>
Date: Fri, 2 Jun 2023 13:06:28 +0800
Subject: [PATCH]
- [networking][999-2704-netfilter_optional_tcp_window_check.patch]
+ [networking][999-2700-netfilter_optional_tcp_window_check.patch]
---
net/netfilter/nf_conntrack_proto_tcp.c | 8 +++++++-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch
new file mode 100644
index 0000000..d089c96
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_dsa_add_an8855.patch
@@ -0,0 +1,25 @@
+Index: linux-5.4.238/drivers/net/dsa/Kconfig
+===================================================================
+--- linux-5.4.238.orig/drivers/net/dsa/Kconfig 2023-12-26 15:31:49.427259000 +0800
++++ linux-5.4.238/drivers/net/dsa/Kconfig 2023-12-26 15:46:52.655226000 +0800
+@@ -48,6 +48,8 @@
+ This enables support for the Marvell 88E6060 ethernet switch
+ chip.
+
++source "drivers/net/dsa/airoha/an8855/Kconfig"
++
+ source "drivers/net/dsa/microchip/Kconfig"
+
+ source "drivers/net/dsa/mv88e6xxx/Kconfig"
+Index: linux-5.4.238/drivers/net/dsa/Makefile
+===================================================================
+--- linux-5.4.238.orig/drivers/net/dsa/Makefile 2023-12-26 15:32:08.081306000 +0800
++++ linux-5.4.238/drivers/net/dsa/Makefile 2023-12-26 15:47:59.858217000 +0800
+@@ -18,6 +18,7 @@
+ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX) += vitesse-vsc73xx-core.o
+ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM) += vitesse-vsc73xx-platform.o
+ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI) += vitesse-vsc73xx-spi.o
++obj-y += airoha/an8855/
+ obj-y += b53/
+ obj-y += microchip/
+ obj-y += mv88e6xxx/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch
new file mode 100644
index 0000000..34855a5
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_ethernet_mediatek_hnat.patch
@@ -0,0 +1,13 @@
+Index: linux-5.4.238/drivers/net/ethernet/mediatek/mtk_hnat/Makefile
+===================================================================
+--- linux-5.4.238.orig/drivers/net/ethernet/mediatek/mtk_hnat/Makefile 2023-09-05 21:55:25.000000000 +0800
++++ linux-5.4.238/drivers/net/ethernet/mediatek/mtk_hnat/Makefile 2023-12-18 11:26:54.110684000 +0800
+@@ -2,4 +2,8 @@
+
+ obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtkhnat.o
+ mtkhnat-objs := hnat.o hnat_nf_hook.o hnat_debugfs.o hnat_mcast.o
++ifeq ($(CONFIG_NET_DSA_AN8855), y)
++mtkhnat-y += hnat_stag.o
++else
+ mtkhnat-$(CONFIG_NET_DSA_MT7530) += hnat_stag.o
++endif
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch
new file mode 100644
index 0000000..58220b3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-drivers_net_phy_add_an8855_gsw.patch
@@ -0,0 +1,24 @@
+Index: linux-5.4.238/drivers/net/phy/Kconfig
+===================================================================
+--- linux-5.4.238.orig/drivers/net/phy/Kconfig 2023-12-19 12:20:34.714805000 +0800
++++ linux-5.4.238/drivers/net/phy/Kconfig 2023-12-25 10:11:11.328554000 +0800
+@@ -337,6 +337,8 @@
+
+ source "drivers/net/phy/mtk/mt753x/Kconfig"
+
++source "drivers/net/phy/airoha/an8855/Kconfig"
++
+ comment "MII PHY device drivers"
+
+ config SFP
+Index: linux-5.4.238/drivers/net/phy/Makefile
+===================================================================
+--- linux-5.4.238.orig/drivers/net/phy/Makefile 2023-12-19 12:20:34.718809000 +0800
++++ linux-5.4.238/drivers/net/phy/Makefile 2023-12-25 10:13:11.891535000 +0800
+@@ -121,5 +121,6 @@
+ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
+ obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+ obj-$(CONFIG_MT753X_GSW) += mtk/mt753x/
++obj-$(CONFIG_AN8855_GSW) += airoha/an8855/
+ obj-$(CONFIG_RTL8367S_GSW) += rtk/
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net-phy-aquantia-add-CUX3410.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net-phy-aquantia-add-CUX3410.patch
new file mode 100644
index 0000000..fcd1fee
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net-phy-aquantia-add-CUX3410.patch
@@ -0,0 +1,160 @@
+diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
+index f46d95f..135b103 100644
+--- a/drivers/net/phy/aquantia.h
++++ b/drivers/net/phy/aquantia.h
+@@ -81,6 +81,8 @@ struct aqr107_priv {
+ int aqr107_set_downshift(struct phy_device *phydev, u8 cnt);
+ void aqr107_chip_info(struct phy_device *phydev);
+ int aqr107_config_mdi(struct phy_device *phydev);
++int aqr107_config_usx_aneg_en(struct phy_device *phydev);
++int aqr107_config_led(struct phy_device *phydev);
+
+ #if IS_REACHABLE(CONFIG_HWMON)
+ int aqr_hwmon_probe(struct phy_device *phydev);
+diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
+index b4ce32f..f37bee1 100644
+--- a/drivers/net/phy/aquantia_firmware.c
++++ b/drivers/net/phy/aquantia_firmware.c
+@@ -973,6 +973,14 @@ retry:
+
+ aqr107_chip_info(phydevs[i]);
+
++ ret = aqr107_config_usx_aneg_en(phydevs[i]);
++ if (ret)
++ dev_err(dev, "USX autonegotiation disabled, ret: %d\n", ret);
++
++ ret = aqr107_config_led(phydevs[i]);
++ if (ret)
++ dev_err(dev, "LED configuration failed, ret: %d\n", ret);
++
+ aqr107_config_mdi(phydevs[i]);
+
+ aqr107_set_downshift(phydevs[i],
+diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
+index e545b28..f445ef9 100644
+--- a/drivers/net/phy/aquantia_main.c
++++ b/drivers/net/phy/aquantia_main.c
+@@ -25,6 +25,7 @@
+ #define PHY_ID_AQCS109 0x03a1b5c2
+ #define PHY_ID_AQR405 0x03a1b4b0
+ #define PHY_ID_AQR113C 0x31c31c12
++#define PHY_ID_CUX3410 0x31c31dd3
+
+ #define MDIO_PHYXS_VEND_IF_STATUS 0xe812
+ #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
+@@ -34,6 +35,9 @@
+ #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
+ #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
+
++#define MDIO_PHYXS_TX_RSVD_VEND_PROV2 0xc441
++#define MDIO_PHYXS_TX_RSVD_VEND_PROV2_ANEG BIT(3)
++
+ #define MDIO_AN_VEND_PROV 0xc400
+ #define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15)
+ #define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14)
+@@ -113,6 +117,16 @@
+ #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
+ #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
+
++#define VEND1_GLOBAL_LED_PROV(x) (0xc430 + (x - 1))
++#define VEND1_GLOBAL_LED_5000_LINK_EST BIT(15)
++#define VEND1_GLOBAL_LED_2500_LINK_EST BIT(14)
++#define VEND1_GLOBAL_LED_10G_LINK_EST BIT(7)
++#define VEND1_GLOBAL_LED_1000_LINK_EST BIT(6)
++#define VEND1_GLOBAL_LED_100_LINK_EST BIT(5)
++#define VEND1_GLOBAL_LED_PROV_RX_ACT BIT(3)
++#define VEND1_GLOBAL_LED_PROV_TX_ACT BIT(2)
++#define VEND1_GLOBAL_LED_PROV_ACT_STRETCH_MASK GENMASK(1, 0)
++
+ static int aqr107_get_sset_count(struct phy_device *phydev)
+ {
+ return AQR107_SGMII_STAT_SZ;
+@@ -170,6 +184,40 @@ static void aqr107_get_stats(struct phy_device *phydev,
+ }
+ }
+
++int aqr107_config_led(struct phy_device *phydev)
++{
++ u16 val;
++ int err;
++
++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(1));
++ val |= VEND1_GLOBAL_LED_10G_LINK_EST;
++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(1), val);
++ if (err < 0)
++ return err;
++
++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(2));
++ val |= VEND1_GLOBAL_LED_100_LINK_EST | VEND1_GLOBAL_LED_1000_LINK_EST |
++ VEND1_GLOBAL_LED_2500_LINK_EST | VEND1_GLOBAL_LED_5000_LINK_EST;
++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(2), val);
++ if (err < 0)
++ return err;
++
++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(3));
++ val |= VEND1_GLOBAL_LED_PROV_ACT_STRETCH_MASK |
++ VEND1_GLOBAL_LED_PROV_TX_ACT | VEND1_GLOBAL_LED_PROV_RX_ACT;
++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(3), val);
++}
++
++int aqr107_config_usx_aneg_en(struct phy_device *phydev)
++{
++ u16 val;
++
++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_TX_RSVD_VEND_PROV2);
++ val |= MDIO_PHYXS_TX_RSVD_VEND_PROV2_ANEG;
++
++ return phy_write_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_TX_RSVD_VEND_PROV2, val);
++}
++
+ static int aqr_config_aneg(struct phy_device *phydev)
+ {
+ bool changed = false;
+@@ -483,6 +531,14 @@ static int aqr107_config_init(struct phy_device *phydev)
+ return aqr_firmware_download(phydev);
+ #endif
+
++ ret = aqr107_config_usx_aneg_en(phydev);
++ if (ret)
++ dev_err(&phydev->mdio.dev, "USX autonegotiation disabled, ret: %d\n", ret);
++
++ ret = aqr107_config_led(phydev);
++ if (ret)
++ dev_err(&phydev->mdio.dev, "LED configuration failed, ret: %d\n", ret);
++
+ aqr107_config_mdi(phydev);
+
+ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+@@ -711,6 +767,24 @@ static struct phy_driver aqr_driver[] = {
+ .get_stats = aqr107_get_stats,
+ .link_change_notify = aqr107_link_change_notify,
+ },
++{
++ PHY_ID_MATCH_MODEL(PHY_ID_CUX3410),
++ .name = "Aquantia CUX3410",
++ .probe = aqr107_probe,
++ .config_init = aqr107_config_init,
++ .config_aneg = aqr_config_aneg,
++ .config_intr = aqr_config_intr,
++ .ack_interrupt = aqr_ack_interrupt,
++ .read_status = aqr107_read_status,
++ .get_tunable = aqr107_get_tunable,
++ .set_tunable = aqr107_set_tunable,
++ .suspend = aqr107_suspend,
++ .resume = aqr107_resume,
++ .get_sset_count = aqr107_get_sset_count,
++ .get_strings = aqr107_get_strings,
++ .get_stats = aqr107_get_stats,
++ .link_change_notify = aqr107_link_change_notify,
++},
+ };
+
+ module_phy_driver(aqr_driver);
+@@ -724,6 +798,7 @@ static struct mdio_device_id __maybe_unused aqr_tbl[] = {
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
++ { PHY_ID_MATCH_MODEL(PHY_ID_CUX3410) },
+ { }
+ };
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch
new file mode 100644
index 0000000..ca36a0c
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2739-net_dsa_add_tag_arht.patch
@@ -0,0 +1,46 @@
+Index: linux-5.4.238/net/dsa/Makefile
+===================================================================
+--- linux-5.4.238.orig/net/dsa/Makefile 2023-12-09 09:43:04.335694000 +0800
++++ linux-5.4.238/net/dsa/Makefile 2023-12-09 10:24:27.672514000 +0800
+@@ -16,3 +16,4 @@
+ obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
+ obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
+ obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
++obj-$(CONFIG_NET_DSA_TAG_AIROHA) += tag_arht.o
+Index: linux-5.4.238/net/dsa/Kconfig
+===================================================================
+--- linux-5.4.238.orig/net/dsa/Kconfig 2023-12-09 09:43:04.332694000 +0800
++++ linux-5.4.238/net/dsa/Kconfig 2023-12-09 10:26:13.596504000 +0800
+@@ -74,6 +74,12 @@
+ Say Y or M if you want to enable support for tagging frames for
+ Mediatek switches.
+
++config NET_DSA_TAG_AIROHA
++ tristate "Tag driver for Airoha switches"
++ help
++ Say Y or M if you want to enable support for tagging frames for
++ Airoha switches.
++
+ config NET_DSA_TAG_KSZ
+ tristate "Tag driver for Microchip 8795/9477/9893 families of switches"
+ help
+Index: linux-5.4.238/include/net/dsa.h
+===================================================================
+--- linux-5.4.238.orig/include/net/dsa.h 2023-12-09 09:43:17.940694000 +0800
++++ linux-5.4.238/include/net/dsa.h 2023-12-09 10:30:06.432504000 +0800
+@@ -43,6 +43,7 @@
+ #define DSA_TAG_PROTO_SJA1105_VALUE 13
+ #define DSA_TAG_PROTO_KSZ8795_VALUE 14
+ #define DSA_TAG_PROTO_RTL4_A_VALUE 17
++#define DSA_TAG_PROTO_ARHT_VALUE 28
+
+ enum dsa_tag_protocol {
+ DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
+@@ -61,6 +62,7 @@
+ DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE,
+ DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE,
+ DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE,
++ DSA_TAG_PROTO_ARHT = DSA_TAG_PROTO_ARHT_VALUE,
+ };
+
+ struct packet_type;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index e5109db..38511b9 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -35,11 +35,16 @@
file://1010-pcie-mediatek-fix-clearing-interrupt-status.patch \
file://1020-spi-nor-w25q512jv.patch \
file://1021-ubnt-ledbar-driver.patch \
+ file://999-1021-v5.7-iopoll-introduce-read_poll_timeout-macro.patch \
file://999-1050-v6.4-backport-jitterrng-2.2.0.patch;apply=no \
file://999-1051-v5.10-backport-libkcapi.patch \
+ file://999-1400-v5.16-spi-add-power-control-when-set_cs.patch \
file://999-1401-v5.7-mtd-spinand-backport-winbond-and-base-file.patch \
file://999-1402-v6.4-mtd-spinand-backport-series-flash.patch \
file://999-1600-v5.18-mdiobus-add-c45.patch \
+ file://999-1700-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
+ file://999-1701-v5.8-net-phy-add-concept-of-shared-storage-for-PHYs.patch \
+ file://999-1702-v6.4-backport-mediatek-ge-and-mediatek-ge-soc.patch \
file://999-1703-v5.18-mxl-gpy-phy-support.patch \
file://999-1704-v6.2-net-phy-aquantia-add-AQR113C.patch \
file://999-1708-v6.2-net-phy-add-5GBASER.patch \
@@ -124,6 +129,8 @@
file://999-2153-sound-add-si3218x-spi-driver.patch \
file://999-2300-mtk-sd-add-mt7986-support.patch \
file://999-2301-mtk-sd-Add-subsys-clock-control.patch \
+ file://999-2328-mtd-add-nmbm-support.patch \
+ file://999-2329-ubi-add-configurable-rootdev.patch \
file://999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch \
file://999-2331-mtd-spinand-macronix-suppress-mx35lf1ge4ab-warning-log.patch \
file://999-2332-mtd-add-mtk-snand-driver.patch \
@@ -134,6 +141,7 @@
file://999-2341-mtd-spinand-Add-support-etron.patch \
file://999-2342-drivers-mtd-spi-nor-Add-support-EN25QX256A-2S.patch \
file://999-2343-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB.patch \
+ file://999-2344-mtd-spinand-Add-support-fudanmicro.patch \
file://999-2350-nvmem-core-Add-functions-to-make-number-reading-easy.patch \
file://999-2351-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch \
file://999-2361-add-spimem-support-to-mtk-spi.patch \
@@ -159,6 +167,7 @@
file://999-2503-cpufreq-mtk-vbining-add-mt7988-support.patch \
file://999-2530-add-pmic-config.patch \
file://999-2531-iio-add-zts8032-config.patch \
+ file://999-2540-cmdline-boot-parameters.patch \
file://999-2550-dual-image-mount-rootfs.patch \
file://999-2600-pcie-add-pcie-gen3-upstream-driver.patch \
file://999-2601-pcie-add-multi-MSI-support.patch \
@@ -171,6 +180,7 @@
file://999-2620-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch \
file://999-2621-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch \
file://999-2622-usb-add-embedded-Host-feature-support.patch \
+ file://999-2700-netfilter_optional_tcp_window_check.patch \
file://999-2704-en8811h-2p5gphy-support.patch \
file://999-2705-hwnat_Kconfig_Makefile.patch \
file://999-2706-crypto-add-eip197-inside-secure-support.patch \
@@ -202,6 +212,11 @@
file://999-2737-net-mt753x-phy-coverity-scan.patch;apply=no \
file://999-2738-an8801sb-gphy-support.patch \
file://999-2738-net-pptp-bypass-seq-check.patch \
+ file://999-2739-drivers_net_dsa_add_an8855.patch \
+ file://999-2739-drivers_net_ethernet_mediatek_hnat.patch;apply=no \
+ file://999-2739-drivers_net_phy_add_an8855_gsw.patch \
+ file://999-2739-net-phy-aquantia-add-CUX3410.patch \
+ file://999-2739-net_dsa_add_tag_arht.patch \
file://999-2800-misc-add-mtk-platform.patch \
file://999-2850-fips-140-3-compliance.patch \
file://999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch
deleted file mode 100644
index b90693d..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch
+++ /dev/null
@@ -1,3755 +0,0 @@
-From 542064ad977706558be071e0f7d706f5aa37f390 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Mon, 18 Sep 2023 13:21:15 +0800
-Subject: [PATCH 1/5] mtk:wed:add wed3 support
-
----
- arch/arm64/boot/dts/mediatek/mt7988.dtsi | 152 ++-
- .../dts/mediatek/mt7988a-dsa-10g-spim-nor.dts | 16 +-
- .../dts/mediatek/mt7988d-dsa-10g-spim-nor.dts | 16 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +-
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +-
- drivers/net/ethernet/mediatek/mtk_ppe.c | 17 +-
- drivers/net/ethernet/mediatek/mtk_ppe.h | 2 +-
- .../net/ethernet/mediatek/mtk_ppe_offload.c | 16 +-
- drivers/net/ethernet/mediatek/mtk_wed.c | 1178 +++++++++++++----
- drivers/net/ethernet/mediatek/mtk_wed.h | 25 +-
- .../net/ethernet/mediatek/mtk_wed_debugfs.c | 584 +++++++-
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 14 +-
- drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 5 +-
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 338 ++++-
- include/linux/netdevice.h | 7 +
- include/linux/soc/mediatek/mtk_wed.h | 83 +-
- 16 files changed, 2070 insertions(+), 391 deletions(-)
- mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
-
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-index 7e96640..3368240 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-@@ -193,44 +193,49 @@
- status = "disabled";
- };
-
-- wed: wed@15010000 {
-- compatible = "mediatek,wed";
-- wed_num = <3>;
-- /* add this property for wed get the pci slot number. */
-- pci_slot_map = <0>, <1>, <2>;
-- reg = <0 0x15010000 0 0x2000>,
-- <0 0x15012000 0 0x2000>,
-- <0 0x15014000 0 0x2000>;
-+ wed0: wed@15010000 {
-+ compatible = "mediatek,mt7988-wed",
-+ "syscon";
-+ reg = <0 0x15010000 0 0x2000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
-- };
--
-- wed2: wed2@15012000 {
-- compatible = "mediatek,wed2";
-- wed_num = <3>;
-- /* add this property for wed get the pci slot number. */
-- reg = <0 0x15010000 0 0x2000>,
-- <0 0x15012000 0 0x2000>,
-- <0 0x15014000 0 0x2000>;
-+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
-+ mediatek,wed_pcie = <&wed_pcie>;
-+ mediatek,ap2woccif = <&ap2woccif0>;
-+ mediatek,wocpu_ilm = <&wocpu0_ilm>;
-+ mediatek,wocpu_dlm = <&wocpu0_dlm>;
-+ mediatek,wocpu_boot = <&cpu0_boot>;
-+ mediatek,wocpu_emi = <&wocpu0_emi>;
-+ mediatek,wocpu_data = <&wocpu_data>;
-+ };
-+
-+ wed1: wed@15012000 {
-+ compatible = "mediatek,mt7988-wed",
-+ "syscon";
-+ reg = <0 0x15012000 0 0x2000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
-- };
--
-- wed3: wed3@15014000 {
-- compatible = "mediatek,wed3";
-- wed_num = <3>;
-- /* add this property for wed get the pci slot number. */
-- reg = <0 0x15010000 0 0x2000>,
-- <0 0x15012000 0 0x2000>,
-- <0 0x15014000 0 0x2000>;
-+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-+ mediatek,wed_pcie = <&wed_pcie>;
-+ mediatek,ap2woccif = <&ap2woccif1>;
-+ mediatek,wocpu_ilm = <&wocpu1_ilm>;
-+ mediatek,wocpu_dlm = <&wocpu1_dlm>;
-+ mediatek,wocpu_boot = <&cpu1_boot>;
-+ mediatek,wocpu_emi = <&wocpu1_emi>;
-+ mediatek,wocpu_data = <&wocpu_data>;
-+ };
-+
-+ wed2: wed@15014000 {
-+ compatible = "mediatek,mt7988-wed",
-+ "syscon";
-+ reg = <0 0x15014000 0 0x2000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
-+ mediatek,wed_pcie = <&wed_pcie>;
-+ mediatek,ap2woccif = <&ap2woccif2>;
-+ mediatek,wocpu_ilm = <&wocpu2_ilm>;
-+ mediatek,wocpu_dlm = <&wocpu2_dlm>;
-+ mediatek,wocpu_boot = <&cpu2_boot>;
-+ mediatek,wocpu_emi = <&wocpu2_emi>;
-+ mediatek,wocpu_data = <&wocpu_data>;
- };
-
- wdma: wdma@15104800 {
-@@ -240,15 +245,25 @@
- <0 0x15105000 0 0x400>;
- };
-
-- ap2woccif: ap2woccif@151A5000 {
-- compatible = "mediatek,ap2woccif";
-- reg = <0 0x151A5000 0 0x1000>,
-- <0 0x152A5000 0 0x1000>,
-- <0 0x153A5000 0 0x1000>;
-+ ap2woccif0: ap2woccif@151A5000 {
-+ compatible = "mediatek,ap2woccif", "syscon";
-+ reg = <0 0x151A5000 0 0x1000>;
-+ interrupt-parent = <&gic>;
-+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ ap2woccif1: ap2woccif@152A5000 {
-+ compatible = "mediatek,ap2woccif", "syscon";
-+ reg = <0 0x152A5000 0 0x1000>;
- interrupt-parent = <&gic>;
-- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
-- <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
-+ };
-+
-+ ap2woccif2: ap2woccif@153A5000 {
-+ compatible = "mediatek,ap2woccif", "syscon";
-+ reg = <0 0x153A5000 0 0x1000>;
-+ interrupt-parent = <&gic>;
-+ interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
- };
-
- wocpu0_ilm: wocpu0_ilm@151E0000 {
-@@ -256,31 +271,53 @@
- reg = <0 0x151E0000 0 0x8000>;
- };
-
-- wocpu1_ilm: wocpu1_ilm@152E0000 {
-- compatible = "mediatek,wocpu1_ilm";
-+ wocpu1_ilm: wocpu_ilm@152E0000 {
-+ compatible = "mediatek,wocpu_ilm";
- reg = <0 0x152E0000 0 0x8000>;
- };
-
-- wocpu2_ilm: wocpu2_ilm@153E0000 {
-- compatible = "mediatek,wocpu2_ilm";
-- reg = <0 0x153E0000 0 0x8000>;
-+ wocpu2_ilm: wocpu_ilm@153E0000 {
-+ compatible = "mediatek,wocpu_ilm";
-+ reg = <0 0x153E0000 0 0x8000>;
-+ };
-+
-+ wocpu0_dlm: wocpu_dlm@151E8000 {
-+ compatible = "mediatek,wocpu_dlm";
-+ reg = <0 0x151E8000 0 0x2000>;
-+
-+ resets = <ðsysrst 0>;
-+ reset-names = "wocpu_rst";
-+ };
-+
-+ wocpu1_dlm: wocpu_dlm@0x152E8000 {
-+ compatible = "mediatek,wocpu_dlm";
-+ reg = <0 0x152E8000 0 0x2000>;
-+
-+ resets = <ðsysrst 0>;
-+ reset-names = "wocpu_rst";
- };
-
-- wocpu_dlm: wocpu_dlm@151E8000 {
-+ wocpu2_dlm: wocpu_dlm@0x153E8000 {
- compatible = "mediatek,wocpu_dlm";
-- reg = <0 0x151E8000 0 0x2000>,
-- <0 0x152E8000 0 0x2000>,
-- <0 0x153E8000 0 0x2000>;
-+ reg = <0 0x153E8000 0 0x2000>;
-
- resets = <ðsysrst 0>;
- reset-names = "wocpu_rst";
- };
-
-- cpu_boot: wocpu_boot@15194000 {
-- compatible = "mediatek,wocpu_boot";
-- reg = <0 0x15194000 0 0x1000>,
-- <0 0x15294000 0 0x1000>,
-- <0 0x15394000 0 0x1000>;
-+ cpu0_boot: wocpu_boot@15194000 {
-+ compatible = "mediatek,wocpu0_boot";
-+ reg = <0 0x15194000 0 0x1000>;
-+ };
-+
-+ cpu1_boot: wocpu_boot@15294000 {
-+ compatible = "mediatek,wocpu1_boot";
-+ reg = <0 0x15294000 0 0x1000>;
-+ };
-+
-+ cpu2_boot: wocpu_boot@15394000 {
-+ compatible = "mediatek,wocpu2_boot";
-+ reg = <0 0x15394000 0 0x1000>;
- };
-
- reserved-memory {
-@@ -901,6 +938,7 @@
- <&topckgen CK_TOP_CB_NET2_D2>;
- mediatek,ethsys = <ðsys>;
- mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
-+ mediatek,wed = <&wed0>, <&wed1>, <&wed2>;
- mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
- mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
- mediatek,xfi_pll = <&xfi_pll>;
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-index 578a489..596f0ca 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
-@@ -369,9 +369,23 @@
- status = "okay";
- };
-
--&wed {
-+&wed0 {
- dy_txbm_enable = "true";
- dy_txbm_budge = <8>;
- txbm_init_sz = <10>;
- status = "okay";
- };
-+
-+&wed1 {
-+ dy_txbm_enable = "true";
-+ dy_txbm_budge = <8>;
-+ txbm_init_sz = <10>;
-+ status = "okay";
-+};
-+
-+&wed2 {
-+ dy_txbm_enable = "true";
-+ dy_txbm_budge = <8>;
-+ txbm_init_sz = <10>;
-+ status = "okay";
-+};
-\ No newline at end of file
-diff --git a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-index e743718..f430118 100644
---- a/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-+++ b/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
-@@ -381,9 +381,23 @@
- status = "okay";
- };
-
--&wed {
-+&wed0 {
- dy_txbm_enable = "true";
- dy_txbm_budge = <8>;
- txbm_init_sz = <10>;
- status = "okay";
- };
-+
-+&wed1 {
-+ dy_txbm_enable = "true";
-+ dy_txbm_budge = <8>;
-+ txbm_init_sz = <10>;
-+ status = "okay";
-+};
-+
-+&wed2 {
-+ dy_txbm_enable = "true";
-+ dy_txbm_budge = <8>;
-+ txbm_init_sz = <10>;
-+ status = "okay";
-+};
-\ No newline at end of file
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index c75ce25..ec78adf 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5216,7 +5216,8 @@ static int mtk_probe(struct platform_device *pdev)
- "mediatek,wed", i);
- static const u32 wdma_regs[] = {
- MTK_WDMA0_BASE,
-- MTK_WDMA1_BASE
-+ MTK_WDMA1_BASE,
-+ MTK_WDMA2_BASE
- };
- void __iomem *wdma;
- u32 wdma_phy;
-diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 1074f46..a788d43 100644
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -623,9 +623,12 @@
- #define RX_DMA_SPORT_MASK 0x7
- #define RX_DMA_SPORT_MASK_V2 0xf
-
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
- #define MTK_WDMA0_BASE 0x4800
- #define MTK_WDMA1_BASE 0x4c00
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WDMA2_BASE 0x5000
-+#endif
- #else
- #define MTK_WDMA0_BASE 0x2800
- #define MTK_WDMA1_BASE 0x2c00
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-old mode 100755
-new mode 100644
-index 0e9c0bd..ae0acd5
---- a/drivers/net/ethernet/mediatek/mtk_ppe.c
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
-@@ -9,6 +9,7 @@
- #include <linux/if_ether.h>
- #include <linux/if_vlan.h>
- #include <net/dsa.h>
-+#include <net/route.h>
- #include "mtk_eth_soc.h"
- #include "mtk_ppe.h"
- #include "mtk_ppe_regs.h"
-@@ -407,7 +408,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
- }
-
- int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
-- int bss, int wcid)
-+ int bss, int wcid, bool amsdu_en)
- {
- struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
- u32 *ib2 = mtk_foe_entry_ib2(entry);
-@@ -419,6 +420,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
-
- l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
- FIELD_PREP(MTK_FOE_WINFO_BSS, bss);
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ l2->winfo_pao = FIELD_PREP(MTK_FOE_WINFO_PAO_AMSDU_EN, amsdu_en);
-+#endif
- #else
- if (wdma_idx)
- *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
-@@ -454,6 +458,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
- *ib2 &= ~MTK_FOE_IB2_DSCP;
- *ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
-
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
-+
-+ if (*ib2 & MTK_FOE_IB2_WDMA_WINFO &&
-+ l2->winfo_pao & MTK_FOE_WINFO_PAO_AMSDU_EN) {
-+ u8 tid = (dscp >> 5) & 0xf;
-+
-+ l2->winfo_pao |= FIELD_PREP(MTK_FOE_WINFO_PAO_TID, tid);
-+ }
-+#endif
-+
- return 0;
- }
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
-index 2a8b6ef..66c7f10 100644
---- a/drivers/net/ethernet/mediatek/mtk_ppe.h
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
-@@ -428,7 +428,7 @@ int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
- int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
- int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
- int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
-- int bss, int wcid);
-+ int bss, int wcid, bool amsdu_en);
- int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
- int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
- bool mtk_foe_entry_match(struct mtk_foe_entry *entry, struct mtk_foe_entry *data);
-diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-index 95174b7..339359e 100644
---- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-@@ -112,6 +112,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
- info->queue = path.mtk_wdma.queue;
- info->bss = path.mtk_wdma.bss;
- info->wcid = path.mtk_wdma.wcid;
-+ info->amsdu_en = path.mtk_wdma.amsdu_en;
-
- return 0;
- }
-@@ -193,13 +194,15 @@ mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
-
- if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
- mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
-- info.wcid);
-+ info.wcid, info.amsdu_en);
- pse_port = PSE_PPE0_PORT;
- #if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
- if (info.wdma_idx == 0)
- pse_port = PSE_WDMA0_PORT;
- else if (info.wdma_idx == 1)
- pse_port = PSE_WDMA1_PORT;
-+ else if (info.wdma_idx == 2)
-+ pse_port = PSE_WDMA2_PORT;
- else
- return -EOPNOTSUPP;
- #endif
-@@ -481,8 +484,6 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- if (data.pppoe.num == 1)
- mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
-
-- mtk_foe_entry_set_dscp(&foe, dscp);
--
- mtk_foe_entry_set_sp(eth->ppe[ppe_index], &foe);
-
- err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
-@@ -490,8 +491,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- if (err)
- return err;
-
-- if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
-- return err;
-+ mtk_foe_entry_set_dscp(&foe, dscp);
-+ /*if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
-+ return err;*/
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
-@@ -516,8 +518,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
- mtk_foe_entry_clear(eth->ppe[ppe_index], entry);
- free:
- kfree(entry);
-- if (wed_index >= 0)
-- mtk_wed_flow_remove(wed_index);
-+ /*if (wed_index >= 0)
-+ mtk_wed_flow_remove(wed_index);*/
- return err;
- }
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 48c35ae..561fc6c 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -28,7 +28,7 @@ struct wo_cmd_ring {
- u32 cnt;
- u32 unit;
- };
--static struct mtk_wed_hw *hw_list[2];
-+static struct mtk_wed_hw *hw_list[3];
- static DEFINE_MUTEX(hw_lock);
-
- static void
-@@ -73,6 +73,26 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
- return wdma_r32(dev, MTK_WDMA_GLO_CFG);
- }
-
-+static u32
-+mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
-+{
-+ if (wed_r32(dev, reg) & mask)
-+ return true;
-+
-+ return false;
-+}
-+
-+static int
-+mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
-+{
-+ int sleep = 1000;
-+ int timeout = 100 * sleep;
-+ u32 val;
-+
-+ return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
-+ timeout, false, dev, reg, mask);
-+}
-+
- static int
- mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- {
-@@ -235,6 +255,8 @@ mtk_wed_assign(struct mtk_wed_device *dev)
- continue;
-
- hw->wed_dev = dev;
-+ hw->pci_base = MTK_WED_PCIE_BASE;
-+
- return hw;
- }
-
-@@ -242,23 +264,84 @@ mtk_wed_assign(struct mtk_wed_device *dev)
- }
-
- static int
--mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
-+mtk_wed_pao_buffer_alloc(struct mtk_wed_device *dev)
-+{
-+ struct mtk_wed_pao *pao;
-+ int i, j;
-+
-+ pao = kzalloc(sizeof(struct mtk_wed_pao), GFP_KERNEL);
-+ if (!pao)
-+ return -ENOMEM;
-+
-+ dev->hw->wed_pao = pao;
-+
-+ for (i = 0; i < 32; i++) {
-+ /* each segment is 64K*/
-+ pao->hif_txd[i] = (char *)__get_free_pages(GFP_ATOMIC |
-+ GFP_DMA32 |
-+ __GFP_ZERO, 4);
-+ if (!pao->hif_txd[i])
-+ goto err;
-+
-+ pao->hif_txd_phys[i] = dma_map_single(dev->hw->dev,
-+ pao->hif_txd[i],
-+ 16 * PAGE_SIZE,
-+ DMA_TO_DEVICE);
-+ if (unlikely(dma_mapping_error(dev->hw->dev,
-+ pao->hif_txd_phys[i])))
-+ goto err;
-+ }
-+
-+ return 0;
-+
-+err:
-+ for (j = 0; j < i; j++)
-+ dma_unmap_single(dev->hw->dev, pao->hif_txd_phys[j],
-+ 16 * PAGE_SIZE, DMA_TO_DEVICE);
-+
-+ return -ENOMEM;
-+}
-+
-+static int
-+mtk_wed_pao_free_buffer(struct mtk_wed_device *dev)
-+{
-+ struct mtk_wed_pao *pao = dev->hw->wed_pao;
-+ int i;
-+
-+ for (i = 0; i < 32; i++) {
-+ dma_unmap_single(dev->hw->dev, pao->hif_txd_phys[i],
-+ 16 * PAGE_SIZE, DMA_TO_DEVICE);
-+ free_pages((unsigned long)pao->hif_txd[i], 4);
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
- {
- struct mtk_wdma_desc *desc;
-+ void *desc_ptr;
- dma_addr_t desc_phys;
-- void **page_list;
-+ struct dma_page_info *page_list;
- u32 last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG1;
- int token = dev->wlan.token_start;
-- int ring_size, n_pages, page_idx;
-- int i;
--
-+ int ring_size, pkt_nums, n_pages, page_idx;
-+ int i, ret = 0;
-
- if (dev->ver == MTK_WED_V1) {
- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
-- } else {
-+ pkt_nums = ring_size;
-+ dev->tx_buf_ring.desc_size = sizeof(struct mtk_wdma_desc);
-+ } else if (dev->hw->version == 2) {
- ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
- MTK_WED_WDMA_RING_SIZE * 2;
- last_seg = MTK_WDMA_DESC_CTRL_LAST_SEG0;
-+ dev->tx_buf_ring.desc_size = sizeof(struct mtk_wdma_desc);
-+ } else if (dev->hw->version == 3) {
-+ ring_size = MTK_WED_TX_BM_DMA_SIZE;
-+ pkt_nums = MTK_WED_TX_BM_PKT_CNT;
-+ dev->tx_buf_ring.desc_size = sizeof(struct mtk_rxbm_desc);
- }
-
- n_pages = ring_size / MTK_WED_BUF_PER_PAGE;
-@@ -267,18 +350,20 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- if (!page_list)
- return -ENOMEM;
-
-- dev->buf_ring.size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
-- dev->buf_ring.pages = page_list;
-+ dev->tx_buf_ring.size = ring_size;
-+ dev->tx_buf_ring.pages = page_list;
-+ dev->tx_buf_ring.pkt_nums = pkt_nums;
-
-- desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-- &desc_phys, GFP_KERNEL);
-- if (!desc)
-+ desc_ptr = dma_alloc_coherent(dev->hw->dev,
-+ ring_size * dev->tx_buf_ring.desc_size,
-+ &desc_phys, GFP_KERNEL);
-+ if (!desc_ptr)
- return -ENOMEM;
-
-- dev->buf_ring.desc = desc;
-- dev->buf_ring.desc_phys = desc_phys;
-+ dev->tx_buf_ring.desc = desc_ptr;
-+ dev->tx_buf_ring.desc_phys = desc_phys;
-
-- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
-+ for (i = 0, page_idx = 0; i < pkt_nums; i += MTK_WED_BUF_PER_PAGE) {
- dma_addr_t page_phys, buf_phys;
- struct page *page;
- void *buf;
-@@ -295,7 +380,10 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- return -ENOMEM;
- }
-
-- page_list[page_idx++] = page;
-+ page_list[page_idx].addr = page;
-+ page_list[page_idx].addr_phys = page_phys;
-+ page_idx++;
-+
- dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
- DMA_BIDIRECTIONAL);
-
-@@ -303,19 +391,23 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- buf_phys = page_phys;
-
- for (s = 0; s < MTK_WED_BUF_PER_PAGE; s++) {
-- u32 txd_size;
--
-- txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
--
-+ desc = desc_ptr;
- desc->buf0 = buf_phys;
-- desc->buf1 = buf_phys + txd_size;
-- desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
-- txd_size) |
-- FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
-- MTK_WED_BUF_SIZE - txd_size) |
-- last_seg;
-- desc->info = 0;
-- desc++;
-+ if (dev->hw->version < 3) {
-+ u32 txd_size;
-+
-+ txd_size = dev->wlan.init_buf(buf, buf_phys, token++);
-+ desc->buf1 = buf_phys + txd_size;
-+ desc->ctrl = FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN0,
-+ txd_size) |
-+ FIELD_PREP(MTK_WDMA_DESC_CTRL_LEN1,
-+ MTK_WED_BUF_SIZE - txd_size) |
-+ last_seg;
-+ desc->info = 0;
-+ } else {
-+ desc->ctrl = token << 16;
-+ }
-+ desc_ptr += dev->tx_buf_ring.desc_size;
-
- buf += MTK_WED_BUF_SIZE;
- buf_phys += MTK_WED_BUF_SIZE;
-@@ -325,15 +417,18 @@ mtk_wed_buffer_alloc(struct mtk_wed_device *dev)
- DMA_BIDIRECTIONAL);
- }
-
-- return 0;
-+ if (dev->hw->version == 3)
-+ ret = mtk_wed_pao_buffer_alloc(dev);
-+
-+ return ret;
- }
-
- static void
--mtk_wed_free_buffer(struct mtk_wed_device *dev)
-+mtk_wed_free_tx_buffer(struct mtk_wed_device *dev)
- {
-- struct mtk_wdma_desc *desc = dev->buf_ring.desc;
-- void **page_list = dev->buf_ring.pages;
-- int ring_size, page_idx;
-+ struct mtk_rxbm_desc *desc = dev->tx_buf_ring.desc;
-+ struct dma_page_info *page_list = dev->tx_buf_ring.pages;
-+ int ring_size, page_idx, pkt_nums;
- int i;
-
- if (!page_list)
-@@ -342,33 +437,33 @@ mtk_wed_free_buffer(struct mtk_wed_device *dev)
- if (!desc)
- goto free_pagelist;
-
-- if (dev->ver == MTK_WED_V1) {
-- ring_size = dev->wlan.nbuf & ~(MTK_WED_BUF_PER_PAGE - 1);
-- } else {
-- ring_size = MTK_WED_VLD_GROUP_SIZE * MTK_WED_PER_GROUP_PKT +
-- MTK_WED_WDMA_RING_SIZE * 2;
-+ pkt_nums = ring_size = dev->tx_buf_ring.size;
-+ if (dev->hw->version == 3) {
-+ mtk_wed_pao_free_buffer(dev);
-+ pkt_nums = dev->tx_buf_ring.pkt_nums;
- }
-
-- for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_BUF_PER_PAGE) {
-- void *page = page_list[page_idx++];
-+ for (i = 0, page_idx = 0; i < pkt_nums; i += MTK_WED_BUF_PER_PAGE) {
-+ void *page = page_list[page_idx].addr;
-
- if (!page)
- break;
-
-- dma_unmap_page(dev->hw->dev, desc[i].buf0,
-+ dma_unmap_page(dev->hw->dev, page_list[page_idx].addr_phys,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- __free_page(page);
-+ page_idx++;
- }
-
-- dma_free_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-- desc, dev->buf_ring.desc_phys);
-+ dma_free_coherent(dev->hw->dev, ring_size * dev->tx_buf_ring.desc_size,
-+ dev->tx_buf_ring.desc, dev->tx_buf_ring.desc_phys);
-
- free_pagelist:
- kfree(page_list);
- }
-
- static int
--mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
-+mtk_wed_rx_buffer_alloc(struct mtk_wed_device *dev)
- {
- struct mtk_rxbm_desc *desc;
- dma_addr_t desc_phys;
-@@ -389,7 +484,7 @@ mtk_wed_rx_bm_alloc(struct mtk_wed_device *dev)
- }
-
- static void
--mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
-+mtk_wed_free_rx_buffer(struct mtk_wed_device *dev)
- {
- struct mtk_rxbm_desc *desc = dev->rx_buf_ring.desc;
- int ring_size = dev->rx_buf_ring.size;
-@@ -403,6 +498,113 @@ mtk_wed_free_rx_bm(struct mtk_wed_device *dev)
- desc, dev->rx_buf_ring.desc_phys);
- }
-
-+/* TODO */
-+static int
-+mtk_wed_rx_page_buffer_alloc(struct mtk_wed_device *dev)
-+{
-+ int ring_size = dev->wlan.rx_nbuf, buf_num = MTK_WED_RX_PG_BM_CNT;
-+ struct mtk_rxbm_desc *desc;
-+ dma_addr_t desc_phys;
-+ struct dma_page_info *page_list;
-+ int n_pages, page_idx;
-+ int i;
-+
-+ n_pages = buf_num / MTK_WED_RX_PAGE_BUF_PER_PAGE;
-+
-+ page_list = kcalloc(n_pages, sizeof(*page_list), GFP_KERNEL);
-+ if (!page_list)
-+ return -ENOMEM;
-+
-+ dev->rx_page_buf_ring.size = ring_size & ~(MTK_WED_BUF_PER_PAGE - 1);
-+ dev->rx_page_buf_ring.pages = page_list;
-+ dev->rx_page_buf_ring.pkt_nums = buf_num;
-+
-+ desc = dma_alloc_coherent(dev->hw->dev, ring_size * sizeof(*desc),
-+ &desc_phys, GFP_KERNEL);
-+ if (!desc)
-+ return -ENOMEM;
-+
-+ dev->rx_page_buf_ring.desc = desc;
-+ dev->rx_page_buf_ring.desc_phys = desc_phys;
-+
-+ for (i = 0, page_idx = 0; i < buf_num; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
-+ dma_addr_t page_phys, buf_phys;
-+ struct page *page;
-+ void *buf;
-+ int s;
-+
-+ page = __dev_alloc_pages(GFP_KERNEL, 0);
-+ if (!page)
-+ return -ENOMEM;
-+
-+ page_phys = dma_map_page(dev->hw->dev, page, 0, PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ if (dma_mapping_error(dev->hw->dev, page_phys)) {
-+ __free_page(page);
-+ return -ENOMEM;
-+ }
-+
-+ page_list[page_idx].addr= page;
-+ page_list[page_idx].addr_phys= page_phys;
-+ page_idx++;
-+
-+ dma_sync_single_for_cpu(dev->hw->dev, page_phys, PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+
-+ buf = page_to_virt(page);
-+ buf_phys = page_phys;
-+
-+ for (s = 0; s < MTK_WED_RX_PAGE_BUF_PER_PAGE; s++) {
-+
-+ desc->buf0 = cpu_to_le32(buf_phys);
-+ desc++;
-+
-+ buf += MTK_WED_PAGE_BUF_SIZE;
-+ buf_phys += MTK_WED_PAGE_BUF_SIZE;
-+ }
-+
-+ dma_sync_single_for_device(dev->hw->dev, page_phys, PAGE_SIZE,
-+ DMA_BIDIRECTIONAL);
-+ }
-+
-+ return 0;
-+}
-+
-+static void
-+mtk_wed_rx_page_free_buffer(struct mtk_wed_device *dev)
-+{
-+ struct mtk_rxbm_desc *desc = dev->rx_page_buf_ring.desc;
-+ struct dma_page_info *page_list = dev->rx_page_buf_ring.pages;
-+ int ring_size, page_idx;
-+ int i;
-+
-+ if (!page_list)
-+ return;
-+
-+ if (!desc)
-+ goto free_pagelist;
-+
-+ ring_size = dev->rx_page_buf_ring.pkt_nums;
-+
-+ for (i = 0, page_idx = 0; i < ring_size; i += MTK_WED_RX_PAGE_BUF_PER_PAGE) {
-+ void *page = page_list[page_idx].addr;
-+
-+ if (!page)
-+ break;
-+
-+ dma_unmap_page(dev->hw->dev, page_list[page_idx].addr_phys,
-+ PAGE_SIZE, DMA_BIDIRECTIONAL);
-+ __free_page(page);
-+ page_idx++;
-+ }
-+
-+ dma_free_coherent(dev->hw->dev, dev->rx_page_buf_ring.size * sizeof(*desc),
-+ desc, dev->rx_page_buf_ring.desc_phys);
-+
-+free_pagelist:
-+ kfree(page_list);
-+}
-+
- static void
- mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int scale)
- {
-@@ -416,19 +618,35 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring, int sca
- static void
- mtk_wed_free_tx_rings(struct mtk_wed_device *dev)
- {
-- int i;
-+ int i, scale = dev->hw->version > 1 ? 2 : 1;
-
- for (i = 0; i < ARRAY_SIZE(dev->tx_ring); i++)
-- mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
-+ if ((dev->tx_ring[i].flags & MTK_WED_RING_CONFIGURED))
-+ mtk_wed_free_ring(dev, &dev->tx_ring[i], 1);
-+
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-- mtk_wed_free_ring(dev, &dev->tx_wdma[i], dev->ver);
-+ if ((dev->tx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
-+ mtk_wed_free_ring(dev, &dev->tx_wdma[i], scale);
- }
-
- static void
- mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
- {
-- mtk_wed_free_rx_bm(dev);
-+ int i, scale = dev->hw->version > 1 ? 2 : 1;
-+
-+ for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++)
-+ if ((dev->rx_ring[i].flags & MTK_WED_RING_CONFIGURED))
-+ mtk_wed_free_ring(dev, &dev->rx_ring[i], 1);
-+
-+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
-+ if ((dev->rx_wdma[i].flags & MTK_WED_RING_CONFIGURED))
-+ mtk_wed_free_ring(dev, &dev->rx_wdma[i], scale);
-+
-+ mtk_wed_free_rx_buffer(dev);
- mtk_wed_free_ring(dev, &dev->rro.rro_ring, 1);
-+
-+ if (dev->wlan.hwrro)
-+ mtk_wed_rx_page_free_buffer(dev);
- }
-
- static void
-@@ -437,7 +655,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- u32 wdma_mask;
-
- wdma_mask = FIELD_PREP(MTK_WDMA_INT_MASK_RX_DONE, GENMASK(1, 0));
-- if (dev->ver > MTK_WED_V1)
-+ if (mtk_wed_get_rx_capa(dev))
- wdma_mask |= FIELD_PREP(MTK_WDMA_INT_MASK_TX_DONE,
- GENMASK(1, 0));
- /* wed control cr set */
-@@ -447,7 +665,7 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- MTK_WED_CTRL_WED_TX_BM_EN |
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-
-- if (dev->ver == MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER,
- MTK_WED_PCIE_INT_TRIGGER_STATUS);
-
-@@ -458,6 +676,8 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
- } else {
-+ if (dev->hw->version == 3)
-+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_TKID_ALI_EN);
-
- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_TX,
- MTK_WED_WPDMA_INT_CTRL_TX0_DONE_EN |
-@@ -475,18 +695,20 @@ mtk_wed_set_int(struct mtk_wed_device *dev, u32 irq_mask)
- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_TX_FREE_DONE_TRIG,
- dev->wlan.txfree_tbit));
-
-- wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
-- MTK_WED_WPDMA_INT_CTRL_RX0_EN |
-- MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
-- MTK_WED_WPDMA_INT_CTRL_RX1_EN |
-- MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
-- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
-- dev->wlan.rx_tbit[0]) |
-- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
-- dev->wlan.rx_tbit[1]));
-+ if (mtk_wed_get_rx_capa(dev))
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RX,
-+ MTK_WED_WPDMA_INT_CTRL_RX0_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RX0_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_RX1_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RX1_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX0_DONE_TRIG,
-+ dev->wlan.rx_tbit[0]) |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RX1_DONE_TRIG,
-+ dev->wlan.rx_tbit[1]));
- }
-+
- wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, wdma_mask);
-- if (dev->ver == MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
- wed_clr(dev, MTK_WED_WDMA_INT_CTRL, wdma_mask);
- } else {
- wed_w32(dev, MTK_WED_WDMA_INT_CLR, wdma_mask);
-@@ -506,6 +728,21 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
- {
- u32 mask = MTK_WED_EXT_INT_STATUS_ERROR_MASK;
-
-+ switch (dev->hw->version) {
-+ case 1:
-+ mask |= MTK_WED_EXT_INT_STATUS_TX_DRV_R_RESP_ERR;
-+ break;
-+ case 2 :
-+ mask |= MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 |
-+ MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 |
-+ MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT |
-+ MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR;
-+ break;
-+ case 3:
-+ mask = MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
-+ break;
-+ }
-+
- if (!dev->hw->num_flows)
- mask &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
-
-@@ -514,31 +751,86 @@ mtk_wed_set_ext_int(struct mtk_wed_device *dev, bool en)
- }
-
- static void
--mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
-+mtk_wed_pao_init(struct mtk_wed_device *dev)
- {
-- if (en) {
-- wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
-- wed_w32(dev, MTK_WED_TXP_DW1,
-- FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
-- } else {
-- wed_w32(dev, MTK_WED_TXP_DW1,
-- FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0100));
-- wed_clr(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
-+ struct mtk_wed_pao *pao = dev->hw->wed_pao;
-+ int i;
-+
-+ for (i = 0; i < 32; i++)
-+ wed_w32(dev, MTK_WED_PAO_HIFTXD_BASE_L(i),
-+ pao->hif_txd_phys[i]);
-+
-+ /* init all sta parameter */
-+ wed_w32(dev, MTK_WED_PAO_STA_INFO_INIT, MTK_WED_PAO_STA_RMVL |
-+ MTK_WED_PAO_STA_WTBL_HDRT_MODE |
-+ FIELD_PREP(MTK_WED_PAO_STA_MAX_AMSDU_LEN,
-+ dev->wlan.max_amsdu_len >> 8) |
-+ FIELD_PREP(MTK_WED_PAO_STA_MAX_AMSDU_NUM,
-+ dev->wlan.max_amsdu_nums));
-+
-+ wed_w32(dev, MTK_WED_PAO_STA_INFO, MTK_WED_PAO_STA_INFO_DO_INIT);
-+
-+ if (mtk_wed_poll_busy(dev, MTK_WED_PAO_STA_INFO,
-+ MTK_WED_PAO_STA_INFO_DO_INIT)) {
-+ dev_err(dev->hw->dev, "mtk_wed%d: pao init failed!\n",
-+ dev->hw->index);
-+ return;
- }
-+
-+ /* init pao txd src */
-+ wed_set(dev, MTK_WED_PAO_HIFTXD_CFG,
-+ FIELD_PREP(MTK_WED_PAO_HIFTXD_SRC, dev->hw->index));
-+
-+ /* init qmem */
-+ wed_set(dev, MTK_WED_PAO_PSE, MTK_WED_PAO_PSE_RESET);
-+ if (mtk_wed_poll_busy(dev, MTK_WED_PAO_MON_QMEM_STS1, BIT(29))) {
-+ pr_info("%s: init pao qmem fail\n", __func__);
-+ return;
-+ }
-+
-+ /* eagle E1 PCIE1 tx ring 22 flow control issue */
-+ if (dev->wlan.chip_id == 0x7991) {
-+ wed_clr(dev, MTK_WED_PAO_AMSDU_FIFO,
-+ MTK_WED_PAO_AMSDU_IS_PRIOR0_RING);
-+ }
-+
-+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+
-+ return;
- }
-
--static void
--mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
-+static int
-+mtk_wed_hwrro_init(struct mtk_wed_device *dev)
- {
--#define MTK_WFMDA_RX_DMA_EN BIT(2)
-+ if (!mtk_wed_get_rx_capa(dev))
-+ return 0;
-
-+ wed_set(dev, MTK_WED_RRO_PG_BM_RX_DMAM,
-+ FIELD_PREP(MTK_WED_RRO_PG_BM_RX_SDL0, 128));
-+
-+ wed_w32(dev, MTK_WED_RRO_PG_BM_BASE,
-+ dev->rx_page_buf_ring.desc_phys);
-+
-+ wed_w32(dev, MTK_WED_RRO_PG_BM_INIT_PTR,
-+ MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX |
-+ FIELD_PREP(MTK_WED_RRO_PG_BM_SW_TAIL_IDX,
-+ MTK_WED_RX_PG_BM_CNT));
-+
-+ /* enable rx_page_bm to fetch dmad */
-+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
-+
-+ return 0;
-+}
-+
-+static int
-+mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev,
-+ struct mtk_wed_ring *ring)
-+{
- int timeout = 3;
-- u32 cur_idx, regs;
-+ u32 cur_idx;
-
- do {
-- regs = MTK_WED_WPDMA_RING_RX_DATA(idx) +
-- MTK_WED_RING_OFS_CPU_IDX;
-- cur_idx = wed_r32(dev, regs);
-+ cur_idx = readl(ring->wpdma + MTK_WED_RING_OFS_CPU_IDX);
- if (cur_idx == MTK_WED_RX_RING_SIZE - 1)
- break;
-
-@@ -546,70 +838,133 @@ mtk_wed_check_wfdma_rx_fill(struct mtk_wed_device *dev, int idx)
- timeout--;
- } while (timeout > 0);
-
-- if (timeout) {
-- unsigned int val;
-+ return timeout;
-+}
-
-- val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
-- dev->wlan.phy_base);
-- val |= MTK_WFMDA_RX_DMA_EN;
-
-- wifi_w32(dev, dev->wlan.wpdma_rx_glo -
-- dev->wlan.phy_base, val);
-+static void
-+mtk_wed_set_512_support(struct mtk_wed_device *dev, bool en)
-+{
-+ if (en) {
-+ wed_w32(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
-+ wed_w32(dev, MTK_WED_TXP_DW1,
-+ FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0103));
- } else {
-- dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
-- dev->hw->index, idx);
-+ wed_w32(dev, MTK_WED_TXP_DW1,
-+ FIELD_PREP(MTK_WED_WPDMA_WRITE_TXP, 0x0100));
-+ wed_clr(dev, MTK_WED_TXDP_CTRL, MTK_WED_TXDP_DW9_OVERWR);
- }
- }
-
- static void
- mtk_wed_dma_enable(struct mtk_wed_device *dev)
- {
-- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-- MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-+#define MTK_WFMDA_RX_DMA_EN BIT(2)
-+
-+ if (dev->hw->version == 1)
-+ wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
-+ MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV);
-
- wed_set(dev, MTK_WED_GLO_CFG,
- MTK_WED_GLO_CFG_TX_DMA_EN |
- MTK_WED_GLO_CFG_RX_DMA_EN);
-+
-+ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ FIELD_PREP(MTK_WED_WDMA_RX_PREF_BURST_SIZE, 0x10) |
-+ FIELD_PREP(MTK_WED_WDMA_RX_PREF_LOW_THRES, 0x8));
-+ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_DDONE2_EN);
-+
-+ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
-+
- wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
-- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN |
-+ MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR);
- wed_set(dev, MTK_WED_WDMA_GLO_CFG,
- MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-
- wdma_set(dev, MTK_WDMA_GLO_CFG,
-- MTK_WDMA_GLO_CFG_TX_DMA_EN |
-+ MTK_WDMA_GLO_CFG_TX_DMA_EN /*|
- MTK_WDMA_GLO_CFG_RX_INFO1_PRERES |
-- MTK_WDMA_GLO_CFG_RX_INFO2_PRERES);
-+ MTK_WDMA_GLO_CFG_RX_INFO2_PRERES*/);
-
-- if (dev->ver == MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
- wdma_set(dev, MTK_WDMA_GLO_CFG,
- MTK_WDMA_GLO_CFG_RX_INFO3_PRERES);
- } else {
- int idx = 0;
-
-- wed_set(dev, MTK_WED_WPDMA_CTRL,
-- MTK_WED_WPDMA_CTRL_SDL1_FIXED);
--
-- wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-- MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
-- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-+ if (mtk_wed_get_rx_capa(dev))
-+ wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-+ MTK_WED_WDMA_GLO_CFG_TX_DRV_EN |
-+ MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-
- wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_PKT_PROC |
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC);
-
-+ if (dev->hw->version == 3) {
-+ wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST);
-+ wed_set(dev, MTK_WED_WPDMA_GLO_CFG,
-+ MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK |
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK |
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
-+
-+ wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+ //wdma_w32(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+ if (mtk_wed_get_rx_capa(dev)) {
-+ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+ MTK_WED_WPDMA_RX_D_PREF_EN |
-+ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE, 0x10) |
-+ FIELD_PREP(MTK_WED_WPDMA_RX_D_PREF_LOW_THRES, 0x8));
-+
-+ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
-+
-+ wdma_set(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+
-+ wdma_set(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+ }
-+ }
-+
- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP |
- MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV);
-
-+ if (!mtk_wed_get_rx_capa(dev))
-+ return;
-+
-+ wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RXD_READ_LEN);
- wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
- MTK_WED_WPDMA_RX_D_RX_DRV_EN |
- FIELD_PREP(MTK_WED_WPDMA_RX_D_RXD_READ_LEN, 0x18) |
- FIELD_PREP(MTK_WED_WPDMA_RX_D_INIT_PHASE_RXEN_SEL,
- 0x2));
-
-- for (idx = 0; idx < dev->hw->ring_num; idx++)
-- mtk_wed_check_wfdma_rx_fill(dev, idx);
-+ for (idx = 0; idx < dev->hw->ring_num; idx++) {
-+ struct mtk_wed_ring *ring = &dev->rx_ring[idx];
-+
-+ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+ continue;
-+
-+ if(mtk_wed_check_wfdma_rx_fill(dev, ring)) {
-+ unsigned int val;
-+
-+ val = wifi_r32(dev, dev->wlan.wpdma_rx_glo -
-+ dev->wlan.phy_base);
-+ val |= MTK_WFMDA_RX_DMA_EN;
-+
-+ wifi_w32(dev, dev->wlan.wpdma_rx_glo -
-+ dev->wlan.phy_base, val);
-+
-+ dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable successful!\n",
-+ dev->hw->index, idx);
-+ } else {
-+ dev_err(dev->hw->dev, "mtk_wed%d: rx(%d) dma enable failed!\n",
-+ dev->hw->index, idx);
-+ }
-+ }
- }
- }
-
-@@ -644,15 +999,20 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
- MTK_WED_WPDMA_RX_D_RX_DRV_EN);
- wed_clr(dev, MTK_WED_WDMA_GLO_CFG,
- MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK);
-- }
-
-- mtk_wed_set_512_support(dev, false);
-+ if (dev->hw->version == 3 && mtk_wed_get_rx_capa(dev)) {
-+ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG,
-+ MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG,
-+ MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+ }
-+ }
- }
-
- static void
- mtk_wed_stop(struct mtk_wed_device *dev)
- {
-- if (dev->ver > MTK_WED_V1) {
-+ if (mtk_wed_get_rx_capa(dev)) {
- wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
- wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
- }
-@@ -677,13 +1037,21 @@ mtk_wed_deinit(struct mtk_wed_device *dev)
- MTK_WED_CTRL_WED_TX_BM_EN |
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-
-- if (dev->hw->ver == 1)
-+ if (dev->hw->version == 1)
- return;
-
- wed_clr(dev, MTK_WED_CTRL,
- MTK_WED_CTRL_RX_ROUTE_QM_EN |
- MTK_WED_CTRL_WED_RX_BM_EN |
- MTK_WED_CTRL_RX_RRO_QM_EN);
-+
-+ if (dev->hw->version == 3) {
-+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_TX_PAO);
-+ wed_clr(dev, MTK_WED_PCIE_INT_CTRL,
-+ MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
-+ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER);
-+ }
- }
-
- static void
-@@ -702,9 +1070,9 @@ mtk_wed_detach(struct mtk_wed_device *dev)
-
- mtk_wdma_tx_reset(dev);
-
-- mtk_wed_free_buffer(dev);
-+ mtk_wed_free_tx_buffer(dev);
- mtk_wed_free_tx_rings(dev);
-- if (dev->ver > MTK_WED_V1) {
-+ if (mtk_wed_get_rx_capa(dev)) {
- mtk_wed_wo_reset(dev);
- mtk_wed_free_rx_rings(dev);
- mtk_wed_wo_exit(hw);
-@@ -731,24 +1099,29 @@ mtk_wed_detach(struct mtk_wed_device *dev)
- static void
- mtk_wed_bus_init(struct mtk_wed_device *dev)
- {
--#define PCIE_BASE_ADDR0 0x11280000
-+ switch (dev->wlan.bus_type) {
-+ case MTK_WED_BUS_PCIE: {
-+ struct device_node *np = dev->hw->eth->dev->of_node;
-+ struct regmap *regs;
-
-- if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
-- struct device_node *node;
-- void __iomem * base_addr;
-- u32 value = 0;
-+ if (dev->hw->version == 2) {
-+ regs = syscon_regmap_lookup_by_phandle(np,
-+ "mediatek,wed-pcie");
-+ if (IS_ERR(regs))
-+ break;
-
-- node = of_parse_phandle(dev->hw->node, "mediatek,wed_pcie", 0);
-- if (!node) {
-- pr_err("%s: no wed_pcie node\n", __func__);
-- return;
-+ regmap_update_bits(regs, 0, BIT(0), BIT(0));
- }
-
-- base_addr = of_iomap(node, 0);
--
-- value = readl(base_addr);
-- value |= BIT(0);
-- writel(value, base_addr);
-+ if (dev->wlan.msi) {
-+ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, dev->hw->pci_base| 0xc08);
-+ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, dev->hw->pci_base | 0xc04);
-+ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(8));
-+ } else {
-+ wed_w32(dev, MTK_WED_PCIE_CFG_INTM, dev->hw->pci_base | 0x180);
-+ wed_w32(dev, MTK_WED_PCIE_CFG_BASE, dev->hw->pci_base | 0x184);
-+ wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
-+ }
-
- wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
- FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
-@@ -756,45 +1129,53 @@ mtk_wed_bus_init(struct mtk_wed_device *dev)
- /* pcie interrupt control: pola/source selection */
- wed_set(dev, MTK_WED_PCIE_INT_CTRL,
- MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
-- FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
-- wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
--
-- value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-- value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
-- wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
-- wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
-+ MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER |
-+ FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, dev->hw->index));
-
-- value = wed_r32(dev, MTK_WED_PCIE_CFG_INTM);
-- value = wed_r32(dev, MTK_WED_PCIE_CFG_BASE);
--
-- wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
-- wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
--
-- /* pola setting */
-- value = wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
-- wed_set(dev, MTK_WED_PCIE_INT_CTRL,
-- MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
-- } else if (dev->wlan.bus_type == MTK_WED_BUS_AXI) {
-+ break;
-+ }
-+ case MTK_WED_BUS_AXI:
- wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
- MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
- FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
-+ break;
-+ default:
-+ break;
- }
-+
- return;
- }
-
- static void
- mtk_wed_set_wpdma(struct mtk_wed_device *dev)
- {
-- if (dev->ver > MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
-+ wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
-+ } else {
-+ mtk_wed_bus_init(dev);
-+
- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_int);
- wed_w32(dev, MTK_WED_WPDMA_CFG_INT_MASK, dev->wlan.wpdma_mask);
-- wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
-+ wed_w32(dev, MTK_WED_WPDMA_CFG_TX, dev->wlan.wpdma_tx);
- wed_w32(dev, MTK_WED_WPDMA_CFG_TX_FREE, dev->wlan.wpdma_txfree);
-
-- wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
-- wed_w32(dev, MTK_WED_WPDMA_RX_RING, dev->wlan.wpdma_rx);
-- } else {
-- wed_w32(dev, MTK_WED_WPDMA_CFG_BASE, dev->wlan.wpdma_phys);
-+ if (mtk_wed_get_rx_capa(dev)) {
-+ int i;
-+
-+ wed_w32(dev, MTK_WED_WPDMA_RX_GLO_CFG, dev->wlan.wpdma_rx_glo);
-+ wed_w32(dev, MTK_WED_WPDMA_RX_RING0, dev->wlan.wpdma_rx[0]);
-+ if (dev->wlan.wpdma_rx[1])
-+ wed_w32(dev, MTK_WED_WPDMA_RX_RING1, dev->wlan.wpdma_rx[1]);
-+
-+ if (dev->wlan.hwrro) {
-+ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(0), dev->wlan.wpdma_rx_rro[0]);
-+ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(1), dev->wlan.wpdma_rx_rro[1]);
-+ for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) {
-+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING_CFG(i),
-+ dev->wlan.wpdma_rx_pg + i * 0x10);
-+ }
-+ }
-+ }
- }
- }
-
-@@ -806,21 +1187,25 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
- mtk_wed_deinit(dev);
- mtk_wed_reset(dev, MTK_WED_RESET_WED);
-
-- if (dev->ver > MTK_WED_V1)
-- mtk_wed_bus_init(dev);
--
- mtk_wed_set_wpdma(dev);
-
-- mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
-- MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
-- MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-- set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
-- MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
-- MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
-+ if (dev->hw->version == 3) {
-+ mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE;
-+ set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2);
-+ } else {
-+ mask = MTK_WED_WDMA_GLO_CFG_BT_SIZE |
-+ MTK_WED_WDMA_GLO_CFG_DYNAMIC_DMAD_RECYCLE |
-+ MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-+ set = FIELD_PREP(MTK_WED_WDMA_GLO_CFG_BT_SIZE, 2) |
-+ MTK_WED_WDMA_GLO_CFG_DYNAMIC_SKIP_DMAD_PREP |
-+ MTK_WED_WDMA_GLO_CFG_IDLE_DMAD_SUPPLY;
-+ }
-+
- wed_m32(dev, MTK_WED_WDMA_GLO_CFG, mask, set);
-
-- if (dev->ver == MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
- u32 offset;
-+
- offset = dev->hw->index ? 0x04000400 : 0;
- wed_w32(dev, MTK_WED_WDMA_OFFSET0, 0x2a042a20 + offset);
- wed_w32(dev, MTK_WED_WDMA_OFFSET1, 0x29002800 + offset);
-@@ -907,11 +1292,16 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
- } while (1);
-
- /* configure RX_ROUTE_QM */
-- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
-- wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-- FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
-- wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+ if (dev->hw->version == 2) {
-+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_TXDMAD_FPORT);
-+ wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-+ FIELD_PREP(MTK_WED_RTQM_TXDMAD_FPORT, 0x3 + dev->hw->index));
-+ wed_clr(dev, MTK_WED_RTQM_GLO_CFG, MTK_WED_RTQM_Q_RST);
-+ } else {
-+ wed_set(dev, MTK_WED_RTQM_ENQ_CFG0,
-+ FIELD_PREP(MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT, 0x3 + dev->hw->index));
-+ }
-
- /* enable RX_ROUTE_QM */
- wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
-@@ -920,23 +1310,45 @@ mtk_wed_route_qm_hw_init(struct mtk_wed_device *dev)
- static void
- mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
- {
-- int size = dev->buf_ring.size;
-+ int size = dev->wlan.nbuf;
- int rev_size = MTK_WED_TX_RING_SIZE / 2;
-- int thr = 1;
-+ int thr_lo = 1, thr_hi = 1;
-
-- if (dev->ver > MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
-+ wed_w32(dev, MTK_WED_TX_BM_CTRL,
-+ MTK_WED_TX_BM_CTRL_PAUSE |
-+ FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
-+ FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
-+ } else {
- size = MTK_WED_WDMA_RING_SIZE * ARRAY_SIZE(dev->tx_wdma) +
-- dev->buf_ring.size;
-+ dev->tx_buf_ring.size;
- rev_size = size;
-- thr = 0;
-+ thr_lo = 0;
-+ thr_hi = MTK_WED_TX_BM_DYN_THR_HI;
-+
-+ wed_w32(dev, MTK_WED_TX_TKID_CTRL,
-+ MTK_WED_TX_TKID_CTRL_PAUSE |
-+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
-+ size / 128) |
-+ FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
-+ size / 128));
-+
-+ /* return SKBID + SDP back to bm */
-+ if (dev->ver == 3) {
-+ wed_set(dev, MTK_WED_TX_TKID_CTRL,
-+ MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
-+ size = dev->wlan.nbuf;
-+ rev_size = size;
-+ } else {
-+ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
-+ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
-+ MTK_WED_TX_TKID_DYN_THR_HI);
-+ }
- }
-
-- wed_w32(dev, MTK_WED_TX_BM_CTRL,
-- MTK_WED_TX_BM_CTRL_PAUSE |
-- FIELD_PREP(MTK_WED_TX_BM_CTRL_VLD_GRP_NUM, size / 128) |
-- FIELD_PREP(MTK_WED_TX_BM_CTRL_RSV_GRP_NUM, rev_size / 128));
-+ mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
-
-- wed_w32(dev, MTK_WED_TX_BM_BASE, dev->buf_ring.desc_phys);
-+ wed_w32(dev, MTK_WED_TX_BM_BASE, dev->tx_buf_ring.desc_phys);
-
- wed_w32(dev, MTK_WED_TX_BM_TKID,
- FIELD_PREP(MTK_WED_TX_BM_TKID_START,
-@@ -946,25 +1358,44 @@ mtk_wed_tx_hw_init(struct mtk_wed_device *dev)
-
- wed_w32(dev, MTK_WED_TX_BM_BUF_LEN, MTK_WED_PKT_SIZE);
-
-- wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
-- FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr) |
-- MTK_WED_TX_BM_DYN_THR_HI);
-+ if (dev->hw->version < 3)
-+ wed_w32(dev, MTK_WED_TX_BM_DYN_THR,
-+ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr_lo) |
-+ FIELD_PREP(MTK_WED_TX_BM_DYN_THR_LO, thr_hi));
-+ else {
-+ /* change to new bm */
-+ wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, dev->tx_buf_ring.pkt_nums |
-+ MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
-+ wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_LEGACY_EN);
-+ }
-
-- if (dev->ver > MTK_WED_V1) {
-+ if (dev->hw->version != 1) {
- wed_w32(dev, MTK_WED_TX_TKID_CTRL,
- MTK_WED_TX_TKID_CTRL_PAUSE |
- FIELD_PREP(MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM,
-- dev->buf_ring.size / 128) |
-+ size / 128) |
- FIELD_PREP(MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM,
-- dev->buf_ring.size / 128));
-- wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
-- FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
-- MTK_WED_TX_TKID_DYN_THR_HI);
-+ size / 128));
-+
-+ /* return SKBID + SDP back to bm */
-+ if (dev->ver == 3)
-+ wed_set(dev, MTK_WED_TX_TKID_CTRL,
-+ MTK_WED_TX_TKID_CTRL_FREE_FORMAT);
-+ else
-+ wed_w32(dev, MTK_WED_TX_TKID_DYN_THR,
-+ FIELD_PREP(MTK_WED_TX_TKID_DYN_THR_LO, 0) |
-+ MTK_WED_TX_TKID_DYN_THR_HI);
- }
-- mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
-+ wed_w32(dev, MTK_WED_TX_BM_TKID,
-+ FIELD_PREP(MTK_WED_TX_BM_TKID_START,
-+ dev->wlan.token_start) |
-+ FIELD_PREP(MTK_WED_TX_BM_TKID_END,
-+ dev->wlan.token_start + dev->wlan.nbuf - 1));
-
-+ wed_w32(dev, MTK_WED_TX_BM_INIT_PTR, dev->tx_buf_ring.pkt_nums |
-+ MTK_WED_TX_BM_INIT_SW_TAIL_IDX);
- wed_clr(dev, MTK_WED_TX_BM_CTRL, MTK_WED_TX_BM_CTRL_PAUSE);
-- if (dev->ver > MTK_WED_V1)
-+ if (dev->hw->version != 1)
- wed_clr(dev, MTK_WED_TX_TKID_CTRL, MTK_WED_TX_TKID_CTRL_PAUSE);
- }
-
-@@ -977,7 +1408,26 @@ mtk_wed_rx_hw_init(struct mtk_wed_device *dev)
-
- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
-
-+ /* reset prefetch index of ring */
-+ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
-+ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX,
-+ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+
-+ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
-+ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX,
-+ MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR);
-+
-+ /* reset prefetch FIFO of ring */
-+ wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG,
-+ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR |
-+ MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR);
-+ wed_w32(dev, MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG, 0);
-+
- mtk_wed_rx_bm_hw_init(dev);
-+ if (dev->wlan.hwrro)
-+ mtk_wed_hwrro_init(dev);
- mtk_wed_rro_hw_init(dev);
- mtk_wed_route_qm_hw_init(dev);
- }
-@@ -991,7 +1441,7 @@ mtk_wed_hw_init(struct mtk_wed_device *dev)
- dev->init_done = true;
- mtk_wed_set_ext_int(dev, false);
- mtk_wed_tx_hw_init(dev);
-- if (dev->ver > MTK_WED_V1)
-+ if (mtk_wed_get_rx_capa(dev))
- mtk_wed_rx_hw_init(dev);
- }
-
-@@ -1015,26 +1465,6 @@ mtk_wed_ring_reset(struct mtk_wdma_desc *desc, int size, int scale, bool tx)
- }
- }
-
--static u32
--mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
--{
-- if (wed_r32(dev, reg) & mask)
-- return true;
--
-- return false;
--}
--
--static int
--mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
--{
-- int sleep = 1000;
-- int timeout = 100 * sleep;
-- u32 val;
--
-- return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
-- timeout, false, dev, reg, mask);
--}
--
- static void
- mtk_wed_rx_reset(struct mtk_wed_device *dev)
- {
-@@ -1133,7 +1563,7 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- mtk_wed_ring_reset(desc, MTK_WED_RX_RING_SIZE, 1, false);
- }
-
-- mtk_wed_free_rx_bm(dev);
-+ mtk_wed_free_rx_buffer(dev);
- }
-
-
-@@ -1271,12 +1701,15 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev,
- int idx, int size, bool reset)
- {
- struct mtk_wed_ring *wdma = &dev->tx_wdma[idx];
-+ int scale = dev->hw->version > 1 ? 2 : 1;
-
- if(!reset)
- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-- dev->ver, true))
-+ scale, true))
- return -ENOMEM;
-
-+ wdma->flags |= MTK_WED_RING_CONFIGURED;
-+
- wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
- wdma->desc_phys);
- wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1296,12 +1729,33 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
- int idx, int size, bool reset)
- {
- struct mtk_wed_ring *wdma = &dev->rx_wdma[idx];
-+ int scale = dev->hw->version > 1 ? 2 : 1;
-
- if (!reset)
- if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
-- dev->ver, true))
-+ scale, true))
- return -ENOMEM;
-
-+ if (dev->hw->version == 3) {
-+ struct mtk_wdma_desc *desc = wdma->desc;
-+ int i;
-+
-+ for (i = 0; i < MTK_WED_WDMA_RING_SIZE; i++) {
-+ desc->buf0 = 0;
-+ desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
-+ desc->buf1 = 0;
-+ desc->info = MTK_WDMA_TXD0_DESC_INFO_DMA_DONE;
-+ desc++;
-+ desc->buf0 = 0;
-+ desc->ctrl = MTK_WDMA_DESC_CTRL_DMA_DONE;
-+ desc->buf1 = 0;
-+ desc->info = MTK_WDMA_TXD1_DESC_INFO_DMA_DONE;
-+ desc++;
-+ }
-+ }
-+
-+ wdma->flags |= MTK_WED_RING_CONFIGURED;
-+
- wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_BASE,
- wdma->desc_phys);
- wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_COUNT,
-@@ -1312,7 +1766,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev,
- MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
- if (reset)
- mtk_wed_ring_reset(wdma->desc, MTK_WED_WDMA_RING_SIZE,
-- dev->ver, true);
-+ scale, true);
- if (idx == 0) {
- wed_w32(dev, MTK_WED_WDMA_RING_TX
- + MTK_WED_RING_OFS_BASE, wdma->desc_phys);
-@@ -1395,7 +1849,7 @@ mtk_wed_send_msg(struct mtk_wed_device *dev, int cmd_id, void *data, int len)
- {
- struct mtk_wed_wo *wo = dev->hw->wed_wo;
-
-- if (dev->ver == MTK_WED_V1)
-+ if (!mtk_wed_get_rx_capa(dev))
- return 0;
-
- return mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, cmd_id, data, len, true);
-@@ -1420,24 +1874,106 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
- }
- }
-
-+static void
-+mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
-+{
-+ int idx, ret;
-+
-+ wed_w32(dev, MTK_WED_WPDMA_INT_MASK, irq_mask);
-+ wed_w32(dev, MTK_WED_INT_MASK, irq_mask);
-+
-+ if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
-+ return;
-+
-+ wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_RX,
-+ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG,
-+ dev->wlan.rro_rx_tbit[0]) |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG,
-+ dev->wlan.rro_rx_tbit[1]));
-+
-+ wed_w32(dev, MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG,
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN |
-+ MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG,
-+ dev->wlan.rx_pg_tbit[0]) |
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG,
-+ dev->wlan.rx_pg_tbit[1])|
-+ FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG,
-+ dev->wlan.rx_pg_tbit[2]));
-+
-+ /*
-+ * RRO_MSDU_PG_RING2_CFG1_FLD_DRV_EN should be enabled after
-+ * WM FWDL completed, otherwise RRO_MSDU_PG ring may broken
-+ */
-+ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+
-+ for (idx = 0; idx < MTK_WED_RX_QUEUES; idx++) {
-+ struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
-+
-+ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+ continue;
-+
-+ ret = mtk_wed_check_wfdma_rx_fill(dev, ring);
-+ if (!ret)
-+ dev_err(dev->hw->dev, "mtk_wed%d: rx_rro_ring(%d) init failed!\n",
-+ dev->hw->index, idx);
-+ }
-+
-+ for (idx = 0; idx < MTK_WED_RX_PAGE_QUEUES; idx++){
-+ struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
-+ if(!(ring->flags & MTK_WED_RING_CONFIGURED))
-+ continue;
-+
-+ ret = mtk_wed_check_wfdma_rx_fill(dev, ring);
-+ if (!ret)
-+ dev_err(dev->hw->dev, "mtk_wed%d: rx_page_ring(%d) init failed!\n",
-+ dev->hw->index, idx);
-+ }
-+}
-+
- static void
- mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- {
- int i, ret;
-
-- if (dev->ver > MTK_WED_V1)
-- ret = mtk_wed_rx_bm_alloc(dev);
-+ if (mtk_wed_get_rx_capa(dev)) {
-+ ret = mtk_wed_rx_buffer_alloc(dev);
-+ if (ret)
-+ return;
-+
-+ if (dev->wlan.hwrro)
-+ mtk_wed_rx_page_buffer_alloc(dev);
-+ }
-
- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
- if (!dev->tx_wdma[i].desc)
- mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
-
-+ for (i = 0; i < ARRAY_SIZE(dev->rx_page_ring); i++) {
-+ u32 count = MTK_WED_RRO_MSDU_PG_CTRL0(i) +
-+ MTK_WED_RING_OFS_COUNT;
-+
-+ if (!wed_r32(dev, count))
-+ wed_w32(dev, count, 1);
-+ }
-+
- mtk_wed_hw_init(dev);
-
- mtk_wed_set_int(dev, irq_mask);
- mtk_wed_set_ext_int(dev, true);
-
-- if (dev->ver == MTK_WED_V1) {
-+ if (dev->hw->version == 1) {
- u32 val;
-
- val = dev->wlan.wpdma_phys |
-@@ -1448,33 +1984,52 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
- val |= BIT(1);
- val |= BIT(0);
- regmap_write(dev->hw->mirror, dev->hw->index * 4, val);
-- } else {
-+ } else if (mtk_wed_get_rx_capa(dev)) {
- /* driver set mid ready and only once */
- wed_w32(dev, MTK_WED_EXT_INT_MASK1,
- MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
- wed_w32(dev, MTK_WED_EXT_INT_MASK2,
- MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
-+ if (dev->hw->version == 3)
-+ wed_w32(dev, MTK_WED_EXT_INT_MASK3,
-+ MTK_WED_EXT_INT_STATUS_WPDMA_MID_RDY);
-
- wed_r32(dev, MTK_WED_EXT_INT_MASK1);
- wed_r32(dev, MTK_WED_EXT_INT_MASK2);
-+ if (dev->hw->version == 3)
-+ wed_r32(dev, MTK_WED_EXT_INT_MASK3);
-
- ret = mtk_wed_rro_cfg(dev);
- if (ret)
- return;
- }
-- mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
-+
-+ if (dev->hw->version == 2)
-+ mtk_wed_set_512_support(dev, dev->wlan.wcid_512);
-+ else if (dev->hw->version == 3)
-+ mtk_wed_pao_init(dev);
-
- mtk_wed_dma_enable(dev);
- dev->running = true;
- }
-
-+static int
-+mtk_wed_get_pci_base(struct mtk_wed_device *dev)
-+{
-+ if (dev->hw->index == 0)
-+ return MTK_WED_PCIE_BASE0;
-+ else if (dev->hw->index == 1)
-+ return MTK_WED_PCIE_BASE1;
-+ else
-+ return MTK_WED_PCIE_BASE2;
-+}
-+
- static int
- mtk_wed_attach(struct mtk_wed_device *dev)
- __releases(RCU)
- {
- struct mtk_wed_hw *hw;
- struct device *device;
-- u16 ver;
- int ret = 0;
-
- RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
-@@ -1494,34 +2049,30 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- goto out;
- }
-
-- device = dev->wlan.bus_type == MTK_WED_BUS_PCIE
-- ? &dev->wlan.pci_dev->dev
-- : &dev->wlan.platform_dev->dev;
-+ device = dev->wlan.bus_type == MTK_WED_BUS_PCIE ?
-+ &dev->wlan.pci_dev->dev
-+ : &dev->wlan.platform_dev->dev;
- dev_info(device, "attaching wed device %d version %d\n",
-- hw->index, hw->ver);
-+ hw->index, hw->version);
-
- dev->hw = hw;
- dev->dev = hw->dev;
- dev->irq = hw->irq;
- dev->wdma_idx = hw->index;
-+ dev->ver = hw->version;
-+
-+ if (dev->hw->version == 3)
-+ dev->hw->pci_base = mtk_wed_get_pci_base(dev);
-
- if (hw->eth->dma_dev == hw->eth->dev &&
- of_dma_is_coherent(hw->eth->dev->of_node))
- mtk_eth_set_dma_device(hw->eth, hw->dev);
-
-- dev->ver = FIELD_GET(MTK_WED_REV_ID_MAJOR,
-- wed_r32(dev, MTK_WED_REV_ID));
-- if (dev->ver > MTK_WED_V1)
-- ver = FIELD_GET(MTK_WED_REV_ID_MINOR,
-- wed_r32(dev, MTK_WED_REV_ID));
--
-- dev->rev_id = ((dev->ver << 28) | ver << 16);
--
-- ret = mtk_wed_buffer_alloc(dev);
-+ ret = mtk_wed_tx_buffer_alloc(dev);
- if (ret)
- goto error;
-
-- if (dev->ver > MTK_WED_V1) {
-+ if (mtk_wed_get_rx_capa(dev)) {
- ret = mtk_wed_rro_alloc(dev);
- if (ret)
- goto error;
-@@ -1533,15 +2084,20 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- init_completion(&dev->wlan_reset_done);
- atomic_set(&dev->fe_reset, 0);
-
-- if (dev->ver == MTK_WED_V1)
-+ if (dev->hw->version != 1)
-+ dev->rev_id = wed_r32(dev, MTK_WED_REV_ID);
-+ else
- regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
- BIT(hw->index), 0);
-- else
-+
-+ if (mtk_wed_get_rx_capa(dev))
- ret = mtk_wed_wo_init(hw);
-
- error:
-- if (ret)
-+ if (ret) {
-+ pr_info("%s: detach wed\n", __func__);
- mtk_wed_detach(dev);
-+ }
- out:
- mutex_unlock(&hw_lock);
-
-@@ -1576,8 +2132,26 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx,
- if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE, reset))
- return -ENOMEM;
-
-+ if (dev->hw->version == 3 && idx == 1) {
-+ /* reset prefetch index */
-+ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+ /* reset prefetch FIFO */
-+ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
-+ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
-+ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
-+ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
-+ }
-+
- ring->reg_base = MTK_WED_RING_TX(idx);
- ring->wpdma = regs;
-+ ring->flags |= MTK_WED_RING_CONFIGURED;
-
- /* WED -> WPDMA */
- wpdma_tx_w32(dev, idx, MTK_WED_RING_OFS_BASE, ring->desc_phys);
-@@ -1599,7 +2173,7 @@ mtk_wed_txfree_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
- struct mtk_wed_ring *ring = &dev->txfree_ring;
- int i, idx = 1;
-
-- if(dev->ver > MTK_WED_V1)
-+ if(dev->hw->version > 1)
- idx = 0;
-
- /*
-@@ -1638,6 +2212,7 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
-
- ring->reg_base = MTK_WED_RING_RX_DATA(idx);
- ring->wpdma = regs;
-+ ring->flags |= MTK_WED_RING_CONFIGURED;
- dev->hw->ring_num = idx + 1;
-
- /* WPDMA -> WED */
-@@ -1652,6 +2227,129 @@ mtk_wed_rx_ring_setup(struct mtk_wed_device *dev,
- return 0;
- }
-
-+static int
-+mtk_wed_rro_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+{
-+ struct mtk_wed_ring *ring = &dev->rx_rro_ring[idx];
-+
-+ ring->wpdma = regs;
-+
-+ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_BASE,
-+ readl(regs));
-+ wed_w32(dev, MTK_WED_RRO_RX_D_RX(idx) + MTK_WED_RING_OFS_COUNT,
-+ readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+ ring->flags |= MTK_WED_RING_CONFIGURED;
-+
-+ return 0;
-+}
-+
-+static int
-+mtk_wed_msdu_pg_rx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
-+{
-+ struct mtk_wed_ring *ring = &dev->rx_page_ring[idx];
-+
-+ ring->wpdma = regs;
-+
-+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_BASE,
-+ readl(regs));
-+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_CTRL0(idx) + MTK_WED_RING_OFS_COUNT,
-+ readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+ ring->flags |= MTK_WED_RING_CONFIGURED;
-+
-+ return 0;
-+}
-+
-+static int
-+mtk_wed_ind_rx_ring_setup(struct mtk_wed_device *dev, void __iomem *regs)
-+{
-+ struct mtk_wed_ring *ring = &dev->ind_cmd_ring;
-+ u32 val = readl(regs + MTK_WED_RING_OFS_COUNT);
-+ int i = 0, cnt = 0;
-+
-+ ring->wpdma = regs;
-+
-+ if (readl(regs) & 0xf)
-+ pr_info("%s(): address is not 16-byte alignment\n", __func__);
-+
-+ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_BASE,
-+ readl(regs) & 0xfffffff0);
-+
-+ wed_w32(dev, MTK_WED_IND_CMD_RX_CTRL1 + MTK_WED_RING_OFS_COUNT,
-+ readl(regs + MTK_WED_RING_OFS_COUNT));
-+
-+ /* ack sn cr */
-+ wed_w32(dev, MTK_WED_RRO_CFG0, dev->wlan.phy_base +
-+ dev->wlan.ind_cmd.ack_sn_addr);
-+ wed_w32(dev, MTK_WED_RRO_CFG1,
-+ FIELD_PREP(MTK_WED_RRO_CFG1_MAX_WIN_SZ,
-+ dev->wlan.ind_cmd.win_size) |
-+ FIELD_PREP(MTK_WED_RRO_CFG1_PARTICL_SE_ID,
-+ dev->wlan.ind_cmd.particular_sid));
-+
-+ /* particular session addr element */
-+ wed_w32(dev, MTK_WED_ADDR_ELEM_CFG0, dev->wlan.ind_cmd.particular_se_phys);
-+
-+ for (i = 0; i < dev->wlan.ind_cmd.se_group_nums; i++) {
-+ wed_w32(dev, MTK_WED_RADDR_ELEM_TBL_WDATA,
-+ dev->wlan.ind_cmd.addr_elem_phys[i] >> 4);
-+ wed_w32(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
-+ MTK_WED_ADDR_ELEM_TBL_WR | (i & 0x7f));
-+
-+ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
-+ while (!(val & MTK_WED_ADDR_ELEM_TBL_WR_RDY) &&
-+ cnt < 100) {
-+ val = wed_r32(dev, MTK_WED_ADDR_ELEM_TBL_CFG);
-+ cnt++;
-+ }
-+ if (cnt >= 100) {
-+ dev_err(dev->hw->dev, "mtk_wed%d: write ba session base failed!\n",
-+ dev->hw->index);
-+ }
-+ /*if (mtk_wed_poll_busy(dev, MTK_WED_ADDR_ELEM_TBL_CFG,
-+ MTK_WED_ADDR_ELEM_TBL_WR_RDY)) {
-+ dev_err(dev->hw->dev, "mtk_wed%d: write ba session base failed!\n",
-+ dev->hw->index);
-+ return -1;
-+ }*/
-+ }
-+
-+ /* pn check init */
-+ for (i = 0; i < dev->wlan.ind_cmd.particular_sid; i++) {
-+ wed_w32(dev, MTK_WED_PN_CHECK_WDATA_M,
-+ MTK_WED_PN_CHECK_IS_FIRST);
-+
-+ wed_w32(dev, MTK_WED_PN_CHECK_CFG, MTK_WED_PN_CHECK_WR |
-+ FIELD_PREP(MTK_WED_PN_CHECK_SE_ID, i));
-+
-+ cnt = 0;
-+ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
-+ while (!(val & MTK_WED_PN_CHECK_WR_RDY) &&
-+ cnt < 100) {
-+ val = wed_r32(dev, MTK_WED_PN_CHECK_CFG);
-+ cnt++;
-+ }
-+ if (cnt >= 100) {
-+ dev_err(dev->hw->dev, "mtk_wed%d: session(%d) init failed!\n",
-+ dev->hw->index, i);
-+ }
-+ /*if (mtk_wed_poll_busy(dev, MTK_WED_PN_CHECK_CFG,
-+ MTK_WED_PN_CHECK_WR_RDY)) {
-+ dev_err(dev->hw->dev, "mtk_wed%d: session(%d) init failed!\n",
-+ dev->hw->index, i);
-+ //return -1;
-+ }*/
-+ }
-+
-+ wed_w32(dev, MTK_WED_RX_IND_CMD_CNT0, MTK_WED_RX_IND_CMD_DBG_CNT_EN);
-+
-+ wed_set(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
-+
-+ return 0;
-+}
-+
-+
- static u32
- mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
- {
-@@ -1659,9 +2357,13 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
-
- val = wed_r32(dev, MTK_WED_EXT_INT_STATUS);
- wed_w32(dev, MTK_WED_EXT_INT_STATUS, val);
-- val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
-- if (!dev->hw->num_flows)
-- val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
-+ if (dev->hw->version == 3) {
-+ val &= MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT;
-+ } else {
-+ val &= MTK_WED_EXT_INT_STATUS_ERROR_MASK;
-+ if (!dev->hw->num_flows)
-+ val &= ~MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD;
-+ }
- if (val && net_ratelimit())
- pr_err("mtk_wed%d: error status=%08x\n", dev->hw->index, val);
-
-@@ -1754,6 +2456,9 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- .tx_ring_setup = mtk_wed_tx_ring_setup,
- .txfree_ring_setup = mtk_wed_txfree_ring_setup,
- .rx_ring_setup = mtk_wed_rx_ring_setup,
-+ .rro_rx_ring_setup = mtk_wed_rro_rx_ring_setup,
-+ .msdu_pg_rx_ring_setup = mtk_wed_msdu_pg_rx_ring_setup,
-+ .ind_rx_ring_setup = mtk_wed_ind_rx_ring_setup,
- .msg_update = mtk_wed_send_msg,
- .start = mtk_wed_start,
- .stop = mtk_wed_stop,
-@@ -1765,6 +2470,7 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- .detach = mtk_wed_detach,
- .setup_tc = mtk_wed_eth_setup_tc,
- .ppe_check = mtk_wed_ppe_check,
-+ .start_hwrro = mtk_wed_start_hwrro,
- };
- struct device_node *eth_np = eth->dev->of_node;
- struct platform_device *pdev;
-@@ -1804,9 +2510,10 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- hw->wdma_phy = wdma_phy;
- hw->index = index;
- hw->irq = irq;
-- hw->ver = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
-+ hw->version = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) ?
-+ 3 : MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1;
-
-- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
-+ if (hw->version == 1) {
- hw->mirror = syscon_regmap_lookup_by_phandle(eth_np,
- "mediatek,pcie-mirror");
- hw->hifsys = syscon_regmap_lookup_by_phandle(eth_np,
-@@ -1821,7 +2528,6 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
- regmap_write(hw->mirror, 0, 0);
- regmap_write(hw->mirror, 4, 0);
- }
-- hw->ver = MTK_WED_V1;
- }
-
- mtk_wed_hw_add_debugfs(hw);
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.h b/drivers/net/ethernet/mediatek/mtk_wed.h
-index 490873c..fcf7bd0 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.h
-@@ -10,10 +10,13 @@
- #include <linux/netdevice.h>
- #define MTK_PCIE_BASE(n) (0x1a143000 + (n) * 0x2000)
-
--#define MTK_WED_PKT_SIZE 1900
-+#define MTK_WED_PKT_SIZE 1920//1900
- #define MTK_WED_BUF_SIZE 2048
-+#define MTK_WED_PAGE_BUF_SIZE 128
- #define MTK_WED_BUF_PER_PAGE (PAGE_SIZE / 2048)
-+#define MTK_WED_RX_PAGE_BUF_PER_PAGE (PAGE_SIZE / 128)
- #define MTK_WED_RX_RING_SIZE 1536
-+#define MTK_WED_RX_PG_BM_CNT 8192
-
- #define MTK_WED_TX_RING_SIZE 2048
- #define MTK_WED_WDMA_RING_SIZE 512
-@@ -27,6 +30,9 @@
- #define MTK_WED_RRO_QUE_CNT 8192
- #define MTK_WED_MIOD_ENTRY_CNT 128
-
-+#define MTK_WED_TX_BM_DMA_SIZE 65536
-+#define MTK_WED_TX_BM_PKT_CNT 32768
-+
- #define MODULE_ID_WO 1
-
- struct mtk_eth;
-@@ -43,6 +49,8 @@ struct mtk_wed_hw {
- struct dentry *debugfs_dir;
- struct mtk_wed_device *wed_dev;
- struct mtk_wed_wo *wed_wo;
-+ struct mtk_wed_pao *wed_pao;
-+ u32 pci_base;
- u32 debugfs_reg;
- u32 num_flows;
- u32 wdma_phy;
-@@ -50,7 +58,8 @@ struct mtk_wed_hw {
- int ring_num;
- int irq;
- int index;
-- u32 ver;
-+ int token_id;
-+ u32 version;
- };
-
- struct mtk_wdma_info {
-@@ -58,6 +67,18 @@ struct mtk_wdma_info {
- u8 queue;
- u16 wcid;
- u8 bss;
-+ u32 usr_info;
-+ u8 tid;
-+ u8 is_fixedrate;
-+ u8 is_prior;
-+ u8 is_sp;
-+ u8 hf;
-+ u8 amsdu_en;
-+};
-+
-+struct mtk_wed_pao {
-+ char *hif_txd[32];
-+ dma_addr_t hif_txd_phys[32];
- };
-
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-index 4a9e684..51e3d7c 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
-@@ -11,9 +11,11 @@ struct reg_dump {
- u16 offset;
- u8 type;
- u8 base;
-+ u32 mask;
- };
-
- enum {
-+ DUMP_TYPE_END,
- DUMP_TYPE_STRING,
- DUMP_TYPE_WED,
- DUMP_TYPE_WDMA,
-@@ -23,8 +25,11 @@ enum {
- DUMP_TYPE_WED_RRO,
- };
-
-+#define DUMP_END() { .type = DUMP_TYPE_END }
- #define DUMP_STR(_str) { _str, 0, DUMP_TYPE_STRING }
- #define DUMP_REG(_reg, ...) { #_reg, MTK_##_reg, __VA_ARGS__ }
-+#define DUMP_REG_MASK(_reg, _mask) { #_mask, MTK_##_reg, DUMP_TYPE_WED, 0, MTK_##_mask }
-+
- #define DUMP_RING(_prefix, _base, ...) \
- { _prefix " BASE", _base, __VA_ARGS__ }, \
- { _prefix " CNT", _base + 0x4, __VA_ARGS__ }, \
-@@ -32,6 +37,7 @@ enum {
- { _prefix " DIDX", _base + 0xc, __VA_ARGS__ }
-
- #define DUMP_WED(_reg) DUMP_REG(_reg, DUMP_TYPE_WED)
-+#define DUMP_WED_MASK(_reg, _mask) DUMP_REG_MASK(_reg, _mask)
- #define DUMP_WED_RING(_base) DUMP_RING(#_base, MTK_##_base, DUMP_TYPE_WED)
-
- #define DUMP_WDMA(_reg) DUMP_REG(_reg, DUMP_TYPE_WDMA)
-@@ -52,36 +58,49 @@ print_reg_val(struct seq_file *s, const char *name, u32 val)
-
- static void
- dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
-- const struct reg_dump *regs, int n_regs)
-+ const struct reg_dump **regs)
- {
-- const struct reg_dump *cur;
-+ const struct reg_dump **cur_o = regs, *cur;
-+ bool newline = false;
- u32 val;
-
-- for (cur = regs; cur < ®s[n_regs]; cur++) {
-- switch (cur->type) {
-- case DUMP_TYPE_STRING:
-- seq_printf(s, "%s======== %s:\n",
-- cur > regs ? "\n" : "",
-- cur->name);
-- continue;
-- case DUMP_TYPE_WED:
-- case DUMP_TYPE_WED_RRO:
-- val = wed_r32(dev, cur->offset);
-- break;
-- case DUMP_TYPE_WDMA:
-- val = wdma_r32(dev, cur->offset);
-- break;
-- case DUMP_TYPE_WPDMA_TX:
-- val = wpdma_tx_r32(dev, cur->base, cur->offset);
-- break;
-- case DUMP_TYPE_WPDMA_TXFREE:
-- val = wpdma_txfree_r32(dev, cur->offset);
-- break;
-- case DUMP_TYPE_WPDMA_RX:
-- val = wpdma_rx_r32(dev, cur->base, cur->offset);
-- break;
-+ while (*cur_o) {
-+ cur = *cur_o;
-+
-+ while (cur->type != DUMP_TYPE_END) {
-+ switch (cur->type) {
-+ case DUMP_TYPE_STRING:
-+ seq_printf(s, "%s======== %s:\n",
-+ newline ? "\n" : "",
-+ cur->name);
-+ newline = true;
-+ cur++;
-+ continue;
-+ case DUMP_TYPE_WED:
-+ case DUMP_TYPE_WED_RRO:
-+ val = wed_r32(dev, cur->offset);
-+ break;
-+ case DUMP_TYPE_WDMA:
-+ val = wdma_r32(dev, cur->offset);
-+ break;
-+ case DUMP_TYPE_WPDMA_TX:
-+ val = wpdma_tx_r32(dev, cur->base, cur->offset);
-+ break;
-+ case DUMP_TYPE_WPDMA_TXFREE:
-+ val = wpdma_txfree_r32(dev, cur->offset);
-+ break;
-+ case DUMP_TYPE_WPDMA_RX:
-+ val = wpdma_rx_r32(dev, cur->base, cur->offset);
-+ break;
-+ }
-+
-+ if (cur->mask)
-+ val = (cur->mask & val) >> (ffs(cur->mask) - 1);
-+
-+ print_reg_val(s, cur->name, val);
-+ cur++;
- }
-- print_reg_val(s, cur->name, val);
-+ cur_o++;
- }
- }
-
-@@ -89,7 +108,7 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev,
- static int
- wed_txinfo_show(struct seq_file *s, void *data)
- {
-- static const struct reg_dump regs[] = {
-+ static const struct reg_dump regs_common[] = {
- DUMP_STR("WED TX"),
- DUMP_WED(WED_TX_MIB(0)),
- DUMP_WED_RING(WED_RING_TX(0)),
-@@ -128,16 +147,32 @@ wed_txinfo_show(struct seq_file *s, void *data)
- DUMP_WDMA_RING(WDMA_RING_RX(0)),
- DUMP_WDMA_RING(WDMA_RING_RX(1)),
-
-- DUMP_STR("TX FREE"),
-+ DUMP_STR("WED TX FREE"),
- DUMP_WED(WED_RX_MIB(0)),
-+ DUMP_WED_RING(WED_RING_RX(0)),
-+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)),
-+
-+ DUMP_WED(WED_RX_MIB(1)),
-+ DUMP_WED_RING(WED_RING_RX(1)),
-+ DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)),
-+ DUMP_STR("WED_WPDMA TX FREE"),
-+ DUMP_WED_RING(WED_WPDMA_RING_RX(0)),
-+ DUMP_WED_RING(WED_WPDMA_RING_RX(1)),
-+ DUMP_END(),
-+ };
-+
-+ static const struct reg_dump *regs[] = {
-+ ®s_common[0],
-+ NULL,
- };
-+
- struct mtk_wed_hw *hw = s->private;
- struct mtk_wed_device *dev = hw->wed_dev;
-
- if (!dev)
- return 0;
-
-- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
-+ dump_wed_regs(s, dev, regs);
-
- return 0;
- }
-@@ -146,7 +181,7 @@ DEFINE_SHOW_ATTRIBUTE(wed_txinfo);
- static int
- wed_rxinfo_show(struct seq_file *s, void *data)
- {
-- static const struct reg_dump regs[] = {
-+ static const struct reg_dump regs_common[] = {
- DUMP_STR("WPDMA RX"),
- DUMP_WPDMA_RX_RING(0),
- DUMP_WPDMA_RX_RING(1),
-@@ -164,7 +199,7 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- DUMP_WED_RING(WED_RING_RX_DATA(0)),
- DUMP_WED_RING(WED_RING_RX_DATA(1)),
-
-- DUMP_STR("WED RRO"),
-+ DUMP_STR("WED WO RRO"),
- DUMP_WED_RRO_RING(WED_RROQM_MIOD_CTRL0),
- DUMP_WED(WED_RROQM_MID_MIB),
- DUMP_WED(WED_RROQM_MOD_MIB),
-@@ -175,16 +210,6 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- DUMP_WED(WED_RROQM_FDBK_ANC_MIB),
- DUMP_WED(WED_RROQM_FDBK_ANC2H_MIB),
-
-- DUMP_STR("WED Route QM"),
-- DUMP_WED(WED_RTQM_R2H_MIB(0)),
-- DUMP_WED(WED_RTQM_R2Q_MIB(0)),
-- DUMP_WED(WED_RTQM_Q2H_MIB(0)),
-- DUMP_WED(WED_RTQM_R2H_MIB(1)),
-- DUMP_WED(WED_RTQM_R2Q_MIB(1)),
-- DUMP_WED(WED_RTQM_Q2H_MIB(1)),
-- DUMP_WED(WED_RTQM_Q2N_MIB),
-- DUMP_WED(WED_RTQM_Q2B_MIB),
-- DUMP_WED(WED_RTQM_PFDBK_MIB),
-
- DUMP_STR("WED WDMA TX"),
- DUMP_WED(WED_WDMA_TX_MIB),
-@@ -205,15 +230,99 @@ wed_rxinfo_show(struct seq_file *s, void *data)
- DUMP_WED(WED_RX_BM_INTF2),
- DUMP_WED(WED_RX_BM_INTF),
- DUMP_WED(WED_RX_BM_ERR_STS),
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump regs_v2[] = {
-+ DUMP_STR("WED Route QM"),
-+ DUMP_WED(WED_RTQM_R2H_MIB(0)),
-+ DUMP_WED(WED_RTQM_R2Q_MIB(0)),
-+ DUMP_WED(WED_RTQM_Q2H_MIB(0)),
-+ DUMP_WED(WED_RTQM_R2H_MIB(1)),
-+ DUMP_WED(WED_RTQM_R2Q_MIB(1)),
-+ DUMP_WED(WED_RTQM_Q2H_MIB(1)),
-+ DUMP_WED(WED_RTQM_Q2N_MIB),
-+ DUMP_WED(WED_RTQM_Q2B_MIB),
-+ DUMP_WED(WED_RTQM_PFDBK_MIB),
-+
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump regs_v3[] = {
-+ DUMP_STR("WED RX RRO DATA"),
-+ DUMP_WED_RING(WED_RRO_RX_D_RX(0)),
-+ DUMP_WED_RING(WED_RRO_RX_D_RX(1)),
-+
-+ DUMP_STR("WED RX MSDU PAGE"),
-+ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(0)),
-+ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(1)),
-+ DUMP_WED_RING(WED_RRO_MSDU_PG_CTRL0(2)),
-+
-+ DUMP_STR("WED RX IND CMD"),
-+ DUMP_WED(WED_IND_CMD_RX_CTRL1),
-+ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL2, WED_IND_CMD_MAX_CNT),
-+ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_PROC_IDX),
-+ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_DMA_IDX),
-+ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0, WED_IND_CMD_MAGIC_CNT),
-+ DUMP_WED_MASK(RRO_IND_CMD_SIGNATURE, RRO_IND_CMD_MAGIC_CNT),
-+ DUMP_WED_MASK(WED_IND_CMD_RX_CTRL0,
-+ WED_IND_CMD_PREFETCH_FREE_CNT),
-+ DUMP_WED_MASK(WED_RRO_CFG1, WED_RRO_CFG1_PARTICL_SE_ID),
-+
-+ DUMP_STR("WED ADDR ELEM"),
-+ DUMP_WED(WED_ADDR_ELEM_CFG0),
-+ DUMP_WED_MASK(WED_ADDR_ELEM_CFG1,
-+ WED_ADDR_ELEM_PREFETCH_FREE_CNT),
-+
-+ DUMP_STR("WED Route QM"),
-+ DUMP_WED(WED_RTQM_ENQ_I2Q_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_ENQ_I2N_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_ENQ_I2Q_PKT_CNT),
-+ DUMP_WED(WED_RTQM_ENQ_I2N_PKT_CNT),
-+ DUMP_WED(WED_RTQM_ENQ_USED_ENTRY_CNT),
-+ DUMP_WED(WED_RTQM_ENQ_ERR_CNT),
-+
-+ DUMP_WED(WED_RTQM_DEQ_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_DEQ_Q2I_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_DEQ_PKT_CNT),
-+ DUMP_WED(WED_RTQM_DEQ_Q2I_PKT_CNT),
-+ DUMP_WED(WED_RTQM_DEQ_USED_PFDBK_CNT),
-+ DUMP_WED(WED_RTQM_DEQ_ERR_CNT),
-+
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump *regs_new_v2[] = {
-+ ®s_common[0],
-+ ®s_v2[0],
-+ NULL,
-+ };
-+
-+ static const struct reg_dump *regs_new_v3[] = {
-+ ®s_common[0],
-+ ®s_v3[0],
-+ NULL,
- };
-
- struct mtk_wed_hw *hw = s->private;
- struct mtk_wed_device *dev = hw->wed_dev;
-+ const struct reg_dump **regs;
-
- if (!dev)
- return 0;
-
-- dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs));
-+ switch(dev->hw->version) {
-+ case 2:
-+ regs = regs_new_v2;
-+ break;
-+ case 3:
-+ regs = regs_new_v3;
-+ break;
-+ default:
-+ return 0;
-+ }
-+
-+ dump_wed_regs(s, dev, regs);
-
- return 0;
- }
-@@ -248,6 +357,383 @@ mtk_wed_reg_get(void *data, u64 *val)
- DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mtk_wed_reg_get, mtk_wed_reg_set,
- "0x%08llx\n");
-
-+static int
-+wed_token_txd_show(struct seq_file *s, void *data)
-+{
-+ struct mtk_wed_hw *hw = s->private;
-+ struct mtk_wed_device *dev = hw->wed_dev;
-+ struct dma_page_info *page_list = dev->tx_buf_ring.pages;
-+ int token = dev->wlan.token_start;
-+ u32 val = hw->token_id, size = 1;
-+ int page_idx = (val - token) / 2;
-+ int i;
-+
-+ if (val < token) {
-+ size = val;
-+ page_idx = 0;
-+ }
-+
-+ for (i = 0; i < size; i += MTK_WED_BUF_PER_PAGE) {
-+ void *page = page_list[page_idx++].addr;
-+ void *buf;
-+ int j;
-+
-+ if (!page)
-+ break;
-+
-+ buf = page_to_virt(page);
-+
-+ for (j = 0; j < MTK_WED_BUF_PER_PAGE; j++) {
-+ printk("[TXD]:token id = %d\n", token + 2 * (page_idx - 1) + j);
-+ print_hex_dump(KERN_ERR , "", DUMP_PREFIX_OFFSET, 16, 1, (u8 *)buf, 128, false);
-+ seq_printf(s, "\n");
-+
-+ buf += MTK_WED_BUF_SIZE;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+DEFINE_SHOW_ATTRIBUTE(wed_token_txd);
-+
-+static int
-+wed_pao_show(struct seq_file *s, void *data)
-+{
-+ static const struct reg_dump regs_common[] = {
-+ DUMP_STR("PAO AMDSU INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_FIFO_DMAD),
-+
-+ DUMP_STR("PAO AMDSU ENG0 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(0)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(0)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(0)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(0)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(0)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(0),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(0),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(0),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG1 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(1)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(1)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(1)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(1)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(1)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(1),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(1),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(1),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG2 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(2)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(2)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(2)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(2)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(2)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(2),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(2),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(2),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG3 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(3)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(3)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(3)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(3)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(3)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(3),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(3),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(3),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG4 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(4)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(4)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(4)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(4)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(4)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(4),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(4),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG5 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(5)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(5)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(5)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(5)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(5)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(5),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(5),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(5),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG6 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(6)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(6)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(6)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(6)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(6)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(6),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(6),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(6),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG7 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(7)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(7)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(7)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(7)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(7)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(7),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(7),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(7),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(7),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(4),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO AMDSU ENG8 INFO"),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_DMAD(8)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QFPL(8)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENI(8)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_QENO(8)),
-+ DUMP_WED(WED_PAO_MON_AMSDU_ENG_MERG(8)),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(8),
-+ WED_PAO_AMSDU_ENG_MAX_PL_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT8(8),
-+ WED_PAO_AMSDU_ENG_MAX_QGPP_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+ WED_PAO_AMSDU_ENG_CUR_ENTRY),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+ WED_PAO_AMSDU_ENG_MAX_BUF_MERGED),
-+ DUMP_WED_MASK(WED_PAO_MON_AMSDU_ENG_CNT9(8),
-+ WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED),
-+
-+ DUMP_STR("PAO QMEM INFO"),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(0), WED_PAO_QMEM_FQ_CNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(0), WED_PAO_QMEM_SP_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(1), WED_PAO_QMEM_TID0_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(1), WED_PAO_QMEM_TID1_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(2), WED_PAO_QMEM_TID2_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(2), WED_PAO_QMEM_TID3_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(3), WED_PAO_QMEM_TID4_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(3), WED_PAO_QMEM_TID5_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(4), WED_PAO_QMEM_TID6_QCNT),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_CNT(4), WED_PAO_QMEM_TID7_QCNT),
-+
-+
-+ DUMP_STR("PAO QMEM HEAD INFO"),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(0), WED_PAO_QMEM_FQ_HEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(0), WED_PAO_QMEM_SP_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(1), WED_PAO_QMEM_TID0_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(1), WED_PAO_QMEM_TID1_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(2), WED_PAO_QMEM_TID2_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(2), WED_PAO_QMEM_TID3_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(3), WED_PAO_QMEM_TID4_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(3), WED_PAO_QMEM_TID5_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(4), WED_PAO_QMEM_TID6_QHEAD),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(4), WED_PAO_QMEM_TID7_QHEAD),
-+
-+ DUMP_STR("PAO QMEM TAIL INFO"),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(5), WED_PAO_QMEM_FQ_TAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(5), WED_PAO_QMEM_SP_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(6), WED_PAO_QMEM_TID0_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(6), WED_PAO_QMEM_TID1_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(7), WED_PAO_QMEM_TID2_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(7), WED_PAO_QMEM_TID3_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(8), WED_PAO_QMEM_TID4_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(8), WED_PAO_QMEM_TID5_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(9), WED_PAO_QMEM_TID6_QTAIL),
-+ DUMP_WED_MASK(WED_PAO_MON_QMEM_PTR(9), WED_PAO_QMEM_TID7_QTAIL),
-+
-+ DUMP_STR("PAO HIFTXD MSDU INFO"),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(1)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(2)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(3)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(4)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(5)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(6)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(7)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(8)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(9)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(10)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(11)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(12)),
-+ DUMP_WED(WED_PAO_MON_HIFTXD_FETCH_MSDU(13)),
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump *regs[] = {
-+ ®s_common[0],
-+ NULL,
-+ };
-+ struct mtk_wed_hw *hw = s->private;
-+ struct mtk_wed_device *dev = hw->wed_dev;
-+
-+ if (!dev)
-+ return 0;
-+
-+ dump_wed_regs(s, dev, regs);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_pao);
-+
-+static int
-+wed_rtqm_show(struct seq_file *s, void *data)
-+{
-+ static const struct reg_dump regs_common[] = {
-+ DUMP_STR("WED Route QM IGRS0(N2H + Recycle)"),
-+ DUMP_WED(WED_RTQM_IGRS0_I2HW_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS0_I2H_DMAD_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS0_I2HW_PKT_CNT),
-+ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS0_I2H_PKT_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS0_FDROP_CNT),
-+
-+
-+ DUMP_STR("WED Route QM IGRS1(Legacy)"),
-+ DUMP_WED(WED_RTQM_IGRS1_I2HW_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS1_I2H_DMAD_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS1_I2HW_PKT_CNT),
-+ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS1_I2H_PKT_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS1_FDROP_CNT),
-+
-+ DUMP_STR("WED Route QM IGRS2(RRO3.0)"),
-+ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS2_I2H_DMAD_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS2_I2HW_PKT_CNT),
-+ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS2_I2H_PKT_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS2_FDROP_CNT),
-+
-+ DUMP_STR("WED Route QM IGRS3(DEBUG)"),
-+ DUMP_WED(WED_RTQM_IGRS2_I2HW_DMAD_CNT),
-+ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS3_I2H_DMAD_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS3_I2HW_PKT_CNT),
-+ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(0)),
-+ DUMP_WED(WED_RTQM_IGRS3_I2H_PKT_CNT(1)),
-+ DUMP_WED(WED_RTQM_IGRS3_FDROP_CNT),
-+
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump *regs[] = {
-+ ®s_common[0],
-+ NULL,
-+ };
-+ struct mtk_wed_hw *hw = s->private;
-+ struct mtk_wed_device *dev = hw->wed_dev;
-+
-+ if (!dev)
-+ return 0;
-+
-+ dump_wed_regs(s, dev, regs);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_rtqm);
-+
-+
-+static int
-+wed_rro_show(struct seq_file *s, void *data)
-+{
-+ static const struct reg_dump regs_common[] = {
-+ DUMP_STR("RRO/IND CMD CNT"),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(1)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(2)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(3)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(4)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(5)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(6)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(7)),
-+ DUMP_WED(WED_RX_IND_CMD_CNT(8)),
-+ DUMP_WED_MASK(WED_RX_IND_CMD_CNT(9),
-+ WED_IND_CMD_MAGIC_CNT_FAIL_CNT),
-+
-+ DUMP_WED(WED_RX_ADDR_ELEM_CNT(0)),
-+ DUMP_WED_MASK(WED_RX_ADDR_ELEM_CNT(1),
-+ WED_ADDR_ELEM_SIG_FAIL_CNT),
-+ DUMP_WED(WED_RX_MSDU_PG_CNT(1)),
-+ DUMP_WED(WED_RX_MSDU_PG_CNT(2)),
-+ DUMP_WED(WED_RX_MSDU_PG_CNT(3)),
-+ DUMP_WED(WED_RX_MSDU_PG_CNT(4)),
-+ DUMP_WED(WED_RX_MSDU_PG_CNT(5)),
-+ DUMP_WED_MASK(WED_RX_PN_CHK_CNT,
-+ WED_PN_CHK_FAIL_CNT),
-+
-+ DUMP_END()
-+ };
-+
-+ static const struct reg_dump *regs[] = {
-+ ®s_common[0],
-+ NULL,
-+ };
-+ struct mtk_wed_hw *hw = s->private;
-+ struct mtk_wed_device *dev = hw->wed_dev;
-+
-+ if (!dev)
-+ return 0;
-+
-+ dump_wed_regs(s, dev, regs);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(wed_rro);
-+
- void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
- {
- struct dentry *dir;
-@@ -261,8 +747,18 @@ void mtk_wed_hw_add_debugfs(struct mtk_wed_hw *hw)
- debugfs_create_u32("regidx", 0600, dir, &hw->debugfs_reg);
- debugfs_create_file_unsafe("regval", 0600, dir, hw, &fops_regval);
- debugfs_create_file_unsafe("txinfo", 0400, dir, hw, &wed_txinfo_fops);
-- debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
-- if (hw->ver != MTK_WED_V1) {
-+ debugfs_create_u32("token_id", 0600, dir, &hw->token_id);
-+ debugfs_create_file_unsafe("token_txd", 0600, dir, hw, &wed_token_txd_fops);
-+
-+ if (hw->version == 3)
-+ debugfs_create_file_unsafe("pao", 0400, dir, hw, &wed_pao_fops);
-+
-+ if (hw->version != 1) {
-+ debugfs_create_file_unsafe("rxinfo", 0400, dir, hw, &wed_rxinfo_fops);
-+ if (hw->version == 3) {
-+ debugfs_create_file_unsafe("rtqm", 0400, dir, hw, &wed_rtqm_fops);
-+ debugfs_create_file_unsafe("rro", 0400, dir, hw, &wed_rro_fops);
-+ }
- wed_wo_mcu_debugfs(hw, dir);
- }
- }
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-index b5a86f6..c2d060b 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -245,8 +245,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
- if (of_device_is_compatible(wo->hw->node, "mediatek,mt7981-wed"))
- mcu = MT7981_FIRMWARE_WO;
- else
-- mcu = wo->hw->index ? MT7986_FIRMWARE_WO_2 :
-- MT7986_FIRMWARE_WO_1;
-+ mcu = wo->hw->index ? MTK_FIRMWARE_WO_1 : MTK_FIRMWARE_WO_0;
-
- ret = request_firmware(&fw, mcu, wo->hw->dev);
- if (ret)
-@@ -293,8 +292,12 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
- }
-
- /* write the start address */
-- boot_cr = wo->hw->index ?
-- WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+ if (wo->hw->version == 3)
-+ boot_cr = WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+ else
-+ boot_cr = wo->hw->index ?
-+ WOX_MCU_CFG_LS_WA_BOOT_ADDR_ADDR : WOX_MCU_CFG_LS_WM_BOOT_ADDR_ADDR;
-+
- wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
-
- /* wo firmware reset */
-@@ -302,8 +305,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
-
- val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
-
-- val |= wo->hw->index ? WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WA_CPU_RSTB_MASK :
-- WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
-+ val |= WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_WM_CPU_RSTB_MASK;
-
- wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-index dbb17ae..a533b6e 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-@@ -17,8 +17,9 @@
- #define WARP_ALREADY_DONE_STATUS (1)
-
- #define MT7981_FIRMWARE_WO "mediatek/mt7981_wo.bin"
--#define MT7986_FIRMWARE_WO_1 "mediatek/mt7986_wo_0.bin"
--#define MT7986_FIRMWARE_WO_2 "mediatek/mt7986_wo_1.bin"
-+#define MTK_FIRMWARE_WO_0 "mediatek/mtk_wo_0.bin"
-+#define MTK_FIRMWARE_WO_1 "mediatek/mtk_wo_1.bin"
-+#define MTK_FIRMWARE_WO_2 "mediatek/mtk_wo_2.bin"
-
- #define WOCPU_EMI_DEV_NODE "mediatek,wocpu_emi"
- #define WOCPU_ILM_DEV_NODE "mediatek,wocpu_ilm"
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 403a36b..25be547 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -20,6 +20,9 @@
- #define MTK_WDMA_DESC_CTRL_DMA_DONE BIT(31)
- #define MTK_WED_RX_BM_TOKEN GENMASK(31, 16)
-
-+#define MTK_WDMA_TXD0_DESC_INFO_DMA_DONE BIT(29)
-+#define MTK_WDMA_TXD1_DESC_INFO_DMA_DONE BIT(31)
-+
- struct mtk_wdma_desc {
- __le32 buf0;
- __le32 ctrl;
-@@ -51,6 +54,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_RESET_WDMA_INT_AGENT BIT(19)
- #define MTK_WED_RESET_RX_RRO_QM BIT(20)
- #define MTK_WED_RESET_RX_ROUTE_QM BIT(21)
-+#define MTK_WED_RESET_TX_PAO BIT(22)
- #define MTK_WED_RESET_WED BIT(31)
-
- #define MTK_WED_CTRL 0x00c
-@@ -58,6 +62,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_WPDMA_INT_AGENT_BUSY BIT(1)
- #define MTK_WED_CTRL_WDMA_INT_AGENT_EN BIT(2)
- #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3)
-+#define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU BIT(7)
- #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8)
- #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
- #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
-@@ -68,9 +75,14 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_RX_RRO_QM_BUSY BIT(15)
- #define MTK_WED_CTRL_RX_ROUTE_QM_EN BIT(16)
- #define MTK_WED_CTRL_RX_ROUTE_QM_BUSY BIT(17)
-+#define MTK_WED_CTRL_TX_TKID_ALI_EN BIT(20)
-+#define MTK_WED_CTRL_TX_TKID_ALI_BUSY BIT(21)
-+#define MTK_WED_CTRL_TX_PAO_EN BIT(22)
-+#define MTK_WED_CTRL_TX_PAO_BUSY BIT(23)
- #define MTK_WED_CTRL_FINAL_DIDX_READ BIT(24)
- #define MTK_WED_CTRL_ETH_DMAD_FMT BIT(25)
- #define MTK_WED_CTRL_MIB_READ_CLEAR BIT(28)
-+#define MTK_WED_CTRL_FLD_MIB_RD_CLR BIT(28)
-
- #define MTK_WED_EXT_INT_STATUS 0x020
- #define MTK_WED_EXT_INT_STATUS_TF_LEN_ERR BIT(0)
-@@ -78,12 +90,10 @@ struct mtk_wdma_desc {
- #define MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID BIT(4)
- #define MTK_WED_EXT_INT_STATUS_TX_FBUF_LO_TH BIT(8)
- #define MTK_WED_EXT_INT_STATUS_TX_FBUF_HI_TH BIT(9)
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
--#define MTK_WED_EXT_INT_STATUS_TX_TKID_LO_TH BIT(10)
--#define MTK_WED_EXT_INT_STATUS_TX_TKID_HI_TH BIT(11)
--#endif
--#define MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY BIT(12)
--#define MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER BIT(13)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH2 BIT(10)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH2 BIT(11)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_LO_TH BIT(12)
-+#define MTK_WED_EXT_INT_STATUS_RX_FBUF_HI_TH BIT(13)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR BIT(16)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR BIT(17)
- #define MTK_WED_EXT_INT_STATUS_RX_DRV_COHERENT BIT(18)
-@@ -100,17 +110,15 @@ struct mtk_wdma_desc {
- #define MTK_WED_EXT_INT_STATUS_ERROR_MASK (MTK_WED_EXT_INT_STATUS_TF_LEN_ERR | \
- MTK_WED_EXT_INT_STATUS_TKID_WO_PYLD | \
- MTK_WED_EXT_INT_STATUS_TKID_TITO_INVALID | \
-- MTK_WED_EXT_INT_STATUS_RX_FREE_AT_EMPTY | \
-- MTK_WED_EXT_INT_STATUS_RX_FBUF_DMAD_ER | \
- MTK_WED_EXT_INT_STATUS_RX_DRV_R_RESP_ERR | \
- MTK_WED_EXT_INT_STATUS_RX_DRV_W_RESP_ERR | \
- MTK_WED_EXT_INT_STATUS_RX_DRV_INIT_WDMA_EN | \
-- MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR | \
-- MTK_WED_EXT_INT_STATUS_TX_DMA_W_RESP_ERR)
-+ MTK_WED_EXT_INT_STATUS_TX_DMA_R_RESP_ERR)
-
- #define MTK_WED_EXT_INT_MASK 0x028
- #define MTK_WED_EXT_INT_MASK1 0x02c
- #define MTK_WED_EXT_INT_MASK2 0x030
-+#define MTK_WED_EXT_INT_MASK3 0x034
-
- #define MTK_WED_STATUS 0x060
- #define MTK_WED_STATUS_TX GENMASK(15, 8)
-@@ -118,9 +126,14 @@ struct mtk_wdma_desc {
- #define MTK_WED_TX_BM_CTRL 0x080
- #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0)
- #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16)
-+#define MTK_WED_TX_BM_CTRL_LEGACY_EN BIT(26)
-+#define MTK_WED_TX_TKID_CTRL_FREE_FORMAT BIT(27)
- #define MTK_WED_TX_BM_CTRL_PAUSE BIT(28)
-
- #define MTK_WED_TX_BM_BASE 0x084
-+#define MTK_WED_TX_BM_INIT_PTR 0x088
-+#define MTK_WED_TX_BM_SW_TAIL_IDX GENMASK(16, 0)
-+#define MTK_WED_TX_BM_INIT_SW_TAIL_IDX BIT(16)
-
- #define MTK_WED_TX_BM_BUF_LEN 0x08c
-
-@@ -134,22 +147,24 @@ struct mtk_wdma_desc {
- #if defined(CONFIG_MEDIATEK_NETSYS_V2)
- #define MTK_WED_TX_BM_DYN_THR_LO GENMASK(8, 0)
- #define MTK_WED_TX_BM_DYN_THR_HI GENMASK(24, 16)
--
--#define MTK_WED_TX_BM_TKID 0x0c8
--#define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
--#define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
- #else
- #define MTK_WED_TX_BM_DYN_THR_LO GENMASK(6, 0)
- #define MTK_WED_TX_BM_DYN_THR_HI GENMASK(22, 16)
-+#endif
-
--#define MTK_WED_TX_BM_TKID 0x088
-+#define MTK_WED_TX_BM_TKID 0x0c8
- #define MTK_WED_TX_BM_TKID_START GENMASK(15, 0)
- #define MTK_WED_TX_BM_TKID_END GENMASK(31, 16)
--#endif
-
- #define MTK_WED_TX_TKID_CTRL 0x0c0
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM GENMASK(7, 0)
-+#define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(23, 16)
-+#else
- #define MTK_WED_TX_TKID_CTRL_VLD_GRP_NUM GENMASK(6, 0)
- #define MTK_WED_TX_TKID_CTRL_RSV_GRP_NUM GENMASK(22, 16)
-+#endif
-+
- #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28)
-
- #define MTK_WED_TX_TKID_DYN_THR 0x0e0
-@@ -220,12 +235,15 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_PKT_PROC BIT(5)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R0_CRX_SYNC BIT(6)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_R1_CRX_SYNC BIT(7)
--#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(18, 16)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_VER GENMASK(15, 12)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4 BIT(18)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNSUPPORT_FMT BIT(19)
--#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_UEVENT_PKT_FMT_CHK BIT(20)
-+#define MTK_WED_WPDMA_GLO_CFG_RX_DRV_EVENT_PKT_FMT_CHK BIT(20)
- #define MTK_WED_WPDMA_GLO_CFG_RX_DDONE2_WR BIT(21)
- #define MTK_WED_WPDMA_GLO_CFG_TX_TKID_KEEP BIT(24)
-+#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK_LAST BIT(25)
- #define MTK_WED_WPDMA_GLO_CFG_TX_DMAD_DW3_PREV BIT(28)
-+#define MTK_WED_WPDMA_GLO_CFG_TX_DDONE_CHK BIT(30)
-
- /* CONFIG_MEDIATEK_NETSYS_V1 */
- #define MTK_WED_WPDMA_GLO_CFG_RX_BT_SIZE GENMASK(5, 4)
-@@ -288,9 +306,11 @@ struct mtk_wdma_desc {
- #define MTK_WED_PCIE_INT_TRIGGER_STATUS BIT(16)
-
- #define MTK_WED_PCIE_INT_CTRL 0x57c
--#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20)
--#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16)
- #define MTK_WED_PCIE_INT_CTRL_POLL_EN GENMASK(13, 12)
-+#define MTK_WED_PCIE_INT_CTRL_SRC_SEL GENMASK(17, 16)
-+#define MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA BIT(20)
-+#define MTK_WED_PCIE_INT_CTRL_MSK_IRQ_FILTER BIT(21)
-+
- #define MTK_WED_WPDMA_CFG_BASE 0x580
- #define MTK_WED_WPDMA_CFG_INT_MASK 0x584
- #define MTK_WED_WPDMA_CFG_TX 0x588
-@@ -319,20 +339,50 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24)
-
- #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c
--#define MTK_WED_WPDMA_RX_RING 0x770
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#define MTK_WED_WPDMA_RX_RING0 0x770
-+#else
-+#define MTK_WED_WPDMA_RX_RING0 0x7d0
-+#endif
-+#define MTK_WED_WPDMA_RX_RING1 0x7d8
-
- #define MTK_WED_WPDMA_RX_D_MIB(_n) (0x774 + (_n) * 4)
- #define MTK_WED_WPDMA_RX_D_PROCESSED_MIB(_n) (0x784 + (_n) * 4)
- #define MTK_WED_WPDMA_RX_D_COHERENT_MIB 0x78c
-
-+#define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4
-+#define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8)
-+#define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16)
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_RX0_SIDX 0x7b8
-+#define MTK_WED_WPDMA_RX_D_PREF_SIDX_IDX_CLR BIT(15)
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_RX1_SIDX 0x7bc
-+
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG 0x7c0
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R0_CLR BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_FIFO_CFG_R1_CLR BIT(16)
-+
- #define MTK_WED_WDMA_RING_TX 0x800
-
- #define MTK_WED_WDMA_TX_MIB 0x810
-
--
- #define MTK_WED_WDMA_RING_RX(_n) (0x900 + (_n) * 0x10)
- #define MTK_WED_WDMA_RX_THRES(_n) (0x940 + (_n) * 0x4)
-
-+#define MTK_WED_WDMA_RX_PREF_CFG 0x950
-+#define MTK_WED_WDMA_RX_PREF_EN BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8)
-+#define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16)
-+#define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24)
-+#define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25)
-+#define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26)
-+
-+#define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C
-+#define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR BIT(16)
-+
- #define MTK_WED_WDMA_GLO_CFG 0xa04
- #define MTK_WED_WDMA_GLO_CFG_TX_DRV_EN BIT(0)
- #define MTK_WED_WDMA_GLO_CFG_TX_DDONE_CHK BIT(1)
-@@ -365,6 +415,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_WDMA_INT_TRIGGER_RX_DONE GENMASK(17, 16)
-
- #define MTK_WED_WDMA_INT_CTRL 0xa2c
-+#define MTK_WED_WDMA_INT_POLL_PRD GENMASK(7, 0)
- #define MTK_WED_WDMA_INT_POLL_SRC_SEL GENMASK(17, 16)
-
- #define MTK_WED_WDMA_CFG_BASE 0xaa0
-@@ -426,6 +477,18 @@ struct mtk_wdma_desc {
- #define MTK_WDMA_INT_GRP1 0x250
- #define MTK_WDMA_INT_GRP2 0x254
-
-+#define MTK_WDMA_PREF_TX_CFG 0x2d0
-+#define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0)
-+
-+#define MTK_WDMA_PREF_RX_CFG 0x2dc
-+#define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0)
-+
-+#define MTK_WDMA_WRBK_TX_CFG 0x300
-+#define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30)
-+
-+#define MTK_WDMA_WRBK_RX_CFG 0x344
-+#define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30)
-+
- #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0)
- #define MTK_PCIE_MIRROR_MAP_EN BIT(0)
- #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1)
-@@ -439,6 +502,31 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5)
- #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20)
-
-+#define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c
-+#define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28
-+#define MTK_WED_RTQM_IGRS0_I2H_PKT_CNT(_n) (0xb2c + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS0_FDROP_CNT 0xb34
-+
-+
-+#define MTK_WED_RTQM_IGRS1_I2HW_DMAD_CNT 0xb44
-+#define MTK_WED_RTQM_IGRS1_I2H_DMAD_CNT(_n) (0xb48 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS1_I2HW_PKT_CNT 0xb50
-+#define MTK_WED_RTQM_IGRS1_I2H_PKT_CNT(_n) (0xb54+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS1_FDROP_CNT 0xb5c
-+
-+#define MTK_WED_RTQM_IGRS2_I2HW_DMAD_CNT 0xb6c
-+#define MTK_WED_RTQM_IGRS2_I2H_DMAD_CNT(_n) (0xb70 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS2_I2HW_PKT_CNT 0xb78
-+#define MTK_WED_RTQM_IGRS2_I2H_PKT_CNT(_n) (0xb7c+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS2_FDROP_CNT 0xb84
-+
-+#define MTK_WED_RTQM_IGRS3_I2HW_DMAD_CNT 0xb94
-+#define MTK_WED_RTQM_IGRS3_I2H_DMAD_CNT(_n) (0xb98 + (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS3_I2HW_PKT_CNT 0xba0
-+#define MTK_WED_RTQM_IGRS3_I2H_PKT_CNT(_n) (0xba4+ (_n) * 0x4)
-+#define MTK_WED_RTQM_IGRS3_FDROP_CNT 0xbac
-+
- #define MTK_WED_RTQM_R2H_MIB(_n) (0xb70 + (_n) * 0x4)
- #define MTK_WED_RTQM_R2Q_MIB(_n) (0xb78 + (_n) * 0x4)
- #define MTK_WED_RTQM_Q2N_MIB 0xb80
-@@ -447,6 +535,24 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q2B_MIB 0xb8c
- #define MTK_WED_RTQM_PFDBK_MIB 0xb90
-
-+#define MTK_WED_RTQM_ENQ_CFG0 0xbb8
-+#define MTK_WED_RTQM_ENQ_CFG_TXDMAD_FPORT GENMASK(15, 12)
-+
-+#define MTK_WED_RTQM_FDROP_MIB 0xb84
-+#define MTK_WED_RTQM_ENQ_I2Q_DMAD_CNT 0xbbc
-+#define MTK_WED_RTQM_ENQ_I2N_DMAD_CNT 0xbc0
-+#define MTK_WED_RTQM_ENQ_I2Q_PKT_CNT 0xbc4
-+#define MTK_WED_RTQM_ENQ_I2N_PKT_CNT 0xbc8
-+#define MTK_WED_RTQM_ENQ_USED_ENTRY_CNT 0xbcc
-+#define MTK_WED_RTQM_ENQ_ERR_CNT 0xbd0
-+
-+#define MTK_WED_RTQM_DEQ_DMAD_CNT 0xbd8
-+#define MTK_WED_RTQM_DEQ_Q2I_DMAD_CNT 0xbdc
-+#define MTK_WED_RTQM_DEQ_PKT_CNT 0xbe0
-+#define MTK_WED_RTQM_DEQ_Q2I_PKT_CNT 0xbe4
-+#define MTK_WED_RTQM_DEQ_USED_PFDBK_CNT 0xbe8
-+#define MTK_WED_RTQM_DEQ_ERR_CNT 0xbec
-+
- #define MTK_WED_RROQM_GLO_CFG 0xc04
- #define MTK_WED_RROQM_RST_IDX 0xc08
- #define MTK_WED_RROQM_RST_IDX_MIOD BIT(0)
-@@ -487,8 +593,8 @@ struct mtk_wdma_desc {
- #define MTK_WED_RX_BM_BASE 0xd84
- #define MTK_WED_RX_BM_INIT_PTR 0xd88
- #define MTK_WED_RX_BM_PTR 0xd8c
--#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16)
- #define MTK_WED_RX_BM_PTR_TAIL GENMASK(15, 0)
-+#define MTK_WED_RX_BM_PTR_HEAD GENMASK(32, 16)
-
- #define MTK_WED_RX_BM_BLEN 0xd90
- #define MTK_WED_RX_BM_STS 0xd94
-@@ -496,7 +602,193 @@ struct mtk_wdma_desc {
- #define MTK_WED_RX_BM_INTF 0xd9c
- #define MTK_WED_RX_BM_ERR_STS 0xda8
-
-+#define MTK_RRO_IND_CMD_SIGNATURE 0xe00
-+#define MTK_RRO_IND_CMD_DMA_IDX GENMASK(11, 0)
-+#define MTK_RRO_IND_CMD_MAGIC_CNT GENMASK(30, 28)
-+
-+#define MTK_WED_IND_CMD_RX_CTRL0 0xe04
-+#define MTK_WED_IND_CMD_PROC_IDX GENMASK(11, 0)
-+#define MTK_WED_IND_CMD_PREFETCH_FREE_CNT GENMASK(19, 16)
-+#define MTK_WED_IND_CMD_MAGIC_CNT GENMASK(30, 28)
-+
-+#define MTK_WED_IND_CMD_RX_CTRL1 0xe08
-+#define MTK_WED_IND_CMD_RX_CTRL2 0xe0c
-+#define MTK_WED_IND_CMD_MAX_CNT GENMASK(11, 0)
-+#define MTK_WED_IND_CMD_BASE_M GENMASK(19, 16)
-+
-+#define MTK_WED_RRO_CFG0 0xe10
-+#define MTK_WED_RRO_CFG1 0xe14
-+#define MTK_WED_RRO_CFG1_MAX_WIN_SZ GENMASK(31, 29)
-+#define MTK_WED_RRO_CFG1_ACK_SN_BASE_M GENMASK(19, 16)
-+#define MTK_WED_RRO_CFG1_PARTICL_SE_ID GENMASK(11, 0)
-+
-+#define MTK_WED_ADDR_ELEM_CFG0 0xe18
-+#define MTK_WED_ADDR_ELEM_CFG1 0xe1c
-+#define MTK_WED_ADDR_ELEM_PREFETCH_FREE_CNT GENMASK(19, 16)
-+
-+#define MTK_WED_ADDR_ELEM_TBL_CFG 0xe20
-+#define MTK_WED_ADDR_ELEM_TBL_OFFSET GENMASK(6, 0)
-+#define MTK_WED_ADDR_ELEM_TBL_RD_RDY BIT(28)
-+#define MTK_WED_ADDR_ELEM_TBL_WR_RDY BIT(29)
-+#define MTK_WED_ADDR_ELEM_TBL_RD BIT(30)
-+#define MTK_WED_ADDR_ELEM_TBL_WR BIT(31)
-+
-+#define MTK_WED_RADDR_ELEM_TBL_WDATA 0xe24
-+#define MTK_WED_RADDR_ELEM_TBL_RDATA 0xe28
-+
-+#define MTK_WED_PN_CHECK_CFG 0xe30
-+#define MTK_WED_PN_CHECK_SE_ID GENMASK(11, 0)
-+#define MTK_WED_PN_CHECK_RD_RDY BIT(28)
-+#define MTK_WED_PN_CHECK_WR_RDY BIT(29)
-+#define MTK_WED_PN_CHECK_RD BIT(30)
-+#define MTK_WED_PN_CHECK_WR BIT(31)
-+
-+#define MTK_WED_PN_CHECK_WDATA_M 0xe38
-+#define MTK_WED_PN_CHECK_IS_FIRST BIT(17)
-+
-+#define MTK_WED_RRO_MSDU_PG_RING_CFG(_n) (0xe44 + (_n) * 0x8)
-+
-+#define MTK_WED_RRO_MSDU_PG_RING2_CFG 0xe58
-+#define MTK_WED_RRO_MSDU_PG_DRV_CLR BIT(26)
-+#define MTK_WED_RRO_MSDU_PG_DRV_EN BIT(31)
-+
-+#define MTK_WED_RRO_MSDU_PG_CTRL0(_n) (0xe5c + (_n) * 0xc)
-+#define MTK_WED_RRO_MSDU_PG_CTRL1(_n) (0xe60 + (_n) * 0xc)
-+#define MTK_WED_RRO_MSDU_PG_CTRL2(_n) (0xe64 + (_n) * 0xc)
-+
-+#define MTK_WED_RRO_RX_D_RX(_n) (0xe80 + (_n) * 0x10)
-+
-+#define MTK_WED_RRO_RX_MAGIC_CNT BIT(13)
-+
-+#define MTK_WED_RRO_RX_D_CFG(_n) (0xea0 + (_n) * 0x4)
-+#define MTK_WED_RRO_RX_D_DRV_CLR BIT(26)
-+#define MTK_WED_RRO_RX_D_DRV_EN BIT(31)
-+
-+#define MTK_WED_RRO_PG_BM_RX_DMAM 0xeb0
-+#define MTK_WED_RRO_PG_BM_RX_SDL0 GENMASK(13, 0)
-+
-+#define MTK_WED_RRO_PG_BM_BASE 0xeb4
-+#define MTK_WED_RRO_PG_BM_INIT_PTR 0xeb8
-+#define MTK_WED_RRO_PG_BM_SW_TAIL_IDX GENMASK(15, 0)
-+#define MTK_WED_RRO_PG_BM_INIT_SW_TAIL_IDX BIT(16)
-+
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX 0xeec
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_EN BIT(0)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_CLR BIT(1)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX0_DONE_TRIG GENMASK(6, 2)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_EN BIT(8)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_CLR BIT(9)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_RX1_DONE_TRIG GENMASK(14, 10)
-+
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_MSDU_PG 0xef4
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_EN BIT(0)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_CLR BIT(1)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG0_DONE_TRIG GENMASK(6, 2)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_EN BIT(8)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_CLR BIT(9)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG1_DONE_TRIG GENMASK(14, 10)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_EN BIT(16)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17)
-+#define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18)
-+
-+#define MTK_WED_RX_IND_CMD_CNT0 0xf20
-+#define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31)
-+
-+#define MTK_WED_RX_IND_CMD_CNT(_n) (0xf20 + (_n) * 0x4)
-+#define MTK_WED_IND_CMD_MAGIC_CNT_FAIL_CNT GENMASK(15, 0)
-+
-+#define MTK_WED_RX_ADDR_ELEM_CNT(_n) (0xf48 + (_n) * 0x4)
-+#define MTK_WED_ADDR_ELEM_SIG_FAIL_CNT GENMASK(15, 0)
-+#define MTK_WED_ADDR_ELEM_FIRST_SIG_FAIL_CNT GENMASK(31, 16)
-+#define MTK_WED_ADDR_ELEM_ACKSN_CNT GENMASK(27, 0)
-+
-+#define MTK_WED_RX_MSDU_PG_CNT(_n) (0xf5c + (_n) * 0x4)
-+
-+#define MTK_WED_RX_PN_CHK_CNT 0xf70
-+#define MTK_WED_PN_CHK_FAIL_CNT GENMASK(15, 0)
-+
- #define MTK_WED_WOCPU_VIEW_MIOD_BASE 0x8000
- #define MTK_WED_PCIE_INT_MASK 0x0
-
-+#define MTK_WED_PAO_AMSDU_FIFO 0x1800
-+#define MTK_WED_PAO_AMSDU_IS_PRIOR0_RING BIT(10)
-+
-+#define MTK_WED_PAO_STA_INFO 0x01810
-+#define MTK_WED_PAO_STA_INFO_DO_INIT BIT(0)
-+#define MTK_WED_PAO_STA_INFO_SET_INIT BIT(1)
-+
-+#define MTK_WED_PAO_STA_INFO_INIT 0x01814
-+#define MTK_WED_PAO_STA_WTBL_HDRT_MODE BIT(0)
-+#define MTK_WED_PAO_STA_RMVL BIT(1)
-+#define MTK_WED_PAO_STA_MAX_AMSDU_LEN GENMASK(7, 2)
-+#define MTK_WED_PAO_STA_MAX_AMSDU_NUM GENMASK(11, 8)
-+
-+#define MTK_WED_PAO_HIFTXD_BASE_L(_n) (0x1980 + (_n) * 0x4)
-+
-+#define MTK_WED_PAO_PSE 0x1910
-+#define MTK_WED_PAO_PSE_RESET BIT(16)
-+
-+#define MTK_WED_PAO_HIFTXD_CFG 0x1968
-+#define MTK_WED_PAO_HIFTXD_SRC GENMASK(16, 15)
-+
-+#define MTK_WED_PAO_MON_AMSDU_FIFO_DMAD 0x1a34
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_DMAD(_n) (0x1a80 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QFPL(_n) (0x1a84 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QENI(_n) (0x1a88 + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_QENO(_n) (0x1a8c + (_n) * 0x50)
-+#define MTK_WED_PAO_MON_AMSDU_ENG_MERG(_n) (0x1a90 + (_n) * 0x50)
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_CNT8(_n) (0x1a94 + (_n) * 0x50)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_QGPP_CNT GENMASK(10, 0)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_PL_CNT GENMASK(27, 16)
-+
-+#define MTK_WED_PAO_MON_AMSDU_ENG_CNT9(_n) (0x1a98 + (_n) * 0x50)
-+#define MTK_WED_PAO_AMSDU_ENG_CUR_ENTRY GENMASK(10, 0)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_BUF_MERGED GENMASK(20, 16)
-+#define MTK_WED_PAO_AMSDU_ENG_MAX_MSDU_MERGED GENMASK(28, 24)
-+
-+#define MTK_WED_PAO_MON_QMEM_STS1 0x1e04
-+
-+#define MTK_WED_PAO_MON_QMEM_CNT(_n) (0x1e0c + (_n) * 0x4)
-+#define MTK_WED_PAO_QMEM_FQ_CNT GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QCNT GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QCNT GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QCNT GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QCNT GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QCNT GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QCNT GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QCNT GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QCNT GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QCNT GENMASK(11, 0)
-+
-+#define MTK_WED_PAO_MON_QMEM_PTR(_n) (0x1e20 + (_n) * 0x4)
-+#define MTK_WED_PAO_QMEM_FQ_HEAD GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QHEAD GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QHEAD GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QHEAD GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QHEAD GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QHEAD GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QHEAD GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QHEAD GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QHEAD GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QHEAD GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_FQ_TAIL GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_SP_QTAIL GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID0_QTAIL GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID1_QTAIL GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID2_QTAIL GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID3_QTAIL GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID4_QTAIL GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID5_QTAIL GENMASK(11, 0)
-+#define MTK_WED_PAO_QMEM_TID6_QTAIL GENMASK(27, 16)
-+#define MTK_WED_PAO_QMEM_TID7_QTAIL GENMASK(11, 0)
-+
-+#define MTK_WED_PAO_MON_HIFTXD_FETCH_MSDU(_n) (0x1ec4 + (_n) * 0x4)
-+
-+#define MTK_WED_PCIE_BASE 0x11280000
-+
-+#define MTK_WED_PCIE_BASE0 0x11300000
-+#define MTK_WED_PCIE_BASE1 0x11310000
-+#define MTK_WED_PCIE_BASE2 0x11290000
- #endif
-diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
-index b2abebe..204051d 100644
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -880,6 +880,13 @@ struct net_device_path {
- u8 queue;
- u16 wcid;
- u8 bss;
-+ u32 usr_info;
-+ u8 tid;
-+ u8 is_fixedrate;
-+ u8 is_prior;
-+ u8 is_sp;
-+ u8 hf;
-+ u8 amsdu_en;
- } mtk_wdma;
- };
- };
-diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 27cf284..92df4ba 100644
---- a/include/linux/soc/mediatek/mtk_wed.h
-+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -5,11 +5,14 @@
- #include <linux/rcupdate.h>
- #include <linux/regmap.h>
- #include <linux/pci.h>
-+#include <linux/skbuff.h>
-+#include <linux/iopoll.h>
-
- #define WED_WO_STA_REC 0x6
-
- #define MTK_WED_TX_QUEUES 2
- #define MTK_WED_RX_QUEUES 2
-+#define MTK_WED_RX_PAGE_QUEUES 3
-
- enum mtk_wed_wo_cmd {
- MTK_WED_WO_CMD_WED_CFG,
-@@ -55,10 +58,13 @@ enum mtk_wed_bus_tye {
- struct mtk_wed_hw;
- struct mtk_wdma_desc;
-
-+#define MTK_WED_RING_CONFIGURED BIT(0)
-+
- struct mtk_wed_ring {
- struct mtk_wdma_desc *desc;
- dma_addr_t desc_phys;
- int size;
-+ u32 flags;
-
- u32 reg_base;
- void __iomem *wpdma;
-@@ -69,11 +75,18 @@ struct mtk_rxbm_desc {
- __le32 token;
- } __packed __aligned(4);
-
-+struct dma_page_info {
-+ void *addr;
-+ dma_addr_t addr_phys;
-+};
-+
- struct dma_buf {
- int size;
-- void **pages;
-- struct mtk_wdma_desc *desc;
-+ int pkt_nums;
-+ void *desc;
-+ int desc_size;
- dma_addr_t desc_phys;
-+ struct dma_page_info *pages;
- };
-
- struct dma_entry {
-@@ -97,6 +110,7 @@ struct mtk_wed_device {
- struct device *dev;
- struct mtk_wed_hw *hw;
- bool init_done, running;
-+ bool wdma_init_done;
- int wdma_idx;
- int irq;
- u8 ver;
-@@ -108,7 +122,11 @@ struct mtk_wed_device {
- struct mtk_wed_ring rx_ring[MTK_WED_RX_QUEUES];
- struct mtk_wed_ring rx_wdma[MTK_WED_RX_QUEUES];
-
-- struct dma_buf buf_ring;
-+ struct mtk_wed_ring rx_rro_ring[MTK_WED_RX_QUEUES];
-+ struct mtk_wed_ring rx_page_ring[MTK_WED_RX_PAGE_QUEUES];
-+ struct mtk_wed_ring ind_cmd_ring;
-+
-+ struct dma_buf tx_buf_ring;
-
- struct {
- int size;
-@@ -117,6 +135,8 @@ struct mtk_wed_device {
- dma_addr_t desc_phys;
- } rx_buf_ring;
-
-+ struct dma_buf rx_page_buf_ring;
-+
- struct {
- struct mtk_wed_ring rro_ring;
- void __iomem *rro_desc;
-@@ -131,8 +151,9 @@ struct mtk_wed_device {
- struct platform_device *platform_dev;
- struct pci_dev *pci_dev;
- };
-+ enum mtk_wed_bus_tye bus_type;
- void __iomem *base;
-- u32 bus_type;
-+ void __iomem *regs;
- u32 phy_base;
-
- u32 wpdma_phys;
-@@ -141,10 +162,14 @@ struct mtk_wed_device {
- u32 wpdma_tx;
- u32 wpdma_txfree;
- u32 wpdma_rx_glo;
-- u32 wpdma_rx;
-+ u32 wpdma_rx[MTK_WED_RX_QUEUES];
-+ u32 wpdma_rx_rro[MTK_WED_RX_QUEUES];
-+ u32 wpdma_rx_pg;
-
- u8 tx_tbit[MTK_WED_TX_QUEUES];
- u8 rx_tbit[MTK_WED_RX_QUEUES];
-+ u8 rro_rx_tbit[MTK_WED_RX_QUEUES];
-+ u8 rx_pg_tbit[MTK_WED_RX_PAGE_QUEUES];
- u8 txfree_tbit;
-
- u16 token_start;
-@@ -154,12 +179,26 @@ struct mtk_wed_device {
- unsigned int rx_size;
-
- bool wcid_512;
--
-+ bool hwrro;
-+ bool msi;
-+
-+ u8 max_amsdu_nums;
-+ u32 max_amsdu_len;
-+
-+ struct {
-+ u8 se_group_nums;
-+ u16 win_size;
-+ u16 particular_sid;
-+ u32 ack_sn_addr;
-+ dma_addr_t particular_se_phys;
-+ dma_addr_t addr_elem_phys[1024];
-+ } ind_cmd;
-+
-+ u32 chip_id;
- u32 (*init_buf)(void *ptr, dma_addr_t phys, int token_id);
- int (*offload_enable)(struct mtk_wed_device *wed);
- void (*offload_disable)(struct mtk_wed_device *wed);
-- u32 (*init_rx_buf)(struct mtk_wed_device *wed,
-- int pkt_num);
-+ u32 (*init_rx_buf)(struct mtk_wed_device *wed, int size);
- void (*release_rx_buf)(struct mtk_wed_device *wed);
- void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
- struct mtk_wed_wo_rx_stats *stats);
-@@ -180,6 +219,11 @@ struct mtk_wed_ops {
- void __iomem *regs);
- int (*rx_ring_setup)(struct mtk_wed_device *dev, int ring,
- void __iomem *regs, bool reset);
-+ int (*rro_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+ void __iomem *regs);
-+ int (*msdu_pg_rx_ring_setup)(struct mtk_wed_device *dev, int ring,
-+ void __iomem *regs);
-+ int (*ind_rx_ring_setup)(struct mtk_wed_device *dev, void __iomem *regs);
- int (*msg_update)(struct mtk_wed_device *dev, int cmd_id,
- void *data, int len);
- void (*detach)(struct mtk_wed_device *dev);
-@@ -196,6 +240,7 @@ struct mtk_wed_ops {
- void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
- void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
- u32 reason, u32 hash);
-+ void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask);
- };
-
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -224,12 +269,21 @@ static inline bool
- mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- {
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
-+ if (dev->ver == 3 && !dev->wlan.hwrro)
-+ return false;
-+
- return dev->ver != 1;
- #else
- return false;
- #endif
- }
-
-+static inline bool
-+mtk_wed_device_support_pao(struct mtk_wed_device *dev)
-+{
-+ return dev->ver == 3;
-+}
-+
- #ifdef CONFIG_NET_MEDIATEK_SOC_WED
- #define mtk_wed_device_active(_dev) !!(_dev)->ops
- #define mtk_wed_device_detach(_dev) (_dev)->ops->detach(_dev)
-@@ -243,6 +297,12 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- (_dev)->ops->txfree_ring_setup(_dev, _regs)
- #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) \
- (_dev)->ops->rx_ring_setup(_dev, _ring, _regs, _reset)
-+#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) \
-+ (_dev)->ops->rro_rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) \
-+ (_dev)->ops->msdu_pg_rx_ring_setup(_dev, _ring, _regs)
-+#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) \
-+ (_dev)->ops->ind_rx_ring_setup(_dev, _regs)
- #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) \
- (_dev)->ops->msg_update(_dev, _id, _msg, _len)
- #define mtk_wed_device_reg_read(_dev, _reg) \
-@@ -257,6 +317,9 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev)
- (_dev)->ops->reset_dma(_dev)
- #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
- (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
-+#define mtk_wed_device_start_hwrro(_dev, _mask) \
-+ (_dev)->ops->start_hwrro(_dev, _mask)
-+
- #else
- static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- {
-@@ -268,6 +331,9 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_tx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
- #define mtk_wed_device_txfree_ring_setup(_dev, _ring, _regs) -ENODEV
- #define mtk_wed_device_rx_ring_setup(_dev, _ring, _regs, _reset) -ENODEV
-+#define mtk_wed_device_rro_rx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_msdu_pg_rx_ring_setup(_dev, _ring, _regs) -ENODEV
-+#define mtk_wed_device_ind_rx_ring_setup(_dev, _regs) -ENODEV
- #define mtk_wed_device_reg_read(_dev, _reg) 0
- #define mtk_wed_device_reg_write(_dev, _reg, _val) do {} while (0)
- #define mtk_wed_device_irq_get(_dev, _mask) 0
-@@ -275,6 +341,7 @@ static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
- #define mtk_wed_device_dma_reset(_dev) do {} while (0)
- #define mtk_wed_device_setup_tc(_dev, _ndev, _type, _data) do {} while (0)
- #define mtk_wed_device_ppe_check(_dev, _hash) do {} while (0)
-+#define mtk_wed_device_start_hwrro(_dev, _mask) do {} while (0)
- #endif
-
- #endif
---
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3020-mtk-wed-add-wed3-ser-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3020-mtk-wed-add-wed3-ser-support.patch
deleted file mode 100644
index 328a4bc..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3020-mtk-wed-add-wed3-ser-support.patch
+++ /dev/null
@@ -1,642 +0,0 @@
-From f0b9f017b170690be346d3e08371fdadca0d59d3 Mon Sep 17 00:00:00 2001
-From: mtk27745 <rex.lu@mediatek.com>
-Date: Mon, 18 Sep 2023 13:22:44 +0800
-Subject: [PATCH] mtk wed add wed3 ser support
-
----
- drivers/net/ethernet/mediatek/mtk_wed.c | 260 +++++++++++++++++--
- drivers/net/ethernet/mediatek/mtk_wed_regs.h | 73 +++++-
- include/linux/soc/mediatek/mtk_wed.h | 6 +-
- 3 files changed, 310 insertions(+), 29 deletions(-)
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 561fc6c..f20a4ae 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -99,16 +99,70 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
- u32 status;
- u32 mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
- int busy, i;
-+ u32 value;
-
- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
- busy = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
-- !(status & mask), 0, 10000);
-+ !(status & mask), 0, 10000);
-
-+ if (dev->hw->version == 3) {
-+ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_PREF_TX_CFG);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_PREF_RX_CFG);
-+
-+ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_WRBK_TX_CFG);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_WRBK_RX_CFG);
-+
-+ /* Prefetch FIFO */
-+ wdma_w32(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
-+ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
-+ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_PREF_RX_FIFO_CFG,
-+ MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR |
-+ MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR);
-+
-+ /* Core FIFO */
-+ value = (MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR);
-+
-+ wdma_w32(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
-+ wdma_clr(dev, MTK_WDMA_XDMA_RX_FIFO_CFG, value);
-+
-+ /* Writeback FIFO */
-+ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+ wdma_w32(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+
-+ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(0), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_WRBK_RX_FIFO_CFG(1), MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR);
-+
-+ /* Prefetch ring status */
-+ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR);
-+ /* Writeback ring status */
-+ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR);
-+ }
- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-
-- for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
-- if (!dev->rx_wdma[i].desc) {
-+ for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+ if (!dev->tx_wdma[i].desc) {
- wdma_w32(dev, MTK_WDMA_RING_RX(i) +
- MTK_WED_RING_OFS_CPU_IDX, 0);
- }
-@@ -121,16 +175,65 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
- {
- u32 status;
- u32 mask = MTK_WDMA_GLO_CFG_TX_DMA_BUSY;
-- int i;
-+ int busy, i;
-+ u32 value;
-
- wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
- if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
- !(status & mask), 0, 10000))
- WARN_ON_ONCE(1);
-
-+ if (dev->hw->version == 3) {
-+ wdma_clr(dev, MTK_WDMA_PREF_TX_CFG, MTK_WDMA_PREF_TX_CFG_PREF_EN);
-+ wdma_clr(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_PREF_TX_CFG_PREF_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_PREF_TX_CFG);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_PREF_RX_CFG_PREF_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_PREF_RX_CFG);
-+
-+ wdma_clr(dev, MTK_WDMA_WRBK_TX_CFG, MTK_WDMA_WRBK_TX_CFG_WRBK_EN);
-+ wdma_clr(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_WRBK_TX_CFG);
-+ busy = read_poll_timeout(wdma_r32, status,
-+ !(status & MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY), 0, 10000,
-+ false, dev, MTK_WDMA_WRBK_RX_CFG);
-+
-+ /* Prefetch FIFO */
-+ wdma_w32(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
-+ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
-+ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_PREF_TX_FIFO_CFG,
-+ MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR |
-+ MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR);
-+ /* Core FIFO */
-+ value = (MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR |
-+ MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR);
-+
-+ wdma_w32(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
-+ wdma_clr(dev, MTK_WDMA_XDMA_TX_FIFO_CFG, value);
-+ /* Writeback FIFO */
-+ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+ wdma_w32(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+
-+ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(0), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_WRBK_TX_FIFO_CFG(1), MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR);
-+
-+ /* Prefetch ring status */
-+ wdma_w32(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_PREF_SIDX_CFG, MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR);
-+ /* Writeback ring status */
-+ wdma_w32(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
-+ wdma_clr(dev, MTK_WDMA_WRBK_SIDX_CFG, MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR);
-+ }
- wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
- wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
-- for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
-+ for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
- wdma_w32(dev, MTK_WDMA_RING_TX(i) +
- MTK_WED_RING_OFS_CPU_IDX, 0);
- }
-@@ -913,7 +1016,7 @@ mtk_wed_dma_enable(struct mtk_wed_device *dev)
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_UNS_VER_FORCE_4);
-
- wdma_set(dev, MTK_WDMA_PREF_RX_CFG, MTK_WDMA_PREF_RX_CFG_PREF_EN);
-- //wdma_w32(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
-+ wdma_set(dev, MTK_WDMA_WRBK_RX_CFG, MTK_WDMA_WRBK_RX_CFG_WRBK_EN);
- if (mtk_wed_get_rx_capa(dev)) {
- wed_set(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
- MTK_WED_WPDMA_RX_D_PREF_EN |
-@@ -1476,13 +1579,30 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
- &state, sizeof(state), true);
-
-+ if (dev->wlan.hwrro) {
-+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_IND_CMD_EN);
-+ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_HW_STS,
-+ MTK_WED_RX_IND_CMD_BUSY);
-+ mtk_wed_reset(dev, MTK_WED_RESET_RRO_RX_TO_PG);
-+ }
- wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
- busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
- MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
-+ if (dev->hw->version == 3)
-+ busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+ MTK_WED_WPDMA_RX_D_PREF_BUSY);
- if (busy) {
- mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
- mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
- } else {
-+ if (dev->hw->version == 3) {
-+ /*1.a. Disable Prefetch HW*/
-+ wed_clr(dev, MTK_WED_WPDMA_RX_D_PREF_CFG, MTK_WED_WPDMA_RX_D_PREF_EN);
-+ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_PREF_CFG,
-+ MTK_WED_WPDMA_RX_D_PREF_BUSY);
-+ wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
-+ MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL);
-+ }
- wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
- MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
- MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
-@@ -1510,6 +1630,24 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
- }
-
-+ if (dev->wlan.hwrro) {
-+ /* Disable RRO MSDU Page Drv */
-+ wed_clr(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+
-+ /* Disable RRO Data Drv */
-+ wed_clr(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_EN);
-+
-+ /* RRO MSDU Page Drv Reset */
-+ wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+ mtk_wed_poll_busy(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG,
-+ MTK_WED_RRO_MSDU_PG_DRV_CLR);
-+
-+ /* RRO Data Drv Reset */
-+ wed_w32(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_RX_D_DRV_CLR);
-+ mtk_wed_poll_busy(dev, MTK_WED_RRO_RX_D_CFG(2),
-+ MTK_WED_RRO_RX_D_DRV_CLR);
-+ }
-+
- /* reset route qm */
- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
- busy = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-@@ -1517,8 +1655,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- if (busy) {
- mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
- } else {
-- wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-- MTK_WED_RTQM_Q_RST);
-+ if (dev->hw->version == 3) {
-+ wed_set(dev, MTK_WED_RTQM_RST, BIT(0));
-+ wed_clr(dev, MTK_WED_RTQM_RST, BIT(0));
-+ mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
-+ } else
-+ wed_set(dev, MTK_WED_RTQM_GLO_CFG,
-+ MTK_WED_RTQM_Q_RST);
- }
-
- /* reset tx wdma */
-@@ -1526,8 +1669,13 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
-
- /* reset tx wdma drv */
- wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
-- mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-- MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
-+ if (dev->hw->version == 3)
-+ mtk_wed_poll_busy(dev, MTK_WED_WPDMA_STATUS,
-+ MTK_WED_WPDMA_STATUS_TX_DRV);
-+ else
-+ mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
-+
- mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
-
- /* reset wed rx dma */
-@@ -1545,9 +1693,17 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- /* reset rx bm */
- wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
- mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-- MTK_WED_CTRL_WED_RX_BM_BUSY);
-+ MTK_WED_CTRL_WED_RX_BM_BUSY);
- mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
-
-+ if (dev->wlan.hwrro) {
-+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_PG_BM_EN);
-+ mtk_wed_poll_busy(dev, MTK_WED_CTRL,
-+ MTK_WED_CTRL_WED_RX_PG_BM_BUSY);
-+ wed_set(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
-+ wed_clr(dev, MTK_WED_RESET, MTK_WED_RESET_RX_PG_BM);
-+ }
-+
- /* wo change to enable state */
- state = WO_STATE_ENABLE;
- mtk_wed_mcu_send_msg(wo, MODULE_ID_WO, MTK_WED_WO_CMD_CHANGE_STATE,
-@@ -1564,6 +1720,9 @@ mtk_wed_rx_reset(struct mtk_wed_device *dev)
- }
-
- mtk_wed_free_rx_buffer(dev);
-+
-+ if (dev->wlan.hwrro)
-+ mtk_wed_rx_page_free_buffer(dev);
- }
-
-
-@@ -1597,18 +1756,54 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
-
- /* 2. Reset WDMA Rx DMA/Driver_Engine */
- busy = !!mtk_wdma_rx_reset(dev);
-+ if (dev->hw->version == 3) {
-+ val = wed_r32(dev, MTK_WED_WDMA_GLO_CFG);
-+ val |= MTK_WED_WDMA_GLO_CFG_RX_DIS_FSM_AUTO_IDLE;
-+ val &= ~MTK_WED_WDMA_GLO_CFG_RX_DRV_EN;
-+ wed_w32(dev, MTK_WED_WDMA_GLO_CFG, val);
-+ } else
-+ wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
-
-- wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
- busy = !!(busy ||
- mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
-- MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
-+ MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY));
-+ if (dev->hw->version == 3)
-+ busy = !!(busy ||
-+ mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_BUSY));
-
- if (busy) {
- mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
- mtk_wed_reset(dev, MTK_WED_RESET_WDMA_RX_DRV);
- } else {
-+ if (dev->hw->version == 3) {
-+ /*1.a. Disable Prefetch HW*/
-+ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_EN);
-+ mtk_wed_poll_busy(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_BUSY);
-+ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG, MTK_WED_WDMA_RX_PREF_DDONE2_EN);
-+
-+ /* reset prefetch index */
-+ wed_set(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+ wed_clr(dev, MTK_WED_WDMA_RX_PREF_CFG,
-+ MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR |
-+ MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR);
-+
-+ /* reset prefetch FIFO */
-+ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG,
-+ MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR |
-+ MTK_WED_WDMA_RX_PREF_FIFO_RX1_CLR);
-+ wed_w32(dev, MTK_WED_WDMA_RX_PREF_FIFO_CFG, 0);
-+ /*2. Reset dma index*/
-+ wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
-+ MTK_WED_WDMA_RESET_IDX_RX_ALL);
-+ }
- wed_w32(dev, MTK_WED_WDMA_RESET_IDX,
-- MTK_WED_WDMA_RESET_IDX_RX | MTK_WED_WDMA_RESET_IDX_DRV);
-+ MTK_WED_WDMA_RESET_IDX_RX |
-+ MTK_WED_WDMA_RESET_IDX_DRV);
- wed_w32(dev, MTK_WED_WDMA_RESET_IDX, 0);
-
- wed_set(dev, MTK_WED_WDMA_GLO_CFG,
-@@ -1623,9 +1818,15 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
-
- for (i = 0; i < 100; i++) {
-- val = wed_r32(dev, MTK_WED_TX_BM_INTF);
-- if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
-- break;
-+ if (dev->ver > MTK_WED_V1) {
-+ val = wed_r32(dev, MTK_WED_TX_TKID_INTF);
-+ if (FIELD_GET(MTK_WED_TX_TKID_INTF_TKFIFO_FDEP, val) == 0x40)
-+ break;
-+ } else {
-+ val = wed_r32(dev, MTK_WED_TX_BM_INTF);
-+ if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
-+ break;
-+ }
- }
- mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
-
-@@ -1634,18 +1835,20 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
-
- /* 4. Reset WED WPDMA Tx Driver Engine */
- busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-- MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
-+ MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
- wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
- MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
- MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
-
- busy = !!(busy ||
- mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
-- MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
-+ MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY));
- if (busy) {
- mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
- mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
- mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_DRV);
-+ if (dev->hw->version == 3)
-+ wed_w32(dev, MTK_WED_RX1_CTRL2, 0);
- } else {
- wed_w32(dev, MTK_WED_WPDMA_RESET_IDX,
- MTK_WED_WPDMA_RESET_IDX_TX |
-@@ -1658,11 +1861,17 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
- }
- }
-
-- if (dev->ver > MTK_WED_V1) {
-- dev->init_done = false;
-- mtk_wed_rx_reset(dev);
-+ dev->init_done = false;
-+
-+ if (dev->hw->version == 3) {
-+ /*reset wed pao*/
-+ wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_TX_PAO_EN);
-+ mtk_wed_reset(dev, MTK_WED_RESET_TX_PAO);
- }
-
-+ if (mtk_wed_get_rx_capa(dev))
-+ mtk_wed_rx_reset(dev);
-+
- }
-
- static int
-@@ -1875,7 +2084,7 @@ mtk_wed_ppe_check(struct mtk_wed_device *dev, struct sk_buff *skb,
- }
-
- static void
--mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
-+mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask, bool reset)
- {
- int idx, ret;
-
-@@ -1885,6 +2094,11 @@ mtk_wed_start_hwrro(struct mtk_wed_device *dev, u32 irq_mask)
- if (!mtk_wed_get_rx_capa(dev) || !dev->wlan.hwrro)
- return;
-
-+ if (reset) {
-+ wed_set(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_EN);
-+ return;
-+ }
-+
- wed_set(dev, MTK_WED_RRO_RX_D_CFG(2), MTK_WED_RRO_MSDU_PG_DRV_CLR);
- wed_w32(dev, MTK_WED_RRO_MSDU_PG_RING2_CFG, MTK_WED_RRO_MSDU_PG_DRV_CLR);
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-index 25be547..4379dc4 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h
-@@ -42,6 +42,8 @@ struct mtk_wdma_desc {
- #define MTK_WED_RESET 0x008
- #define MTK_WED_RESET_TX_BM BIT(0)
- #define MTK_WED_RESET_RX_BM BIT(1)
-+#define MTK_WED_RESET_RX_PG_BM BIT(2)
-+#define MTK_WED_RESET_RRO_RX_TO_PG BIT(3)
- #define MTK_WED_RESET_TX_FREE_AGENT BIT(4)
- #define MTK_WED_RESET_WPDMA_TX_DRV BIT(8)
- #define MTK_WED_RESET_WPDMA_RX_DRV BIT(9)
-@@ -64,7 +66,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_CTRL_WDMA_INT_AGENT_BUSY BIT(3)
- #define MTK_WED_CTRL_WED_RX_IND_CMD_EN BIT(5)
- #define MTK_WED_CTRL_WED_RX_PG_BM_EN BIT(6)
--#define MTK_WED_CTRL_WED_RX_PG_BM_BUSU BIT(7)
-+#define MTK_WED_CTRL_WED_RX_PG_BM_BUSY BIT(7)
- #define MTK_WED_CTRL_WED_TX_BM_EN BIT(8)
- #define MTK_WED_CTRL_WED_TX_BM_BUSY BIT(9)
- #define MTK_WED_CTRL_WED_TX_FREE_AGENT_EN BIT(10)
-@@ -123,6 +125,10 @@ struct mtk_wdma_desc {
- #define MTK_WED_STATUS 0x060
- #define MTK_WED_STATUS_TX GENMASK(15, 8)
-
-+#define MTK_WED_WPDMA_STATUS 0x068
-+#define MTK_WED_WPDMA_STATUS_TX_DRV GENMASK(15, 8)
-+
-+
- #define MTK_WED_TX_BM_CTRL 0x080
- #define MTK_WED_TX_BM_CTRL_VLD_GRP_NUM GENMASK(6, 0)
- #define MTK_WED_TX_BM_CTRL_RSV_GRP_NUM GENMASK(22, 16)
-@@ -167,6 +173,9 @@ struct mtk_wdma_desc {
-
- #define MTK_WED_TX_TKID_CTRL_PAUSE BIT(28)
-
-+#define MTK_WED_TX_TKID_INTF 0x0dc
-+#define MTK_WED_TX_TKID_INTF_TKFIFO_FDEP GENMASK(25, 16)
-+
- #define MTK_WED_TX_TKID_DYN_THR 0x0e0
- #define MTK_WED_TX_TKID_DYN_THR_LO GENMASK(6, 0)
- #define MTK_WED_TX_TKID_DYN_THR_HI GENMASK(22, 16)
-@@ -203,10 +212,11 @@ struct mtk_wdma_desc {
- #define MTK_WED_GLO_CFG_RX_2B_OFFSET BIT(31)
-
- #define MTK_WED_RESET_IDX 0x20c
--#define MTK_WED_RESET_IDX_TX GENMASK(3, 0)
--#if defined(CONFIG_MEDIATEK_NETSYS_V2)
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define MTK_WED_RESET_IDX_TX GENMASK(1, 0)
- #define MTK_WED_RESET_IDX_RX GENMASK(7, 6)
- #else
-+#define MTK_WED_RESET_IDX_TX GENMASK(3, 0)
- #define MTK_WED_RESET_IDX_RX GENMASK(17, 16)
- #endif
- #define MTK_WED_RESET_WPDMA_IDX_RX GENMASK(31, 30)
-@@ -221,6 +231,7 @@ struct mtk_wdma_desc {
- #define MTK_WED_RING_RX_DATA(_n) (0x420 + (_n) * 0x10)
-
- #define MTK_WED_SCR0 0x3c0
-+#define MTK_WED_RX1_CTRL2 0x418
- #define MTK_WED_WPDMA_INT_TRIGGER 0x504
- #define MTK_WED_WPDMA_INT_TRIGGER_RX_DONE BIT(1)
- #define MTK_WED_WPDMA_INT_TRIGGER_TX_DONE GENMASK(5, 4)
-@@ -336,6 +347,7 @@ struct mtk_wdma_desc {
-
- #define MTK_WED_WPDMA_RX_D_RST_IDX 0x760
- #define MTK_WED_WPDMA_RX_D_RST_CRX_IDX GENMASK(17, 16)
-+#define MTK_WED_WPDMA_RX_D_RST_DRV_IDX_ALL BIT(20)
- #define MTK_WED_WPDMA_RX_D_RST_DRV_IDX GENMASK(25, 24)
-
- #define MTK_WED_WPDMA_RX_GLO_CFG 0x76c
-@@ -352,6 +364,7 @@ struct mtk_wdma_desc {
-
- #define MTK_WED_WPDMA_RX_D_PREF_CFG 0x7b4
- #define MTK_WED_WPDMA_RX_D_PREF_EN BIT(0)
-+#define MTK_WED_WPDMA_RX_D_PREF_BUSY BIT(1)
- #define MTK_WED_WPDMA_RX_D_PREF_BURST_SIZE GENMASK(12, 8)
- #define MTK_WED_WPDMA_RX_D_PREF_LOW_THRES GENMASK(21, 16)
-
-@@ -373,11 +386,13 @@ struct mtk_wdma_desc {
-
- #define MTK_WED_WDMA_RX_PREF_CFG 0x950
- #define MTK_WED_WDMA_RX_PREF_EN BIT(0)
-+#define MTK_WED_WDMA_RX_PREF_BUSY BIT(1)
- #define MTK_WED_WDMA_RX_PREF_BURST_SIZE GENMASK(12, 8)
- #define MTK_WED_WDMA_RX_PREF_LOW_THRES GENMASK(21, 16)
- #define MTK_WED_WDMA_RX_PREF_RX0_SIDX_CLR BIT(24)
- #define MTK_WED_WDMA_RX_PREF_RX1_SIDX_CLR BIT(25)
- #define MTK_WED_WDMA_RX_PREF_DDONE2_EN BIT(26)
-+#define MTK_WED_WDMA_RX_PREF_DDONE2_BUSY BIT(27)
-
- #define MTK_WED_WDMA_RX_PREF_FIFO_CFG 0x95C
- #define MTK_WED_WDMA_RX_PREF_FIFO_RX0_CLR BIT(0)
-@@ -406,6 +421,7 @@ struct mtk_wdma_desc {
-
- #define MTK_WED_WDMA_RESET_IDX 0xa08
- #define MTK_WED_WDMA_RESET_IDX_RX GENMASK(17, 16)
-+#define MTK_WED_WDMA_RESET_IDX_RX_ALL BIT(20)
- #define MTK_WED_WDMA_RESET_IDX_DRV GENMASK(25, 24)
-
- #define MTK_WED_WDMA_INT_CLR 0xa24
-@@ -474,21 +490,66 @@ struct mtk_wdma_desc {
- #define MTK_WDMA_INT_MASK_RX_DELAY BIT(30)
- #define MTK_WDMA_INT_MASK_RX_COHERENT BIT(31)
-
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG 0x238
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_PAR_FIFO_CLEAR BIT(0)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_CMD_FIFO_CLEAR BIT(4)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_DMAD_FIFO_CLEAR BIT(8)
-+#define MTK_WDMA_XDMA_TX_FIFO_CFG_TX_ARR_FIFO_CLEAR BIT(12)
-+
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG 0x23c
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_PAR_FIFO_CLEAR BIT(0)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_CMD_FIFO_CLEAR BIT(4)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_DMAD_FIFO_CLEAR BIT(8)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_ARR_FIFO_CLEAR BIT(12)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_LEN_FIFO_CLEAR BIT(15)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_WID_FIFO_CLEAR BIT(18)
-+#define MTK_WDMA_XDMA_RX_FIFO_CFG_RX_BID_FIFO_CLEAR BIT(21)
-+
-+
-+
- #define MTK_WDMA_INT_GRP1 0x250
- #define MTK_WDMA_INT_GRP2 0x254
-
- #define MTK_WDMA_PREF_TX_CFG 0x2d0
- #define MTK_WDMA_PREF_TX_CFG_PREF_EN BIT(0)
-+#define MTK_WDMA_PREF_TX_CFG_PREF_BUSY BIT(1)
-
- #define MTK_WDMA_PREF_RX_CFG 0x2dc
- #define MTK_WDMA_PREF_RX_CFG_PREF_EN BIT(0)
-+#define MTK_WDMA_PREF_RX_CFG_PREF_BUSY BIT(1)
-+
-+#define MTK_WDMA_PREF_RX_FIFO_CFG 0x2e0
-+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING0_CLEAR BIT(0)
-+#define MTK_WDMA_PREF_RX_FIFO_CFG_RING1_CLEAR BIT(16)
-+
-+#define MTK_WDMA_PREF_TX_FIFO_CFG 0x2d4
-+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING0_CLEAR BIT(0)
-+#define MTK_WDMA_PREF_TX_FIFO_CFG_RING1_CLEAR BIT(16)
-+
-+#define MTK_WDMA_PREF_SIDX_CFG 0x2e4
-+#define MTK_WDMA_PREF_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0)
-+#define MTK_WDMA_PREF_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4)
-
- #define MTK_WDMA_WRBK_TX_CFG 0x300
-+#define MTK_WDMA_WRBK_TX_CFG_WRBK_BUSY BIT(0)
- #define MTK_WDMA_WRBK_TX_CFG_WRBK_EN BIT(30)
-
-+#define MTK_WDMA_WRBK_TX_FIFO_CFG(_n) (0x304 + (_n) * 0x4)
-+#define MTK_WDMA_WRBK_TX_FIFO_CFG_RING_CLEAR BIT(0)
-+
-+
- #define MTK_WDMA_WRBK_RX_CFG 0x344
-+#define MTK_WDMA_WRBK_RX_CFG_WRBK_BUSY BIT(0)
- #define MTK_WDMA_WRBK_RX_CFG_WRBK_EN BIT(30)
-
-+#define MTK_WDMA_WRBK_RX_FIFO_CFG(_n) (0x348 + (_n) * 0x4)
-+#define MTK_WDMA_WRBK_RX_FIFO_CFG_RING_CLEAR BIT(0)
-+
-+
-+#define MTK_WDMA_WRBK_SIDX_CFG 0x388
-+#define MTK_WDMA_WRBK_SIDX_CFG_TX_RING_CLEAR GENMASK(3, 0)
-+#define MTK_WDMA_WRBK_SIDX_CFG_RX_RING_CLEAR GENMASK(5, 4)
-+
- #define MTK_PCIE_MIRROR_MAP(n) ((n) ? 0x4 : 0x0)
- #define MTK_PCIE_MIRROR_MAP_EN BIT(0)
- #define MTK_PCIE_MIRROR_MAP_WED_ID BIT(1)
-@@ -502,6 +563,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_RTQM_Q_DBG_BYPASS BIT(5)
- #define MTK_WED_RTQM_TXDMAD_FPORT GENMASK(23, 20)
-
-+#define MTK_WED_RTQM_RST 0xb04
-+
-+
- #define MTK_WED_RTQM_IGRS0_I2HW_DMAD_CNT 0xb1c
- #define MTK_WED_RTQM_IGRS0_I2H_DMAD_CNT(_n) (0xb20 + (_n) * 0x4)
- #define MTK_WED_RTQM_IGRS0_I2HW_PKT_CNT 0xb28
-@@ -691,6 +755,9 @@ struct mtk_wdma_desc {
- #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_CLR BIT(17)
- #define MTK_WED_WPDMA_INT_CTRL_RRO_PG2_DONE_TRIG GENMASK(22, 18)
-
-+#define MTK_WED_RRO_RX_HW_STS 0xf00
-+#define MTK_WED_RX_IND_CMD_BUSY GENMASK(31, 0)
-+
- #define MTK_WED_RX_IND_CMD_CNT0 0xf20
- #define MTK_WED_RX_IND_CMD_DBG_CNT_EN BIT(31)
-
-diff --git a/include/linux/soc/mediatek/mtk_wed.h b/include/linux/soc/mediatek/mtk_wed.h
-index 92df4ba..1438692 100644
---- a/include/linux/soc/mediatek/mtk_wed.h
-+++ b/include/linux/soc/mediatek/mtk_wed.h
-@@ -240,7 +240,7 @@ struct mtk_wed_ops {
- void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
- void (*ppe_check)(struct mtk_wed_device *dev, struct sk_buff *skb,
- u32 reason, u32 hash);
-- void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask);
-+ void (*start_hwrro)(struct mtk_wed_device *dev, u32 irq_mask, bool reset);
- };
-
- extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
-@@ -317,8 +317,8 @@ mtk_wed_device_support_pao(struct mtk_wed_device *dev)
- (_dev)->ops->reset_dma(_dev)
- #define mtk_wed_device_ppe_check(_dev, _skb, _reason, _hash) \
- (_dev)->ops->ppe_check(_dev, _skb, _reason, _hash)
--#define mtk_wed_device_start_hwrro(_dev, _mask) \
-- (_dev)->ops->start_hwrro(_dev, _mask)
-+#define mtk_wed_device_start_hwrro(_dev, _mask, _reset) \
-+ (_dev)->ops->start_hwrro(_dev, _mask, _reset)
-
- #else
- static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
---
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
deleted file mode 100644
index af32459..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3021-mtk-wed-add-dma-mask-limitation-and-GFP_DMA32-for-bo.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From 659d8d088ee856cbc7598a26a307fd3e20a70e8e Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Mon, 18 Sep 2023 13:23:56 +0800
-Subject: [PATCH 22/22] mtk: wed: add dma mask limitation and GFP_DMA32 for
- board >= 4GB dram
-
----
- drivers/net/ethernet/mediatek/mtk_wed.c | 8 ++++++--
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 4 ++--
- drivers/net/ethernet/mediatek/mtk_wed_wo.c | 4 ++--
- drivers/net/ethernet/mediatek/mtk_wed_wo.h | 1 +
- 4 files changed, 11 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index 0d101d5..2ec7148 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
-@@ -472,7 +472,7 @@ mtk_wed_tx_buffer_alloc(struct mtk_wed_device *dev)
- void *buf;
- int s;
-
-- page = __dev_alloc_pages(GFP_KERNEL, 0);
-+ page = __dev_alloc_pages(GFP_KERNEL | GFP_DMA32, 0);
- if (!page)
- return -ENOMEM;
-
-@@ -636,7 +636,7 @@ mtk_wed_rx_page_buffer_alloc(struct mtk_wed_device *dev)
- void *buf;
- int s;
-
-- page = __dev_alloc_pages(GFP_KERNEL, 0);
-+ page = __dev_alloc_pages(GFP_KERNEL | GFP_DMA32, 0);
- if (!page)
- return -ENOMEM;
-
-@@ -2249,6 +2249,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
- dev->wdma_idx = hw->index;
- dev->ver = hw->version;
-
-+ ret = dma_set_mask_and_coherent(hw->dev, DMA_BIT_MASK(32));
-+ if (ret)
-+ return ret;
-+
- if (dev->hw->version == 3)
- dev->hw->pci_base = mtk_wed_get_pci_base(dev);
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-index 055594d..4ed1548 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-@@ -131,7 +131,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
- }req;
-
- exp->log_size = EXCEPTION_LOG_SIZE;
-- exp->log = kmalloc(exp->log_size, GFP_ATOMIC);
-+ exp->log = page_frag_alloc(&wo->page, exp->log_size, GFP_ATOMIC | GFP_DMA32);
- if (!exp->log)
- return -ENOMEM;
-
-@@ -151,7 +151,7 @@ int mtk_wed_exception_init(struct mtk_wed_wo *wo)
- &req, sizeof(req), false);
-
- free:
-- kfree(exp->log);
-+ skb_free_frag(exp->log);
- return -ENOMEM;
- }
-
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.c b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
-index 54b7787..e991d20 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.c
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.c
-@@ -88,7 +88,7 @@ woif_q_rx_fill(struct mtk_wed_wo *wo, struct wed_wo_queue *q, bool rx)
- page = &q->rx_page;
-
- while (q->queued < q->ndesc) {
-- buf = page_frag_alloc(page, len, GFP_ATOMIC);
-+ buf = page_frag_alloc(page, len, GFP_ATOMIC | GFP_DMA32);
- if (!buf)
- break;
-
-@@ -555,7 +555,7 @@ void mtk_wed_wo_exit(struct mtk_wed_hw *hw)
-
- if (wo->exp.log) {
- dma_unmap_single(wo->hw->dev, wo->exp.phys, wo->exp.log_size, DMA_FROM_DEVICE);
-- kfree(wo->exp.log);
-+ skb_free_frag(wo->exp.log);
- }
-
- wo->hw = NULL;
-diff --git a/drivers/net/ethernet/mediatek/mtk_wed_wo.h b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-index 548b38e..3fd1f3f 100644
---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h
-@@ -193,6 +193,7 @@ struct mtk_wed_wo {
- const struct wed_wo_drv_ops *drv_ops;
- const struct wed_wo_mcu_ops *mcu_ops;
- const struct wed_wo_queue_ops *queue_ops;
-+ struct page_frag_cache page;
-
- struct net_device napi_dev;
- spinlock_t rx_lock;
---
-2.18.0
-
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index 2c688d4..a6e6a07 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -103,9 +103,9 @@
patch -p1 < ${WORKDIR}/999-2737-net-mt753x-phy-coverity-scan.patch
patch -p1 < ${WORKDIR}/999-1710-v6.2-net-phy-add-phylink-pcs-support.patch
patch -p1 < ${WORKDIR}/999-1712-v6.2-net-phy-add-phylink-rate-matching-support.patch
- patch -p1 < ${WORKDIR}/999-2702-v5.9-net-phy-add-support-for-a-common-probe-between-shared-PHYs.patch
patch -p1 < ${WORKDIR}/999-2725-iwconfig-wireless-rate-fix.patch
patch -p1 < ${WORKDIR}/999-2729-net-phy-remove-reporting-line-rate-to-mac.patch
+ patch -p1 < ${WORKDIR}/999-2739-drivers_net_ethernet_mediatek_hnat.patch
if [ $DISTRO_secure_boot_ENABLED = 'true' ]; then
patch -p1 < ${WORKDIR}/0404-mtdsplit-dm-verity.patch
patch -p1 < ${WORKDIR}/0800-dm-verity-redo-hash-for-safexel-sha256.patch
@@ -124,14 +124,6 @@
fi
}
-do_filogic_patches_append_mt7988() {
- if [ ! -e wed3_patch_applied ]; then
- if [ $DISTRO_FlowBlock_ENABLED = 'true' ]; then
- for i in ${WORKDIR}/mediatek/wed3/*.patch; do patch -p1 < $i; done
- fi
- touch wed3_patch_applied
- fi
-}
addtask filogic_patches after do_patch before do_compile
KERNEL_MODULE_AUTOLOAD += "${@bb.utils.contains('DISTRO_FEATURES','logan','mtkhnat nf_flow_table_hw','',d)}"