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
20union 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
42union 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
61union 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
73union 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
86struct opcap {
87	u64 bits[4];
88};
89
90#define IDXD_OPCAP_OFFSET		0x40
91
92#define IDXD_TABLE_OFFSET		0x60
93union 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
106union 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
117union 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
126union gensts_reg {
127	struct {
128		u32 state:2;
129		u32 reset_type:2;
130		u32 rsvd:28;
131	};
132	u32 bits;
133} __packed;
134
135enum 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
142enum 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
156union 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
166enum 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
183union 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
194enum 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)
232union 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
260union 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
271union 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
285struct grpcfg {
286	u64 wqs[4];
287	u64 engines;
288	union group_flags flags;
289} __packed;
290
291union 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