#include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 
 
 module_platform_driver(g_dsaf_driver);
 
+/**
+ * hns_dsaf_roce_reset - reset dsaf and roce
+ * @dsaf_fwnode: Pointer to framework node for the dasf
+ * @enable: false - request reset , true - drop reset
+ * retuen 0 - success , negative -fail
+ */
+int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool enable)
+{
+       struct dsaf_device *dsaf_dev;
+       struct platform_device *pdev;
+       u32 mp;
+       u32 sl;
+       u32 credit;
+       int i;
+       const u32 port_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = {
+               {DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0},
+               {DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0},
+               {DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0},
+               {DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0},
+               {DSAF_ROCE_PORT_4, DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1},
+               {DSAF_ROCE_PORT_4, DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1},
+               {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1},
+               {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1},
+       };
+       const u32 sl_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = {
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_0},
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_1, DSAF_ROCE_SL_1},
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_2},
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_1, DSAF_ROCE_SL_3},
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_0},
+               {DSAF_ROCE_SL_1, DSAF_ROCE_SL_1, DSAF_ROCE_SL_1},
+               {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_2},
+               {DSAF_ROCE_SL_1, DSAF_ROCE_SL_1, DSAF_ROCE_SL_3},
+       };
+
+       if (!is_of_node(dsaf_fwnode)) {
+               pr_err("hisi_dsaf: Only support DT node!\n");
+               return -EINVAL;
+       }
+       pdev = of_find_device_by_node(to_of_node(dsaf_fwnode));
+       dsaf_dev = dev_get_drvdata(&pdev->dev);
+       if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
+               dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
+                       dsaf_dev->ae_dev.name);
+               return -ENODEV;
+       }
+
+       if (!enable) {
+               /* Reset rocee-channels in dsaf and rocee */
+               hns_dsaf_srst_chns(dsaf_dev, DSAF_CHNS_MASK, false);
+               hns_dsaf_roce_srst(dsaf_dev, false);
+       } else {
+               /* Configure dsaf tx roce correspond to port map and sl map */
+               mp = dsaf_read_dev(dsaf_dev, DSAF_ROCE_PORT_MAP_REG);
+               for (i = 0; i < DSAF_ROCE_CREDIT_CHN; i++)
+                       dsaf_set_field(mp, 7 << i * 3, i * 3,
+                                      port_map[i][DSAF_ROCE_6PORT_MODE]);
+               dsaf_set_field(mp, 3 << i * 3, i * 3, 0);
+               dsaf_write_dev(dsaf_dev, DSAF_ROCE_PORT_MAP_REG, mp);
+
+               sl = dsaf_read_dev(dsaf_dev, DSAF_ROCE_SL_MAP_REG);
+               for (i = 0; i < DSAF_ROCE_CREDIT_CHN; i++)
+                       dsaf_set_field(sl, 3 << i * 2, i * 2,
+                                      sl_map[i][DSAF_ROCE_6PORT_MODE]);
+               dsaf_write_dev(dsaf_dev, DSAF_ROCE_SL_MAP_REG, sl);
+
+               /* De-reset rocee-channels in dsaf and rocee */
+               hns_dsaf_srst_chns(dsaf_dev, DSAF_CHNS_MASK, true);
+               msleep(SRST_TIME_INTERVAL);
+               hns_dsaf_roce_srst(dsaf_dev, true);
+
+               /* Eanble dsaf channel rocee credit */
+               credit = dsaf_read_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG);
+               dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 0);
+               dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
+
+               dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 1);
+               dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
+       }
+       return 0;
+}
+EXPORT_SYMBOL(hns_dsaf_roce_reset);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
 MODULE_DESCRIPTION("HNS DSAF driver");
 
        dsaf_write_sub(dsaf_dev, reg_addr, reg_val);
 }
 
