[qca-ssdk] support eee property configuration

Change-Id: Id8ff0aad0916d4370df57e3f98434d4ca0b3cda4
Signed-off-by: esong <song@codeaurora.org>
diff --git a/include/adpt/adpt.h b/include/adpt/adpt.h
index b648314..3f3a9db 100755
--- a/include/adpt/adpt.h
+++ b/include/adpt/adpt.h
@@ -307,7 +307,10 @@
 			fal_port_t port_id, a_bool_t enable);
 typedef sw_error_t (*adpt_port_promisc_mode_get_func)(a_uint32_t dev_id,
 			fal_port_t port_id, a_bool_t *enable);
-
+typedef sw_error_t (*adpt_port_interface_eee_cfg_set_func)(a_uint32_t dev_id,
+			fal_port_t port_id, fal_port_eee_cfg_t *port_eee_cfg);
+typedef sw_error_t (*adpt_port_interface_eee_cfg_get_func)(a_uint32_t dev_id,
+			fal_port_t port_id, fal_port_eee_cfg_t *port_eee_cfg);
 
 // mirror
 typedef sw_error_t (*adpt_mirr_port_in_set_func)(a_uint32_t dev_id, fal_port_t port_id,
@@ -1125,6 +1128,9 @@
 	adpt_port_flowctrl_forcemode_get_func adpt_port_flowctrl_forcemode_get;
 	adpt_port_promisc_mode_set_func adpt_port_promisc_mode_set;
 	adpt_port_promisc_mode_get_func adpt_port_promisc_mode_get;
+	adpt_port_interface_eee_cfg_set_func adpt_port_interface_eee_cfg_set;
+	adpt_port_interface_eee_cfg_get_func adpt_port_interface_eee_cfg_get;
+
 
 // mirror
 	a_uint32_t adpt_mirror_func_bitmap;
diff --git a/include/api/api_desc.h b/include/api/api_desc.h
index 04c2cd5..817b3c9 100755
--- a/include/api/api_desc.h
+++ b/include/api/api_desc.h
@@ -518,6 +518,18 @@
     SW_PARAM_DEF(SW_API_PT_PROMISC_MODE_GET, SW_UINT32, 4, SW_PARAM_IN, "Port ID"),\
     SW_PARAM_DEF(SW_API_PT_PROMISC_MODE_GET, SW_ENABLE, 4, SW_PARAM_PTR|SW_PARAM_OUT, "Enable"),
 
+#define SW_API_PT_INTERFACE_EEE_CFG_SET_DESC \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_SET, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_SET, SW_UINT32, 4, SW_PARAM_IN, "Port ID"), \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_SET, SW_PORT_EEE_CONFIG, \
+		sizeof(fal_port_eee_cfg_t), SW_PARAM_PTR|SW_PARAM_IN, "EEE"),
+
+#define SW_API_PT_INTERFACE_EEE_CFG_GET_DESC \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_GET, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_GET, SW_UINT32, 4, SW_PARAM_IN, "Port ID"), \
+    SW_PARAM_DEF(SW_API_PT_INTERFACE_EEE_CFG_GET, SW_PORT_EEE_CONFIG, \
+		sizeof(fal_port_eee_cfg_t), SW_PARAM_PTR|SW_PARAM_OUT, "EEE"),
+
 #define SW_API_VLAN_ADD_DESC \
     SW_PARAM_DEF(SW_API_VLAN_ADD, SW_UINT32, 4, SW_PARAM_IN, "Dev ID"), \
     SW_PARAM_DEF(SW_API_VLAN_ADD, SW_UINT32, 4, SW_PARAM_IN, "Vlan Id"),
diff --git a/include/api/sw_api.h b/include/api/sw_api.h
index 7661f90..fc58bac 100755
--- a/include/api/sw_api.h
+++ b/include/api/sw_api.h
@@ -225,6 +225,7 @@
 	SW_PTP_TRIGGER,
 	SW_PTP_CAPTURE,
 	SW_PTP_INTERRUPT,
+	SW_PORT_EEE_CONFIG,
     } sw_data_type_e;
 
     typedef struct
diff --git a/include/api/sw_ioctl.h b/include/api/sw_ioctl.h
index 20af99d..f1fa594 100755
--- a/include/api/sw_ioctl.h
+++ b/include/api/sw_ioctl.h
@@ -121,6 +121,8 @@
 #define SW_API_PT_INTERFACE_3AZ_STATUS_GET  (76 + SW_API_PORT_OFFSET)
 #define SW_API_PT_PROMISC_MODE_SET   (77  + SW_API_PORT_OFFSET)
 #define SW_API_PT_PROMISC_MODE_GET   (78  + SW_API_PORT_OFFSET)
+#define SW_API_PT_INTERFACE_EEE_CFG_SET  (79 + SW_API_PORT_OFFSET)
+#define SW_API_PT_INTERFACE_EEE_CFG_GET  (80 + SW_API_PORT_OFFSET)
 
 
     /*vlan*/
diff --git a/include/fal/fal_api.h b/include/fal/fal_api.h
index a37ac59..a5c4094 100755
--- a/include/fal/fal_api.h
+++ b/include/fal/fal_api.h
@@ -122,7 +122,9 @@
     SW_API_DEF(SW_API_PT_INTERFACE_3AZ_STATUS_SET, fal_port_interface_3az_status_set), \
     SW_API_DEF(SW_API_PT_INTERFACE_3AZ_STATUS_GET, fal_port_interface_3az_status_get), \
     SW_API_DEF(SW_API_PT_PROMISC_MODE_SET, fal_port_promisc_mode_set),  \
-    SW_API_DEF(SW_API_PT_PROMISC_MODE_GET, fal_port_promisc_mode_get),
+    SW_API_DEF(SW_API_PT_PROMISC_MODE_GET, fal_port_promisc_mode_get), \
+    SW_API_DEF(SW_API_PT_INTERFACE_EEE_CFG_SET, fal_port_interface_eee_cfg_set),  \
+    SW_API_DEF(SW_API_PT_INTERFACE_EEE_CFG_GET, fal_port_interface_eee_cfg_get),
 /*qca808x_start*/
 /*end of PORTCONTROL_API*/
 #define PORTCONTROL_API_PARAM \
@@ -223,7 +225,9 @@
     SW_API_DESC(SW_API_PT_INTERFACE_3AZ_STATUS_SET)  \
     SW_API_DESC(SW_API_PT_INTERFACE_3AZ_STATUS_GET) \
     SW_API_DESC(SW_API_PT_PROMISC_MODE_SET)  \
-    SW_API_DESC(SW_API_PT_PROMISC_MODE_GET)
+    SW_API_DESC(SW_API_PT_PROMISC_MODE_GET) \
+    SW_API_DESC(SW_API_PT_INTERFACE_EEE_CFG_SET)  \
+    SW_API_DESC(SW_API_PT_INTERFACE_EEE_CFG_GET)
 /*qca808x_start*/
 /*end of PORTCONTROL_API_PARAM*/
 /*qca808x_end*/
