[Bugfix][API-660]reboot after sleep

Change-Id: I066a492ad374a56b2fa2b2777929814796311fb9
(cherry picked from commit ba25fe97fb4fd9229f97295fb9896933fd5c40ee)
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
index 6b11ec6..50ee280 100644
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/mt2735.dtsi
@@ -314,28 +314,6 @@
 #endif
 	};
 
-	wed: wed@15010000 {
-                compatible = "mediatek,wed";
-                wed_num = <2>;
-                /* add this property for wed get the pci slot number. */
-                pci_slot_map = <0>, <1>;
-                reg = <0 0x15010000 0 0x1000>,
-                                <0 0x15011000 0 0x1000>;
-		interrupt-parent = <&gic>;
-                interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>,
-                                                <GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>;
-        };
-
-        wed2: wed2@15011000 {
-                compatible = "mediatek,wed2";
-                wed_num = <2>;
-                reg = <0 0x15010000 0 0x1000>,
-                                <0 0x15011000 0 0x1000>;
-		interrupt-parent = <&gic>;
-                interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>,
-                                                <GIC_SPI 407 IRQ_TYPE_LEVEL_HIGH>;
-        };
-
         wdma: wdma@15102800 {
                 compatible = "mediatek,wed-wdma";
                 reg = <0 0x15102800 0 0x400>,
@@ -3233,7 +3211,17 @@
 		compatible = "mediatek,leopard-ethsys", "syscon", "simple-mfd";
                 reg = <0 0x15195000 0 0x1000>;
         };
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+        wed: wed@15010000 {
+                compatible = "mediatek,leopard-ethsys", "syscon", "simple-mfd";
+                reg = <0 0x15010000 0 0x1000>;
+        };
 
+        wed2: wed2@15195000 {
+                compatible = "mediatek,leopard-ethsys", "syscon", "simple-mfd";
+                reg = <0 0x15011000 0 0x1000>;
+        };
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	hnat: hnat@15100e00 {
 		compatible = "mediatek,hnat", "syscon";
 		reg = <0 0x15100e00 0 0x1000>;
@@ -3283,6 +3271,8 @@
 		power-domains = <&scpsys MT6890_POWER_DOMAIN_NETSYS>;
 		mediatek,ethsys = <&ethsys>;
 		mediatek,wo = <&wo>;
+		mediatek,wed = <&wed>; //jb.qi change for reboot after sleep on 20230417
+		mediatek,wed2 = <&wed2>; //jb.qi change for reboot after sleep on 20230417
 #if defined(CONFIG_MTK_SGMII_NETSYS)
 		mediatek,sgmiisys = <&sgmiisys_0>,<&sgmiisys_1>;
 		mediatek,sgmiisys_phy = <&sgmiisys_phy_0>,<&sgmiisys_phy_1>;
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
index 10a6735..86123c0 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_edma.c
@@ -569,9 +569,11 @@
 	//EDMA_GLO_CFG: TX_WB_DDONE | RX_DMA_EN |
 	//   PDMA_BT_SIZE_16DWORDS | PDMA_DESC_32B_E |
 	//   MULTI_EN | ADMA_RX_BT_SIZE_32DWORDS  RX_2B_OFFSET
-
-	mtk_w32(eth, 0x80001C64, MTK_EDMA0_GLO_CFG);
-	mtk_w32(eth, 0x80001C64, MTK_EDMA1_GLO_CFG);
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	/* Set EDMA0_GLO_CFG and EDMA1_GLO_CFG [23:16] to 0x80 since CDM FIFO overrun issue */
+	mtk_w32(eth, 0x80801C64, MTK_EDMA0_GLO_CFG);
+	mtk_w32(eth, 0x80801C64, MTK_EDMA1_GLO_CFG);
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 }
 
 void mtk_stop_dma_edma(struct mtk_eth *eth, u32 glo_cfg)
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
index 9a98183..3e92205 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
@@ -695,7 +695,7 @@
 
 	cr_max = 5000 * 4;
 	seq_puts(seq, "       <<FE CR DUMP>>\n");
