summaryrefslogtreecommitdiff
path: root/drivers/dma/amd/qdma/qdma.h
blob: 94089f1f0c115f5c89b3ffc5f543f4694dd3ba15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * DMA header for AMD Queue-based DMA Subsystem
 *
 * Copyright (C) 2023-2024, Advanced Micro Devices, Inc.
 */

#ifndef __QDMA_H
#define __QDMA_H

#include <linux/bitfield.h>
#include <linux/dmaengine.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#include "../../virt-dma.h"

#define DISABLE					0
#define ENABLE					1

#define QDMA_MIN_IRQ				3
#define QDMA_INTR_NAME_MAX_LEN			30
#define QDMA_INTR_PREFIX			"amd-qdma"

#define QDMA_IDENTIFIER				0x1FD3
#define QDMA_DEFAULT_RING_SIZE			(BIT(10) + 1)
#define QDMA_DEFAULT_RING_ID			0
#define QDMA_POLL_INTRVL_US			10		/* 10us */
#define QDMA_POLL_TIMEOUT_US			(500 * 1000)	/* 500ms */
#define QDMA_DMAP_REG_STRIDE			16
#define QDMA_CTXT_REGMAP_LEN			8		/* 8 regs */
#define QDMA_MM_DESC_SIZE			32		/* Bytes */
#define QDMA_MM_DESC_LEN_BITS			28
#define QDMA_MM_DESC_MAX_LEN			(BIT(QDMA_MM_DESC_LEN_BITS) - 1)
#define QDMA_MIN_DMA_ALLOC_SIZE			4096
#define QDMA_INTR_RING_SIZE			BIT(13)
#define QDMA_INTR_RING_IDX_MASK			GENMASK(9, 0)
#define QDMA_INTR_RING_BASE(_addr)		((_addr) >> 12)

#define QDMA_IDENTIFIER_REGOFF			0x0
#define QDMA_IDENTIFIER_MASK			GENMASK(31, 16)
#define QDMA_QUEUE_ARM_BIT			BIT(16)