+/**
+ * hns_dsaf_srst_chns - reset dsaf channels
+ * @dsaf_dev: dsaf device struct pointer
+ * @msk: xbar channels mask value:
+ * bit0-5 for xge0-5
+ * bit6-11 for ppe0-5
+ * bit12-17 for roce0-5
+ * bit18-19 for com/dfx
+ * @enable: false - request reset , true - drop reset
+ */
+void hns_dsaf_srst_chns(struct dsaf_device *dsaf_dev, u32 msk, bool enable)
+{
+       u32 reg_addr;
+
+       if (!enable)
+               reg_addr = DSAF_SUB_SC_DSAF_RESET_REQ_REG;
+       else
+               reg_addr = DSAF_SUB_SC_DSAF_RESET_DREQ_REG;
+
+       dsaf_write_sub(dsaf_dev, reg_addr, msk);
+}
+
+void hns_dsaf_roce_srst(struct dsaf_device *dsaf_dev, bool enable)
+{
+       if (!enable) {
+               dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_RESET_REQ_REG, 1);
+       } else {
+               dsaf_write_sub(dsaf_dev,
+                              DSAF_SUB_SC_ROCEE_CLK_DIS_REG, 1);
+               dsaf_write_sub(dsaf_dev,
+                              DSAF_SUB_SC_ROCEE_RESET_DREQ_REG, 1);
+               msleep(20);
+               dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_CLK_EN_REG, 1);
+       }
+}
+
 static void
 hns_dsaf_xge_core_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
                                    u32 port, bool dereset)
 
 #define DSAF_SUB_SC_PPE_RESET_DREQ_REG                 0xA4C
 #define DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG          0xA88
 #define DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG         0xA8C
+#define DSAF_SUB_SC_DSAF_RESET_REQ_REG                 0xAA8
+#define DSAF_SUB_SC_ROCEE_RESET_REQ_REG                        0xA50
+#define DSAF_SUB_SC_DSAF_RESET_DREQ_REG                        0xAAC
+#define DSAF_SUB_SC_ROCEE_CLK_DIS_REG                  0x32C
+#define DSAF_SUB_SC_ROCEE_RESET_DREQ_REG               0xA54
+#define DSAF_SUB_SC_ROCEE_CLK_EN_REG                   0x328
 #define DSAF_SUB_SC_LIGHT_MODULE_DETECT_EN_REG         0x2060
 #define DSAF_SUB_SC_TCAM_MBIST_EN_REG                  0x2300
 #define DSAF_SUB_SC_DSAF_CLK_ST_REG                    0x5300
 #define DSAF_ROCEE_INT_STS_0_REG       0x200
 #define DSAFV2_SERDES_LBK_0_REG         0x220
 #define DSAF_PAUSE_CFG_REG             0x240
+#define DSAF_ROCE_PORT_MAP_REG         0x2A0
+#define DSAF_ROCE_SL_MAP_REG           0x2A4
 #define DSAF_PPE_QID_CFG_0_REG         0x300
 #define DSAF_SW_PORT_TYPE_0_REG                0x320
 #define DSAF_STP_PORT_TYPE_0_REG       0x340
 #define DSAF_SBM_BP_CFG_2_XGE_REG_0_REG                0x200C
 #define DSAF_SBM_BP_CFG_2_PPE_REG_0_REG                0x230C
 #define DSAF_SBM_BP_CFG_2_ROCEE_REG_0_REG      0x260C
+#define DSAF_SBM_ROCEE_CFG_REG_REG             0x2380
 #define DSAFV2_SBM_BP_CFG_2_ROCEE_REG_0_REG    0x238C
 #define DSAF_SBM_FREE_CNT_0_0_REG              0x2010
 #define DSAF_SBM_FREE_CNT_1_0_REG              0x2014
 #define DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_S 9
 #define DSAFV2_SBM_CFG4_RESET_BUF_NUM_NO_PFC_M (((1ULL << 9) - 1) << 9)
 
+#define DSAF_CHNS_MASK                 0x3f000
+#define DSAF_SBM_ROCEE_CFG_CRD_EN_B    2
+#define SRST_TIME_INTERVAL             20
 #define DSAFV2_SBM_CFG2_ROCEE_SET_BUF_NUM_S 0
 #define DSAFV2_SBM_CFG2_ROCEE_SET_BUF_NUM_M (((1ULL << 8) - 1) << 0)
 #define DSAFV2_SBM_CFG2_ROCEE_RESET_BUF_NUM_S 8