1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright 2019 NXP |
3 | |
4 | #include <linux/module.h> |
5 | #include <linux/types.h> |
6 | #include <linux/io.h> |
7 | #include <linux/fsl/mc.h> |
8 | #include "dpdmai.h" |
9 | |
10 | struct dpdmai_rsp_get_attributes { |
11 | __le32 id; |
12 | u8 num_of_priorities; |
13 | u8 pad0[3]; |
14 | __le16 major; |
15 | __le16 minor; |
16 | }; |
17 | |
18 | struct dpdmai_cmd_queue { |
19 | __le32 dest_id; |
20 | u8 priority; |
21 | u8 queue; |
22 | u8 dest_type; |
23 | u8 pad; |
24 | __le64 user_ctx; |
25 | union { |
26 | __le32 options; |
27 | __le32 fqid; |
28 | }; |
29 | }; |
30 | |
31 | struct dpdmai_rsp_get_tx_queue { |
32 | __le64 pad; |
33 | __le32 fqid; |
34 | }; |
35 | |
36 | #define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \ |
37 | ((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg)) |
38 | |
39 | /* cmd, param, offset, width, type, arg_name */ |
40 | #define DPDMAI_CMD_CREATE(cmd, cfg) \ |
41 | do { \ |
42 | MC_CMD_OP(cmd, 0, 8, 8, u8, (cfg)->priorities[0]);\ |
43 | MC_CMD_OP(cmd, 0, 16, 8, u8, (cfg)->priorities[1]);\ |
44 | } while (0) |
45 | |
46 | static inline u64 mc_enc(int lsoffset, int width, u64 val) |
47 | { |
48 | return (val & MAKE_UMASK64(width)) << lsoffset; |
49 | } |
50 | |
51 | /** |
52 | * dpdmai_open() - Open a control session for the specified object |
53 | * @mc_io: Pointer to MC portal's I/O object |
54 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
55 | * @dpdmai_id: DPDMAI unique ID |
56 | * @token: Returned token; use in subsequent API calls |
57 | * |
58 | * This function can be used to open a control session for an |
59 | * already created object; an object may have been declared in |
60 | * the DPL or by calling the dpdmai_create() function. |
61 | * This function returns a unique authentication token, |
62 | * associated with the specific object ID and the specific MC |
63 | * portal; this token must be used in all subsequent commands for |
64 | * this specific object. |
65 | * |
66 | * Return: '0' on Success; Error code otherwise. |
67 | */ |
68 | int dpdmai_open(struct fsl_mc_io *mc_io, u32 cmd_flags, |
69 | int dpdmai_id, u16 *token) |
70 | { |
71 | struct fsl_mc_command cmd = { 0 }; |
72 | __le64 *cmd_dpdmai_id; |
73 | int err; |
74 | |
75 | /* prepare command */ |
76 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN, |
77 | cmd_flags, token: 0); |
78 | |
79 | cmd_dpdmai_id = cmd.params; |
80 | *cmd_dpdmai_id = cpu_to_le32(dpdmai_id); |
81 | |
82 | /* send command to mc*/ |
83 | err = mc_send_command(mc_io, cmd: &cmd); |
84 | if (err) |
85 | return err; |
86 | |
87 | /* retrieve response parameters */ |
88 | *token = mc_cmd_hdr_read_token(cmd: &cmd); |
89 | |
90 | return 0; |
91 | } |
92 | EXPORT_SYMBOL_GPL(dpdmai_open); |
93 | |
94 | /** |
95 | * dpdmai_close() - Close the control session of the object |
96 | * @mc_io: Pointer to MC portal's I/O object |
97 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
98 | * @token: Token of DPDMAI object |
99 | * |
100 | * After this function is called, no further operations are |
101 | * allowed on the object without opening a new control session. |
102 | * |
103 | * Return: '0' on Success; Error code otherwise. |
104 | */ |
105 | int dpdmai_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) |
106 | { |
107 | struct fsl_mc_command cmd = { 0 }; |
108 | |
109 | /* prepare command */ |
110 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLOSE, |
111 | cmd_flags, token); |
112 | |
113 | /* send command to mc*/ |
114 | return mc_send_command(mc_io, cmd: &cmd); |
115 | } |
116 | EXPORT_SYMBOL_GPL(dpdmai_close); |
117 | |
118 | /** |
119 | * dpdmai_create() - Create the DPDMAI object |
120 | * @mc_io: Pointer to MC portal's I/O object |
121 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
122 | * @cfg: Configuration structure |
123 | * @token: Returned token; use in subsequent API calls |
124 | * |
125 | * Create the DPDMAI object, allocate required resources and |
126 | * perform required initialization. |
127 | * |
128 | * The object can be created either by declaring it in the |
129 | * DPL file, or by calling this function. |
130 | * |
131 | * This function returns a unique authentication token, |
132 | * associated with the specific object ID and the specific MC |
133 | * portal; this token must be used in all subsequent calls to |
134 | * this specific object. For objects that are created using the |
135 | * DPL file, call dpdmai_open() function to get an authentication |
136 | * token first. |
137 | * |
138 | * Return: '0' on Success; Error code otherwise. |
139 | */ |
140 | int dpdmai_create(struct fsl_mc_io *mc_io, u32 cmd_flags, |
141 | const struct dpdmai_cfg *cfg, u16 *token) |
142 | { |
143 | struct fsl_mc_command cmd = { 0 }; |
144 | int err; |
145 | |
146 | /* prepare command */ |
147 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CREATE, |
148 | cmd_flags, token: 0); |
149 | DPDMAI_CMD_CREATE(cmd, cfg); |
150 | |
151 | /* send command to mc*/ |
152 | err = mc_send_command(mc_io, cmd: &cmd); |
153 | if (err) |
154 | return err; |
155 | |
156 | /* retrieve response parameters */ |
157 | *token = mc_cmd_hdr_read_token(cmd: &cmd); |
158 | |
159 | return 0; |
160 | } |
161 | |
162 | /** |
163 | * dpdmai_destroy() - Destroy the DPDMAI object and release all its resources. |
164 | * @mc_io: Pointer to MC portal's I/O object |
165 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
166 | * @token: Token of DPDMAI object |
167 | * |
168 | * Return: '0' on Success; error code otherwise. |
169 | */ |
170 | int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) |
171 | { |
172 | struct fsl_mc_command cmd = { 0 }; |
173 | |
174 | /* prepare command */ |
175 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, |
176 | cmd_flags, token); |
177 | |
178 | /* send command to mc*/ |
179 | return mc_send_command(mc_io, cmd: &cmd); |
180 | } |
181 | EXPORT_SYMBOL_GPL(dpdmai_destroy); |
182 | |
183 | /** |
184 | * dpdmai_enable() - Enable the DPDMAI, allow sending and receiving frames. |
185 | * @mc_io: Pointer to MC portal's I/O object |
186 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
187 | * @token: Token of DPDMAI object |
188 | * |
189 | * Return: '0' on Success; Error code otherwise. |
190 | */ |
191 | int dpdmai_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) |
192 | { |
193 | struct fsl_mc_command cmd = { 0 }; |
194 | |
195 | /* prepare command */ |
196 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_ENABLE, |
197 | cmd_flags, token); |
198 | |
199 | /* send command to mc*/ |
200 | return mc_send_command(mc_io, cmd: &cmd); |
201 | } |
202 | EXPORT_SYMBOL_GPL(dpdmai_enable); |
203 | |
204 | /** |
205 | * dpdmai_disable() - Disable the DPDMAI, stop sending and receiving frames. |
206 | * @mc_io: Pointer to MC portal's I/O object |
207 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
208 | * @token: Token of DPDMAI object |
209 | * |
210 | * Return: '0' on Success; Error code otherwise. |
211 | */ |
212 | int dpdmai_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) |
213 | { |
214 | struct fsl_mc_command cmd = { 0 }; |
215 | |
216 | /* prepare command */ |
217 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DISABLE, |
218 | cmd_flags, token); |
219 | |
220 | /* send command to mc*/ |
221 | return mc_send_command(mc_io, cmd: &cmd); |
222 | } |
223 | EXPORT_SYMBOL_GPL(dpdmai_disable); |
224 | |
225 | /** |
226 | * dpdmai_reset() - Reset the DPDMAI, returns the object to initial state. |
227 | * @mc_io: Pointer to MC portal's I/O object |
228 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
229 | * @token: Token of DPDMAI object |
230 | * |
231 | * Return: '0' on Success; Error code otherwise. |
232 | */ |
233 | int dpdmai_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) |
234 | { |
235 | struct fsl_mc_command cmd = { 0 }; |
236 | |
237 | /* prepare command */ |
238 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_RESET, |
239 | cmd_flags, token); |
240 | |
241 | /* send command to mc*/ |
242 | return mc_send_command(mc_io, cmd: &cmd); |
243 | } |
244 | EXPORT_SYMBOL_GPL(dpdmai_reset); |
245 | |
246 | /** |
247 | * dpdmai_get_attributes() - Retrieve DPDMAI attributes. |
248 | * @mc_io: Pointer to MC portal's I/O object |
249 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
250 | * @token: Token of DPDMAI object |
251 | * @attr: Returned object's attributes |
252 | * |
253 | * Return: '0' on Success; Error code otherwise. |
254 | */ |
255 | int dpdmai_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, |
256 | u16 token, struct dpdmai_attr *attr) |
257 | { |
258 | struct dpdmai_rsp_get_attributes *rsp_params; |
259 | struct fsl_mc_command cmd = { 0 }; |
260 | int err; |
261 | |
262 | /* prepare command */ |
263 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_ATTR, |
264 | cmd_flags, token); |
265 | |
266 | /* send command to mc*/ |
267 | err = mc_send_command(mc_io, cmd: &cmd); |
268 | if (err) |
269 | return err; |
270 | |
271 | /* retrieve response parameters */ |
272 | rsp_params = (struct dpdmai_rsp_get_attributes *)cmd.params; |
273 | attr->id = le32_to_cpu(rsp_params->id); |
274 | attr->version.major = le16_to_cpu(rsp_params->major); |
275 | attr->version.minor = le16_to_cpu(rsp_params->minor); |
276 | attr->num_of_priorities = rsp_params->num_of_priorities; |
277 | |
278 | return 0; |
279 | } |
280 | EXPORT_SYMBOL_GPL(dpdmai_get_attributes); |
281 | |
282 | /** |
283 | * dpdmai_set_rx_queue() - Set Rx queue configuration |
284 | * @mc_io: Pointer to MC portal's I/O object |
285 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
286 | * @token: Token of DPDMAI object |
287 | * @priority: Select the queue relative to number of |
288 | * priorities configured at DPDMAI creation |
289 | * @cfg: Rx queue configuration |
290 | * |
291 | * Return: '0' on Success; Error code otherwise. |
292 | */ |
293 | int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, |
294 | u8 priority, const struct dpdmai_rx_queue_cfg *cfg) |
295 | { |
296 | struct dpdmai_cmd_queue *cmd_params; |
297 | struct fsl_mc_command cmd = { 0 }; |
298 | |
299 | /* prepare command */ |
300 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_RX_QUEUE, |
301 | cmd_flags, token); |
302 | |
303 | cmd_params = (struct dpdmai_cmd_queue *)cmd.params; |
304 | cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); |
305 | cmd_params->priority = cfg->dest_cfg.priority; |
306 | cmd_params->queue = priority; |
307 | cmd_params->dest_type = cfg->dest_cfg.dest_type; |
308 | cmd_params->user_ctx = cpu_to_le64(cfg->user_ctx); |
309 | cmd_params->options = cpu_to_le32(cfg->options); |
310 | |
311 | /* send command to mc*/ |
312 | return mc_send_command(mc_io, cmd: &cmd); |
313 | } |
314 | EXPORT_SYMBOL_GPL(dpdmai_set_rx_queue); |
315 | |
316 | /** |
317 | * dpdmai_get_rx_queue() - Retrieve Rx queue attributes. |
318 | * @mc_io: Pointer to MC portal's I/O object |
319 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
320 | * @token: Token of DPDMAI object |
321 | * @priority: Select the queue relative to number of |
322 | * priorities configured at DPDMAI creation |
323 | * @attr: Returned Rx queue attributes |
324 | * |
325 | * Return: '0' on Success; Error code otherwise. |
326 | */ |
327 | int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, |
328 | u8 priority, struct dpdmai_rx_queue_attr *attr) |
329 | { |
330 | struct dpdmai_cmd_queue *cmd_params; |
331 | struct fsl_mc_command cmd = { 0 }; |
332 | int err; |
333 | |
334 | /* prepare command */ |
335 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_RX_QUEUE, |
336 | cmd_flags, token); |
337 | |
338 | cmd_params = (struct dpdmai_cmd_queue *)cmd.params; |
339 | cmd_params->queue = priority; |
340 | |
341 | /* send command to mc*/ |
342 | err = mc_send_command(mc_io, cmd: &cmd); |
343 | if (err) |
344 | return err; |
345 | |
346 | /* retrieve response parameters */ |
347 | attr->dest_cfg.dest_id = le32_to_cpu(cmd_params->dest_id); |
348 | attr->dest_cfg.priority = cmd_params->priority; |
349 | attr->dest_cfg.dest_type = cmd_params->dest_type; |
350 | attr->user_ctx = le64_to_cpu(cmd_params->user_ctx); |
351 | attr->fqid = le32_to_cpu(cmd_params->fqid); |
352 | |
353 | return 0; |
354 | } |
355 | EXPORT_SYMBOL_GPL(dpdmai_get_rx_queue); |
356 | |
357 | /** |
358 | * dpdmai_get_tx_queue() - Retrieve Tx queue attributes. |
359 | * @mc_io: Pointer to MC portal's I/O object |
360 | * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
361 | * @token: Token of DPDMAI object |
362 | * @priority: Select the queue relative to number of |
363 | * priorities configured at DPDMAI creation |
364 | * @fqid: Returned Tx queue |
365 | * |
366 | * Return: '0' on Success; Error code otherwise. |
367 | */ |
368 | int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, |
369 | u16 token, u8 priority, u32 *fqid) |
370 | { |
371 | struct dpdmai_rsp_get_tx_queue *rsp_params; |
372 | struct dpdmai_cmd_queue *cmd_params; |
373 | struct fsl_mc_command cmd = { 0 }; |
374 | int err; |
375 | |
376 | /* prepare command */ |
377 | cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_TX_QUEUE, |
378 | cmd_flags, token); |
379 | |
380 | cmd_params = (struct dpdmai_cmd_queue *)cmd.params; |
381 | cmd_params->queue = priority; |
382 | |
383 | /* send command to mc*/ |
384 | err = mc_send_command(mc_io, cmd: &cmd); |
385 | if (err) |
386 | return err; |
387 | |
388 | /* retrieve response parameters */ |
389 | |
390 | rsp_params = (struct dpdmai_rsp_get_tx_queue *)cmd.params; |
391 | *fqid = le32_to_cpu(rsp_params->fqid); |
392 | |
393 | return 0; |
394 | } |
395 | EXPORT_SYMBOL_GPL(dpdmai_get_tx_queue); |
396 | |
397 | MODULE_LICENSE("GPL v2" ); |
398 | |