diff --git a/include/fal/fal_port_ctrl.h b/include/fal/fal_port_ctrl.h
index 6bb89be..94d7249 100755
--- a/include/fal/fal_port_ctrl.h
+++ b/include/fal/fal_port_ctrl.h
@@ -146,6 +146,13 @@
 #define FAL_PHY_INTR_WOL_STATUS   0x80
 #define FAL_PHY_INTR_POE_STATUS   0x100
 
+/* phy eee */
+#define FAL_PHY_EEE_10BASE_T  0x1
+#define FAL_PHY_EEE_100BASE_T  0x2
+#define FAL_PHY_EEE_1000BASE_T  0x4
+#define FAL_PHY_EEE_2500BASE_T  0x8
+#define FAL_PHY_EEE_5000BASE_T  0x10
+#define FAL_PHY_EEE_10000BASE_T  0x20
 	typedef enum {
 		FAL_NO_HEADER_EN = 0,
 		FAL_ONLY_MANAGE_FRAME_EN,
@@ -282,6 +289,18 @@
 } fal_port_counter_info_t;
 
 /*above is new add for malibu phy*/
+
+typedef struct {
+	a_bool_t enable;
+	a_uint32_t capability;
+	a_uint32_t lpi_sleep_timer; /* unit is us*/
+	a_uint32_t advertisement;
+	a_uint32_t lpi_tx_enable;
+	a_uint32_t eee_status;
+	a_uint32_t lpi_wakeup_timer; /* unit is us*/
+	a_uint32_t link_partner_advertisement;
+} fal_port_eee_cfg_t;
+
 /*qca808x_end*/
 enum
 {
@@ -721,6 +740,13 @@
 sw_error_t
 fal_port_promisc_mode_get(a_uint32_t dev_id,fal_port_t port_id,a_bool_t *enable);
 
+sw_error_t
+fal_port_interface_eee_cfg_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg);
+sw_error_t
+fal_port_interface_eee_cfg_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg);
+
 /*qca808x_start*/
 #ifdef __cplusplus
 }
diff --git a/include/hsl/phy/aquantia_phy.h b/include/hsl/phy/aquantia_phy.h
index 0a03918..b409166 100755
--- a/include/hsl/phy/aquantia_phy.h
+++ b/include/hsl/phy/aquantia_phy.h
@@ -37,6 +37,11 @@
 #define AQUANTIA_GLOBAL_STANDARD_CONTROL1        0
 #define AQUANTIA_EEE_ADVERTISTMENT_REGISTER        0x3C
 #define AQUANTIA_EEE_ADVERTISTMENT_REGISTER1        0x3E
+#define AQUANTIA_EEE_PARTNER_ADVERTISTMENT_REGISTER        0x3D
+#define AQUANTIA_EEE_PARTNER_ADVERTISTMENT_REGISTER1        0x3F
+#define AQUANTIA_EEE_CAPABILITY_REGISTER        0x14
+#define AQUANTIA_EEE_CAPABILITY_REGISTER1        0x15
+
 #define AQUANTIA_REG_AUTONEG_VENDOR_STATUS  0xC800
 #define AQUANTIA_AUTONEG_STANDARD_STATUS1  0x1
 #define AQUANTIA_AUTONEG_STANDARD_CONTROL1  0
@@ -147,6 +152,15 @@
 #define AQUANTIA_EEE_ADV_2500M 0x0001
 #define AQUANTIA_EEE_ADV_5000M 0x0002
 #define AQUANTIA_EEE_ADV_10000M 0x0008
+#define AQUANTIA_EEE_PARTNER_ADV_1000M 0x0004
+#define AQUANTIA_EEE_PARTNER_ADV_2500M 0x0001
+#define AQUANTIA_EEE_PARTNER_ADV_5000M 0x0002
+#define AQUANTIA_EEE_PARTNER_ADV_10000M 0x0008
+#define AQUANTIA_EEE_CAPABILITY_1000M 0x0004
+#define AQUANTIA_EEE_CAPABILITY_2500M 0x0001
+#define AQUANTIA_EEE_CAPABILITY_5000M 0x0002
+#define AQUANTIA_EEE_CAPABILITY_10000M 0x0008
+
 #define AQUANTIA_PHY_USX_AUTONEG_ENABLE	0x0008
 
 #define AQUANTIA_PHY_RX_FLOWCTRL_STATUS 0x0002
diff --git a/include/hsl/phy/hsl_phy.h b/include/hsl/phy/hsl_phy.h
index 59f9379..325d865 100755
--- a/include/hsl/phy/hsl_phy.h
+++ b/include/hsl/phy/hsl_phy.h
@@ -213,6 +213,21 @@
 	typedef sw_error_t(*hsl_phy_get_status) (a_uint32_t dev_id,
 				a_uint32_t phy_id, struct port_phy_status *phy_status);
 
+	typedef sw_error_t(*hsl_phy_eee_adv_set) (a_uint32_t dev_id,
+					      a_uint32_t phy_id,
+					      a_uint32_t adv);
+	typedef sw_error_t(*hsl_phy_eee_adv_get) (a_uint32_t dev_id,
+					      a_uint32_t phy_id,
+					      a_uint32_t * adv);
+	typedef sw_error_t(*hsl_phy_eee_partner_adv_get) (a_uint32_t dev_id,
+					      a_uint32_t phy_id,
+					      a_uint32_t * adv);
+	typedef sw_error_t(*hsl_phy_eee_cap_get) (a_uint32_t dev_id,
+					      a_uint32_t phy_id,
+					      a_uint32_t * cap);
+	typedef sw_error_t(*hsl_phy_eee_status_get) (a_uint32_t dev_id,
+					      a_uint32_t phy_id,
+					      a_uint32_t * status);
 /*qca808x_end*/
 	typedef sw_error_t(*hsl_phy_ptp_security_set) (a_uint32_t dev_id,
 				a_uint32_t phy_id, fal_ptp_security_t *sec);
@@ -464,6 +479,11 @@
 		hsl_phy_counter_show  phy_counter_show;
 		hsl_phy_serdes_reset phy_serdes_reset;
 		hsl_phy_get_status phy_get_status;
+		hsl_phy_eee_adv_set phy_eee_adv_set;
+		hsl_phy_eee_adv_get phy_eee_adv_get;
+		hsl_phy_eee_partner_adv_get phy_eee_partner_adv_get;
+		hsl_phy_eee_cap_get phy_eee_cap_get;
+		hsl_phy_eee_status_get phy_eee_status_get;
 /*qca808x_end*/
 		hsl_phy_ptp_ops_t phy_ptp_ops;
 /*qca808x_start*/
diff --git a/include/hsl/phy/malibu_phy.h b/include/hsl/phy/malibu_phy.h
index 5b7c5af..22aa9f1 100755
--- a/include/hsl/phy/malibu_phy.h
+++ b/include/hsl/phy/malibu_phy.h
@@ -76,6 +76,10 @@
 #define MALIBU_DEBUG_PHY_HIBERNATION_CTRL  0xb
 #define MALIBU_DEBUG_PHY_POWER_SAVING_CTRL  0x29
 #define MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_CTRL       0x3c
