scsi: hisi_sas: Add BIST support for phy FFE
authorLuo Jiaxing <luojiaxing@huawei.com>
Tue, 1 Sep 2020 11:13:07 +0000 (19:13 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 3 Sep 2020 02:49:08 +0000 (22:49 -0400)
Add BIST support for phy FFE (Feed forward equalizer) setting. The user can
configure FFE through the new debugfs interface.

FFE is a parameter used for link layer control. It will affect the link
quality between the SAS controller and the backplane. In the BIST test, the
FFE interface is provided to assist board testers in optimizing link
parameters.

The modification of the FFE parameter will affect the test after BIST or
the normal running of the board. The user should save the initial FFE
values and restore them after BIST test is complete.

Link: https://lore.kernel.org/r/1598958790-232272-6-git-send-email-john.garry@huawei.com
Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hisi_sas/hisi_sas.h
drivers/scsi/hisi_sas/hisi_sas_main.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

index 2bdd64648ef0e4c01e63c6845237e9ad6b57971d..ce6a7d212afe2262632709c3618abd5aa37cafd2 100644 (file)
@@ -273,6 +273,18 @@ enum hisi_sas_debugfs_cache_type {
        HISI_SAS_IOST_CACHE,
 };
 
+enum hisi_sas_debugfs_bist_ffe_cfg {
+       FFE_SAS_1_5_GBPS,
+       FFE_SAS_3_0_GBPS,
+       FFE_SAS_6_0_GBPS,
+       FFE_SAS_12_0_GBPS,
+       FFE_RESV,
+       FFE_SATA_1_5_GBPS,
+       FFE_SATA_3_0_GBPS,
+       FFE_SATA_6_0_GBPS,
+       FFE_CFG_MAX
+};
+
 struct hisi_sas_hw {
        int (*hw_init)(struct hisi_hba *hisi_hba);
        void (*setup_itct)(struct hisi_hba *hisi_hba,
@@ -440,6 +452,7 @@ struct hisi_hba {
        int debugfs_bist_mode;
        u32 debugfs_bist_cnt;
        int debugfs_bist_enable;
+       u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX];
 
        /* debugfs memories */
        /* Put Global AXI and RAS Register into register array */
index fdf5f0f1b60bc452afe264807a5d966b9a0089be..6cd9b25fbbe7283f5050ed773f040154f1bd7de3 100644 (file)
@@ -3704,6 +3704,58 @@ static const struct file_operations hisi_sas_debugfs_bist_enable_ops = {
        .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)
@@ -3901,6 +3953,9 @@ static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
 
 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,
@@ -3924,6 +3979,27 @@ static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
        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;
 }
 
index 8a5c6f5e2a7a24faaaa1615041a6c3c361c8f040..f5d566832d6c6400db2b790c59fe1165a979a232 100644 (file)
 #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)
@@ -567,7 +568,7 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
 
 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,
@@ -637,6 +638,13 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
                /* 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++) {
@@ -2972,10 +2980,16 @@ static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba)
 {
        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;
@@ -3016,12 +3030,17 @@ static int debugfs_set_bist_v3_hw(struct hisi_hba *hisi_hba, bool enable)
        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 */