-	for (i = 0x800; i < cr_max; i = i + 0x10) {
+	for (i = 0x0; i < cr_max; i = i + 0x10) { //jb.qi change for reboot after sleep on20230417
 		seq_printf(seq, "0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x\n", cr_base + i,
 			mtk_r32(eth, i), mtk_r32(eth, i + 4),
 			mtk_r32(eth, i + 8), mtk_r32(eth, i + 0xc));
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 6dd83e1..8c1b6d6 100755
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -827,7 +827,10 @@
 				  DMA_FROM_DEVICE);
 	if (unlikely(dma_mapping_error(eth->dev, dma_addr)))
 		return -ENOMEM;
-
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	eth->phy_scratch_head = dma_addr;
+	eth->scratch_head_size = cnt * MTK_QDMA_PAGE_SIZE;
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	memset(eth->scratch_ring, 0x0, sizeof(struct mtk_tx_dma) * cnt);
 	phy_ring_tail = eth->phy_scratch_ring +
 			(sizeof(struct mtk_tx_dma) * (cnt - 1));
@@ -2927,9 +2930,19 @@
 		for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
 			mtk_rx_clean(eth, &eth->rx_ring[i]);
 	}
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	if (eth->phy_scratch_head) {
+		dma_unmap_single(eth->dev, eth->phy_scratch_head,
+			eth->scratch_head_size,	DMA_FROM_DEVICE);
+		eth->phy_scratch_head  = 0;
+		eth->scratch_head_size = 0;
+	}
 
