1
0
Fork 0

scsi: hisi_sas: add v3 hw PHY init

Add code to configure PHYs for v3 hw.

Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
zero-colors
Xiang Chen 2017-06-14 23:33:22 +08:00 committed by Martin K. Petersen
parent c94d8ca2b1
commit 3975f6054e
1 changed files with 126 additions and 1 deletions

View File

@ -19,6 +19,10 @@
#define ITCT_BASE_ADDR_HI 0x14
#define IO_BROKEN_MSG_ADDR_LO 0x18
#define IO_BROKEN_MSG_ADDR_HI 0x1c
#define PHY_CONTEXT 0x20
#define PHY_STATE 0x24
#define PHY_PORT_NUM_MA 0x28
#define PHY_CONN_RATE 0x30
#define AXI_AHB_CLK_CFG 0x3c
#define AXI_USER1 0x48
#define AXI_USER2 0x4c
@ -42,6 +46,7 @@
#define CFG_SET_ABORTED_IPTT_OFF 0
#define CFG_SET_ABORTED_IPTT_MSK (0xfff << CFG_SET_ABORTED_IPTT_OFF)
#define CFG_1US_TIMER_TRSH 0xcc
#define CHNL_INT_STATUS 0x148
#define INT_COAL_EN 0x19c
#define OQ_INT_COAL_TIME 0x1a0
#define OQ_INT_COAL_CNT 0x1a4
@ -68,9 +73,11 @@
#define ENT_INT_SRC_MSK1 0x1c4
#define ENT_INT_SRC_MSK2 0x1c8
#define ENT_INT_SRC_MSK3 0x1cc
#define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
#define CHNL_PHYUPDOWN_INT_MSK 0x1d0
#define CHNL_ENT_INT_MSK 0x1d4
#define HGC_COM_INT_MSK 0x1d8
#define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
#define SAS_ECC_INTR 0x1e8
#define SAS_ECC_INTR_MSK 0x1ec
#define HGC_ERR_STAT_EN 0x238
@ -91,11 +98,33 @@
/* phy registers requiring init */
#define PORT_BASE (0x2000)
#define PHY_CFG (PORT_BASE + 0x0)
#define HARD_PHY_LINKRATE (PORT_BASE + 0x4)
#define PHY_CFG_ENA_OFF 0
#define PHY_CFG_ENA_MSK (0x1 << PHY_CFG_ENA_OFF)
#define PHY_CFG_DC_OPT_OFF 2
#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
#define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
#define PHY_CTRL (PORT_BASE + 0x14)
#define PHY_CTRL_RESET_OFF 0
#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
#define SL_CFG (PORT_BASE + 0x84)
#define SL_CONTROL (PORT_BASE + 0x94)
#define SL_CONTROL_NOTIFY_EN_OFF 0
#define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
#define SL_CTA_OFF 17
#define SL_CTA_MSK (0x1 << SL_CTA_OFF)
#define TX_ID_DWORD0 (PORT_BASE + 0x9c)
#define TX_ID_DWORD1 (PORT_BASE + 0xa0)
#define TX_ID_DWORD2 (PORT_BASE + 0xa4)
#define TX_ID_DWORD3 (PORT_BASE + 0xa8)
#define TX_ID_DWORD4 (PORT_BASE + 0xaC)
#define TX_ID_DWORD5 (PORT_BASE + 0xb0)
#define TX_ID_DWORD6 (PORT_BASE + 0xb4)
#define TXID_AUTO (PORT_BASE + 0xb8)
#define CT3_OFF 1
#define CT3_MSK (0x1 << CT3_OFF)
#define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
#define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
#define SAS_SSP_CON_TIMER_CFG (PORT_BASE + 0x134)
#define SAS_SMP_CON_TIMER_CFG (PORT_BASE + 0x138)
@ -136,6 +165,13 @@ struct hisi_sas_complete_v3_hdr {
};
#define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
#define HISI_SAS_MSI_COUNT_V3_HW 32
enum {
HISI_SAS_PHY_PHY_UPDOWN,
HISI_SAS_PHY_CHNL_INT,
HISI_SAS_PHY_INT_NR
};
static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
{
@ -152,6 +188,14 @@ static void hisi_sas_phy_write32(struct hisi_hba *hisi_hba, int phy_no,
writel(val, regs);
}
static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
int phy_no, u32 off)
{
void __iomem *regs = hisi_hba->regs + (0x400 * phy_no) + off;
return readl(regs);
}
static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
{
int i;
@ -266,6 +310,45 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
upper_32_bits(hisi_hba->initial_fis_dma));
}
static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
cfg &= ~PHY_CFG_DC_OPT_MSK;
cfg |= 1 << PHY_CFG_DC_OPT_OFF;
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
}
static void config_id_frame_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
struct sas_identify_frame identify_frame;
u32 *identify_buffer;
memset(&identify_frame, 0, sizeof(identify_frame));
identify_frame.dev_type = SAS_END_DEVICE;
identify_frame.frame_type = 0;
identify_frame._un1 = 1;
identify_frame.initiator_bits = SAS_PROTOCOL_ALL;
identify_frame.target_bits = SAS_PROTOCOL_NONE;
memcpy(&identify_frame._un4_11[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
memcpy(&identify_frame.sas_addr[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
identify_frame.phy_id = phy_no;
identify_buffer = (u32 *)(&identify_frame);
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
__swab32(identify_buffer[0]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
__swab32(identify_buffer[1]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
__swab32(identify_buffer[2]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
__swab32(identify_buffer[3]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
__swab32(identify_buffer[4]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
__swab32(identify_buffer[5]));
}
static int hw_init_v3_hw(struct hisi_hba *hisi_hba)
{
init_reg_v3_hw(hisi_hba);
@ -273,6 +356,47 @@ static int hw_init_v3_hw(struct hisi_hba *hisi_hba)
return 0;
}
static void enable_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
cfg |= PHY_CFG_ENA_MSK;
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
}
static void start_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
config_id_frame_v3_hw(hisi_hba, phy_no);
config_phy_opt_mode_v3_hw(hisi_hba, phy_no);
enable_phy_v3_hw(hisi_hba, phy_no);
}
static void start_phys_v3_hw(struct hisi_hba *hisi_hba)
{
int i;
for (i = 0; i < hisi_hba->n_phy; i++)
start_phy_v3_hw(hisi_hba, i);
}
static void phys_init_v3_hw(struct hisi_hba *hisi_hba)
{
start_phys_v3_hw(hisi_hba);
}
static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
{
u32 sl_control;
sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
sl_control |= SL_CONTROL_NOTIFY_EN_MSK;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
msleep(1);
sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
sl_control &= ~SL_CONTROL_NOTIFY_EN_MSK;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
}
static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
{
int rc;
@ -288,6 +412,8 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.hw_init = hisi_sas_v3_init,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V3_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr),
.sl_notify = sl_notify_v3_hw,
.phys_init = phys_init_v3_hw,
};
static struct Scsi_Host *
@ -451,7 +577,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
enum {
/* instances of the controller */
hip08,