xref: /openbmc/linux/drivers/dma/idxd/registers.h (revision e5acf9c8)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright(c) 2019 Intel Corporation. All rights rsvd. */
3 #ifndef _IDXD_REGISTERS_H_
4 #define _IDXD_REGISTERS_H_
5 
6 /* PCI Config */
7 #define PCI_DEVICE_ID_INTEL_DSA_SPR0	0x0b25
8 
9 #define IDXD_MMIO_BAR		0
10 #define IDXD_WQ_BAR		2
11 #define IDXD_PORTAL_SIZE	PAGE_SIZE
12 
13 /* MMIO Device BAR0 Registers */
14 #define IDXD_VER_OFFSET			0x00
15 #define IDXD_VER_MAJOR_MASK		0xf0
16 #define IDXD_VER_MINOR_MASK		0x0f
17 #define GET_IDXD_VER_MAJOR(x)		(((x) & IDXD_VER_MAJOR_MASK) >> 4)
18 #define GET_IDXD_VER_MINOR(x)		((x) & IDXD_VER_MINOR_MASK)
19 
20 union gen_cap_reg {
21 	struct {
22 		u64 block_on_fault:1;
23 		u64 overlap_copy:1;
24 		u64 cache_control_mem:1;
25 		u64 cache_control_cache:1;
26 		u64 rsvd:3;
27 		u64 int_handle_req:1;
28 		u64 dest_readback:1;
29 		u64 drain_readback:1;
30 		u64 rsvd2:6;
31 		u64 max_xfer_shift:5;
32 		u64 max_batch_shift:4;
33 		u64 max_ims_mult:6;
34 		u64 config_en:1;
35 		u64 max_descs_per_engine:8;
36 		u64 rsvd3:24;
37 	};
38 	u64 bits;
39 } __packed;
40 #define IDXD_GENCAP_OFFSET		0x10
41 
42 union wq_cap_reg {
43 	struct {
44 		u64 total_wq_size:16;
45 		u64 num_wqs:8;
46 		u64 wqcfg_size:4;
47 		u64 rsvd:20;
48 		u64 shared_mode:1;
49 		u64 dedicated_mode:1;
50 		u64 rsvd2:1;
51 		u64 priority:1;
52 		u64 occupancy:1;
53 		u64 occupancy_int:1;
54 		u64 rsvd3:10;
55 	};
56 	u64 bits;
57 } __packed;
58 #define IDXD_WQCAP_OFFSET		0x20
59 #define IDXD_WQCFG_MIN			5
60 
61 union group_cap_reg {
62 	struct {
63 		u64 num_groups:8;
64 		u64 total_tokens:8;
65 		u64 token_en:1;
66 		u64 token_limit:1;
67 		u64 rsvd:46;
68 	};
69 	u64 bits;
70 } __packed;
71 #define IDXD_GRPCAP_OFFSET		0x30
72 
73 union engine_cap_reg {
74 	struct {
75 		u64 num_engines:8;
76 		u64 rsvd:56;
77 	};
78 	u64 bits;
79 } __packed;
80 
81 #define IDXD_ENGCAP_OFFSET		0x38
82 
83 #define IDXD_OPCAP_NOOP			0x0001
84 #define IDXD_OPCAP_BATCH			0x0002
85 #define IDXD_OPCAP_MEMMOVE		0x0008
86 struct opcap {
87 	u64 bits[4];
88 };
89 
90 #define IDXD_OPCAP_OFFSET		0x40
91 
92 #define IDXD_TABLE_OFFSET		0x60
93 union offsets_reg {
94 	struct {
95 		u64 grpcfg:16;
96 		u64 wqcfg:16;
97 		u64 msix_perm:16;
98 		u64 ims:16;
99 		u64 perfmon:16;
100 		u64 rsvd:48;
101 	};
102 	u64 bits[2];
103 } __packed;
104 
105 #define IDXD_GENCFG_OFFSET		0x80
106 union gencfg_reg {
107 	struct {
108 		u32 token_limit:8;
109 		u32 rsvd:4;
110 		u32 user_int_en:1;
111 		u32 rsvd2:19;
112 	};
113 	u32 bits;
114 } __packed;
115 
116 #define IDXD_GENCTRL_OFFSET		0x88
117 union genctrl_reg {
118 	struct {
119 		u32 softerr_int_en:1;
120 		u32 rsvd:31;
121 	};
122 	u32 bits;
123 } __packed;
124 
125 #define IDXD_GENSTATS_OFFSET		0x90
126 union gensts_reg {
127 	struct {
128 		u32 state:2;
129 		u32 reset_type:2;
130 		u32 rsvd:28;
131 	};
132 	u32 bits;
133 } __packed;
134 
135 enum idxd_device_status_state {
136 	IDXD_DEVICE_STATE_DISABLED = 0,
137 	IDXD_DEVICE_STATE_ENABLED,
138 	IDXD_DEVICE_STATE_DRAIN,
139 	IDXD_DEVICE_STATE_HALT,
140 };
141 
142 enum idxd_device_reset_type {
143 	IDXD_DEVICE_RESET_SOFTWARE = 0,
144 	IDXD_DEVICE_RESET_FLR,
145 	IDXD_DEVICE_RESET_WARM,
146 	IDXD_DEVICE_RESET_COLD,
147 };
148 
149 #define IDXD_INTCAUSE_OFFSET		0x98
150 #define IDXD_INTC_ERR			0x01
151 #define IDXD_INTC_CMD			0x02
152 #define IDXD_INTC_OCCUPY			0x04
153 #define IDXD_INTC_PERFMON_OVFL		0x08
154 
155 #define IDXD_CMD_OFFSET			0xa0
156 union idxd_command_reg {
157 	struct {
158 		u32 operand:20;
159 		u32 cmd:5;
160 		u32 rsvd:6;
161 		u32 int_req:1;
162 	};
163 	u32 bits;
164 } __packed;
165 
166 enum idxd_cmd {
167 	IDXD_CMD_ENABLE_DEVICE = 1,
168 	IDXD_CMD_DISABLE_DEVICE,
169 	IDXD_CMD_DRAIN_ALL,
170 	IDXD_CMD_ABORT_ALL,
171 	IDXD_CMD_RESET_DEVICE,
172 	IDXD_CMD_ENABLE_WQ,
173 	IDXD_CMD_DISABLE_WQ,
174 	IDXD_CMD_DRAIN_WQ,
175 	IDXD_CMD_ABORT_WQ,
176 	IDXD_CMD_RESET_WQ,
177 	IDXD_CMD_DRAIN_PASID,
178 	IDXD_CMD_ABORT_PASID,
179 	IDXD_CMD_REQUEST_INT_HANDLE,
180 };
181 
182 #define IDXD_CMDSTS_OFFSET		0xa8
183 union cmdsts_reg {
184 	struct {
185 		u8 err;
186 		u16 result;
187 		u8 rsvd:7;
188 		u8 active:1;
189 	};
190 	u32 bits;
191 } __packed;
192 #define IDXD_CMDSTS_ACTIVE		0x80000000
193 
194 enum idxd_cmdsts_err {
195 	IDXD_CMDSTS_SUCCESS = 0,
196 	IDXD_CMDSTS_INVAL_CMD,
197 	IDXD_CMDSTS_INVAL_WQIDX,
198 	IDXD_CMDSTS_HW_ERR,
199 	/* enable device errors */
200 	IDXD_CMDSTS_ERR_DEV_ENABLED = 0x10,
201 	IDXD_CMDSTS_ERR_CONFIG,
202 	IDXD_CMDSTS_ERR_BUSMASTER_EN,
203 	IDXD_CMDSTS_ERR_PASID_INVAL,
204 	IDXD_CMDSTS_ERR_WQ_SIZE_ERANGE,
205 	IDXD_CMDSTS_ERR_GRP_CONFIG,
206 	IDXD_CMDSTS_ERR_GRP_CONFIG2,
207 	IDXD_CMDSTS_ERR_GRP_CONFIG3,
208 	IDXD_CMDSTS_ERR_GRP_CONFIG4,
209 	/* enable wq errors */
210 	IDXD_CMDSTS_ERR_DEV_NOTEN = 0x20,
211 	IDXD_CMDSTS_ERR_WQ_ENABLED,
212 	IDXD_CMDSTS_ERR_WQ_SIZE,
213 	IDXD_CMDSTS_ERR_WQ_PRIOR,
214 	IDXD_CMDSTS_ERR_WQ_MODE,
215 	IDXD_CMDSTS_ERR_BOF_EN,
216 	IDXD_CMDSTS_ERR_PASID_EN,
217 	IDXD_CMDSTS_ERR_MAX_BATCH_SIZE,
218 	IDXD_CMDSTS_ERR_MAX_XFER_SIZE,
219 	/* disable device errors */
220 	IDXD_CMDSTS_ERR_DIS_DEV_EN = 0x31,
221 	/* disable WQ, drain WQ, abort WQ, reset WQ */
222 	IDXD_CMDSTS_ERR_DEV_NOT_EN,
223 	/* request interrupt handle */
224 	IDXD_CMDSTS_ERR_INVAL_INT_IDX = 0x41,
225 	IDXD_CMDSTS_ERR_NO_HANDLE,
226 };
227 
228 #define IDXD_SWERR_OFFSET		0xc0
229 #define IDXD_SWERR_VALID		0x00000001
230 #define IDXD_SWERR_OVERFLOW		0x00000002
231 #define IDXD_SWERR_ACK			(IDXD_SWERR_VALID | IDXD_SWERR_OVERFLOW)
232 union sw_err_reg {
233 	struct {
234 		u64 valid:1;
235 		u64 overflow:1;
236 		u64 desc_valid:1;
237 		u64 wq_idx_valid:1;
238 		u64 batch:1;
239 		u64 fault_rw:1;
240 		u64 priv:1;
241 		u64 rsvd:1;
242 		u64 error:8;
243 		u64 wq_idx:8;
244 		u64 rsvd2:8;
245 		u64 operation:8;
246 		u64 pasid:20;
247 		u64 rsvd3:4;
248 
249 		u64 batch_idx:16;
250 		u64 rsvd4:16;
251 		u64 invalid_flags:32;
252 
253 		u64 fault_addr;
254 
255 		u64 rsvd5;
256 	};
257 	u64 bits[4];
258 } __packed;
259 
260 union msix_perm {
261 	struct {
262 		u32 rsvd:2;
263 		u32 ignore:1;
264 		u32 pasid_en:1;
265 		u32 rsvd2:8;
266 		u32 pasid:20;
267 	};
268 	u32 bits;
269 } __packed;
270 
271 union group_flags {
272 	struct {
273 		u32 tc_a:3;
274 		u32 tc_b:3;
275 		u32 rsvd:1;
276 		u32 use_token_limit:1;
277 		u32 tokens_reserved:8;
278 		u32 rsvd2:4;
279 		u32 tokens_allowed:8;
280 		u32 rsvd3:4;
281 	};
282 	u32 bits;
283 } __packed;
284 
285 struct grpcfg {
286 	u64 wqs[4];
287 	u64 engines;
288 	union group_flags flags;
289 } __packed;
290 
291 union wqcfg {
292 	struct {
293 		/* bytes 0-3 */
294 		u16 wq_size;
295 		u16 rsvd;
296 
297 		/* bytes 4-7 */
298 		u16 wq_thresh;
299 		u16 rsvd1;
300 
301 		/* bytes 8-11 */
302 		u32 mode:1;	/* shared or dedicated */
303 		u32 bof:1;	/* block on fault */
304 		u32 rsvd2:2;
305 		u32 priority:4;
306 		u32 pasid:20;
307 		u32 pasid_en:1;
308 		u32 priv:1;
309 		u32 rsvd3:2;
310 
311 		/* bytes 12-15 */
312 		u32 max_xfer_shift:5;
313 		u32 max_batch_shift:4;
314 		u32 rsvd4:23;
315 
316 		/* bytes 16-19 */
317 		u16 occupancy_inth;
318 		u16 occupancy_table_sel:1;
319 		u16 rsvd5:15;
320 
321 		/* bytes 20-23 */
322 		u16 occupancy_limit;
323 		u16 occupancy_int_en:1;
324 		u16 rsvd6:15;
325 
326 		/* bytes 24-27 */
327 		u16 occupancy;
328 		u16 occupancy_int:1;
329 		u16 rsvd7:12;
330 		u16 mode_support:1;
331 		u16 wq_state:2;
332 
333 		/* bytes 28-31 */
334 		u32 rsvd8;
335 	};
336 	u32 bits[8];
337 } __packed;
338 
339 /*
340  * This macro calculates the offset into the WQCFG register
341  * idxd - struct idxd *
342  * n - wq id
343  * ofs - the index of the 32b dword for the config register
344  *
345  * The WQCFG register block is divided into groups per each wq. The n index
346  * allows us to move to the register group that's for that particular wq.
347  * Each register is 32bits. The ofs gives us the number of register to access.
348  */
349 #define WQCFG_OFFSET(_idxd_dev, n, ofs) \
350 ({\
351 	typeof(_idxd_dev) __idxd_dev = (_idxd_dev);	\
352 	(__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs);	\
353 })
354 
355 #define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32))
356 
357 #endif
358