12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23417ba8aSJohn Garry /*
33417ba8aSJohn Garry * Copyright (c) 2016 Linaro Ltd.
43417ba8aSJohn Garry * Copyright (c) 2016 Hisilicon Limited.
53417ba8aSJohn Garry */
63417ba8aSJohn Garry
73417ba8aSJohn Garry #include "hisi_sas.h"
83417ba8aSJohn Garry #define DRV_NAME "hisi_sas_v2_hw"
93417ba8aSJohn Garry
1045c901b8SJohn Garry /* global registers need init*/
1145c901b8SJohn Garry #define DLVRY_QUEUE_ENABLE 0x0
1245c901b8SJohn Garry #define IOST_BASE_ADDR_LO 0x8
1345c901b8SJohn Garry #define IOST_BASE_ADDR_HI 0xc
1445c901b8SJohn Garry #define ITCT_BASE_ADDR_LO 0x10
1545c901b8SJohn Garry #define ITCT_BASE_ADDR_HI 0x14
1645c901b8SJohn Garry #define IO_BROKEN_MSG_ADDR_LO 0x18
1745c901b8SJohn Garry #define IO_BROKEN_MSG_ADDR_HI 0x1c
1845c901b8SJohn Garry #define PHY_CONTEXT 0x20
1945c901b8SJohn Garry #define PHY_STATE 0x24
2045c901b8SJohn Garry #define PHY_PORT_NUM_MA 0x28
2145c901b8SJohn Garry #define PORT_STATE 0x2c
2245c901b8SJohn Garry #define PORT_STATE_PHY8_PORT_NUM_OFF 16
2345c901b8SJohn Garry #define PORT_STATE_PHY8_PORT_NUM_MSK (0xf << PORT_STATE_PHY8_PORT_NUM_OFF)
2445c901b8SJohn Garry #define PORT_STATE_PHY8_CONN_RATE_OFF 20
2545c901b8SJohn Garry #define PORT_STATE_PHY8_CONN_RATE_MSK (0xf << PORT_STATE_PHY8_CONN_RATE_OFF)
2645c901b8SJohn Garry #define PHY_CONN_RATE 0x30
2745c901b8SJohn Garry #define HGC_TRANS_TASK_CNT_LIMIT 0x38
2845c901b8SJohn Garry #define AXI_AHB_CLK_CFG 0x3c
2945c901b8SJohn Garry #define ITCT_CLR 0x44
3045c901b8SJohn Garry #define ITCT_CLR_EN_OFF 16
3145c901b8SJohn Garry #define ITCT_CLR_EN_MSK (0x1 << ITCT_CLR_EN_OFF)
3245c901b8SJohn Garry #define ITCT_DEV_OFF 0
3345c901b8SJohn Garry #define ITCT_DEV_MSK (0x7ff << ITCT_DEV_OFF)
3445c901b8SJohn Garry #define AXI_USER1 0x48
3545c901b8SJohn Garry #define AXI_USER2 0x4c
3645c901b8SJohn Garry #define IO_SATA_BROKEN_MSG_ADDR_LO 0x58
3745c901b8SJohn Garry #define IO_SATA_BROKEN_MSG_ADDR_HI 0x5c
3845c901b8SJohn Garry #define SATA_INITI_D2H_STORE_ADDR_LO 0x60
3945c901b8SJohn Garry #define SATA_INITI_D2H_STORE_ADDR_HI 0x64
4045c901b8SJohn Garry #define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL 0x84
4145c901b8SJohn Garry #define HGC_SAS_TXFAIL_RETRY_CTRL 0x88
4245c901b8SJohn Garry #define HGC_GET_ITV_TIME 0x90
4345c901b8SJohn Garry #define DEVICE_MSG_WORK_MODE 0x94
4445c901b8SJohn Garry #define OPENA_WT_CONTI_TIME 0x9c
4545c901b8SJohn Garry #define I_T_NEXUS_LOSS_TIME 0xa0
4645c901b8SJohn Garry #define MAX_CON_TIME_LIMIT_TIME 0xa4
4745c901b8SJohn Garry #define BUS_INACTIVE_LIMIT_TIME 0xa8
4845c901b8SJohn Garry #define REJECT_TO_OPEN_LIMIT_TIME 0xac
4945c901b8SJohn Garry #define CFG_AGING_TIME 0xbc
5045c901b8SJohn Garry #define HGC_DFX_CFG2 0xc0
5145c901b8SJohn Garry #define HGC_IOMB_PROC1_STATUS 0x104
5245c901b8SJohn Garry #define CFG_1US_TIMER_TRSH 0xcc
53d3b688d3SXiang Chen #define HGC_LM_DFX_STATUS2 0x128
54d3b688d3SXiang Chen #define HGC_LM_DFX_STATUS2_IOSTLIST_OFF 0
55d3b688d3SXiang Chen #define HGC_LM_DFX_STATUS2_IOSTLIST_MSK (0xfff << \
56d3b688d3SXiang Chen HGC_LM_DFX_STATUS2_IOSTLIST_OFF)
57d3b688d3SXiang Chen #define HGC_LM_DFX_STATUS2_ITCTLIST_OFF 12
58d3b688d3SXiang Chen #define HGC_LM_DFX_STATUS2_ITCTLIST_MSK (0x7ff << \
59d3b688d3SXiang Chen HGC_LM_DFX_STATUS2_ITCTLIST_OFF)
60d3b688d3SXiang Chen #define HGC_CQE_ECC_ADDR 0x13c
61d3b688d3SXiang Chen #define HGC_CQE_ECC_1B_ADDR_OFF 0
62ce41b41eSDan Carpenter #define HGC_CQE_ECC_1B_ADDR_MSK (0x3f << HGC_CQE_ECC_1B_ADDR_OFF)
63d3b688d3SXiang Chen #define HGC_CQE_ECC_MB_ADDR_OFF 8
64ce41b41eSDan Carpenter #define HGC_CQE_ECC_MB_ADDR_MSK (0x3f << HGC_CQE_ECC_MB_ADDR_OFF)
65d3b688d3SXiang Chen #define HGC_IOST_ECC_ADDR 0x140
66d3b688d3SXiang Chen #define HGC_IOST_ECC_1B_ADDR_OFF 0
67ce41b41eSDan Carpenter #define HGC_IOST_ECC_1B_ADDR_MSK (0x3ff << HGC_IOST_ECC_1B_ADDR_OFF)
68d3b688d3SXiang Chen #define HGC_IOST_ECC_MB_ADDR_OFF 16
69ce41b41eSDan Carpenter #define HGC_IOST_ECC_MB_ADDR_MSK (0x3ff << HGC_IOST_ECC_MB_ADDR_OFF)
70d3b688d3SXiang Chen #define HGC_DQE_ECC_ADDR 0x144
71d3b688d3SXiang Chen #define HGC_DQE_ECC_1B_ADDR_OFF 0
72ce41b41eSDan Carpenter #define HGC_DQE_ECC_1B_ADDR_MSK (0xfff << HGC_DQE_ECC_1B_ADDR_OFF)
73d3b688d3SXiang Chen #define HGC_DQE_ECC_MB_ADDR_OFF 16
74ce41b41eSDan Carpenter #define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF)
7545c901b8SJohn Garry #define HGC_INVLD_DQE_INFO 0x148
7645c901b8SJohn Garry #define HGC_INVLD_DQE_INFO_FB_CH0_OFF 9
7745c901b8SJohn Garry #define HGC_INVLD_DQE_INFO_FB_CH0_MSK (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF)
7845c901b8SJohn Garry #define HGC_INVLD_DQE_INFO_FB_CH3_OFF 18
79d3b688d3SXiang Chen #define HGC_ITCT_ECC_ADDR 0x150
80d3b688d3SXiang Chen #define HGC_ITCT_ECC_1B_ADDR_OFF 0
81d3b688d3SXiang Chen #define HGC_ITCT_ECC_1B_ADDR_MSK (0x3ff << \
82d3b688d3SXiang Chen HGC_ITCT_ECC_1B_ADDR_OFF)
83d3b688d3SXiang Chen #define HGC_ITCT_ECC_MB_ADDR_OFF 16
84d3b688d3SXiang Chen #define HGC_ITCT_ECC_MB_ADDR_MSK (0x3ff << \
85d3b688d3SXiang Chen HGC_ITCT_ECC_MB_ADDR_OFF)
86d3b688d3SXiang Chen #define HGC_AXI_FIFO_ERR_INFO 0x154
87d3b688d3SXiang Chen #define AXI_ERR_INFO_OFF 0
88d3b688d3SXiang Chen #define AXI_ERR_INFO_MSK (0xff << AXI_ERR_INFO_OFF)
89d3b688d3SXiang Chen #define FIFO_ERR_INFO_OFF 8
90d3b688d3SXiang Chen #define FIFO_ERR_INFO_MSK (0xff << FIFO_ERR_INFO_OFF)
9145c901b8SJohn Garry #define INT_COAL_EN 0x19c
9245c901b8SJohn Garry #define OQ_INT_COAL_TIME 0x1a0
9345c901b8SJohn Garry #define OQ_INT_COAL_CNT 0x1a4
9445c901b8SJohn Garry #define ENT_INT_COAL_TIME 0x1a8
9545c901b8SJohn Garry #define ENT_INT_COAL_CNT 0x1ac
9645c901b8SJohn Garry #define OQ_INT_SRC 0x1b0
9745c901b8SJohn Garry #define OQ_INT_SRC_MSK 0x1b4
9845c901b8SJohn Garry #define ENT_INT_SRC1 0x1b8
9945c901b8SJohn Garry #define ENT_INT_SRC1_D2H_FIS_CH0_OFF 0
10045c901b8SJohn Garry #define ENT_INT_SRC1_D2H_FIS_CH0_MSK (0x1 << ENT_INT_SRC1_D2H_FIS_CH0_OFF)
10145c901b8SJohn Garry #define ENT_INT_SRC1_D2H_FIS_CH1_OFF 8
10245c901b8SJohn Garry #define ENT_INT_SRC1_D2H_FIS_CH1_MSK (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF)
10345c901b8SJohn Garry #define ENT_INT_SRC2 0x1bc
10445c901b8SJohn Garry #define ENT_INT_SRC3 0x1c0
105d3b688d3SXiang Chen #define ENT_INT_SRC3_WP_DEPTH_OFF 8
106d3b688d3SXiang Chen #define ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF 9
107d3b688d3SXiang Chen #define ENT_INT_SRC3_RP_DEPTH_OFF 10
108d3b688d3SXiang Chen #define ENT_INT_SRC3_AXI_OFF 11
109d3b688d3SXiang Chen #define ENT_INT_SRC3_FIFO_OFF 12
110d3b688d3SXiang Chen #define ENT_INT_SRC3_LM_OFF 14
11145c901b8SJohn Garry #define ENT_INT_SRC3_ITC_INT_OFF 15
11245c901b8SJohn Garry #define ENT_INT_SRC3_ITC_INT_MSK (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
113d3b688d3SXiang Chen #define ENT_INT_SRC3_ABT_OFF 16
11445c901b8SJohn Garry #define ENT_INT_SRC_MSK1 0x1c4
11545c901b8SJohn Garry #define ENT_INT_SRC_MSK2 0x1c8
11645c901b8SJohn Garry #define ENT_INT_SRC_MSK3 0x1cc
11745c901b8SJohn Garry #define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
11845c901b8SJohn Garry #define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
119d3b688d3SXiang Chen #define SAS_ECC_INTR 0x1e8
120d3b688d3SXiang Chen #define SAS_ECC_INTR_DQE_ECC_1B_OFF 0
121d3b688d3SXiang Chen #define SAS_ECC_INTR_DQE_ECC_MB_OFF 1
122d3b688d3SXiang Chen #define SAS_ECC_INTR_IOST_ECC_1B_OFF 2
123d3b688d3SXiang Chen #define SAS_ECC_INTR_IOST_ECC_MB_OFF 3
124d3b688d3SXiang Chen #define SAS_ECC_INTR_ITCT_ECC_MB_OFF 4
125d3b688d3SXiang Chen #define SAS_ECC_INTR_ITCT_ECC_1B_OFF 5
126d3b688d3SXiang Chen #define SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF 6
127d3b688d3SXiang Chen #define SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF 7
128d3b688d3SXiang Chen #define SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF 8
129d3b688d3SXiang Chen #define SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF 9
130d3b688d3SXiang Chen #define SAS_ECC_INTR_CQE_ECC_1B_OFF 10
131d3b688d3SXiang Chen #define SAS_ECC_INTR_CQE_ECC_MB_OFF 11
132d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF 12
133d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF 13
134d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF 14
135d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF 15
136d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF 16
137d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF 17
138d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF 18
139d3b688d3SXiang Chen #define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF 19
14045c901b8SJohn Garry #define SAS_ECC_INTR_MSK 0x1ec
14145c901b8SJohn Garry #define HGC_ERR_STAT_EN 0x238
142a865ae14SXiaofei Tan #define CQE_SEND_CNT 0x248
14345c901b8SJohn Garry #define DLVRY_Q_0_BASE_ADDR_LO 0x260
14445c901b8SJohn Garry #define DLVRY_Q_0_BASE_ADDR_HI 0x264
14545c901b8SJohn Garry #define DLVRY_Q_0_DEPTH 0x268
14645c901b8SJohn Garry #define DLVRY_Q_0_WR_PTR 0x26c
14745c901b8SJohn Garry #define DLVRY_Q_0_RD_PTR 0x270
14845c901b8SJohn Garry #define HYPER_STREAM_ID_EN_CFG 0xc80
14945c901b8SJohn Garry #define OQ0_INT_SRC_MSK 0xc90
15045c901b8SJohn Garry #define COMPL_Q_0_BASE_ADDR_LO 0x4e0
15145c901b8SJohn Garry #define COMPL_Q_0_BASE_ADDR_HI 0x4e4
15245c901b8SJohn Garry #define COMPL_Q_0_DEPTH 0x4e8
15345c901b8SJohn Garry #define COMPL_Q_0_WR_PTR 0x4ec
15445c901b8SJohn Garry #define COMPL_Q_0_RD_PTR 0x4f0
155d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14 0xae8
156d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM0_OFF 0
157d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM0_MSK (0x1ff << \
158d3b688d3SXiang Chen HGC_RXM_DFX_STATUS14_MEM0_OFF)
159d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM1_OFF 9
160d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM1_MSK (0x1ff << \
161d3b688d3SXiang Chen HGC_RXM_DFX_STATUS14_MEM1_OFF)
162d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM2_OFF 18
163d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS14_MEM2_MSK (0x1ff << \
164d3b688d3SXiang Chen HGC_RXM_DFX_STATUS14_MEM2_OFF)
165d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS15 0xaec
166d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS15_MEM3_OFF 0
167d3b688d3SXiang Chen #define HGC_RXM_DFX_STATUS15_MEM3_MSK (0x1ff << \
168d3b688d3SXiang Chen HGC_RXM_DFX_STATUS15_MEM3_OFF)
16945c901b8SJohn Garry /* phy registers need init */
17045c901b8SJohn Garry #define PORT_BASE (0x2000)
17145c901b8SJohn Garry
17245c901b8SJohn Garry #define PHY_CFG (PORT_BASE + 0x0)
17345c901b8SJohn Garry #define HARD_PHY_LINKRATE (PORT_BASE + 0x4)
17445c901b8SJohn Garry #define PHY_CFG_ENA_OFF 0
17545c901b8SJohn Garry #define PHY_CFG_ENA_MSK (0x1 << PHY_CFG_ENA_OFF)
17645c901b8SJohn Garry #define PHY_CFG_DC_OPT_OFF 2
17745c901b8SJohn Garry #define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
17845c901b8SJohn Garry #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
17945c901b8SJohn Garry #define PROG_PHY_LINK_RATE_MAX_OFF 0
18045c901b8SJohn Garry #define PROG_PHY_LINK_RATE_MAX_MSK (0xff << PROG_PHY_LINK_RATE_MAX_OFF)
18145c901b8SJohn Garry #define PHY_CTRL (PORT_BASE + 0x14)
18245c901b8SJohn Garry #define PHY_CTRL_RESET_OFF 0
18345c901b8SJohn Garry #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
18445c901b8SJohn Garry #define SAS_PHY_CTRL (PORT_BASE + 0x20)
18545c901b8SJohn Garry #define SL_CFG (PORT_BASE + 0x84)
18645c901b8SJohn Garry #define PHY_PCN (PORT_BASE + 0x44)
18745c901b8SJohn Garry #define SL_TOUT_CFG (PORT_BASE + 0x8c)
18845c901b8SJohn Garry #define SL_CONTROL (PORT_BASE + 0x94)
18945c901b8SJohn Garry #define SL_CONTROL_NOTIFY_EN_OFF 0
19045c901b8SJohn Garry #define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
1919c81e2cfSJohn Garry #define SL_CONTROL_CTA_OFF 17
1929c81e2cfSJohn Garry #define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF)
19385080a25SXiang Chen #define RX_PRIMS_STATUS (PORT_BASE + 0x98)
19485080a25SXiang Chen #define RX_BCAST_CHG_OFF 1
19585080a25SXiang Chen #define RX_BCAST_CHG_MSK (0x1 << RX_BCAST_CHG_OFF)
19645c901b8SJohn Garry #define TX_ID_DWORD0 (PORT_BASE + 0x9c)
19745c901b8SJohn Garry #define TX_ID_DWORD1 (PORT_BASE + 0xa0)
19845c901b8SJohn Garry #define TX_ID_DWORD2 (PORT_BASE + 0xa4)
19945c901b8SJohn Garry #define TX_ID_DWORD3 (PORT_BASE + 0xa8)
20045c901b8SJohn Garry #define TX_ID_DWORD4 (PORT_BASE + 0xaC)
20145c901b8SJohn Garry #define TX_ID_DWORD5 (PORT_BASE + 0xb0)
20245c901b8SJohn Garry #define TX_ID_DWORD6 (PORT_BASE + 0xb4)
2039c81e2cfSJohn Garry #define TXID_AUTO (PORT_BASE + 0xb8)
2049c81e2cfSJohn Garry #define TXID_AUTO_CT3_OFF 1
2059c81e2cfSJohn Garry #define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF)
206819cbf18SXiaofei Tan #define TXID_AUTO_CTB_OFF 11
207819cbf18SXiaofei Tan #define TXID_AUTO_CTB_MSK (0x1 << TXID_AUTO_CTB_OFF)
2080edef7e4SXiang Chen #define TX_HARDRST_OFF 2
2090edef7e4SXiang Chen #define TX_HARDRST_MSK (0x1 << TX_HARDRST_OFF)
21045c901b8SJohn Garry #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
21145c901b8SJohn Garry #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
21245c901b8SJohn Garry #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
21345c901b8SJohn Garry #define RX_IDAF_DWORD3 (PORT_BASE + 0xd0)
21445c901b8SJohn Garry #define RX_IDAF_DWORD4 (PORT_BASE + 0xd4)
21545c901b8SJohn Garry #define RX_IDAF_DWORD5 (PORT_BASE + 0xd8)
21645c901b8SJohn Garry #define RX_IDAF_DWORD6 (PORT_BASE + 0xdc)
21745c901b8SJohn Garry #define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
218f2f89c32SXiang Chen #define CON_CONTROL (PORT_BASE + 0x118)
219c7b9d369SXiaofei Tan #define CON_CONTROL_CFG_OPEN_ACC_STP_OFF 0
220c7b9d369SXiaofei Tan #define CON_CONTROL_CFG_OPEN_ACC_STP_MSK \
221c7b9d369SXiaofei Tan (0x01 << CON_CONTROL_CFG_OPEN_ACC_STP_OFF)
22245c901b8SJohn Garry #define DONE_RECEIVED_TIME (PORT_BASE + 0x11c)
22345c901b8SJohn Garry #define CHL_INT0 (PORT_BASE + 0x1b4)
22445c901b8SJohn Garry #define CHL_INT0_HOTPLUG_TOUT_OFF 0
22545c901b8SJohn Garry #define CHL_INT0_HOTPLUG_TOUT_MSK (0x1 << CHL_INT0_HOTPLUG_TOUT_OFF)
22645c901b8SJohn Garry #define CHL_INT0_SL_RX_BCST_ACK_OFF 1
22745c901b8SJohn Garry #define CHL_INT0_SL_RX_BCST_ACK_MSK (0x1 << CHL_INT0_SL_RX_BCST_ACK_OFF)
22845c901b8SJohn Garry #define CHL_INT0_SL_PHY_ENABLE_OFF 2
22945c901b8SJohn Garry #define CHL_INT0_SL_PHY_ENABLE_MSK (0x1 << CHL_INT0_SL_PHY_ENABLE_OFF)
23045c901b8SJohn Garry #define CHL_INT0_NOT_RDY_OFF 4
23145c901b8SJohn Garry #define CHL_INT0_NOT_RDY_MSK (0x1 << CHL_INT0_NOT_RDY_OFF)
23245c901b8SJohn Garry #define CHL_INT0_PHY_RDY_OFF 5
23345c901b8SJohn Garry #define CHL_INT0_PHY_RDY_MSK (0x1 << CHL_INT0_PHY_RDY_OFF)
23445c901b8SJohn Garry #define CHL_INT1 (PORT_BASE + 0x1b8)
23545c901b8SJohn Garry #define CHL_INT1_DMAC_TX_ECC_ERR_OFF 15
23645c901b8SJohn Garry #define CHL_INT1_DMAC_TX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_TX_ECC_ERR_OFF)
23745c901b8SJohn Garry #define CHL_INT1_DMAC_RX_ECC_ERR_OFF 17
23845c901b8SJohn Garry #define CHL_INT1_DMAC_RX_ECC_ERR_MSK (0x1 << CHL_INT1_DMAC_RX_ECC_ERR_OFF)
23972f7fc30SXiaofei Tan #define CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF 19
24072f7fc30SXiaofei Tan #define CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF 20
24172f7fc30SXiaofei Tan #define CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF 21
24272f7fc30SXiaofei Tan #define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
24345c901b8SJohn Garry #define CHL_INT2 (PORT_BASE + 0x1bc)
244057c3d1fSXiaofei Tan #define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
24545c901b8SJohn Garry #define CHL_INT0_MSK (PORT_BASE + 0x1c0)
24645c901b8SJohn Garry #define CHL_INT1_MSK (PORT_BASE + 0x1c4)
24745c901b8SJohn Garry #define CHL_INT2_MSK (PORT_BASE + 0x1c8)
24845c901b8SJohn Garry #define CHL_INT_COAL_EN (PORT_BASE + 0x1d0)
249819cbf18SXiaofei Tan #define DMA_TX_DFX0 (PORT_BASE + 0x200)
250c7b9d369SXiaofei Tan #define DMA_TX_DFX1 (PORT_BASE + 0x204)
251c7b9d369SXiaofei Tan #define DMA_TX_DFX1_IPTT_OFF 0
252c7b9d369SXiaofei Tan #define DMA_TX_DFX1_IPTT_MSK (0xffff << DMA_TX_DFX1_IPTT_OFF)
253819cbf18SXiaofei Tan #define DMA_TX_FIFO_DFX0 (PORT_BASE + 0x240)
254819cbf18SXiaofei Tan #define PORT_DFX0 (PORT_BASE + 0x258)
255819cbf18SXiaofei Tan #define LINK_DFX2 (PORT_BASE + 0X264)
256819cbf18SXiaofei Tan #define LINK_DFX2_RCVR_HOLD_STS_OFF 9
257819cbf18SXiaofei Tan #define LINK_DFX2_RCVR_HOLD_STS_MSK (0x1 << LINK_DFX2_RCVR_HOLD_STS_OFF)
258819cbf18SXiaofei Tan #define LINK_DFX2_SEND_HOLD_STS_OFF 10
259819cbf18SXiaofei Tan #define LINK_DFX2_SEND_HOLD_STS_MSK (0x1 << LINK_DFX2_SEND_HOLD_STS_OFF)
260c52108c6SXiaofei Tan #define SAS_ERR_CNT4_REG (PORT_BASE + 0x290)
261c52108c6SXiaofei Tan #define SAS_ERR_CNT6_REG (PORT_BASE + 0x298)
26245c901b8SJohn Garry #define PHY_CTRL_RDY_MSK (PORT_BASE + 0x2b0)
26345c901b8SJohn Garry #define PHYCTRL_NOT_RDY_MSK (PORT_BASE + 0x2b4)
26445c901b8SJohn Garry #define PHYCTRL_DWS_RESET_MSK (PORT_BASE + 0x2b8)
26545c901b8SJohn Garry #define PHYCTRL_PHY_ENA_MSK (PORT_BASE + 0x2bc)
26645c901b8SJohn Garry #define SL_RX_BCAST_CHK_MSK (PORT_BASE + 0x2c0)
26745c901b8SJohn Garry #define PHYCTRL_OOB_RESTART_MSK (PORT_BASE + 0x2c4)
26845c901b8SJohn Garry #define DMA_TX_STATUS (PORT_BASE + 0x2d0)
26945c901b8SJohn Garry #define DMA_TX_STATUS_BUSY_OFF 0
27045c901b8SJohn Garry #define DMA_TX_STATUS_BUSY_MSK (0x1 << DMA_TX_STATUS_BUSY_OFF)
27145c901b8SJohn Garry #define DMA_RX_STATUS (PORT_BASE + 0x2e8)
27245c901b8SJohn Garry #define DMA_RX_STATUS_BUSY_OFF 0
27345c901b8SJohn Garry #define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
27445c901b8SJohn Garry
27545c901b8SJohn Garry #define AXI_CFG (0x5100)
27645c901b8SJohn Garry #define AM_CFG_MAX_TRANS (0x5010)
27745c901b8SJohn Garry #define AM_CFG_SINGLE_PORT_MAX_TRANS (0x5014)
27845c901b8SJohn Garry
27906ec0fb9SXiang Chen #define AXI_MASTER_CFG_BASE (0x5000)
28006ec0fb9SXiang Chen #define AM_CTRL_GLOBAL (0x0)
28106ec0fb9SXiang Chen #define AM_CURR_TRANS_RETURN (0x150)
28206ec0fb9SXiang Chen
28345c901b8SJohn Garry /* HW dma structures */
28445c901b8SJohn Garry /* Delivery queue header */
28545c901b8SJohn Garry /* dw0 */
286a3e665d9SJohn Garry #define CMD_HDR_ABORT_FLAG_OFF 0
287a3e665d9SJohn Garry #define CMD_HDR_ABORT_FLAG_MSK (0x3 << CMD_HDR_ABORT_FLAG_OFF)
288a3e665d9SJohn Garry #define CMD_HDR_ABORT_DEVICE_TYPE_OFF 2
289a3e665d9SJohn Garry #define CMD_HDR_ABORT_DEVICE_TYPE_MSK (0x1 << CMD_HDR_ABORT_DEVICE_TYPE_OFF)
29045c901b8SJohn Garry #define CMD_HDR_RESP_REPORT_OFF 5
29145c901b8SJohn Garry #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
29245c901b8SJohn Garry #define CMD_HDR_TLR_CTRL_OFF 6
29345c901b8SJohn Garry #define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF)
294b09fcd09SXiaofei Tan #define CMD_HDR_PHY_ID_OFF 8
295b09fcd09SXiaofei Tan #define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF)
296b09fcd09SXiaofei Tan #define CMD_HDR_FORCE_PHY_OFF 17
297b09fcd09SXiaofei Tan #define CMD_HDR_FORCE_PHY_MSK (0x1 << CMD_HDR_FORCE_PHY_OFF)
29845c901b8SJohn Garry #define CMD_HDR_PORT_OFF 18
29945c901b8SJohn Garry #define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF)
30045c901b8SJohn Garry #define CMD_HDR_PRIORITY_OFF 27
30145c901b8SJohn Garry #define CMD_HDR_PRIORITY_MSK (0x1 << CMD_HDR_PRIORITY_OFF)
30245c901b8SJohn Garry #define CMD_HDR_CMD_OFF 29
30345c901b8SJohn Garry #define CMD_HDR_CMD_MSK (0x7 << CMD_HDR_CMD_OFF)
30445c901b8SJohn Garry /* dw1 */
30545c901b8SJohn Garry #define CMD_HDR_DIR_OFF 5
30645c901b8SJohn Garry #define CMD_HDR_DIR_MSK (0x3 << CMD_HDR_DIR_OFF)
30745c901b8SJohn Garry #define CMD_HDR_RESET_OFF 7
30845c901b8SJohn Garry #define CMD_HDR_RESET_MSK (0x1 << CMD_HDR_RESET_OFF)
30945c901b8SJohn Garry #define CMD_HDR_VDTL_OFF 10
31045c901b8SJohn Garry #define CMD_HDR_VDTL_MSK (0x1 << CMD_HDR_VDTL_OFF)
31145c901b8SJohn Garry #define CMD_HDR_FRAME_TYPE_OFF 11
31245c901b8SJohn Garry #define CMD_HDR_FRAME_TYPE_MSK (0x1f << CMD_HDR_FRAME_TYPE_OFF)
31345c901b8SJohn Garry #define CMD_HDR_DEV_ID_OFF 16
31445c901b8SJohn Garry #define CMD_HDR_DEV_ID_MSK (0xffff << CMD_HDR_DEV_ID_OFF)
31545c901b8SJohn Garry /* dw2 */
31645c901b8SJohn Garry #define CMD_HDR_CFL_OFF 0
31745c901b8SJohn Garry #define CMD_HDR_CFL_MSK (0x1ff << CMD_HDR_CFL_OFF)
31845c901b8SJohn Garry #define CMD_HDR_NCQ_TAG_OFF 10
31945c901b8SJohn Garry #define CMD_HDR_NCQ_TAG_MSK (0x1f << CMD_HDR_NCQ_TAG_OFF)
32045c901b8SJohn Garry #define CMD_HDR_MRFL_OFF 15
32145c901b8SJohn Garry #define CMD_HDR_MRFL_MSK (0x1ff << CMD_HDR_MRFL_OFF)
32245c901b8SJohn Garry #define CMD_HDR_SG_MOD_OFF 24
32345c901b8SJohn Garry #define CMD_HDR_SG_MOD_MSK (0x3 << CMD_HDR_SG_MOD_OFF)
32445c901b8SJohn Garry #define CMD_HDR_FIRST_BURST_OFF 26
32545c901b8SJohn Garry #define CMD_HDR_FIRST_BURST_MSK (0x1 << CMD_HDR_SG_MOD_OFF)
32645c901b8SJohn Garry /* dw3 */
32745c901b8SJohn Garry #define CMD_HDR_IPTT_OFF 0
32845c901b8SJohn Garry #define CMD_HDR_IPTT_MSK (0xffff << CMD_HDR_IPTT_OFF)
32945c901b8SJohn Garry /* dw6 */
33045c901b8SJohn Garry #define CMD_HDR_DIF_SGL_LEN_OFF 0
33145c901b8SJohn Garry #define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF)
33245c901b8SJohn Garry #define CMD_HDR_DATA_SGL_LEN_OFF 16
33345c901b8SJohn Garry #define CMD_HDR_DATA_SGL_LEN_MSK (0xffff << CMD_HDR_DATA_SGL_LEN_OFF)
334a3e665d9SJohn Garry #define CMD_HDR_ABORT_IPTT_OFF 16
335a3e665d9SJohn Garry #define CMD_HDR_ABORT_IPTT_MSK (0xffff << CMD_HDR_ABORT_IPTT_OFF)
33645c901b8SJohn Garry
33745c901b8SJohn Garry /* Completion header */
33845c901b8SJohn Garry /* dw0 */
339634a9585SXiang Chen #define CMPLT_HDR_ERR_PHASE_OFF 2
340634a9585SXiang Chen #define CMPLT_HDR_ERR_PHASE_MSK (0xff << CMPLT_HDR_ERR_PHASE_OFF)
34145c901b8SJohn Garry #define CMPLT_HDR_RSPNS_XFRD_OFF 10
34245c901b8SJohn Garry #define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
34345c901b8SJohn Garry #define CMPLT_HDR_ERX_OFF 12
34445c901b8SJohn Garry #define CMPLT_HDR_ERX_MSK (0x1 << CMPLT_HDR_ERX_OFF)
345df032d0eSJohn Garry #define CMPLT_HDR_ABORT_STAT_OFF 13
346df032d0eSJohn Garry #define CMPLT_HDR_ABORT_STAT_MSK (0x7 << CMPLT_HDR_ABORT_STAT_OFF)
347df032d0eSJohn Garry /* abort_stat */
348df032d0eSJohn Garry #define STAT_IO_NOT_VALID 0x1
349df032d0eSJohn Garry #define STAT_IO_NO_DEVICE 0x2
350df032d0eSJohn Garry #define STAT_IO_COMPLETE 0x3
351df032d0eSJohn Garry #define STAT_IO_ABORTED 0x4
35245c901b8SJohn Garry /* dw1 */
35345c901b8SJohn Garry #define CMPLT_HDR_IPTT_OFF 0
35445c901b8SJohn Garry #define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF)
35545c901b8SJohn Garry #define CMPLT_HDR_DEV_ID_OFF 16
35645c901b8SJohn Garry #define CMPLT_HDR_DEV_ID_MSK (0xffff << CMPLT_HDR_DEV_ID_OFF)
35745c901b8SJohn Garry
35845c901b8SJohn Garry /* ITCT header */
35945c901b8SJohn Garry /* qw0 */
36045c901b8SJohn Garry #define ITCT_HDR_DEV_TYPE_OFF 0
36145c901b8SJohn Garry #define ITCT_HDR_DEV_TYPE_MSK (0x3 << ITCT_HDR_DEV_TYPE_OFF)
36245c901b8SJohn Garry #define ITCT_HDR_VALID_OFF 2
36345c901b8SJohn Garry #define ITCT_HDR_VALID_MSK (0x1 << ITCT_HDR_VALID_OFF)
36445c901b8SJohn Garry #define ITCT_HDR_MCR_OFF 5
36545c901b8SJohn Garry #define ITCT_HDR_MCR_MSK (0xf << ITCT_HDR_MCR_OFF)
36645c901b8SJohn Garry #define ITCT_HDR_VLN_OFF 9
36745c901b8SJohn Garry #define ITCT_HDR_VLN_MSK (0xf << ITCT_HDR_VLN_OFF)
368c399acfbSXiang Chen #define ITCT_HDR_SMP_TIMEOUT_OFF 16
369c399acfbSXiang Chen #define ITCT_HDR_SMP_TIMEOUT_8US 1
370c399acfbSXiang Chen #define ITCT_HDR_SMP_TIMEOUT (ITCT_HDR_SMP_TIMEOUT_8US * \
371c399acfbSXiang Chen 250) /* 2ms */
372c399acfbSXiang Chen #define ITCT_HDR_AWT_CONTINUE_OFF 25
37345c901b8SJohn Garry #define ITCT_HDR_PORT_ID_OFF 28
37445c901b8SJohn Garry #define ITCT_HDR_PORT_ID_MSK (0xf << ITCT_HDR_PORT_ID_OFF)
37545c901b8SJohn Garry /* qw2 */
37645c901b8SJohn Garry #define ITCT_HDR_INLT_OFF 0
37745c901b8SJohn Garry #define ITCT_HDR_INLT_MSK (0xffffULL << ITCT_HDR_INLT_OFF)
37845c901b8SJohn Garry #define ITCT_HDR_BITLT_OFF 16
37945c901b8SJohn Garry #define ITCT_HDR_BITLT_MSK (0xffffULL << ITCT_HDR_BITLT_OFF)
38045c901b8SJohn Garry #define ITCT_HDR_MCTLT_OFF 32
38145c901b8SJohn Garry #define ITCT_HDR_MCTLT_MSK (0xffffULL << ITCT_HDR_MCTLT_OFF)
38245c901b8SJohn Garry #define ITCT_HDR_RTOLT_OFF 48
38345c901b8SJohn Garry #define ITCT_HDR_RTOLT_MSK (0xffffULL << ITCT_HDR_RTOLT_OFF)
38445c901b8SJohn Garry
385d3b688d3SXiang Chen #define HISI_SAS_FATAL_INT_NR 2
386d3b688d3SXiang Chen
38794eac9e1SJohn Garry struct hisi_sas_complete_v2_hdr {
38894eac9e1SJohn Garry __le32 dw0;
38994eac9e1SJohn Garry __le32 dw1;
39094eac9e1SJohn Garry __le32 act;
39194eac9e1SJohn Garry __le32 dw3;
39294eac9e1SJohn Garry };
39394eac9e1SJohn Garry
394e8fed0e9SJohn Garry struct hisi_sas_err_record_v2 {
395e8fed0e9SJohn Garry /* dw0 */
396e8fed0e9SJohn Garry __le32 trans_tx_fail_type;
397e8fed0e9SJohn Garry
398e8fed0e9SJohn Garry /* dw1 */
399e8fed0e9SJohn Garry __le32 trans_rx_fail_type;
400e8fed0e9SJohn Garry
401e8fed0e9SJohn Garry /* dw2 */
402e8fed0e9SJohn Garry __le16 dma_tx_err_type;
403e8fed0e9SJohn Garry __le16 sipc_rx_err_type;
404e8fed0e9SJohn Garry
405e8fed0e9SJohn Garry /* dw3 */
406e8fed0e9SJohn Garry __le32 dma_rx_err_type;
407e8fed0e9SJohn Garry };
408e8fed0e9SJohn Garry
40967c2bf23SXiaofei Tan struct signal_attenuation_s {
41067c2bf23SXiaofei Tan u32 de_emphasis;
41167c2bf23SXiaofei Tan u32 preshoot;
41267c2bf23SXiaofei Tan u32 boost;
41367c2bf23SXiaofei Tan };
41467c2bf23SXiaofei Tan
41567c2bf23SXiaofei Tan struct sig_atten_lu_s {
41667c2bf23SXiaofei Tan const struct signal_attenuation_s *att;
41767c2bf23SXiaofei Tan u32 sas_phy_ctrl;
41867c2bf23SXiaofei Tan };
41967c2bf23SXiaofei Tan
4202b383351SJohn Garry static const struct hisi_sas_hw_error one_bit_ecc_errors[] = {
4212b383351SJohn Garry {
4222b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF),
4232b383351SJohn Garry .msk = HGC_DQE_ECC_1B_ADDR_MSK,
4242b383351SJohn Garry .shift = HGC_DQE_ECC_1B_ADDR_OFF,
425794327abSXiaofei Tan .msg = "hgc_dqe_ecc1b_intr",
4262b383351SJohn Garry .reg = HGC_DQE_ECC_ADDR,
4272b383351SJohn Garry },
4282b383351SJohn Garry {
4292b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_1B_OFF),
4302b383351SJohn Garry .msk = HGC_IOST_ECC_1B_ADDR_MSK,
4312b383351SJohn Garry .shift = HGC_IOST_ECC_1B_ADDR_OFF,
432794327abSXiaofei Tan .msg = "hgc_iost_ecc1b_intr",
4332b383351SJohn Garry .reg = HGC_IOST_ECC_ADDR,
4342b383351SJohn Garry },
4352b383351SJohn Garry {
4362b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_1B_OFF),
4372b383351SJohn Garry .msk = HGC_ITCT_ECC_1B_ADDR_MSK,
4382b383351SJohn Garry .shift = HGC_ITCT_ECC_1B_ADDR_OFF,
439794327abSXiaofei Tan .msg = "hgc_itct_ecc1b_intr",
4402b383351SJohn Garry .reg = HGC_ITCT_ECC_ADDR,
4412b383351SJohn Garry },
4422b383351SJohn Garry {
4432b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF),
4442b383351SJohn Garry .msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
4452b383351SJohn Garry .shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
446794327abSXiaofei Tan .msg = "hgc_iostl_ecc1b_intr",
4472b383351SJohn Garry .reg = HGC_LM_DFX_STATUS2,
4482b383351SJohn Garry },
4492b383351SJohn Garry {
4502b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF),
4512b383351SJohn Garry .msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
4522b383351SJohn Garry .shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
453794327abSXiaofei Tan .msg = "hgc_itctl_ecc1b_intr",
4542b383351SJohn Garry .reg = HGC_LM_DFX_STATUS2,
4552b383351SJohn Garry },
4562b383351SJohn Garry {
4572b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_1B_OFF),
4582b383351SJohn Garry .msk = HGC_CQE_ECC_1B_ADDR_MSK,
4592b383351SJohn Garry .shift = HGC_CQE_ECC_1B_ADDR_OFF,
460794327abSXiaofei Tan .msg = "hgc_cqe_ecc1b_intr",
4612b383351SJohn Garry .reg = HGC_CQE_ECC_ADDR,
4622b383351SJohn Garry },
4632b383351SJohn Garry {
4642b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF),
4652b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
4662b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
467794327abSXiaofei Tan .msg = "rxm_mem0_ecc1b_intr",
4682b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
4692b383351SJohn Garry },
4702b383351SJohn Garry {
4712b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF),
4722b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
4732b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
474794327abSXiaofei Tan .msg = "rxm_mem1_ecc1b_intr",
4752b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
4762b383351SJohn Garry },
4772b383351SJohn Garry {
4782b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF),
4792b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
4802b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
481794327abSXiaofei Tan .msg = "rxm_mem2_ecc1b_intr",
4822b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
4832b383351SJohn Garry },
4842b383351SJohn Garry {
4852b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF),
4862b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
4872b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
488794327abSXiaofei Tan .msg = "rxm_mem3_ecc1b_intr",
4892b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS15,
4902b383351SJohn Garry },
4912b383351SJohn Garry };
4922b383351SJohn Garry
4932b383351SJohn Garry static const struct hisi_sas_hw_error multi_bit_ecc_errors[] = {
4942b383351SJohn Garry {
4952b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_MB_OFF),
4962b383351SJohn Garry .msk = HGC_DQE_ECC_MB_ADDR_MSK,
4972b383351SJohn Garry .shift = HGC_DQE_ECC_MB_ADDR_OFF,
498794327abSXiaofei Tan .msg = "hgc_dqe_eccbad_intr",
4992b383351SJohn Garry .reg = HGC_DQE_ECC_ADDR,
5002b383351SJohn Garry },
5012b383351SJohn Garry {
5022b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_IOST_ECC_MB_OFF),
5032b383351SJohn Garry .msk = HGC_IOST_ECC_MB_ADDR_MSK,
5042b383351SJohn Garry .shift = HGC_IOST_ECC_MB_ADDR_OFF,
505794327abSXiaofei Tan .msg = "hgc_iost_eccbad_intr",
5062b383351SJohn Garry .reg = HGC_IOST_ECC_ADDR,
5072b383351SJohn Garry },
5082b383351SJohn Garry {
5092b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_ITCT_ECC_MB_OFF),
5102b383351SJohn Garry .msk = HGC_ITCT_ECC_MB_ADDR_MSK,
5112b383351SJohn Garry .shift = HGC_ITCT_ECC_MB_ADDR_OFF,
512794327abSXiaofei Tan .msg = "hgc_itct_eccbad_intr",
5132b383351SJohn Garry .reg = HGC_ITCT_ECC_ADDR,
5142b383351SJohn Garry },
5152b383351SJohn Garry {
5162b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF),
5172b383351SJohn Garry .msk = HGC_LM_DFX_STATUS2_IOSTLIST_MSK,
5182b383351SJohn Garry .shift = HGC_LM_DFX_STATUS2_IOSTLIST_OFF,
519794327abSXiaofei Tan .msg = "hgc_iostl_eccbad_intr",
5202b383351SJohn Garry .reg = HGC_LM_DFX_STATUS2,
5212b383351SJohn Garry },
5222b383351SJohn Garry {
5232b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF),
5242b383351SJohn Garry .msk = HGC_LM_DFX_STATUS2_ITCTLIST_MSK,
5252b383351SJohn Garry .shift = HGC_LM_DFX_STATUS2_ITCTLIST_OFF,
526794327abSXiaofei Tan .msg = "hgc_itctl_eccbad_intr",
5272b383351SJohn Garry .reg = HGC_LM_DFX_STATUS2,
5282b383351SJohn Garry },
5292b383351SJohn Garry {
5302b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_CQE_ECC_MB_OFF),
5312b383351SJohn Garry .msk = HGC_CQE_ECC_MB_ADDR_MSK,
5322b383351SJohn Garry .shift = HGC_CQE_ECC_MB_ADDR_OFF,
533794327abSXiaofei Tan .msg = "hgc_cqe_eccbad_intr",
5342b383351SJohn Garry .reg = HGC_CQE_ECC_ADDR,
5352b383351SJohn Garry },
5362b383351SJohn Garry {
5372b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF),
5382b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM0_MSK,
5392b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM0_OFF,
540794327abSXiaofei Tan .msg = "rxm_mem0_eccbad_intr",
5412b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
5422b383351SJohn Garry },
5432b383351SJohn Garry {
5442b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF),
5452b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM1_MSK,
5462b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM1_OFF,
547794327abSXiaofei Tan .msg = "rxm_mem1_eccbad_intr",
5482b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
5492b383351SJohn Garry },
5502b383351SJohn Garry {
5512b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF),
5522b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS14_MEM2_MSK,
5532b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS14_MEM2_OFF,
554794327abSXiaofei Tan .msg = "rxm_mem2_eccbad_intr",
5552b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS14,
5562b383351SJohn Garry },
5572b383351SJohn Garry {
5582b383351SJohn Garry .irq_msk = BIT(SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF),
5592b383351SJohn Garry .msk = HGC_RXM_DFX_STATUS15_MEM3_MSK,
5602b383351SJohn Garry .shift = HGC_RXM_DFX_STATUS15_MEM3_OFF,
561794327abSXiaofei Tan .msg = "rxm_mem3_eccbad_intr",
5622b383351SJohn Garry .reg = HGC_RXM_DFX_STATUS15,
5632b383351SJohn Garry },
5642b383351SJohn Garry };
5652b383351SJohn Garry
5667911e66fSJohn Garry enum {
5677911e66fSJohn Garry HISI_SAS_PHY_PHY_UPDOWN,
568d3bf3d84SJohn Garry HISI_SAS_PHY_CHNL_INT,
5697911e66fSJohn Garry HISI_SAS_PHY_INT_NR
5707911e66fSJohn Garry };
5717911e66fSJohn Garry
572e8fed0e9SJohn Garry enum {
573e8fed0e9SJohn Garry TRANS_TX_FAIL_BASE = 0x0, /* dw0 */
574634a9585SXiang Chen TRANS_RX_FAIL_BASE = 0x20, /* dw1 */
575634a9585SXiang Chen DMA_TX_ERR_BASE = 0x40, /* dw2 bit 15-0 */
576634a9585SXiang Chen SIPC_RX_ERR_BASE = 0x50, /* dw2 bit 31-16*/
577634a9585SXiang Chen DMA_RX_ERR_BASE = 0x60, /* dw3 */
578e8fed0e9SJohn Garry
579e8fed0e9SJohn Garry /* trans tx*/
580e8fed0e9SJohn Garry TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS = TRANS_TX_FAIL_BASE, /* 0x0 */
581e8fed0e9SJohn Garry TRANS_TX_ERR_PHY_NOT_ENABLE, /* 0x1 */
582e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION, /* 0x2 */
583e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION, /* 0x3 */
584e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_BY_OTHER, /* 0x4 */
585e8fed0e9SJohn Garry RESERVED0, /* 0x5 */
586e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT, /* 0x6 */
587e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_STP_RESOURCES_BUSY, /* 0x7 */
588e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED, /* 0x8 */
589e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED, /* 0x9 */
590e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION, /* 0xa */
591e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD, /* 0xb */
592e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER, /* 0xc */
593e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED, /* 0xd */
594e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT, /* 0xe */
595e8fed0e9SJohn Garry TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION, /* 0xf */
596e8fed0e9SJohn Garry TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED, /* 0x10 */
597e8fed0e9SJohn Garry TRANS_TX_ERR_FRAME_TXED, /* 0x11 */
598e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_BREAK_TIMEOUT, /* 0x12 */
599e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_BREAK_REQUEST, /* 0x13 */
600e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_BREAK_RECEVIED, /* 0x14 */
601e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CLOSE_TIMEOUT, /* 0x15 */
602e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CLOSE_NORMAL, /* 0x16 for ssp*/
603e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CLOSE_PHYDISALE, /* 0x17 */
604e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x18 */
605e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CLOSE_COMINIT, /* 0x19 */
606e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_NAK_RECEVIED, /* 0x1a for ssp*/
607e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT, /* 0x1b for ssp*/
608e8fed0e9SJohn Garry /*IO_TX_ERR_WITH_R_ERR_RECEVIED, [> 0x1b for sata/stp<] */
609e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_CREDIT_TIMEOUT, /* 0x1c for ssp */
610e8fed0e9SJohn Garry /*IO_RX_ERR_WITH_SATA_DEVICE_LOST 0x1c for sata/stp */
611e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_IPTT_CONFLICT, /* 0x1d for ssp/smp */
612e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_OPEN_BY_DES_OR_OTHERS, /* 0x1e */
613e8fed0e9SJohn Garry /*IO_TX_ERR_WITH_SYNC_RXD, [> 0x1e <] for sata/stp */
614e8fed0e9SJohn Garry TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT, /* 0x1f for sata/stp */
615e8fed0e9SJohn Garry
616e8fed0e9SJohn Garry /* trans rx */
617634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR = TRANS_RX_FAIL_BASE, /* 0x20 */
618634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR, /* 0x21 for sata/stp */
619634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM, /* 0x22 for ssp/smp */
620634a9585SXiang Chen /*IO_ERR_WITH_RXFIS_8B10B_CODE_ERR, [> 0x22 <] for sata/stp */
621634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR, /* 0x23 for sata/stp */
622634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_CRC_ERR, /* 0x24 for sata/stp */
623634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN, /* 0x25 for smp */
624634a9585SXiang Chen /*IO_ERR_WITH_RXFIS_TX SYNCP, [> 0x25 <] for sata/stp */
625634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP, /* 0x26 for sata/stp*/
626634a9585SXiang Chen TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN, /* 0x27 */
627634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_TIMEOUT, /* 0x28 */
628634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_REQUEST, /* 0x29 */
629634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_RECEVIED, /* 0x2a */
630634a9585SXiang Chen RESERVED1, /* 0x2b */
631634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_NORMAL, /* 0x2c */
632634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE, /* 0x2d */
633634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x2e */
634634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_COMINIT, /* 0x2f */
635634a9585SXiang Chen TRANS_RX_ERR_WITH_DATA_LEN0, /* 0x30 for ssp/smp */
636634a9585SXiang Chen TRANS_RX_ERR_WITH_BAD_HASH, /* 0x31 for ssp */
637634a9585SXiang Chen /*IO_RX_ERR_WITH_FIS_TOO_SHORT, [> 0x31 <] for sata/stp */
638634a9585SXiang Chen TRANS_RX_XRDY_WLEN_ZERO_ERR, /* 0x32 for ssp*/
639634a9585SXiang Chen /*IO_RX_ERR_WITH_FIS_TOO_LONG, [> 0x32 <] for sata/stp */
640634a9585SXiang Chen TRANS_RX_SSP_FRM_LEN_ERR, /* 0x33 for ssp */
641634a9585SXiang Chen /*IO_RX_ERR_WITH_SATA_DEVICE_LOST, [> 0x33 <] for sata */
642634a9585SXiang Chen RESERVED2, /* 0x34 */
643634a9585SXiang Chen RESERVED3, /* 0x35 */
644634a9585SXiang Chen RESERVED4, /* 0x36 */
645634a9585SXiang Chen RESERVED5, /* 0x37 */
646634a9585SXiang Chen TRANS_RX_ERR_WITH_BAD_FRM_TYPE, /* 0x38 */
647634a9585SXiang Chen TRANS_RX_SMP_FRM_LEN_ERR, /* 0x39 */
648634a9585SXiang Chen TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x3a */
649634a9585SXiang Chen RESERVED6, /* 0x3b */
650634a9585SXiang Chen RESERVED7, /* 0x3c */
651634a9585SXiang Chen RESERVED8, /* 0x3d */
652634a9585SXiang Chen RESERVED9, /* 0x3e */
653634a9585SXiang Chen TRANS_RX_R_ERR, /* 0x3f */
654e8fed0e9SJohn Garry
655e8fed0e9SJohn Garry /* dma tx */
656634a9585SXiang Chen DMA_TX_DIF_CRC_ERR = DMA_TX_ERR_BASE, /* 0x40 */
657634a9585SXiang Chen DMA_TX_DIF_APP_ERR, /* 0x41 */
658634a9585SXiang Chen DMA_TX_DIF_RPP_ERR, /* 0x42 */
659634a9585SXiang Chen DMA_TX_DATA_SGL_OVERFLOW, /* 0x43 */
660634a9585SXiang Chen DMA_TX_DIF_SGL_OVERFLOW, /* 0x44 */
661634a9585SXiang Chen DMA_TX_UNEXP_XFER_ERR, /* 0x45 */
662634a9585SXiang Chen DMA_TX_UNEXP_RETRANS_ERR, /* 0x46 */
663634a9585SXiang Chen DMA_TX_XFER_LEN_OVERFLOW, /* 0x47 */
664634a9585SXiang Chen DMA_TX_XFER_OFFSET_ERR, /* 0x48 */
665634a9585SXiang Chen DMA_TX_RAM_ECC_ERR, /* 0x49 */
666634a9585SXiang Chen DMA_TX_DIF_LEN_ALIGN_ERR, /* 0x4a */
667634a9585SXiang Chen DMA_TX_MAX_ERR_CODE,
668e8fed0e9SJohn Garry
669e8fed0e9SJohn Garry /* sipc rx */
670634a9585SXiang Chen SIPC_RX_FIS_STATUS_ERR_BIT_VLD = SIPC_RX_ERR_BASE, /* 0x50 */
671634a9585SXiang Chen SIPC_RX_PIO_WRSETUP_STATUS_DRQ_ERR, /* 0x51 */
672634a9585SXiang Chen SIPC_RX_FIS_STATUS_BSY_BIT_ERR, /* 0x52 */
673634a9585SXiang Chen SIPC_RX_WRSETUP_LEN_ODD_ERR, /* 0x53 */
674634a9585SXiang Chen SIPC_RX_WRSETUP_LEN_ZERO_ERR, /* 0x54 */
675634a9585SXiang Chen SIPC_RX_WRDATA_LEN_NOT_MATCH_ERR, /* 0x55 */
676634a9585SXiang Chen SIPC_RX_NCQ_WRSETUP_OFFSET_ERR, /* 0x56 */
677634a9585SXiang Chen SIPC_RX_NCQ_WRSETUP_AUTO_ACTIVE_ERR, /* 0x57 */
678634a9585SXiang Chen SIPC_RX_SATA_UNEXP_FIS_ERR, /* 0x58 */
679634a9585SXiang Chen SIPC_RX_WRSETUP_ESTATUS_ERR, /* 0x59 */
680634a9585SXiang Chen SIPC_RX_DATA_UNDERFLOW_ERR, /* 0x5a */
681634a9585SXiang Chen SIPC_RX_MAX_ERR_CODE,
682e8fed0e9SJohn Garry
683e8fed0e9SJohn Garry /* dma rx */
684634a9585SXiang Chen DMA_RX_DIF_CRC_ERR = DMA_RX_ERR_BASE, /* 0x60 */
685634a9585SXiang Chen DMA_RX_DIF_APP_ERR, /* 0x61 */
686634a9585SXiang Chen DMA_RX_DIF_RPP_ERR, /* 0x62 */
687634a9585SXiang Chen DMA_RX_DATA_SGL_OVERFLOW, /* 0x63 */
688634a9585SXiang Chen DMA_RX_DIF_SGL_OVERFLOW, /* 0x64 */
689634a9585SXiang Chen DMA_RX_DATA_LEN_OVERFLOW, /* 0x65 */
690634a9585SXiang Chen DMA_RX_DATA_LEN_UNDERFLOW, /* 0x66 */
691634a9585SXiang Chen DMA_RX_DATA_OFFSET_ERR, /* 0x67 */
692634a9585SXiang Chen RESERVED10, /* 0x68 */
693634a9585SXiang Chen DMA_RX_SATA_FRAME_TYPE_ERR, /* 0x69 */
694634a9585SXiang Chen DMA_RX_RESP_BUF_OVERFLOW, /* 0x6a */
695634a9585SXiang Chen DMA_RX_UNEXP_RETRANS_RESP_ERR, /* 0x6b */
696634a9585SXiang Chen DMA_RX_UNEXP_NORM_RESP_ERR, /* 0x6c */
697634a9585SXiang Chen DMA_RX_UNEXP_RDFRAME_ERR, /* 0x6d */
698634a9585SXiang Chen DMA_RX_PIO_DATA_LEN_ERR, /* 0x6e */
699634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_ERR, /* 0x6f */
700634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_DRQ_ERR, /* 0x70 */
701634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_BSY_ERR, /* 0x71 */
702634a9585SXiang Chen DMA_RX_RDSETUP_LEN_ODD_ERR, /* 0x72 */
703634a9585SXiang Chen DMA_RX_RDSETUP_LEN_ZERO_ERR, /* 0x73 */
704634a9585SXiang Chen DMA_RX_RDSETUP_LEN_OVER_ERR, /* 0x74 */
705634a9585SXiang Chen DMA_RX_RDSETUP_OFFSET_ERR, /* 0x75 */
706634a9585SXiang Chen DMA_RX_RDSETUP_ACTIVE_ERR, /* 0x76 */
707634a9585SXiang Chen DMA_RX_RDSETUP_ESTATUS_ERR, /* 0x77 */
708634a9585SXiang Chen DMA_RX_RAM_ECC_ERR, /* 0x78 */
709634a9585SXiang Chen DMA_RX_UNKNOWN_FRM_ERR, /* 0x79 */
710634a9585SXiang Chen DMA_RX_MAX_ERR_CODE,
711e8fed0e9SJohn Garry };
712e8fed0e9SJohn Garry
71394eac9e1SJohn Garry #define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
71432ccba52SXiaofei Tan #define HISI_MAX_SATA_SUPPORT_V2_HW (HISI_SAS_COMMAND_ENTRIES_V2_HW/64 - 1)
71594eac9e1SJohn Garry
7168c36e31dSJohn Garry #define DIR_NO_DATA 0
7178c36e31dSJohn Garry #define DIR_TO_INI 1
7188c36e31dSJohn Garry #define DIR_TO_DEVICE 2
7198c36e31dSJohn Garry #define DIR_RESERVED 3
7208c36e31dSJohn Garry
721634a9585SXiang Chen #define ERR_ON_TX_PHASE(err_phase) (err_phase == 0x2 || \
722634a9585SXiang Chen err_phase == 0x4 || err_phase == 0x8 ||\
723634a9585SXiang Chen err_phase == 0x6 || err_phase == 0xa)
724634a9585SXiang Chen #define ERR_ON_RX_PHASE(err_phase) (err_phase == 0x10 || \
725634a9585SXiang Chen err_phase == 0x20 || err_phase == 0x40)
726634a9585SXiang Chen
72777570eedSKees Cook static void link_timeout_disable_link(struct timer_list *t);
728f2f89c32SXiang Chen
hisi_sas_read32(struct hisi_hba * hisi_hba,u32 off)72994eac9e1SJohn Garry static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
73094eac9e1SJohn Garry {
73194eac9e1SJohn Garry void __iomem *regs = hisi_hba->regs + off;
73294eac9e1SJohn Garry
73394eac9e1SJohn Garry return readl(regs);
73494eac9e1SJohn Garry }
73594eac9e1SJohn Garry
hisi_sas_read32_relaxed(struct hisi_hba * hisi_hba,u32 off)7368c36e31dSJohn Garry static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off)
7378c36e31dSJohn Garry {
7388c36e31dSJohn Garry void __iomem *regs = hisi_hba->regs + off;
7398c36e31dSJohn Garry
7408c36e31dSJohn Garry return readl_relaxed(regs);
7418c36e31dSJohn Garry }
7428c36e31dSJohn Garry
hisi_sas_write32(struct hisi_hba * hisi_hba,u32 off,u32 val)74394eac9e1SJohn Garry static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
74494eac9e1SJohn Garry {
74594eac9e1SJohn Garry void __iomem *regs = hisi_hba->regs + off;
74694eac9e1SJohn Garry
74794eac9e1SJohn Garry writel(val, regs);
74894eac9e1SJohn Garry }
74994eac9e1SJohn Garry
hisi_sas_phy_write32(struct hisi_hba * hisi_hba,int phy_no,u32 off,u32 val)75094eac9e1SJohn Garry static void hisi_sas_phy_write32(struct hisi_hba *hisi_hba, int phy_no,
75194eac9e1SJohn Garry u32 off, u32 val)
75294eac9e1SJohn Garry {
75394eac9e1SJohn Garry void __iomem *regs = hisi_hba->regs + (0x400 * phy_no) + off;
75494eac9e1SJohn Garry
75594eac9e1SJohn Garry writel(val, regs);
75694eac9e1SJohn Garry }
75794eac9e1SJohn Garry
hisi_sas_phy_read32(struct hisi_hba * hisi_hba,int phy_no,u32 off)75894eac9e1SJohn Garry static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
75994eac9e1SJohn Garry int phy_no, u32 off)
76094eac9e1SJohn Garry {
76194eac9e1SJohn Garry void __iomem *regs = hisi_hba->regs + (0x400 * phy_no) + off;
76294eac9e1SJohn Garry
76394eac9e1SJohn Garry return readl(regs);
76494eac9e1SJohn Garry }
76594eac9e1SJohn Garry
766330fa7f3SJohn Garry /* This function needs to be protected from pre-emption. */
767330fa7f3SJohn Garry static int
slot_index_alloc_quirk_v2_hw(struct hisi_hba * hisi_hba,struct domain_device * device)768784b46b7SXiang Chen slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba,
769330fa7f3SJohn Garry struct domain_device *device)
770330fa7f3SJohn Garry {
771330fa7f3SJohn Garry int sata_dev = dev_is_sata(device);
77232ccba52SXiaofei Tan void *bitmap = hisi_hba->slot_index_tags;
77332ccba52SXiaofei Tan struct hisi_sas_device *sas_dev = device->lldd_dev;
77432ccba52SXiaofei Tan int sata_idx = sas_dev->sata_idx;
77532ccba52SXiaofei Tan int start, end;
77632ccba52SXiaofei Tan
77732ccba52SXiaofei Tan if (!sata_dev) {
77832ccba52SXiaofei Tan /*
77932ccba52SXiaofei Tan * STP link SoC bug workaround: index starts from 1.
78032ccba52SXiaofei Tan * additionally, we can only allocate odd IPTT(1~4095)
78132ccba52SXiaofei Tan * for SAS/SMP device.
78232ccba52SXiaofei Tan */
78332ccba52SXiaofei Tan start = 1;
78432ccba52SXiaofei Tan end = hisi_hba->slot_index_count;
78532ccba52SXiaofei Tan } else {
78632ccba52SXiaofei Tan if (sata_idx >= HISI_MAX_SATA_SUPPORT_V2_HW)
78732ccba52SXiaofei Tan return -EINVAL;
78832ccba52SXiaofei Tan
78932ccba52SXiaofei Tan /*
79032ccba52SXiaofei Tan * For SATA device: allocate even IPTT in this interval
79132ccba52SXiaofei Tan * [64*(sata_idx+1), 64*(sata_idx+2)], then each SATA device
79232ccba52SXiaofei Tan * own 32 IPTTs. IPTT 0 shall not be used duing to STP link
79332ccba52SXiaofei Tan * SoC bug workaround. So we ignore the first 32 even IPTTs.
79432ccba52SXiaofei Tan */
79532ccba52SXiaofei Tan start = 64 * (sata_idx + 1);
79632ccba52SXiaofei Tan end = 64 * (sata_idx + 2);
79732ccba52SXiaofei Tan }
798330fa7f3SJohn Garry
799e9dc5e11SXiang Chen spin_lock(&hisi_hba->lock);
800330fa7f3SJohn Garry while (1) {
80132ccba52SXiaofei Tan start = find_next_zero_bit(bitmap,
80232ccba52SXiaofei Tan hisi_hba->slot_index_count, start);
803fe5fb42dSJohn Garry if (start >= end) {
804e9dc5e11SXiang Chen spin_unlock(&hisi_hba->lock);
805330fa7f3SJohn Garry return -SAS_QUEUE_FULL;
806fe5fb42dSJohn Garry }
807330fa7f3SJohn Garry /*
80832ccba52SXiaofei Tan * SAS IPTT bit0 should be 1, and SATA IPTT bit0 should be 0.
809330fa7f3SJohn Garry */
81032ccba52SXiaofei Tan if (sata_dev ^ (start & 1))
811330fa7f3SJohn Garry break;
81232ccba52SXiaofei Tan start++;
81332ccba52SXiaofei Tan }
81432ccba52SXiaofei Tan
81532ccba52SXiaofei Tan set_bit(start, bitmap);
816e9dc5e11SXiang Chen spin_unlock(&hisi_hba->lock);
817784b46b7SXiang Chen return start;
81832ccba52SXiaofei Tan }
81932ccba52SXiaofei Tan
sata_index_alloc_v2_hw(struct hisi_hba * hisi_hba,int * idx)82032ccba52SXiaofei Tan static bool sata_index_alloc_v2_hw(struct hisi_hba *hisi_hba, int *idx)
82132ccba52SXiaofei Tan {
82232ccba52SXiaofei Tan unsigned int index;
82311b75249SJohn Garry struct device *dev = hisi_hba->dev;
82432ccba52SXiaofei Tan void *bitmap = hisi_hba->sata_dev_bitmap;
82532ccba52SXiaofei Tan
82632ccba52SXiaofei Tan index = find_first_zero_bit(bitmap, HISI_MAX_SATA_SUPPORT_V2_HW);
82732ccba52SXiaofei Tan if (index >= HISI_MAX_SATA_SUPPORT_V2_HW) {
82832ccba52SXiaofei Tan dev_warn(dev, "alloc sata index failed, index=%d\n", index);
82932ccba52SXiaofei Tan return false;
830330fa7f3SJohn Garry }
831330fa7f3SJohn Garry
832330fa7f3SJohn Garry set_bit(index, bitmap);
83332ccba52SXiaofei Tan *idx = index;
83432ccba52SXiaofei Tan return true;
835330fa7f3SJohn Garry }
836330fa7f3SJohn Garry
83732ccba52SXiaofei Tan
838b2bdaf2bSJohn Garry static struct
alloc_dev_quirk_v2_hw(struct domain_device * device)839b2bdaf2bSJohn Garry hisi_sas_device *alloc_dev_quirk_v2_hw(struct domain_device *device)
840b2bdaf2bSJohn Garry {
841b2bdaf2bSJohn Garry struct hisi_hba *hisi_hba = device->port->ha->lldd_ha;
842b2bdaf2bSJohn Garry struct hisi_sas_device *sas_dev = NULL;
843b2bdaf2bSJohn Garry int i, sata_dev = dev_is_sata(device);
84432ccba52SXiaofei Tan int sata_idx = -1;
845b2bdaf2bSJohn Garry
846e9dc5e11SXiang Chen spin_lock(&hisi_hba->lock);
84732ccba52SXiaofei Tan
84832ccba52SXiaofei Tan if (sata_dev)
84932ccba52SXiaofei Tan if (!sata_index_alloc_v2_hw(hisi_hba, &sata_idx))
85032ccba52SXiaofei Tan goto out;
85132ccba52SXiaofei Tan
852b2bdaf2bSJohn Garry for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
853b2bdaf2bSJohn Garry /*
854b2bdaf2bSJohn Garry * SATA device id bit0 should be 0
855b2bdaf2bSJohn Garry */
856b2bdaf2bSJohn Garry if (sata_dev && (i & 1))
857b2bdaf2bSJohn Garry continue;
858b2bdaf2bSJohn Garry if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
859b1a49412SXiang Chen int queue = i % hisi_hba->queue_count;
860b1a49412SXiang Chen struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
861b1a49412SXiang Chen
862b2bdaf2bSJohn Garry hisi_hba->devices[i].device_id = i;
863b2bdaf2bSJohn Garry sas_dev = &hisi_hba->devices[i];
86457dbb2b2SXiang Chen sas_dev->dev_status = HISI_SAS_DEV_INIT;
865b2bdaf2bSJohn Garry sas_dev->dev_type = device->dev_type;
866b2bdaf2bSJohn Garry sas_dev->hisi_hba = hisi_hba;
867b2bdaf2bSJohn Garry sas_dev->sas_device = device;
86832ccba52SXiaofei Tan sas_dev->sata_idx = sata_idx;
869b1a49412SXiang Chen sas_dev->dq = dq;
8704fefe5bbSXiang Chen spin_lock_init(&sas_dev->lock);
871405314dfSJohn Garry INIT_LIST_HEAD(&hisi_hba->devices[i].list);
872b2bdaf2bSJohn Garry break;
873b2bdaf2bSJohn Garry }
874b2bdaf2bSJohn Garry }
87532ccba52SXiaofei Tan
87632ccba52SXiaofei Tan out:
877e9dc5e11SXiang Chen spin_unlock(&hisi_hba->lock);
878b2bdaf2bSJohn Garry
879b2bdaf2bSJohn Garry return sas_dev;
880b2bdaf2bSJohn Garry }
881b2bdaf2bSJohn Garry
config_phy_opt_mode_v2_hw(struct hisi_hba * hisi_hba,int phy_no)88229a20428SJohn Garry static void config_phy_opt_mode_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
88329a20428SJohn Garry {
88429a20428SJohn Garry u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
88529a20428SJohn Garry
88629a20428SJohn Garry cfg &= ~PHY_CFG_DC_OPT_MSK;
88729a20428SJohn Garry cfg |= 1 << PHY_CFG_DC_OPT_OFF;
88829a20428SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
88929a20428SJohn Garry }
89029a20428SJohn Garry
config_id_frame_v2_hw(struct hisi_hba * hisi_hba,int phy_no)891806bb768SJohn Garry static void config_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
892806bb768SJohn Garry {
893806bb768SJohn Garry struct sas_identify_frame identify_frame;
894806bb768SJohn Garry u32 *identify_buffer;
895806bb768SJohn Garry
896806bb768SJohn Garry memset(&identify_frame, 0, sizeof(identify_frame));
897806bb768SJohn Garry identify_frame.dev_type = SAS_END_DEVICE;
898806bb768SJohn Garry identify_frame.frame_type = 0;
899806bb768SJohn Garry identify_frame._un1 = 1;
900806bb768SJohn Garry identify_frame.initiator_bits = SAS_PROTOCOL_ALL;
901806bb768SJohn Garry identify_frame.target_bits = SAS_PROTOCOL_NONE;
902806bb768SJohn Garry memcpy(&identify_frame._un4_11[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
903806bb768SJohn Garry memcpy(&identify_frame.sas_addr[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
904806bb768SJohn Garry identify_frame.phy_id = phy_no;
905806bb768SJohn Garry identify_buffer = (u32 *)(&identify_frame);
906806bb768SJohn Garry
907806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
908806bb768SJohn Garry __swab32(identify_buffer[0]));
909806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
910d82debecSJohn Garry __swab32(identify_buffer[1]));
911806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
912d82debecSJohn Garry __swab32(identify_buffer[2]));
913806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
914d82debecSJohn Garry __swab32(identify_buffer[3]));
915806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
916d82debecSJohn Garry __swab32(identify_buffer[4]));
917806bb768SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
918806bb768SJohn Garry __swab32(identify_buffer[5]));
919806bb768SJohn Garry }
920806bb768SJohn Garry
setup_itct_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_device * sas_dev)92185b2c3c0SJohn Garry static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
92285b2c3c0SJohn Garry struct hisi_sas_device *sas_dev)
92385b2c3c0SJohn Garry {
92485b2c3c0SJohn Garry struct domain_device *device = sas_dev->sas_device;
92511b75249SJohn Garry struct device *dev = hisi_hba->dev;
92685b2c3c0SJohn Garry u64 qw0, device_id = sas_dev->device_id;
92785b2c3c0SJohn Garry struct hisi_sas_itct *itct = &hisi_hba->itct[device_id];
92885b2c3c0SJohn Garry struct domain_device *parent_dev = device->parent;
9292e244f0fSJohn Garry struct asd_sas_port *sas_port = device->port;
9302e244f0fSJohn Garry struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
931735bcc77SJohn Garry u64 sas_addr;
93285b2c3c0SJohn Garry
93385b2c3c0SJohn Garry memset(itct, 0, sizeof(*itct));
93485b2c3c0SJohn Garry
93585b2c3c0SJohn Garry /* qw0 */
93685b2c3c0SJohn Garry qw0 = 0;
93785b2c3c0SJohn Garry switch (sas_dev->dev_type) {
93885b2c3c0SJohn Garry case SAS_END_DEVICE:
93985b2c3c0SJohn Garry case SAS_EDGE_EXPANDER_DEVICE:
94085b2c3c0SJohn Garry case SAS_FANOUT_EXPANDER_DEVICE:
94185b2c3c0SJohn Garry qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF;
94285b2c3c0SJohn Garry break;
94385b2c3c0SJohn Garry case SAS_SATA_DEV:
94456cc74b9SJohn Garry case SAS_SATA_PENDING:
945924a3541SJohn Garry if (parent_dev && dev_is_expander(parent_dev->dev_type))
94685b2c3c0SJohn Garry qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF;
94785b2c3c0SJohn Garry else
94885b2c3c0SJohn Garry qw0 = HISI_SAS_DEV_TYPE_SATA << ITCT_HDR_DEV_TYPE_OFF;
94985b2c3c0SJohn Garry break;
95085b2c3c0SJohn Garry default:
95185b2c3c0SJohn Garry dev_warn(dev, "setup itct: unsupported dev type (%d)\n",
95285b2c3c0SJohn Garry sas_dev->dev_type);
95385b2c3c0SJohn Garry }
95485b2c3c0SJohn Garry
95585b2c3c0SJohn Garry qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
95675249268SJohn Garry (device->linkrate << ITCT_HDR_MCR_OFF) |
95785b2c3c0SJohn Garry (1 << ITCT_HDR_VLN_OFF) |
958c399acfbSXiang Chen (ITCT_HDR_SMP_TIMEOUT << ITCT_HDR_SMP_TIMEOUT_OFF) |
959c399acfbSXiang Chen (1 << ITCT_HDR_AWT_CONTINUE_OFF) |
96085b2c3c0SJohn Garry (port->id << ITCT_HDR_PORT_ID_OFF));
96185b2c3c0SJohn Garry itct->qw0 = cpu_to_le64(qw0);
96285b2c3c0SJohn Garry
96385b2c3c0SJohn Garry /* qw1 */
964735bcc77SJohn Garry memcpy(&sas_addr, device->sas_addr, SAS_ADDR_SIZE);
965735bcc77SJohn Garry itct->sas_addr = cpu_to_le64(__swab64(sas_addr));
96685b2c3c0SJohn Garry
96785b2c3c0SJohn Garry /* qw2 */
968f76a0b49SJohn Garry if (!dev_is_sata(device))
969c399acfbSXiang Chen itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) |
970f76a0b49SJohn Garry (0x1ULL << ITCT_HDR_BITLT_OFF) |
971f76a0b49SJohn Garry (0x32ULL << ITCT_HDR_MCTLT_OFF) |
972f76a0b49SJohn Garry (0x1ULL << ITCT_HDR_RTOLT_OFF));
97385b2c3c0SJohn Garry }
97485b2c3c0SJohn Garry
clear_itct_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_device * sas_dev)9758fa9a7bdSXiang Chen static int clear_itct_v2_hw(struct hisi_hba *hisi_hba,
97685b2c3c0SJohn Garry struct hisi_sas_device *sas_dev)
97785b2c3c0SJohn Garry {
978640acc9aSXiang Chen DECLARE_COMPLETION_ONSTACK(completion);
979c399acfbSXiang Chen u64 dev_id = sas_dev->device_id;
98085b2c3c0SJohn Garry struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
98185b2c3c0SJohn Garry u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
9828fa9a7bdSXiang Chen struct device *dev = hisi_hba->dev;
98385b2c3c0SJohn Garry int i;
98485b2c3c0SJohn Garry
985640acc9aSXiang Chen sas_dev->completion = &completion;
986640acc9aSXiang Chen
98785b2c3c0SJohn Garry /* clear the itct interrupt state */
98885b2c3c0SJohn Garry if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
98985b2c3c0SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
99085b2c3c0SJohn Garry ENT_INT_SRC3_ITC_INT_MSK);
99185b2c3c0SJohn Garry
9928fa9a7bdSXiang Chen /* need to set register twice to clear ITCT for v2 hw */
99385b2c3c0SJohn Garry for (i = 0; i < 2; i++) {
994640acc9aSXiang Chen reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
99585b2c3c0SJohn Garry hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
9968fa9a7bdSXiang Chen if (!wait_for_completion_timeout(sas_dev->completion,
9972f12a499SLuo Jiaxing HISI_SAS_CLEAR_ITCT_TIMEOUT)) {
9988fa9a7bdSXiang Chen dev_warn(dev, "failed to clear ITCT\n");
9998fa9a7bdSXiang Chen return -ETIMEDOUT;
10008fa9a7bdSXiang Chen }
100185b2c3c0SJohn Garry
1002c399acfbSXiang Chen memset(itct, 0, sizeof(struct hisi_sas_itct));
100385b2c3c0SJohn Garry }
10048fa9a7bdSXiang Chen return 0;
100585b2c3c0SJohn Garry }
100685b2c3c0SJohn Garry
free_device_v2_hw(struct hisi_sas_device * sas_dev)10070258141aSXiaofei Tan static void free_device_v2_hw(struct hisi_sas_device *sas_dev)
10080258141aSXiaofei Tan {
10090258141aSXiaofei Tan struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
10100258141aSXiaofei Tan
10110258141aSXiaofei Tan /* SoC bug workaround */
10120258141aSXiaofei Tan if (dev_is_sata(sas_dev->sas_device))
10130258141aSXiaofei Tan clear_bit(sas_dev->sata_idx, hisi_hba->sata_dev_bitmap);
10140258141aSXiaofei Tan }
10150258141aSXiaofei Tan
reset_hw_v2_hw(struct hisi_hba * hisi_hba)101694eac9e1SJohn Garry static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
101794eac9e1SJohn Garry {
101894eac9e1SJohn Garry int i, reset_val;
101994eac9e1SJohn Garry u32 val;
102094eac9e1SJohn Garry unsigned long end_time;
102111b75249SJohn Garry struct device *dev = hisi_hba->dev;
102294eac9e1SJohn Garry
102394eac9e1SJohn Garry /* The mask needs to be set depending on the number of phys */
102494eac9e1SJohn Garry if (hisi_hba->n_phy == 9)
102594eac9e1SJohn Garry reset_val = 0x1fffff;
102694eac9e1SJohn Garry else
102794eac9e1SJohn Garry reset_val = 0x7ffff;
102894eac9e1SJohn Garry
102994eac9e1SJohn Garry hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
103094eac9e1SJohn Garry
103194eac9e1SJohn Garry /* Disable all of the PHYs */
103294eac9e1SJohn Garry for (i = 0; i < hisi_hba->n_phy; i++) {
103394eac9e1SJohn Garry u32 phy_cfg = hisi_sas_phy_read32(hisi_hba, i, PHY_CFG);
103494eac9e1SJohn Garry
103594eac9e1SJohn Garry phy_cfg &= ~PHY_CTRL_RESET_MSK;
103694eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHY_CFG, phy_cfg);
103794eac9e1SJohn Garry }
103894eac9e1SJohn Garry udelay(50);
103994eac9e1SJohn Garry
104094eac9e1SJohn Garry /* Ensure DMA tx & rx idle */
104194eac9e1SJohn Garry for (i = 0; i < hisi_hba->n_phy; i++) {
104294eac9e1SJohn Garry u32 dma_tx_status, dma_rx_status;
104394eac9e1SJohn Garry
104494eac9e1SJohn Garry end_time = jiffies + msecs_to_jiffies(1000);
104594eac9e1SJohn Garry
104694eac9e1SJohn Garry while (1) {
104794eac9e1SJohn Garry dma_tx_status = hisi_sas_phy_read32(hisi_hba, i,
104894eac9e1SJohn Garry DMA_TX_STATUS);
104994eac9e1SJohn Garry dma_rx_status = hisi_sas_phy_read32(hisi_hba, i,
105094eac9e1SJohn Garry DMA_RX_STATUS);
105194eac9e1SJohn Garry
105294eac9e1SJohn Garry if (!(dma_tx_status & DMA_TX_STATUS_BUSY_MSK) &&
105394eac9e1SJohn Garry !(dma_rx_status & DMA_RX_STATUS_BUSY_MSK))
105494eac9e1SJohn Garry break;
105594eac9e1SJohn Garry
105694eac9e1SJohn Garry msleep(20);
105794eac9e1SJohn Garry if (time_after(jiffies, end_time))
105894eac9e1SJohn Garry return -EIO;
105994eac9e1SJohn Garry }
106094eac9e1SJohn Garry }
106194eac9e1SJohn Garry
106294eac9e1SJohn Garry /* Ensure axi bus idle */
106394eac9e1SJohn Garry end_time = jiffies + msecs_to_jiffies(1000);
106494eac9e1SJohn Garry while (1) {
106594eac9e1SJohn Garry u32 axi_status =
106694eac9e1SJohn Garry hisi_sas_read32(hisi_hba, AXI_CFG);
106794eac9e1SJohn Garry
106894eac9e1SJohn Garry if (axi_status == 0)
106994eac9e1SJohn Garry break;
107094eac9e1SJohn Garry
107194eac9e1SJohn Garry msleep(20);
107294eac9e1SJohn Garry if (time_after(jiffies, end_time))
107394eac9e1SJohn Garry return -EIO;
107494eac9e1SJohn Garry }
107594eac9e1SJohn Garry
107650408712SJohn Garry if (ACPI_HANDLE(dev)) {
107750408712SJohn Garry acpi_status s;
107850408712SJohn Garry
107950408712SJohn Garry s = acpi_evaluate_object(ACPI_HANDLE(dev), "_RST", NULL, NULL);
108050408712SJohn Garry if (ACPI_FAILURE(s)) {
108150408712SJohn Garry dev_err(dev, "Reset failed\n");
108250408712SJohn Garry return -EIO;
108350408712SJohn Garry }
108450408712SJohn Garry } else if (hisi_hba->ctrl) {
108594eac9e1SJohn Garry /* reset and disable clock*/
108694eac9e1SJohn Garry regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
108794eac9e1SJohn Garry reset_val);
108894eac9e1SJohn Garry regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
108994eac9e1SJohn Garry reset_val);
109094eac9e1SJohn Garry msleep(1);
109194eac9e1SJohn Garry regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
109294eac9e1SJohn Garry if (reset_val != (val & reset_val)) {
109394eac9e1SJohn Garry dev_err(dev, "SAS reset fail.\n");
109494eac9e1SJohn Garry return -EIO;
109594eac9e1SJohn Garry }
109694eac9e1SJohn Garry
109794eac9e1SJohn Garry /* De-reset and enable clock*/
109894eac9e1SJohn Garry regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
109994eac9e1SJohn Garry reset_val);
110094eac9e1SJohn Garry regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
110194eac9e1SJohn Garry reset_val);
110294eac9e1SJohn Garry msleep(1);
110394eac9e1SJohn Garry regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
110494eac9e1SJohn Garry &val);
110594eac9e1SJohn Garry if (val & reset_val) {
110694eac9e1SJohn Garry dev_err(dev, "SAS de-reset fail.\n");
110794eac9e1SJohn Garry return -EIO;
110894eac9e1SJohn Garry }
1109edafeef4SXiang Chen } else {
1110edafeef4SXiang Chen dev_err(dev, "no reset method\n");
1111edafeef4SXiang Chen return -EINVAL;
1112edafeef4SXiang Chen }
111394eac9e1SJohn Garry
111494eac9e1SJohn Garry return 0;
111594eac9e1SJohn Garry }
111694eac9e1SJohn Garry
1117c7b9d369SXiaofei Tan /* This function needs to be called after resetting SAS controller. */
phys_reject_stp_links_v2_hw(struct hisi_hba * hisi_hba)1118c7b9d369SXiaofei Tan static void phys_reject_stp_links_v2_hw(struct hisi_hba *hisi_hba)
1119c7b9d369SXiaofei Tan {
1120c7b9d369SXiaofei Tan u32 cfg;
1121c7b9d369SXiaofei Tan int phy_no;
1122c7b9d369SXiaofei Tan
1123c7b9d369SXiaofei Tan hisi_hba->reject_stp_links_msk = (1 << hisi_hba->n_phy) - 1;
1124c7b9d369SXiaofei Tan for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
1125c7b9d369SXiaofei Tan cfg = hisi_sas_phy_read32(hisi_hba, phy_no, CON_CONTROL);
1126c7b9d369SXiaofei Tan if (!(cfg & CON_CONTROL_CFG_OPEN_ACC_STP_MSK))
1127c7b9d369SXiaofei Tan continue;
1128c7b9d369SXiaofei Tan
1129c7b9d369SXiaofei Tan cfg &= ~CON_CONTROL_CFG_OPEN_ACC_STP_MSK;
1130c7b9d369SXiaofei Tan hisi_sas_phy_write32(hisi_hba, phy_no, CON_CONTROL, cfg);
1131c7b9d369SXiaofei Tan }
1132c7b9d369SXiaofei Tan }
1133c7b9d369SXiaofei Tan
phys_try_accept_stp_links_v2_hw(struct hisi_hba * hisi_hba)1134c7b9d369SXiaofei Tan static void phys_try_accept_stp_links_v2_hw(struct hisi_hba *hisi_hba)
1135c7b9d369SXiaofei Tan {
1136c7b9d369SXiaofei Tan int phy_no;
1137c7b9d369SXiaofei Tan u32 dma_tx_dfx1;
1138c7b9d369SXiaofei Tan
1139c7b9d369SXiaofei Tan for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
1140c7b9d369SXiaofei Tan if (!(hisi_hba->reject_stp_links_msk & BIT(phy_no)))
1141c7b9d369SXiaofei Tan continue;
1142c7b9d369SXiaofei Tan
1143c7b9d369SXiaofei Tan dma_tx_dfx1 = hisi_sas_phy_read32(hisi_hba, phy_no,
1144c7b9d369SXiaofei Tan DMA_TX_DFX1);
1145c7b9d369SXiaofei Tan if (dma_tx_dfx1 & DMA_TX_DFX1_IPTT_MSK) {
1146c7b9d369SXiaofei Tan u32 cfg = hisi_sas_phy_read32(hisi_hba,
1147c7b9d369SXiaofei Tan phy_no, CON_CONTROL);
1148c7b9d369SXiaofei Tan
1149c7b9d369SXiaofei Tan cfg |= CON_CONTROL_CFG_OPEN_ACC_STP_MSK;
1150c7b9d369SXiaofei Tan hisi_sas_phy_write32(hisi_hba, phy_no,
1151c7b9d369SXiaofei Tan CON_CONTROL, cfg);
1152c7b9d369SXiaofei Tan clear_bit(phy_no, &hisi_hba->reject_stp_links_msk);
1153c7b9d369SXiaofei Tan }
1154c7b9d369SXiaofei Tan }
1155c7b9d369SXiaofei Tan }
1156c7b9d369SXiaofei Tan
115767c2bf23SXiaofei Tan static const struct signal_attenuation_s x6000 = {9200, 0, 10476};
115867c2bf23SXiaofei Tan static const struct sig_atten_lu_s sig_atten_lu[] = {
115967c2bf23SXiaofei Tan { &x6000, 0x3016a68 },
116067c2bf23SXiaofei Tan };
116167c2bf23SXiaofei Tan
init_reg_v2_hw(struct hisi_hba * hisi_hba)116294eac9e1SJohn Garry static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
116394eac9e1SJohn Garry {
116411b75249SJohn Garry struct device *dev = hisi_hba->dev;
116567c2bf23SXiaofei Tan u32 sas_phy_ctrl = 0x30b9908;
116667c2bf23SXiaofei Tan u32 signal[3];
116794eac9e1SJohn Garry int i;
116894eac9e1SJohn Garry
116994eac9e1SJohn Garry /* Global registers init */
117094eac9e1SJohn Garry
117194eac9e1SJohn Garry /* Deal with am-max-transmissions quirk */
117250408712SJohn Garry if (device_property_present(dev, "hip06-sas-v2-quirk-amt")) {
117394eac9e1SJohn Garry hisi_sas_write32(hisi_hba, AM_CFG_MAX_TRANS, 0x2020);
117494eac9e1SJohn Garry hisi_sas_write32(hisi_hba, AM_CFG_SINGLE_PORT_MAX_TRANS,
117594eac9e1SJohn Garry 0x2020);
117694eac9e1SJohn Garry } /* Else, use defaults -> do nothing */
117794eac9e1SJohn Garry
117894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
117994eac9e1SJohn Garry (u32)((1ULL << hisi_hba->queue_count) - 1));
118094eac9e1SJohn Garry hisi_sas_write32(hisi_hba, AXI_USER1, 0xc0000000);
118194eac9e1SJohn Garry hisi_sas_write32(hisi_hba, AXI_USER2, 0x10000);
1182f1dc7518SJohn Garry hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x0);
118394eac9e1SJohn Garry hisi_sas_write32(hisi_hba, HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL, 0x7FF);
118494eac9e1SJohn Garry hisi_sas_write32(hisi_hba, OPENA_WT_CONTI_TIME, 0x1);
118594eac9e1SJohn Garry hisi_sas_write32(hisi_hba, I_T_NEXUS_LOSS_TIME, 0x1F4);
1186f76a0b49SJohn Garry hisi_sas_write32(hisi_hba, MAX_CON_TIME_LIMIT_TIME, 0x32);
118794eac9e1SJohn Garry hisi_sas_write32(hisi_hba, BUS_INACTIVE_LIMIT_TIME, 0x1);
118894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1);
118994eac9e1SJohn Garry hisi_sas_write32(hisi_hba, HGC_ERR_STAT_EN, 0x1);
119094eac9e1SJohn Garry hisi_sas_write32(hisi_hba, HGC_GET_ITV_TIME, 0x1);
1191f1dc7518SJohn Garry hisi_sas_write32(hisi_hba, INT_COAL_EN, 0xc);
1192f1dc7518SJohn Garry hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x60);
1193f1dc7518SJohn Garry hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x3);
119494eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_COAL_TIME, 0x1);
119594eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_COAL_CNT, 0x1);
119694eac9e1SJohn Garry hisi_sas_write32(hisi_hba, OQ_INT_SRC, 0x0);
119794eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC1, 0xffffffff);
119894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC2, 0xffffffff);
119994eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff);
120094eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0x7efefefe);
120194eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0x7efefefe);
1202640acc9aSXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x7ffe20fe);
1203d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfff00c30);
120494eac9e1SJohn Garry for (i = 0; i < hisi_hba->queue_count; i++)
120594eac9e1SJohn Garry hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0);
120694eac9e1SJohn Garry
120794eac9e1SJohn Garry hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1);
120894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
120994eac9e1SJohn Garry
121067c2bf23SXiaofei Tan /* Get sas_phy_ctrl value to deal with TX FFE issue. */
121167c2bf23SXiaofei Tan if (!device_property_read_u32_array(dev, "hisilicon,signal-attenuation",
121267c2bf23SXiaofei Tan signal, ARRAY_SIZE(signal))) {
121367c2bf23SXiaofei Tan for (i = 0; i < ARRAY_SIZE(sig_atten_lu); i++) {
121467c2bf23SXiaofei Tan const struct sig_atten_lu_s *lookup = &sig_atten_lu[i];
121567c2bf23SXiaofei Tan const struct signal_attenuation_s *att = lookup->att;
121667c2bf23SXiaofei Tan
121767c2bf23SXiaofei Tan if ((signal[0] == att->de_emphasis) &&
121867c2bf23SXiaofei Tan (signal[1] == att->preshoot) &&
121967c2bf23SXiaofei Tan (signal[2] == att->boost)) {
122067c2bf23SXiaofei Tan sas_phy_ctrl = lookup->sas_phy_ctrl;
122167c2bf23SXiaofei Tan break;
122267c2bf23SXiaofei Tan }
122367c2bf23SXiaofei Tan }
122467c2bf23SXiaofei Tan
122567c2bf23SXiaofei Tan if (i == ARRAY_SIZE(sig_atten_lu))
122667c2bf23SXiaofei Tan dev_warn(dev, "unknown signal attenuation values, using default PHY ctrl config\n");
122767c2bf23SXiaofei Tan }
122867c2bf23SXiaofei Tan
122994eac9e1SJohn Garry for (i = 0; i < hisi_hba->n_phy; i++) {
1230c2c1d9deSXiang Chen struct hisi_sas_phy *phy = &hisi_hba->phy[i];
1231c2c1d9deSXiang Chen struct asd_sas_phy *sas_phy = &phy->sas_phy;
1232c2c1d9deSXiang Chen u32 prog_phy_link_rate = 0x800;
1233c2c1d9deSXiang Chen
1234c2c1d9deSXiang Chen if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
1235c2c1d9deSXiang Chen SAS_LINK_RATE_1_5_GBPS)) {
1236c2c1d9deSXiang Chen prog_phy_link_rate = 0x855;
1237c2c1d9deSXiang Chen } else {
1238c2c1d9deSXiang Chen enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
1239c2c1d9deSXiang Chen
1240c2c1d9deSXiang Chen prog_phy_link_rate =
1241c2c1d9deSXiang Chen hisi_sas_get_prog_phy_linkrate_mask(max) |
1242c2c1d9deSXiang Chen 0x800;
1243c2c1d9deSXiang Chen }
1244c2c1d9deSXiang Chen hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
1245c2c1d9deSXiang Chen prog_phy_link_rate);
124667c2bf23SXiaofei Tan hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl);
124794eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
12489c81e2cfSJohn Garry hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
12499c81e2cfSJohn Garry hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2);
1250f1dc7518SJohn Garry hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x8);
125194eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
125294eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
1253d3b688d3SXiang Chen hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xfff87fff);
125494eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
125572f7fc30SXiaofei Tan hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff857fff);
1256057c3d1fSXiaofei Tan hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8ffffbfe);
1257f1dc7518SJohn Garry hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x13f801fc);
125894eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
125994eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
126094eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0);
126194eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_PHY_ENA_MSK, 0x0);
126294eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0);
126394eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, CHL_INT_COAL_EN, 0x0);
126494eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0);
12653bc45af8SJohn Garry if (hisi_hba->refclk_frequency_mhz == 66)
126694eac9e1SJohn Garry hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694);
12673bc45af8SJohn Garry /* else, do nothing -> leave it how you found it */
126894eac9e1SJohn Garry }
126994eac9e1SJohn Garry
127094eac9e1SJohn Garry for (i = 0; i < hisi_hba->queue_count; i++) {
127194eac9e1SJohn Garry /* Delivery queue */
127294eac9e1SJohn Garry hisi_sas_write32(hisi_hba,
127394eac9e1SJohn Garry DLVRY_Q_0_BASE_ADDR_HI + (i * 0x14),
127494eac9e1SJohn Garry upper_32_bits(hisi_hba->cmd_hdr_dma[i]));
127594eac9e1SJohn Garry
127694eac9e1SJohn Garry hisi_sas_write32(hisi_hba, DLVRY_Q_0_BASE_ADDR_LO + (i * 0x14),
127794eac9e1SJohn Garry lower_32_bits(hisi_hba->cmd_hdr_dma[i]));
127894eac9e1SJohn Garry
127994eac9e1SJohn Garry hisi_sas_write32(hisi_hba, DLVRY_Q_0_DEPTH + (i * 0x14),
128094eac9e1SJohn Garry HISI_SAS_QUEUE_SLOTS);
128194eac9e1SJohn Garry
128294eac9e1SJohn Garry /* Completion queue */
128394eac9e1SJohn Garry hisi_sas_write32(hisi_hba, COMPL_Q_0_BASE_ADDR_HI + (i * 0x14),
128494eac9e1SJohn Garry upper_32_bits(hisi_hba->complete_hdr_dma[i]));
128594eac9e1SJohn Garry
128694eac9e1SJohn Garry hisi_sas_write32(hisi_hba, COMPL_Q_0_BASE_ADDR_LO + (i * 0x14),
128794eac9e1SJohn Garry lower_32_bits(hisi_hba->complete_hdr_dma[i]));
128894eac9e1SJohn Garry
128994eac9e1SJohn Garry hisi_sas_write32(hisi_hba, COMPL_Q_0_DEPTH + (i * 0x14),
129094eac9e1SJohn Garry HISI_SAS_QUEUE_SLOTS);
129194eac9e1SJohn Garry }
129294eac9e1SJohn Garry
129394eac9e1SJohn Garry /* itct */
129494eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ITCT_BASE_ADDR_LO,
129594eac9e1SJohn Garry lower_32_bits(hisi_hba->itct_dma));
129694eac9e1SJohn Garry
129794eac9e1SJohn Garry hisi_sas_write32(hisi_hba, ITCT_BASE_ADDR_HI,
129894eac9e1SJohn Garry upper_32_bits(hisi_hba->itct_dma));
129994eac9e1SJohn Garry
130094eac9e1SJohn Garry /* iost */
130194eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IOST_BASE_ADDR_LO,
130294eac9e1SJohn Garry lower_32_bits(hisi_hba->iost_dma));
130394eac9e1SJohn Garry
130494eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IOST_BASE_ADDR_HI,
130594eac9e1SJohn Garry upper_32_bits(hisi_hba->iost_dma));
130694eac9e1SJohn Garry
130794eac9e1SJohn Garry /* breakpoint */
130894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IO_BROKEN_MSG_ADDR_LO,
130994eac9e1SJohn Garry lower_32_bits(hisi_hba->breakpoint_dma));
131094eac9e1SJohn Garry
131194eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IO_BROKEN_MSG_ADDR_HI,
131294eac9e1SJohn Garry upper_32_bits(hisi_hba->breakpoint_dma));
131394eac9e1SJohn Garry
131494eac9e1SJohn Garry /* SATA broken msg */
131594eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IO_SATA_BROKEN_MSG_ADDR_LO,
131694eac9e1SJohn Garry lower_32_bits(hisi_hba->sata_breakpoint_dma));
131794eac9e1SJohn Garry
131894eac9e1SJohn Garry hisi_sas_write32(hisi_hba, IO_SATA_BROKEN_MSG_ADDR_HI,
131994eac9e1SJohn Garry upper_32_bits(hisi_hba->sata_breakpoint_dma));
132094eac9e1SJohn Garry
132194eac9e1SJohn Garry /* SATA initial fis */
132294eac9e1SJohn Garry hisi_sas_write32(hisi_hba, SATA_INITI_D2H_STORE_ADDR_LO,
132394eac9e1SJohn Garry lower_32_bits(hisi_hba->initial_fis_dma));
132494eac9e1SJohn Garry
132594eac9e1SJohn Garry hisi_sas_write32(hisi_hba, SATA_INITI_D2H_STORE_ADDR_HI,
132694eac9e1SJohn Garry upper_32_bits(hisi_hba->initial_fis_dma));
132794eac9e1SJohn Garry }
132894eac9e1SJohn Garry
link_timeout_enable_link(struct timer_list * t)132977570eedSKees Cook static void link_timeout_enable_link(struct timer_list *t)
1330f2f89c32SXiang Chen {
133177570eedSKees Cook struct hisi_hba *hisi_hba = from_timer(hisi_hba, t, timer);
1332f2f89c32SXiang Chen int i, reg_val;
1333f2f89c32SXiang Chen
1334f2f89c32SXiang Chen for (i = 0; i < hisi_hba->n_phy; i++) {
1335c7b9d369SXiaofei Tan if (hisi_hba->reject_stp_links_msk & BIT(i))
1336c7b9d369SXiaofei Tan continue;
1337c7b9d369SXiaofei Tan
1338f2f89c32SXiang Chen reg_val = hisi_sas_phy_read32(hisi_hba, i, CON_CONTROL);
1339f2f89c32SXiang Chen if (!(reg_val & BIT(0))) {
1340f2f89c32SXiang Chen hisi_sas_phy_write32(hisi_hba, i,
1341f2f89c32SXiang Chen CON_CONTROL, 0x7);
1342f2f89c32SXiang Chen break;
1343f2f89c32SXiang Chen }
1344f2f89c32SXiang Chen }
1345f2f89c32SXiang Chen
1346841b86f3SKees Cook hisi_hba->timer.function = link_timeout_disable_link;
1347f2f89c32SXiang Chen mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(900));
1348f2f89c32SXiang Chen }
1349f2f89c32SXiang Chen
link_timeout_disable_link(struct timer_list * t)135077570eedSKees Cook static void link_timeout_disable_link(struct timer_list *t)
1351f2f89c32SXiang Chen {
135277570eedSKees Cook struct hisi_hba *hisi_hba = from_timer(hisi_hba, t, timer);
1353f2f89c32SXiang Chen int i, reg_val;
1354f2f89c32SXiang Chen
1355f2f89c32SXiang Chen reg_val = hisi_sas_read32(hisi_hba, PHY_STATE);
1356f2f89c32SXiang Chen for (i = 0; i < hisi_hba->n_phy && reg_val; i++) {
1357c7b9d369SXiaofei Tan if (hisi_hba->reject_stp_links_msk & BIT(i))
1358c7b9d369SXiaofei Tan continue;
1359c7b9d369SXiaofei Tan
1360f2f89c32SXiang Chen if (reg_val & BIT(i)) {
1361f2f89c32SXiang Chen hisi_sas_phy_write32(hisi_hba, i,
1362f2f89c32SXiang Chen CON_CONTROL, 0x6);
1363f2f89c32SXiang Chen break;
1364f2f89c32SXiang Chen }
1365f2f89c32SXiang Chen }
1366f2f89c32SXiang Chen
1367841b86f3SKees Cook hisi_hba->timer.function = link_timeout_enable_link;
1368f2f89c32SXiang Chen mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(100));
1369f2f89c32SXiang Chen }
1370f2f89c32SXiang Chen
set_link_timer_quirk(struct hisi_hba * hisi_hba)1371f2f89c32SXiang Chen static void set_link_timer_quirk(struct hisi_hba *hisi_hba)
1372f2f89c32SXiang Chen {
1373841b86f3SKees Cook hisi_hba->timer.function = link_timeout_disable_link;
1374f2f89c32SXiang Chen hisi_hba->timer.expires = jiffies + msecs_to_jiffies(1000);
1375f2f89c32SXiang Chen add_timer(&hisi_hba->timer);
1376f2f89c32SXiang Chen }
1377f2f89c32SXiang Chen
hw_init_v2_hw(struct hisi_hba * hisi_hba)137894eac9e1SJohn Garry static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
137994eac9e1SJohn Garry {
138011b75249SJohn Garry struct device *dev = hisi_hba->dev;
138194eac9e1SJohn Garry int rc;
138294eac9e1SJohn Garry
138394eac9e1SJohn Garry rc = reset_hw_v2_hw(hisi_hba);
138494eac9e1SJohn Garry if (rc) {
1385b601577dSXiang Chen dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc);
138694eac9e1SJohn Garry return rc;
138794eac9e1SJohn Garry }
138894eac9e1SJohn Garry
138994eac9e1SJohn Garry msleep(100);
139094eac9e1SJohn Garry init_reg_v2_hw(hisi_hba);
139194eac9e1SJohn Garry
139294eac9e1SJohn Garry return 0;
139394eac9e1SJohn Garry }
139494eac9e1SJohn Garry
enable_phy_v2_hw(struct hisi_hba * hisi_hba,int phy_no)139529a20428SJohn Garry static void enable_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
139629a20428SJohn Garry {
139729a20428SJohn Garry u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
139829a20428SJohn Garry
139929a20428SJohn Garry cfg |= PHY_CFG_ENA_MSK;
140029a20428SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
140129a20428SJohn Garry }
140229a20428SJohn Garry
is_sata_phy_v2_hw(struct hisi_hba * hisi_hba,int phy_no)14034935933eSXiaofei Tan static bool is_sata_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
14044935933eSXiaofei Tan {
14054935933eSXiaofei Tan u32 context;
14064935933eSXiaofei Tan
14074935933eSXiaofei Tan context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
14084935933eSXiaofei Tan if (context & (1 << phy_no))
14094935933eSXiaofei Tan return true;
14104935933eSXiaofei Tan
14114935933eSXiaofei Tan return false;
14124935933eSXiaofei Tan }
14134935933eSXiaofei Tan
tx_fifo_is_empty_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1414819cbf18SXiaofei Tan static bool tx_fifo_is_empty_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
1415819cbf18SXiaofei Tan {
1416819cbf18SXiaofei Tan u32 dfx_val;
1417819cbf18SXiaofei Tan
1418819cbf18SXiaofei Tan dfx_val = hisi_sas_phy_read32(hisi_hba, phy_no, DMA_TX_DFX1);
1419819cbf18SXiaofei Tan
1420819cbf18SXiaofei Tan if (dfx_val & BIT(16))
1421819cbf18SXiaofei Tan return false;
1422819cbf18SXiaofei Tan
1423819cbf18SXiaofei Tan return true;
1424819cbf18SXiaofei Tan }
1425819cbf18SXiaofei Tan
axi_bus_is_idle_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1426819cbf18SXiaofei Tan static bool axi_bus_is_idle_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
1427819cbf18SXiaofei Tan {
1428819cbf18SXiaofei Tan int i, max_loop = 1000;
142911b75249SJohn Garry struct device *dev = hisi_hba->dev;
1430819cbf18SXiaofei Tan u32 status, axi_status, dfx_val, dfx_tx_val;
1431819cbf18SXiaofei Tan
1432819cbf18SXiaofei Tan for (i = 0; i < max_loop; i++) {
1433819cbf18SXiaofei Tan status = hisi_sas_read32_relaxed(hisi_hba,
1434819cbf18SXiaofei Tan AXI_MASTER_CFG_BASE + AM_CURR_TRANS_RETURN);
1435819cbf18SXiaofei Tan
1436819cbf18SXiaofei Tan axi_status = hisi_sas_read32(hisi_hba, AXI_CFG);
1437819cbf18SXiaofei Tan dfx_val = hisi_sas_phy_read32(hisi_hba, phy_no, DMA_TX_DFX1);
1438819cbf18SXiaofei Tan dfx_tx_val = hisi_sas_phy_read32(hisi_hba,
1439819cbf18SXiaofei Tan phy_no, DMA_TX_FIFO_DFX0);
1440819cbf18SXiaofei Tan
1441819cbf18SXiaofei Tan if ((status == 0x3) && (axi_status == 0x0) &&
1442819cbf18SXiaofei Tan (dfx_val & BIT(20)) && (dfx_tx_val & BIT(10)))
1443819cbf18SXiaofei Tan return true;
1444819cbf18SXiaofei Tan udelay(10);
1445819cbf18SXiaofei Tan }
1446819cbf18SXiaofei Tan dev_err(dev, "bus is not idle phy%d, axi150:0x%x axi100:0x%x port204:0x%x port240:0x%x\n",
1447819cbf18SXiaofei Tan phy_no, status, axi_status,
1448819cbf18SXiaofei Tan dfx_val, dfx_tx_val);
1449819cbf18SXiaofei Tan return false;
1450819cbf18SXiaofei Tan }
1451819cbf18SXiaofei Tan
wait_io_done_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1452819cbf18SXiaofei Tan static bool wait_io_done_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
1453819cbf18SXiaofei Tan {
1454819cbf18SXiaofei Tan int i, max_loop = 1000;
145511b75249SJohn Garry struct device *dev = hisi_hba->dev;
1456819cbf18SXiaofei Tan u32 status, tx_dfx0;
1457819cbf18SXiaofei Tan
1458819cbf18SXiaofei Tan for (i = 0; i < max_loop; i++) {
1459819cbf18SXiaofei Tan status = hisi_sas_phy_read32(hisi_hba, phy_no, LINK_DFX2);
1460819cbf18SXiaofei Tan status = (status & 0x3fc0) >> 6;
1461819cbf18SXiaofei Tan
1462819cbf18SXiaofei Tan if (status != 0x1)
1463819cbf18SXiaofei Tan return true;
1464819cbf18SXiaofei Tan
1465819cbf18SXiaofei Tan tx_dfx0 = hisi_sas_phy_read32(hisi_hba, phy_no, DMA_TX_DFX0);
1466819cbf18SXiaofei Tan if ((tx_dfx0 & 0x1ff) == 0x2)
1467819cbf18SXiaofei Tan return true;
1468819cbf18SXiaofei Tan udelay(10);
1469819cbf18SXiaofei Tan }
1470819cbf18SXiaofei Tan dev_err(dev, "IO not done phy%d, port264:0x%x port200:0x%x\n",
1471819cbf18SXiaofei Tan phy_no, status, tx_dfx0);
1472819cbf18SXiaofei Tan return false;
1473819cbf18SXiaofei Tan }
1474819cbf18SXiaofei Tan
allowed_disable_phy_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1475819cbf18SXiaofei Tan static bool allowed_disable_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
1476819cbf18SXiaofei Tan {
1477819cbf18SXiaofei Tan if (tx_fifo_is_empty_v2_hw(hisi_hba, phy_no))
1478819cbf18SXiaofei Tan return true;
1479819cbf18SXiaofei Tan
1480819cbf18SXiaofei Tan if (!axi_bus_is_idle_v2_hw(hisi_hba, phy_no))
1481819cbf18SXiaofei Tan return false;
1482819cbf18SXiaofei Tan
1483819cbf18SXiaofei Tan if (!wait_io_done_v2_hw(hisi_hba, phy_no))
1484819cbf18SXiaofei Tan return false;
1485819cbf18SXiaofei Tan
1486819cbf18SXiaofei Tan return true;
1487819cbf18SXiaofei Tan }
1488819cbf18SXiaofei Tan
1489819cbf18SXiaofei Tan
disable_phy_v2_hw(struct hisi_hba * hisi_hba,int phy_no)149063fb11b8SJohn Garry static void disable_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
149163fb11b8SJohn Garry {
1492819cbf18SXiaofei Tan u32 cfg, axi_val, dfx0_val, txid_auto;
149311b75249SJohn Garry struct device *dev = hisi_hba->dev;
149463fb11b8SJohn Garry
1495819cbf18SXiaofei Tan /* Close axi bus. */
1496819cbf18SXiaofei Tan axi_val = hisi_sas_read32(hisi_hba, AXI_MASTER_CFG_BASE +
1497819cbf18SXiaofei Tan AM_CTRL_GLOBAL);
1498819cbf18SXiaofei Tan axi_val |= 0x1;
1499819cbf18SXiaofei Tan hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE +
1500819cbf18SXiaofei Tan AM_CTRL_GLOBAL, axi_val);
1501819cbf18SXiaofei Tan
1502819cbf18SXiaofei Tan if (is_sata_phy_v2_hw(hisi_hba, phy_no)) {
1503819cbf18SXiaofei Tan if (allowed_disable_phy_v2_hw(hisi_hba, phy_no))
1504819cbf18SXiaofei Tan goto do_disable;
1505819cbf18SXiaofei Tan
1506819cbf18SXiaofei Tan /* Reset host controller. */
1507819cbf18SXiaofei Tan queue_work(hisi_hba->wq, &hisi_hba->rst_work);
1508819cbf18SXiaofei Tan return;
1509819cbf18SXiaofei Tan }
1510819cbf18SXiaofei Tan
1511819cbf18SXiaofei Tan dfx0_val = hisi_sas_phy_read32(hisi_hba, phy_no, PORT_DFX0);
1512819cbf18SXiaofei Tan dfx0_val = (dfx0_val & 0x1fc0) >> 6;
1513819cbf18SXiaofei Tan if (dfx0_val != 0x4)
1514819cbf18SXiaofei Tan goto do_disable;
1515819cbf18SXiaofei Tan
1516819cbf18SXiaofei Tan if (!tx_fifo_is_empty_v2_hw(hisi_hba, phy_no)) {
1517819cbf18SXiaofei Tan dev_warn(dev, "phy%d, wait tx fifo need send break\n",
1518819cbf18SXiaofei Tan phy_no);
1519819cbf18SXiaofei Tan txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no,
1520819cbf18SXiaofei Tan TXID_AUTO);
1521819cbf18SXiaofei Tan txid_auto |= TXID_AUTO_CTB_MSK;
1522819cbf18SXiaofei Tan hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
1523819cbf18SXiaofei Tan txid_auto);
1524819cbf18SXiaofei Tan }
1525819cbf18SXiaofei Tan
1526819cbf18SXiaofei Tan do_disable:
1527819cbf18SXiaofei Tan cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
152863fb11b8SJohn Garry cfg &= ~PHY_CFG_ENA_MSK;
152963fb11b8SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
1530819cbf18SXiaofei Tan
1531819cbf18SXiaofei Tan /* Open axi bus. */
1532819cbf18SXiaofei Tan axi_val &= ~0x1;
1533819cbf18SXiaofei Tan hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE +
1534819cbf18SXiaofei Tan AM_CTRL_GLOBAL, axi_val);
153563fb11b8SJohn Garry }
153663fb11b8SJohn Garry
start_phy_v2_hw(struct hisi_hba * hisi_hba,int phy_no)153729a20428SJohn Garry static void start_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
153829a20428SJohn Garry {
153929a20428SJohn Garry config_id_frame_v2_hw(hisi_hba, phy_no);
154029a20428SJohn Garry config_phy_opt_mode_v2_hw(hisi_hba, phy_no);
154129a20428SJohn Garry enable_phy_v2_hw(hisi_hba, phy_no);
154229a20428SJohn Garry }
154329a20428SJohn Garry
phy_hard_reset_v2_hw(struct hisi_hba * hisi_hba,int phy_no)154463fb11b8SJohn Garry static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
154563fb11b8SJohn Garry {
15460edef7e4SXiang Chen struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
15470edef7e4SXiang Chen u32 txid_auto;
15480edef7e4SXiang Chen
1549c63b88ccSJohn Garry hisi_sas_phy_enable(hisi_hba, phy_no, 0);
15500edef7e4SXiang Chen if (phy->identify.device_type == SAS_END_DEVICE) {
15510edef7e4SXiang Chen txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
15520edef7e4SXiang Chen hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
15530edef7e4SXiang Chen txid_auto | TX_HARDRST_MSK);
15540edef7e4SXiang Chen }
155563fb11b8SJohn Garry msleep(100);
1556c63b88ccSJohn Garry hisi_sas_phy_enable(hisi_hba, phy_no, 1);
155763fb11b8SJohn Garry }
155863fb11b8SJohn Garry
phy_get_events_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1559c52108c6SXiaofei Tan static void phy_get_events_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
1560c52108c6SXiaofei Tan {
1561c52108c6SXiaofei Tan struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
1562c52108c6SXiaofei Tan struct asd_sas_phy *sas_phy = &phy->sas_phy;
1563c52108c6SXiaofei Tan struct sas_phy *sphy = sas_phy->phy;
1564c52108c6SXiaofei Tan u32 err4_reg_val, err6_reg_val;
1565c52108c6SXiaofei Tan
1566c52108c6SXiaofei Tan /* loss dword syn, phy reset problem */
1567c52108c6SXiaofei Tan err4_reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_ERR_CNT4_REG);
1568c52108c6SXiaofei Tan
1569c52108c6SXiaofei Tan /* disparity err, invalid dword */
1570c52108c6SXiaofei Tan err6_reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_ERR_CNT6_REG);
1571c52108c6SXiaofei Tan
1572c52108c6SXiaofei Tan sphy->loss_of_dword_sync_count += (err4_reg_val >> 16) & 0xFFFF;
1573c52108c6SXiaofei Tan sphy->phy_reset_problem_count += err4_reg_val & 0xFFFF;
1574c52108c6SXiaofei Tan sphy->invalid_dword_count += (err6_reg_val & 0xFF0000) >> 16;
1575c52108c6SXiaofei Tan sphy->running_disparity_error_count += err6_reg_val & 0xFF;
1576c52108c6SXiaofei Tan }
1577c52108c6SXiaofei Tan
phys_init_v2_hw(struct hisi_hba * hisi_hba)1578a25d0d3dSXiang Chen static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
157929a20428SJohn Garry {
158029a20428SJohn Garry int i;
158129a20428SJohn Garry
1582917d3bdaSXiaofei Tan for (i = 0; i < hisi_hba->n_phy; i++) {
1583917d3bdaSXiaofei Tan struct hisi_sas_phy *phy = &hisi_hba->phy[i];
1584917d3bdaSXiaofei Tan struct asd_sas_phy *sas_phy = &phy->sas_phy;
1585917d3bdaSXiaofei Tan
1586917d3bdaSXiaofei Tan if (!sas_phy->phy->enabled)
1587917d3bdaSXiaofei Tan continue;
1588917d3bdaSXiaofei Tan
1589c63b88ccSJohn Garry hisi_sas_phy_enable(hisi_hba, i, 1);
159029a20428SJohn Garry }
1591917d3bdaSXiaofei Tan }
159229a20428SJohn Garry
sl_notify_ssp_v2_hw(struct hisi_hba * hisi_hba,int phy_no)1593569eddcfSXiang Chen static void sl_notify_ssp_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
15947911e66fSJohn Garry {
15957911e66fSJohn Garry u32 sl_control;
15967911e66fSJohn Garry
15977911e66fSJohn Garry sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
15987911e66fSJohn Garry sl_control |= SL_CONTROL_NOTIFY_EN_MSK;
15997911e66fSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
16007911e66fSJohn Garry msleep(1);
16017911e66fSJohn Garry sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
16027911e66fSJohn Garry sl_control &= ~SL_CONTROL_NOTIFY_EN_MSK;
16037911e66fSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
16047911e66fSJohn Garry }
16057911e66fSJohn Garry
phy_get_max_linkrate_v2_hw(void)16062ae75787SXiang Chen static enum sas_linkrate phy_get_max_linkrate_v2_hw(void)
16072ae75787SXiang Chen {
16082ae75787SXiang Chen return SAS_LINK_RATE_12_0_GBPS;
16092ae75787SXiang Chen }
16102ae75787SXiang Chen
phy_set_linkrate_v2_hw(struct hisi_hba * hisi_hba,int phy_no,struct sas_phy_linkrates * r)16112ae75787SXiang Chen static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
16122ae75787SXiang Chen struct sas_phy_linkrates *r)
16132ae75787SXiang Chen {
1614757db2daSJohn Garry enum sas_linkrate max = r->maximum_linkrate;
1615c2c1d9deSXiang Chen u32 prog_phy_link_rate = 0x800;
16162ae75787SXiang Chen
1617c2c1d9deSXiang Chen prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
16182ae75787SXiang Chen hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
16192ae75787SXiang Chen prog_phy_link_rate);
16202ae75787SXiang Chen }
16212ae75787SXiang Chen
get_wideport_bitmap_v2_hw(struct hisi_hba * hisi_hba,int port_id)16225473c060SJohn Garry static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
16235473c060SJohn Garry {
16245473c060SJohn Garry int i, bitmap = 0;
16255473c060SJohn Garry u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
16265473c060SJohn Garry u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
16275473c060SJohn Garry
16285473c060SJohn Garry for (i = 0; i < (hisi_hba->n_phy < 9 ? hisi_hba->n_phy : 8); i++)
16295473c060SJohn Garry if (phy_state & 1 << i)
16305473c060SJohn Garry if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
16315473c060SJohn Garry bitmap |= 1 << i;
16325473c060SJohn Garry
16335473c060SJohn Garry if (hisi_hba->n_phy == 9) {
16345473c060SJohn Garry u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
16355473c060SJohn Garry
16365473c060SJohn Garry if (phy_state & 1 << 8)
16375473c060SJohn Garry if (((port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
16385473c060SJohn Garry PORT_STATE_PHY8_PORT_NUM_OFF) == port_id)
16395473c060SJohn Garry bitmap |= 1 << 9;
16405473c060SJohn Garry }
16415473c060SJohn Garry
16425473c060SJohn Garry return bitmap;
16435473c060SJohn Garry }
16445473c060SJohn Garry
1645fa222db0SXiang Chen /* DQ lock must be taken here */
start_delivery_v2_hw(struct hisi_sas_dq * dq)1646b1a49412SXiang Chen static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
16478c36e31dSJohn Garry {
1648b1a49412SXiang Chen struct hisi_hba *hisi_hba = dq->hisi_hba;
16491c09b663SXiaofei Tan struct hisi_sas_slot *s, *s1, *s2 = NULL;
1650fa222db0SXiang Chen int dlvry_queue = dq->id;
16511c09b663SXiaofei Tan int wp;
16528c36e31dSJohn Garry
1653fa222db0SXiang Chen list_for_each_entry_safe(s, s1, &dq->list, delivery) {
1654fa222db0SXiang Chen if (!s->ready)
1655fa222db0SXiang Chen break;
16561c09b663SXiaofei Tan s2 = s;
1657fa222db0SXiang Chen list_del(&s->delivery);
1658fa222db0SXiang Chen }
1659fa222db0SXiang Chen
16601c09b663SXiaofei Tan if (!s2)
1661fa222db0SXiang Chen return;
1662fa222db0SXiang Chen
16631c09b663SXiaofei Tan /*
16641c09b663SXiaofei Tan * Ensure that memories for slots built on other CPUs is observed.
16651c09b663SXiaofei Tan */
16661c09b663SXiaofei Tan smp_rmb();
16671c09b663SXiaofei Tan wp = (s2->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
16681c09b663SXiaofei Tan
1669fa222db0SXiang Chen hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
16708c36e31dSJohn Garry }
16718c36e31dSJohn Garry
prep_prd_sge_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot,struct hisi_sas_cmd_hdr * hdr,struct scatterlist * scatter,int n_elem)1672a2b3820bSXiang Chen static void prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
16738c36e31dSJohn Garry struct hisi_sas_slot *slot,
16748c36e31dSJohn Garry struct hisi_sas_cmd_hdr *hdr,
16758c36e31dSJohn Garry struct scatterlist *scatter,
16768c36e31dSJohn Garry int n_elem)
16778c36e31dSJohn Garry {
1678f557e32cSXiaofei Tan struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
16798c36e31dSJohn Garry struct scatterlist *sg;
16808c36e31dSJohn Garry int i;
16818c36e31dSJohn Garry
16828c36e31dSJohn Garry for_each_sg(scatter, sg, n_elem, i) {
1683f557e32cSXiaofei Tan struct hisi_sas_sge *entry = &sge_page->sge[i];
16848c36e31dSJohn Garry
16858c36e31dSJohn Garry entry->addr = cpu_to_le64(sg_dma_address(sg));
16868c36e31dSJohn Garry entry->page_ctrl_0 = entry->page_ctrl_1 = 0;
16878c36e31dSJohn Garry entry->data_len = cpu_to_le32(sg_dma_len(sg));
16888c36e31dSJohn Garry entry->data_off = 0;
16898c36e31dSJohn Garry }
16908c36e31dSJohn Garry
1691f557e32cSXiaofei Tan hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
16928c36e31dSJohn Garry
16938c36e31dSJohn Garry hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
16948c36e31dSJohn Garry }
16958c36e31dSJohn Garry
prep_smp_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot)1696a2b3820bSXiang Chen static void prep_smp_v2_hw(struct hisi_hba *hisi_hba,
1697c2d89392SJohn Garry struct hisi_sas_slot *slot)
1698c2d89392SJohn Garry {
1699c2d89392SJohn Garry struct sas_task *task = slot->task;
1700c2d89392SJohn Garry struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
1701c2d89392SJohn Garry struct domain_device *device = task->dev;
1702c2d89392SJohn Garry struct hisi_sas_port *port = slot->port;
17037eee4b92SXiang Chen struct scatterlist *sg_req;
1704c2d89392SJohn Garry struct hisi_sas_device *sas_dev = device->lldd_dev;
1705c2d89392SJohn Garry dma_addr_t req_dma_addr;
17067eee4b92SXiang Chen unsigned int req_len;
1707c2d89392SJohn Garry
1708c2d89392SJohn Garry /* req */
1709c2d89392SJohn Garry sg_req = &task->smp_task.smp_req;
1710c2d89392SJohn Garry req_dma_addr = sg_dma_address(sg_req);
17117eee4b92SXiang Chen req_len = sg_dma_len(&task->smp_task.smp_req);
1712c2d89392SJohn Garry
1713c2d89392SJohn Garry /* create header */
1714c2d89392SJohn Garry /* dw0 */
1715c2d89392SJohn Garry hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
1716c2d89392SJohn Garry (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */
1717c2d89392SJohn Garry (2 << CMD_HDR_CMD_OFF)); /* smp */
1718c2d89392SJohn Garry
1719c2d89392SJohn Garry /* map itct entry */
1720c2d89392SJohn Garry hdr->dw1 = cpu_to_le32((sas_dev->device_id << CMD_HDR_DEV_ID_OFF) |
1721c2d89392SJohn Garry (1 << CMD_HDR_FRAME_TYPE_OFF) |
1722c2d89392SJohn Garry (DIR_NO_DATA << CMD_HDR_DIR_OFF));
1723c2d89392SJohn Garry
1724c2d89392SJohn Garry /* dw2 */
1725c2d89392SJohn Garry hdr->dw2 = cpu_to_le32((((req_len - 4) / 4) << CMD_HDR_CFL_OFF) |
1726c2d89392SJohn Garry (HISI_SAS_MAX_SMP_RESP_SZ / 4 <<
1727c2d89392SJohn Garry CMD_HDR_MRFL_OFF));
1728c2d89392SJohn Garry
1729c2d89392SJohn Garry hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
1730c2d89392SJohn Garry
1731c2d89392SJohn Garry hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
1732f557e32cSXiaofei Tan hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
1733c2d89392SJohn Garry }
1734c2d89392SJohn Garry
prep_ssp_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot)1735a2b3820bSXiang Chen static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
173678bd2b4fSXiaofei Tan struct hisi_sas_slot *slot)
17378c36e31dSJohn Garry {
17388c36e31dSJohn Garry struct sas_task *task = slot->task;
17398c36e31dSJohn Garry struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
17408c36e31dSJohn Garry struct domain_device *device = task->dev;
17418c36e31dSJohn Garry struct hisi_sas_device *sas_dev = device->lldd_dev;
17428c36e31dSJohn Garry struct hisi_sas_port *port = slot->port;
17438c36e31dSJohn Garry struct sas_ssp_task *ssp_task = &task->ssp_task;
17448c36e31dSJohn Garry struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
1745bbfe82cdSJohn Garry struct sas_tmf_task *tmf = slot->tmf;
174678bd2b4fSXiaofei Tan int has_data = 0, priority = !!tmf;
17478c36e31dSJohn Garry u8 *buf_cmd;
17488c36e31dSJohn Garry u32 dw1 = 0, dw2 = 0;
17498c36e31dSJohn Garry
17508c36e31dSJohn Garry hdr->dw0 = cpu_to_le32((1 << CMD_HDR_RESP_REPORT_OFF) |
17518c36e31dSJohn Garry (2 << CMD_HDR_TLR_CTRL_OFF) |
17528c36e31dSJohn Garry (port->id << CMD_HDR_PORT_OFF) |
17538c36e31dSJohn Garry (priority << CMD_HDR_PRIORITY_OFF) |
17548c36e31dSJohn Garry (1 << CMD_HDR_CMD_OFF)); /* ssp */
17558c36e31dSJohn Garry
17568c36e31dSJohn Garry dw1 = 1 << CMD_HDR_VDTL_OFF;
175778bd2b4fSXiaofei Tan if (tmf) {
17588c36e31dSJohn Garry dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF;
17598c36e31dSJohn Garry dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF;
17608c36e31dSJohn Garry } else {
17618c36e31dSJohn Garry dw1 |= 1 << CMD_HDR_FRAME_TYPE_OFF;
17628c36e31dSJohn Garry switch (scsi_cmnd->sc_data_direction) {
17638c36e31dSJohn Garry case DMA_TO_DEVICE:
17648c36e31dSJohn Garry has_data = 1;
17658c36e31dSJohn Garry dw1 |= DIR_TO_DEVICE << CMD_HDR_DIR_OFF;
17668c36e31dSJohn Garry break;
17678c36e31dSJohn Garry case DMA_FROM_DEVICE:
17688c36e31dSJohn Garry has_data = 1;
17698c36e31dSJohn Garry dw1 |= DIR_TO_INI << CMD_HDR_DIR_OFF;
17708c36e31dSJohn Garry break;
17718c36e31dSJohn Garry default:
17728c36e31dSJohn Garry dw1 &= ~CMD_HDR_DIR_MSK;
17738c36e31dSJohn Garry }
17748c36e31dSJohn Garry }
17758c36e31dSJohn Garry
17768c36e31dSJohn Garry /* map itct entry */
17778c36e31dSJohn Garry dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
17788c36e31dSJohn Garry hdr->dw1 = cpu_to_le32(dw1);
17798c36e31dSJohn Garry
17808c36e31dSJohn Garry dw2 = (((sizeof(struct ssp_command_iu) + sizeof(struct ssp_frame_hdr)
17818c36e31dSJohn Garry + 3) / 4) << CMD_HDR_CFL_OFF) |
17828c36e31dSJohn Garry ((HISI_SAS_MAX_SSP_RESP_SZ / 4) << CMD_HDR_MRFL_OFF) |
17838c36e31dSJohn Garry (2 << CMD_HDR_SG_MOD_OFF);
17848c36e31dSJohn Garry hdr->dw2 = cpu_to_le32(dw2);
17858c36e31dSJohn Garry
17868c36e31dSJohn Garry hdr->transfer_tags = cpu_to_le32(slot->idx);
17878c36e31dSJohn Garry
1788a2b3820bSXiang Chen if (has_data)
1789a2b3820bSXiang Chen prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
17908c36e31dSJohn Garry slot->n_elem);
17918c36e31dSJohn Garry
17928c36e31dSJohn Garry hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
1793f557e32cSXiaofei Tan hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
1794f557e32cSXiaofei Tan hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
17958c36e31dSJohn Garry
1796f557e32cSXiaofei Tan buf_cmd = hisi_sas_cmd_hdr_addr_mem(slot) +
1797f557e32cSXiaofei Tan sizeof(struct ssp_frame_hdr);
17988c36e31dSJohn Garry
17998c36e31dSJohn Garry memcpy(buf_cmd, &task->ssp_task.LUN, 8);
180078bd2b4fSXiaofei Tan if (!tmf) {
1801*4dc051ebSJohn Garry buf_cmd[9] = task->ssp_task.task_attr;
18028c36e31dSJohn Garry memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
18038c36e31dSJohn Garry task->ssp_task.cmd->cmd_len);
18048c36e31dSJohn Garry } else {
18058c36e31dSJohn Garry buf_cmd[10] = tmf->tmf;
18068c36e31dSJohn Garry switch (tmf->tmf) {
18078c36e31dSJohn Garry case TMF_ABORT_TASK:
18088c36e31dSJohn Garry case TMF_QUERY_TASK:
18098c36e31dSJohn Garry buf_cmd[12] =
18108c36e31dSJohn Garry (tmf->tag_of_task_to_be_managed >> 8) & 0xff;
18118c36e31dSJohn Garry buf_cmd[13] =
18128c36e31dSJohn Garry tmf->tag_of_task_to_be_managed & 0xff;
18138c36e31dSJohn Garry break;
18148c36e31dSJohn Garry default:
18158c36e31dSJohn Garry break;
18168c36e31dSJohn Garry }
18178c36e31dSJohn Garry }
18188c36e31dSJohn Garry }
18198c36e31dSJohn Garry
1820634a9585SXiang Chen #define TRANS_TX_ERR 0
1821634a9585SXiang Chen #define TRANS_RX_ERR 1
1822634a9585SXiang Chen #define DMA_TX_ERR 2
1823634a9585SXiang Chen #define SIPC_RX_ERR 3
1824634a9585SXiang Chen #define DMA_RX_ERR 4
1825634a9585SXiang Chen
1826634a9585SXiang Chen #define DMA_TX_ERR_OFF 0
1827634a9585SXiang Chen #define DMA_TX_ERR_MSK (0xffff << DMA_TX_ERR_OFF)
1828634a9585SXiang Chen #define SIPC_RX_ERR_OFF 16
1829634a9585SXiang Chen #define SIPC_RX_ERR_MSK (0xffff << SIPC_RX_ERR_OFF)
1830634a9585SXiang Chen
parse_trans_tx_err_code_v2_hw(u32 err_msk)1831634a9585SXiang Chen static int parse_trans_tx_err_code_v2_hw(u32 err_msk)
1832634a9585SXiang Chen {
183389b203e9SColin Ian King static const u8 trans_tx_err_code_prio[] = {
1834634a9585SXiang Chen TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS,
1835634a9585SXiang Chen TRANS_TX_ERR_PHY_NOT_ENABLE,
1836634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION,
1837634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION,
1838634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_BY_OTHER,
1839634a9585SXiang Chen RESERVED0,
1840634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT,
1841634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_STP_RESOURCES_BUSY,
1842634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED,
1843634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED,
1844634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION,
1845634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD,
1846634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER,
1847634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED,
1848634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT,
1849634a9585SXiang Chen TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION,
1850634a9585SXiang Chen TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED,
1851634a9585SXiang Chen TRANS_TX_ERR_WITH_CLOSE_PHYDISALE,
1852634a9585SXiang Chen TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT,
1853634a9585SXiang Chen TRANS_TX_ERR_WITH_CLOSE_COMINIT,
1854634a9585SXiang Chen TRANS_TX_ERR_WITH_BREAK_TIMEOUT,
1855634a9585SXiang Chen TRANS_TX_ERR_WITH_BREAK_REQUEST,
1856634a9585SXiang Chen TRANS_TX_ERR_WITH_BREAK_RECEVIED,
1857634a9585SXiang Chen TRANS_TX_ERR_WITH_CLOSE_TIMEOUT,
1858634a9585SXiang Chen TRANS_TX_ERR_WITH_CLOSE_NORMAL,
1859634a9585SXiang Chen TRANS_TX_ERR_WITH_NAK_RECEVIED,
1860634a9585SXiang Chen TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT,
1861634a9585SXiang Chen TRANS_TX_ERR_WITH_CREDIT_TIMEOUT,
1862634a9585SXiang Chen TRANS_TX_ERR_WITH_IPTT_CONFLICT,
1863634a9585SXiang Chen TRANS_TX_ERR_WITH_OPEN_BY_DES_OR_OTHERS,
1864634a9585SXiang Chen TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT,
1865634a9585SXiang Chen };
1866634a9585SXiang Chen int index, i;
1867634a9585SXiang Chen
1868634a9585SXiang Chen for (i = 0; i < ARRAY_SIZE(trans_tx_err_code_prio); i++) {
1869634a9585SXiang Chen index = trans_tx_err_code_prio[i] - TRANS_TX_FAIL_BASE;
1870634a9585SXiang Chen if (err_msk & (1 << index))
1871634a9585SXiang Chen return trans_tx_err_code_prio[i];
1872634a9585SXiang Chen }
1873634a9585SXiang Chen return -1;
1874634a9585SXiang Chen }
1875634a9585SXiang Chen
parse_trans_rx_err_code_v2_hw(u32 err_msk)1876634a9585SXiang Chen static int parse_trans_rx_err_code_v2_hw(u32 err_msk)
1877634a9585SXiang Chen {
187889b203e9SColin Ian King static const u8 trans_rx_err_code_prio[] = {
1879634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR,
1880634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR,
1881634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM,
1882634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR,
1883634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_CRC_ERR,
1884634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN,
1885634a9585SXiang Chen TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP,
1886634a9585SXiang Chen TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN,
1887634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE,
1888634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT,
1889634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_COMINIT,
1890634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_TIMEOUT,
1891634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_REQUEST,
1892634a9585SXiang Chen TRANS_RX_ERR_WITH_BREAK_RECEVIED,
1893634a9585SXiang Chen RESERVED1,
1894634a9585SXiang Chen TRANS_RX_ERR_WITH_CLOSE_NORMAL,
1895634a9585SXiang Chen TRANS_RX_ERR_WITH_DATA_LEN0,
1896634a9585SXiang Chen TRANS_RX_ERR_WITH_BAD_HASH,
1897634a9585SXiang Chen TRANS_RX_XRDY_WLEN_ZERO_ERR,
1898634a9585SXiang Chen TRANS_RX_SSP_FRM_LEN_ERR,
1899634a9585SXiang Chen RESERVED2,
1900634a9585SXiang Chen RESERVED3,
1901634a9585SXiang Chen RESERVED4,
1902634a9585SXiang Chen RESERVED5,
1903634a9585SXiang Chen TRANS_RX_ERR_WITH_BAD_FRM_TYPE,
1904634a9585SXiang Chen TRANS_RX_SMP_FRM_LEN_ERR,
1905634a9585SXiang Chen TRANS_RX_SMP_RESP_TIMEOUT_ERR,
1906634a9585SXiang Chen RESERVED6,
1907634a9585SXiang Chen RESERVED7,
1908634a9585SXiang Chen RESERVED8,
1909634a9585SXiang Chen RESERVED9,
1910634a9585SXiang Chen TRANS_RX_R_ERR,
1911634a9585SXiang Chen };
1912634a9585SXiang Chen int index, i;
1913634a9585SXiang Chen
1914634a9585SXiang Chen for (i = 0; i < ARRAY_SIZE(trans_rx_err_code_prio); i++) {
1915634a9585SXiang Chen index = trans_rx_err_code_prio[i] - TRANS_RX_FAIL_BASE;
1916634a9585SXiang Chen if (err_msk & (1 << index))
1917634a9585SXiang Chen return trans_rx_err_code_prio[i];
1918634a9585SXiang Chen }
1919634a9585SXiang Chen return -1;
1920634a9585SXiang Chen }
1921634a9585SXiang Chen
parse_dma_tx_err_code_v2_hw(u32 err_msk)1922634a9585SXiang Chen static int parse_dma_tx_err_code_v2_hw(u32 err_msk)
1923634a9585SXiang Chen {
192489b203e9SColin Ian King static const u8 dma_tx_err_code_prio[] = {
1925634a9585SXiang Chen DMA_TX_UNEXP_XFER_ERR,
1926634a9585SXiang Chen DMA_TX_UNEXP_RETRANS_ERR,
1927634a9585SXiang Chen DMA_TX_XFER_LEN_OVERFLOW,
1928634a9585SXiang Chen DMA_TX_XFER_OFFSET_ERR,
1929634a9585SXiang Chen DMA_TX_RAM_ECC_ERR,
1930634a9585SXiang Chen DMA_TX_DIF_LEN_ALIGN_ERR,
1931634a9585SXiang Chen DMA_TX_DIF_CRC_ERR,
1932634a9585SXiang Chen DMA_TX_DIF_APP_ERR,
1933634a9585SXiang Chen DMA_TX_DIF_RPP_ERR,
1934634a9585SXiang Chen DMA_TX_DATA_SGL_OVERFLOW,
1935634a9585SXiang Chen DMA_TX_DIF_SGL_OVERFLOW,
1936634a9585SXiang Chen };
1937634a9585SXiang Chen int index, i;
1938634a9585SXiang Chen
1939634a9585SXiang Chen for (i = 0; i < ARRAY_SIZE(dma_tx_err_code_prio); i++) {
1940634a9585SXiang Chen index = dma_tx_err_code_prio[i] - DMA_TX_ERR_BASE;
1941634a9585SXiang Chen err_msk = err_msk & DMA_TX_ERR_MSK;
1942634a9585SXiang Chen if (err_msk & (1 << index))
1943634a9585SXiang Chen return dma_tx_err_code_prio[i];
1944634a9585SXiang Chen }
1945634a9585SXiang Chen return -1;
1946634a9585SXiang Chen }
1947634a9585SXiang Chen
parse_sipc_rx_err_code_v2_hw(u32 err_msk)1948634a9585SXiang Chen static int parse_sipc_rx_err_code_v2_hw(u32 err_msk)
1949634a9585SXiang Chen {
195089b203e9SColin Ian King static const u8 sipc_rx_err_code_prio[] = {
1951634a9585SXiang Chen SIPC_RX_FIS_STATUS_ERR_BIT_VLD,
1952634a9585SXiang Chen SIPC_RX_PIO_WRSETUP_STATUS_DRQ_ERR,
1953634a9585SXiang Chen SIPC_RX_FIS_STATUS_BSY_BIT_ERR,
1954634a9585SXiang Chen SIPC_RX_WRSETUP_LEN_ODD_ERR,
1955634a9585SXiang Chen SIPC_RX_WRSETUP_LEN_ZERO_ERR,
1956634a9585SXiang Chen SIPC_RX_WRDATA_LEN_NOT_MATCH_ERR,
1957634a9585SXiang Chen SIPC_RX_NCQ_WRSETUP_OFFSET_ERR,
1958634a9585SXiang Chen SIPC_RX_NCQ_WRSETUP_AUTO_ACTIVE_ERR,
1959634a9585SXiang Chen SIPC_RX_SATA_UNEXP_FIS_ERR,
1960634a9585SXiang Chen SIPC_RX_WRSETUP_ESTATUS_ERR,
1961634a9585SXiang Chen SIPC_RX_DATA_UNDERFLOW_ERR,
1962634a9585SXiang Chen };
1963634a9585SXiang Chen int index, i;
1964634a9585SXiang Chen
1965634a9585SXiang Chen for (i = 0; i < ARRAY_SIZE(sipc_rx_err_code_prio); i++) {
1966634a9585SXiang Chen index = sipc_rx_err_code_prio[i] - SIPC_RX_ERR_BASE;
1967634a9585SXiang Chen err_msk = err_msk & SIPC_RX_ERR_MSK;
1968634a9585SXiang Chen if (err_msk & (1 << (index + 0x10)))
1969634a9585SXiang Chen return sipc_rx_err_code_prio[i];
1970634a9585SXiang Chen }
1971634a9585SXiang Chen return -1;
1972634a9585SXiang Chen }
1973634a9585SXiang Chen
parse_dma_rx_err_code_v2_hw(u32 err_msk)1974634a9585SXiang Chen static int parse_dma_rx_err_code_v2_hw(u32 err_msk)
1975634a9585SXiang Chen {
197689b203e9SColin Ian King static const u8 dma_rx_err_code_prio[] = {
1977634a9585SXiang Chen DMA_RX_UNKNOWN_FRM_ERR,
1978634a9585SXiang Chen DMA_RX_DATA_LEN_OVERFLOW,
1979634a9585SXiang Chen DMA_RX_DATA_LEN_UNDERFLOW,
1980634a9585SXiang Chen DMA_RX_DATA_OFFSET_ERR,
1981634a9585SXiang Chen RESERVED10,
1982634a9585SXiang Chen DMA_RX_SATA_FRAME_TYPE_ERR,
1983634a9585SXiang Chen DMA_RX_RESP_BUF_OVERFLOW,
1984634a9585SXiang Chen DMA_RX_UNEXP_RETRANS_RESP_ERR,
1985634a9585SXiang Chen DMA_RX_UNEXP_NORM_RESP_ERR,
1986634a9585SXiang Chen DMA_RX_UNEXP_RDFRAME_ERR,
1987634a9585SXiang Chen DMA_RX_PIO_DATA_LEN_ERR,
1988634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_ERR,
1989634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_DRQ_ERR,
1990634a9585SXiang Chen DMA_RX_RDSETUP_STATUS_BSY_ERR,
1991634a9585SXiang Chen DMA_RX_RDSETUP_LEN_ODD_ERR,
1992634a9585SXiang Chen DMA_RX_RDSETUP_LEN_ZERO_ERR,
1993634a9585SXiang Chen DMA_RX_RDSETUP_LEN_OVER_ERR,
1994634a9585SXiang Chen DMA_RX_RDSETUP_OFFSET_ERR,
1995634a9585SXiang Chen DMA_RX_RDSETUP_ACTIVE_ERR,
1996634a9585SXiang Chen DMA_RX_RDSETUP_ESTATUS_ERR,
1997634a9585SXiang Chen DMA_RX_RAM_ECC_ERR,
1998634a9585SXiang Chen DMA_RX_DIF_CRC_ERR,
1999634a9585SXiang Chen DMA_RX_DIF_APP_ERR,
2000634a9585SXiang Chen DMA_RX_DIF_RPP_ERR,
2001634a9585SXiang Chen DMA_RX_DATA_SGL_OVERFLOW,
2002634a9585SXiang Chen DMA_RX_DIF_SGL_OVERFLOW,
2003634a9585SXiang Chen };
2004634a9585SXiang Chen int index, i;
2005634a9585SXiang Chen
2006634a9585SXiang Chen for (i = 0; i < ARRAY_SIZE(dma_rx_err_code_prio); i++) {
2007634a9585SXiang Chen index = dma_rx_err_code_prio[i] - DMA_RX_ERR_BASE;
2008634a9585SXiang Chen if (err_msk & (1 << index))
2009634a9585SXiang Chen return dma_rx_err_code_prio[i];
2010634a9585SXiang Chen }
2011634a9585SXiang Chen return -1;
2012634a9585SXiang Chen }
2013634a9585SXiang Chen
2014e8fed0e9SJohn Garry /* by default, task resp is complete */
slot_err_v2_hw(struct hisi_hba * hisi_hba,struct sas_task * task,struct hisi_sas_slot * slot,int err_phase)2015e8fed0e9SJohn Garry static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
2016e8fed0e9SJohn Garry struct sas_task *task,
2017634a9585SXiang Chen struct hisi_sas_slot *slot,
2018634a9585SXiang Chen int err_phase)
2019e8fed0e9SJohn Garry {
2020e8fed0e9SJohn Garry struct task_status_struct *ts = &task->task_status;
2021f557e32cSXiaofei Tan struct hisi_sas_err_record_v2 *err_record =
2022f557e32cSXiaofei Tan hisi_sas_status_buf_addr_mem(slot);
2023735bcc77SJohn Garry u32 trans_tx_fail_type = le32_to_cpu(err_record->trans_tx_fail_type);
2024735bcc77SJohn Garry u32 trans_rx_fail_type = le32_to_cpu(err_record->trans_rx_fail_type);
2025735bcc77SJohn Garry u16 dma_tx_err_type = le16_to_cpu(err_record->dma_tx_err_type);
2026735bcc77SJohn Garry u16 sipc_rx_err_type = le16_to_cpu(err_record->sipc_rx_err_type);
2027735bcc77SJohn Garry u32 dma_rx_err_type = le32_to_cpu(err_record->dma_rx_err_type);
2028f5393a56SXingui Yang struct hisi_sas_complete_v2_hdr *complete_queue =
2029f5393a56SXingui Yang hisi_hba->complete_hdr[slot->cmplt_queue];
2030f5393a56SXingui Yang struct hisi_sas_complete_v2_hdr *complete_hdr =
2031f5393a56SXingui Yang &complete_queue[slot->cmplt_queue_slot];
2032f5393a56SXingui Yang u32 dw0 = le32_to_cpu(complete_hdr->dw0);
2033e8fed0e9SJohn Garry int error = -1;
2034e8fed0e9SJohn Garry
2035634a9585SXiang Chen if (err_phase == 1) {
2036634a9585SXiang Chen /* error in TX phase, the priority of error is: DW2 > DW0 */
2037634a9585SXiang Chen error = parse_dma_tx_err_code_v2_hw(dma_tx_err_type);
2038634a9585SXiang Chen if (error == -1)
2039634a9585SXiang Chen error = parse_trans_tx_err_code_v2_hw(
2040634a9585SXiang Chen trans_tx_fail_type);
2041634a9585SXiang Chen } else if (err_phase == 2) {
2042634a9585SXiang Chen /* error in RX phase, the priority is: DW1 > DW3 > DW2 */
2043735bcc77SJohn Garry error = parse_trans_rx_err_code_v2_hw(trans_rx_fail_type);
2044634a9585SXiang Chen if (error == -1) {
2045634a9585SXiang Chen error = parse_dma_rx_err_code_v2_hw(
2046634a9585SXiang Chen dma_rx_err_type);
2047634a9585SXiang Chen if (error == -1)
2048634a9585SXiang Chen error = parse_sipc_rx_err_code_v2_hw(
2049634a9585SXiang Chen sipc_rx_err_type);
2050634a9585SXiang Chen }
2051e8fed0e9SJohn Garry }
2052e8fed0e9SJohn Garry
2053e8fed0e9SJohn Garry switch (task->task_proto) {
2054e8fed0e9SJohn Garry case SAS_PROTOCOL_SSP:
2055e8fed0e9SJohn Garry {
2056e8fed0e9SJohn Garry switch (error) {
2057e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION:
2058e8fed0e9SJohn Garry {
2059e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2060e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_NO_DEST;
2061a28b259bSColin Ian King break;
2062e8fed0e9SJohn Garry }
2063e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED:
2064e8fed0e9SJohn Garry {
2065e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2066e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_EPROTO;
2067e8fed0e9SJohn Garry break;
2068e8fed0e9SJohn Garry }
2069e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED:
2070e8fed0e9SJohn Garry {
2071e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2072e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_CONN_RATE;
2073e8fed0e9SJohn Garry break;
2074e8fed0e9SJohn Garry }
2075e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION:
2076e8fed0e9SJohn Garry {
2077e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2078e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_BAD_DEST;
2079e8fed0e9SJohn Garry break;
2080e8fed0e9SJohn Garry }
2081e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION:
2082e8fed0e9SJohn Garry {
2083e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2084e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
2085e8fed0e9SJohn Garry break;
2086e8fed0e9SJohn Garry }
2087634a9585SXiang Chen case DMA_RX_UNEXP_NORM_RESP_ERR:
2088e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION:
2089634a9585SXiang Chen case DMA_RX_RESP_BUF_OVERFLOW:
2090e8fed0e9SJohn Garry {
2091e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2092e8fed0e9SJohn Garry ts->open_rej_reason = SAS_OREJ_UNKNOWN;
2093e8fed0e9SJohn Garry break;
2094e8fed0e9SJohn Garry }
2095e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER:
2096e8fed0e9SJohn Garry {
2097e8fed0e9SJohn Garry /* not sure */
2098e8fed0e9SJohn Garry ts->stat = SAS_DEV_NO_RESPONSE;
2099e8fed0e9SJohn Garry break;
2100e8fed0e9SJohn Garry }
2101e8fed0e9SJohn Garry case DMA_RX_DATA_LEN_OVERFLOW:
2102e8fed0e9SJohn Garry {
2103e8fed0e9SJohn Garry ts->stat = SAS_DATA_OVERRUN;
2104e8fed0e9SJohn Garry ts->residual = 0;
2105e8fed0e9SJohn Garry break;
2106e8fed0e9SJohn Garry }
2107e8fed0e9SJohn Garry case DMA_RX_DATA_LEN_UNDERFLOW:
2108e8fed0e9SJohn Garry {
210901b361fcSXiang Chen ts->residual = trans_tx_fail_type;
2110e8fed0e9SJohn Garry ts->stat = SAS_DATA_UNDERRUN;
2111e8fed0e9SJohn Garry break;
2112e8fed0e9SJohn Garry }
2113e8fed0e9SJohn Garry case TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS:
2114e8fed0e9SJohn Garry case TRANS_TX_ERR_PHY_NOT_ENABLE:
2115e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_BY_OTHER:
2116e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT:
2117634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD:
2118634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED:
2119634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT:
2120e8fed0e9SJohn Garry case TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED:
2121e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_TIMEOUT:
2122e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_REQUEST:
2123e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_RECEVIED:
2124e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_TIMEOUT:
2125e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_NORMAL:
2126634a9585SXiang Chen case TRANS_TX_ERR_WITH_CLOSE_PHYDISALE:
2127e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT:
2128e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_COMINIT:
2129e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_NAK_RECEVIED:
2130e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT:
2131e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CREDIT_TIMEOUT:
2132634a9585SXiang Chen case TRANS_TX_ERR_WITH_IPTT_CONFLICT:
2133e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR:
2134e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR:
2135e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM:
2136634a9585SXiang Chen case TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN:
2137e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BREAK_TIMEOUT:
2138e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BREAK_REQUEST:
2139e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BREAK_RECEVIED:
2140e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_NORMAL:
2141e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT:
2142e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_COMINIT:
2143634a9585SXiang Chen case TRANS_TX_ERR_FRAME_TXED:
2144634a9585SXiang Chen case TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE:
2145e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_DATA_LEN0:
2146e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BAD_HASH:
2147e8fed0e9SJohn Garry case TRANS_RX_XRDY_WLEN_ZERO_ERR:
2148e8fed0e9SJohn Garry case TRANS_RX_SSP_FRM_LEN_ERR:
2149e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BAD_FRM_TYPE:
2150634a9585SXiang Chen case DMA_TX_DATA_SGL_OVERFLOW:
2151e8fed0e9SJohn Garry case DMA_TX_UNEXP_XFER_ERR:
2152e8fed0e9SJohn Garry case DMA_TX_UNEXP_RETRANS_ERR:
2153e8fed0e9SJohn Garry case DMA_TX_XFER_LEN_OVERFLOW:
2154e8fed0e9SJohn Garry case DMA_TX_XFER_OFFSET_ERR:
2155634a9585SXiang Chen case SIPC_RX_DATA_UNDERFLOW_ERR:
2156634a9585SXiang Chen case DMA_RX_DATA_SGL_OVERFLOW:
2157e8fed0e9SJohn Garry case DMA_RX_DATA_OFFSET_ERR:
2158634a9585SXiang Chen case DMA_RX_RDSETUP_LEN_ODD_ERR:
2159634a9585SXiang Chen case DMA_RX_RDSETUP_LEN_ZERO_ERR:
2160634a9585SXiang Chen case DMA_RX_RDSETUP_LEN_OVER_ERR:
2161634a9585SXiang Chen case DMA_RX_SATA_FRAME_TYPE_ERR:
2162e8fed0e9SJohn Garry case DMA_RX_UNKNOWN_FRM_ERR:
2163e8fed0e9SJohn Garry {
2164634a9585SXiang Chen /* This will request a retry */
2165634a9585SXiang Chen ts->stat = SAS_QUEUE_FULL;
2166634a9585SXiang Chen slot->abort = 1;
2167e8fed0e9SJohn Garry break;
2168e8fed0e9SJohn Garry }
2169e8fed0e9SJohn Garry default:
2170e8fed0e9SJohn Garry break;
2171e8fed0e9SJohn Garry }
2172e8fed0e9SJohn Garry }
2173e8fed0e9SJohn Garry break;
2174e8fed0e9SJohn Garry case SAS_PROTOCOL_SMP:
2175d377f415SBart Van Assche ts->stat = SAS_SAM_STAT_CHECK_CONDITION;
2176e8fed0e9SJohn Garry break;
2177e8fed0e9SJohn Garry
2178e8fed0e9SJohn Garry case SAS_PROTOCOL_SATA:
2179e8fed0e9SJohn Garry case SAS_PROTOCOL_STP:
2180e8fed0e9SJohn Garry case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
2181e8fed0e9SJohn Garry {
2182e8fed0e9SJohn Garry switch (error) {
2183e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION:
2184e8fed0e9SJohn Garry {
2185634a9585SXiang Chen ts->stat = SAS_OPEN_REJECT;
2186634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_NO_DEST;
2187634a9585SXiang Chen break;
2188634a9585SXiang Chen }
2189634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER:
2190634a9585SXiang Chen {
2191e8fed0e9SJohn Garry ts->resp = SAS_TASK_UNDELIVERED;
2192e8fed0e9SJohn Garry ts->stat = SAS_DEV_NO_RESPONSE;
2193e8fed0e9SJohn Garry break;
2194e8fed0e9SJohn Garry }
2195e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED:
2196e8fed0e9SJohn Garry {
2197e8fed0e9SJohn Garry ts->stat = SAS_OPEN_REJECT;
2198634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_EPROTO;
2199e8fed0e9SJohn Garry break;
2200e8fed0e9SJohn Garry }
2201634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED:
2202e8fed0e9SJohn Garry {
2203634a9585SXiang Chen ts->stat = SAS_OPEN_REJECT;
2204634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_CONN_RATE;
2205634a9585SXiang Chen break;
2206634a9585SXiang Chen }
2207634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION:
2208634a9585SXiang Chen {
2209634a9585SXiang Chen ts->stat = SAS_OPEN_REJECT;
2210634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_CONN_RATE;
2211634a9585SXiang Chen break;
2212634a9585SXiang Chen }
2213634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION:
2214634a9585SXiang Chen {
2215634a9585SXiang Chen ts->stat = SAS_OPEN_REJECT;
2216634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
2217634a9585SXiang Chen break;
2218634a9585SXiang Chen }
2219634a9585SXiang Chen case DMA_RX_RESP_BUF_OVERFLOW:
2220634a9585SXiang Chen case DMA_RX_UNEXP_NORM_RESP_ERR:
2221634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION:
2222634a9585SXiang Chen {
2223634a9585SXiang Chen ts->stat = SAS_OPEN_REJECT;
2224634a9585SXiang Chen ts->open_rej_reason = SAS_OREJ_UNKNOWN;
2225e8fed0e9SJohn Garry break;
2226e8fed0e9SJohn Garry }
2227e8fed0e9SJohn Garry case DMA_RX_DATA_LEN_OVERFLOW:
2228e8fed0e9SJohn Garry {
2229e8fed0e9SJohn Garry ts->stat = SAS_DATA_OVERRUN;
2230634a9585SXiang Chen ts->residual = 0;
2231634a9585SXiang Chen break;
2232634a9585SXiang Chen }
2233634a9585SXiang Chen case DMA_RX_DATA_LEN_UNDERFLOW:
2234634a9585SXiang Chen {
223501b361fcSXiang Chen ts->residual = trans_tx_fail_type;
2236634a9585SXiang Chen ts->stat = SAS_DATA_UNDERRUN;
2237e8fed0e9SJohn Garry break;
2238e8fed0e9SJohn Garry }
2239e8fed0e9SJohn Garry case TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS:
2240e8fed0e9SJohn Garry case TRANS_TX_ERR_PHY_NOT_ENABLE:
2241e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_BY_OTHER:
2242e8fed0e9SJohn Garry case TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT:
2243634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD:
2244634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED:
2245634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT:
2246e8fed0e9SJohn Garry case TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED:
2247e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_TIMEOUT:
2248e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_REQUEST:
2249e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_BREAK_RECEVIED:
2250e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_TIMEOUT:
2251e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_NORMAL:
2252634a9585SXiang Chen case TRANS_TX_ERR_WITH_CLOSE_PHYDISALE:
2253e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT:
2254e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CLOSE_COMINIT:
2255e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT:
2256e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_CREDIT_TIMEOUT:
2257634a9585SXiang Chen case TRANS_TX_ERR_WITH_OPEN_BY_DES_OR_OTHERS:
2258e8fed0e9SJohn Garry case TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT:
2259e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM:
2260634a9585SXiang Chen case TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR:
2261e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR:
2262e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFIS_CRC_ERR:
2263e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN:
2264e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP:
2265634a9585SXiang Chen case TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN:
2266634a9585SXiang Chen case TRANS_RX_ERR_WITH_BREAK_TIMEOUT:
2267634a9585SXiang Chen case TRANS_RX_ERR_WITH_BREAK_REQUEST:
2268634a9585SXiang Chen case TRANS_RX_ERR_WITH_BREAK_RECEVIED:
2269e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_NORMAL:
2270e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE:
2271e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT:
2272e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_CLOSE_COMINIT:
2273e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_DATA_LEN0:
2274e8fed0e9SJohn Garry case TRANS_RX_ERR_WITH_BAD_HASH:
2275e8fed0e9SJohn Garry case TRANS_RX_XRDY_WLEN_ZERO_ERR:
2276634a9585SXiang Chen case TRANS_RX_ERR_WITH_BAD_FRM_TYPE:
2277634a9585SXiang Chen case DMA_TX_DATA_SGL_OVERFLOW:
2278634a9585SXiang Chen case DMA_TX_UNEXP_XFER_ERR:
2279634a9585SXiang Chen case DMA_TX_UNEXP_RETRANS_ERR:
2280634a9585SXiang Chen case DMA_TX_XFER_LEN_OVERFLOW:
2281634a9585SXiang Chen case DMA_TX_XFER_OFFSET_ERR:
2282e8fed0e9SJohn Garry case SIPC_RX_FIS_STATUS_ERR_BIT_VLD:
2283e8fed0e9SJohn Garry case SIPC_RX_PIO_WRSETUP_STATUS_DRQ_ERR:
2284e8fed0e9SJohn Garry case SIPC_RX_FIS_STATUS_BSY_BIT_ERR:
2285e8fed0e9SJohn Garry case SIPC_RX_WRSETUP_LEN_ODD_ERR:
2286e8fed0e9SJohn Garry case SIPC_RX_WRSETUP_LEN_ZERO_ERR:
2287e8fed0e9SJohn Garry case SIPC_RX_WRDATA_LEN_NOT_MATCH_ERR:
2288e8fed0e9SJohn Garry case SIPC_RX_SATA_UNEXP_FIS_ERR:
2289634a9585SXiang Chen case DMA_RX_DATA_SGL_OVERFLOW:
2290634a9585SXiang Chen case DMA_RX_DATA_OFFSET_ERR:
2291e8fed0e9SJohn Garry case DMA_RX_SATA_FRAME_TYPE_ERR:
2292e8fed0e9SJohn Garry case DMA_RX_UNEXP_RDFRAME_ERR:
2293e8fed0e9SJohn Garry case DMA_RX_PIO_DATA_LEN_ERR:
2294e8fed0e9SJohn Garry case DMA_RX_RDSETUP_STATUS_ERR:
2295e8fed0e9SJohn Garry case DMA_RX_RDSETUP_STATUS_DRQ_ERR:
2296e8fed0e9SJohn Garry case DMA_RX_RDSETUP_STATUS_BSY_ERR:
2297e8fed0e9SJohn Garry case DMA_RX_RDSETUP_LEN_ODD_ERR:
2298e8fed0e9SJohn Garry case DMA_RX_RDSETUP_LEN_ZERO_ERR:
2299e8fed0e9SJohn Garry case DMA_RX_RDSETUP_LEN_OVER_ERR:
2300e8fed0e9SJohn Garry case DMA_RX_RDSETUP_OFFSET_ERR:
2301e8fed0e9SJohn Garry case DMA_RX_RDSETUP_ACTIVE_ERR:
2302e8fed0e9SJohn Garry case DMA_RX_RDSETUP_ESTATUS_ERR:
2303e8fed0e9SJohn Garry case DMA_RX_UNKNOWN_FRM_ERR:
2304634a9585SXiang Chen case TRANS_RX_SSP_FRM_LEN_ERR:
2305634a9585SXiang Chen case TRANS_TX_OPEN_CNX_ERR_STP_RESOURCES_BUSY:
2306e8fed0e9SJohn Garry {
2307634a9585SXiang Chen slot->abort = 1;
2308634a9585SXiang Chen ts->stat = SAS_PHY_DOWN;
2309e8fed0e9SJohn Garry break;
2310e8fed0e9SJohn Garry }
2311e8fed0e9SJohn Garry default:
2312e8fed0e9SJohn Garry {
2313e8fed0e9SJohn Garry ts->stat = SAS_PROTO_RESPONSE;
2314e8fed0e9SJohn Garry break;
2315e8fed0e9SJohn Garry }
2316e8fed0e9SJohn Garry }
2317f5393a56SXingui Yang if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
231875904077SXiang Chen hisi_sas_sata_done(task, slot);
2319e8fed0e9SJohn Garry }
2320e8fed0e9SJohn Garry break;
2321e8fed0e9SJohn Garry default:
2322e8fed0e9SJohn Garry break;
2323e8fed0e9SJohn Garry }
2324e8fed0e9SJohn Garry }
2325e8fed0e9SJohn Garry
slot_complete_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot)23261cdee004SJohn Garry static void slot_complete_v2_hw(struct hisi_hba *hisi_hba,
23271cdee004SJohn Garry struct hisi_sas_slot *slot)
232831a9cfa6SJohn Garry {
232931a9cfa6SJohn Garry struct sas_task *task = slot->task;
233031a9cfa6SJohn Garry struct hisi_sas_device *sas_dev;
233111b75249SJohn Garry struct device *dev = hisi_hba->dev;
233231a9cfa6SJohn Garry struct task_status_struct *ts;
233331a9cfa6SJohn Garry struct domain_device *device;
2334cd938e53SXiang Chen struct sas_ha_struct *ha;
233531a9cfa6SJohn Garry struct hisi_sas_complete_v2_hdr *complete_queue =
233631a9cfa6SJohn Garry hisi_hba->complete_hdr[slot->cmplt_queue];
233731a9cfa6SJohn Garry struct hisi_sas_complete_v2_hdr *complete_hdr =
233831a9cfa6SJohn Garry &complete_queue[slot->cmplt_queue_slot];
233954c9dd2dSJohn Garry unsigned long flags;
2340cd938e53SXiang Chen bool is_internal = slot->is_internal;
2341735bcc77SJohn Garry u32 dw0;
234231a9cfa6SJohn Garry
234331a9cfa6SJohn Garry if (unlikely(!task || !task->lldd_task || !task->dev))
23441cdee004SJohn Garry return;
234531a9cfa6SJohn Garry
234631a9cfa6SJohn Garry ts = &task->task_status;
234731a9cfa6SJohn Garry device = task->dev;
2348cd938e53SXiang Chen ha = device->port->ha;
234931a9cfa6SJohn Garry sas_dev = device->lldd_dev;
235031a9cfa6SJohn Garry
235154c9dd2dSJohn Garry spin_lock_irqsave(&task->task_state_lock, flags);
235226fc0ea7SJohn Garry task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
235354c9dd2dSJohn Garry spin_unlock_irqrestore(&task->task_state_lock, flags);
235431a9cfa6SJohn Garry
235531a9cfa6SJohn Garry memset(ts, 0, sizeof(*ts));
235631a9cfa6SJohn Garry ts->resp = SAS_TASK_COMPLETE;
235731a9cfa6SJohn Garry
2358405314dfSJohn Garry if (unlikely(!sas_dev)) {
2359405314dfSJohn Garry dev_dbg(dev, "slot complete: port has no device\n");
236031a9cfa6SJohn Garry ts->stat = SAS_PHY_DOWN;
236131a9cfa6SJohn Garry goto out;
236231a9cfa6SJohn Garry }
236331a9cfa6SJohn Garry
2364df032d0eSJohn Garry /* Use SAS+TMF status codes */
2365735bcc77SJohn Garry dw0 = le32_to_cpu(complete_hdr->dw0);
2366735bcc77SJohn Garry switch ((dw0 & CMPLT_HDR_ABORT_STAT_MSK) >>
2367735bcc77SJohn Garry CMPLT_HDR_ABORT_STAT_OFF) {
2368df032d0eSJohn Garry case STAT_IO_ABORTED:
2369df032d0eSJohn Garry /* this io has been aborted by abort command */
2370df032d0eSJohn Garry ts->stat = SAS_ABORTED_TASK;
2371df032d0eSJohn Garry goto out;
2372df032d0eSJohn Garry case STAT_IO_COMPLETE:
2373df032d0eSJohn Garry /* internal abort command complete */
2374c35279f2SJohn Garry ts->stat = TMF_RESP_FUNC_SUCC;
2375080b4f97SXiang Chen del_timer_sync(&slot->internal_abort_timer);
2376df032d0eSJohn Garry goto out;
2377df032d0eSJohn Garry case STAT_IO_NO_DEVICE:
2378df032d0eSJohn Garry ts->stat = TMF_RESP_FUNC_COMPLETE;
2379080b4f97SXiang Chen del_timer_sync(&slot->internal_abort_timer);
2380df032d0eSJohn Garry goto out;
2381df032d0eSJohn Garry case STAT_IO_NOT_VALID:
2382df032d0eSJohn Garry /* abort single io, controller don't find
2383df032d0eSJohn Garry * the io need to abort
2384df032d0eSJohn Garry */
2385df032d0eSJohn Garry ts->stat = TMF_RESP_FUNC_FAILED;
2386080b4f97SXiang Chen del_timer_sync(&slot->internal_abort_timer);
2387df032d0eSJohn Garry goto out;
2388df032d0eSJohn Garry default:
2389df032d0eSJohn Garry break;
2390df032d0eSJohn Garry }
2391df032d0eSJohn Garry
2392735bcc77SJohn Garry if ((dw0 & CMPLT_HDR_ERX_MSK) && (!(dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
2393735bcc77SJohn Garry u32 err_phase = (dw0 & CMPLT_HDR_ERR_PHASE_MSK)
2394634a9585SXiang Chen >> CMPLT_HDR_ERR_PHASE_OFF;
2395f1c88211SXiang Chen u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
239631a9cfa6SJohn Garry
2397634a9585SXiang Chen /* Analyse error happens on which phase TX or RX */
2398634a9585SXiang Chen if (ERR_ON_TX_PHASE(err_phase))
2399634a9585SXiang Chen slot_err_v2_hw(hisi_hba, task, slot, 1);
2400634a9585SXiang Chen else if (ERR_ON_RX_PHASE(err_phase))
2401634a9585SXiang Chen slot_err_v2_hw(hisi_hba, task, slot, 2);
2402fc866951SXiang Chen
2403f1c88211SXiang Chen if (ts->stat != SAS_DATA_UNDERRUN)
2404e7513f66SXiang Chen dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n",
2405381ed6c0SJohn Garry slot->idx, task, sas_dev->device_id,
2406f1c88211SXiang Chen complete_hdr->dw0, complete_hdr->dw1,
2407f1c88211SXiang Chen complete_hdr->act, complete_hdr->dw3,
2408f1c88211SXiang Chen error_info[0], error_info[1],
2409f1c88211SXiang Chen error_info[2], error_info[3]);
2410f1c88211SXiang Chen
241105d91b55SLuo Jiaxing if (unlikely(slot->abort)) {
2412bb544224SXingui Yang if (dev_is_sata(device) && task->ata_task.use_ncq)
2413bb544224SXingui Yang sas_ata_device_link_abort(device, true);
2414bb544224SXingui Yang else
241505d91b55SLuo Jiaxing sas_task_abort(task);
2416bb544224SXingui Yang
24171cdee004SJohn Garry return;
241805d91b55SLuo Jiaxing }
241931a9cfa6SJohn Garry goto out;
242031a9cfa6SJohn Garry }
242131a9cfa6SJohn Garry
242231a9cfa6SJohn Garry switch (task->task_proto) {
242331a9cfa6SJohn Garry case SAS_PROTOCOL_SSP:
242431a9cfa6SJohn Garry {
2425f557e32cSXiaofei Tan struct hisi_sas_status_buffer *status_buffer =
2426f557e32cSXiaofei Tan hisi_sas_status_buf_addr_mem(slot);
2427f557e32cSXiaofei Tan struct ssp_response_iu *iu = (struct ssp_response_iu *)
2428f557e32cSXiaofei Tan &status_buffer->iu[0];
242931a9cfa6SJohn Garry
243031a9cfa6SJohn Garry sas_ssp_task_response(dev, task, iu);
243131a9cfa6SJohn Garry break;
243231a9cfa6SJohn Garry }
243331a9cfa6SJohn Garry case SAS_PROTOCOL_SMP:
243431a9cfa6SJohn Garry {
243531a9cfa6SJohn Garry struct scatterlist *sg_resp = &task->smp_task.smp_resp;
24361c003146SJohn Garry void *to = page_address(sg_page(sg_resp));
243731a9cfa6SJohn Garry
2438d377f415SBart Van Assche ts->stat = SAS_SAM_STAT_GOOD;
243931a9cfa6SJohn Garry
244031a9cfa6SJohn Garry memcpy(to + sg_resp->offset,
2441f557e32cSXiaofei Tan hisi_sas_status_buf_addr_mem(slot) +
244231a9cfa6SJohn Garry sizeof(struct hisi_sas_err_record),
24435f6c32d7SJohn Garry sg_resp->length);
244431a9cfa6SJohn Garry break;
244531a9cfa6SJohn Garry }
244631a9cfa6SJohn Garry case SAS_PROTOCOL_SATA:
244731a9cfa6SJohn Garry case SAS_PROTOCOL_STP:
244831a9cfa6SJohn Garry case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
24496f2ff1a1SJohn Garry {
2450d377f415SBart Van Assche ts->stat = SAS_SAM_STAT_GOOD;
2451f5393a56SXingui Yang if (dw0 & CMPLT_HDR_RSPNS_XFRD_MSK)
245275904077SXiang Chen hisi_sas_sata_done(task, slot);
24536f2ff1a1SJohn Garry break;
24546f2ff1a1SJohn Garry }
245531a9cfa6SJohn Garry default:
2456d377f415SBart Van Assche ts->stat = SAS_SAM_STAT_CHECK_CONDITION;
245731a9cfa6SJohn Garry break;
245831a9cfa6SJohn Garry }
245931a9cfa6SJohn Garry
246031a9cfa6SJohn Garry if (!slot->port->port_attached) {
2461f1c88211SXiang Chen dev_warn(dev, "slot complete: port %d has removed\n",
246231a9cfa6SJohn Garry slot->port->sas_port.id);
246331a9cfa6SJohn Garry ts->stat = SAS_PHY_DOWN;
246431a9cfa6SJohn Garry }
246531a9cfa6SJohn Garry
246631a9cfa6SJohn Garry out:
246754c9dd2dSJohn Garry spin_lock_irqsave(&task->task_state_lock, flags);
2468b81b6cceSXiang Chen if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
2469b81b6cceSXiang Chen spin_unlock_irqrestore(&task->task_state_lock, flags);
2470e7513f66SXiang Chen dev_info(dev, "slot complete: task(%pK) aborted\n", task);
24711cdee004SJohn Garry return;
2472b81b6cceSXiang Chen }
2473fc866951SXiang Chen task->task_state_flags |= SAS_TASK_STATE_DONE;
247454c9dd2dSJohn Garry spin_unlock_irqrestore(&task->task_state_lock, flags);
247571fb36b5SXingui Yang hisi_sas_slot_task_free(hisi_hba, task, slot, true);
247631a9cfa6SJohn Garry
2477cd938e53SXiang Chen if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) {
2478cd938e53SXiang Chen spin_lock_irqsave(&device->done_lock, flags);
2479cd938e53SXiang Chen if (test_bit(SAS_HA_FROZEN, &ha->state)) {
2480cd938e53SXiang Chen spin_unlock_irqrestore(&device->done_lock, flags);
2481e7513f66SXiang Chen dev_info(dev, "slot complete: task(%pK) ignored\n",
2482cd938e53SXiang Chen task);
24831cdee004SJohn Garry return;
2484cd938e53SXiang Chen }
2485cd938e53SXiang Chen spin_unlock_irqrestore(&device->done_lock, flags);
2486cd938e53SXiang Chen }
2487cd938e53SXiang Chen
248831a9cfa6SJohn Garry if (task->task_done)
248931a9cfa6SJohn Garry task->task_done(task);
249031a9cfa6SJohn Garry }
249131a9cfa6SJohn Garry
prep_ata_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot)2492a2b3820bSXiang Chen static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
24936f2ff1a1SJohn Garry struct hisi_sas_slot *slot)
24946f2ff1a1SJohn Garry {
24956f2ff1a1SJohn Garry struct sas_task *task = slot->task;
24966f2ff1a1SJohn Garry struct domain_device *device = task->dev;
24976f2ff1a1SJohn Garry struct domain_device *parent_dev = device->parent;
24986f2ff1a1SJohn Garry struct hisi_sas_device *sas_dev = device->lldd_dev;
24996f2ff1a1SJohn Garry struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
25002e244f0fSJohn Garry struct asd_sas_port *sas_port = device->port;
25012e244f0fSJohn Garry struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
25023f2e252eSJohn Garry struct sas_ata_task *ata_task = &task->ata_task;
2503bbfe82cdSJohn Garry struct sas_tmf_task *tmf = slot->tmf;
25046f2ff1a1SJohn Garry u8 *buf_cmd;
2505a2b3820bSXiang Chen int has_data = 0, hdr_tag = 0;
2506735bcc77SJohn Garry u32 dw0, dw1 = 0, dw2 = 0;
25076f2ff1a1SJohn Garry
25086f2ff1a1SJohn Garry /* create header */
25096f2ff1a1SJohn Garry /* dw0 */
2510735bcc77SJohn Garry dw0 = port->id << CMD_HDR_PORT_OFF;
2511924a3541SJohn Garry if (parent_dev && dev_is_expander(parent_dev->dev_type))
2512735bcc77SJohn Garry dw0 |= 3 << CMD_HDR_CMD_OFF;
25136f2ff1a1SJohn Garry else
2514735bcc77SJohn Garry dw0 |= 4 << CMD_HDR_CMD_OFF;
25156f2ff1a1SJohn Garry
25163f2e252eSJohn Garry if (tmf && ata_task->force_phy) {
2517735bcc77SJohn Garry dw0 |= CMD_HDR_FORCE_PHY_MSK;
25183f2e252eSJohn Garry dw0 |= (1 << ata_task->force_phy_id) << CMD_HDR_PHY_ID_OFF;
2519b09fcd09SXiaofei Tan }
2520b09fcd09SXiaofei Tan
2521735bcc77SJohn Garry hdr->dw0 = cpu_to_le32(dw0);
2522735bcc77SJohn Garry
25236f2ff1a1SJohn Garry /* dw1 */
25246f2ff1a1SJohn Garry switch (task->data_dir) {
25256f2ff1a1SJohn Garry case DMA_TO_DEVICE:
25266f2ff1a1SJohn Garry has_data = 1;
25276f2ff1a1SJohn Garry dw1 |= DIR_TO_DEVICE << CMD_HDR_DIR_OFF;
25286f2ff1a1SJohn Garry break;
25296f2ff1a1SJohn Garry case DMA_FROM_DEVICE:
25306f2ff1a1SJohn Garry has_data = 1;
25316f2ff1a1SJohn Garry dw1 |= DIR_TO_INI << CMD_HDR_DIR_OFF;
25326f2ff1a1SJohn Garry break;
25336f2ff1a1SJohn Garry default:
25346f2ff1a1SJohn Garry dw1 &= ~CMD_HDR_DIR_MSK;
25356f2ff1a1SJohn Garry }
25366f2ff1a1SJohn Garry
25377c594f04SXiang Chen if ((task->ata_task.fis.command == ATA_CMD_DEV_RESET) &&
25387c594f04SXiang Chen (task->ata_task.fis.control & ATA_SRST))
25396f2ff1a1SJohn Garry dw1 |= 1 << CMD_HDR_RESET_OFF;
25406f2ff1a1SJohn Garry
25416c7bb8a1SXiang Chen dw1 |= (hisi_sas_get_ata_protocol(
2542468f4b8dSchenxiang &task->ata_task.fis, task->data_dir))
25436f2ff1a1SJohn Garry << CMD_HDR_FRAME_TYPE_OFF;
25446f2ff1a1SJohn Garry dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
25456f2ff1a1SJohn Garry hdr->dw1 = cpu_to_le32(dw1);
25466f2ff1a1SJohn Garry
25476f2ff1a1SJohn Garry /* dw2 */
2548435a05cfSXiang Chen if (task->ata_task.use_ncq) {
2549435a05cfSXiang Chen struct ata_queued_cmd *qc = task->uldd_task;
2550435a05cfSXiang Chen
2551435a05cfSXiang Chen hdr_tag = qc->tag;
25526f2ff1a1SJohn Garry task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
25536f2ff1a1SJohn Garry dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
25546f2ff1a1SJohn Garry }
25556f2ff1a1SJohn Garry
25566f2ff1a1SJohn Garry dw2 |= (HISI_SAS_MAX_STP_RESP_SZ / 4) << CMD_HDR_CFL_OFF |
25576f2ff1a1SJohn Garry 2 << CMD_HDR_SG_MOD_OFF;
25586f2ff1a1SJohn Garry hdr->dw2 = cpu_to_le32(dw2);
25596f2ff1a1SJohn Garry
25606f2ff1a1SJohn Garry /* dw3 */
25616f2ff1a1SJohn Garry hdr->transfer_tags = cpu_to_le32(slot->idx);
25626f2ff1a1SJohn Garry
2563a2b3820bSXiang Chen if (has_data)
2564a2b3820bSXiang Chen prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
25656f2ff1a1SJohn Garry slot->n_elem);
25666f2ff1a1SJohn Garry
25676f2ff1a1SJohn Garry hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
2568f557e32cSXiaofei Tan hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
2569f557e32cSXiaofei Tan hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
25706f2ff1a1SJohn Garry
2571f557e32cSXiaofei Tan buf_cmd = hisi_sas_cmd_hdr_addr_mem(slot);
25726f2ff1a1SJohn Garry
25736f2ff1a1SJohn Garry if (likely(!task->ata_task.device_control_reg_update))
25746f2ff1a1SJohn Garry task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
25756f2ff1a1SJohn Garry /* fill in command FIS */
25766f2ff1a1SJohn Garry memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
25776f2ff1a1SJohn Garry }
25786f2ff1a1SJohn Garry
hisi_sas_internal_abort_quirk_timeout(struct timer_list * t)257977570eedSKees Cook static void hisi_sas_internal_abort_quirk_timeout(struct timer_list *t)
25800844a3ffSJohn Garry {
258177570eedSKees Cook struct hisi_sas_slot *slot = from_timer(slot, t, internal_abort_timer);
25820844a3ffSJohn Garry struct hisi_sas_port *port = slot->port;
25830844a3ffSJohn Garry struct asd_sas_port *asd_sas_port;
25840844a3ffSJohn Garry struct asd_sas_phy *sas_phy;
25850844a3ffSJohn Garry
25860844a3ffSJohn Garry if (!port)
25870844a3ffSJohn Garry return;
25880844a3ffSJohn Garry
25890844a3ffSJohn Garry asd_sas_port = &port->sas_port;
25900844a3ffSJohn Garry
25910844a3ffSJohn Garry /* Kick the hardware - send break command */
25920844a3ffSJohn Garry list_for_each_entry(sas_phy, &asd_sas_port->phy_list, port_phy_el) {
25930844a3ffSJohn Garry struct hisi_sas_phy *phy = sas_phy->lldd_phy;
25940844a3ffSJohn Garry struct hisi_hba *hisi_hba = phy->hisi_hba;
25950844a3ffSJohn Garry int phy_no = sas_phy->id;
25960844a3ffSJohn Garry u32 link_dfx2;
25970844a3ffSJohn Garry
25980844a3ffSJohn Garry link_dfx2 = hisi_sas_phy_read32(hisi_hba, phy_no, LINK_DFX2);
25990844a3ffSJohn Garry if ((link_dfx2 == LINK_DFX2_RCVR_HOLD_STS_MSK) ||
26000844a3ffSJohn Garry (link_dfx2 & LINK_DFX2_SEND_HOLD_STS_MSK)) {
26010844a3ffSJohn Garry u32 txid_auto;
26020844a3ffSJohn Garry
26030844a3ffSJohn Garry txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no,
26040844a3ffSJohn Garry TXID_AUTO);
26050844a3ffSJohn Garry txid_auto |= TXID_AUTO_CTB_MSK;
26060844a3ffSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
26070844a3ffSJohn Garry txid_auto);
26080844a3ffSJohn Garry return;
26090844a3ffSJohn Garry }
26100844a3ffSJohn Garry }
26110844a3ffSJohn Garry }
26120844a3ffSJohn Garry
prep_abort_v2_hw(struct hisi_hba * hisi_hba,struct hisi_sas_slot * slot)2613a2b3820bSXiang Chen static void prep_abort_v2_hw(struct hisi_hba *hisi_hba,
2614095478a6SJohn Garry struct hisi_sas_slot *slot)
2615a3e665d9SJohn Garry {
2616a3e665d9SJohn Garry struct sas_task *task = slot->task;
2617095478a6SJohn Garry struct sas_internal_abort_task *abort = &task->abort_task;
2618a3e665d9SJohn Garry struct domain_device *dev = task->dev;
2619a3e665d9SJohn Garry struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
2620a3e665d9SJohn Garry struct hisi_sas_port *port = slot->port;
26210844a3ffSJohn Garry struct timer_list *timer = &slot->internal_abort_timer;
2622095478a6SJohn Garry struct hisi_sas_device *sas_dev = dev->lldd_dev;
26230844a3ffSJohn Garry
26240844a3ffSJohn Garry /* setup the quirk timer */
262577570eedSKees Cook timer_setup(timer, hisi_sas_internal_abort_quirk_timeout, 0);
26260844a3ffSJohn Garry /* Set the timeout to 10ms less than internal abort timeout */
26270844a3ffSJohn Garry mod_timer(timer, jiffies + msecs_to_jiffies(100));
2628a3e665d9SJohn Garry
2629a3e665d9SJohn Garry /* dw0 */
2630a3e665d9SJohn Garry hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
2631a3e665d9SJohn Garry (port->id << CMD_HDR_PORT_OFF) |
2632edafeef4SXiang Chen (dev_is_sata(dev) <<
2633a3e665d9SJohn Garry CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
2634095478a6SJohn Garry (abort->type << CMD_HDR_ABORT_FLAG_OFF));
2635a3e665d9SJohn Garry
2636a3e665d9SJohn Garry /* dw1 */
2637095478a6SJohn Garry hdr->dw1 = cpu_to_le32(sas_dev->device_id << CMD_HDR_DEV_ID_OFF);
2638a3e665d9SJohn Garry
2639a3e665d9SJohn Garry /* dw7 */
2640095478a6SJohn Garry hdr->dw7 = cpu_to_le32(abort->tag << CMD_HDR_ABORT_IPTT_OFF);
2641a3e665d9SJohn Garry hdr->transfer_tags = cpu_to_le32(slot->idx);
2642a3e665d9SJohn Garry }
2643a3e665d9SJohn Garry
phy_up_v2_hw(int phy_no,struct hisi_hba * hisi_hba)26447911e66fSJohn Garry static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
26457911e66fSJohn Garry {
2646981843c6SXiaofei Tan int i, res = IRQ_HANDLED;
2647eba8c20cSXiaofei Tan u32 port_id, link_rate;
26487911e66fSJohn Garry struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
26497911e66fSJohn Garry struct asd_sas_phy *sas_phy = &phy->sas_phy;
265011b75249SJohn Garry struct device *dev = hisi_hba->dev;
26517911e66fSJohn Garry u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
26527911e66fSJohn Garry struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
26537911e66fSJohn Garry
26547911e66fSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
26557911e66fSJohn Garry
26564935933eSXiaofei Tan if (is_sata_phy_v2_hw(hisi_hba, phy_no))
26577911e66fSJohn Garry goto end;
26587911e66fSJohn Garry
2659b6c9b15eSXiaofei Tan del_timer(&phy->timer);
2660b6c9b15eSXiaofei Tan
26617911e66fSJohn Garry if (phy_no == 8) {
26627911e66fSJohn Garry u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
26637911e66fSJohn Garry
26647911e66fSJohn Garry port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
26657911e66fSJohn Garry PORT_STATE_PHY8_PORT_NUM_OFF;
26667911e66fSJohn Garry link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
26677911e66fSJohn Garry PORT_STATE_PHY8_CONN_RATE_OFF;
26687911e66fSJohn Garry } else {
26697911e66fSJohn Garry port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
26707911e66fSJohn Garry port_id = (port_id >> (4 * phy_no)) & 0xf;
26717911e66fSJohn Garry link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
26727911e66fSJohn Garry link_rate = (link_rate >> (phy_no * 4)) & 0xf;
26737911e66fSJohn Garry }
26747911e66fSJohn Garry
26757911e66fSJohn Garry if (port_id == 0xf) {
26767911e66fSJohn Garry dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
26777911e66fSJohn Garry res = IRQ_NONE;
26787911e66fSJohn Garry goto end;
26797911e66fSJohn Garry }
26807911e66fSJohn Garry
26817911e66fSJohn Garry for (i = 0; i < 6; i++) {
26827911e66fSJohn Garry u32 idaf = hisi_sas_phy_read32(hisi_hba, phy_no,
26837911e66fSJohn Garry RX_IDAF_DWORD0 + (i * 4));
26847911e66fSJohn Garry frame_rcvd[i] = __swab32(idaf);
26857911e66fSJohn Garry }
26867911e66fSJohn Garry
26877911e66fSJohn Garry sas_phy->linkrate = link_rate;
26887911e66fSJohn Garry sas_phy->oob_mode = SAS_OOB_MODE;
26897911e66fSJohn Garry memcpy(sas_phy->attached_sas_addr, &id->sas_addr, SAS_ADDR_SIZE);
26907911e66fSJohn Garry dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
26917911e66fSJohn Garry phy->port_id = port_id;
26927911e66fSJohn Garry phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
26937911e66fSJohn Garry phy->phy_type |= PORT_TYPE_SAS;
26947911e66fSJohn Garry phy->phy_attached = 1;
26957911e66fSJohn Garry phy->identify.device_type = id->dev_type;
26967911e66fSJohn Garry phy->frame_rcvd_size = sizeof(struct sas_identify_frame);
26977911e66fSJohn Garry if (phy->identify.device_type == SAS_END_DEVICE)
26987911e66fSJohn Garry phy->identify.target_port_protocols =
26997911e66fSJohn Garry SAS_PROTOCOL_SSP;
2700f2f89c32SXiang Chen else if (phy->identify.device_type != SAS_PHY_UNUSED) {
27017911e66fSJohn Garry phy->identify.target_port_protocols =
27027911e66fSJohn Garry SAS_PROTOCOL_SMP;
2703f2f89c32SXiang Chen if (!timer_pending(&hisi_hba->timer))
2704f2f89c32SXiang Chen set_link_timer_quirk(hisi_hba);
2705f2f89c32SXiang Chen }
2706e537b62bSXiaofei Tan hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
27077911e66fSJohn Garry end:
2708046ab7d0SXiang Chen if (phy->reset_completion)
2709046ab7d0SXiang Chen complete(phy->reset_completion);
27107911e66fSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
27117911e66fSJohn Garry CHL_INT0_SL_PHY_ENABLE_MSK);
27127911e66fSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
27137911e66fSJohn Garry
27147911e66fSJohn Garry return res;
27157911e66fSJohn Garry }
27167911e66fSJohn Garry
check_any_wideports_v2_hw(struct hisi_hba * hisi_hba)2717f2f89c32SXiang Chen static bool check_any_wideports_v2_hw(struct hisi_hba *hisi_hba)
2718f2f89c32SXiang Chen {
2719f2f89c32SXiang Chen u32 port_state;
2720f2f89c32SXiang Chen
2721f2f89c32SXiang Chen port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
2722f2f89c32SXiang Chen if (port_state & 0x1ff)
2723f2f89c32SXiang Chen return true;
2724f2f89c32SXiang Chen
2725f2f89c32SXiang Chen return false;
2726f2f89c32SXiang Chen }
2727f2f89c32SXiang Chen
phy_down_v2_hw(int phy_no,struct hisi_hba * hisi_hba)27285473c060SJohn Garry static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
27295473c060SJohn Garry {
27309c81e2cfSJohn Garry u32 phy_state, sl_ctrl, txid_auto;
2731f2f89c32SXiang Chen struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
2732f2f89c32SXiang Chen struct hisi_sas_port *port = phy->port;
2733f1c88211SXiang Chen struct device *dev = hisi_hba->dev;
27345473c060SJohn Garry
2735b6c9b15eSXiaofei Tan del_timer(&phy->timer);
27365473c060SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
27375473c060SJohn Garry
27385473c060SJohn Garry phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
2739f1c88211SXiang Chen dev_info(dev, "phydown: phy%d phy_state=0x%x\n", phy_no, phy_state);
274026c7efc3SAhmed S. Darwish hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0,
274126c7efc3SAhmed S. Darwish GFP_ATOMIC);
27425473c060SJohn Garry
27439c81e2cfSJohn Garry sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
27449c81e2cfSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL,
27459c81e2cfSJohn Garry sl_ctrl & ~SL_CONTROL_CTA_MSK);
2746f2f89c32SXiang Chen if (port && !get_wideport_bitmap_v2_hw(hisi_hba, port->id))
2747f2f89c32SXiang Chen if (!check_any_wideports_v2_hw(hisi_hba) &&
2748f2f89c32SXiang Chen timer_pending(&hisi_hba->timer))
2749f2f89c32SXiang Chen del_timer(&hisi_hba->timer);
27509c81e2cfSJohn Garry
27519c81e2cfSJohn Garry txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
27529c81e2cfSJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
27539c81e2cfSJohn Garry txid_auto | TXID_AUTO_CT3_MSK);
27549c81e2cfSJohn Garry
27555473c060SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
27565473c060SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
27575473c060SJohn Garry
2758981843c6SXiaofei Tan return IRQ_HANDLED;
27595473c060SJohn Garry }
27605473c060SJohn Garry
int_phy_updown_v2_hw(int irq_no,void * p)27617911e66fSJohn Garry static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
27627911e66fSJohn Garry {
27637911e66fSJohn Garry struct hisi_hba *hisi_hba = p;
27647911e66fSJohn Garry u32 irq_msk;
27657911e66fSJohn Garry int phy_no = 0;
2766c16db736SXiang Chen irqreturn_t res = IRQ_NONE;
27677911e66fSJohn Garry
27687911e66fSJohn Garry irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO)
27697911e66fSJohn Garry >> HGC_INVLD_DQE_INFO_FB_CH0_OFF) & 0x1ff;
27707911e66fSJohn Garry while (irq_msk) {
27717911e66fSJohn Garry if (irq_msk & 1) {
2772981843c6SXiaofei Tan u32 reg_value = hisi_sas_phy_read32(hisi_hba, phy_no,
27737911e66fSJohn Garry CHL_INT0);
27747911e66fSJohn Garry
2775981843c6SXiaofei Tan switch (reg_value & (CHL_INT0_NOT_RDY_MSK |
2776981843c6SXiaofei Tan CHL_INT0_SL_PHY_ENABLE_MSK)) {
2777981843c6SXiaofei Tan
2778981843c6SXiaofei Tan case CHL_INT0_SL_PHY_ENABLE_MSK:
27797911e66fSJohn Garry /* phy up */
2780981843c6SXiaofei Tan if (phy_up_v2_hw(phy_no, hisi_hba) ==
2781c16db736SXiang Chen IRQ_HANDLED)
2782c16db736SXiang Chen res = IRQ_HANDLED;
2783981843c6SXiaofei Tan break;
2784981843c6SXiaofei Tan
2785981843c6SXiaofei Tan case CHL_INT0_NOT_RDY_MSK:
2786981843c6SXiaofei Tan /* phy down */
2787981843c6SXiaofei Tan if (phy_down_v2_hw(phy_no, hisi_hba) ==
2788c16db736SXiang Chen IRQ_HANDLED)
2789c16db736SXiang Chen res = IRQ_HANDLED;
2790981843c6SXiaofei Tan break;
2791981843c6SXiaofei Tan
2792981843c6SXiaofei Tan case (CHL_INT0_NOT_RDY_MSK |
2793981843c6SXiaofei Tan CHL_INT0_SL_PHY_ENABLE_MSK):
2794981843c6SXiaofei Tan reg_value = hisi_sas_read32(hisi_hba,
2795981843c6SXiaofei Tan PHY_STATE);
2796981843c6SXiaofei Tan if (reg_value & BIT(phy_no)) {
2797981843c6SXiaofei Tan /* phy up */
2798981843c6SXiaofei Tan if (phy_up_v2_hw(phy_no, hisi_hba) ==
2799c16db736SXiang Chen IRQ_HANDLED)
2800c16db736SXiang Chen res = IRQ_HANDLED;
2801981843c6SXiaofei Tan } else {
2802981843c6SXiaofei Tan /* phy down */
2803981843c6SXiaofei Tan if (phy_down_v2_hw(phy_no, hisi_hba) ==
2804c16db736SXiang Chen IRQ_HANDLED)
2805c16db736SXiang Chen res = IRQ_HANDLED;
2806981843c6SXiaofei Tan }
2807981843c6SXiaofei Tan break;
2808981843c6SXiaofei Tan
2809981843c6SXiaofei Tan default:
2810981843c6SXiaofei Tan break;
28117911e66fSJohn Garry }
28127911e66fSJohn Garry
28137911e66fSJohn Garry }
28147911e66fSJohn Garry irq_msk >>= 1;
28157911e66fSJohn Garry phy_no++;
28167911e66fSJohn Garry }
28177911e66fSJohn Garry
2818c16db736SXiang Chen return res;
28197911e66fSJohn Garry }
28207911e66fSJohn Garry
phy_bcast_v2_hw(int phy_no,struct hisi_hba * hisi_hba)2821d3bf3d84SJohn Garry static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
2822d3bf3d84SJohn Garry {
2823d3bf3d84SJohn Garry struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
282485080a25SXiang Chen u32 bcast_status;
2825d3bf3d84SJohn Garry
2826d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
282785080a25SXiang Chen bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
2828e9b6badaSJohn Garry if (bcast_status & RX_BCAST_CHG_MSK)
2829e9b6badaSJohn Garry hisi_sas_phy_bcast(phy);
2830d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
2831d3bf3d84SJohn Garry CHL_INT0_SL_RX_BCST_ACK_MSK);
2832d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
2833d3bf3d84SJohn Garry }
2834d3bf3d84SJohn Garry
283572f7fc30SXiaofei Tan static const struct hisi_sas_hw_error port_ecc_axi_error[] = {
283672f7fc30SXiaofei Tan {
283772f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_TX_ECC_ERR_OFF),
283872f7fc30SXiaofei Tan .msg = "dmac_tx_ecc_bad_err",
283972f7fc30SXiaofei Tan },
284072f7fc30SXiaofei Tan {
284172f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_RX_ECC_ERR_OFF),
284272f7fc30SXiaofei Tan .msg = "dmac_rx_ecc_bad_err",
284372f7fc30SXiaofei Tan },
284472f7fc30SXiaofei Tan {
284572f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_WR_ERR_OFF),
284672f7fc30SXiaofei Tan .msg = "dma_tx_axi_wr_err",
284772f7fc30SXiaofei Tan },
284872f7fc30SXiaofei Tan {
284972f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_TX_AXI_RD_ERR_OFF),
285072f7fc30SXiaofei Tan .msg = "dma_tx_axi_rd_err",
285172f7fc30SXiaofei Tan },
285272f7fc30SXiaofei Tan {
285372f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_WR_ERR_OFF),
285472f7fc30SXiaofei Tan .msg = "dma_rx_axi_wr_err",
285572f7fc30SXiaofei Tan },
285672f7fc30SXiaofei Tan {
285772f7fc30SXiaofei Tan .irq_msk = BIT(CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF),
285872f7fc30SXiaofei Tan .msg = "dma_rx_axi_rd_err",
285972f7fc30SXiaofei Tan },
286072f7fc30SXiaofei Tan };
286172f7fc30SXiaofei Tan
int_chnl_int_v2_hw(int irq_no,void * p)2862d3bf3d84SJohn Garry static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
2863d3bf3d84SJohn Garry {
2864d3bf3d84SJohn Garry struct hisi_hba *hisi_hba = p;
286511b75249SJohn Garry struct device *dev = hisi_hba->dev;
2866d3bf3d84SJohn Garry u32 ent_msk, ent_tmp, irq_msk;
2867d3bf3d84SJohn Garry int phy_no = 0;
2868d3bf3d84SJohn Garry
2869d3bf3d84SJohn Garry ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
2870d3bf3d84SJohn Garry ent_tmp = ent_msk;
2871d3bf3d84SJohn Garry ent_msk |= ENT_INT_SRC_MSK3_ENT95_MSK_MSK;
2872d3bf3d84SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_msk);
2873d3bf3d84SJohn Garry
2874d3bf3d84SJohn Garry irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO) >>
2875d3bf3d84SJohn Garry HGC_INVLD_DQE_INFO_FB_CH3_OFF) & 0x1ff;
2876d3bf3d84SJohn Garry
2877d3bf3d84SJohn Garry while (irq_msk) {
2878d3bf3d84SJohn Garry u32 irq_value0 = hisi_sas_phy_read32(hisi_hba, phy_no,
2879d3bf3d84SJohn Garry CHL_INT0);
2880d3bf3d84SJohn Garry u32 irq_value1 = hisi_sas_phy_read32(hisi_hba, phy_no,
2881d3bf3d84SJohn Garry CHL_INT1);
2882d3bf3d84SJohn Garry u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
2883d3bf3d84SJohn Garry CHL_INT2);
2884d3bf3d84SJohn Garry
2885f64715d2SXiaofei Tan if ((irq_msk & (1 << phy_no)) && irq_value1) {
288672f7fc30SXiaofei Tan int i;
288772f7fc30SXiaofei Tan
288872f7fc30SXiaofei Tan for (i = 0; i < ARRAY_SIZE(port_ecc_axi_error); i++) {
288972f7fc30SXiaofei Tan const struct hisi_sas_hw_error *error =
289072f7fc30SXiaofei Tan &port_ecc_axi_error[i];
289172f7fc30SXiaofei Tan
289272f7fc30SXiaofei Tan if (!(irq_value1 & error->irq_msk))
289372f7fc30SXiaofei Tan continue;
289472f7fc30SXiaofei Tan
289572f7fc30SXiaofei Tan dev_warn(dev, "%s error (phy%d 0x%x) found!\n",
289672f7fc30SXiaofei Tan error->msg, phy_no, irq_value1);
289772f7fc30SXiaofei Tan queue_work(hisi_hba->wq, &hisi_hba->rst_work);
289872f7fc30SXiaofei Tan }
2899d3bf3d84SJohn Garry
2900d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no,
2901d3bf3d84SJohn Garry CHL_INT1, irq_value1);
2902d3bf3d84SJohn Garry }
2903d3bf3d84SJohn Garry
2904057c3d1fSXiaofei Tan if ((irq_msk & (1 << phy_no)) && irq_value2) {
2905057c3d1fSXiaofei Tan struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
2906057c3d1fSXiaofei Tan
2907057c3d1fSXiaofei Tan if (irq_value2 & BIT(CHL_INT2_SL_IDAF_TOUT_CONF_OFF)) {
2908057c3d1fSXiaofei Tan dev_warn(dev, "phy%d identify timeout\n",
2909057c3d1fSXiaofei Tan phy_no);
2910057c3d1fSXiaofei Tan hisi_sas_notify_phy_event(phy,
2911057c3d1fSXiaofei Tan HISI_PHYE_LINK_RESET);
2912057c3d1fSXiaofei Tan }
2913057c3d1fSXiaofei Tan
2914d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no,
2915d3bf3d84SJohn Garry CHL_INT2, irq_value2);
2916057c3d1fSXiaofei Tan }
2917d3bf3d84SJohn Garry
2918f64715d2SXiaofei Tan if ((irq_msk & (1 << phy_no)) && irq_value0) {
2919d3bf3d84SJohn Garry if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK)
2920d3bf3d84SJohn Garry phy_bcast_v2_hw(phy_no, hisi_hba);
2921d3bf3d84SJohn Garry
2922b6c9b15eSXiaofei Tan if (irq_value0 & CHL_INT0_PHY_RDY_MSK)
2923b6c9b15eSXiaofei Tan hisi_sas_phy_oob_ready(hisi_hba, phy_no);
2924b6c9b15eSXiaofei Tan
2925d3bf3d84SJohn Garry hisi_sas_phy_write32(hisi_hba, phy_no,
2926d3bf3d84SJohn Garry CHL_INT0, irq_value0
2927d3bf3d84SJohn Garry & (~CHL_INT0_HOTPLUG_TOUT_MSK)
2928d3bf3d84SJohn Garry & (~CHL_INT0_SL_PHY_ENABLE_MSK)
2929d3bf3d84SJohn Garry & (~CHL_INT0_NOT_RDY_MSK));
2930d3bf3d84SJohn Garry }
2931d3bf3d84SJohn Garry irq_msk &= ~(1 << phy_no);
2932d3bf3d84SJohn Garry phy_no++;
2933d3bf3d84SJohn Garry }
2934d3bf3d84SJohn Garry
2935d3bf3d84SJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_tmp);
2936d3bf3d84SJohn Garry
2937d3bf3d84SJohn Garry return IRQ_HANDLED;
2938d3bf3d84SJohn Garry }
2939d3bf3d84SJohn Garry
2940d3b688d3SXiang Chen static void
one_bit_ecc_error_process_v2_hw(struct hisi_hba * hisi_hba,u32 irq_value)2941d3b688d3SXiang Chen one_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba, u32 irq_value)
2942d3b688d3SXiang Chen {
294311b75249SJohn Garry struct device *dev = hisi_hba->dev;
29442b383351SJohn Garry const struct hisi_sas_hw_error *ecc_error;
29452b383351SJohn Garry u32 val;
29462b383351SJohn Garry int i;
2947d3b688d3SXiang Chen
29482b383351SJohn Garry for (i = 0; i < ARRAY_SIZE(one_bit_ecc_errors); i++) {
29492b383351SJohn Garry ecc_error = &one_bit_ecc_errors[i];
29502b383351SJohn Garry if (irq_value & ecc_error->irq_msk) {
29512b383351SJohn Garry val = hisi_sas_read32(hisi_hba, ecc_error->reg);
29522b383351SJohn Garry val &= ecc_error->msk;
29532b383351SJohn Garry val >>= ecc_error->shift;
2954794327abSXiaofei Tan dev_warn(dev, "%s found: mem addr is 0x%08X\n",
2955794327abSXiaofei Tan ecc_error->msg, val);
2956d3b688d3SXiang Chen }
2957d3b688d3SXiang Chen }
2958d3b688d3SXiang Chen }
2959d3b688d3SXiang Chen
multi_bit_ecc_error_process_v2_hw(struct hisi_hba * hisi_hba,u32 irq_value)2960d3b688d3SXiang Chen static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba,
2961d3b688d3SXiang Chen u32 irq_value)
2962d3b688d3SXiang Chen {
296311b75249SJohn Garry struct device *dev = hisi_hba->dev;
29642b383351SJohn Garry const struct hisi_sas_hw_error *ecc_error;
29652b383351SJohn Garry u32 val;
29662b383351SJohn Garry int i;
2967d3b688d3SXiang Chen
29682b383351SJohn Garry for (i = 0; i < ARRAY_SIZE(multi_bit_ecc_errors); i++) {
29692b383351SJohn Garry ecc_error = &multi_bit_ecc_errors[i];
29702b383351SJohn Garry if (irq_value & ecc_error->irq_msk) {
29712b383351SJohn Garry val = hisi_sas_read32(hisi_hba, ecc_error->reg);
29722b383351SJohn Garry val &= ecc_error->msk;
29732b383351SJohn Garry val >>= ecc_error->shift;
2974794327abSXiaofei Tan dev_err(dev, "%s (0x%x) found: mem addr is 0x%08X\n",
2975794327abSXiaofei Tan ecc_error->msg, irq_value, val);
2976e281f42fSXiang Chen queue_work(hisi_hba->wq, &hisi_hba->rst_work);
2977d3b688d3SXiang Chen }
2978d3b688d3SXiang Chen }
2979d3b688d3SXiang Chen
2980e281f42fSXiang Chen return;
2981d3b688d3SXiang Chen }
2982d3b688d3SXiang Chen
fatal_ecc_int_v2_hw(int irq_no,void * p)2983d3b688d3SXiang Chen static irqreturn_t fatal_ecc_int_v2_hw(int irq_no, void *p)
2984d3b688d3SXiang Chen {
2985d3b688d3SXiang Chen struct hisi_hba *hisi_hba = p;
2986d3b688d3SXiang Chen u32 irq_value, irq_msk;
2987d3b688d3SXiang Chen
2988d3b688d3SXiang Chen irq_msk = hisi_sas_read32(hisi_hba, SAS_ECC_INTR_MSK);
2989d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk | 0xffffffff);
2990d3b688d3SXiang Chen
2991d3b688d3SXiang Chen irq_value = hisi_sas_read32(hisi_hba, SAS_ECC_INTR);
2992d3b688d3SXiang Chen if (irq_value) {
2993d3b688d3SXiang Chen one_bit_ecc_error_process_v2_hw(hisi_hba, irq_value);
2994d3b688d3SXiang Chen multi_bit_ecc_error_process_v2_hw(hisi_hba, irq_value);
2995d3b688d3SXiang Chen }
2996d3b688d3SXiang Chen
2997d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, SAS_ECC_INTR, irq_value);
2998d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, irq_msk);
2999d3b688d3SXiang Chen
3000d3b688d3SXiang Chen return IRQ_HANDLED;
3001d3b688d3SXiang Chen }
3002d3b688d3SXiang Chen
3003729428caSShiju Jose static const struct hisi_sas_hw_error axi_error[] = {
3004729428caSShiju Jose { .msk = BIT(0), .msg = "IOST_AXI_W_ERR" },
3005729428caSShiju Jose { .msk = BIT(1), .msg = "IOST_AXI_R_ERR" },
3006729428caSShiju Jose { .msk = BIT(2), .msg = "ITCT_AXI_W_ERR" },
3007729428caSShiju Jose { .msk = BIT(3), .msg = "ITCT_AXI_R_ERR" },
3008729428caSShiju Jose { .msk = BIT(4), .msg = "SATA_AXI_W_ERR" },
3009729428caSShiju Jose { .msk = BIT(5), .msg = "SATA_AXI_R_ERR" },
3010729428caSShiju Jose { .msk = BIT(6), .msg = "DQE_AXI_R_ERR" },
3011729428caSShiju Jose { .msk = BIT(7), .msg = "CQE_AXI_W_ERR" },
301201d4e3a2SXiang Chen {}
3013d3b688d3SXiang Chen };
3014d3b688d3SXiang Chen
3015729428caSShiju Jose static const struct hisi_sas_hw_error fifo_error[] = {
3016729428caSShiju Jose { .msk = BIT(8), .msg = "CQE_WINFO_FIFO" },
3017729428caSShiju Jose { .msk = BIT(9), .msg = "CQE_MSG_FIFIO" },
3018729428caSShiju Jose { .msk = BIT(10), .msg = "GETDQE_FIFO" },
3019729428caSShiju Jose { .msk = BIT(11), .msg = "CMDP_FIFO" },
3020729428caSShiju Jose { .msk = BIT(12), .msg = "AWTCTRL_FIFO" },
302101d4e3a2SXiang Chen {}
3022729428caSShiju Jose };
3023729428caSShiju Jose
3024729428caSShiju Jose static const struct hisi_sas_hw_error fatal_axi_errors[] = {
3025729428caSShiju Jose {
3026729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_WP_DEPTH_OFF),
3027729428caSShiju Jose .msg = "write pointer and depth",
3028729428caSShiju Jose },
3029729428caSShiju Jose {
3030729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF),
3031729428caSShiju Jose .msg = "iptt no match slot",
3032729428caSShiju Jose },
3033729428caSShiju Jose {
3034729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_RP_DEPTH_OFF),
3035729428caSShiju Jose .msg = "read pointer and depth",
3036729428caSShiju Jose },
3037729428caSShiju Jose {
3038729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_AXI_OFF),
3039729428caSShiju Jose .reg = HGC_AXI_FIFO_ERR_INFO,
3040729428caSShiju Jose .sub = axi_error,
3041729428caSShiju Jose },
3042729428caSShiju Jose {
3043729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_FIFO_OFF),
3044729428caSShiju Jose .reg = HGC_AXI_FIFO_ERR_INFO,
3045729428caSShiju Jose .sub = fifo_error,
3046729428caSShiju Jose },
3047729428caSShiju Jose {
3048729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_LM_OFF),
3049729428caSShiju Jose .msg = "LM add/fetch list",
3050729428caSShiju Jose },
3051729428caSShiju Jose {
3052729428caSShiju Jose .irq_msk = BIT(ENT_INT_SRC3_ABT_OFF),
3053729428caSShiju Jose .msg = "SAS_HGC_ABT fetch LM list",
3054729428caSShiju Jose },
3055d3b688d3SXiang Chen };
3056d3b688d3SXiang Chen
fatal_axi_int_v2_hw(int irq_no,void * p)3057d3b688d3SXiang Chen static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
3058d3b688d3SXiang Chen {
3059d3b688d3SXiang Chen struct hisi_hba *hisi_hba = p;
3060d3b688d3SXiang Chen u32 irq_value, irq_msk, err_value;
306111b75249SJohn Garry struct device *dev = hisi_hba->dev;
3062729428caSShiju Jose const struct hisi_sas_hw_error *axi_error;
3063729428caSShiju Jose int i;
3064d3b688d3SXiang Chen
3065d3b688d3SXiang Chen irq_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
3066d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0xfffffffe);
3067d3b688d3SXiang Chen
3068d3b688d3SXiang Chen irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
3069d3b688d3SXiang Chen
3070729428caSShiju Jose for (i = 0; i < ARRAY_SIZE(fatal_axi_errors); i++) {
3071729428caSShiju Jose axi_error = &fatal_axi_errors[i];
3072729428caSShiju Jose if (!(irq_value & axi_error->irq_msk))
3073729428caSShiju Jose continue;
3074d3b688d3SXiang Chen
3075d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
3076729428caSShiju Jose 1 << axi_error->shift);
3077729428caSShiju Jose if (axi_error->sub) {
3078729428caSShiju Jose const struct hisi_sas_hw_error *sub = axi_error->sub;
3079d3b688d3SXiang Chen
3080729428caSShiju Jose err_value = hisi_sas_read32(hisi_hba, axi_error->reg);
3081729428caSShiju Jose for (; sub->msk || sub->msg; sub++) {
3082729428caSShiju Jose if (!(err_value & sub->msk))
3083729428caSShiju Jose continue;
3084f1c88211SXiang Chen dev_err(dev, "%s (0x%x) found!\n",
3085729428caSShiju Jose sub->msg, irq_value);
3086e281f42fSXiang Chen queue_work(hisi_hba->wq, &hisi_hba->rst_work);
3087e281f42fSXiang Chen }
3088729428caSShiju Jose } else {
3089f1c88211SXiang Chen dev_err(dev, "%s (0x%x) found!\n",
3090729428caSShiju Jose axi_error->msg, irq_value);
3091e281f42fSXiang Chen queue_work(hisi_hba->wq, &hisi_hba->rst_work);
3092e281f42fSXiang Chen }
3093d3b688d3SXiang Chen }
3094d3b688d3SXiang Chen
3095640acc9aSXiang Chen if (irq_value & BIT(ENT_INT_SRC3_ITC_INT_OFF)) {
3096640acc9aSXiang Chen u32 reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
3097640acc9aSXiang Chen u32 dev_id = reg_val & ITCT_DEV_MSK;
3098729428caSShiju Jose struct hisi_sas_device *sas_dev = &hisi_hba->devices[dev_id];
3099640acc9aSXiang Chen
3100640acc9aSXiang Chen hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
3101640acc9aSXiang Chen dev_dbg(dev, "clear ITCT ok\n");
3102640acc9aSXiang Chen complete(sas_dev->completion);
3103640acc9aSXiang Chen }
3104d3b688d3SXiang Chen
3105640acc9aSXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC3, irq_value);
3106d3b688d3SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk);
3107d3b688d3SXiang Chen
3108d3b688d3SXiang Chen return IRQ_HANDLED;
3109d3b688d3SXiang Chen }
3110d3b688d3SXiang Chen
cq_thread_v2_hw(int irq_no,void * p)311181f338e9SXiang Chen static irqreturn_t cq_thread_v2_hw(int irq_no, void *p)
311231a9cfa6SJohn Garry {
311381f338e9SXiang Chen struct hisi_sas_cq *cq = p;
311431a9cfa6SJohn Garry struct hisi_hba *hisi_hba = cq->hisi_hba;
311531a9cfa6SJohn Garry struct hisi_sas_slot *slot;
311631a9cfa6SJohn Garry struct hisi_sas_itct *itct;
311731a9cfa6SJohn Garry struct hisi_sas_complete_v2_hdr *complete_queue;
3118d177c408SJohn Garry u32 rd_point = cq->rd_point, wr_point, dev_id;
311931a9cfa6SJohn Garry int queue = cq->id;
312031a9cfa6SJohn Garry
3121c7b9d369SXiaofei Tan if (unlikely(hisi_hba->reject_stp_links_msk))
3122c7b9d369SXiaofei Tan phys_try_accept_stp_links_v2_hw(hisi_hba);
3123c7b9d369SXiaofei Tan
312431a9cfa6SJohn Garry complete_queue = hisi_hba->complete_hdr[queue];
312531a9cfa6SJohn Garry
312631a9cfa6SJohn Garry wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
312731a9cfa6SJohn Garry (0x14 * queue));
312831a9cfa6SJohn Garry
312931a9cfa6SJohn Garry while (rd_point != wr_point) {
313031a9cfa6SJohn Garry struct hisi_sas_complete_v2_hdr *complete_hdr;
313131a9cfa6SJohn Garry int iptt;
313231a9cfa6SJohn Garry
313331a9cfa6SJohn Garry complete_hdr = &complete_queue[rd_point];
313431a9cfa6SJohn Garry
313531a9cfa6SJohn Garry /* Check for NCQ completion */
313631a9cfa6SJohn Garry if (complete_hdr->act) {
3137735bcc77SJohn Garry u32 act_tmp = le32_to_cpu(complete_hdr->act);
313831a9cfa6SJohn Garry int ncq_tag_count = ffs(act_tmp);
3139735bcc77SJohn Garry u32 dw1 = le32_to_cpu(complete_hdr->dw1);
314031a9cfa6SJohn Garry
3141735bcc77SJohn Garry dev_id = (dw1 & CMPLT_HDR_DEV_ID_MSK) >>
314231a9cfa6SJohn Garry CMPLT_HDR_DEV_ID_OFF;
314331a9cfa6SJohn Garry itct = &hisi_hba->itct[dev_id];
314431a9cfa6SJohn Garry
314531a9cfa6SJohn Garry /* The NCQ tags are held in the itct header */
314631a9cfa6SJohn Garry while (ncq_tag_count) {
3147735bcc77SJohn Garry __le64 *_ncq_tag = &itct->qw4_15[0], __ncq_tag;
3148735bcc77SJohn Garry u64 ncq_tag;
314931a9cfa6SJohn Garry
3150735bcc77SJohn Garry ncq_tag_count--;
3151735bcc77SJohn Garry __ncq_tag = _ncq_tag[ncq_tag_count / 5];
3152735bcc77SJohn Garry ncq_tag = le64_to_cpu(__ncq_tag);
3153735bcc77SJohn Garry iptt = (ncq_tag >> (ncq_tag_count % 5) * 12) &
3154735bcc77SJohn Garry 0xfff;
315531a9cfa6SJohn Garry
315631a9cfa6SJohn Garry slot = &hisi_hba->slot_info[iptt];
315731a9cfa6SJohn Garry slot->cmplt_queue_slot = rd_point;
315831a9cfa6SJohn Garry slot->cmplt_queue = queue;
3159405314dfSJohn Garry slot_complete_v2_hw(hisi_hba, slot);
316031a9cfa6SJohn Garry
316131a9cfa6SJohn Garry act_tmp &= ~(1 << ncq_tag_count);
316231a9cfa6SJohn Garry ncq_tag_count = ffs(act_tmp);
316331a9cfa6SJohn Garry }
316431a9cfa6SJohn Garry } else {
3165735bcc77SJohn Garry u32 dw1 = le32_to_cpu(complete_hdr->dw1);
3166735bcc77SJohn Garry
3167735bcc77SJohn Garry iptt = dw1 & CMPLT_HDR_IPTT_MSK;
316831a9cfa6SJohn Garry slot = &hisi_hba->slot_info[iptt];
316931a9cfa6SJohn Garry slot->cmplt_queue_slot = rd_point;
317031a9cfa6SJohn Garry slot->cmplt_queue = queue;
3171405314dfSJohn Garry slot_complete_v2_hw(hisi_hba, slot);
317231a9cfa6SJohn Garry }
317331a9cfa6SJohn Garry
317431a9cfa6SJohn Garry if (++rd_point >= HISI_SAS_QUEUE_SLOTS)
317531a9cfa6SJohn Garry rd_point = 0;
317631a9cfa6SJohn Garry }
317731a9cfa6SJohn Garry
317831a9cfa6SJohn Garry /* update rd_point */
3179e6c346f3SJohn Garry cq->rd_point = rd_point;
318031a9cfa6SJohn Garry hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
318181f338e9SXiang Chen
318281f338e9SXiang Chen return IRQ_HANDLED;
3183d177c408SJohn Garry }
3184d177c408SJohn Garry
cq_interrupt_v2_hw(int irq_no,void * p)3185d177c408SJohn Garry static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
3186d177c408SJohn Garry {
3187d177c408SJohn Garry struct hisi_sas_cq *cq = p;
3188d177c408SJohn Garry struct hisi_hba *hisi_hba = cq->hisi_hba;
3189d177c408SJohn Garry int queue = cq->id;
3190d177c408SJohn Garry
3191d177c408SJohn Garry hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
3192d177c408SJohn Garry
319381f338e9SXiang Chen return IRQ_WAKE_THREAD;
319431a9cfa6SJohn Garry }
319531a9cfa6SJohn Garry
sata_int_v2_hw(int irq_no,void * p)3196d43f9cdbSJohn Garry static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
3197d43f9cdbSJohn Garry {
3198d43f9cdbSJohn Garry struct hisi_sas_phy *phy = p;
3199d43f9cdbSJohn Garry struct hisi_hba *hisi_hba = phy->hisi_hba;
3200d43f9cdbSJohn Garry struct asd_sas_phy *sas_phy = &phy->sas_phy;
320111b75249SJohn Garry struct device *dev = hisi_hba->dev;
3202d43f9cdbSJohn Garry struct hisi_sas_initial_fis *initial_fis;
3203d43f9cdbSJohn Garry struct dev_to_host_fis *fis;
3204d43f9cdbSJohn Garry u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate;
3205d43f9cdbSJohn Garry irqreturn_t res = IRQ_HANDLED;
3206d43f9cdbSJohn Garry u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
320711826e5dSJohn Garry int phy_no, offset;
3208d43f9cdbSJohn Garry
3209b6c9b15eSXiaofei Tan del_timer(&phy->timer);
3210b6c9b15eSXiaofei Tan
3211d43f9cdbSJohn Garry phy_no = sas_phy->id;
3212d43f9cdbSJohn Garry initial_fis = &hisi_hba->initial_fis[phy_no];
3213d43f9cdbSJohn Garry fis = &initial_fis->fis;
3214d43f9cdbSJohn Garry
321511826e5dSJohn Garry offset = 4 * (phy_no / 4);
321611826e5dSJohn Garry ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1 + offset);
321711826e5dSJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset,
321811826e5dSJohn Garry ent_msk | 1 << ((phy_no % 4) * 8));
3219d43f9cdbSJohn Garry
322011826e5dSJohn Garry ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1 + offset);
322111826e5dSJohn Garry ent_tmp = ent_int & (1 << (ENT_INT_SRC1_D2H_FIS_CH1_OFF *
322211826e5dSJohn Garry (phy_no % 4)));
3223d43f9cdbSJohn Garry ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4);
3224d43f9cdbSJohn Garry if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) {
3225d43f9cdbSJohn Garry dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no);
3226d43f9cdbSJohn Garry res = IRQ_NONE;
3227d43f9cdbSJohn Garry goto end;
3228d43f9cdbSJohn Garry }
3229d43f9cdbSJohn Garry
323004708ff4SXiang Chen /* check ERR bit of Status Register */
323104708ff4SXiang Chen if (fis->status & ATA_ERR) {
323204708ff4SXiang Chen dev_warn(dev, "sata int: phy%d FIS status: 0x%x\n", phy_no,
323304708ff4SXiang Chen fis->status);
3234f4e34f2aSXiang Chen hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
323504708ff4SXiang Chen res = IRQ_NONE;
323604708ff4SXiang Chen goto end;
323704708ff4SXiang Chen }
323804708ff4SXiang Chen
3239d43f9cdbSJohn Garry if (unlikely(phy_no == 8)) {
3240d43f9cdbSJohn Garry u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
3241d43f9cdbSJohn Garry
3242d43f9cdbSJohn Garry port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
3243d43f9cdbSJohn Garry PORT_STATE_PHY8_PORT_NUM_OFF;
3244d43f9cdbSJohn Garry link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
3245d43f9cdbSJohn Garry PORT_STATE_PHY8_CONN_RATE_OFF;
3246d43f9cdbSJohn Garry } else {
3247d43f9cdbSJohn Garry port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
3248d43f9cdbSJohn Garry port_id = (port_id >> (4 * phy_no)) & 0xf;
3249d43f9cdbSJohn Garry link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
3250d43f9cdbSJohn Garry link_rate = (link_rate >> (phy_no * 4)) & 0xf;
3251d43f9cdbSJohn Garry }
3252d43f9cdbSJohn Garry
3253d43f9cdbSJohn Garry if (port_id == 0xf) {
3254d43f9cdbSJohn Garry dev_err(dev, "sata int: phy%d invalid portid\n", phy_no);
3255d43f9cdbSJohn Garry res = IRQ_NONE;
3256d43f9cdbSJohn Garry goto end;
3257d43f9cdbSJohn Garry }
3258d43f9cdbSJohn Garry
3259d43f9cdbSJohn Garry sas_phy->linkrate = link_rate;
3260d43f9cdbSJohn Garry hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
3261d43f9cdbSJohn Garry HARD_PHY_LINKRATE);
3262d43f9cdbSJohn Garry phy->maximum_linkrate = hard_phy_linkrate & 0xf;
3263d43f9cdbSJohn Garry phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
3264d43f9cdbSJohn Garry
3265d43f9cdbSJohn Garry sas_phy->oob_mode = SATA_OOB_MODE;
3266d43f9cdbSJohn Garry /* Make up some unique SAS address */
3267d43f9cdbSJohn Garry attached_sas_addr[0] = 0x50;
32688b8d6653SXiang Chen attached_sas_addr[6] = hisi_hba->shost->host_no;
3269d43f9cdbSJohn Garry attached_sas_addr[7] = phy_no;
3270d43f9cdbSJohn Garry memcpy(sas_phy->attached_sas_addr, attached_sas_addr, SAS_ADDR_SIZE);
3271d43f9cdbSJohn Garry memcpy(sas_phy->frame_rcvd, fis, sizeof(struct dev_to_host_fis));
3272d43f9cdbSJohn Garry dev_info(dev, "sata int phyup: phy%d link_rate=%d\n", phy_no, link_rate);
3273d43f9cdbSJohn Garry phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
3274d43f9cdbSJohn Garry phy->port_id = port_id;
3275d43f9cdbSJohn Garry phy->phy_type |= PORT_TYPE_SATA;
3276d43f9cdbSJohn Garry phy->phy_attached = 1;
3277d43f9cdbSJohn Garry phy->identify.device_type = SAS_SATA_DEV;
3278d43f9cdbSJohn Garry phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
3279d43f9cdbSJohn Garry phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
3280e537b62bSXiaofei Tan hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
3281d43f9cdbSJohn Garry
3282046ab7d0SXiang Chen if (phy->reset_completion)
32833e1fb1b8SXiang Chen complete(phy->reset_completion);
3284d43f9cdbSJohn Garry end:
328511826e5dSJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp);
328611826e5dSJohn Garry hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk);
3287d43f9cdbSJohn Garry
3288d43f9cdbSJohn Garry return res;
3289d43f9cdbSJohn Garry }
3290d43f9cdbSJohn Garry
32917911e66fSJohn Garry static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
32927911e66fSJohn Garry int_phy_updown_v2_hw,
3293d3bf3d84SJohn Garry int_chnl_int_v2_hw,
32947911e66fSJohn Garry };
32957911e66fSJohn Garry
3296d3b688d3SXiang Chen static irq_handler_t fatal_interrupts[HISI_SAS_FATAL_INT_NR] = {
3297d3b688d3SXiang Chen fatal_ecc_int_v2_hw,
3298d3b688d3SXiang Chen fatal_axi_int_v2_hw
3299d3b688d3SXiang Chen };
3300d3b688d3SXiang Chen
330174a29219SJohn Garry #define CQ0_IRQ_INDEX (96)
330274a29219SJohn Garry
hisi_sas_v2_interrupt_preinit(struct hisi_hba * hisi_hba)330374a29219SJohn Garry static int hisi_sas_v2_interrupt_preinit(struct hisi_hba *hisi_hba)
330474a29219SJohn Garry {
330574a29219SJohn Garry struct platform_device *pdev = hisi_hba->platform_dev;
330674a29219SJohn Garry struct Scsi_Host *shost = hisi_hba->shost;
330774a29219SJohn Garry struct irq_affinity desc = {
330874a29219SJohn Garry .pre_vectors = CQ0_IRQ_INDEX,
330974a29219SJohn Garry .post_vectors = 16,
331074a29219SJohn Garry };
331174a29219SJohn Garry int resv = desc.pre_vectors + desc.post_vectors, minvec = resv + 1, nvec;
331274a29219SJohn Garry
331374a29219SJohn Garry nvec = devm_platform_get_irqs_affinity(pdev, &desc, minvec, 128,
331474a29219SJohn Garry &hisi_hba->irq_map);
331574a29219SJohn Garry if (nvec < 0)
331674a29219SJohn Garry return nvec;
331774a29219SJohn Garry
331874a29219SJohn Garry shost->nr_hw_queues = hisi_hba->cq_nvecs = nvec - resv;
331974a29219SJohn Garry
332074a29219SJohn Garry return 0;
332174a29219SJohn Garry }
332274a29219SJohn Garry
33233d570a28SJohn Garry /*
33247911e66fSJohn Garry * There is a limitation in the hip06 chipset that we need
33257911e66fSJohn Garry * to map in all mbigen interrupts, even if they are not used.
33267911e66fSJohn Garry */
interrupt_init_v2_hw(struct hisi_hba * hisi_hba)33277911e66fSJohn Garry static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
33287911e66fSJohn Garry {
332911b75249SJohn Garry struct platform_device *pdev = hisi_hba->platform_dev;
33307911e66fSJohn Garry struct device *dev = &pdev->dev;
333174a29219SJohn Garry int irq, rc = 0;
3332e16963f3SXiang Chen int i, phy_no, fatal_no, queue_no;
33337911e66fSJohn Garry
33347911e66fSJohn Garry for (i = 0; i < HISI_SAS_PHY_INT_NR; i++) {
333574a29219SJohn Garry irq = hisi_hba->irq_map[i + 1]; /* Phy up/down is irq1 */
33367911e66fSJohn Garry rc = devm_request_irq(dev, irq, phy_interrupts[i], 0,
33377911e66fSJohn Garry DRV_NAME " phy", hisi_hba);
33387911e66fSJohn Garry if (rc) {
333901d4e3a2SXiang Chen dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n",
33407911e66fSJohn Garry irq, rc);
33418a253888SXiang Chen rc = -ENOENT;
3342e16963f3SXiang Chen goto err_out;
33437911e66fSJohn Garry }
33447911e66fSJohn Garry }
33457911e66fSJohn Garry
33468a253888SXiang Chen for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
33478a253888SXiang Chen struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
3348d43f9cdbSJohn Garry
334974a29219SJohn Garry irq = hisi_hba->irq_map[phy_no + 72];
3350d43f9cdbSJohn Garry rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0,
3351d43f9cdbSJohn Garry DRV_NAME " sata", phy);
3352d43f9cdbSJohn Garry if (rc) {
335301d4e3a2SXiang Chen dev_err(dev, "irq init: could not request sata interrupt %d, rc=%d\n",
3354d43f9cdbSJohn Garry irq, rc);
33558a253888SXiang Chen rc = -ENOENT;
3356e16963f3SXiang Chen goto err_out;
3357d43f9cdbSJohn Garry }
3358d43f9cdbSJohn Garry }
335931a9cfa6SJohn Garry
33608a253888SXiang Chen for (fatal_no = 0; fatal_no < HISI_SAS_FATAL_INT_NR; fatal_no++) {
336174a29219SJohn Garry irq = hisi_hba->irq_map[fatal_no + 81];
33628a253888SXiang Chen rc = devm_request_irq(dev, irq, fatal_interrupts[fatal_no], 0,
3363d3b688d3SXiang Chen DRV_NAME " fatal", hisi_hba);
3364d3b688d3SXiang Chen if (rc) {
336501d4e3a2SXiang Chen dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n",
3366d3b688d3SXiang Chen irq, rc);
33678a253888SXiang Chen rc = -ENOENT;
3368e16963f3SXiang Chen goto err_out;
3369d3b688d3SXiang Chen }
3370d3b688d3SXiang Chen }
3371d3b688d3SXiang Chen
337274a29219SJohn Garry for (queue_no = 0; queue_no < hisi_hba->cq_nvecs; queue_no++) {
33738a253888SXiang Chen struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no];
337431a9cfa6SJohn Garry
337574a29219SJohn Garry cq->irq_no = hisi_hba->irq_map[queue_no + 96];
337681f338e9SXiang Chen rc = devm_request_threaded_irq(dev, cq->irq_no,
337781f338e9SXiang Chen cq_interrupt_v2_hw,
337881f338e9SXiang Chen cq_thread_v2_hw, IRQF_ONESHOT,
33798a253888SXiang Chen DRV_NAME " cq", cq);
338031a9cfa6SJohn Garry if (rc) {
338101d4e3a2SXiang Chen dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
338274a29219SJohn Garry cq->irq_no, rc);
33838a253888SXiang Chen rc = -ENOENT;
3384e16963f3SXiang Chen goto err_out;
338531a9cfa6SJohn Garry }
338674a29219SJohn Garry cq->irq_mask = irq_get_affinity_mask(cq->irq_no);
338731a9cfa6SJohn Garry }
3388e16963f3SXiang Chen err_out:
33898a253888SXiang Chen return rc;
33907911e66fSJohn Garry }
33917911e66fSJohn Garry
hisi_sas_v2_init(struct hisi_hba * hisi_hba)339294eac9e1SJohn Garry static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
339394eac9e1SJohn Garry {
339494eac9e1SJohn Garry int rc;
339594eac9e1SJohn Garry
339632ccba52SXiaofei Tan memset(hisi_hba->sata_dev_bitmap, 0, sizeof(hisi_hba->sata_dev_bitmap));
339732ccba52SXiaofei Tan
339894eac9e1SJohn Garry rc = hw_init_v2_hw(hisi_hba);
339994eac9e1SJohn Garry if (rc)
340094eac9e1SJohn Garry return rc;
340194eac9e1SJohn Garry
34027911e66fSJohn Garry rc = interrupt_init_v2_hw(hisi_hba);
34037911e66fSJohn Garry if (rc)
34047911e66fSJohn Garry return rc;
34057911e66fSJohn Garry
340694eac9e1SJohn Garry return 0;
340794eac9e1SJohn Garry }
340894eac9e1SJohn Garry
interrupt_disable_v2_hw(struct hisi_hba * hisi_hba)340906ec0fb9SXiang Chen static void interrupt_disable_v2_hw(struct hisi_hba *hisi_hba)
341006ec0fb9SXiang Chen {
341111b75249SJohn Garry struct platform_device *pdev = hisi_hba->platform_dev;
341206ec0fb9SXiang Chen int i;
341306ec0fb9SXiang Chen
341406ec0fb9SXiang Chen for (i = 0; i < hisi_hba->queue_count; i++)
341506ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0x1);
341606ec0fb9SXiang Chen
341706ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xffffffff);
341806ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xffffffff);
341906ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffffffff);
342006ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xffffffff);
342106ec0fb9SXiang Chen
342206ec0fb9SXiang Chen for (i = 0; i < hisi_hba->n_phy; i++) {
342306ec0fb9SXiang Chen hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xffffffff);
342406ec0fb9SXiang Chen hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffffff);
342506ec0fb9SXiang Chen }
342606ec0fb9SXiang Chen
342706ec0fb9SXiang Chen for (i = 0; i < 128; i++)
342806ec0fb9SXiang Chen synchronize_irq(platform_get_irq(pdev, i));
342906ec0fb9SXiang Chen }
343006ec0fb9SXiang Chen
3431917d3bdaSXiaofei Tan
get_phys_state_v2_hw(struct hisi_hba * hisi_hba)3432917d3bdaSXiaofei Tan static u32 get_phys_state_v2_hw(struct hisi_hba *hisi_hba)
3433917d3bdaSXiaofei Tan {
3434917d3bdaSXiaofei Tan return hisi_sas_read32(hisi_hba, PHY_STATE);
3435917d3bdaSXiaofei Tan }
3436917d3bdaSXiaofei Tan
soft_reset_v2_hw(struct hisi_hba * hisi_hba)343706ec0fb9SXiang Chen static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
343806ec0fb9SXiang Chen {
343911b75249SJohn Garry struct device *dev = hisi_hba->dev;
344006ec0fb9SXiang Chen int rc, cnt;
344106ec0fb9SXiang Chen
344206ec0fb9SXiang Chen interrupt_disable_v2_hw(hisi_hba);
344306ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
344406ec0fb9SXiang Chen
3445a25d0d3dSXiang Chen hisi_sas_stop_phys(hisi_hba);
344606ec0fb9SXiang Chen
344706ec0fb9SXiang Chen mdelay(10);
344806ec0fb9SXiang Chen
344906ec0fb9SXiang Chen hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + AM_CTRL_GLOBAL, 0x1);
345006ec0fb9SXiang Chen
345106ec0fb9SXiang Chen /* wait until bus idle */
345206ec0fb9SXiang Chen cnt = 0;
345306ec0fb9SXiang Chen while (1) {
345406ec0fb9SXiang Chen u32 status = hisi_sas_read32_relaxed(hisi_hba,
345506ec0fb9SXiang Chen AXI_MASTER_CFG_BASE + AM_CURR_TRANS_RETURN);
345606ec0fb9SXiang Chen
345706ec0fb9SXiang Chen if (status == 0x3)
345806ec0fb9SXiang Chen break;
345906ec0fb9SXiang Chen
346006ec0fb9SXiang Chen udelay(10);
346106ec0fb9SXiang Chen if (cnt++ > 10) {
3462f1c88211SXiang Chen dev_err(dev, "wait axi bus state to idle timeout!\n");
346306ec0fb9SXiang Chen return -1;
346406ec0fb9SXiang Chen }
346506ec0fb9SXiang Chen }
346606ec0fb9SXiang Chen
346706ec0fb9SXiang Chen hisi_sas_init_mem(hisi_hba);
346806ec0fb9SXiang Chen
346906ec0fb9SXiang Chen rc = hw_init_v2_hw(hisi_hba);
347006ec0fb9SXiang Chen if (rc)
347106ec0fb9SXiang Chen return rc;
347206ec0fb9SXiang Chen
3473c7b9d369SXiaofei Tan phys_reject_stp_links_v2_hw(hisi_hba);
3474c7b9d369SXiaofei Tan
347506ec0fb9SXiang Chen return 0;
347606ec0fb9SXiang Chen }
347706ec0fb9SXiang Chen
write_gpio_v2_hw(struct hisi_hba * hisi_hba,u8 reg_type,u8 reg_index,u8 reg_count,u8 * write_data)34786379c560SXiaofei Tan static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
34796379c560SXiaofei Tan u8 reg_index, u8 reg_count, u8 *write_data)
34806379c560SXiaofei Tan {
34816379c560SXiaofei Tan struct device *dev = hisi_hba->dev;
34826379c560SXiaofei Tan int phy_no, count;
34836379c560SXiaofei Tan
34846379c560SXiaofei Tan if (!hisi_hba->sgpio_regs)
34856379c560SXiaofei Tan return -EOPNOTSUPP;
34866379c560SXiaofei Tan
34876379c560SXiaofei Tan switch (reg_type) {
34886379c560SXiaofei Tan case SAS_GPIO_REG_TX:
34896379c560SXiaofei Tan count = reg_count * 4;
34906379c560SXiaofei Tan count = min(count, hisi_hba->n_phy);
34916379c560SXiaofei Tan
34926379c560SXiaofei Tan for (phy_no = 0; phy_no < count; phy_no++) {
34936379c560SXiaofei Tan /*
34946379c560SXiaofei Tan * GPIO_TX[n] register has the highest numbered drive
34956379c560SXiaofei Tan * of the four in the first byte and the lowest
34966379c560SXiaofei Tan * numbered drive in the fourth byte.
34976379c560SXiaofei Tan * See SFF-8485 Rev. 0.7 Table 24.
34986379c560SXiaofei Tan */
34996379c560SXiaofei Tan void __iomem *reg_addr = hisi_hba->sgpio_regs +
35006379c560SXiaofei Tan reg_index * 4 + phy_no;
35016379c560SXiaofei Tan int data_idx = phy_no + 3 - (phy_no % 4) * 2;
35026379c560SXiaofei Tan
35036379c560SXiaofei Tan writeb(write_data[data_idx], reg_addr);
35046379c560SXiaofei Tan }
35056379c560SXiaofei Tan
35066379c560SXiaofei Tan break;
35076379c560SXiaofei Tan default:
35086379c560SXiaofei Tan dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
35096379c560SXiaofei Tan reg_type);
35106379c560SXiaofei Tan return -EINVAL;
35116379c560SXiaofei Tan }
35126379c560SXiaofei Tan
35136379c560SXiaofei Tan return 0;
35146379c560SXiaofei Tan }
35156379c560SXiaofei Tan
wait_cmds_complete_timeout_v2_hw(struct hisi_hba * hisi_hba,int delay_ms,int timeout_ms)35164bc05809SLuo Jiaxing static void wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba,
3517a865ae14SXiaofei Tan int delay_ms, int timeout_ms)
3518a865ae14SXiaofei Tan {
3519a865ae14SXiaofei Tan struct device *dev = hisi_hba->dev;
3520a865ae14SXiaofei Tan int entries, entries_old = 0, time;
3521a865ae14SXiaofei Tan
3522a865ae14SXiaofei Tan for (time = 0; time < timeout_ms; time += delay_ms) {
3523a865ae14SXiaofei Tan entries = hisi_sas_read32(hisi_hba, CQE_SEND_CNT);
3524a865ae14SXiaofei Tan if (entries == entries_old)
3525a865ae14SXiaofei Tan break;
3526a865ae14SXiaofei Tan
3527a865ae14SXiaofei Tan entries_old = entries;
3528a865ae14SXiaofei Tan msleep(delay_ms);
3529a865ae14SXiaofei Tan }
3530a865ae14SXiaofei Tan
35314bc05809SLuo Jiaxing if (time >= timeout_ms) {
35324bc05809SLuo Jiaxing dev_dbg(dev, "Wait commands complete timeout!\n");
35334bc05809SLuo Jiaxing return;
35344bc05809SLuo Jiaxing }
353549159a5eSLuo Jiaxing
3536a865ae14SXiaofei Tan dev_dbg(dev, "wait commands complete %dms\n", time);
353749159a5eSLuo Jiaxing
3538a865ae14SXiaofei Tan }
3539235bfc7fSXiang Chen
354062ac8ccbSBart Van Assche static struct attribute *host_v2_hw_attrs[] = {
354162ac8ccbSBart Van Assche &dev_attr_phy_event_threshold.attr,
3542c3566f9aSXiang Chen NULL
3543c3566f9aSXiang Chen };
3544c3566f9aSXiang Chen
354562ac8ccbSBart Van Assche ATTRIBUTE_GROUPS(host_v2_hw);
354662ac8ccbSBart Van Assche
map_queues_v2_hw(struct Scsi_Host * shost)3547a4e1d0b7SBart Van Assche static void map_queues_v2_hw(struct Scsi_Host *shost)
354874a29219SJohn Garry {
354974a29219SJohn Garry struct hisi_hba *hisi_hba = shost_priv(shost);
355074a29219SJohn Garry struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
355174a29219SJohn Garry const struct cpumask *mask;
355274a29219SJohn Garry unsigned int queue, cpu;
355374a29219SJohn Garry
355474a29219SJohn Garry for (queue = 0; queue < qmap->nr_queues; queue++) {
355574a29219SJohn Garry mask = irq_get_affinity_mask(hisi_hba->irq_map[96 + queue]);
355674a29219SJohn Garry if (!mask)
355774a29219SJohn Garry continue;
355874a29219SJohn Garry
355974a29219SJohn Garry for_each_cpu(cpu, mask)
356074a29219SJohn Garry qmap->mq_map[cpu] = qmap->queue_offset + queue;
356174a29219SJohn Garry }
356274a29219SJohn Garry }
356374a29219SJohn Garry
3564e8c0ced9SBart Van Assche static const struct scsi_host_template sht_v2_hw = {
3565235bfc7fSXiang Chen .name = DRV_NAME,
356655ce24b3SJason Yan .proc_name = DRV_NAME,
3567235bfc7fSXiang Chen .module = THIS_MODULE,
3568235bfc7fSXiang Chen .queuecommand = sas_queuecommand,
3569b8f1d1e0SChristoph Hellwig .dma_need_drain = ata_scsi_dma_need_drain,
3570235bfc7fSXiang Chen .target_alloc = sas_target_alloc,
3571235bfc7fSXiang Chen .slave_configure = hisi_sas_slave_configure,
3572235bfc7fSXiang Chen .scan_finished = hisi_sas_scan_finished,
3573235bfc7fSXiang Chen .scan_start = hisi_sas_scan_start,
3574235bfc7fSXiang Chen .change_queue_depth = sas_change_queue_depth,
3575235bfc7fSXiang Chen .bios_param = sas_bios_param,
3576235bfc7fSXiang Chen .this_id = -1,
35776db831f4SXiang Chen .sg_tablesize = HISI_SAS_SGE_PAGE_CNT,
3578235bfc7fSXiang Chen .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
3579235bfc7fSXiang Chen .eh_device_reset_handler = sas_eh_device_reset_handler,
3580235bfc7fSXiang Chen .eh_target_reset_handler = sas_eh_target_reset_handler,
358136c6b761SXiang Chen .slave_alloc = hisi_sas_slave_alloc,
3582235bfc7fSXiang Chen .target_destroy = sas_target_destroy,
3583235bfc7fSXiang Chen .ioctl = sas_ioctl,
358475c0b0e1SArnd Bergmann #ifdef CONFIG_COMPAT
358575c0b0e1SArnd Bergmann .compat_ioctl = sas_ioctl,
358675c0b0e1SArnd Bergmann #endif
358762ac8ccbSBart Van Assche .shost_groups = host_v2_hw_groups,
3588a97fa586SXiang Chen .host_reset = hisi_sas_host_reset,
358974a29219SJohn Garry .map_queues = map_queues_v2_hw,
359074a29219SJohn Garry .host_tagset = 1,
3591235bfc7fSXiang Chen };
3592235bfc7fSXiang Chen
35933417ba8aSJohn Garry static const struct hisi_sas_hw hisi_sas_v2_hw = {
359494eac9e1SJohn Garry .hw_init = hisi_sas_v2_init,
359574a29219SJohn Garry .interrupt_preinit = hisi_sas_v2_interrupt_preinit,
359685b2c3c0SJohn Garry .setup_itct = setup_itct_v2_hw,
3597330fa7f3SJohn Garry .slot_index_alloc = slot_index_alloc_quirk_v2_hw,
3598b2bdaf2bSJohn Garry .alloc_dev = alloc_dev_quirk_v2_hw,
3599569eddcfSXiang Chen .sl_notify_ssp = sl_notify_ssp_v2_hw,
36005473c060SJohn Garry .get_wideport_bitmap = get_wideport_bitmap_v2_hw,
36010258141aSXiaofei Tan .clear_itct = clear_itct_v2_hw,
360285b2c3c0SJohn Garry .free_device = free_device_v2_hw,
3603c2d89392SJohn Garry .prep_smp = prep_smp_v2_hw,
36048c36e31dSJohn Garry .prep_ssp = prep_ssp_v2_hw,
36056f2ff1a1SJohn Garry .prep_stp = prep_ata_v2_hw,
3606a3e665d9SJohn Garry .prep_abort = prep_abort_v2_hw,
36078c36e31dSJohn Garry .start_delivery = start_delivery_v2_hw,
3608396b8044SJohn Garry .phys_init = phys_init_v2_hw,
36091eb8eeacSXiang Chen .phy_start = start_phy_v2_hw,
361063fb11b8SJohn Garry .phy_disable = disable_phy_v2_hw,
361163fb11b8SJohn Garry .phy_hard_reset = phy_hard_reset_v2_hw,
3612c52108c6SXiaofei Tan .get_events = phy_get_events_v2_hw,
36132ae75787SXiang Chen .phy_set_linkrate = phy_set_linkrate_v2_hw,
36142ae75787SXiang Chen .phy_get_max_linkrate = phy_get_max_linkrate_v2_hw,
361594eac9e1SJohn Garry .complete_hdr_size = sizeof(struct hisi_sas_complete_v2_hdr),
361606ec0fb9SXiang Chen .soft_reset = soft_reset_v2_hw,
3617917d3bdaSXiaofei Tan .get_phys_state = get_phys_state_v2_hw,
36186379c560SXiaofei Tan .write_gpio = write_gpio_v2_hw,
3619a865ae14SXiaofei Tan .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v2_hw,
3620235bfc7fSXiang Chen .sht = &sht_v2_hw,
36213417ba8aSJohn Garry };
36223417ba8aSJohn Garry
hisi_sas_v2_probe(struct platform_device * pdev)36233417ba8aSJohn Garry static int hisi_sas_v2_probe(struct platform_device *pdev)
36243417ba8aSJohn Garry {
36253417ba8aSJohn Garry return hisi_sas_probe(pdev, &hisi_sas_v2_hw);
36263417ba8aSJohn Garry }
36273417ba8aSJohn Garry
36283417ba8aSJohn Garry static const struct of_device_id sas_v2_of_match[] = {
36293417ba8aSJohn Garry { .compatible = "hisilicon,hip06-sas-v2",},
3630039ae102SJohn Garry { .compatible = "hisilicon,hip07-sas-v2",},
36313417ba8aSJohn Garry {},
36323417ba8aSJohn Garry };
36333417ba8aSJohn Garry MODULE_DEVICE_TABLE(of, sas_v2_of_match);
36343417ba8aSJohn Garry
363550408712SJohn Garry static const struct acpi_device_id sas_v2_acpi_match[] = {
363650408712SJohn Garry { "HISI0162", 0 },
363750408712SJohn Garry { }
363850408712SJohn Garry };
363950408712SJohn Garry
364050408712SJohn Garry MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match);
364150408712SJohn Garry
36423417ba8aSJohn Garry static struct platform_driver hisi_sas_v2_driver = {
36433417ba8aSJohn Garry .probe = hisi_sas_v2_probe,
36448cd6d0a3SUwe Kleine-König .remove_new = hisi_sas_remove,
36453417ba8aSJohn Garry .driver = {
36463417ba8aSJohn Garry .name = DRV_NAME,
36473417ba8aSJohn Garry .of_match_table = sas_v2_of_match,
364850408712SJohn Garry .acpi_match_table = ACPI_PTR(sas_v2_acpi_match),
36493417ba8aSJohn Garry },
36503417ba8aSJohn Garry };
36513417ba8aSJohn Garry
36523417ba8aSJohn Garry module_platform_driver(hisi_sas_v2_driver);
36533417ba8aSJohn Garry
36543417ba8aSJohn Garry MODULE_LICENSE("GPL");
36553417ba8aSJohn Garry MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
36563417ba8aSJohn Garry MODULE_DESCRIPTION("HISILICON SAS controller v2 hw driver");
36573417ba8aSJohn Garry MODULE_ALIAS("platform:" DRV_NAME);
3658