12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
251ba902aSAviad Krawczyk /*
351ba902aSAviad Krawczyk  * Huawei HiNIC PCI Express Linux driver
451ba902aSAviad Krawczyk  * Copyright(c) 2017 Huawei Technologies Co., Ltd
551ba902aSAviad Krawczyk  */
651ba902aSAviad Krawczyk 
751ba902aSAviad Krawczyk #include <linux/pci.h>
851ba902aSAviad Krawczyk #include <linux/device.h>
951ba902aSAviad Krawczyk #include <linux/errno.h>
1051ba902aSAviad Krawczyk #include <linux/io.h>
1151ba902aSAviad Krawczyk #include <linux/types.h>
1251ba902aSAviad Krawczyk #include <linux/bitops.h>
1372ef908bSLuo bin #include <linux/delay.h>
1451ba902aSAviad Krawczyk 
1551ba902aSAviad Krawczyk #include "hinic_hw_csr.h"
1651ba902aSAviad Krawczyk #include "hinic_hw_if.h"
1751ba902aSAviad Krawczyk 
1851ba902aSAviad Krawczyk #define PCIE_ATTR_ENTRY         0
1951ba902aSAviad Krawczyk 
20f00fe738SAviad Krawczyk #define VALID_MSIX_IDX(attr, msix_index) ((msix_index) < (attr)->num_irqs)
21f00fe738SAviad Krawczyk 
2272ef908bSLuo bin #define WAIT_HWIF_READY_TIMEOUT	10000
2372ef908bSLuo bin 
2490f86b8aSLuo bin #define HINIC_SELFTEST_RESULT 0x883C
2590f86b8aSLuo bin 
26f00fe738SAviad Krawczyk /**
27f00fe738SAviad Krawczyk  * hinic_msix_attr_set - set message attribute for msix entry
28f00fe738SAviad Krawczyk  * @hwif: the HW interface of a pci function device
29f00fe738SAviad Krawczyk  * @msix_index: msix_index
30f00fe738SAviad Krawczyk  * @pending_limit: the maximum pending interrupt events (unit 8)
31f00fe738SAviad Krawczyk  * @coalesc_timer: coalesc period for interrupt (unit 8 us)
32f00fe738SAviad Krawczyk  * @lli_timer: replenishing period for low latency credit (unit 8 us)
33f00fe738SAviad Krawczyk  * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
34f00fe738SAviad Krawczyk  * @resend_timer: maximum wait for resending msix (unit coalesc period)
35f00fe738SAviad Krawczyk  *
36f00fe738SAviad Krawczyk  * Return 0 - Success, negative - Failure
37f00fe738SAviad Krawczyk  **/
hinic_msix_attr_set(struct hinic_hwif * hwif,u16 msix_index,u8 pending_limit,u8 coalesc_timer,u8 lli_timer,u8 lli_credit_limit,u8 resend_timer)38f00fe738SAviad Krawczyk int hinic_msix_attr_set(struct hinic_hwif *hwif, u16 msix_index,
39f00fe738SAviad Krawczyk 			u8 pending_limit, u8 coalesc_timer,
40f00fe738SAviad Krawczyk 			u8 lli_timer, u8 lli_credit_limit,
41f00fe738SAviad Krawczyk 			u8 resend_timer)
42f00fe738SAviad Krawczyk {
43f00fe738SAviad Krawczyk 	u32 msix_ctrl, addr;
44f00fe738SAviad Krawczyk 
45f00fe738SAviad Krawczyk 	if (!VALID_MSIX_IDX(&hwif->attr, msix_index))
46f00fe738SAviad Krawczyk 		return -EINVAL;
47f00fe738SAviad Krawczyk 
48f00fe738SAviad Krawczyk 	msix_ctrl = HINIC_MSIX_ATTR_SET(pending_limit, PENDING_LIMIT)   |
49f00fe738SAviad Krawczyk 		    HINIC_MSIX_ATTR_SET(coalesc_timer, COALESC_TIMER)   |
50f00fe738SAviad Krawczyk 		    HINIC_MSIX_ATTR_SET(lli_timer, LLI_TIMER)           |
51f00fe738SAviad Krawczyk 		    HINIC_MSIX_ATTR_SET(lli_credit_limit, LLI_CREDIT)   |
52f00fe738SAviad Krawczyk 		    HINIC_MSIX_ATTR_SET(resend_timer, RESEND_TIMER);
53f00fe738SAviad Krawczyk 
54f00fe738SAviad Krawczyk 	addr = HINIC_CSR_MSIX_CTRL_ADDR(msix_index);
55f00fe738SAviad Krawczyk 
56f00fe738SAviad Krawczyk 	hinic_hwif_write_reg(hwif, addr, msix_ctrl);
57f00fe738SAviad Krawczyk 	return 0;
58f00fe738SAviad Krawczyk }
59f00fe738SAviad Krawczyk 
60f00fe738SAviad Krawczyk /**
61f00fe738SAviad Krawczyk  * hinic_msix_attr_cnt_clear - clear message attribute counters for msix entry
62f00fe738SAviad Krawczyk  * @hwif: the HW interface of a pci function device
63f00fe738SAviad Krawczyk  * @msix_index: msix_index
64f00fe738SAviad Krawczyk  *
65f00fe738SAviad Krawczyk  * Return 0 - Success, negative - Failure
66f00fe738SAviad Krawczyk  **/
hinic_msix_attr_cnt_clear(struct hinic_hwif * hwif,u16 msix_index)67f00fe738SAviad Krawczyk int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index)
68f00fe738SAviad Krawczyk {
69f00fe738SAviad Krawczyk 	u32 msix_ctrl, addr;
70f00fe738SAviad Krawczyk 
71f00fe738SAviad Krawczyk 	if (!VALID_MSIX_IDX(&hwif->attr, msix_index))
72f00fe738SAviad Krawczyk 		return -EINVAL;
73f00fe738SAviad Krawczyk 
74f00fe738SAviad Krawczyk 	msix_ctrl = HINIC_MSIX_CNT_SET(1, RESEND_TIMER);
75f00fe738SAviad Krawczyk 	addr = HINIC_CSR_MSIX_CNT_ADDR(msix_index);
76f00fe738SAviad Krawczyk 
77f00fe738SAviad Krawczyk 	hinic_hwif_write_reg(hwif, addr, msix_ctrl);
78f00fe738SAviad Krawczyk 	return 0;
79f00fe738SAviad Krawczyk }
80f00fe738SAviad Krawczyk 
8151ba902aSAviad Krawczyk /**
82c4d06d2dSAviad Krawczyk  * hinic_set_pf_action - set action on pf channel
83c4d06d2dSAviad Krawczyk  * @hwif: the HW interface of a pci function device
84c4d06d2dSAviad Krawczyk  * @action: action on pf channel
85c4d06d2dSAviad Krawczyk  **/
hinic_set_pf_action(struct hinic_hwif * hwif,enum hinic_pf_action action)86c4d06d2dSAviad Krawczyk void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action)
87c4d06d2dSAviad Krawczyk {
88a425b6e1SLuo bin 	u32 attr5;
89c4d06d2dSAviad Krawczyk 
90a425b6e1SLuo bin 	if (HINIC_IS_VF(hwif))
91a425b6e1SLuo bin 		return;
92a425b6e1SLuo bin 
93a425b6e1SLuo bin 	attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR);
94c4d06d2dSAviad Krawczyk 	attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION);
95c4d06d2dSAviad Krawczyk 	attr5 |= HINIC_FA5_SET(action, PF_ACTION);
96c4d06d2dSAviad Krawczyk 
97c4d06d2dSAviad Krawczyk 	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR, attr5);
98c4d06d2dSAviad Krawczyk }
99c4d06d2dSAviad Krawczyk 
hinic_outbound_state_get(struct hinic_hwif * hwif)100e2585ea7SAviad Krawczyk enum hinic_outbound_state hinic_outbound_state_get(struct hinic_hwif *hwif)
101e2585ea7SAviad Krawczyk {
102e2585ea7SAviad Krawczyk 	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
103e2585ea7SAviad Krawczyk 
104e2585ea7SAviad Krawczyk 	return HINIC_FA4_GET(attr4, OUTBOUND_STATE);
105e2585ea7SAviad Krawczyk }
106e2585ea7SAviad Krawczyk 
hinic_outbound_state_set(struct hinic_hwif * hwif,enum hinic_outbound_state outbound_state)107e2585ea7SAviad Krawczyk void hinic_outbound_state_set(struct hinic_hwif *hwif,
108e2585ea7SAviad Krawczyk 			      enum hinic_outbound_state outbound_state)
109e2585ea7SAviad Krawczyk {
110e2585ea7SAviad Krawczyk 	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
111e2585ea7SAviad Krawczyk 
112e2585ea7SAviad Krawczyk 	attr4 = HINIC_FA4_CLEAR(attr4, OUTBOUND_STATE);
113e2585ea7SAviad Krawczyk 	attr4 |= HINIC_FA4_SET(outbound_state, OUTBOUND_STATE);
114e2585ea7SAviad Krawczyk 
115e2585ea7SAviad Krawczyk 	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
116e2585ea7SAviad Krawczyk }
117e2585ea7SAviad Krawczyk 
hinic_db_state_get(struct hinic_hwif * hwif)118e2585ea7SAviad Krawczyk enum hinic_db_state hinic_db_state_get(struct hinic_hwif *hwif)
119e2585ea7SAviad Krawczyk {
120e2585ea7SAviad Krawczyk 	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
121e2585ea7SAviad Krawczyk 
122e2585ea7SAviad Krawczyk 	return HINIC_FA4_GET(attr4, DB_STATE);
123e2585ea7SAviad Krawczyk }
124e2585ea7SAviad Krawczyk 
hinic_db_state_set(struct hinic_hwif * hwif,enum hinic_db_state db_state)125e2585ea7SAviad Krawczyk void hinic_db_state_set(struct hinic_hwif *hwif,
126e2585ea7SAviad Krawczyk 			enum hinic_db_state db_state)
127e2585ea7SAviad Krawczyk {
128e2585ea7SAviad Krawczyk 	u32 attr4 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR);
129e2585ea7SAviad Krawczyk 
130e2585ea7SAviad Krawczyk 	attr4 = HINIC_FA4_CLEAR(attr4, DB_STATE);
131e2585ea7SAviad Krawczyk 	attr4 |= HINIC_FA4_SET(db_state, DB_STATE);
132e2585ea7SAviad Krawczyk 
133e2585ea7SAviad Krawczyk 	hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4);
134e2585ea7SAviad Krawczyk }
135e2585ea7SAviad Krawczyk 
hinic_set_msix_state(struct hinic_hwif * hwif,u16 msix_idx,enum hinic_msix_state flag)136905b464aSXue Chaojing void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx,
137905b464aSXue Chaojing 			  enum hinic_msix_state flag)
138905b464aSXue Chaojing {
139905b464aSXue Chaojing 	u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE +
140905b464aSXue Chaojing 			HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL;
141905b464aSXue Chaojing 	u32 mask_bits;
142905b464aSXue Chaojing 
143905b464aSXue Chaojing 	mask_bits = readl(hwif->intr_regs_base + offset);
144905b464aSXue Chaojing 	mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
145905b464aSXue Chaojing 
146905b464aSXue Chaojing 	if (flag)
147905b464aSXue Chaojing 		mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT;
148905b464aSXue Chaojing 
149905b464aSXue Chaojing 	writel(mask_bits, hwif->intr_regs_base + offset);
150905b464aSXue Chaojing }
151905b464aSXue Chaojing 
152c4d06d2dSAviad Krawczyk /**
15351ba902aSAviad Krawczyk  * hwif_ready - test if the HW is ready for use
15451ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
15551ba902aSAviad Krawczyk  *
15651ba902aSAviad Krawczyk  * Return 0 - Success, negative - Failure
15751ba902aSAviad Krawczyk  **/
hwif_ready(struct hinic_hwif * hwif)15851ba902aSAviad Krawczyk static int hwif_ready(struct hinic_hwif *hwif)
15951ba902aSAviad Krawczyk {
16051ba902aSAviad Krawczyk 	u32 addr, attr1;
16151ba902aSAviad Krawczyk 
16251ba902aSAviad Krawczyk 	addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
16351ba902aSAviad Krawczyk 	attr1  = hinic_hwif_read_reg(hwif, addr);
16451ba902aSAviad Krawczyk 
16572ef908bSLuo bin 	if (!HINIC_FA1_GET(attr1, MGMT_INIT_STATUS))
16672ef908bSLuo bin 		return -EBUSY;
16772ef908bSLuo bin 
16872ef908bSLuo bin 	if (HINIC_IS_VF(hwif)) {
16972ef908bSLuo bin 		if (!HINIC_FA1_GET(attr1, PF_INIT_STATUS))
17072ef908bSLuo bin 			return -EBUSY;
17151ba902aSAviad Krawczyk 	}
17251ba902aSAviad Krawczyk 
17351ba902aSAviad Krawczyk 	return 0;
17451ba902aSAviad Krawczyk }
17551ba902aSAviad Krawczyk 
wait_hwif_ready(struct hinic_hwif * hwif)17672ef908bSLuo bin static int wait_hwif_ready(struct hinic_hwif *hwif)
17772ef908bSLuo bin {
17872ef908bSLuo bin 	unsigned long timeout = 0;
17972ef908bSLuo bin 
18072ef908bSLuo bin 	do {
18172ef908bSLuo bin 		if (!hwif_ready(hwif))
18272ef908bSLuo bin 			return 0;
18372ef908bSLuo bin 
18472ef908bSLuo bin 		usleep_range(999, 1000);
18572ef908bSLuo bin 		timeout++;
18672ef908bSLuo bin 	} while (timeout <= WAIT_HWIF_READY_TIMEOUT);
18772ef908bSLuo bin 
18872ef908bSLuo bin 	dev_err(&hwif->pdev->dev, "Wait for hwif timeout\n");
18972ef908bSLuo bin 
19072ef908bSLuo bin 	return -EBUSY;
19172ef908bSLuo bin }
19272ef908bSLuo bin 
19351ba902aSAviad Krawczyk /**
19451ba902aSAviad Krawczyk  * set_hwif_attr - set the attributes in the relevant members in hwif
19551ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
19651ba902aSAviad Krawczyk  * @attr0: the first attribute that was read from the hw
19751ba902aSAviad Krawczyk  * @attr1: the second attribute that was read from the hw
198b1b6c110SLuo bin  * @attr2: the third attribute that was read from the hw
19951ba902aSAviad Krawczyk  **/
set_hwif_attr(struct hinic_hwif * hwif,u32 attr0,u32 attr1,u32 attr2)200a425b6e1SLuo bin static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1,
201a425b6e1SLuo bin 			  u32 attr2)
20251ba902aSAviad Krawczyk {
20351ba902aSAviad Krawczyk 	hwif->attr.func_idx     = HINIC_FA0_GET(attr0, FUNC_IDX);
20451ba902aSAviad Krawczyk 	hwif->attr.pf_idx       = HINIC_FA0_GET(attr0, PF_IDX);
20551ba902aSAviad Krawczyk 	hwif->attr.pci_intf_idx = HINIC_FA0_GET(attr0, PCI_INTF_IDX);
20651ba902aSAviad Krawczyk 	hwif->attr.func_type    = HINIC_FA0_GET(attr0, FUNC_TYPE);
20751ba902aSAviad Krawczyk 
20851ba902aSAviad Krawczyk 	hwif->attr.num_aeqs = BIT(HINIC_FA1_GET(attr1, AEQS_PER_FUNC));
20951ba902aSAviad Krawczyk 	hwif->attr.num_ceqs = BIT(HINIC_FA1_GET(attr1, CEQS_PER_FUNC));
21051ba902aSAviad Krawczyk 	hwif->attr.num_irqs = BIT(HINIC_FA1_GET(attr1, IRQS_PER_FUNC));
21151ba902aSAviad Krawczyk 	hwif->attr.num_dma_attr = BIT(HINIC_FA1_GET(attr1, DMA_ATTR_PER_FUNC));
212a425b6e1SLuo bin 	hwif->attr.global_vf_id_of_pf = HINIC_FA2_GET(attr2,
213a425b6e1SLuo bin 						      GLOBAL_VF_ID_OF_PF);
21451ba902aSAviad Krawczyk }
21551ba902aSAviad Krawczyk 
21651ba902aSAviad Krawczyk /**
21751ba902aSAviad Krawczyk  * read_hwif_attr - read the attributes and set members in hwif
21851ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
21951ba902aSAviad Krawczyk  **/
read_hwif_attr(struct hinic_hwif * hwif)22051ba902aSAviad Krawczyk static void read_hwif_attr(struct hinic_hwif *hwif)
22151ba902aSAviad Krawczyk {
222a425b6e1SLuo bin 	u32 addr, attr0, attr1, attr2;
22351ba902aSAviad Krawczyk 
22451ba902aSAviad Krawczyk 	addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
22551ba902aSAviad Krawczyk 	attr0  = hinic_hwif_read_reg(hwif, addr);
22651ba902aSAviad Krawczyk 
22751ba902aSAviad Krawczyk 	addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
22851ba902aSAviad Krawczyk 	attr1  = hinic_hwif_read_reg(hwif, addr);
22951ba902aSAviad Krawczyk 
230a425b6e1SLuo bin 	addr   = HINIC_CSR_FUNC_ATTR2_ADDR;
231a425b6e1SLuo bin 	attr2  = hinic_hwif_read_reg(hwif, addr);
232a425b6e1SLuo bin 
233a425b6e1SLuo bin 	set_hwif_attr(hwif, attr0, attr1, attr2);
23451ba902aSAviad Krawczyk }
23551ba902aSAviad Krawczyk 
23651ba902aSAviad Krawczyk /**
23751ba902aSAviad Krawczyk  * set_ppf - try to set hwif as ppf and set the type of hwif in this case
23851ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
23951ba902aSAviad Krawczyk  **/
set_ppf(struct hinic_hwif * hwif)24051ba902aSAviad Krawczyk static void set_ppf(struct hinic_hwif *hwif)
24151ba902aSAviad Krawczyk {
24251ba902aSAviad Krawczyk 	struct hinic_func_attr *attr = &hwif->attr;
24351ba902aSAviad Krawczyk 	u32 addr, val, ppf_election;
24451ba902aSAviad Krawczyk 
24551ba902aSAviad Krawczyk 	/* Read Modify Write */
24651ba902aSAviad Krawczyk 	addr = HINIC_CSR_PPF_ELECTION_ADDR(HINIC_HWIF_PCI_INTF(hwif));
24751ba902aSAviad Krawczyk 
24851ba902aSAviad Krawczyk 	val = hinic_hwif_read_reg(hwif, addr);
24951ba902aSAviad Krawczyk 	val = HINIC_PPF_ELECTION_CLEAR(val, IDX);
25051ba902aSAviad Krawczyk 
25151ba902aSAviad Krawczyk 	ppf_election = HINIC_PPF_ELECTION_SET(HINIC_HWIF_FUNC_IDX(hwif), IDX);
25251ba902aSAviad Krawczyk 
25351ba902aSAviad Krawczyk 	val |= ppf_election;
25451ba902aSAviad Krawczyk 	hinic_hwif_write_reg(hwif, addr, val);
25551ba902aSAviad Krawczyk 
25651ba902aSAviad Krawczyk 	/* check PPF */
25751ba902aSAviad Krawczyk 	val = hinic_hwif_read_reg(hwif, addr);
25851ba902aSAviad Krawczyk 
25951ba902aSAviad Krawczyk 	attr->ppf_idx = HINIC_PPF_ELECTION_GET(val, IDX);
26051ba902aSAviad Krawczyk 	if (attr->ppf_idx == HINIC_HWIF_FUNC_IDX(hwif))
26151ba902aSAviad Krawczyk 		attr->func_type = HINIC_PPF;
26251ba902aSAviad Krawczyk }
26351ba902aSAviad Krawczyk 
26451ba902aSAviad Krawczyk /**
26551ba902aSAviad Krawczyk  * set_dma_attr - set the dma attributes in the HW
26651ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
26751ba902aSAviad Krawczyk  * @entry_idx: the entry index in the dma table
26851ba902aSAviad Krawczyk  * @st: PCIE TLP steering tag
26951ba902aSAviad Krawczyk  * @at: PCIE TLP AT field
27051ba902aSAviad Krawczyk  * @ph: PCIE TLP Processing Hint field
27151ba902aSAviad Krawczyk  * @no_snooping: PCIE TLP No snooping
27251ba902aSAviad Krawczyk  * @tph_en: PCIE TLP Processing Hint Enable
27351ba902aSAviad Krawczyk  **/
set_dma_attr(struct hinic_hwif * hwif,u32 entry_idx,u8 st,u8 at,u8 ph,enum hinic_pcie_nosnoop no_snooping,enum hinic_pcie_tph tph_en)27451ba902aSAviad Krawczyk static void set_dma_attr(struct hinic_hwif *hwif, u32 entry_idx,
27551ba902aSAviad Krawczyk 			 u8 st, u8 at, u8 ph,
27651ba902aSAviad Krawczyk 			 enum hinic_pcie_nosnoop no_snooping,
27751ba902aSAviad Krawczyk 			 enum hinic_pcie_tph tph_en)
27851ba902aSAviad Krawczyk {
27951ba902aSAviad Krawczyk 	u32 addr, val, dma_attr_entry;
28051ba902aSAviad Krawczyk 
28151ba902aSAviad Krawczyk 	/* Read Modify Write */
28251ba902aSAviad Krawczyk 	addr = HINIC_CSR_DMA_ATTR_ADDR(entry_idx);
28351ba902aSAviad Krawczyk 
28451ba902aSAviad Krawczyk 	val = hinic_hwif_read_reg(hwif, addr);
28551ba902aSAviad Krawczyk 	val = HINIC_DMA_ATTR_CLEAR(val, ST)             &
28651ba902aSAviad Krawczyk 	      HINIC_DMA_ATTR_CLEAR(val, AT)             &
28751ba902aSAviad Krawczyk 	      HINIC_DMA_ATTR_CLEAR(val, PH)             &
28851ba902aSAviad Krawczyk 	      HINIC_DMA_ATTR_CLEAR(val, NO_SNOOPING)    &
28951ba902aSAviad Krawczyk 	      HINIC_DMA_ATTR_CLEAR(val, TPH_EN);
29051ba902aSAviad Krawczyk 
29151ba902aSAviad Krawczyk 	dma_attr_entry = HINIC_DMA_ATTR_SET(st, ST)                     |
29251ba902aSAviad Krawczyk 			 HINIC_DMA_ATTR_SET(at, AT)                     |
29351ba902aSAviad Krawczyk 			 HINIC_DMA_ATTR_SET(ph, PH)                     |
29451ba902aSAviad Krawczyk 			 HINIC_DMA_ATTR_SET(no_snooping, NO_SNOOPING)   |
29551ba902aSAviad Krawczyk 			 HINIC_DMA_ATTR_SET(tph_en, TPH_EN);
29651ba902aSAviad Krawczyk 
29751ba902aSAviad Krawczyk 	val |= dma_attr_entry;
29851ba902aSAviad Krawczyk 	hinic_hwif_write_reg(hwif, addr, val);
29951ba902aSAviad Krawczyk }
30051ba902aSAviad Krawczyk 
30151ba902aSAviad Krawczyk /**
302*d6174870SYang Shen  * dma_attr_init - initialize the default dma attributes
30351ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
30451ba902aSAviad Krawczyk  **/
dma_attr_init(struct hinic_hwif * hwif)30551ba902aSAviad Krawczyk static void dma_attr_init(struct hinic_hwif *hwif)
30651ba902aSAviad Krawczyk {
30751ba902aSAviad Krawczyk 	set_dma_attr(hwif, PCIE_ATTR_ENTRY, HINIC_PCIE_ST_DISABLE,
30851ba902aSAviad Krawczyk 		     HINIC_PCIE_AT_DISABLE, HINIC_PCIE_PH_DISABLE,
30951ba902aSAviad Krawczyk 		     HINIC_PCIE_SNOOP, HINIC_PCIE_TPH_DISABLE);
31051ba902aSAviad Krawczyk }
31151ba902aSAviad Krawczyk 
hinic_glb_pf_vf_offset(struct hinic_hwif * hwif)312a425b6e1SLuo bin u16 hinic_glb_pf_vf_offset(struct hinic_hwif *hwif)
313a425b6e1SLuo bin {
314a425b6e1SLuo bin 	if (!hwif)
315a425b6e1SLuo bin 		return 0;
316a425b6e1SLuo bin 
317a425b6e1SLuo bin 	return hwif->attr.global_vf_id_of_pf;
318a425b6e1SLuo bin }
319a425b6e1SLuo bin 
hinic_global_func_id_hw(struct hinic_hwif * hwif)320a425b6e1SLuo bin u16 hinic_global_func_id_hw(struct hinic_hwif *hwif)
321a425b6e1SLuo bin {
322a425b6e1SLuo bin 	u32 addr, attr0;
323a425b6e1SLuo bin 
324a425b6e1SLuo bin 	addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
325a425b6e1SLuo bin 	attr0  = hinic_hwif_read_reg(hwif, addr);
326a425b6e1SLuo bin 
327a425b6e1SLuo bin 	return HINIC_FA0_GET(attr0, FUNC_IDX);
328a425b6e1SLuo bin }
329a425b6e1SLuo bin 
hinic_pf_id_of_vf_hw(struct hinic_hwif * hwif)330a425b6e1SLuo bin u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif)
331a425b6e1SLuo bin {
332a425b6e1SLuo bin 	u32 addr, attr0;
333a425b6e1SLuo bin 
334a425b6e1SLuo bin 	addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
335a425b6e1SLuo bin 	attr0  = hinic_hwif_read_reg(hwif, addr);
336a425b6e1SLuo bin 
337a425b6e1SLuo bin 	return HINIC_FA0_GET(attr0, PF_IDX);
338a425b6e1SLuo bin }
339a425b6e1SLuo bin 
__print_selftest_reg(struct hinic_hwif * hwif)34090f86b8aSLuo bin static void __print_selftest_reg(struct hinic_hwif *hwif)
34190f86b8aSLuo bin {
34290f86b8aSLuo bin 	u32 addr, attr0, attr1;
34390f86b8aSLuo bin 
34490f86b8aSLuo bin 	addr   = HINIC_CSR_FUNC_ATTR1_ADDR;
34590f86b8aSLuo bin 	attr1  = hinic_hwif_read_reg(hwif, addr);
34690f86b8aSLuo bin 
34790f86b8aSLuo bin 	if (attr1 == HINIC_PCIE_LINK_DOWN) {
34890f86b8aSLuo bin 		dev_err(&hwif->pdev->dev, "PCIE is link down\n");
34990f86b8aSLuo bin 		return;
35090f86b8aSLuo bin 	}
35190f86b8aSLuo bin 
35290f86b8aSLuo bin 	addr   = HINIC_CSR_FUNC_ATTR0_ADDR;
35390f86b8aSLuo bin 	attr0  = hinic_hwif_read_reg(hwif, addr);
35490f86b8aSLuo bin 	if (HINIC_FA0_GET(attr0, FUNC_TYPE) != HINIC_VF &&
35590f86b8aSLuo bin 	    !HINIC_FA0_GET(attr0, PCI_INTF_IDX))
35690f86b8aSLuo bin 		dev_err(&hwif->pdev->dev, "Selftest reg: 0x%08x\n",
35790f86b8aSLuo bin 			hinic_hwif_read_reg(hwif, HINIC_SELFTEST_RESULT));
35890f86b8aSLuo bin }
35990f86b8aSLuo bin 
36051ba902aSAviad Krawczyk /**
36151ba902aSAviad Krawczyk  * hinic_init_hwif - initialize the hw interface
36251ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
3635db8c86eSGuangbin Huang  * @pdev: the pci device for accessing PCI resources
36451ba902aSAviad Krawczyk  *
36551ba902aSAviad Krawczyk  * Return 0 - Success, negative - Failure
36651ba902aSAviad Krawczyk  **/
hinic_init_hwif(struct hinic_hwif * hwif,struct pci_dev * pdev)36751ba902aSAviad Krawczyk int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
36851ba902aSAviad Krawczyk {
36951ba902aSAviad Krawczyk 	int err;
37051ba902aSAviad Krawczyk 
37151ba902aSAviad Krawczyk 	hwif->pdev = pdev;
37251ba902aSAviad Krawczyk 
37351ba902aSAviad Krawczyk 	hwif->cfg_regs_bar = pci_ioremap_bar(pdev, HINIC_PCI_CFG_REGS_BAR);
37451ba902aSAviad Krawczyk 	if (!hwif->cfg_regs_bar) {
37551ba902aSAviad Krawczyk 		dev_err(&pdev->dev, "Failed to map configuration regs\n");
37651ba902aSAviad Krawczyk 		return -ENOMEM;
37751ba902aSAviad Krawczyk 	}
37851ba902aSAviad Krawczyk 
379905b464aSXue Chaojing 	hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR);
380905b464aSXue Chaojing 	if (!hwif->intr_regs_base) {
381905b464aSXue Chaojing 		dev_err(&pdev->dev, "Failed to map configuration regs\n");
382905b464aSXue Chaojing 		err = -ENOMEM;
383905b464aSXue Chaojing 		goto err_map_intr_bar;
384905b464aSXue Chaojing 	}
385905b464aSXue Chaojing 
38672ef908bSLuo bin 	err = wait_hwif_ready(hwif);
38751ba902aSAviad Krawczyk 	if (err) {
38851ba902aSAviad Krawczyk 		dev_err(&pdev->dev, "HW interface is not ready\n");
38990f86b8aSLuo bin 		__print_selftest_reg(hwif);
39051ba902aSAviad Krawczyk 		goto err_hwif_ready;
39151ba902aSAviad Krawczyk 	}
39251ba902aSAviad Krawczyk 
39351ba902aSAviad Krawczyk 	read_hwif_attr(hwif);
39451ba902aSAviad Krawczyk 
39551ba902aSAviad Krawczyk 	if (HINIC_IS_PF(hwif))
39651ba902aSAviad Krawczyk 		set_ppf(hwif);
39751ba902aSAviad Krawczyk 
39851ba902aSAviad Krawczyk 	/* No transactionss before DMA is initialized */
39951ba902aSAviad Krawczyk 	dma_attr_init(hwif);
40051ba902aSAviad Krawczyk 	return 0;
40151ba902aSAviad Krawczyk 
40251ba902aSAviad Krawczyk err_hwif_ready:
403905b464aSXue Chaojing 	iounmap(hwif->intr_regs_base);
404905b464aSXue Chaojing 
405905b464aSXue Chaojing err_map_intr_bar:
40651ba902aSAviad Krawczyk 	iounmap(hwif->cfg_regs_bar);
407905b464aSXue Chaojing 
40851ba902aSAviad Krawczyk 	return err;
40951ba902aSAviad Krawczyk }
41051ba902aSAviad Krawczyk 
41151ba902aSAviad Krawczyk /**
41251ba902aSAviad Krawczyk  * hinic_free_hwif - free the HW interface
41351ba902aSAviad Krawczyk  * @hwif: the HW interface of a pci function device
41451ba902aSAviad Krawczyk  **/
hinic_free_hwif(struct hinic_hwif * hwif)41551ba902aSAviad Krawczyk void hinic_free_hwif(struct hinic_hwif *hwif)
41651ba902aSAviad Krawczyk {
417905b464aSXue Chaojing 	iounmap(hwif->intr_regs_base);
41851ba902aSAviad Krawczyk 	iounmap(hwif->cfg_regs_bar);
41951ba902aSAviad Krawczyk }
420