+#define MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER       0x3d
+#define MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_STATUS       0x8000
+#define MALIBU_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY       0x14
+
 #define MALIBU_PHY_MMD3_ADDR_REMOTE_LOOPBACK_CTRL       0x805a
 #define MALIBU_PHY_MMD3_WOL_MAGIC_MAC_CTRL1   0x804a
 #define MALIBU_PHY_MMD3_WOL_MAGIC_MAC_CTRL2   0x804b
@@ -90,6 +94,15 @@
 #define MALIBU_DAC_CTRL_VALUE  0x280
 #define MALIBU_LED_1000_CTRL1_100_10_MASK  0x30
 
+#define MALIBU_PHY_EEE_ADV_100M 0x0002
+#define MALIBU_PHY_EEE_ADV_1000M 0x0004
+#define MALIBU_PHY_EEE_PARTNER_ADV_100M 0x0002
+#define MALIBU_PHY_EEE_PARTNER_ADV_1000M 0x0004
+#define MALIBU_PHY_EEE_CAPABILITY_100M 0x0002
+#define MALIBU_PHY_EEE_CAPABILITY_1000M 0x0004
+#define MALIBU_PHY_EEE_STATUS_100M 0x0002
+#define MALIBU_PHY_EEE_STATUS_1000M 0x0004
+
 
 #define AZ_TIMER_CTRL_DEFAULT_VALUE    0x3062
 #define AZ_CLD_CTRL_DEFAULT_VALUE     0x83f6
diff --git a/include/hsl/phy/qca803x_phy.h b/include/hsl/phy/qca803x_phy.h
index 5514d54..75e4805 100755
--- a/include/hsl/phy/qca803x_phy.h
+++ b/include/hsl/phy/qca803x_phy.h
@@ -59,6 +59,10 @@
 #define QCA803X_DEBUG_PHY_HIBERNATION_CTRL  0xb
 #define QCA803X_DEBUG_PHY_POWER_SAVING_CTRL  0x29
 #define QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL       0x3c
+#define QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER       0x3d
+#define QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_STATUS       0x8000
+#define QCA803X_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY       0x14
+
 #define QCA803X_PHY_MMD3_ADDR_REMOTE_LOOPBACK_CTRL       0x805a
 #define QCA803X_PHY_MMD3_WOL_MAGIC_MAC_CTRL1   0x804a
 #define QCA803X_PHY_MMD3_WOL_MAGIC_MAC_CTRL2   0x804b
@@ -79,6 +83,15 @@
 #define QCA803X_PWR_SAVE 0x29
 #define QCA803X_PWR_SAVE_EN 0x8000
 
+#define QCA803X_PHY_EEE_ADV_100M 0x0002
+#define QCA803X_PHY_EEE_ADV_1000M 0x0004
+#define QCA803X_PHY_EEE_PARTNER_ADV_100M 0x0002
+#define QCA803X_PHY_EEE_PARTNER_ADV_1000M 0x0004
+#define QCA803X_PHY_EEE_CAPABILITY_100M 0x0002
+#define QCA803X_PHY_EEE_CAPABILITY_1000M 0x0004
+#define QCA803X_PHY_EEE_STATUS_100M 0x0002
+#define QCA803X_PHY_EEE_STATUS_1000M 0x0004
+
 	/* CDT */
 #define QCA803X_MDI_PAIR_NUM 4
 #define QCA803X_RUN_CDT 0x1
diff --git a/include/hsl/phy/qca808x_phy.h b/include/hsl/phy/qca808x_phy.h
index 2dffec3..7284f1d 100755
--- a/include/hsl/phy/qca808x_phy.h
+++ b/include/hsl/phy/qca808x_phy.h
@@ -74,6 +74,10 @@
 #define QCA808X_DEBUG_PHY_HIBERNATION_STAT          0xc
 #define QCA808X_DEBUG_PHY_POWER_SAVING_CTRL         0x29
 #define QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL       0x3c
+#define QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER       0x3d
+#define QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_STATUS       0x8000
+#define QCA808X_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY       0x14
+
 #define QCA808X_PHY_MMD3_ADDR_8023AZ_EEE_DB         0x800f
 #define QCA808X_PHY_8023AZ_EEE_LP_STAT              0x2000
 #define QCA808X_PHY_MMD3_ADDR_REMOTE_LOOPBACK_CTRL  0x805a
@@ -104,6 +108,15 @@
 #define QCA808X_PHY_MMD3_NUM  3
 #define QCA808X_PHY_MMD1_NUM  1
 
+#define QCA808X_PHY_EEE_ADV_100M 0x0002
+#define QCA808X_PHY_EEE_ADV_1000M 0x0004
+#define QCA808X_PHY_EEE_PARTNER_ADV_100M 0x0002
+#define QCA808X_PHY_EEE_PARTNER_ADV_1000M 0x0004
+#define QCA808X_PHY_EEE_CAPABILITY_100M 0x0002
+#define QCA808X_PHY_EEE_CAPABILITY_1000M 0x0004
+#define QCA808X_PHY_EEE_STATUS_100M 0x0002
+#define QCA808X_PHY_EEE_STATUS_1000M 0x0004
+
 	/* CDT */
 #define QCA808X_MDI_PAIR_NUM            4
 #define QCA808X_RUN_CDT                 0x8000
diff --git a/include/shell_lib/shell_io.h b/include/shell_lib/shell_io.h
index fa8ac15..b6c76da 100755
--- a/include/shell_lib/shell_io.h
+++ b/include/shell_lib/shell_io.h
@@ -61,6 +61,9 @@
                                  a_uint32_t size);
 sw_error_t cmd_data_check_speed(char *cmd_str, a_uint32_t * arg_val,
                                 a_uint32_t size);