-	kfree(eth->scratch_head);
-
+	if (eth->scratch_head) {
+		kfree(eth->scratch_head);
+		eth->scratch_head = NULL;
+	}
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	if (eth->hwedmarx) {
 		for (i = 0; i < MTK_MAX_EDMA_RX_RING_NUM; i++) {
 			mtk_rx_clean_edma(eth, &eth->rx_ring_edma0[i]);
@@ -3205,14 +3218,16 @@
 	/* we run 2 netdevs on the same dma ring so we only bring it up once */
 	if (!refcount_read(&eth->dma_refcnt)) {
 		err = mtk_start_dma(eth);
-
 		if (err) {
 			dev_err(eth->dev, "%s: mtk_start_dma err\n", __func__);
 			return err;
 		}
-		mtk_gdma_config(eth, MTK_GDMA_ICS_EN | MTK_GDMA_TCS_EN | MTK_GDMA_UCS_EN);
-		napi_enable(&eth->tx_napi);
 
+		/* redirect GDM packets to PPE */
+		mtk_gdma_config(eth, MTK_GDMA_ICS_EN | MTK_GDMA_TCS_EN | MTK_GDMA_UCS_EN);
+
+		/* enable IRQ Bottom */
+		napi_enable(&eth->tx_napi);
 		if (eth->hwrss) {
 			napi_enable(&eth->rx_napi0);
 			napi_enable(&eth->rx_napi1);
@@ -3221,6 +3236,11 @@
 		} else {
 			napi_enable(&eth->rx_napi);
 		}
+		/*jb.qi change for reboot after sleep on 20230417 start*/
+		if (eth->hwedmarx)
+			napi_enable_edma(eth);
+		/*jb.qi change for reboot after sleep on 20230417 end*/
+		/* enable IRQ Top */
 		mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
 		if (eth->hwrss) {
 			mtk_rx_irq_enable0(eth, MTK_RX_DONE_DLY);
@@ -3231,10 +3251,8 @@
 			mtk_rx_irq_enable(eth, MTK_RX_DONE_INT);
 		}
 
-		if (eth->hwedmarx) {
-			napi_enable_edma(eth);
+		if (eth->hwedmarx) //jb.qi change for reboot after sleep on 20230417
 			mtk_rx_irq_enable_edma_all(eth);
-		}
 
 #if defined(CONFIG_HW_NAT)
 		mtk_register_fast_path();
@@ -3281,6 +3299,8 @@
 	struct mtk_mac *mac = netdev_priv(dev);
 	struct mtk_eth *eth = mac->hw;
 
+	pr_info("%s in mac[%d]\n", __func__, mac->id); //jb.qi change for reboot after sleep on 20230417
+
 	netif_tx_disable(dev);
 
 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
@@ -3289,9 +3309,14 @@
 	/* only shutdown DMA if this is the last user */
 	if (!refcount_dec_and_test(&eth->dma_refcnt))
 		return 0;
-
+/*jb.qi change for reboot after sleep on 20230417 start*/
+#if defined(CONFIG_HW_NAT)
+	mtk_unregister_fast_path();
+#endif
+/*jb.qi change for reboot after sleep on 20230417 end*/
 	mtk_gdma_config(eth, MTK_GDMA_DROP_ALL);
 
+	/* disable IRQ Top */
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
 
 	if (eth->hwrss) {
@@ -3302,12 +3327,14 @@
 	} else {
 		mtk_rx_irq_disable(eth, MTK_RX_DONE_INT);
 	}
-
-	if (eth->hwedmarx) {
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	if (eth->hwedmarx)
 		mtk_rx_irq_disable_edma_all(eth);
-		napi_disable(&eth->rx_napi_edma0);
-		napi_disable(&eth->rx_napi_edma1);
-	}
+
+	if (eth->int_ext)
+		disable_irq_nosync(eth->irq[8]);
+	/*jb.qi change for reboot after sleep on 20230417 end*/
+	/* disable IRQ Bottom */
 	napi_disable(&eth->tx_napi);
 
 	if (eth->hwrss) {
@@ -3318,7 +3345,12 @@
 	} else {
 		napi_disable(&eth->rx_napi);
 	}
-
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	if (eth->hwedmarx) {
+		napi_disable(&eth->rx_napi_edma0);
+		napi_disable(&eth->rx_napi_edma1);
+	}
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
 	mtk_stop_dma(eth, MTK_PDMA_GLO_CFG);
 
@@ -3333,10 +3365,6 @@
 		regulator_set_voltage(eth->dvfsrc_vcore_power,
 				      SGMII_VCORE_NON_OPS, INT_MAX);
 
-#if defined(CONFIG_HW_NAT)
-	mtk_unregister_fast_path();
-#endif
-
 	return 0;
 }
 
@@ -3612,6 +3640,7 @@
 		//set FE_INT no RX ADMA INT
 		mtk_w32(eth, 0x01000000, MTK_FE_INT_GRP);
 	}
+
 	mtk_w32(eth, MTK_TX_DONE_INT, MTK_QDMA_INT_GRP1);
 	//maybe no need to set
 	//mtk_w32(eth, MTK_RX_DONE_INT, MTK_QDMA_INT_GRP2);
@@ -3639,11 +3668,10 @@
 //echo reg_write 0x15100178 0x00060006 > /proc/clkdbg ; cat /proc/clkdbg"
 //echo reg_write 0x1510017C 0x00060006 > /proc/clkdbg ; cat /proc/clkdbg"
 
-//#Global FC threshold
+	//#Global FC threshold
 	mtk_w32(eth, 0x01fa01f4, 0x104);
 
-//#Per CDM Input threshold update
-
+	//#Per CDM Input threshold update
 	mtk_w32(eth, 0x001a000e, 0x140);
 	mtk_w32(eth, 0x01ff001a, 0x144);
 	mtk_w32(eth, 0x000e01ff, 0x148);
@@ -3652,7 +3680,8 @@
 	mtk_w32(eth, 0x000e000e, 0x154);
 	mtk_w32(eth, 0x000e000e, 0x158);
 	mtk_w32(eth, 0x000e000e, 0x15c);
-//#Per port Output threshold update
+
+	//#Per port Output threshold update
 	mtk_w32(eth, 0x000f000a, 0x160);
 	mtk_w32(eth, 0x001a000f, 0x164);
 	mtk_w32(eth, 0x000f001a, 0x168);
@@ -3669,18 +3698,18 @@
 	mtk_w32(eth, 0x00000004, 0x1658);
 	mtk_w32(eth, 0x00000004, 0x165c);
 
-/* Notice: The following modification is to set Single PHY chip
- * This Solution is only for AQR112C Chip. If Single PHY chip is not
- *	AQR112C, the solution is not available.
- *	If Single PHY chip is not AQR112C, the following step you should do:
- *	1. Contact your Single PHY chip vendor and get the details of
- *	    - how to enable flow control
- *		- how to Enables link status change alarm
- *		- how to Enables vendor Auto-Neg alarm
- *		- how to Enables Chip-wide vendor alarm
- *		- restart AN
- *	2. Modify the code for the customization.
- */
+	/* Notice: The following modification is to set Single PHY chip
+	 * This Solution is only for AQR112C Chip. If Single PHY chip is not
+	 *	AQR112C, the solution is not available.
+	 *	If Single PHY chip is not AQR112C, the following step you should do:
+	 *	1. Contact your Single PHY chip vendor and get the details of
+	 *	    - how to enable flow control
+	 *		- how to Enables link status change alarm
+	 *		- how to Enables vendor Auto-Neg alarm
+	 *		- how to Enables Chip-wide vendor alarm
+	 *		- restart AN
+	 *	2. Modify the code for the customization.
+	 */
 	_mtk_mdio_write_C45(eth, 8, 0x10, 0x9d81, 7);
 
 	tmp = _mtk_mdio_read_C45(eth, 8, 0xd401, 7);
@@ -3713,9 +3742,10 @@
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
 {
-	if (!test_and_clear_bit(MTK_HW_INIT, &eth->state))
-		return 0;
-
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	//if (!test_and_clear_bit(MTK_HW_INIT, &eth->state))
+	//	return 0;
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_FPGA_CLK)) {
 		mtk_clk_disable(eth);
 		pm_runtime_put_sync(eth->dev);
@@ -4249,10 +4279,27 @@
 		dev_err(&pdev->dev, "no wo regmap found\n");
 		return PTR_ERR(eth->wo);
 	}
