Merge changes 
diff --git a/config b/config
index 5d811bb..15f580c 100755
--- a/config
+++ b/config
@@ -236,6 +236,11 @@
 else
 IN_SFE=FALSE
 endif
+ifeq ($(IN_QCA808X_PHY), TRUE)
+IN_PHY_I2C_MODE=TRUE
+else
+IN_PHY_I2C_MODE=FALSE
+endif
 IN_VSI=TRUE
 IN_CTRLPKT=TRUE
 IN_SERVCODE=TRUE
diff --git a/include/api/sw_ioctl.h b/include/api/sw_ioctl.h
index 974cd5e..3c12b27 100644
--- a/include/api/sw_ioctl.h
+++ b/include/api/sw_ioctl.h
@@ -885,6 +885,8 @@
 #define SW_API_PHY_DUMP             (13  + SW_API_DEBUG_OFFSET)
 #define SW_API_UNIPHY_REG_GET             (20  + SW_API_DEBUG_OFFSET)
 #define SW_API_UNIPHY_REG_SET             (21  + SW_API_DEBUG_OFFSET)
+#define SW_API_PHY_I2C_GET                (22  + SW_API_DEBUG_OFFSET)
+#define SW_API_PHY_I2C_SET                (23  + SW_API_DEBUG_OFFSET)
 
 #define SW_API_MAX                 0xffff
 
diff --git a/include/hsl/hsl.h b/include/hsl/hsl.h
index a580aed..6f036ef 100755
--- a/include/hsl/hsl.h
+++ b/include/hsl/hsl.h
@@ -103,6 +103,14 @@
 #define HSL_PHY_SET(rv, dev, phy_addr, reg, value) \
 		rv = reduce_hsl_phy_set(dev,phy_addr,reg,value);
 
+extern sw_error_t hsl_phy_i2c_get(a_uint32_t dev,a_uint32_t phy_addr,a_uint32_t reg,a_uint16_t* value);
+#define HSL_PHY_I2C_GET(rv, dev, phy_addr, reg, value) \
+		rv = hsl_phy_i2c_get(dev,phy_addr,reg,value);
+
+
+extern sw_error_t hsl_phy_i2c_set(a_uint32_t dev,a_uint32_t phy_addr,a_uint32_t reg,a_uint16_t value);
+#define HSL_PHY_I2C_SET(rv, dev, phy_addr, reg, value) \
+		rv = hsl_phy_i2c_set(dev,phy_addr,reg,value);
 
 
 
diff --git a/include/hsl/hsl_api.h b/include/hsl/hsl_api.h
index 34f1cb2..3d18444 100755
--- a/include/hsl/hsl_api.h
+++ b/include/hsl/hsl_api.h
@@ -2570,6 +2570,8 @@
       /*INIT*/ hsl_dev_reset dev_reset;
     hsl_dev_clean dev_clean;
     hsl_dev_access_set dev_access_set;
+    hsl_phy_get phy_i2c_get;
+    hsl_phy_set phy_i2c_set;
   } hsl_api_t;
 
   hsl_api_t *hsl_api_ptr_get (a_uint32_t dev_id);
diff --git a/include/hsl/phy/hsl_phy.h b/include/hsl/phy/hsl_phy.h
index d3276a6..59761e0 100755
--- a/include/hsl/phy/hsl_phy.h
+++ b/include/hsl/phy/hsl_phy.h
@@ -298,6 +298,10 @@
 	a_uint32_t phy_address[SW_MAX_NR_PORT];
 	a_uint32_t phy_address_from_dts[SW_MAX_NR_PORT];
 	a_uint32_t phy_type[SW_MAX_NR_PORT];
+	/* fake mdio address is used to register the phy device,
+	 * when the phy is not accessed by the MDIO bus.
+	 * */
+	a_uint32_t phy_mdio_fake_address[SW_MAX_NR_PORT];
 	a_uint8_t phy_access_type[SW_MAX_NR_PORT];
 	a_bool_t phy_c45[SW_MAX_NR_PORT];
 	a_bool_t phy_combo[SW_MAX_NR_PORT];
@@ -330,6 +334,8 @@
 #define CABLE_PAIR_C  2
 #define CABLE_PAIR_D  3
 
