Commit 97b151e7 authored by Xiang Chen's avatar Xiang Chen Committed by Martin K. Petersen

scsi: hisi_sas: Add BIST support for phy loopback

Add BIST (built in self test) support for phy loopback.

Through the new debugfs interface, the user can configure loopback
mode/linkrate/phy id/code mode before enabling it. And also user can
enable/disable BIST function.

Link: https://lore.kernel.org/r/1567774537-20003-13-git-send-email-john.garry@huawei.comSigned-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7ec7082c
...@@ -310,6 +310,7 @@ struct hisi_sas_hw { ...@@ -310,6 +310,7 @@ struct hisi_sas_hw {
int delay_ms, int timeout_ms); int delay_ms, int timeout_ms);
void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_prepare)(struct hisi_hba *hisi_hba);
void (*snapshot_restore)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba);
int (*set_bist)(struct hisi_hba *hisi_hba, bool enable);
void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba,
enum hisi_sas_debugfs_cache_type type, enum hisi_sas_debugfs_cache_type type,
u32 *cache); u32 *cache);
...@@ -391,6 +392,14 @@ struct hisi_hba { ...@@ -391,6 +392,14 @@ struct hisi_hba {
int cq_nvecs; int cq_nvecs;
unsigned int *reply_map; unsigned int *reply_map;
/* bist */
enum sas_linkrate debugfs_bist_linkrate;
int debugfs_bist_code_mode;
int debugfs_bist_phy_no;
int debugfs_bist_mode;
u32 debugfs_bist_cnt;
int debugfs_bist_enable;
/* debugfs memories */ /* debugfs memories */
/* Put Global AXI and RAS Register into register array */ /* Put Global AXI and RAS Register into register array */
u32 *debugfs_regs[DEBUGFS_REGS_NUM]; u32 *debugfs_regs[DEBUGFS_REGS_NUM];
...@@ -404,6 +413,7 @@ struct hisi_hba { ...@@ -404,6 +413,7 @@ struct hisi_hba {
struct dentry *debugfs_dir; struct dentry *debugfs_dir;
struct dentry *debugfs_dump_dentry; struct dentry *debugfs_dump_dentry;
struct dentry *debugfs_bist_dentry;
bool debugfs_snapshot; bool debugfs_snapshot;
}; };
......
This diff is collapsed.
...@@ -191,12 +191,30 @@ ...@@ -191,12 +191,30 @@
#define PHY_CFG_PHY_RST_OFF 3 #define PHY_CFG_PHY_RST_OFF 3
#define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF) #define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF)
#define PROG_PHY_LINK_RATE (PORT_BASE + 0x8) #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
#define CFG_PROG_PHY_LINK_RATE_OFF 8
#define CFG_PROG_PHY_LINK_RATE_MSK (0xf << CFG_PROG_PHY_LINK_RATE_OFF)
#define PHY_CTRL (PORT_BASE + 0x14) #define PHY_CTRL (PORT_BASE + 0x14)
#define PHY_CTRL_RESET_OFF 0 #define PHY_CTRL_RESET_OFF 0
#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF) #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
#define CMD_HDR_PIR_OFF 8 #define CMD_HDR_PIR_OFF 8
#define CMD_HDR_PIR_MSK (0x1 << CMD_HDR_PIR_OFF) #define CMD_HDR_PIR_MSK (0x1 << CMD_HDR_PIR_OFF)
#define SERDES_CFG (PORT_BASE + 0x1c) #define SERDES_CFG (PORT_BASE + 0x1c)
#define CFG_ALOS_CHK_DISABLE_OFF 9
#define CFG_ALOS_CHK_DISABLE_MSK (0x1 << CFG_ALOS_CHK_DISABLE_OFF)
#define SAS_PHY_BIST_CTRL (PORT_BASE + 0x2c)
#define CFG_BIST_MODE_SEL_OFF 0
#define CFG_BIST_MODE_SEL_MSK (0xf << CFG_BIST_MODE_SEL_OFF)
#define CFG_LOOP_TEST_MODE_OFF 14
#define CFG_LOOP_TEST_MODE_MSK (0x3 << CFG_LOOP_TEST_MODE_OFF)
#define CFG_RX_BIST_EN_OFF 16
#define CFG_RX_BIST_EN_MSK (0x1 << CFG_RX_BIST_EN_OFF)
#define CFG_TX_BIST_EN_OFF 17
#define CFG_TX_BIST_EN_MSK (0x1 << CFG_TX_BIST_EN_OFF)
#define CFG_BIST_TEST_OFF 18
#define CFG_BIST_TEST_MSK (0x1 << CFG_BIST_TEST_OFF)
#define SAS_PHY_BIST_CODE (PORT_BASE + 0x30)
#define SAS_PHY_BIST_CODE1 (PORT_BASE + 0x34)
#define SAS_BIST_ERR_CNT (PORT_BASE + 0x38)
#define SL_CFG (PORT_BASE + 0x84) #define SL_CFG (PORT_BASE + 0x84)
#define AIP_LIMIT (PORT_BASE + 0x90) #define AIP_LIMIT (PORT_BASE + 0x90)
#define SL_CONTROL (PORT_BASE + 0x94) #define SL_CONTROL (PORT_BASE + 0x94)
...@@ -2923,6 +2941,113 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba, ...@@ -2923,6 +2941,113 @@ static void read_iost_itct_cache_v3_hw(struct hisi_hba *hisi_hba,
buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX); buf[i] = hisi_sas_read32(hisi_hba, TAB_DFX);
} }
static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba)
{
u32 reg_val;
int phy_id = hisi_hba->debugfs_bist_phy_no;
/* disable PHY */
hisi_sas_phy_enable(hisi_hba, phy_id, 0);
/* disable ALOS */
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG);
reg_val |= CFG_ALOS_CHK_DISABLE_MSK;
hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val);
}
static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba)
{
u32 reg_val;
int phy_id = hisi_hba->debugfs_bist_phy_no;
/* disable loopback */
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL);
reg_val &= ~(CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK |
CFG_BIST_TEST_MSK);
hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL, reg_val);
/* enable ALOS */
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG);
reg_val &= ~CFG_ALOS_CHK_DISABLE_MSK;
hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val);
/* restore the linkrate */
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE);
/* init OOB link rate as 1.5 Gbits */
reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK;
reg_val |= (0x8 << CFG_PROG_PHY_LINK_RATE_OFF);
hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val);
/* enable PHY */
hisi_sas_phy_enable(hisi_hba, phy_id, 1);
}
#define SAS_PHY_BIST_CODE_INIT 0x1
#define SAS_PHY_BIST_CODE1_INIT 0X80
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_id = hisi_hba->debugfs_bist_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_id=%d code_mode=%d path_mode=%d\n",
linkrate, phy_id, code_mode, path_mode);
mode_tmp = path_mode ? 2 : 1;
if (enable) {
/* some preparations before bist test */
hisi_sas_bist_test_prep_v3_hw(hisi_hba);
/* set linkrate of bit test*/
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id,
PROG_PHY_LINK_RATE);
reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK;
reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF);
hisi_sas_phy_write32(hisi_hba, phy_id,
PROG_PHY_LINK_RATE, reg_val);
/* set code mode of bit test */
reg_val = hisi_sas_phy_read32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL);
reg_val &= ~(CFG_BIST_MODE_SEL_MSK |
CFG_LOOP_TEST_MODE_MSK |
CFG_RX_BIST_EN_MSK |
CFG_TX_BIST_EN_MSK |
CFG_BIST_TEST_MSK);
reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) |
(mode_tmp << CFG_LOOP_TEST_MODE_OFF) |
CFG_BIST_TEST_MSK);
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL, reg_val);
mdelay(100);
reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CTRL, reg_val);
/* set the bist init value */
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CODE,
SAS_PHY_BIST_CODE_INIT);
hisi_sas_phy_write32(hisi_hba, phy_id,
SAS_PHY_BIST_CODE1,
SAS_PHY_BIST_CODE1_INIT);
/* clear error bit */
mdelay(100);
hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT);
} else {
/* disable bist test and recover it */
hisi_hba->debugfs_bist_cnt += hisi_sas_phy_read32(hisi_hba,
phy_id, SAS_BIST_ERR_CNT);
hisi_sas_bist_test_restore_v3_hw(hisi_hba);
}
return 0;
}
static struct scsi_host_template sht_v3_hw = { static struct scsi_host_template sht_v3_hw = {
.name = DRV_NAME, .name = DRV_NAME,
.module = THIS_MODULE, .module = THIS_MODULE,
...@@ -2977,6 +3102,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { ...@@ -2977,6 +3102,7 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.snapshot_prepare = debugfs_snapshot_prepare_v3_hw, .snapshot_prepare = debugfs_snapshot_prepare_v3_hw,
.snapshot_restore = debugfs_snapshot_restore_v3_hw, .snapshot_restore = debugfs_snapshot_restore_v3_hw,
.read_iost_itct_cache = read_iost_itct_cache_v3_hw, .read_iost_itct_cache = read_iost_itct_cache_v3_hw,
.set_bist = debugfs_set_bist_v3_hw,
}; };
static struct Scsi_Host * static struct Scsi_Host *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment