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 
109a5564e7eSAviad Krawczyk enum hinic_eq_type {
110a5564e7eSAviad Krawczyk 	HINIC_AEQ,
111a5564e7eSAviad Krawczyk };
112a5564e7eSAviad Krawczyk 
113a5564e7eSAviad Krawczyk enum hinic_aeq_type {
114a5564e7eSAviad Krawczyk 	HINIC_MSG_FROM_MGMT_CPU = 2,
115a5564e7eSAviad Krawczyk 
116a5564e7eSAviad Krawczyk 	HINIC_MAX_AEQ_EVENTS,
117a5564e7eSAviad Krawczyk };
118a5564e7eSAviad Krawczyk 
119a5564e7eSAviad Krawczyk enum hinic_eqe_state {
120a5564e7eSAviad Krawczyk 	HINIC_EQE_ENABLED = BIT(0),
121a5564e7eSAviad Krawczyk 	HINIC_EQE_RUNNING = BIT(1),
122a5564e7eSAviad Krawczyk };
123a5564e7eSAviad Krawczyk 
124f00fe738SAviad Krawczyk struct hinic_aeq_elem {
125f00fe738SAviad Krawczyk 	u8      data[HINIC_AEQE_DATA_SIZE];
126f00fe738SAviad Krawczyk 	u32     desc;
127f00fe738SAviad Krawczyk };
128f00fe738SAviad Krawczyk 
129a5564e7eSAviad Krawczyk struct hinic_eq_work {
130a5564e7eSAviad Krawczyk 	struct work_struct      work;
131a5564e7eSAviad Krawczyk 	void                    *data;
132a5564e7eSAviad Krawczyk };
133a5564e7eSAviad Krawczyk 
134a5564e7eSAviad Krawczyk struct hinic_eq {
135a5564e7eSAviad Krawczyk 	struct hinic_hwif       *hwif;
136a5564e7eSAviad Krawczyk 
137a5564e7eSAviad Krawczyk 	enum hinic_eq_type      type;
138a5564e7eSAviad Krawczyk 	int                     q_id;
139a5564e7eSAviad Krawczyk 	u32                     q_len;
140a5564e7eSAviad Krawczyk 	u32                     page_size;
141a5564e7eSAviad Krawczyk 
142a5564e7eSAviad Krawczyk 	u32                     cons_idx;
143a5564e7eSAviad Krawczyk 	int                     wrapped;
144a5564e7eSAviad Krawczyk 
145a5564e7eSAviad Krawczyk 	size_t                  elem_size;
146a5564e7eSAviad Krawczyk 	int                     num_pages;
147a5564e7eSAviad Krawczyk 	int                     num_elem_in_pg;
148a5564e7eSAviad Krawczyk 
149a5564e7eSAviad Krawczyk 	struct msix_entry       msix_entry;
150a5564e7eSAviad Krawczyk 
151a5564e7eSAviad Krawczyk 	dma_addr_t              *dma_addr;
152a5564e7eSAviad Krawczyk 	void                    **virt_addr;
153a5564e7eSAviad Krawczyk 
154a5564e7eSAviad Krawczyk 	struct hinic_eq_work    aeq_work;
155a5564e7eSAviad Krawczyk };
156a5564e7eSAviad Krawczyk 
157a5564e7eSAviad Krawczyk struct hinic_hw_event_cb {
158a5564e7eSAviad Krawczyk 	void    (*hwe_handler)(void *handle, void *data, u8 size);
159a5564e7eSAviad Krawczyk 	void                    *handle;
160a5564e7eSAviad Krawczyk 	unsigned long           hwe_state;
161a5564e7eSAviad Krawczyk };
162a5564e7eSAviad Krawczyk 
163a5564e7eSAviad Krawczyk struct hinic_aeqs {
164a5564e7eSAviad Krawczyk 	struct hinic_hwif       *hwif;
165a5564e7eSAviad Krawczyk 
166a5564e7eSAviad Krawczyk 	struct hinic_eq         aeq[HINIC_MAX_AEQS];
167a5564e7eSAviad Krawczyk 	int                     num_aeqs;
168a5564e7eSAviad Krawczyk 
169a5564e7eSAviad Krawczyk 	struct hinic_hw_event_cb hwe_cb[HINIC_MAX_AEQ_EVENTS];
170a5564e7eSAviad Krawczyk 
171a5564e7eSAviad Krawczyk 	struct workqueue_struct *workq;
172a5564e7eSAviad Krawczyk };
173a5564e7eSAviad Krawczyk 
174a5564e7eSAviad Krawczyk void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs,
175a5564e7eSAviad Krawczyk 			      enum hinic_aeq_type event, void *handle,
176a5564e7eSAviad Krawczyk 			      void (*hwe_handler)(void *handle, void *data,
177a5564e7eSAviad Krawczyk 						  u8 size));
178a5564e7eSAviad Krawczyk 
179a5564e7eSAviad Krawczyk void hinic_aeq_unregister_hw_cb(struct hinic_aeqs *aeqs,
180a5564e7eSAviad Krawczyk 				enum hinic_aeq_type event);
181a5564e7eSAviad Krawczyk 
182a5564e7eSAviad Krawczyk int hinic_aeqs_init(struct hinic_aeqs *aeqs, struct hinic_hwif *hwif,
183a5564e7eSAviad Krawczyk 		    int num_aeqs, u32 q_len, u32 page_size,
184a5564e7eSAviad Krawczyk 		    struct msix_entry *msix_entries);
185a5564e7eSAviad Krawczyk 
186a5564e7eSAviad Krawczyk void hinic_aeqs_free(struct hinic_aeqs *aeqs);
187a5564e7eSAviad Krawczyk 
188a5564e7eSAviad Krawczyk #endif
189