+#define PHY_I2C_ACCESS 1
+
 sw_error_t
 hsl_phy_api_ops_register(phy_type_t phy_type, hsl_phy_ops_t * phy_api_ops);
 
@@ -355,6 +361,15 @@
 a_uint32_t
 qca_ssdk_port_to_phy_addr(a_uint32_t dev_id, a_uint32_t port_id);
 
+a_uint32_t
+qca_ssdk_port_to_phy_mdio_fake_addr(a_uint32_t dev_id, a_uint32_t port_id);
+
+a_uint32_t
+qca_ssdk_phy_mdio_fake_addr_to_port(a_uint32_t dev_id, a_uint32_t phy_addr);
+
+void qca_ssdk_phy_mdio_fake_address_set(a_uint32_t dev_id, a_uint32_t i,
+				a_uint32_t value);
+
 void qca_ssdk_port_bmp_set(a_uint32_t dev_id, a_uint32_t value);
 
 a_uint32_t qca_ssdk_port_bmp_get(a_uint32_t dev_id);
diff --git a/include/hsl/phy/qca808x_phy.h b/include/hsl/phy/qca808x_phy.h
index fe400d9..721ffc9 100755
--- a/include/hsl/phy/qca808x_phy.h
+++ b/include/hsl/phy/qca808x_phy.h
@@ -210,6 +210,7 @@
 
 #define QCA808X_STATUS_1000X_FD_CAPS             0x8000
 
+#define QCA808X_MMD1_PMA_CAP_REG                 0x4
 	/* MMD1 2500T capabilities */
 #define QCA808X_STATUS_2500T_FD_CAPS             0x2000
 
@@ -373,6 +374,28 @@
 #define QCA808X_PHY_FRAME_CHECK_EN              0x0001
 #define QCA808X_PHY_XMIT_MAC_CNT_SELFCLR        0x0002
 
+a_uint16_t
+qca808x_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg_id);
+
+sw_error_t
+qca808x_phy_reg_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t
+reg_id, a_uint16_t reg_val);
+
+sw_error_t
+qca808x_phy_debug_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_id,
+		       a_uint16_t reg_val);
+a_uint16_t
+qca808x_phy_debug_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_id);
+
+sw_error_t
+qca808x_phy_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id,
+		a_uint16_t mmd_num, a_uint16_t reg_id, a_uint16_t
+reg_val);
+
+a_uint16_t
+qca808x_phy_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id,
+		a_uint16_t mmd_num, a_uint16_t reg_id);
+
 sw_error_t
 qca808x_phy_set_duplex (a_uint32_t dev_id, a_uint32_t phy_id,
 		   fal_port_duplex_t duplex);
@@ -424,6 +447,20 @@
 qca808x_phy_get_phy_id(a_uint32_t dev_id, a_uint32_t phy_id,
 		a_uint16_t * org_id, a_uint16_t * rev_id);
 
+sw_error_t
+qca808x_phy_get_status(a_uint32_t dev_id, a_uint32_t phy_id,
+		struct port_phy_status *phy_status);
+
+sw_error_t
+qca808x_phy_interface_get_mode_status(a_uint32_t dev_id, a_uint32_t phy_id,
+		fal_port_interface_mode_t *interface_mode_status);
+
+sw_error_t qca808x_phy_reset(a_uint32_t dev_id, a_uint32_t phy_id);
+
+sw_error_t
+qca808x_phy_set_force_speed(a_uint32_t dev_id, a_uint32_t phy_id,
+		     fal_port_speed_t speed);
+
 int qca808x_phy_init(a_uint32_t dev_id, a_uint32_t port_bmp);
 
 #ifdef __cplusplus
diff --git a/include/init/ssdk_init.h b/include/init/ssdk_init.h
index da71744..40e8fe8 100755
--- a/include/init/ssdk_init.h
+++ b/include/init/ssdk_init.h
@@ -66,6 +66,14 @@
                      a_uint16_t * data);
 
     typedef sw_error_t
+    (*i2c_reg_set) (a_uint32_t dev_id, a_uint32_t phy_addr, a_uint32_t reg,
+                     a_uint16_t data);
+
+    typedef sw_error_t
+    (*i2c_reg_get) (a_uint32_t dev_id, a_uint32_t phy_addr, a_uint32_t reg,
+                     a_uint16_t * data);
+
+    typedef sw_error_t
     (*hdr_reg_set) (a_uint32_t dev_id, a_uint32_t reg_addr, a_uint8_t *reg_data, a_uint32_t len);
 
     typedef sw_error_t
