Merge "[qca-ssdk]: adjust switch init sequence"
diff --git a/include/init/ssdk_plat.h b/include/init/ssdk_plat.h
index 75df79d..584c1c7 100755
--- a/include/init/ssdk_plat.h
+++ b/include/init/ssdk_plat.h
@@ -94,11 +94,17 @@
 
 
 #define AR8327_REG_POS		0x10
+#define AR8327_REG_POS_HW_INIT 0x261320
 #define   AR8327_POS_POWER_ON_SEL	BIT(31)
 #define   AR8327_POS_LED_OPEN_EN	BIT(24)
 #define   AR8327_POS_SERDES_AEN	    BIT(7)
 
+#define AR8327_REG_MODULE_EN  0x30
+#define   AR8327_REG_MODULE_EN_QM_ERR	BIT(8)
+
+
 #define AR8327_REG_PAD_SGMII_CTRL			0xe0
+#define AR8327_REG_PAD_SGMII_CTRL_HW_INIT   0xc70164c0
 #define   AR8327_PAD_SGMII_CTRL_MODE_CTRL	BITS(22, 2)
 #define   AR8327_PAD_SGMII_CTRL_MODE_CTRL_S		22
 #define   AR8327_PAD_SGMII_CTRL_EN_SD		BIT(4)
@@ -139,6 +145,24 @@
 #define QCA_PHY_MIB_WORK_DELAY	120000
 #define QCA_MIB_ITEM_NUMBER	41
 
+#define SSDK_GLOBAL_INT0_ACL_INI_INT        (1<<29)
+#define SSDK_GLOBAL_INT0_LOOKUP_INI_INT     (1<<28)
+#define SSDK_GLOBAL_INT0_QM_INI_INT         (1<<27)
+#define SSDK_GLOBAL_INT0_MIB_INI_INT        (1<<26)
+#define SSDK_GLOBAL_INT0_OFFLOAD_INI_INT    (1<<25)
+#define SSDK_GLOBAL_INT0_HARDWARE_INI_DONE  (1<<24)
+
+#define SSDK_GLOBAL_INITIALIZED_STATUS 				\
+			(					\
+			SSDK_GLOBAL_INT0_ACL_INI_INT | 		\
+			SSDK_GLOBAL_INT0_LOOKUP_INI_INT | 	\
+			SSDK_GLOBAL_INT0_QM_INI_INT | 		\
+			SSDK_GLOBAL_INT0_MIB_INI_INT | 		\
+			SSDK_GLOBAL_INT0_OFFLOAD_INI_INT |	\
+			SSDK_GLOBAL_INT0_HARDWARE_INI_DONE	\
+			)
+
+
 struct qca_phy_priv {
 	struct phy_device *phy;
 	struct switch_dev sw_dev;
diff --git a/src/hsl/isisc/isisc_port_ctrl.c b/src/hsl/isisc/isisc_port_ctrl.c
index 92d0458..4a11d79 100755
--- a/src/hsl/isisc/isisc_port_ctrl.c
+++ b/src/hsl/isisc/isisc_port_ctrl.c
@@ -1227,7 +1227,7 @@
 _isisc_port_link_forcemode_set(a_uint32_t dev_id, fal_port_t port_id, a_bool_t enable)
 {
     sw_error_t rv;
-    a_uint32_t reg;
+    a_uint32_t reg, tmp;
 
     HSL_DEV_ID_CHECK(dev_id);
 
@@ -1240,12 +1240,18 @@
                       (a_uint8_t *) (&reg), sizeof (a_uint32_t));
     SW_RTN_ON_ERROR(rv);
 
+    SW_GET_FIELD_BY_REG(PORT_STATUS, LINK_EN, tmp, reg);
+
     if (A_TRUE == enable)
     {
+	if(tmp == 0)
+		return SW_OK;
         SW_SET_REG_BY_FIELD(PORT_STATUS, LINK_EN, 0, reg);
     }
     else if (A_FALSE == enable)
     {
+	if(tmp == 1)
+		return SW_OK;
         /* for those ports without PHY, it can't sync link status */
         if (A_FALSE == _isisc_port_phy_connected(dev_id, port_id))
         {
diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c
index 9784664..4fa5bf4 100755
--- a/src/init/ssdk_init.c
+++ b/src/init/ssdk_init.c
@@ -153,6 +153,49 @@
 	}
 }
 
+void
+qca_ar8327_phy_disable()
+{
+	int i = 0;
+	for (i = 0; i < AR8327_NUM_PHYS; i++) {
+		/* power down all phy*/
+		qca_ar8327_phy_write(0, i, MII_BMCR, BMCR_PDOWN);
+	}
+}
+
+void
+qca_mac_disable()
+{
+	qca_ar8216_mii_write(AR8327_REG_PAD0_CTRL, 0);
+	qca_ar8216_mii_write(AR8327_REG_PAD5_CTRL, 0);
+	qca_ar8216_mii_write(AR8327_REG_PAD6_CTRL, 0);
+	qca_ar8216_mii_write(AR8327_REG_POS, AR8327_REG_POS_HW_INIT);
+	qca_ar8216_mii_write(AR8327_REG_PAD_SGMII_CTRL, AR8327_REG_PAD_SGMII_CTRL_HW_INIT);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(0), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(1), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(2), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(3), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(4), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(5), 0);
+	qca_ar8216_mii_write(AR8327_REG_PORT_STATUS(6), 0);
+}
+
+
+void
+qca_ar8327_phy_enable(struct qca_phy_priv *priv)
+{
+	int i = 0;
+	for (i = 0; i < AR8327_NUM_PHYS; i++) {
+		qca_ar8327_phy_fixup(priv, i);
+
+		/* start autoneg*/
+		priv->phy_write(0, i, MII_ADVERTISE, ADVERTISE_ALL |
+						     ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+		priv->phy_write(0, i, MII_CTRL1000, ADVERTISE_1000FULL);
+		priv->phy_write(0, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
+	}
+}
+
 #if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
 static int
 qca_ar8327_hw_init(struct qca_phy_priv *priv)
@@ -393,7 +436,7 @@
     return new_pos;
 }
 
-static void
+void
 qca_ar8327_port_init(struct qca_phy_priv *priv, a_uint32_t port)
 {
 	struct ar8327_platform_data *plat_data;
@@ -440,48 +483,29 @@
 			return;
 		}
 	}