+sw_error_t
+cmd_data_check_port_eee_config(char *cmd_str, void * val, a_uint32_t size);
+
 #endif
 #ifdef IN_PORTVLAN
 sw_error_t cmd_data_check_1qmode(char *cmd_str, a_uint32_t * arg_val,
diff --git a/src/adpt/hppe/adpt_hppe_portctrl.c b/src/adpt/hppe/adpt_hppe_portctrl.c
index 37cfb8a..e40c371 100755
--- a/src/adpt/hppe/adpt_hppe_portctrl.c
+++ b/src/adpt/hppe/adpt_hppe_portctrl.c
@@ -72,6 +72,8 @@
 
 #define PHY_PORT_TO_BM_PORT(port)	(port + 7)
 #define GMAC_IPG_CHECK 0xc
+#define LPI_EEE_TIMER_FREQUENCY 300  /* 300MHZ*/
+#define LPI_EEE_TIMER_UNIT 256
 
 /* This register is used to adjust the write timing for reserving
  * some bandwidth of the memory to read operation.
@@ -3503,6 +3505,138 @@
 
 	return rv;
 }
+static a_uint32_t port_lpi_sleep_timer[SW_MAX_NR_DEV][SSDK_PHYSICAL_PORT6] = {
+	{218, 218, 218, 218, 218, 218},
+	{218, 218, 218, 218, 218, 218},
+	{218, 218, 218, 218, 218, 218},
+}; /* unit is us*/
+static a_uint32_t port_lpi_wakeup_timer[SW_MAX_NR_DEV][SSDK_PHYSICAL_PORT6] = {
+	{27, 27, 27, 27, 27, 27},
+	{27, 27, 27, 27, 27, 27},
+	{27, 27, 27, 27, 27, 27},
+}; /* unit is us*/
+static sw_error_t
+adpt_hppe_port_interface_eee_cfg_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
+	sw_error_t rv = 0;
+	union lpi_enable_u lpi_enable = {0};
+	union lpi_port_timer_u lpi_port_timer = {0};
+	a_uint32_t phy_id = 0;
+	a_uint32_t adv, enable;
+	hsl_phy_ops_t *phy_drv;
+
+	ADPT_DEV_ID_CHECK(dev_id);
+
+	if ((port_id < SSDK_PHYSICAL_PORT1) || (port_id > SSDK_PHYSICAL_PORT6)) {
+		return SW_BAD_PARAM;
+	}
+	if (port_eee_cfg->enable) {
+		adv = port_eee_cfg->advertisement;
+	} else {
+		adv = 0;
+	}
+	if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_PHY)) {
+		return SW_BAD_PARAM;
+	}
+	if (A_FALSE == _adpt_hppe_port_phy_connected (dev_id, port_id)) {
+		return SW_NOT_SUPPORTED;
+	}
+
+	SW_RTN_ON_NULL(phy_drv = hsl_phy_api_ops_get(dev_id, port_id));
+	if (NULL == phy_drv->phy_eee_adv_set) {
+		return SW_NOT_SUPPORTED;
+	}
+
+	rv = hsl_port_prop_get_phyid(dev_id, port_id, &phy_id);
+	SW_RTN_ON_ERROR (rv);
+
+	rv = phy_drv->phy_eee_adv_set(dev_id, phy_id, adv);
+	SW_RTN_ON_ERROR (rv);
+
+	hppe_lpi_enable_get(dev_id, port_id, &lpi_enable);
+
+	enable = port_eee_cfg->lpi_tx_enable;
+	lpi_enable.val &= ~(0x1 << (port_id - 1));
+	lpi_enable.val |= (enable << (port_id - 1));
+	hppe_lpi_enable_set(dev_id, port_id, &lpi_enable);
+
+	lpi_port_timer.bf.lpi_port_wakeup_timer =
+		(port_eee_cfg->lpi_wakeup_timer * LPI_EEE_TIMER_FREQUENCY) /LPI_EEE_TIMER_UNIT;
+	lpi_port_timer.bf.lpi_port_sleep_timer =
+		(port_eee_cfg->lpi_sleep_timer * LPI_EEE_TIMER_FREQUENCY) /LPI_EEE_TIMER_UNIT;
+	rv = hppe_lpi_timer_set(dev_id, port_id, &lpi_port_timer);
+	SW_RTN_ON_ERROR (rv);
+	port_lpi_wakeup_timer[dev_id][port_id - 1] = port_eee_cfg->lpi_wakeup_timer;
+	port_lpi_sleep_timer[dev_id][port_id - 1] = port_eee_cfg->lpi_sleep_timer;
+
+	return rv;
+}
+static sw_error_t
+adpt_hppe_port_interface_eee_cfg_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
+	sw_error_t rv = 0;
+	union lpi_enable_u lpi_enable = {0};
+	a_uint32_t phy_id = 0;
+	hsl_phy_ops_t *phy_drv;
+	a_uint32_t adv, lp_adv, cap, status;
+
+	if ((port_id < SSDK_PHYSICAL_PORT1) || (port_id > SSDK_PHYSICAL_PORT6)) {
+		return SW_BAD_PARAM;
+	}
+
+	ADPT_DEV_ID_CHECK(dev_id);
+	ADPT_NULL_POINT_CHECK(port_eee_cfg);
+	memset(port_eee_cfg, 0, sizeof(*port_eee_cfg));
+
+	if (A_TRUE != hsl_port_prop_check(dev_id, port_id, HSL_PP_PHY)) {
+		return SW_BAD_PARAM;
+	}
+	if (A_FALSE == _adpt_hppe_port_phy_connected (dev_id, port_id)) {
+		return SW_NOT_SUPPORTED;
+	}
+
+	SW_RTN_ON_NULL (phy_drv =hsl_phy_api_ops_get (dev_id, port_id));
+	if ((NULL == phy_drv->phy_eee_adv_get) || (NULL == phy_drv->phy_eee_partner_adv_get) ||
+		(NULL == phy_drv->phy_eee_cap_get) || (NULL == phy_drv->phy_eee_status_get)) {
+		return SW_NOT_SUPPORTED;
+	}
+
+	rv = hsl_port_prop_get_phyid(dev_id, port_id, &phy_id);
+	SW_RTN_ON_ERROR (rv);
+
+	rv = phy_drv->phy_eee_adv_get(dev_id, phy_id, &adv);
+	SW_RTN_ON_ERROR (rv);
+	port_eee_cfg->advertisement = adv;
+	rv = phy_drv->phy_eee_partner_adv_get(dev_id, phy_id, &lp_adv);
+	SW_RTN_ON_ERROR (rv);
+	port_eee_cfg->link_partner_advertisement = lp_adv;
+	rv = phy_drv->phy_eee_cap_get(dev_id, phy_id, &cap);
+	SW_RTN_ON_ERROR (rv);
+	port_eee_cfg->capability = cap;
+	rv = phy_drv->phy_eee_status_get(dev_id, phy_id, &status);
+	SW_RTN_ON_ERROR (rv);
+	port_eee_cfg->eee_status = status;
+
+	if (port_eee_cfg->advertisement) {
+		port_eee_cfg->enable = A_TRUE;
+	} else {
+		port_eee_cfg->enable = A_FALSE;
+	}
+	rv = hppe_lpi_enable_get(dev_id, port_id, &lpi_enable);
+	SW_RTN_ON_ERROR (rv);
+
+	if(((lpi_enable.val >> (port_id - 1)) & 0x1) == A_TRUE) {
+		port_eee_cfg->lpi_tx_enable = A_TRUE;
+	} else {
+		port_eee_cfg->lpi_tx_enable = A_FALSE;
+	}
+	port_eee_cfg->lpi_wakeup_timer =  port_lpi_wakeup_timer[dev_id][port_id - 1];
+	port_eee_cfg->lpi_sleep_timer = port_lpi_sleep_timer[dev_id][port_id - 1];
+
+	return rv;
+}
 
 #ifdef HAWKEYE_CHIP
 static sw_error_t
@@ -4707,6 +4841,8 @@
 	p_adpt_api->adpt_port_polling_sw_sync_set = qca_hppe_mac_sw_sync_task;
 #endif
 	p_adpt_api->adpt_port_bridge_txmac_set = adpt_hppe_port_bridge_txmac_set;
+	p_adpt_api->adpt_port_interface_eee_cfg_set = adpt_hppe_port_interface_eee_cfg_set;
+	p_adpt_api->adpt_port_interface_eee_cfg_get = adpt_hppe_port_interface_eee_cfg_get;
 
 	return SW_OK;
 }