-	regmap_write(eth->wo, 0x0070, 0xb);
-	regmap_write(eth->wo, 0x0074, 0xb);
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	regmap_write(eth->wo, 0x0070, 0x1);
+	regmap_write(eth->wo, 0x0074, 0x1);
+	pr_notice("%s reset wo\n", __func__);
 
+	eth->wed = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mediatek,wed");
+	if (IS_ERR(eth->wed)) {
+		dev_err(&pdev->dev, "no wed regmap found\n");
+		return PTR_ERR(eth->wed);
+	}
+	regmap_write(eth->wed, 0x057c, 0x0);
+	pr_notice("%s reset wed\n", __func__);
 
+	eth->wed2 = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mediatek,wed2");
+	if (IS_ERR(eth->wed2)) {
+		dev_err(&pdev->dev, "no wed2 regmap found\n");
+		return PTR_ERR(eth->wed2);
+	}
+	regmap_write(eth->wed2, 0x057c, 0x0);
+	pr_notice("%s reset wed2\n", __func__);
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	if (MTK_HAS_CAPS(eth->soc->caps, MTK_INFRA)) {
 		eth->infra = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 							"mediatek,infracfg");
@@ -4524,40 +4571,145 @@
 
 	return 0;
 }
+/*jb.qi change for reboot after sleep on 20230417 start*/
+int netsys_pm_check_status(struct mtk_eth *eth, u32 idle)
+{
+	u32 val = 0, tmp = 0, cnt = 0, pass = 0;
 
+	/* check continuous 10 pass in 1000 times */
+	for (cnt = 0; cnt < 1000; cnt++)
+	{
+		regmap_read(eth->ethsys, 0x54, &val);
+		tmp = val & idle;
+		if (tmp == idle) {
+			pass++;
+		} else {
+			pr_notice("cnt = %d: val= 0x%x\n", cnt, tmp);
+			pass = 0;
+		}
+
+		if (pass > 10)
+			break;
+
+		/* sleep 1ms */
+		usleep_range(1000, 1100);
+	}
+
+	if (cnt == 1000) {
+		pr_notice("ADMA related bus not idle!!!!\n");
+		return 1;
+	}
+
+	pr_notice("NETSYS hw idle status: 0x%x\n", val);
+
+	return 0;
+}
+
+int netsys_pm_reset_adma(struct mtk_eth *eth)
+{
+	int ret;
+	u32 val;
+
+	/* disable CDM */
+	mtk_w32(eth, 0x00200080, MTK_PDMA_LRO_CTRL_DW0);
+	mtk_w32(eth, 0x80001c00, MTK_PDMA_GLO_CFG);
+	mtk_w32(eth, 0x810001b0, 0);
+
+	//regmap_write(eth->ethsys, 0xe8, 0x00008202);
+	regmap_write(eth->ethsys, 0xe4, 0x7c000000);
+	pr_notice("reset adma\n");
+
+	msleep(1);
+
+	regmap_write(eth->wo, 0x0070, 0x1);
+	regmap_write(eth->wo, 0x0074, 0x1);
+	pr_notice("reset wo APSRC\n");
+
+	msleep(1);
+
+	regmap_write(eth->wed, 0x057c, 0x0);
+	regmap_read(eth->wed, 0x057c, &val);
+	pr_notice("reset wed INT_CTL to 0x%x\n", val);
+
+	msleep(1);
+
+	regmap_write(eth->wed2, 0x057c, 0x0);
+	regmap_read(eth->wed2, 0x057c, &val);
+	pr_notice("reset wed2 INT_CTL to 0x%x\n", val);
+
+	msleep(1);
+
+	/* check CDM IDLE */
+	ret = netsys_pm_check_status(eth, 0x0C000002);
+	if (ret)
+		return ret;
+
+	pr_notice("ethernet suspend time reset CDM = %lx\n", jiffies);
+
+	/* disable ADMA */
+	mtk_w32(eth, 0x05f2c040, 0x98c);
+	msleep(1);
+	mtk_w32(eth, 0x05f28040, 0x98c);
+	msleep(3);
+
+	/* check ADMA IDLE */
+	ret = netsys_pm_check_status(eth, 0x9FFFFFFF);
+	if (ret)
+		return ret;
+
+	pr_notice("ethernet suspend time reset ADMA = %lx\n", jiffies);
+
+	return 0;
+}
+
+void netsys_pm_recovery(struct mtk_eth *eth)
+{
+}
+/*jb.qi change for reboot after sleep on 20230417 end*/
 int netsys_pm_suspend(struct device *device)
 {
 	struct platform_device *pdev = to_platform_device(device);
 	struct mtk_eth *eth;
-	u32 val = 0;
 	int i, ret;
-	static int enable_hw_idle = 0;
 
 	pr_notice("ethernet suspend time start = %lx\n", jiffies);
+
 	if (pdev == NULL) {
-		////pr_notice("%s pdev == NULL\n", __func__);
+		pr_notice("%s pdev == NULL\n", __func__); //jb.qi change for reboot after sleep on 20230417
 		return -1;
 	}
 
 	eth = platform_get_drvdata(pdev);
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	regmap_write(eth->ethsys, 0x10, 0xb6000000);
+	regmap_write(eth->ethsys, 0x58, 0x20000000);
+	regmap_write(eth->ethsys, 0xf0, 0x007f0000);
+	regmap_write(eth->ethsys, 0xfc, 0x00001080);
+	pr_notice("ethernet suspend time reset cdm = %lx\n", jiffies);
+
+	/* eth down */
+	memset(&eth->suspend_data, 0x0, sizeof(struct mtk_suspend_data));
 
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		if (!eth->netdev[i])
 			continue;
 
-		netif_stop_queue(eth->netdev[i]);
-	}
+		eth->suspend_data.eth_state[i] = netif_running(eth->netdev[i])? 1 : 0;
+		eth->suspend_data.mcr[i] = mtk_r32(eth, MTK_MAC_MCR(i));
 
