[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",
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/frame_engine.h b/src/kernel/modules/netsys_driver/nat/hw_nat/frame_engine.h
index d8d5ddb..49e1c6b 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/frame_engine.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/frame_engine.h
@@ -206,6 +206,9 @@
 #define CAH_WDATA           (PPE_BASE + 0x32C)
 #define CAH_RDATA           (PPE_BASE + 0x330)
 #define PPE_SBW_CTRL        (PPE_BASE + 0x374)
+#define PPE_S0_DBG          (PPE_BASE + 0x384)//jb.qi change for reboot after sleep on 20230417
+#define PPE_S1_DBG          (PPE_BASE + 0x388)//jb.qi change for reboot after sleep on 20230417
+#define PPE_S2_DBG          (PPE_BASE + 0x38C)//jb.qi change for reboot after sleep on 20230417
 
 #define PS_CFG	            (PPE_BASE + 0x400)
 #define PS_FBC		    (PPE_BASE + 0x404)
@@ -248,7 +251,7 @@
 
 #define MEDHW_SSR1_DST_RB0_CFG		(MED_BASE + 0xa0)
 #define MEDHW_SSR1_DST_RB0_STS		(MED_BASE + 0xa4)
-//MED_HNAT_INFO_HOST_ADD_ENTRY_CNT (18): 
+//MED_HNAT_INFO_HOST_ADD_ENTRY_CNT (18):\A0
 #define MEDHW_SSR1_DST_RB0_INC		(MED_BASE + 0xb0)
 #define MEDHW_SSR1_DST_RB0_DEC		(MED_BASE + 0xb4)
 
@@ -585,6 +588,9 @@
 #define MIB_CAH_CTRL_PPE1   (PPE1_BASE + 0x350)
 #define PPE1_6RD_ID	    (PPE1_BASE + 0x36c)
 #define PPE1_SBW_CTRL       (PPE1_BASE + 0x374)
+#define PPE1_S0_DBG         (PPE1_BASE + 0x384)//jb.qi change for reboot after sleep on 20230417
+#define PPE1_S1_DBG         (PPE1_BASE + 0x388)//jb.qi change for reboot after sleep on 20230417
+#define PPE1_S2_DBG         (PPE1_BASE + 0x38C)//jb.qi change for reboot after sleep on 20230417
 
 #define NETSYS_DVFS_CFG0		(netsys_base + 0xCC)
 #define NETSYS_DVFS_EN			BIT(0)
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
index 09360ce..e988c6d 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.c
@@ -3306,7 +3306,155 @@
 	else
 		return 0;
 }