diff --git a/src/fal/fal_port_ctrl.c b/src/fal/fal_port_ctrl.c
index bb88343..aef1fe5 100755
--- a/src/fal/fal_port_ctrl.c
+++ b/src/fal/fal_port_ctrl.c
@@ -1962,7 +1962,40 @@
 
 	return rv;
 }
+static sw_error_t
+_fal_port_interface_eee_cfg_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
 
+	adpt_api_t *p_api;
+	sw_error_t rv = SW_OK;
+
+	SW_RTN_ON_NULL(p_api = adpt_api_ptr_get(dev_id));
+
+	if (NULL == p_api->adpt_port_interface_eee_cfg_set)
+		return SW_NOT_SUPPORTED;
+
+	rv = p_api->adpt_port_interface_eee_cfg_set(dev_id, port_id, port_eee_cfg);
+	return rv;
+
+}
+
+static sw_error_t
+_fal_port_interface_eee_cfg_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
+	adpt_api_t *p_api;
+	sw_error_t rv = SW_OK;
+
+	SW_RTN_ON_NULL(p_api = adpt_api_ptr_get(dev_id));
+
+	if (NULL == p_api->adpt_port_interface_eee_cfg_get)
+		return SW_NOT_SUPPORTED;
+
+	rv = p_api->adpt_port_interface_eee_cfg_get(dev_id, port_id, port_eee_cfg);
+	return rv;
+
+}
 /*qca808x_start*/
 /*insert flag for inner fal, don't remove it*/
 /**
@@ -3534,6 +3567,30 @@
     return rv;
 }
 
+sw_error_t
+fal_port_interface_eee_cfg_set(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
+    sw_error_t rv = SW_OK;
+
+    FAL_API_LOCK;
+    rv = _fal_port_interface_eee_cfg_set(dev_id, port_id, port_eee_cfg);
+    FAL_API_UNLOCK;
+    return rv;
+}
+
+sw_error_t
+fal_port_interface_eee_cfg_get(a_uint32_t dev_id, fal_port_t port_id,
+	fal_port_eee_cfg_t *port_eee_cfg)
+{
+    sw_error_t rv = SW_OK;
+
+    FAL_API_LOCK;
+    rv = _fal_port_interface_eee_cfg_get(dev_id, port_id, port_eee_cfg);
+    FAL_API_UNLOCK;
+    return rv;
+}
+
 /*insert flag for outter fal, don't remove it*/
 /**
  * @}
@@ -3609,3 +3666,5 @@
 EXPORT_SYMBOL(fal_port_flowctrl_forcemode_get);
 EXPORT_SYMBOL(fal_port_promisc_mode_set);
 EXPORT_SYMBOL(fal_port_promisc_mode_get);
+EXPORT_SYMBOL(fal_port_interface_eee_cfg_set);
+EXPORT_SYMBOL(fal_port_interface_eee_cfg_get);
diff --git a/src/hsl/phy/aquantia_phy.c b/src/hsl/phy/aquantia_phy.c
index 2b096a4..1582df5 100755
--- a/src/hsl/phy/aquantia_phy.c
+++ b/src/hsl/phy/aquantia_phy.c
@@ -1793,6 +1793,191 @@
 
 /******************************************************************************
 *
+* aquantia_phy_set_eee_advertisement
+*
+* set eee advertisement
+*/
+sw_error_t
+aquantia_phy_set_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t adv)
+{
+	a_uint16_t phy_data = 0, phy_data1 = 0;
+	sw_error_t rv = SW_OK;
+
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER1, &phy_data1);
+	SW_RTN_ON_ERROR(rv);
+
+	phy_data &= ~(AQUANTIA_EEE_ADV_1000M | AQUANTIA_EEE_ADV_10000M);
+	if (adv & FAL_PHY_EEE_1000BASE_T) {
+		phy_data |= AQUANTIA_EEE_ADV_1000M;
+	}
+	if (adv & FAL_PHY_EEE_10000BASE_T) {
+		phy_data |= AQUANTIA_EEE_ADV_10000M;
+	}
+
+	phy_data1 &= ~(AQUANTIA_EEE_ADV_2500M | AQUANTIA_EEE_ADV_5000M);
+	if (adv & FAL_PHY_EEE_2500BASE_T) {
+		phy_data1 |= AQUANTIA_EEE_ADV_2500M;
+	}
+	if (adv & FAL_PHY_EEE_5000BASE_T) {
+		phy_data1 |= AQUANTIA_EEE_ADV_5000M;
+	}
+
+	rv = aquantia_phy_reg_write(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER, phy_data);
+	SW_RTN_ON_ERROR(rv);
+	rv = aquantia_phy_reg_write(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER1, phy_data1);
+	SW_RTN_ON_ERROR(rv);
+	rv = aquantia_phy_restart_autoneg(dev_id, phy_id);
+
+	return rv;
+}
+
+/******************************************************************************
+*
+* aquantia_phy_get_eee_advertisement
+*
+* get eee advertisement
+*/
+sw_error_t
+aquantia_phy_get_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_ADV_10000M){
+		*adv |= FAL_PHY_EEE_10000BASE_T;
+	}
+	phy_data = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_ADVERTISTMENT_REGISTER1, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_ADV_2500M) {
+		*adv |= FAL_PHY_EEE_2500BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_ADV_5000M) {
+		*adv |= FAL_PHY_EEE_5000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* aquantia_phy_get_eee_partner_advertisement
+*
+* get eee partner advertisement
+*/
+sw_error_t
+aquantia_phy_get_eee_partner_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_PARTNER_ADVERTISTMENT_REGISTER, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_PARTNER_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_PARTNER_ADV_10000M){
+		*adv |= FAL_PHY_EEE_10000BASE_T;
+	}
+	phy_data = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_AUTONEG,
+		AQUANTIA_EEE_PARTNER_ADVERTISTMENT_REGISTER1, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_PARTNER_ADV_2500M) {
+		*adv |= FAL_PHY_EEE_2500BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_PARTNER_ADV_5000M) {
+		*adv |= FAL_PHY_EEE_5000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* aquantia_phy_get_eee_capability
+*
+* get eee capability
+*/
+sw_error_t
+aquantia_phy_get_eee_cap(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *cap)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*cap = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_PCS_REGISTERS,
+		AQUANTIA_EEE_CAPABILITY_REGISTER, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_CAPABILITY_1000M) {
+		*cap |= FAL_PHY_EEE_1000BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_CAPABILITY_10000M){
+		*cap |= FAL_PHY_EEE_10000BASE_T;
+	}
+	phy_data = 0;
+	rv = aquantia_phy_reg_read(dev_id, phy_id, AQUANTIA_MMD_PCS_REGISTERS,
+		AQUANTIA_EEE_CAPABILITY_REGISTER1, &phy_data);
+	SW_RTN_ON_ERROR(rv);
+
+	if (phy_data & AQUANTIA_EEE_CAPABILITY_2500M) {
+		*cap |= FAL_PHY_EEE_2500BASE_T;
+	}
+	if (phy_data & AQUANTIA_EEE_CAPABILITY_5000M) {
+		*cap |= FAL_PHY_EEE_5000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* aquantia_phy_get_eee_status
+*
+* get eee status
+*/
+sw_error_t
+aquantia_phy_get_eee_status(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *status)
+{
+	a_uint32_t adv = 0, lp_adv = 0;
+	sw_error_t rv = SW_OK;
+
+	rv = aquantia_phy_get_eee_adv(dev_id, phy_id, &adv);
+	SW_RTN_ON_ERROR(rv);
+
+	rv = aquantia_phy_get_eee_partner_adv(dev_id, phy_id, &lp_adv);
+	SW_RTN_ON_ERROR(rv);
+
+	*status = (adv & lp_adv);
+
+	return rv;
+}
+
+/******************************************************************************
+*
 * aquantia_phy_hw_register init to avoid packet loss
 *
 */
@@ -1853,6 +2038,10 @@
 				FAL_PHY_ADV_XGE_SPEED_ALL | FAL_PHY_ADV_100TX_FD |
 				FAL_PHY_ADV_1000T_FD);
 			SW_RTN_ON_ERROR(rv);