-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
-		for (i = 0; i < MTK_MAC_COUNT; i++) {
-			if (!eth->netdev[i])
-				continue;
+		pr_notice("save %s state=%d mac%d=0x%x",
+			eth->netdev[i]->name,
+			eth->suspend_data.eth_state[i],
+			i, eth->suspend_data.mcr[i]);
 
-			phy_stop(eth->netdev[i]->phydev);
+		if (eth->suspend_data.eth_state[i]) {
+			netif_stop_queue(eth->netdev[i]);
+			if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+				phy_stop(eth->netdev[i]->phydev);
 		}
 	}
-	pr_notice("ethernet suspend time  kerenel stop = %lx\n", jiffies);
-
+	pr_notice("ethernet suspend time phy stop = %lx\n", jiffies);
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 #if 0
 	regmap_update_bits(eth->ethsys, MTK_PPE_TB_CFG,
 			   SCAN_MODE_MASK,
@@ -4572,10 +4724,10 @@
 	if (eth->soc->sgmii_pm)
 		regulator_set_voltage(eth->dvfsrc_vcore_power,
 				      SGMII_VCORE_NON_OPS, INT_MAX);
-	pr_notice("ethernet suspend time  vcore 0.55V = %lx\n", jiffies);
+	pr_notice("ethernet suspend time set vcore 0.55V = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
 
 	mtk_gdma_config(eth, MTK_GDMA_DROP_ALL);
-	pr_notice("ethernet suspend time  set GDM ingress pkt drop = %lx\n", jiffies);
+	pr_notice("ethernet suspend time set GDM ingress pkt drop = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
 
 	mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
 	if (eth->hwrss) {
@@ -4590,55 +4742,38 @@
 	if (eth->int_ext)
 		disable_irq_nosync(eth->irq[8]);
 
+	pr_notice("ethernet suspend time disable irq = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
+
 	if (eth->hwedmarx) {
 		mtk_rx_irq_disable_edma_all(eth);
 		mtk_stop_dma_edma(eth, MTK_EDMA0_GLO_CFG);
 		mtk_stop_dma_edma(eth, MTK_EDMA1_GLO_CFG);
 	}
-
+	pr_notice("ethernet suspend time stop EDMA = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
+	/*jb.qi change for reboot after sleep on 20230417 start*/
 	//napi_disable(&eth->tx_napi);
 	//napi_disable(&eth->rx_napi);
 	/*disable ADMA*/
-	pr_notice("ethernet suspend time disable irq = %lx\n", jiffies);
-	mtk_w32(eth, 0x00200080, MTK_PDMA_LRO_CTRL_DW0);
-	mtk_w32(eth, 0x80001c00, MTK_PDMA_GLO_CFG);
-	mtk_w32(eth, 0x810001b0, 0);
-	/*check ADMA IDLE*/
-	if (enable_hw_idle == 0) {
-		regmap_write(eth->ethsys, 0xe8, 0x00008202);
-		regmap_write(eth->ethsys, 0xe4, 0x7c000000);
-		regmap_write(eth->ethsys, 0x10, 0xb6000000);
-		regmap_write(eth->ethsys, 0x58, 0x20000000);
-		regmap_write(eth->ethsys, 0xf0, 0x007f0000);
-		regmap_write(eth->ethsys, 0xfc, 0x00001080);
-		enable_hw_idle = 1;
-	}
-	ret = regmap_read(eth->ethsys, 0x54, &val);
-	if (ret)
+	ret = netsys_pm_reset_adma(eth);
+	if (ret) {
+		netsys_pm_recovery(eth);
 		return ret;
-
-	pr_notice("0x15000054 is 0x%x\n", val);
-	val = val & 0x0C000002;
-	if (val == 0x0C000002) {
-		mtk_w32(eth, 0x05f2c040, 0x98c);
-		msleep(1);
-		mtk_w32(eth, 0x05f28040, 0x98c);
-		regmap_read(eth->ethsys, 0x54, &val);
-		pr_notice("NETSYS hw idle status: 0x%x\n", val);
-		msleep(3);
-	} else
-		pr_notice("ADMA related bus not idle!!!!\n");
+	}
 	pr_notice("ethernet suspend time reset ADMA = %lx\n", jiffies);
 
-	mtk_dma_free(eth);	
-	pr_notice("ethernet suspend time dma freee = %lx\n", jiffies);
+	mtk_stop_dma(eth, MTK_QDMA_GLO_CFG);
+	pr_notice("ethernet suspend time reset QDMA = %lx\n", jiffies);
+
+	mtk_dma_free(eth);
+	pr_notice("ethernet suspend time dma free = %lx\n", jiffies);
+
+	regmap_write(eth->ethsys, 0xe8, 0x80000000);
+	pr_notice("ethernet suspend time force AP_SRC DDR_EN off = %lx\n", jiffies);
 
 	mtk_clk_disable(eth);
 	pr_notice("ethernet suspend time clk disable = %lx\n", jiffies);
 	pr_notice("ethernet suspend time end = %lx\n", jiffies);
-	pr_notice("power down\n");
-	pr_notice("netsys suspend_noirq done\n");
-
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	return 0;
 }
 
@@ -4651,14 +4786,13 @@
 	const char *str;
 
 	pr_notice("ethernet resume time start = %lx\n", jiffies);
+
 	if (pdev == NULL) {
-		////pr_notice("%s pdev == NULL\n", __func__);
+		pr_notice("%s pdev == NULL\n", __func__); //jb.qi change for reboot after sleep on 20230417
 		return -1;
 	}
 
-	pr_notice("ethernet resume time start = %lx\n", jiffies);
 	eth = platform_get_drvdata(pdev);
-	pr_notice("ethernet resume platform_get_drvdata = %lx\n", jiffies);
 
 #if 0
 	regmap_update_bits(eth->ethsys, MTK_PPE_TB_CFG,
@@ -4668,11 +4802,10 @@
 			   SCAN_MODE_MASK,
 			   SCAN_MODE);
 #endif
-	mtk_clk_enable(eth);
-	pr_notice("ethernet resume mtk_clk_enable = %lx\n", jiffies);
 
+	mtk_clk_enable(eth);//jb.qi change for reboot after sleep on 20230417
 	mtk_hw_init_resume(eth);
-	pr_notice("ethernet resume mtk_hw_init_resume = %lx\n", jiffies);
+	pr_notice("ethernet resume time clk enable = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
 
 	//mtk_w32(eth, 0x27fb5, MTK_PPE_TB_CFG);
 	//mtk_w32(eth, 0x27fb5, MTK_PPE1_TB_CFG);
@@ -4744,7 +4877,6 @@
 	pr_notice("ethernet resume set GDM normal = %lx\n", jiffies);
 
 	mtk_w32(eth, 0x810000b0, 0);
-	//TBD check harry
 	if (eth->hwrss)
 		mtk_w32(eth, 0x002000a4, MTK_PDMA_LRO_CTRL_DW0);
 	else
@@ -4752,24 +4884,26 @@
 	mtk_w32(eth, 0x80001c04, MTK_PDMA_GLO_CFG);
 	pr_notice("ethernet resume ADMA setting  = %lx\n", jiffies);
 
-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY)) {
-		for (i = 0; i < MTK_MAC_COUNT; i++) {
-			if (!eth->netdev[i])
-				continue;
-
-			phy_start(eth->netdev[i]->phydev);
-		}
-	}
-
+	/* eth up */
 	for (i = 0; i < MTK_MAC_COUNT; i++) {
 		if (!eth->netdev[i])
 			continue;
+		/*jb.qi change for reboot after sleep on 20230417 start*/
+		pr_notice("restore %s state=%d mac%d=0x%x",
+			eth->netdev[i]->name,
+			eth->suspend_data.eth_state[i],
+			i, eth->suspend_data.mcr[i]);
 
-		netif_start_queue(eth->netdev[i]);
+		if (eth->suspend_data.eth_state[i] == 1) {
+			if (!MTK_HAS_CAPS(eth->soc->caps, MTK_DISABLE_PHY))
+				phy_start(eth->netdev[i]->phydev);
+			netif_start_queue(eth->netdev[i]);
+		}
+		/*jb.qi change for reboot after sleep on 20230417 end*/
 	}
-	pr_notice("ethernet resume netif_start_queue  = %lx\n", jiffies);
+
+	pr_notice("ethernet resume time eth up = %lx\n", jiffies);//jb.qi change for reboot after sleep on 20230417
 	pr_notice("ethernet resume time end = %lx\n", jiffies);
-	pr_notice("netsys resume_noirq done\n");
 
 	return 0;
 }
diff --git a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 5af8aca..2a5cffa 100644
--- a/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/src/kernel/linux/v4.19/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1022,7 +1022,12 @@
 	u32             flags[MTK_MAX_DEVS];
 	u32             ana_rgc3;
 };
-
+/*jb.qi change for reboot after sleep on 20230417 start*/
+struct mtk_suspend_data {
+	int		eth_state[MTK_MAX_DEVS];
+	u32		mcr[MTK_MAX_DEVS];
+};
+/*jb.qi change for reboot after sleep on 20230417 end*/
 /* struct mtk_eth -	This is the main datasructure for holding the state
  *			of the driver
  * @dev:		The device pointer
@@ -1074,6 +1079,8 @@
 	struct regmap			*ethsys;
 	struct regmap                   *infra;
 	struct regmap                   *wo;
+	struct regmap                   *wed;//jb.qi change for reboot after sleep on 20230417
+	struct regmap                   *wed2;//jb.qi change for reboot after sleep on 20230417
 	struct mtk_sgmii                *sgmii;
 	struct regmap			*pctl;
 	u32				hwlro;
@@ -1101,6 +1108,9 @@
 	struct mtk_tx_dma		*scratch_ring;
 	dma_addr_t			phy_scratch_ring;
 	void				*scratch_head;
+	dma_addr_t			phy_scratch_head;
+	size_t				scratch_head_size;
+
 	struct clk			*clks[MTK_CLK_MAX];
 
 	struct mii_bus			*mii_bus;
@@ -1121,6 +1131,8 @@
 	struct regulator		*dvfsrc_vcore_power;
 	unsigned int			irq_work;
 	struct work_struct		link_work;
+
+	struct mtk_suspend_data		suspend_data;//jb.qi change for reboot after sleep on 20230417
 };
 
 /* struct mtk_mac -	the structure that holds the info about the MACs of the
diff --git a/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c b/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
index 2c822d1..ca78b03 100755
--- a/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
+++ b/src/kernel/linux/v4.19/drivers/soc/mediatek/mtk-scpsys.c
@@ -1395,31 +1395,30 @@
 {
 	struct genpd_onecell_data *pd_data;
 	int i, ret;
-
 	for (i = 0; i < num; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		struct generic_pm_domain *genpd = &scpd->genpd;
-
+		bool on;//jb.qi change for reboot after sleep on 20230417
 		/*
-		 * Initially turn on all domains to make the domains usable
+		 * Initially turn on the domains to make the domains usable
 		 * with !CONFIG_PM and to get the hardware in sync with the
 		 * software.  The unused domains will be switched off during
 		 * late_init time.
+		 * Power on the ssusb/netsys/connectivity by default to let each driver
+		 * disable the clock in case of no usage.
 		 */
-		if(strcmp(genpd->name,"conn")){
-			if(strcmp(genpd->name,"ssusb_phy")==0)
-				dev_err(&pdev->dev, "Skip ssusb_phy & netsys pwr_on \n");
-			else if (strcmp(genpd->name,"netsys")==0){
-				ret = scpsys_clk_enable(scpd->clk, MAX_CLKS);
-				if (ret)
-					pr_notice("netsys clock on fail");
-				dev_err(&pdev->dev, "Skip netsys pwr_on \n");
-			}
-			else
-				genpd->power_on(genpd);
+		/*jb.qi change for reboot after sleep on 20230417 start*/
+		if (strcmp(genpd->name, "ssusb_phy") == 0 ||
+		    strcmp(genpd->name, "netsys") == 0 ||
+		    strcmp(genpd->name, "conn") == 0) {
+			on = false;
+			dev_err(&pdev->dev, "Skip %s pwr_on\n", genpd->name);
+		} else {
+			on = !WARN_ON(genpd->power_on(genpd) < 0);
 		}
 
-		pm_genpd_init(genpd, NULL, false);
+		pm_genpd_init(genpd, NULL, !on);
+		/*jb.qi change for reboot after sleep on 20230417 end*/
 	}
 
 	/*
@@ -1722,10 +1721,12 @@
 		.sram_pdn_ack_bits = GENMASK(12, 12),
 		.basic_clk_name = {"audio"},
 		.caps = MTK_SCPD_STRICT_BUSP,
+		/*jb.qi change for reboot after sleep on 20230417 start*/
 		.bp_table = {
 			BUS_PROT(IFR_TYPE, MT6779_IFR_SET, MT6779_IFR_CLR,
 				0, MT6779_IFR_STA1, BIT(31), BIT(31), 0),
 		},
+		/*jb.qi change for reboot after sleep on 20230417 end*/
 	},
 
 	[MT6779_POWER_DOMAIN_MM] = {
@@ -2093,7 +2094,7 @@
 		.sram_pdn_ack_bits2 = GENMASK(25, 25),
 		.clk_id = {CLK_NETSYS1, CLK_NETSYS2, CLK_NETSYS3, CLK_NETSYS4,
 		    CLK_NETSYS5, CLK_NETSYS6, CLK_NETSYS7, CLK_NETSYS8},
-		/*.bp_table = {
+		.bp_table = {
 			BUS_PROT(IFR_TYPE, 0x0714, 0x0718, 0x0710, 0x0724,
 				MT6890_TOP_AXI_PROT_EN_2_NETSYS,MT6890_TOP_AXI_PROT_EN_2_NETSYS,0),
 			BUS_PROT(IFR_TYPE, 0x02A0, 0x02A4, 0x0220, 0x0228,
@@ -2102,7 +2103,7 @@
 				MT6890_TOP_AXI_PROT_EN_NETSYS_2ND,MT6890_TOP_AXI_PROT_EN_NETSYS_2ND,0),
 			BUS_PROT(IFR_TYPE, 0x0714, 0x0718, 0x0710, 0x0724,
 				MT6890_TOP_AXI_PROT_EN_2_NETSYS_2ND,MT6890_TOP_AXI_PROT_EN_2_NETSYS_2ND,0),
-		},*/
+		},
 	},
 	[MT6890_POWER_DOMAIN_AUDIO] = {
 		.name = "audio",