+/*jb.qi change for reboot after sleep on 20230417 start*/
+void ppe_resume_foe_hash_mode(void)
+{
+	/* set foe table */
+	reg_write(PPE_FOE_BASE, ppe_phy_foe_base);
+	reg_write(MIB_TB_BASE, ppe_phy_mib_base);
 
+	reg_write(PPE1_FOE_BASE, ppe1_phy_foe_base);
+	reg_write(MIB_TB_BASE_PPE1, ppe1_phy_mib_base);
+
+
+	switch (FOE_4TB_SIZ) {
+	case 1024:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_1K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_1K, 0, 3);
+		break;
+
+	case 2048:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_2K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_2K, 0, 3);
+		break;
+
+	case 4096:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_4K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_4K, 0, 3);
+		break;
+
+	case 8192:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_8K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_8K, 0, 3);
+		break;
+
+	case 16384:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_16K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_16K, 0, 3);
+		break;
+
+	case 32768:
+		reg_modify_bits(PPE_FOE_CFG, FOE_TBL_SIZE_32K, 0, 3);
+		reg_modify_bits(PPE1_FOE_CFG, FOE_TBL_SIZE_32K, 0, 3);
+		break;
+	}
+
+	/* Set Hash Mode */
+	reg_modify_bits(PPE_FOE_CFG, DFL_FOE_HASH_MODE, 14, 2);
+	reg_modify_bits(PPE1_FOE_CFG, DFL_FOE_HASH_MODE, 14, 2);
+
+	reg_write(PPE_HASH_SEED, HASH_SEED);
+	reg_write(PPE1_HASH_SEED, HASH_SEED);
+
+	reg_modify_bits(PPE_FOE_CFG, 0, 18, 2);	/* disable */
+	reg_modify_bits(PPE1_FOE_CFG, 0, 18, 2);	/* disable */
+
+#ifdef CONFIG_RA_HW_NAT_PREBIND
+	reg_modify_bits(PPE_FOE_CFG, 1, 6, 1);	/* pre-bind age enable */
+	reg_modify_bits(PPE1_FOE_CFG, 1, 6, 1);	/* pre-bind age enable */
+
+#endif
+	/* Set action for FOE search miss */
+	reg_modify_bits(PPE_FOE_CFG, FWD_CPU_BUILD_ENTRY, 4, 2);
+	reg_modify_bits(PPE1_FOE_CFG, FWD_CPU_BUILD_ENTRY, 4, 2);
+}
+
+void ppe_set_gdm_fwd(uint32_t ebl)
+{
+	u32 data = 0;
+
+	data = reg_read(FE_GDMA1_FWD_CFG);
+	data &= ~0xffff;
+	if (ebl)
+		data |= 0x3333;
+	else
+		data |= 0x7777;
+	reg_write(FE_GDMA1_FWD_CFG, data);
+	pr_notice("%s: GDM1 val = 0x%x\n", __func__, data);
+
+	if (fe_feature & GE2_SUPPORT) {
+		data = reg_read(FE_GDMA2_FWD_CFG);
+		data &= ~0xffff;
+		if (ebl)
+			data |= 0x3333;
+		else
+			data |= 0x7777;
+		reg_write(FE_GDMA2_FWD_CFG, data);
+		pr_notice("%s: GDM2 val = 0x%x\n", __func__, data);
+	}
+
+	/* Reset and enable PSE */
+	//reg_write(FE_RST_GLO, 1);
+	//reg_write(FE_RST_GLO, 0);
+}
+
+void ppe_suspend_tbl_clear(void)
+{
+	u32 foe_tbl_size;
+
+	reg_modify_bits(PPE_FOE_CFG, ONLY_FWD_CPU, 4, 2);
+	reg_modify_bits(PPE1_FOE_CFG, ONLY_FWD_CPU, 4, 2);
+
+	/* clear cache table before enabling cache */
+	reg_modify_bits(CAH_CTRL, 1, 9, 1);
+	reg_modify_bits(CAH_CTRL, 0, 9, 1);
+
+	foe_tbl_size = FOE_4TB_SIZ * sizeof(struct foe_entry);
+	memset(ppe_foe_base, 0, foe_tbl_size);
+	memset(ppe1_foe_base, 0, foe_tbl_size);
+
+	/* Cache enable */
+	reg_modify_bits(CAH_CTRL, 1, 0, 1);
+	reg_modify_bits(CAH_CTRL_PPE1, 1, 9, 1);
+	reg_modify_bits(CAH_CTRL_PPE1, 0, 9, 1);
+	reg_modify_bits(CAH_CTRL_PPE1, 1, 0, 1);
+
+	reg_modify_bits(PPE_FOE_CFG, FWD_CPU_BUILD_ENTRY, 4, 2);
+	reg_modify_bits(PPE1_FOE_CFG, FWD_CPU_BUILD_ENTRY, 4, 2);
+}
+
+int ppe_suspend_check_status(void)
+{
+	u32 ppe0 = 0, ppe1 = 0, cnt = 0, pass = 0;
+
+	/* check continuous 10 pass in 1000 times */
+	for (cnt = 0; cnt < 1000; cnt++)
+	{
+		ppe0 = reg_read(PPE_GLO_CFG);
+		ppe1 = reg_read(PPE1_GLO_CFG);
+
+		if ((ppe0 & 0x80000000) || (ppe1 & 0x80000000)) {
+			pr_notice("cnt = %d: ppe0 = 0x%x, ppe1 = 0x%x\n", cnt, ppe0, ppe1);
+			pass = 0;
+		} else {
+			pass++;
+		}
+
+		if (pass > 10)
+			break;
+
+		/* sleep 1ms */
+		usleep_range(1000, 1100);
+	}
+
+	if (cnt == 1000) {
+		pr_notice("ppe0 = 0x%x, ppe1 = 0x%x\n", ppe0, ppe1);
+		return 1;
+	}
+
+	return 0;
+}
+/*jb.qi change for reboot after sleep on 20230417 end*/
 void ppe_setfoe_ebl(uint32_t foe_ebl)
 {
 	u32 ppe_flow_set = 0;
@@ -3704,7 +3852,7 @@
 }
 
 