+			rv = aquantia_phy_set_eee_adv(dev_id, phy_addr, FAL_PHY_EEE_1000BASE_T
+				| FAL_PHY_EEE_2500BASE_T | FAL_PHY_EEE_5000BASE_T |
+				FAL_PHY_EEE_10000BASE_T);
+			SW_RTN_ON_ERROR(rv);
 		}
 	}
 
@@ -1907,6 +2096,11 @@
 	aquantia_phy_api_ops->phy_interface_mode_set = aquantia_phy_interface_set_mode;
 	aquantia_phy_api_ops->phy_get_status = aquantia_phy_get_status;
 	aquantia_phy_api_ops->phy_counter_show = aquantia_phy_show_counter;
+	aquantia_phy_api_ops->phy_eee_adv_set = aquantia_phy_set_eee_adv;
+	aquantia_phy_api_ops->phy_eee_adv_get = aquantia_phy_get_eee_adv;
+	aquantia_phy_api_ops->phy_eee_partner_adv_get = aquantia_phy_get_eee_partner_adv;
+	aquantia_phy_api_ops->phy_eee_cap_get = aquantia_phy_get_eee_cap;
+	aquantia_phy_api_ops->phy_eee_status_get = aquantia_phy_get_eee_status;
 	ret = hsl_phy_api_ops_register(AQUANTIA_PHY_CHIP, aquantia_phy_api_ops);
 	if (ret == 0)
 		SSDK_INFO("qca probe aquantia phy driver succeeded!\n");
diff --git a/src/hsl/phy/malibu_phy.c b/src/hsl/phy/malibu_phy.c
index ad6d6f6..5853821 100755
--- a/src/hsl/phy/malibu_phy.c
+++ b/src/hsl/phy/malibu_phy.c
@@ -2431,7 +2431,173 @@
 
 	return SW_OK;
 }
+/******************************************************************************
+*
+* malibu_phy_set_eee_advertisement
+*
+* set eee advertisement
+*/
+sw_error_t
+malibu_phy_set_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
 