@@ -123,6 +131,8 @@
         uniphy_reg_get     uniphy_reg_get;
 	mii_reg_set	mii_reg_set;
 	mii_reg_get	mii_reg_get;
+        i2c_reg_set    i2c_set;
+        i2c_reg_get    i2c_get;
     } hsl_reg_func;
 
     typedef struct
diff --git a/include/sal/sd/sd.h b/include/sal/sd/sd.h
index c32d9eb..4c6bb2d 100755
--- a/include/sal/sd/sd.h
+++ b/include/sal/sd/sd.h
@@ -30,6 +30,14 @@
                     a_uint16_t * data);
 
     sw_error_t
+    sd_reg_i2c_set(a_uint32_t dev_id, a_uint32_t phy, a_uint32_t reg,
+                    a_uint16_t data);
+
+    sw_error_t
+    sd_reg_i2c_get(a_uint32_t dev_id, a_uint32_t phy, a_uint32_t reg,
+                    a_uint16_t * data);
+
+    sw_error_t
     sd_reg_hdr_set(a_uint32_t dev_id, a_uint32_t reg_addr,
                    a_uint8_t * reg_data, a_uint32_t len);
 
diff --git a/make/linux_opt.mk b/make/linux_opt.mk
index fae3406..d88a9cf 100755
--- a/make/linux_opt.mk
+++ b/make/linux_opt.mk
@@ -171,6 +171,10 @@
   MODULE_CFLAG += -DIN_SFP_PHY
 endif
 
+ifeq (TRUE, $(IN_PHY_I2C_MODE))
+  MODULE_CFLAG += -DIN_PHY_I2C_MODE
+endif
+
 ifeq (TRUE, $(IN_VSI))
   MODULE_CFLAG += -DIN_VSI
 endif
diff --git a/src/hsl/hppe/hppe_init.c b/src/hsl/hppe/hppe_init.c
index d20318c..47e2199 100755
--- a/src/hsl/hppe/hppe_init.c
+++ b/src/hsl/hppe/hppe_init.c
@@ -189,6 +189,8 @@
 		p_api->reg_set = sd_reg_hdr_set;
 		p_api->phy_get = sd_reg_mdio_get;
 		p_api->phy_set = sd_reg_mdio_set;
+		p_api->phy_i2c_get = sd_reg_i2c_get;
+		p_api->phy_i2c_set = sd_reg_i2c_set;
 		p_api->uniphy_reg_get = sd_reg_uniphy_get;
 		p_api->uniphy_reg_set = sd_reg_uniphy_set;
 
diff --git a/src/hsl/hsl_dev.c b/src/hsl/hsl_dev.c
index c8b794c..f6e6286 100755
--- a/src/hsl/hsl_dev.c
+++ b/src/hsl/hsl_dev.c
@@ -609,6 +609,34 @@
 	return rv;
 }
 
+sw_error_t hsl_phy_i2c_set(a_uint32_t dev,a_uint32_t phy_addr,a_uint32_t reg,a_uint16_t value)
+{
+	sw_error_t rv;
+
+	hsl_api_t *p_api = hsl_api_ptr_get(dev);
+	if (p_api) {
+	    rv = p_api->phy_i2c_set(dev, phy_addr, reg, value);
+	} else {
+	    rv = SW_NOT_INITIALIZED;
+	}
+
+	return rv;
+}
+
+sw_error_t hsl_phy_i2c_get(a_uint32_t dev,a_uint32_t phy_addr,a_uint32_t reg,a_uint16_t* value)
+{
+	sw_error_t rv;
+
+	hsl_api_t *p_api = hsl_api_ptr_get(dev);
+	if (p_api) {
+	    rv = p_api->phy_i2c_get(dev, phy_addr, reg, value);
+	} else {
+	    rv = SW_NOT_INITIALIZED;
+	}
+
+	return rv;
+}
+
 #if 0
 void reduce_sw_set_reg_by_field_u32(unsigned int reg_value,unsigned int field_value,
 													unsigned int reg_offset,unsigned int reg_len)
