1a5564e7eSAviad Krawczyk /*
2a5564e7eSAviad Krawczyk  * Huawei HiNIC PCI Express Linux driver
3a5564e7eSAviad Krawczyk  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4a5564e7eSAviad Krawczyk  *
5a5564e7eSAviad Krawczyk  * This program is free software; you can redistribute it and/or modify it
6a5564e7eSAviad Krawczyk  * under the terms and conditions of the GNU General Public License,
7a5564e7eSAviad Krawczyk  * version 2, as published by the Free Software Foundation.
8a5564e7eSAviad Krawczyk  *
9a5564e7eSAviad Krawczyk  * This program is distributed in the hope it will be useful, but WITHOUT
10a5564e7eSAviad Krawczyk  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11a5564e7eSAviad Krawczyk  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12a5564e7eSAviad Krawczyk  * for more details.
13a5564e7eSAviad Krawczyk  *
14a5564e7eSAviad Krawczyk  */
15a5564e7eSAviad Krawczyk 
16a5564e7eSAviad Krawczyk #ifndef HINIC_HW_EQS_H
17a5564e7eSAviad Krawczyk #define HINIC_HW_EQS_H
18a5564e7eSAviad Krawczyk 
19a5564e7eSAviad Krawczyk #include <linux/types.h>
20a5564e7eSAviad Krawczyk #include <linux/workqueue.h>
21a5564e7eSAviad Krawczyk #include <linux/pci.h>
22a5564e7eSAviad Krawczyk #include <linux/sizes.h>
23a5564e7eSAviad Krawczyk #include <linux/bitops.h>
24a5564e7eSAviad Krawczyk 
25a5564e7eSAviad Krawczyk #include "hinic_hw_if.h"
26a5564e7eSAviad Krawczyk 
27f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_INT_IDX_SHIFT          0
28f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_DMA_ATTR_SHIFT         12
29f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_SHIFT     20
30f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_INT_MODE_SHIFT         31
31f00fe738SAviad Krawczyk 
32f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_INT_IDX_MASK           0x3FF
33f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_DMA_ATTR_MASK          0x3F
34f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_PCI_INTF_IDX_MASK      0x3
35f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_INT_MODE_MASK          0x1
36f00fe738SAviad Krawczyk 
37f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_SET(val, member)       \
38f00fe738SAviad Krawczyk 			(((u32)(val) & HINIC_AEQ_CTRL_0_##member##_MASK) << \
39f00fe738SAviad Krawczyk 			 HINIC_AEQ_CTRL_0_##member##_SHIFT)
40f00fe738SAviad Krawczyk 
41f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_0_CLEAR(val, member)     \
42f00fe738SAviad Krawczyk 			((val) & (~(HINIC_AEQ_CTRL_0_##member##_MASK \
43f00fe738SAviad Krawczyk 			 << HINIC_AEQ_CTRL_0_##member##_SHIFT)))
44f00fe738SAviad Krawczyk 
45f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_LEN_SHIFT              0
46f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_ELEM_SIZE_SHIFT        24
47f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_PAGE_SIZE_SHIFT        28
48f00fe738SAviad Krawczyk 
49f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_LEN_MASK               0x1FFFFF
50f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_ELEM_SIZE_MASK         0x3
51f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_PAGE_SIZE_MASK         0xF
52f00fe738SAviad Krawczyk 
53f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_SET(val, member)       \
54f00fe738SAviad Krawczyk 			(((u32)(val) & HINIC_AEQ_CTRL_1_##member##_MASK) << \
55f00fe738SAviad Krawczyk 			 HINIC_AEQ_CTRL_1_##member##_SHIFT)
56f00fe738SAviad Krawczyk 
57f00fe738SAviad Krawczyk #define HINIC_AEQ_CTRL_1_CLEAR(val, member)     \
58f00fe738SAviad Krawczyk 			((val) & (~(HINIC_AEQ_CTRL_1_##member##_MASK \
59f00fe738SAviad Krawczyk 			 << HINIC_AEQ_CTRL_1_##member##_SHIFT)))
60f00fe738SAviad Krawczyk 
61f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_TYPE_SHIFT           0
62f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_SRC_SHIFT            7
63f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_SIZE_SHIFT           8
64f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_WRAPPED_SHIFT        31
65f00fe738SAviad Krawczyk 
66f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_TYPE_MASK            0x7F
67f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_SRC_MASK             0x1
68f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_SIZE_MASK            0xFF
69f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_WRAPPED_MASK         0x1
70f00fe738SAviad Krawczyk 
71f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_SET(val, member)     \
72f00fe738SAviad Krawczyk 			(((u32)(val) & HINIC_EQ_ELEM_DESC_##member##_MASK) << \
73f00fe738SAviad Krawczyk 			 HINIC_EQ_ELEM_DESC_##member##_SHIFT)
74f00fe738SAviad Krawczyk 
75f00fe738SAviad Krawczyk #define HINIC_EQ_ELEM_DESC_GET(val, member)     \
76f00fe738SAviad Krawczyk 			(((val) >> HINIC_EQ_ELEM_DESC_##member##_SHIFT) & \
77f00fe738SAviad Krawczyk 			 HINIC_EQ_ELEM_DESC_##member##_MASK)
78f00fe738SAviad Krawczyk 
79f00fe738SAviad Krawczyk #define HINIC_EQ_CI_IDX_SHIFT                   0
80f00fe738SAviad Krawczyk #define HINIC_EQ_CI_WRAPPED_SHIFT               20
81f00fe738SAviad Krawczyk #define HINIC_EQ_CI_XOR_CHKSUM_SHIFT            24
82f00fe738SAviad Krawczyk #define HINIC_EQ_CI_INT_ARMED_SHIFT             31
83f00fe738SAviad Krawczyk 
84f00fe738SAviad Krawczyk #define HINIC_EQ_CI_IDX_MASK                    0xFFFFF
85f00fe738SAviad Krawczyk #define HINIC_EQ_CI_WRAPPED_MASK                0x1
86f00fe738SAviad Krawczyk #define HINIC_EQ_CI_XOR_CHKSUM_MASK             0xF
87f00fe738SAviad Krawczyk #define HINIC_EQ_CI_INT_ARMED_MASK              0x1
88f00fe738SAviad Krawczyk 
89f00fe738SAviad Krawczyk #define HINIC_EQ_CI_SET(val, member)            \
90f00fe738SAviad Krawczyk 			(((u32)(val) & HINIC_EQ_CI_##member##_MASK) << \
91f00fe738SAviad Krawczyk 			 HINIC_EQ_CI_##member##_SHIFT)
92f00fe738SAviad Krawczyk 
93f00fe738SAviad Krawczyk #define HINIC_EQ_CI_CLEAR(val, member)          \
94f00fe738SAviad Krawczyk 			((val) & (~(HINIC_EQ_CI_##member##_MASK \
95f00fe738SAviad Krawczyk 			 << HINIC_EQ_CI_##member##_SHIFT)))
96f00fe738SAviad Krawczyk 
97a5564e7eSAviad Krawczyk #define HINIC_MAX_AEQS                  4
98a5564e7eSAviad Krawczyk 
99f00fe738SAviad Krawczyk #define HINIC_AEQE_SIZE                 64
100f00fe738SAviad Krawczyk 
101f00fe738SAviad Krawczyk #define HINIC_AEQE_DESC_SIZE            4
102f00fe738SAviad Krawczyk #define HINIC_AEQE_DATA_SIZE            \
103f00fe738SAviad Krawczyk 			(HINIC_AEQE_SIZE - HINIC_AEQE_DESC_SIZE)
104f00fe738SAviad Krawczyk 
105a5564e7eSAviad Krawczyk #define HINIC_DEFAULT_AEQ_LEN           64
106a5564e7eSAviad Krawczyk 
107a5564e7eSAviad Krawczyk #define HINIC_EQ_PAGE_SIZE              SZ_4K
108a5564e7eSAviad Krawczyk 
109d0b9805eSAviad Krawczyk #define HINIC_CEQ_ID_CMDQ               0
110d0b9805eSAviad Krawczyk 
111a5564e7eSAviad Krawczyk enum hinic_eq_type {
112a5564e7eSAviad Krawczyk 	HINIC_AEQ,
113a5564e7eSAviad Krawczyk };
114a5564e7eSAviad Krawczyk 
115a5564e7eSAviad Krawczyk enum hinic_aeq_type {
116a5564e7eSAviad Krawczyk 	HINIC_MSG_FROM_MGMT_CPU = 2,
117a5564e7eSAviad Krawczyk 
118a5564e7eSAviad Krawczyk 	HINIC_MAX_AEQ_EVENTS,
119a5564e7eSAviad Krawczyk };
120a5564e7eSAviad Krawczyk 
121a5564e7eSAviad Krawczyk enum hinic_eqe_state {
122a5564e7eSAviad Krawczyk 	HINIC_EQE_ENABLED = BIT(0),
123a5564e7eSAviad Krawczyk 	HINIC_EQE_RUNNING = BIT(1),
124a5564e7eSAviad Krawczyk };
125a5564e7eSAviad Krawczyk 
126f00fe738SAviad Krawczyk struct hinic_aeq_elem {
127f00fe738SAviad Krawczyk 	u8      data[HINIC_AEQE_DATA_SIZE];
128f00fe738SAviad Krawczyk 	u32     desc;
129f00fe738SAviad Krawczyk };
130f00fe738SAviad Krawczyk 
131a5564e7eSAviad Krawczyk struct hinic_eq_work {
132a5564e7eSAviad Krawczyk 	struct work_struct      work;
133a5564e7eSAviad Krawczyk 	void                    *data;
134a5564e7eSAviad Krawczyk };
135a5564e7eSAviad Krawczyk 
136a5564e7eSAviad Krawczyk struct hinic_eq {
137a5564e7eSAviad Krawczyk 	struct hinic_hwif       *hwif;
138a5564e7eSAviad Krawczyk 
139a5564e7eSAviad Krawczyk 	enum hinic_eq_type      type;
140a5564e7eSAviad Krawczyk 	int                     q_id;
141a5564e7eSAviad Krawczyk 	u32                     q_len;
142a5564e7eSAviad Krawczyk 	u32                     page_size;
143a5564e7eSAviad Krawczyk 
144a5564e7eSAviad Krawczyk 	u32                     cons_idx;
145a5564e7eSAviad Krawczyk 	int                     wrapped;
146a5564e7eSAviad Krawczyk 
147a5564e7eSAviad Krawczyk 	size_t                  elem_size;
148a5564e7eSAviad Krawczyk 	int                     num_pages;
149a5564e7eSAviad Krawczyk 	int                     num_elem_in_pg;
150a5564e7eSAviad Krawczyk 
151a5564e7eSAviad Krawczyk 	struct msix_entry       msix_entry;
152a5564e7eSAviad Krawczyk 
153a5564e7eSAviad Krawczyk 	dma_addr_t              *dma_addr;
154a5564e7eSAviad Krawczyk 	void                    **virt_addr;
155a5564e7eSAviad Krawczyk 
156a5564e7eSAviad Krawczyk 	struct hinic_eq_work    aeq_work;
157a5564e7eSAviad Krawczyk };
158a5564e7eSAviad Krawczyk 
159a5564e7eSAviad Krawczyk struct hinic_hw_event_cb {
160a5564e7eSAviad Krawczyk 	void    (*hwe_handler)(void *handle, void *data, u8 size);
161a5564e7eSAviad Krawczyk 	void                    *handle;
162a5564e7eSAviad Krawczyk 	unsigned long           hwe_state;
163a5564e7eSAviad Krawczyk };
164a5564e7eSAviad Krawczyk 
165a5564e7eSAviad Krawczyk struct hinic_aeqs {
166a5564e7eSAviad Krawczyk 	struct hinic_hwif       *hwif;
167a5564e7eSAviad Krawczyk 
168a5564e7eSAviad Krawczyk 	struct hinic_eq         aeq[HINIC_MAX_AEQS];
169a5564e7eSAviad Krawczyk 	int                     num_aeqs;
170a5564e7eSAviad Krawczyk 
171a5564e7eSAviad Krawczyk 	struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS];
172a5564e7eSAviad Krawczyk 
173a5564e7eSAviad Krawczyk 	struct workqueue_struct *workq;
174a5564e7eSAviad Krawczyk };
175a5564e7eSAviad Krawczyk 
176a5564e7eSAviad Krawczyk void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs,
177a5564e7eSAviad Krawczyk 			      enum hinic_aeq_type event, void *handle,
178a5564e7eSAviad Krawczyk 			      void (*hwe_handler)(void *handle, void *data,
179a5564e7eSAviad Krawczyk 						  u8 size));
180a5564e7eSAviad Krawczyk 
181a5564e7eSAviad Krawczyk void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs,
182a5564e7eSAviad Krawczyk 				enum hinic_aeq_type event);
183a5564e7eSAviad Krawczyk 
184a5564e7eSAviad Krawczyk int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif,
185a5564e7eSAviad Krawczyk 		    int num_aeqs, u32 q_len, u32 page_size,
186a5564e7eSAviad Krawczyk 		    struct msix_entry *msix_entries);
187a5564e7eSAviad Krawczyk 
188a5564e7eSAviad Krawczyk void hinic_aeqs_free(struct hinic_aeqs *aeqs);
189a5564e7eSAviad Krawczyk 
190a5564e7eSAviad Krawczyk #endif
191