-
-	value = AR8327_PORT_STATUS_TXMAC | AR8327_PORT_STATUS_RXMAC;
-	value|= port_cfg->duplex ? AR8327_PORT_STATUS_DUPLEX : 0;
-	value |= port_cfg->rxpause ? AR8327_PORT_STATUS_RXFLOW : 0;
-	value |= port_cfg->txpause ? AR8327_PORT_STATUS_TXFLOW : 0;
-
-    if(port_cfg->speed == AR8327_PORT_SPEED_10) {
-        value |= AR8327_PORT_SPEED_10M;
-    } else if(port_cfg->speed == AR8327_PORT_SPEED_100) {
-        value |= AR8327_PORT_SPEED_100M;
-    } else if(port_cfg->speed == AR8327_PORT_SPEED_1000) {
-        value |= AR8327_PORT_SPEED_1000M;
-    } else {
-        value |= AR8327_PORT_SPEED_1000M;
-    }
-
-	priv->mii_write(AR8327_REG_PORT_STATUS(port), value);
-	if((port == 5) && plat_data->pad5_cfg) {
-		if(plat_data->pad5_cfg->mode == AR8327_PAD_PHY_RGMII) {
-			a_uint16_t val = 0;
-			/*enable RGMII  mode */
-			priv->phy_dbg_read(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_MODE_SEL, &val);
-			val |= AR8327_PHY_RGMII_MODE;
-			priv->phy_dbg_write(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_MODE_SEL, val);
-			if(plat_data->pad5_cfg->txclk_delay_en) {
-				priv->phy_dbg_read(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_SYS_CTRL, &val);
-				val |= AR8327_PHY_RGMII_TX_DELAY;
-				priv->phy_dbg_write(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_SYS_CTRL, val);
-			}
-			if(plat_data->pad5_cfg->rxclk_delay_en) {
-				priv->phy_dbg_read(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_TEST_CTRL, &val);
-				val |= AR8327_PHY_RGMII_RX_DELAY;
-				priv->phy_dbg_write(0, AR8327_PORT5_PHY_ADDR,
-								AR8327_PHY_REG_TEST_CTRL, val);
-			}
-		}
+	/*disable mac at first*/
+	fal_port_rxmac_status_set(0, port, A_FALSE);
+	fal_port_txmac_status_set(0, port, A_FALSE);
+	value = port_cfg->duplex ? FAL_FULL_DUPLEX : FAL_HALF_DUPLEX;
+	fal_port_duplex_set(0, port, value);
+	value = port_cfg->txpause ? A_TRUE : A_FALSE;
+	fal_port_txfc_status_set(0, port, value);
+	value = port_cfg->rxpause ? A_TRUE : A_FALSE;
+	fal_port_rxfc_status_set(0, port, value);
+	if(port_cfg->speed == AR8327_PORT_SPEED_10) {
+		value = FAL_SPEED_10;
+	} else if(port_cfg->speed == AR8327_PORT_SPEED_100) {
+		value = FAL_SPEED_100;
+	} else if(port_cfg->speed == AR8327_PORT_SPEED_1000) {
+		value = FAL_SPEED_1000;
+	} else {
+		value = FAL_SPEED_1000;
 	}
+	fal_port_speed_set(0, port, value);
+	/*enable mac at last*/
+	udelay(800);
+	fal_port_rxmac_status_set(0, port, A_TRUE);
+	fal_port_txmac_status_set(0, port, A_TRUE);
 }
 
 static int