diff --git a/src/hsl/phy/hsl_phy.c b/src/hsl/phy/hsl_phy.c
index 1ff44f3..0caf7e2 100755
--- a/src/hsl/phy/hsl_phy.c
+++ b/src/hsl/phy/hsl_phy.c
@@ -151,14 +151,24 @@
 	if (phy_info[dev_id]->phy_c45[port_id] == A_TRUE)
 		reg_pad = BIT(30) | BIT(16);
 
-	cfg->reg_func.mdio_get(dev_id,
-			phy_info[dev_id]->phy_address[port_id], reg_pad | 2, &org_id);
-	cfg->reg_func.mdio_get(dev_id,
-			phy_info[dev_id]->phy_address[port_id], reg_pad | 3, &rev_id);
+#if defined(IN_PHY_I2C_MODE)
+	if (hsl_port_phy_access_type_get(dev_id, port_id) == PHY_I2C_ACCESS) {
+		cfg->reg_func.i2c_get(dev_id,
+				phy_info[dev_id]->phy_address[port_id], reg_pad | 2, &org_id);
+		cfg->reg_func.i2c_get(dev_id,
+				phy_info[dev_id]->phy_address[port_id], reg_pad | 3, &rev_id);
+	}
+	else
+#endif
+	{
+		cfg->reg_func.mdio_get(dev_id,
+				phy_info[dev_id]->phy_address[port_id], reg_pad | 2, &org_id);
+		cfg->reg_func.mdio_get(dev_id,
+				phy_info[dev_id]->phy_address[port_id], reg_pad | 3, &rev_id);
+	}
 
 	phy_id = (org_id<<16) | rev_id;
 
-
 	return phy_id;
 }
 
@@ -336,7 +346,7 @@
 {
 	 phy_info[dev_id]->phy_address[port_id] = phy_addr;
 
-	return;
+	 return;
 }
 
 a_uint32_t
@@ -346,6 +356,33 @@
 	 return phy_info[dev_id]->phy_address_from_dts[port_id];
 }
 
+a_uint32_t
+qca_ssdk_port_to_phy_mdio_fake_addr(a_uint32_t dev_id, a_uint32_t port_id)
+{
+	return phy_info[dev_id]->phy_mdio_fake_address[port_id];
+}
+
+void qca_ssdk_phy_mdio_fake_address_set(a_uint32_t dev_id, a_uint32_t i,
+			a_uint32_t value)
+{
+	phy_info[dev_id]->phy_mdio_fake_address[i] = value;
+
+	return;
+}
+
+a_uint32_t
+qca_ssdk_phy_mdio_fake_addr_to_port(a_uint32_t dev_id, a_uint32_t phy_mdio_fake_addr)
+{
+	a_uint32_t i = 0;
+
+	for (i = 0; i < SW_MAX_NR_PORT; i ++)
+	{
+		if (phy_info[dev_id]->phy_mdio_fake_address[i] == phy_mdio_fake_addr)
+			return i;
+	}
+	SSDK_ERROR("doesn't match port_id to specified phy_mdio_fake_addr !\n");
+	return 0;
+}
 
 a_uint32_t
 qca_ssdk_port_to_phy_addr(a_uint32_t dev_id, a_uint32_t port_id)
diff --git a/src/hsl/phy/qca808x_phy.c b/src/hsl/phy/qca808x_phy.c
index a0dab3e..6ee018e 100755
--- a/src/hsl/phy/qca808x_phy.c
+++ b/src/hsl/phy/qca808x_phy.c
@@ -279,11 +279,11 @@
 
 /******************************************************************************
 *
-* _qca808x_phy_set_force_speed - Force the speed of qca808x phy ports associated with the
+* qca808x_phy_set_force_speed - Force the speed of qca808x phy ports associated with the
 * specified device.
 */
 sw_error_t
