.owner = THIS_MODULE,
 };
 
+static const struct {
+       char *name;
+} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = {
+       { "SAS_1_5_GBPS" },
+       { "SAS_3_0_GBPS" },
+       { "SAS_6_0_GBPS" },
+       { "SAS_12_0_GBPS" },
+       { "FFE_RESV" },
+       { "SATA_1_5_GBPS" },
+       { "SATA_3_0_GBPS" },
+       { "SATA_6_0_GBPS" },
+};
+
+static ssize_t hisi_sas_debugfs_write(struct file *filp,
+                                     const char __user *buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct seq_file *m = filp->private_data;
+       u32 *val = m->private;
+       int res;
+
+       res = kstrtouint_from_user(buf, count, 0, val);
+       if (res)
+               return res;
+
+       return count;
+}
+
+static int hisi_sas_debugfs_show(struct seq_file *s, void *p)
+{
+       u32 *val = s->private;
+
+       seq_printf(s, "0x%x\n", *val);
+
+       return 0;
+}
+
+static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, hisi_sas_debugfs_show,
+                          inode->i_private);
+}
+
+static const struct file_operations hisi_sas_debugfs_ops = {
+       .open = hisi_sas_debugfs_open,
+       .read = seq_read,
+       .write = hisi_sas_debugfs_write,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
 static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
                                                   const char __user *buf,
                                                   size_t count, loff_t *ppos)
 
 static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
 {
+       struct dentry *ports_dentry;
+       int phy_no;
+
        hisi_hba->debugfs_bist_dentry =
                        debugfs_create_dir("bist", hisi_hba->debugfs_dir);
        debugfs_create_file("link_rate", 0600,
        debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry,
                            hisi_hba, &hisi_sas_debugfs_bist_enable_ops);
 
+       ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry);
+
+       for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
+               struct dentry *port_dentry;
+               struct dentry *ffe_dentry;
+               char name[256];
+               int i;
+
+               snprintf(name, 256, "%d", phy_no);
+               port_dentry = debugfs_create_dir(name, ports_dentry);
+               ffe_dentry = debugfs_create_dir("ffe", port_dentry);
+               for (i = 0; i < FFE_CFG_MAX; i++) {
+                       if (i == FFE_RESV)
+                               continue;
+                       debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name,
+                                           0600, ffe_dentry,
+                                           &hisi_hba->debugfs_bist_ffe[phy_no][i],
+                                           &hisi_sas_debugfs_ops);
+               }
+       }
+
        hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
 }
 
 
 #define DMA_RX_STATUS_BUSY_MSK         (0x1 << DMA_RX_STATUS_BUSY_OFF)
 
 #define COARSETUNE_TIME                        (PORT_BASE + 0x304)
+#define TXDEEMPH_G1                    (PORT_BASE + 0x350)
 #define ERR_CNT_DWS_LOST               (PORT_BASE + 0x380)
 #define ERR_CNT_RESET_PROB             (PORT_BASE + 0x384)
 #define ERR_CNT_INVLD_DW               (PORT_BASE + 0x390)
 
 static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
 {
-       int i;
+       int i, j;
 
        /* Global registers init */
        hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
                /* used for 12G negotiate */
                hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
                hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff);
+
+               /* get default FFE configuration for BIST */
+               for (j = 0; j < FFE_CFG_MAX; j++) {
+                       u32 val = hisi_sas_phy_read32(hisi_hba, i,
+                                                     TXDEEMPH_G1 + (j * 0x4));
+                       hisi_hba->debugfs_bist_ffe[i][j] = val;
+               }
        }
 
        for (i = 0; i < hisi_hba->queue_count; i++) {
 {
        u32 reg_val;
        int phy_no = hisi_hba->debugfs_bist_phy_no;
+       int i;
 
        /* disable PHY */
        hisi_sas_phy_enable(hisi_hba, phy_no, 0);
 
+       /* update FFE */
+       for (i = 0; i < FFE_CFG_MAX; i++)
+               hisi_sas_phy_write32(hisi_hba, phy_no, TXDEEMPH_G1 + (i * 0x4),
+                                    hisi_hba->debugfs_bist_ffe[phy_no][i]);
+
        /* disable ALOS */
        reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG);
        reg_val |= CFG_ALOS_CHK_DISABLE_MSK;
        u32 reg_val, mode_tmp;
        u32 linkrate = hisi_hba->debugfs_bist_linkrate;
        u32 phy_no = hisi_hba->debugfs_bist_phy_no;
+       u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no];
        u32 code_mode = hisi_hba->debugfs_bist_code_mode;
        u32 path_mode = hisi_hba->debugfs_bist_mode;
        struct device *dev = hisi_hba->dev;
 
-       dev_info(dev, "BIST info:linkrate=%d phy_no=%d code_mode=%d path_mode=%d\n",
-                linkrate, phy_no, code_mode, path_mode);
+       dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x}\n",
+                phy_no, linkrate, code_mode, path_mode,
+                ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS],
+                ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS],
+                ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS],
+                ffe[FFE_SATA_6_0_GBPS]);
        mode_tmp = path_mode ? 2 : 1;
        if (enable) {
                /* some preparations before bist test */