@@ -499,6 +523,18 @@
 	value = priv->mii_read(AR8327_REG_CTRL);
 	value |= 0x80000000;
 	priv->mii_write(AR8327_REG_CTRL, value);
+	/*Need wait reset done*/
+	do {
+		udelay(10);
+		value = priv->mii_read(AR8327_REG_CTRL);
+	} while(value & AR8327_CTRL_RESET);
+	do {
+		udelay(10);
+		value = priv->mii_read(0x20);
+	} while ((value & SSDK_GLOBAL_INITIALIZED_STATUS) != SSDK_GLOBAL_INITIALIZED_STATUS);
+	#ifndef BOARD_AR71XX
+	fal_port_link_forcemode_set(0, 5, A_TRUE);
+	#endif
 
 	value = priv->mii_read(AR8327_REG_PORT_LOOKUP(0));
 	value &= ~0x5e;
@@ -601,6 +637,7 @@
 
 	priv->mii_write(AR8327_REG_POS, new_pos);
 
+#ifdef BOARD_AR71XX
 	for (i = 0; i < AR8327_NUM_PHYS; i++) {
 		qca_ar8327_phy_fixup(priv, i);
 
@@ -610,6 +647,7 @@
 		priv->phy_write(0, i, MII_CTRL1000, ADVERTISE_1000FULL);
 		priv->phy_write(0, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
 	}
+#endif
 
 	if(priv->version == QCA_VER_AR8337) {
         value = priv->mii_read(AR8327_REG_PAD5_CTRL);
@@ -617,11 +655,13 @@
         priv->mii_write(AR8327_REG_PAD5_CTRL, value);
     }
 
+#ifdef BOARD_AR71XX
 	msleep(1000);
 
 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
 		qca_ar8327_port_init(priv, i);
     }
+#endif
 
 	return 0;
 }
@@ -1305,9 +1345,11 @@
             break;
         }
 #endif
+#ifdef BOARD_AR71XX
         if (i  != 0) {
             fal_port_link_forcemode_set(dev_id, i, A_FALSE);
         }
+#endif
         fal_port_rxhdr_mode_set(dev_id, i, FAL_NO_HEADER_EN);
         fal_port_txhdr_mode_set(dev_id, i, FAL_NO_HEADER_EN);
         fal_port_3az_status_set(dev_id, i, A_FALSE);
@@ -1423,6 +1465,14 @@
 {
     sw_error_t rv;
 
+	#ifndef BOARD_AR71XX
+		if(ssdk_dt_global.switch_reg_access_mode == HSL_REG_MDIO) {
+			qca_ar8327_phy_disable();
+			qca_mac_disable();
+			msleep(1000);
+		}
+	#endif
+
 #if (defined(KERNEL_MODULE) && defined(USER_MODE))
     rv = hsl_dev_init(dev_id, cfg);
 #else
diff --git a/src/ref/ref_misc.c b/src/ref/ref_misc.c
index bd138d4..18a89db 100755
--- a/src/ref/ref_misc.c
+++ b/src/ref/ref_misc.c
@@ -47,6 +47,13 @@
 #include "ssdk_plat.h"
 #include "ref_vlan.h"
 
+extern void
+qca_ar8327_phy_disable();
+extern void
+qca_ar8327_phy_enable(struct qca_phy_priv *priv);
+extern void
+qca_ar8327_port_init(struct qca_phy_priv *priv, a_uint32_t port);
+
 int
 qca_ar8327_sw_set_max_frame_size(struct switch_dev *dev,
 										const struct switch_attr *attr,
@@ -105,7 +112,12 @@
 
     /*for (i = 0; i < AR8327_MAX_VLANS; i++)*/
     /*    priv->vlan_id[i] = i;*/
+#ifndef BOARD_AR71XX
 
+	qca_ar8327_phy_disable();
+	msleep(1000);
+
+#endif
     /* init switch */
     rv += ssdk_switch_init(0);
 
@@ -114,7 +126,13 @@
     priv->init = true;
     rv += qca_ar8327_sw_hw_apply(dev);
     priv->init = false;
-
+	#ifndef BOARD_AR71XX
+	for (i = 0; i < AR8327_NUM_PORTS; i++) {
+		qca_ar8327_port_init(priv, i);
+    }
+	fal_port_link_forcemode_set(0, 5, A_FALSE);
+	qca_ar8327_phy_enable(priv);
+	#endif
     return rv;
 }