-_qca808x_phy_set_force_speed(a_uint32_t dev_id, a_uint32_t phy_id,
+qca808x_phy_set_force_speed(a_uint32_t dev_id, a_uint32_t phy_id,
 		     fal_port_speed_t speed)
 {
 	a_uint16_t phy_data1 = 0;
@@ -392,7 +392,7 @@
 		case FAL_SPEED_100:
 		case FAL_SPEED_10:
 			/* set qca808x phy speed by pma control registers */
-			rv = _qca808x_phy_set_force_speed(dev_id, phy_id, speed);
+			rv = qca808x_phy_set_force_speed(dev_id, phy_id, speed);
 			PHY_RTN_ON_ERROR(rv);
 			rv = qca808x_phy_get_duplex(dev_id, phy_id, &old_duplex);
 			PHY_RTN_ON_ERROR(rv);
@@ -457,7 +457,7 @@
 		case FAL_SPEED_100:
 		case FAL_SPEED_10:
 			/* force the speed */
-			rv = _qca808x_phy_set_force_speed(dev_id, phy_id, old_speed);
+			rv = qca808x_phy_set_force_speed(dev_id, phy_id, old_speed);
 			PHY_RTN_ON_ERROR(rv);
 			phy_data &= ~QCA808X_CTRL_AUTONEGOTIATION_ENABLE;
 			if (duplex == FAL_FULL_DUPLEX) {
@@ -769,7 +769,7 @@
 		 * speed to enable local loopback */
 		rv = qca808x_phy_get_speed(dev_id, phy_id, &old_speed);
 		PHY_RTN_ON_ERROR(rv);
-		rv = _qca808x_phy_set_force_speed(dev_id, phy_id, old_speed);
+		rv = qca808x_phy_set_force_speed(dev_id, phy_id, old_speed);
 		PHY_RTN_ON_ERROR(rv);
 
 		phy_data &= ~QCA808X_CTRL_AUTONEGOTIATION_ENABLE;
diff --git a/src/hsl/phy/sfp_phy.c b/src/hsl/phy/sfp_phy.c
index f55caa4..b8bf02d 100755
--- a/src/hsl/phy/sfp_phy.c
+++ b/src/hsl/phy/sfp_phy.c
@@ -100,7 +100,8 @@
 	.driver		= { .owner = THIS_MODULE },
 #endif
 };
-static int sfp_phy_device_setup(a_uint32_t dev_id, a_uint32_t port)
+
+int sfp_phy_device_setup(a_uint32_t dev_id, a_uint32_t port, a_uint32_t phy_id)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
 	struct phy_device *phydev;
@@ -111,10 +112,17 @@
 
 	priv = ssdk_phy_priv_data_get(dev_id);
 	/*create phy device*/
-	addr = qca_ssdk_port_to_phy_addr(dev_id, port);
+#if defined(IN_PHY_I2C_MODE)
+	if (hsl_port_phy_access_type_get(dev_id, port) == PHY_I2C_ACCESS) {
+		addr = qca_ssdk_port_to_phy_mdio_fake_addr(dev_id, port);
+	} else
+#endif
+	{
+		addr = qca_ssdk_port_to_phy_addr(dev_id, port);
+	}
 	bus = ssdk_miibus_get_by_device(dev_id);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
-	phydev = phy_device_create(bus, addr, SFP_PHY, false, NULL);
+	phydev = phy_device_create(bus, addr, phy_id, false, NULL);
 	if (IS_ERR(phydev) || phydev == NULL) {
 		SSDK_ERROR("Failed to create phy device!\n");
 		return SW_NOT_SUPPORTED;
@@ -127,7 +135,7 @@
 	return 0;
 }
 
-static void sfp_phy_device_remove(a_uint32_t dev_id, a_uint32_t port)
+void sfp_phy_device_remove(a_uint32_t dev_id, a_uint32_t port)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
 	struct phy_device *phydev = NULL;
@@ -136,7 +144,14 @@
 	struct mii_bus *bus;
 
 	bus = ssdk_miibus_get_by_device(dev_id);
-	addr = qca_ssdk_port_to_phy_addr(dev_id, port);
+#if defined(IN_PHY_I2C_MODE)
+	if (hsl_port_phy_access_type_get(dev_id, port) == PHY_I2C_ACCESS) {
+		addr = qca_ssdk_port_to_phy_mdio_fake_addr(dev_id, port);
+	} else
+#endif
+	{
+		addr = qca_ssdk_port_to_phy_addr(dev_id, port);
+	}
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
 	if (addr < PHY_MAX_ADDR)
@@ -154,7 +169,7 @@
 
 	for (port_id = 0; port_id < SW_MAX_NR_PORT; port_id ++) {
 		if (port_bmp & (0x1 << port_id)) {
-			sfp_phy_device_setup(dev_id, port_id);
+			sfp_phy_device_setup(dev_id, port_id, SFP_PHY);
 		}
 	}
 
diff --git a/src/init/Makefile b/src/init/Makefile
index 906b5ba..7e85875 100755
--- a/src/init/Makefile
+++ b/src/init/Makefile
@@ -6,11 +6,15 @@
 SRC_LIST=ssdk_init.c ssdk_plat.c ssdk_interrupt.c ssdk_clk.c ssdk_dts.c
 
 ifneq (,$(findstring HPPE, $(SUPPORT_CHIP)))
-SRC_LIST+=ssdk_hppe.c
+	SRC_LIST += ssdk_hppe.c
 endif
 
 ifeq (TRUE, $(SWCONFIG))
-SRC_LIST+=ssdk_uci.c
+	SRC_LIST += ssdk_uci.c
+endif
+
+ifeq (TRUE, $(IN_PHY_I2C_MODE))
+	SRC_LIST += ssdk_phy_i2c.c
 endif
 
 include $(PRJ_PATH)/make/components.mk
diff --git a/src/init/ssdk_dts.c b/src/init/ssdk_dts.c
index a06708e..f878280 100755
--- a/src/init/ssdk_dts.c
+++ b/src/init/ssdk_dts.c
@@ -482,8 +482,8 @@
 {
 	struct device_node *phy_info_node, *port_node;
 	ssdk_port_phyinfo *port_phyinfo;
-	a_uint32_t port_id, phy_addr;
-	a_bool_t phy_c45, phy_combo;
+	a_uint32_t port_id, phy_addr, phy_i2c_addr;
+	a_bool_t phy_c45, phy_combo, phy_i2c;
 	const char *mac_type = NULL;
 	sw_error_t rv = SW_OK;
 
@@ -502,10 +502,27 @@
 				"ethernet-phy-ieee802.3-c45");
 		phy_combo = of_property_read_bool(port_node,
 				"ethernet-phy-combo");
+		phy_i2c = of_property_read_bool(port_node,
+				"phy-i2c-mode");
+
+		if (phy_i2c) {
+			SSDK_INFO("[PORT %d] phy-i2c-mode\n", port_id);
+			hsl_port_phy_access_type_set(dev_id, port_id, PHY_I2C_ACCESS);
+			if (of_property_read_u32(port_node, "phy_i2c_address",
+						&phy_i2c_addr)) {
+				return SW_BAD_VALUE;
+			}
+			/* phy_i2c_address is the i2c slave addr */
+			hsl_phy_address_init(dev_id, port_id, phy_i2c_addr);
+			/* phy_address is the mdio addr,
+			 * which is a fake mdio addr in i2c mode */
+			qca_ssdk_phy_mdio_fake_address_set(dev_id, port_id, phy_addr);
+		} else {
+			hsl_phy_address_init(dev_id, port_id, phy_addr);
+		}
 
 		hsl_port_phy_combo_capability_set(dev_id, port_id, phy_combo);
 		hsl_port_phy_c45_capability_set(dev_id, port_id, phy_c45);
-		hsl_phy_address_init(dev_id, port_id, phy_addr);
 
 		port_phyinfo = ssdk_port_phyinfo_get(dev_id, port_id);
 		if (port_phyinfo) {
@@ -519,6 +536,10 @@
 				port_phyinfo->phy_features |= PHY_F_COMBO;
 			}
 
+			if (phy_i2c) {
+				port_phyinfo->phy_features |= PHY_F_I2C;
+			}
+
 			if (!of_property_read_string(port_node, "port_mac_sel", &mac_type))
 			{
 				SSDK_INFO("[PORT %d] port_mac_sel = %s\n", port_id, mac_type);
diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c
index 1cb105d..cc045c9 100755
--- a/src/init/ssdk_init.c
+++ b/src/init/ssdk_init.c
@@ -97,6 +97,10 @@
 #include "ssdk_uci.h"
 #endif
 
+#if defined(IN_PHY_I2C_MODE)
+#include "ssdk_phy_i2c.h"
+#endif
+
 #ifdef IN_IP
 #if defined (CONFIG_NF_FLOW_COOKIE)
 #include "fal_flowcookie.h"
@@ -2881,6 +2885,10 @@
 	cfg->nl_prot = 30;
 	cfg->reg_func.mdio_set = qca_ar8327_phy_write;
 	cfg->reg_func.mdio_get = qca_ar8327_phy_read;
+#if defined(IN_PHY_I2C_MODE)
+	cfg->reg_func.i2c_set = qca_phy_i2c_write;
+	cfg->reg_func.i2c_get = qca_phy_i2c_read;
+#endif
 	cfg->reg_func.header_reg_set = qca_switch_reg_write;
 	cfg->reg_func.header_reg_get = qca_switch_reg_read;
 	cfg->reg_func.mii_reg_set = qca_ar8216_mii_write;
diff --git a/src/sal/sd/sd.c b/src/sal/sd/sd.c
index b72816b..a9c2a47 100755
--- a/src/sal/sd/sd.c
+++ b/src/sal/sd/sd.c
@@ -23,6 +23,8 @@
 
 mdio_reg_set ssdk_mdio_set    = NULL;
 mdio_reg_get ssdk_mdio_get    = NULL;
+i2c_reg_set ssdk_i2c_set    = NULL;
+i2c_reg_get ssdk_i2c_get    = NULL;
 hdr_reg_set  ssdk_hdr_reg_set = NULL;
 hdr_reg_get  ssdk_hdr_reg_get = NULL;
 psgmii_reg_set  ssdk_psgmii_reg_set = NULL;
@@ -105,6 +107,77 @@
 }
 
 sw_error_t
+sd_reg_i2c_set(a_uint32_t dev_id, a_uint32_t phy, a_uint32_t reg,
+                a_uint16_t data)
+{
+    sw_error_t rv = SW_OK;
+
+    if (NULL != ssdk_i2c_set)
+    {
+        rv = ssdk_i2c_set(dev_id, phy, reg, data);
+    }
+    else
+    {
+#if ((!defined(KERNEL_MODULE)) && defined(UK_IF))
+        {
+            a_uint32_t args[SW_MAX_API_PARAM];
+
+            args[0] = SW_API_PHY_I2C_SET;
+            args[1] = (a_uint32_t) & rv;
+            args[2] = dev_id;
+            args[3] = phy;
+            args[4] = reg;
+            args[5] = data;
+            if (SW_OK != sw_uk_if(args))
+            {
+                return SW_FAIL;
+            }
+        }
+#else
+        return SW_NOT_SUPPORTED;
+#endif
+    }
+
+    return rv;
+}
+
+sw_error_t
+sd_reg_i2c_get(a_uint32_t dev_id, a_uint32_t phy, a_uint32_t reg, a_uint16_t * data)
+{
+    sw_error_t rv = SW_OK;
+
+    if (NULL != ssdk_i2c_get)
+    {
+        rv = ssdk_i2c_get(dev_id, phy, reg, data);
+    }
+    else
+    {
+#if ((!defined(KERNEL_MODULE)) && defined(UK_IF))
+        {
+            a_uint32_t args[SW_MAX_API_PARAM];
+            a_uint32_t tmp;
+
+            args[0] = SW_API_PHY_I2C_GET;
+            args[1] = (a_uint32_t) & rv;
+            args[2] = dev_id;
+            args[3] = phy;
+            args[4] = reg;
+            args[5] = (a_uint32_t) & tmp;
+            if (SW_OK != sw_uk_if(args))
+            {
+                return SW_FAIL;
+            }
+            *data = *((a_uint16_t *)&tmp);
+        }
+#else
+        return SW_NOT_SUPPORTED;
+#endif
+    }
+
+    return rv;
+}
+
+sw_error_t
 sd_reg_hdr_set(a_uint32_t dev_id, a_uint32_t reg_addr, a_uint8_t * reg_data, a_uint32_t len)
 {
     sw_error_t rv;
@@ -243,6 +316,16 @@
         ssdk_mdio_get = cfg->reg_func.mdio_get;
     }
 
+    if (NULL != cfg->reg_func.i2c_set)
+    {
+        ssdk_i2c_set = cfg->reg_func.i2c_set;
+    }
+
+    if (NULL != cfg->reg_func.i2c_get)
+    {
+        ssdk_i2c_get = cfg->reg_func.i2c_get;
+    }
+
     if (NULL != cfg->reg_func.header_reg_set)
     {
         ssdk_hdr_reg_set = cfg->reg_func.header_reg_set;