-#if (1)
+#if (0) //jb.qi change for reboot after sleep on 20230417
 static void foe_free_tbl(uint32_t num_of_entry, struct device *dev)
 {
 	u32 foe_tbl_size, mib_tbl_size;
@@ -3759,14 +3907,29 @@
 
 	return 0;
 }
-
-#if (1)
-int ppe_eng_stop(struct device *dev)
+/*jb.qi change for reboot after sleep on 20230417 start*/
+void ppe_en_scan_mode(void)
 {
-	/*disable TB CFG*/
-	reg_write(PPE_TB_CFG, 0x2f000);
-	reg_write(PPE1_TB_CFG, 0x2f000);
+	/* enable scan mode */
+	reg_modify_bits(PPE_FOE_CFG, 2, 16, 2);
+	reg_modify_bits(PPE1_FOE_CFG, 2, 16, 2);
+}
 
+int ppe_dis_scan_mode(void)
+{
+	/* disable scan mode */
+	reg_modify_bits(PPE_FOE_CFG, 0, 16, 2);
+	reg_modify_bits(PPE1_FOE_CFG, 0, 16, 2);
+
+	/*disable TB CFG*/
+	reg_write(PPE_TB_CFG, 0xf000);
+	reg_write(PPE1_TB_CFG, 0xf000);
+
+	return 0;
+}
+
+int ppe_eng_stop(void) 
+{
 	/* Set PPE FOE ENABLE */
 	ppe_setfoe_glocfg_ebl(0);
 	ppe1_setfoe_glocfg_ebl(0);
@@ -3775,12 +3938,15 @@
 	ppe_setfoe_ebl(0);
 
 	/* Free FOE table */
-	foe_free_tbl(FOE_4TB_SIZ, dev);
+	//foe_free_tbl(FOE_4TB_SIZ, dev);
+
+	/* clear FOE table */
+	reg_write(PPE_FOE_BASE, 0);
+	reg_write(PPE1_FOE_BASE, 0);
 
 	return 0;
 }
-#endif
-
+/*jb.qi change for reboot after sleep on 20230417 end*/
 struct net_device *ra_dev_get_by_name(const char *name)
 {
 	return dev_get_by_name(&init_net, name);
@@ -4880,6 +5046,7 @@
 	ppe_set_cache_ebl();
 
 	/* Initialize PPE related register */
+	ppe_en_scan_mode(); //jb.qi change for reboot after sleep on 20230417
 	ppe_eng_start();
 }
 
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
index 22d132d..3be3d84 100755
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/hnat_common.h
@@ -59,7 +59,12 @@
 #ifndef NEXTHDR_IPIP
 #define NEXTHDR_IPIP 4
 #endif
-
+/*jb.qi change for reboot after sleep on 20230417 start*/
+void ppe_resume_foe_hash_mode(void);
+void ppe_set_gdm_fwd(uint32_t ebl);
+void ppe_suspend_tbl_clear(void);
+int ppe_suspend_check_status(void);
+/*jb.qi change for reboot after sleep on 20230417 end*/
 int ppe_setfoe_hash_mode(u32 hash_mode, struct device *dev);
 void ppe_set_dst_port(uint32_t ebl);
 void ppe_set_ip_prot(void);
