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>
This commit is contained in:
parent
c94d8ca2b1
commit
3975f6054e
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue