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 #define PCI_DEVICE_ID_INTEL_IAX_SPR0	0x0cfe
9 
10 #define DEVICE_VERSION_1		0x100
11 #define DEVICE_VERSION_2		0x200
12 
13 #define IDXD_MMIO_BAR		0
14 #define IDXD_WQ_BAR		2
15 #define IDXD_PORTAL_SIZE	PAGE_SIZE
16 
17 /* MMIO Device BAR0 Registers */
18 #define IDXD_VER_OFFSET			0x00
19 #define IDXD_VER_MAJOR_MASK		0xf0
20 #define IDXD_VER_MINOR_MASK		0x0f
21 #define GET_IDXD_VER_MAJOR(x)		(((x) & IDXD_VER_MAJOR_MASK) >> 4)
22 #define GET_IDXD_VER_MINOR(x)		((x) & IDXD_VER_MINOR_MASK)
23 
24 union gen_cap_reg {
25 	struct {
26 		u64 block_on_fault:1;
27 		u64 overlap_copy:1;
28 		u64 cache_control_mem:1;
29 		u64 cache_control_cache:1;
30 		u64 cmd_cap:1;
31 		u64 rsvd:3;
32 		u64 dest_readback:1;
33 		u64 drain_readback:1;
34 		u64 rsvd2:6;
35 		u64 max_xfer_shift:5;
36 		u64 max_batch_shift:4;
37 		u64 max_ims_mult:6;
38 		u64 config_en:1;
39 		u64 rsvd3:32;
40 	};
41 	u64 bits;
42 } __packed;
43 #define IDXD_GENCAP_OFFSET		0x10
44 
45 union wq_cap_reg {
46 	struct {
47 		u64 total_wq_size:16;
48 		u64 num_wqs:8;
49 		u64 wqcfg_size:4;
50 		u64 rsvd:20;
51 		u64 shared_mode:1;
52 		u64 dedicated_mode:1;
53 		u64 wq_ats_support:1;
54 		u64 priority:1;
55 		u64 occupancy:1;
56 		u64 occupancy_int:1;
57 		u64 rsvd3:10;
58 	};
59 	u64 bits;
60 } __packed;
61 #define IDXD_WQCAP_OFFSET		0x20
62 #define IDXD_WQCFG_MIN			5
63 
64 union group_cap_reg {
65 	struct {
66 		u64 num_groups:8;
67 		u64 total_rdbufs:8;	/* formerly total_tokens */
68 		u64 rdbuf_ctrl:1;	/* formerly token_en */
69 		u64 rdbuf_limit:1;	/* formerly token_limit */
70 		u64 rsvd:46;
71 	};
72 	u64 bits;
73 } __packed;
74 #define IDXD_GRPCAP_OFFSET		0x30
75 
76 union engine_cap_reg {
77 	struct {
78 		u64 num_engines:8;
79 		u64 rsvd:56;
80 	};
81 	u64 bits;
82 } __packed;
83 
84 #define IDXD_ENGCAP_OFFSET		0x38
85 
86 #define IDXD_OPCAP_NOOP			0x0001
87 #define IDXD_OPCAP_BATCH			0x0002
88 #define IDXD_OPCAP_MEMMOVE		0x0008
89 struct opcap {
90 	u64 bits[4];
91 };
92 
93 #define IDXD_OPCAP_OFFSET		0x40
94 
95 #define IDXD_TABLE_OFFSET		0x60
96 union offsets_reg {
97 	struct {
98 		u64 grpcfg:16;
99 		u64 wqcfg:16;
100 		u64 msix_perm:16;
101 		u64 ims:16;
102 		u64 perfmon:16;
103 		u64 rsvd:48;
104 	};
105 	u64 bits[2];
106 } __packed;
107 
108 #define IDXD_TABLE_MULT			0x100
109 
110 #define IDXD_GENCFG_OFFSET		0x80
111 union gencfg_reg {
112 	struct {
113 		u32 rdbuf_limit:8;
114 		u32 rsvd:4;
115 		u32 user_int_en:1;
116 		u32 rsvd2:19;
117 	};
118 	u32 bits;
119 } __packed;
120 
121 #define IDXD_GENCTRL_OFFSET		0x88
122 union genctrl_reg {
123 	struct {
124 		u32 softerr_int_en:1;
125 		u32 halt_int_en:1;
126 		u32 rsvd:30;
127 	};
128 	u32 bits;
129 } __packed;
130 
131 #define IDXD_GENSTATS_OFFSET		0x90
132 union gensts_reg {
133 	struct {
134 		u32 state:2;
135 		u32 reset_type:2;
136 		u32 rsvd:28;
137 	};
138 	u32 bits;
139 } __packed;
140 
141 enum idxd_device_status_state {
142 	IDXD_DEVICE_STATE_DISABLED = 0,
143 	IDXD_DEVICE_STATE_ENABLED,
144 	IDXD_DEVICE_STATE_DRAIN,
145 	IDXD_DEVICE_STATE_HALT,
146 };
147 
148 enum idxd_device_reset_type {
149 	IDXD_DEVICE_RESET_SOFTWARE = 0,
150 	IDXD_DEVICE_RESET_FLR,
151 	IDXD_DEVICE_RESET_WARM,
152 	IDXD_DEVICE_RESET_COLD,
153 };
154 
155 #define IDXD_INTCAUSE_OFFSET		0x98
156 #define IDXD_INTC_ERR			0x01
157 #define IDXD_INTC_CMD			0x02
158 #define IDXD_INTC_OCCUPY			0x04
159 #define IDXD_INTC_PERFMON_OVFL		0x08
160 #define IDXD_INTC_HALT_STATE		0x10
161 #define IDXD_INTC_INT_HANDLE_REVOKED	0x80000000
162 
163 #define IDXD_CMD_OFFSET			0xa0
164 union idxd_command_reg {
165 	struct {
166 		u32 operand:20;
167 		u32 cmd:5;
168 		u32 rsvd:6;
169 		u32 int_req:1;
170 	};
171 	u32 bits;
172 } __packed;
173 
174 enum idxd_cmd {
175 	IDXD_CMD_ENABLE_DEVICE = 1,
176 	IDXD_CMD_DISABLE_DEVICE,
177 	IDXD_CMD_DRAIN_ALL,
178 	IDXD_CMD_ABORT_ALL,
179 	IDXD_CMD_RESET_DEVICE,
180 	IDXD_CMD_ENABLE_WQ,
181 	IDXD_CMD_DISABLE_WQ,
182 	IDXD_CMD_DRAIN_WQ,
183 	IDXD_CMD_ABORT_WQ,
184 	IDXD_CMD_RESET_WQ,
185 	IDXD_CMD_DRAIN_PASID,
186 	IDXD_CMD_ABORT_PASID,
187 	IDXD_CMD_REQUEST_INT_HANDLE,
188 	IDXD_CMD_RELEASE_INT_HANDLE,
189 };
190 
191 #define CMD_INT_HANDLE_IMS		0x10000
192 
193 #define IDXD_CMDSTS_OFFSET		0xa8
194 union cmdsts_reg {
195 	struct {
196 		u8 err;
197 		u16 result;
198 		u8 rsvd:7;
199 		u8 active:1;
200 	};
201 	u32 bits;
202 } __packed;
203 #define IDXD_CMDSTS_ACTIVE		0x80000000
204 #define IDXD_CMDSTS_ERR_MASK		0xff
205 #define IDXD_CMDSTS_RES_SHIFT		8
206 
207 enum idxd_cmdsts_err {
208 	IDXD_CMDSTS_SUCCESS = 0,
209 	IDXD_CMDSTS_INVAL_CMD,
210 	IDXD_CMDSTS_INVAL_WQIDX,
211 	IDXD_CMDSTS_HW_ERR,
212 	/* enable device errors */
213 	IDXD_CMDSTS_ERR_DEV_ENABLED = 0x10,
214 	IDXD_CMDSTS_ERR_CONFIG,
215 	IDXD_CMDSTS_ERR_BUSMASTER_EN,
216 	IDXD_CMDSTS_ERR_PASID_INVAL,
217 	IDXD_CMDSTS_ERR_WQ_SIZE_ERANGE,
218 	IDXD_CMDSTS_ERR_GRP_CONFIG,
219 	IDXD_CMDSTS_ERR_GRP_CONFIG2,
220 	IDXD_CMDSTS_ERR_GRP_CONFIG3,
221 	IDXD_CMDSTS_ERR_GRP_CONFIG4,
222 	/* enable wq errors */
223 	IDXD_CMDSTS_ERR_DEV_NOTEN = 0x20,
224 	IDXD_CMDSTS_ERR_WQ_ENABLED,
225 	IDXD_CMDSTS_ERR_WQ_SIZE,
226 	IDXD_CMDSTS_ERR_WQ_PRIOR,
227 	IDXD_CMDSTS_ERR_WQ_MODE,
228 	IDXD_CMDSTS_ERR_BOF_EN,
229 	IDXD_CMDSTS_ERR_PASID_EN,
230 	IDXD_CMDSTS_ERR_MAX_BATCH_SIZE,
231 	IDXD_CMDSTS_ERR_MAX_XFER_SIZE,
232 	/* disable device errors */
233 	IDXD_CMDSTS_ERR_DIS_DEV_EN = 0x31,
234 	/* disable WQ, drain WQ, abort WQ, reset WQ */
235 	IDXD_CMDSTS_ERR_DEV_NOT_EN,
236 	/* request interrupt handle */
237 	IDXD_CMDSTS_ERR_INVAL_INT_IDX = 0x41,
238 	IDXD_CMDSTS_ERR_NO_HANDLE,
239 };
240 
241 #define IDXD_CMDCAP_OFFSET		0xb0
242 
243 #define IDXD_SWERR_OFFSET		0xc0
244 #define IDXD_SWERR_VALID		0x00000001
245 #define IDXD_SWERR_OVERFLOW		0x00000002
246 #define IDXD_SWERR_ACK			(IDXD_SWERR_VALID | IDXD_SWERR_OVERFLOW)
247 union sw_err_reg {
248 	struct {
249 		u64 valid:1;
250 		u64 overflow:1;
251 		u64 desc_valid:1;
252 		u64 wq_idx_valid:1;
253 		u64 batch:1;
254 		u64 fault_rw:1;
255 		u64 priv:1;
256 		u64 rsvd:1;
257 		u64 error:8;
258 		u64 wq_idx:8;
259 		u64 rsvd2:8;
260 		u64 operation:8;
261 		u64 pasid:20;
262 		u64 rsvd3:4;
263 
264 		u64 batch_idx:16;
265 		u64 rsvd4:16;
266 		u64 invalid_flags:32;
267 
268 		u64 fault_addr;
269 
270 		u64 rsvd5;
271 	};
272 	u64 bits[4];
273 } __packed;
274 
275 union msix_perm {
276 	struct {
277 		u32 rsvd:2;
278 		u32 ignore:1;
279 		u32 pasid_en:1;
280 		u32 rsvd2:8;
281 		u32 pasid:20;
282 	};
283 	u32 bits;
284 } __packed;
285 
286 union group_flags {
287 	struct {
288 		u32 tc_a:3;
289 		u32 tc_b:3;
290 		u32 rsvd:1;
291 		u32 use_rdbuf_limit:1;
292 		u32 rdbufs_reserved:8;
293 		u32 rsvd2:4;
294 		u32 rdbufs_allowed:8;
295 		u32 rsvd3:4;
296 	};
297 	u32 bits;
298 } __packed;
299 
300 struct grpcfg {
301 	u64 wqs[4];
302 	u64 engines;
303 	union group_flags flags;
304 } __packed;
305 
306 union wqcfg {
307 	struct {
308 		/* bytes 0-3 */
309 		u16 wq_size;
310 		u16 rsvd;
311 
312 		/* bytes 4-7 */
313 		u16 wq_thresh;
314 		u16 rsvd1;
315 
316 		/* bytes 8-11 */
317 		u32 mode:1;	/* shared or dedicated */
318 		u32 bof:1;	/* block on fault */
319 		u32 wq_ats_disable:1;
320 		u32 rsvd2:1;
321 		u32 priority:4;
322 		u32 pasid:20;
323 		u32 pasid_en:1;
324 		u32 priv:1;
325 		u32 rsvd3:2;
326 
327 		/* bytes 12-15 */
328 		u32 max_xfer_shift:5;
329 		u32 max_batch_shift:4;
330 		u32 rsvd4:23;
331 
332 		/* bytes 16-19 */
333 		u16 occupancy_inth;
334 		u16 occupancy_table_sel:1;
335 		u16 rsvd5:15;
336 
337 		/* bytes 20-23 */
338 		u16 occupancy_limit;
339 		u16 occupancy_int_en:1;
340 		u16 rsvd6:15;
341 
342 		/* bytes 24-27 */
343 		u16 occupancy;
344 		u16 occupancy_int:1;
345 		u16 rsvd7:12;
346 		u16 mode_support:1;
347 		u16 wq_state:2;
348 
349 		/* bytes 28-31 */
350 		u32 rsvd8;
351 	};
352 	u32 bits[8];
353 } __packed;
354 
355 #define WQCFG_PASID_IDX                2
356 #define WQCFG_PRIVL_IDX		2
357 #define WQCFG_OCCUP_IDX		6
358 
359 #define WQCFG_OCCUP_MASK	0xffff
360 
361 /*
362  * This macro calculates the offset into the WQCFG register
363  * idxd - struct idxd *
364  * n - wq id
365  * ofs - the index of the 32b dword for the config register
366  *
367  * The WQCFG register block is divided into groups per each wq. The n index
368  * allows us to move to the register group that's for that particular wq.
369  * Each register is 32bits. The ofs gives us the number of register to access.
370  */
371 #define WQCFG_OFFSET(_idxd_dev, n, ofs) \
372 ({\
373 	typeof(_idxd_dev) __idxd_dev = (_idxd_dev);	\
374 	(__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs);	\
375 })
376 
377 #define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32))
378 
379 #define GRPCFG_SIZE		64
380 #define GRPWQCFG_STRIDES	4
381 
382 /*
383  * This macro calculates the offset into the GRPCFG register
384  * idxd - struct idxd *
385  * n - wq id
386  * ofs - the index of the 32b dword for the config register
387  *
388  * The WQCFG register block is divided into groups per each wq. The n index
389  * allows us to move to the register group that's for that particular wq.
390  * Each register is 32bits. The ofs gives us the number of register to access.
391  */
392 #define GRPWQCFG_OFFSET(idxd_dev, n, ofs) ((idxd_dev)->grpcfg_offset +\
393 					   (n) * GRPCFG_SIZE + sizeof(u64) * (ofs))
394 #define GRPENGCFG_OFFSET(idxd_dev, n) ((idxd_dev)->grpcfg_offset + (n) * GRPCFG_SIZE + 32)
395 #define GRPFLGCFG_OFFSET(idxd_dev, n) ((idxd_dev)->grpcfg_offset + (n) * GRPCFG_SIZE + 40)
396 
397 /* Following is performance monitor registers */
398 #define IDXD_PERFCAP_OFFSET		0x0
399 union idxd_perfcap {
400 	struct {
401 		u64 num_perf_counter:6;
402 		u64 rsvd1:2;
403 		u64 counter_width:8;
404 		u64 num_event_category:4;
405 		u64 global_event_category:16;
406 		u64 filter:8;
407 		u64 rsvd2:8;
408 		u64 cap_per_counter:1;
409 		u64 writeable_counter:1;
410 		u64 counter_freeze:1;
411 		u64 overflow_interrupt:1;
412 		u64 rsvd3:8;
413 	};
414 	u64 bits;
415 } __packed;
416 
417 #define IDXD_EVNTCAP_OFFSET		0x80
418 union idxd_evntcap {
419 	struct {
420 		u64 events:28;
421 		u64 rsvd:36;
422 	};
423 	u64 bits;
424 } __packed;
425 
426 struct idxd_event {
427 	union {
428 		struct {
429 			u32 event_category:4;
430 			u32 events:28;
431 		};
432 		u32 val;
433 	};
434 } __packed;
435 
436 #define IDXD_CNTRCAP_OFFSET		0x800
437 struct idxd_cntrcap {
438 	union {
439 		struct {
440 			u32 counter_width:8;
441 			u32 rsvd:20;
442 			u32 num_events:4;
443 		};
444 		u32 val;
445 	};
446 	struct idxd_event events[];
447 } __packed;
448 
449 #define IDXD_PERFRST_OFFSET		0x10
450 union idxd_perfrst {
451 	struct {
452 		u32 perfrst_config:1;
453 		u32 perfrst_counter:1;
454 		u32 rsvd:30;
455 	};
456 	u32 val;
457 } __packed;
458 
459 #define IDXD_OVFSTATUS_OFFSET		0x30
460 #define IDXD_PERFFRZ_OFFSET		0x20
461 #define IDXD_CNTRCFG_OFFSET		0x100
462 union idxd_cntrcfg {
463 	struct {
464 		u64 enable:1;
465 		u64 interrupt_ovf:1;
466 		u64 global_freeze_ovf:1;
467 		u64 rsvd1:5;
468 		u64 event_category:4;
469 		u64 rsvd2:20;
470 		u64 events:28;
471 		u64 rsvd3:4;
472 	};
473 	u64 val;
474 } __packed;
475 
476 #define IDXD_FLTCFG_OFFSET		0x300
477 
478 #define IDXD_CNTRDATA_OFFSET		0x200
479 union idxd_cntrdata {
480 	struct {
481 		u64 event_count_value;
482 	};
483 	u64 val;
484 } __packed;
485 
486 union event_cfg {
487 	struct {
488 		u64 event_cat:4;
489 		u64 event_enc:28;
490 	};
491 	u64 val;
492 } __packed;
493 
494 union filter_cfg {
495 	struct {
496 		u64 wq:32;
497 		u64 tc:8;
498 		u64 pg_sz:4;
499 		u64 xfer_sz:8;
500 		u64 eng:8;
501 	};
502 	u64 val;
503 } __packed;
504 
505 #endif
506