@@ -133,5 +138,6 @@
 void hwnat_config_setting(void);
 void fe_feature_setting(void);
 void FOE_INFO_DUMP(struct sk_buff *skb);
-int ppe_eng_stop(struct device *dev);
+int ppe_dis_scan_mode(void);//jb.qi change for reboot after sleep on 20230417
+int ppe_eng_stop(void);//jb.qi change for reboot after sleep on 20230417
 #endif
diff --git a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
index ab0f906..2c64392 100644
--- a/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
+++ b/src/kernel/modules/netsys_driver/nat/hw_nat/ra_nat.c
@@ -519,7 +519,71 @@
 
 	return ret;
 }
+/*jb.qi change for reboot after sleep on 20230417 start*/
+void ppe_restore_hook(void)
+{
+	if (!(fe_feature & MANUAL_MODE)) {
+		ppe_hook_rx_wifi = ppe_rx_wifi_handler;
+		ppe_hook_tx_wifi = ppe_tx_wifi_handler;
+		ra_sw_nat_hook_rx = ppe_rx_wifi_handler;
+		ra_sw_nat_hook_tx = ppe_tx_wifi_handler;
+#ifdef CONFIG_MTK_TINYSYS_MEDMCU_SUPPORT
+		ppe_hook_rx_modem = ppe_rx_modem_handler;
+		ppe_hook_tx_modem = ppe_tx_modem_handler;
+#endif
+		ppe_hook_rx_rndis = ppe_rx_rndis_handler;
+		ppe_hook_tx_rndis = ppe_tx_rndis_handler;
 
+#ifdef	CONFIG_RAETH_EDMA
+		ppe_hook_rx_eth = NULL;
+		ppe_hook_tx_eth = NULL;
+#else
+		ppe_hook_rx_eth = ppe_rx_eth_handler;
+		ppe_hook_tx_eth = ppe_tx_eth_handler;
+#endif
+		ppe_hook_rx_ext = ppe_rx_ext_handler;
+		/* EDIA TX fast path is not ready */
+		ppe_hook_tx_ext = NULL;
+
+		ppe_hook_rx_snps = ppe_rx_snps_handler;
+		ppe_hook_tx_snps = ppe_tx_snps_handler;
+
+		ppe_get_dev_stats = ppe_get_dev_stats_handler;
+	}
+}
+
+void ppe_clear_hook(void)
+{
+	if (!(fe_feature & MANUAL_MODE)) {
+		ppe_hook_rx_wifi = NULL;
+		ppe_hook_tx_wifi = NULL;
+		ra_sw_nat_hook_rx = NULL;
+		ra_sw_nat_hook_tx = NULL;
+#ifdef CONFIG_MTK_TINYSYS_MEDMCU_SUPPORT
+		ppe_hook_rx_modem = NULL;
+		ppe_hook_tx_modem = NULL;
+#endif
+		ppe_hook_rx_rndis = NULL;
+		ppe_hook_tx_rndis = NULL;
+
+#ifdef	CONFIG_RAETH_EDMA
+		ppe_hook_rx_eth = NULL;
+		ppe_hook_tx_eth = NULL;
+#else
+		ppe_hook_rx_eth = NULL;
+		ppe_hook_tx_eth = NULL;
+#endif
+		ppe_hook_rx_ext = NULL;
+		/* EDIA TX fast path is not ready */
+		ppe_hook_tx_ext = NULL;
+
+		ppe_hook_rx_snps = NULL;
+		ppe_hook_tx_snps = NULL;
+
+		ppe_get_dev_stats = NULL;
+	}
+}
+/*jb.qi change for reboot after sleep on 20230417 end*/
 void ppe_modify_hook(bool clear, unsigned char hook_id, int dir) {
 
 	pr_info("ppe_modify_hook, clear = %d, hook_id = %d, dir=%d\n", clear, hook_id, dir);
@@ -609,34 +673,81 @@
 
 int hnat_pm_suspend(struct device *device)
 {
-	ppe_eng_stop(&pdev_hnat->dev);
+	/*jb.qi change for reboot after sleep on 20230417 start*/
+	int ret;
+
+	ppe_clear_hook();
+	pr_notice("!!!!  hnat stop all hook\n");
+
+	ppe_set_gdm_fwd(0);
+	pr_notice("!!!!  hnat set gdm drop all\n");
+
+	ppe_dis_scan_mode();
+	pr_notice("!!!!  hnat disable scan mode\n");
+
+	ret = ppe_suspend_check_status();
+	pr_notice("!!!!  hnat is %s\n", (ret)? "busy" : "idle");
+	if (ret)
+		goto error;
+
+	ppe_eng_stop();
+	pr_notice("!!!!  hnat stop ppe\n");
+
+	ppe_suspend_tbl_clear();
+	pr_notice("!!!!  hnat clear ppe table\n");
+
 	pr_notice("!!!!  hnat suspend done\n");
 
-	return 0;
+	pr_notice("!!!!  return\n");
+	return ret;
+
+error:
+	ppe_resume_foe_hash_mode();
+	ppe_eng_init();
+	ppe_restore_hook();
+
+	return ret;
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 }
 
 int hnat_pm_resume(struct device *device)
 {
 	NAT_PRINT("MEDIATEK HW NAT Module Enabled\n");
-
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	/* Set PPE FOE Hash Mode */
-	if (!ppe_setfoe_hash_mode(DFL_FOE_HASH_MODE, &pdev_hnat->dev)) {
-		pr_info("PPE0 memory allocation failed\n");
-		return -ENOMEM;	/* memory allocation failed */
-	}
+	//if (!ppe_setfoe_hash_mode(DFL_FOE_HASH_MODE, &pdev_hnat->dev)) {
+	//	pr_info("PPE0 memory allocation failed\n");
+	//	return -ENOMEM; /* memory allocation failed */
+	//}
 
-	if (!ppe1_setfoe_hash_mode(DFL_FOE_HASH_MODE, &pdev_hnat->dev)) {
-		pr_info("PPE1 memory allocation failed\n");
-		return -ENOMEM;	/* memory allocation failed */
-	}
+	//if (!ppe1_setfoe_hash_mode(DFL_FOE_HASH_MODE, &pdev_hnat->dev)) {
+	//	pr_info("PPE1 memory allocation failed\n");
+	//	return -ENOMEM; /* memory allocation failed */
+	//}
 
 	/* Register ioctl handler */
 	//ppe_reg_ioctl_handler(dev_hnat);
 
+	/* Set PPE FOE Table */
+	ppe_resume_foe_hash_mode();
+	pr_notice("!!!! hnat resume foe hash mode\n");
+
+	pr_notice("PPE_S0_DBG = 0x%x\n", reg_read(PPE_S0_DBG));
+	pr_notice("PPE_S1_DBG = 0x%x\n", reg_read(PPE_S1_DBG));
+	pr_notice("PPE_S2_DBG = 0x%x\n", reg_read(PPE_S2_DBG));
+	pr_notice("PPE1_S0_DBG = 0x%x\n", reg_read(PPE1_S0_DBG));
+	pr_notice("PPE1_S1_DBG = 0x%x\n", reg_read(PPE1_S1_DBG));
+	pr_notice("PPE1_S2_DBG = 0x%x\n", reg_read(PPE1_S2_DBG));
+
 	ppe_eng_init();
+	pr_notice("!!!! hnat resume ppe\n");
 
-	set_gdma_fwd(1);
+	ppe_set_gdm_fwd(1);
+	pr_notice("!!!! hnat set gdm ppe\n");
 
+	ppe_restore_hook();
+	pr_notice("!!!! hnat restore hook\n");
+	/*jb.qi change for reboot after sleep on 20230417 end*/
 	pr_notice("!!!! hnat resume done\n");
 
 	return 0;