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