+	if (phy_id == COMBO_PHY_ID) {
+		if (MALIBU_PHY_MEDIUM_COPPER !=
+		    __phy_active_medium_get(dev_id, phy_id))
+			return SW_NOT_SUPPORTED;
+	}
+
+	phy_data = malibu_phy_mmd_read(dev_id, phy_id, MALIBU_PHY_MMD7_NUM,
+				       MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+	phy_data &= ~(MALIBU_PHY_EEE_ADV_100M | MALIBU_PHY_EEE_ADV_1000M);
+
+	if (adv & FAL_PHY_EEE_100BASE_T) {
+		phy_data |= MALIBU_PHY_EEE_ADV_100M;
+	}
+	if (adv & FAL_PHY_EEE_1000BASE_T) {
+		phy_data |= MALIBU_PHY_EEE_ADV_1000M;
+	}
+
+	rv = malibu_phy_mmd_write(dev_id, phy_id, MALIBU_PHY_MMD7_NUM,
+		     MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_CTRL, phy_data);
+
+	rv = malibu_phy_restart_autoneg(dev_id, phy_id);
+
+	return rv;
+
+}
+
+/******************************************************************************
+*
+* malibu_phy_get_eee_advertisement
+*
+* get eee advertisement
+*/
+sw_error_t
+malibu_phy_get_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	if (phy_id == COMBO_PHY_ID) {
+		if (MALIBU_PHY_MEDIUM_COPPER !=
+		    __phy_active_medium_get(dev_id, phy_id))
+			return SW_NOT_SUPPORTED;
+	}
+
+	*adv = 0;
+	phy_data = malibu_phy_mmd_read(dev_id, phy_id, MALIBU_PHY_MMD7_NUM,
+				       MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+
+	if (phy_data & MALIBU_PHY_EEE_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & MALIBU_PHY_EEE_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* malibu_phy_get_eee_partner_advertisement
+*
+* get eee partner advertisement
+*/
+sw_error_t
+malibu_phy_get_eee_partner_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	if (phy_id == COMBO_PHY_ID) {
+		if (MALIBU_PHY_MEDIUM_COPPER !=
+		    __phy_active_medium_get(dev_id, phy_id))
+			return SW_NOT_SUPPORTED;
+	}
+
+	*adv = 0;
+	phy_data = malibu_phy_mmd_read(dev_id, phy_id, MALIBU_PHY_MMD7_NUM,
+				       MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER);
+
+	if (phy_data & MALIBU_PHY_EEE_PARTNER_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & MALIBU_PHY_EEE_PARTNER_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* malibu_phy_get_eee_capability
+*
+* get eee capability
+*/
+sw_error_t
+malibu_phy_get_eee_cap(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *cap)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	if (phy_id == COMBO_PHY_ID) {
+		if (MALIBU_PHY_MEDIUM_COPPER !=
+		    __phy_active_medium_get(dev_id, phy_id))
+			return SW_NOT_SUPPORTED;
+	}
+
+	*cap = 0;
+	phy_data = malibu_phy_mmd_read(dev_id, phy_id, MALIBU_PHY_MMD3_NUM,
+				       MALIBU_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY);
+
+	if (phy_data & MALIBU_PHY_EEE_CAPABILITY_100M) {
+		*cap |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & MALIBU_PHY_EEE_CAPABILITY_1000M) {
+		*cap |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* malibu_phy_get_eee_status
+*
+* get eee status
+*/
+sw_error_t
+malibu_phy_get_eee_status(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *status)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	if (phy_id == COMBO_PHY_ID) {
+		if (MALIBU_PHY_MEDIUM_COPPER !=
+		    __phy_active_medium_get(dev_id, phy_id))
+			return SW_NOT_SUPPORTED;
+	}
+
+	*status = 0;
+	phy_data = malibu_phy_mmd_read(dev_id, phy_id, MALIBU_PHY_MMD7_NUM,
+				       MALIBU_PHY_MMD7_ADDR_8023AZ_EEE_STATUS);
+
+	if (phy_data & MALIBU_PHY_EEE_STATUS_100M) {
+		*status |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & MALIBU_PHY_EEE_STATUS_1000M) {
+		*status |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
 /******************************************************************************
 *
 * malibu_phy_hw_register init
@@ -2571,6 +2737,11 @@
 	malibu_phy_api_ops->phy_counter_show = malibu_phy_show_counter;
 	malibu_phy_api_ops->phy_serdes_reset = malibu_phy_serdes_reset;
 	malibu_phy_api_ops->phy_get_status = malibu_phy_get_status;
+	malibu_phy_api_ops->phy_eee_adv_set = malibu_phy_set_eee_adv;
+	malibu_phy_api_ops->phy_eee_adv_get = malibu_phy_get_eee_adv;
+	malibu_phy_api_ops->phy_eee_partner_adv_get = malibu_phy_get_eee_partner_adv;
+	malibu_phy_api_ops->phy_eee_cap_get = malibu_phy_get_eee_cap;
+	malibu_phy_api_ops->phy_eee_status_get = malibu_phy_get_eee_status;
 
 	ret = hsl_phy_api_ops_register(MALIBU_PHY_CHIP, malibu_phy_api_ops);
 
diff --git a/src/hsl/phy/qca803x_phy.c b/src/hsl/phy/qca803x_phy.c
index 051a9c2..6a0a006 100755
--- a/src/hsl/phy/qca803x_phy.c
+++ b/src/hsl/phy/qca803x_phy.c
@@ -1817,6 +1817,142 @@
 
 	return SW_OK;
 }
+/******************************************************************************
+*
+* qca803x_phy_set_eee_advertisement
+*
+* set eee advertisement
+*/
+sw_error_t
+qca803x_phy_set_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	phy_data = qca803x_phy_mmd_read(dev_id, phy_id, QCA803X_PHY_MMD7_NUM,
+				       QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+	phy_data &= ~(QCA803X_PHY_EEE_ADV_100M | QCA803X_PHY_EEE_ADV_1000M);
+
+	if (adv & FAL_PHY_EEE_100BASE_T) {
+		phy_data |= QCA803X_PHY_EEE_ADV_100M;
+	}
+	if (adv & FAL_PHY_EEE_1000BASE_T) {
+		phy_data |= QCA803X_PHY_EEE_ADV_1000M;
+	}
+
+	rv = qca803x_phy_mmd_write(dev_id, phy_id, QCA803X_PHY_MMD7_NUM,
+		     QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL, phy_data);
+
+	rv = qca803x_phy_restart_autoneg(dev_id, phy_id);
+
+	return rv;
+}
+
+/******************************************************************************
+*
+* qca803x_phy_get_eee_advertisement
+*
+* get eee advertisement
+*/
+sw_error_t
+qca803x_phy_get_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	phy_data = qca803x_phy_mmd_read(dev_id, phy_id, QCA803X_PHY_MMD7_NUM,
+				       QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+
+	if (phy_data & QCA803X_PHY_EEE_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA803X_PHY_EEE_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca803x_phy_get_eee_partner_advertisement
+*
+* get eee partner advertisement
+*/
+sw_error_t
+qca803x_phy_get_eee_partner_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	phy_data = qca803x_phy_mmd_read(dev_id, phy_id, QCA803X_PHY_MMD7_NUM,
+				       QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER);
+
+	if (phy_data & QCA803X_PHY_EEE_PARTNER_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA803X_PHY_EEE_PARTNER_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca803x_phy_get_eee_capability
+*
+* get eee capability
+*/
+sw_error_t
+qca803x_phy_get_eee_cap(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *cap)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*cap = 0;
+	phy_data = qca803x_phy_mmd_read(dev_id, phy_id, QCA803X_PHY_MMD3_NUM,
+				       QCA803X_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY);
+
+	if (phy_data & QCA803X_PHY_EEE_CAPABILITY_100M) {
+		*cap |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA803X_PHY_EEE_CAPABILITY_1000M) {
+		*cap |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca803x_phy_get_eee_status
+*
+* get eee status
+*/
+sw_error_t
+qca803x_phy_get_eee_status(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *status)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*status = 0;
+	phy_data = qca803x_phy_mmd_read(dev_id, phy_id, QCA803X_PHY_MMD7_NUM,
+				       QCA803X_PHY_MMD7_ADDR_8023AZ_EEE_STATUS);
+
+	if (phy_data & QCA803X_PHY_EEE_STATUS_100M) {
+		*status |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA803X_PHY_EEE_STATUS_1000M) {
+		*status |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
 
 static sw_error_t qca803x_phy_api_ops_init(void)
 {
@@ -1881,6 +2017,11 @@
 	qca803x_phy_api_ops->phy_combo_fiber_mode_set = qca803x_phy_set_combo_fiber_mode;
 	qca803x_phy_api_ops->phy_combo_fiber_mode_get = qca803x_phy_get_combo_fiber_mode;
 	qca803x_phy_api_ops->phy_get_status = qca803x_phy_get_status;
+	qca803x_phy_api_ops->phy_eee_adv_set = qca803x_phy_set_eee_adv;
+	qca803x_phy_api_ops->phy_eee_adv_get = qca803x_phy_get_eee_adv;
+	qca803x_phy_api_ops->phy_eee_partner_adv_get = qca803x_phy_get_eee_partner_adv;
+	qca803x_phy_api_ops->phy_eee_cap_get = qca803x_phy_get_eee_cap;
+	qca803x_phy_api_ops->phy_eee_status_get = qca803x_phy_get_eee_status;
 
 	ret = hsl_phy_api_ops_register(QCA803X_PHY_CHIP, qca803x_phy_api_ops);
 
diff --git a/src/hsl/phy/qca808x_phy.c b/src/hsl/phy/qca808x_phy.c
index 3e1f8bb..32ba662 100755
--- a/src/hsl/phy/qca808x_phy.c
+++ b/src/hsl/phy/qca808x_phy.c
@@ -1709,6 +1709,142 @@
 
 	return SW_OK;
 }
+/******************************************************************************
+*
+* qca808x_phy_set_eee_advertisement
+*
+* set eee advertisement
+*/
+sw_error_t
+qca808x_phy_set_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	phy_data = qca808x_phy_mmd_read(dev_id, phy_id, QCA808X_PHY_MMD7_NUM,
+				       QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+	phy_data &= ~(QCA808X_PHY_EEE_ADV_100M | QCA808X_PHY_EEE_ADV_1000M);
+
+	if (adv & FAL_PHY_EEE_100BASE_T) {
+		phy_data |= QCA808X_PHY_EEE_ADV_100M;
+	}
+	if (adv & FAL_PHY_EEE_1000BASE_T) {
+		phy_data |= QCA808X_PHY_EEE_ADV_1000M;
+	}
+
+	rv = qca808x_phy_mmd_write(dev_id, phy_id, QCA808X_PHY_MMD7_NUM,
+		     QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL, phy_data);
+
+	rv = qca808x_phy_restart_autoneg(dev_id, phy_id);
+
+	return rv;
+}
+
+/******************************************************************************
+*
+* qca808x_phy_get_eee_advertisement
+*
+* get eee advertisement
+*/
+sw_error_t
+qca808x_phy_get_eee_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	phy_data = qca808x_phy_mmd_read(dev_id, phy_id, QCA808X_PHY_MMD7_NUM,
+				       QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_CTRL);
+
+	if (phy_data & QCA808X_PHY_EEE_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA808X_PHY_EEE_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca808x_phy_get_eee_partner_advertisement
+*
+* get eee partner advertisement
+*/
+sw_error_t
+qca808x_phy_get_eee_partner_adv(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *adv)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*adv = 0;
+	phy_data = qca808x_phy_mmd_read(dev_id, phy_id, QCA808X_PHY_MMD7_NUM,
+				       QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_PARTNER);
+
+	if (phy_data & QCA808X_PHY_EEE_PARTNER_ADV_100M) {
+		*adv |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA808X_PHY_EEE_PARTNER_ADV_1000M) {
+		*adv |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca808x_phy_get_eee_capability
+*
+* get eee capability
+*/
+sw_error_t
+qca808x_phy_get_eee_cap(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *cap)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*cap = 0;
+	phy_data = qca808x_phy_mmd_read(dev_id, phy_id, QCA808X_PHY_MMD3_NUM,
+				       QCA808X_PHY_MMD3_ADDR_8023AZ_EEE_CAPABILITY);
+
+	if (phy_data & QCA808X_PHY_EEE_CAPABILITY_100M) {
+		*cap |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA808X_PHY_EEE_CAPABILITY_1000M) {
+		*cap |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
+/******************************************************************************
+*
+* qca808x_phy_get_eee_status
+*
+* get eee status
+*/
+sw_error_t
+qca808x_phy_get_eee_status(a_uint32_t dev_id, a_uint32_t phy_id,
+	a_uint32_t *status)
+{
+	a_uint16_t phy_data = 0;
+	sw_error_t rv = SW_OK;
+
+	*status = 0;
+	phy_data = qca808x_phy_mmd_read(dev_id, phy_id, QCA808X_PHY_MMD7_NUM,
+				       QCA808X_PHY_MMD7_ADDR_8023AZ_EEE_STATUS);
+
+	if (phy_data & QCA808X_PHY_EEE_STATUS_100M) {
+		*status |= FAL_PHY_EEE_100BASE_T;
+	}
+	if (phy_data & QCA808X_PHY_EEE_STATUS_1000M) {
+		*status |= FAL_PHY_EEE_1000BASE_T;
+	}
+
+	return rv;
+}
 
 static sw_error_t
 qca808x_phy_hw_init(a_uint32_t dev_id,  a_uint32_t port_bmp)
@@ -1795,6 +1931,11 @@
 	qca808x_phy_api_ops->phy_counter_set = qca808x_phy_set_counter;
 	qca808x_phy_api_ops->phy_counter_get = qca808x_phy_get_counter;
 	qca808x_phy_api_ops->phy_counter_show = qca808x_phy_show_counter;
+	qca808x_phy_api_ops->phy_eee_adv_set = qca808x_phy_set_eee_adv;
+	qca808x_phy_api_ops->phy_eee_adv_get = qca808x_phy_get_eee_adv;
+	qca808x_phy_api_ops->phy_eee_partner_adv_get = qca808x_phy_get_eee_partner_adv;
+	qca808x_phy_api_ops->phy_eee_cap_get = qca808x_phy_get_eee_cap;
+	qca808x_phy_api_ops->phy_eee_status_get = qca808x_phy_get_eee_status;
 
 /*qca808x_end*/
 #if defined(IN_PTP)
diff --git a/src/shell_lib/shell_config.c b/src/shell_lib/shell_config.c
index 8bb3935..39083e5 100755
--- a/src/shell_lib/shell_config.c
+++ b/src/shell_lib/shell_config.c
@@ -660,6 +660,7 @@
 	{"frameMaxSize", "set",   SW_API_PT_FRAME_MAX_SIZE_SET, NULL},
 	{"interface3az", "set", SW_API_PT_INTERFACE_3AZ_STATUS_SET, NULL},
 	{"promiscmode", "set",   SW_API_PT_PROMISC_MODE_SET, NULL},
+	{"eeecfg", "set", SW_API_PT_INTERFACE_EEE_CFG_SET, NULL},
 	#endif
 	{NULL, NULL,  (int)NULL, NULL},/*end of desc*/
 };
diff --git a/src/shell_lib/shell_io.c b/src/shell_lib/shell_io.c
index 7dd9981..6d72dac 100755
--- a/src/shell_lib/shell_io.c
+++ b/src/shell_lib/shell_io.c
@@ -128,6 +128,7 @@
 	SW_TYPE_DEF(SW_DUPLEX, cmd_data_check_duplex, NULL),
     SW_TYPE_DEF(SW_SPEED, cmd_data_check_speed, NULL),
     SW_TYPE_DEF(SW_CAP, cmd_data_check_capable, NULL),
+    SW_TYPE_DEF(SW_PORT_EEE_CONFIG, (param_check_t)cmd_data_check_port_eee_config, NULL),
 	#endif
 	#ifdef IN_PORTVLAN
     SW_TYPE_DEF(SW_1QMODE, cmd_data_check_1qmode, NULL),
@@ -603,6 +604,180 @@
 
     return SW_OK;
 }
+sw_error_t
+cmd_data_check_port_eee_config(char *cmd_str, void * val, a_uint32_t size)
+{
+    char *cmd;
+    sw_error_t rv;
+    fal_port_eee_cfg_t cfg;
+
+    aos_mem_zero(&cfg, sizeof (fal_port_eee_cfg_t));
+
+    do
+    {
+        cmd = get_sub_cmd("eee_enable", "yes");
+        SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_confirm(cmd, A_FALSE, &(cfg.enable),
+                                        sizeof (a_bool_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+    do
+    {
+        cmd = get_sub_cmd("eee_capability", "0xffff");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.capability), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("lpi_sleep_timer", "256");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.lpi_sleep_timer), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("advertisement", "0xffff");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.advertisement), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+
+    do
+    {
+        cmd = get_sub_cmd("lpi_tx_enable", "1");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.lpi_tx_enable), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("eee_status", "0xffff");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.eee_status), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("lpi_wakeup_timer", "32");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.lpi_wakeup_timer), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    do
+    {
+        cmd = get_sub_cmd("link_partner_advertisement", "0xffff");
+		SW_RTN_ON_NULL_PARAM(cmd);
+
+        if (!strncasecmp(cmd, "quit", 4))
+        {
+            return SW_BAD_VALUE;
+        }
+        else if (!strncasecmp(cmd, "help", 4))
+        {
+            rv = SW_BAD_VALUE;
+        }
+        else
+        {
+            rv = cmd_data_check_uint32(cmd, &(cfg.link_partner_advertisement), sizeof (a_uint32_t));
+        }
+    }
+    while (talk_mode && (SW_OK != rv));
+
+    *(fal_port_eee_cfg_t *)val = cfg;
+    return SW_OK;
+}
 
 #ifndef IN_PORTCONTROL_MINI