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