#define qdma_err(qdev, fmt, args...)					\
	dev_err(&(qdev)->pdev->dev, fmt, ##args)

#define qdma_dbg(qdev, fmt, args...)					\
	dev_dbg(&(qdev)->pdev->dev, fmt, ##args)

#define qdma_info(qdev, fmt, args...)					\
	dev_info(&(qdev)->pdev->dev, fmt, ##args)

enum qdma_reg_fields {
	QDMA_REGF_IRQ_ENABLE,
	QDMA_REGF_WBK_ENABLE,
	QDMA_REGF_WBI_CHECK,
	QDMA_REGF_IRQ_ARM,
	QDMA_REGF_IRQ_VEC,
	QDMA_REGF_IRQ_AGG,
	QDMA_REGF_WBI_INTVL_ENABLE,
	QDMA_REGF_MRKR_DISABLE,
	QDMA_REGF_QUEUE_ENABLE,
	QDMA_REGF_QUEUE_MODE,
	QDMA_REGF_DESC_BASE,
	QDMA_REGF_DESC_SIZE,
	QDMA_REGF_RING_ID,
	QDMA_REGF_CMD_INDX,
	QDMA_REGF_CMD_CMD,
	QDMA_REGF_CMD_TYPE,
	QDMA_REGF_CMD_BUSY,
	QDMA_REGF_QUEUE_COUNT,
	QDMA_REGF_QUEUE_MAX,
	QDMA_REGF_QUEUE_BASE,
	QDMA_REGF_FUNCTION_ID,
	QDMA_REGF_INTR_AGG_BASE,
	QDMA_REGF_INTR_VECTOR,
	QDMA_REGF_INTR_SIZE,
	QDMA_REGF_INTR_VALID,
	QDMA_REGF_INTR_COLOR,
	QDMA_REGF_INTR_FUNCTION_ID,
	QDMA_REGF_ERR_INT_FUNC,
	QDMA_REGF_ERR_INT_VEC,
	QDMA_REGF_ERR_INT_ARM,
	QDMA_REGF_MAX
};

enum qdma_regs {
	QDMA_REGO_CTXT_DATA,
	QDMA_REGO_CTXT_CMD,
	QDMA_REGO_CTXT_MASK,
	QDMA_REGO_MM_H2C_CTRL,
	QDMA_REGO_MM_C2H_CTRL,
	QDMA_REGO_QUEUE_COUNT,
	QDMA_REGO_RING_SIZE,
	QDMA_REGO_H2C_PIDX,
	QDMA_REGO_C2H_PIDX,
	QDMA_REGO_INTR_CIDX,
	QDMA_REGO_FUNC_ID,
	QDMA_REGO_ERR_INT,
	QDMA_REGO_ERR_STAT,
	QDMA_REGO_MAX
};

struct qdma_reg_field {
	u16 lsb; /* Least significant bit of field */
	u16 msb; /* Most significant bit of field */
};

struct qdma_reg {
	u32 off;
	u32 count;
};

#define QDMA_REGF(_msb, _lsb) {						\
	.lsb = (_lsb),							\
	.msb = (_msb),							\
}

#define QDMA_REGO(_off, _count) {					\
	.off = (_off),							\
	.count = (_count),						\
}

enum qdma_desc_size {
	QDMA_DESC_SIZE_8B,
	QDMA_DESC_SIZE_16B,
	QDMA_DESC_SIZE_32B,
	QDMA_DESC_SIZE_64B,
};

enum qdma_queue_op_mode {
	QDMA_QUEUE_OP_STREAM,
	QDMA_QUEUE_OP_MM,
};

enum qdma_ctxt_type {
	QDMA_CTXT_DESC_SW_C2H,
	QDMA_CTXT_DESC_SW_H2C,
	QDMA_CTXT_DESC_HW_C2H,
	QDMA_CTXT_DESC_HW_H2C,
	QDMA_CTXT_DESC_CR_C2H,
	QDMA_CTXT_DESC_CR_H2C,
	QDMA_CTXT_WRB,
	QDMA_CTXT_PFTCH,
	QDMA_CTXT_INTR_COAL,
	QDMA_CTXT_RSVD,
	QDMA_CTXT_HOST_PROFILE,
	QDMA_CTXT_TIMER,
	QDMA_CTXT_FMAP,
	QDMA_CTXT_FNC_STS,
};

enum qdma_ctxt_cmd {
	QDMA_CTXT_CLEAR,
	QDMA_CTXT_WRITE,
	QDMA_CTXT_READ,
	QDMA_CTXT_INVALIDATE,
	QDMA_CTXT_MAX
};

struct qdma_ctxt_sw_desc {
	u64				desc_base;
	u16				vec;
};

struct qdma_ctxt_intr {
	u64				agg_base;
	u16				vec;
	u32				size;
	bool				valid;
	bool				color;
};

struct qdma_ctxt_fmap {
	u16				qbase;
	u16				qmax;
};

struct qdma_device;

struct qdma_mm_desc {
	__le64			src_addr;
	__le32			len;
	__le32			reserved1;
	__le64			dst_addr;
	__le64			reserved2;
} __packed;

struct qdma_mm_vdesc {
	struct virt_dma_desc		vdesc;
	struct qdma_queue		*queue;
	struct scatterlist		*sgl;
	u64				sg_off;
	u32				sg_len;
	u64				dev_addr;
	u32				pidx;
	u32				pending_descs;
	struct dma_slave_config		cfg;
};

#define QDMA_VDESC_QUEUED(vdesc)	(!(vdesc)->sg_len)

struct qdma_queue {
	struct qdma_device		*qdev;
	struct virt_dma_chan		vchan;
	enum dma_transfer_direction	dir;
	struct dma_slave_config		cfg;
	struct qdma_mm_desc		*desc_base;
	struct qdma_mm_vdesc		*submitted_vdesc;
	struct qdma_mm_vdesc		*issued_vdesc;
	dma_addr_t			dma_desc_base;
	u32				pidx_reg;
	u32				cidx_reg;
	u32				ring_size;
	u32				idx_mask;
	u16				qid;
	u32				pidx;
	u32				cidx;
};

struct qdma_intr_ring {
	struct qdma_device		*qdev;
	__le64				*base;
	dma_addr_t			dev_base;
	char				msix_name[QDMA_INTR_NAME_MAX_LEN];
	u32				msix_vector;
	u16				msix_id;
	u32				ring_size;
	u16				ridx;
	u16				cidx;
	u8				color;
};

#define QDMA_INTR_MASK_PIDX		GENMASK_ULL(15, 0)
#define QDMA_INTR_MASK_CIDX		GENMASK_ULL(31, 16)
#define QDMA_INTR_MASK_DESC_COLOR	GENMASK_ULL(32, 32)
#define QDMA_INTR_MASK_STATE		GENMASK_ULL(34, 33)
#define QDMA_INTR_MASK_ERROR		GENMASK_ULL(36, 35)
#define QDMA_INTR_MASK_TYPE		GENMASK_ULL(38, 38)
#define QDMA_INTR_MASK_QID		GENMASK_ULL(62, 39)
#define QDMA_INTR_MASK_COLOR		GENMASK_ULL(63, 63)

struct qdma_device {
	struct platform_device		*pdev;
	struct dma_device		dma_dev;
	struct regmap			*regmap;
	struct mutex			ctxt_lock; /* protect ctxt registers */
	const struct qdma_reg_field	*rfields;
	const struct qdma_reg		*roffs;
	struct qdma_queue		*h2c_queues;
	struct qdma_queue		*c2h_queues;
	struct qdma_intr_ring		*qintr_rings;
	u32				qintr_ring_num;
	u32				qintr_ring_idx;
	u32				chan_num;
	u32				queue_irq_start;
	u32				queue_irq_num;
	u32				err_irq_idx;
	u32				fid;
};

extern const struct qdma_reg qdma_regos_default[QDMA_REGO_MAX];
extern const struct qdma_reg_field qdma_regfs_default[QDMA_REGF_MAX];

#endif	/* __QDMA_H */