blob: 34038b31f70214029381632eabcf6e2c3707e6eb [file] [log] [blame]
Grygorii Strashkoe85901c2019-02-05 17:31:23 +05301/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * CPPI5 descriptors interface
4 *
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
6 */
7
8#ifndef __TI_CPPI5_H__
9#define __TI_CPPI5_H__
10
11#include <hexdump.h>
12#include <linux/bitops.h>
13
14/**
15 * Descriptor header, present in all types of descriptors
16 */
17struct cppi5_desc_hdr_t {
18 u32 pkt_info0; /* Packet info word 0 (n/a in Buffer desc) */
19 u32 pkt_info1; /* Packet info word 1 (n/a in Buffer desc) */
20 u32 pkt_info2; /* Packet info word 2 Buffer reclamation info */
21 u32 src_dst_tag; /* Packet info word 3 (n/a in Buffer desc) */
22} __packed;
23
24/**
25 * Host-mode packet and buffer descriptor definition
26 */
27struct cppi5_host_desc_t {
28 struct cppi5_desc_hdr_t hdr;
29 u64 next_desc; /* w4/5: Linking word */
30 u64 buf_ptr; /* w6/7: Buffer pointer */
31 u32 buf_info1; /* w8: Buffer valid data length */
32 u32 org_buf_len; /* w9: Original buffer length */
33 u64 org_buf_ptr; /* w10/11: Original buffer pointer */
34 u32 epib[0]; /* Extended Packet Info Data (optional, 4 words) */
35 /*
36 * Protocol Specific Data (optional, 0-128 bytes in multiples of 4),
37 * and/or Other Software Data (0-N bytes, optional)
38 */
39} __packed;
40
41#define CPPI5_DESC_MIN_ALIGN (16U)
42
43#define CPPI5_INFO0_HDESC_EPIB_SIZE (16U)
44#define CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE (128U)
45
46#define CPPI5_INFO0_HDESC_TYPE_SHIFT (30U)
47#define CPPI5_INFO0_HDESC_TYPE_MASK GENMASK(31, 30)
48#define CPPI5_INFO0_DESC_TYPE_VAL_HOST (1U)
49#define CPPI5_INFO0_DESC_TYPE_VAL_MONO (2U)
50#define CPPI5_INFO0_DESC_TYPE_VAL_TR (3U)
51#define CPPI5_INFO0_HDESC_EPIB_PRESENT BIT(29)
52/*
53 * Protocol Specific Words location:
54 * 0 - located in the descriptor,
55 * 1 = located in the SOP Buffer immediately prior to the data.
56 */
57#define CPPI5_INFO0_HDESC_PSINFO_LOCATION BIT(28)
58#define CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT (22U)
59#define CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK GENMASK(27, 22)
60#define CPPI5_INFO0_HDESC_PKTLEN_SHIFT (0)
61#define CPPI5_INFO0_HDESC_PKTLEN_MASK GENMASK(21, 0)
62
63#define CPPI5_INFO1_DESC_PKTERROR_SHIFT (28U)
64#define CPPI5_INFO1_DESC_PKTERROR_MASK GENMASK(31, 28)
65#define CPPI5_INFO1_HDESC_PSFLGS_SHIFT (24U)
66#define CPPI5_INFO1_HDESC_PSFLGS_MASK GENMASK(27, 24)
67#define CPPI5_INFO1_DESC_PKTID_SHIFT (14U)
68#define CPPI5_INFO1_DESC_PKTID_MASK GENMASK(23, 14)
69#define CPPI5_INFO1_DESC_FLOWID_SHIFT (0)
70#define CPPI5_INFO1_DESC_FLOWID_MASK GENMASK(13, 0)
71
72#define CPPI5_INFO2_HDESC_PKTTYPE_SHIFT (27U)
73#define CPPI5_INFO2_HDESC_PKTTYPE_MASK GENMASK(31, 27)
74/* Return Policy: 0 - Entire packet 1 - Each buffer */
75#define CPPI5_INFO2_HDESC_RETPOLICY BIT(18)
76/*
77 * Early Return:
78 * 0 = desc pointers should be returned after all reads have been completed
79 * 1 = desc pointers should be returned immediately upon fetching
80 * the descriptor and beginning to transfer data.
81 */
82#define CPPI5_INFO2_HDESC_EARLYRET BIT(17)
83/*
84 * Return Push Policy:
85 * 0 = Descriptor must be returned to tail of queue
86 * 1 = Descriptor must be returned to head of queue
87 */
88#define CPPI5_INFO2_DESC_RETPUSHPOLICY BIT(16)
89#define CPPI5_INFO2_DESC_RETQ_SHIFT (0)
90#define CPPI5_INFO2_DESC_RETQ_MASK GENMASK(15, 0)
91
92#define CPPI5_INFO3_DESC_SRCTAG_SHIFT (16U)
93#define CPPI5_INFO3_DESC_SRCTAG_MASK GENMASK(31, 16)
94#define CPPI5_INFO3_DESC_DSTTAG_SHIFT (0)
95#define CPPI5_INFO3_DESC_DSTTAG_MASK GENMASK(15, 0)
96
97#define CPPI5_BUFINFO1_HDESC_DATA_LEN_SHIFT (0)
98#define CPPI5_BUFINFO1_HDESC_DATA_LEN_MASK GENMASK(27, 0)
99
100#define CPPI5_OBUFINFO0_HDESC_BUF_LEN_SHIFT (0)
101#define CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK GENMASK(27, 0)
102
103/*
104 * Host Packet Descriptor Extended Packet Info Block
105 */
106struct cppi5_desc_epib_t {
107 u32 timestamp; /* w0: application specific timestamp */
108 u32 sw_info0; /* w1: Software Info 0 */
109 u32 sw_info1; /* w2: Software Info 1 */
110 u32 sw_info2; /* w3: Software Info 2 */
111};
112
113/**
114 * Monolithic-mode packet descriptor
115 */
116struct cppi5_monolithic_desc_t {
117 struct cppi5_desc_hdr_t hdr;
118 u32 epib[0]; /* Extended Packet Info Data (optional, 4 words) */
119 /*
120 * Protocol Specific Data (optional, 0-128 bytes in multiples of 4),
121 * and/or Other Software Data (0-N bytes, optional)
122 */
123};
124
125#define CPPI5_INFO2_MDESC_DATA_OFFSET_SHIFT (18U)
126#define CPPI5_INFO2_MDESC_DATA_OFFSET_MASK GENMASK(26, 18)
127
128/*
129 * Reload Enable:
130 * 0 = Finish the packet and place the descriptor back on the return queue
131 * 1 = Vector to the Reload Index and resume processing
132 */
133#define CPPI5_INFO0_TRDESC_RLDCNT_SHIFT (20U)
134#define CPPI5_INFO0_TRDESC_RLDCNT_MASK GENMASK(28, 20)
135#define CPPI5_INFO0_TRDESC_RLDCNT_MAX (0x1ff)
136#define CPPI5_INFO0_TRDESC_RLDCNT_INFINITE CPPI5_INFO0_TRDESC_RLDCNT_MAX
137#define CPPI5_INFO0_TRDESC_RLDIDX_SHIFT (14U)
138#define CPPI5_INFO0_TRDESC_RLDIDX_MASK GENMASK(19, 14)
139#define CPPI5_INFO0_TRDESC_RLDIDX_MAX (0x3f)
140#define CPPI5_INFO0_TRDESC_LASTIDX_SHIFT (0)
141#define CPPI5_INFO0_TRDESC_LASTIDX_MASK GENMASK(13, 0)
142
143#define CPPI5_INFO1_TRDESC_RECSIZE_SHIFT (24U)
144#define CPPI5_INFO1_TRDESC_RECSIZE_MASK GENMASK(26, 24)
145#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_16B (0)
146#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_32B (1U)
147#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_64B (2U)
148#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_128B (3U)
149
150static inline void cppi5_desc_dump(void *desc, u32 size)
151{
152 print_hex_dump(KERN_ERR "dump udmap_desc: ", DUMP_PREFIX_NONE,
153 32, 4, desc, size, false);
154}
155
156/**
157 * cppi5_desc_get_type - get descriptor type
158 * @desc_hdr: packet descriptor/TR header
159 *
160 * Returns descriptor type:
161 * CPPI5_INFO0_DESC_TYPE_VAL_HOST
162 * CPPI5_INFO0_DESC_TYPE_VAL_MONO
163 * CPPI5_INFO0_DESC_TYPE_VAL_TR
164 */
165static inline u32 cppi5_desc_get_type(struct cppi5_desc_hdr_t *desc_hdr)
166{
167 WARN_ON(!desc_hdr);
168
169 return (desc_hdr->pkt_info0 & CPPI5_INFO0_HDESC_TYPE_MASK) >>
170 CPPI5_INFO0_HDESC_TYPE_SHIFT;
171}
172
173/**
174 * cppi5_desc_get_errflags - get Error Flags from Desc
175 * @desc_hdr: packet/TR descriptor header
176 *
177 * Returns Error Flags from Packet/TR Descriptor
178 */
179static inline u32 cppi5_desc_get_errflags(struct cppi5_desc_hdr_t *desc_hdr)
180{
181 WARN_ON(!desc_hdr);
182
183 return (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_PKTERROR_MASK) >>
184 CPPI5_INFO1_DESC_PKTERROR_SHIFT;
185}
186
187/**
188 * cppi5_desc_get_pktids - get Packet and Flow ids from Desc
189 * @desc_hdr: packet/TR descriptor header
190 * @pkt_id: Packet ID
191 * @flow_id: Flow ID
192 *
193 * Returns Packet and Flow ids from packet/TR descriptor
194 */
195static inline void cppi5_desc_get_pktids(struct cppi5_desc_hdr_t *desc_hdr,
196 u32 *pkt_id, u32 *flow_id)
197{
198 WARN_ON(!desc_hdr);
199
200 *pkt_id = (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_PKTID_MASK) >>
201 CPPI5_INFO1_DESC_PKTID_SHIFT;
202 *flow_id = (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_FLOWID_MASK) >>
203 CPPI5_INFO1_DESC_FLOWID_SHIFT;
204}
205
206/**
207 * cppi5_desc_set_pktids - set Packet and Flow ids in Desc
208 * @desc_hdr: packet/TR descriptor header
209 * @pkt_id: Packet ID
210 * @flow_id: Flow ID
211 */
212static inline void cppi5_desc_set_pktids(struct cppi5_desc_hdr_t *desc_hdr,
213 u32 pkt_id, u32 flow_id)
214{
215 WARN_ON(!desc_hdr);
216
217 desc_hdr->pkt_info1 |= (pkt_id << CPPI5_INFO1_DESC_PKTID_SHIFT) &
218 CPPI5_INFO1_DESC_PKTID_MASK;
219 desc_hdr->pkt_info1 |= (flow_id << CPPI5_INFO1_DESC_FLOWID_SHIFT) &
220 CPPI5_INFO1_DESC_FLOWID_MASK;
221}
222
223/**
224 * cppi5_desc_set_retpolicy - set Packet Return Policy in Desc
225 * @desc_hdr: packet/TR descriptor header
226 * @flags: fags, supported values
227 * CPPI5_INFO2_HDESC_RETPOLICY
228 * CPPI5_INFO2_HDESC_EARLYRET
229 * CPPI5_INFO2_DESC_RETPUSHPOLICY
230 * @return_ring_id: Packet Return Queue/Ring id, value 0xFFFF reserved
231 */
232static inline void cppi5_desc_set_retpolicy(struct cppi5_desc_hdr_t *desc_hdr,
233 u32 flags, u32 return_ring_id)
234{
235 WARN_ON(!desc_hdr);
236
237 desc_hdr->pkt_info2 |= flags;
238 desc_hdr->pkt_info2 |= return_ring_id & CPPI5_INFO2_DESC_RETQ_MASK;
239}
240
241/**
242 * cppi5_desc_get_tags_ids - get Packet Src/Dst Tags from Desc
243 * @desc_hdr: packet/TR descriptor header
244 * @src_tag_id: Source Tag
245 * @dst_tag_id: Dest Tag
246 *
247 * Returns Packet Src/Dst Tags from packet/TR descriptor
248 */
249static inline void cppi5_desc_get_tags_ids(struct cppi5_desc_hdr_t *desc_hdr,
250 u32 *src_tag_id, u32 *dst_tag_id)
251{
252 WARN_ON(!desc_hdr);
253
254 if (src_tag_id)
255 *src_tag_id = (desc_hdr->src_dst_tag &
256 CPPI5_INFO3_DESC_SRCTAG_MASK) >>
257 CPPI5_INFO3_DESC_SRCTAG_SHIFT;
258 if (dst_tag_id)
259 *dst_tag_id = desc_hdr->src_dst_tag &
260 CPPI5_INFO3_DESC_DSTTAG_MASK;
261}
262
263/**
264 * cppi5_desc_set_tags_ids - set Packet Src/Dst Tags in HDesc
265 * @desc_hdr: packet/TR descriptor header
266 * @src_tag_id: Source Tag
267 * @dst_tag_id: Dest Tag
268 *
269 * Returns Packet Src/Dst Tags from packet/TR descriptor
270 */
271static inline void cppi5_desc_set_tags_ids(struct cppi5_desc_hdr_t *desc_hdr,
272 u32 src_tag_id, u32 dst_tag_id)
273{
274 WARN_ON(!desc_hdr);
275
276 desc_hdr->src_dst_tag = (src_tag_id << CPPI5_INFO3_DESC_SRCTAG_SHIFT) &
277 CPPI5_INFO3_DESC_SRCTAG_MASK;
278 desc_hdr->src_dst_tag |= dst_tag_id & CPPI5_INFO3_DESC_DSTTAG_MASK;
279}
280
281/**
282 * cppi5_hdesc_calc_size - Calculate Host Packet Descriptor size
283 * @epib: is EPIB present
284 * @psdata_size: PSDATA size
285 * @sw_data_size: SWDATA size
286 *
287 * Returns required Host Packet Descriptor size
288 * 0 - if PSDATA > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE
289 */
290static inline u32 cppi5_hdesc_calc_size(bool epib, u32 psdata_size,
291 u32 sw_data_size)
292{
293 u32 desc_size;
294
295 if (psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE)
296 return 0;
297 //TODO_GS: align
298 desc_size = sizeof(struct cppi5_host_desc_t) + psdata_size +
299 sw_data_size;
300
301 if (epib)
302 desc_size += CPPI5_INFO0_HDESC_EPIB_SIZE;
303
304 return ALIGN(desc_size, CPPI5_DESC_MIN_ALIGN);
305}
306
307/**
308 * cppi5_hdesc_init - Init Host Packet Descriptor size
309 * @desc: Host packet descriptor
310 * @flags: supported values
311 * CPPI5_INFO0_HDESC_EPIB_PRESENT
312 * CPPI5_INFO0_HDESC_PSINFO_LOCATION
313 * @psdata_size: PSDATA size
314 *
315 * Returns required Host Packet Descriptor size
316 * 0 - if PSDATA > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE
317 */
318static inline void cppi5_hdesc_init(struct cppi5_host_desc_t *desc, u32 flags,
319 u32 psdata_size)
320{
321 WARN_ON(!desc);
322 WARN_ON(psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE);
323 WARN_ON(flags & ~(CPPI5_INFO0_HDESC_EPIB_PRESENT |
324 CPPI5_INFO0_HDESC_PSINFO_LOCATION));
325
326 desc->hdr.pkt_info0 = (CPPI5_INFO0_DESC_TYPE_VAL_HOST <<
327 CPPI5_INFO0_HDESC_TYPE_SHIFT) | (flags);
328 desc->hdr.pkt_info0 |= ((psdata_size >> 2) <<
329 CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT) &
330 CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK;
331 desc->next_desc = 0;
332}
333
334/**
335 * cppi5_hdesc_update_flags - Replace descriptor flags
336 * @desc: Host packet descriptor
337 * @flags: supported values
338 * CPPI5_INFO0_HDESC_EPIB_PRESENT
339 * CPPI5_INFO0_HDESC_PSINFO_LOCATION
340 */
341static inline void cppi5_hdesc_update_flags(struct cppi5_host_desc_t *desc,
342 u32 flags)
343{
344 WARN_ON(!desc);
345 WARN_ON(flags & ~(CPPI5_INFO0_HDESC_EPIB_PRESENT |
346 CPPI5_INFO0_HDESC_PSINFO_LOCATION));
347
348 desc->hdr.pkt_info0 &= ~(CPPI5_INFO0_HDESC_EPIB_PRESENT |
349 CPPI5_INFO0_HDESC_PSINFO_LOCATION);
350 desc->hdr.pkt_info0 |= flags;
351}
352
353/**
354 * cppi5_hdesc_update_psdata_size - Replace PSdata size
355 * @desc: Host packet descriptor
356 * @psdata_size: PSDATA size
357 */
358static inline void cppi5_hdesc_update_psdata_size(
359 struct cppi5_host_desc_t *desc, u32 psdata_size)
360{
361 WARN_ON(!desc);
362 WARN_ON(psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE);
363
364 desc->hdr.pkt_info0 &= ~CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK;
365 desc->hdr.pkt_info0 |= ((psdata_size >> 2) <<
366 CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT) &
367 CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK;
368}
369
370/**
371 * cppi5_hdesc_get_psdata_size - get PSdata size in bytes
372 * @desc: Host packet descriptor
373 */
374static inline u32 cppi5_hdesc_get_psdata_size(struct cppi5_host_desc_t *desc)
375{
376 u32 psdata_size = 0;
377
378 WARN_ON(!desc);
379
380 if (!(desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION))
381 psdata_size = (desc->hdr.pkt_info0 &
382 CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >>
383 CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT;
384
385 return (psdata_size << 2);
386}
387
388/**
389 * cppi5_hdesc_get_pktlen - get Packet Length from HDesc
390 * @desc: Host packet descriptor
391 *
392 * Returns Packet Length from Host Packet Descriptor
393 */
394static inline u32 cppi5_hdesc_get_pktlen(struct cppi5_host_desc_t *desc)
395{
396 WARN_ON(!desc);
397
398 return (desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PKTLEN_MASK);
399}
400
401/**
402 * cppi5_hdesc_set_pktlen - set Packet Length in HDesc
403 * @desc: Host packet descriptor
404 */
405static inline void cppi5_hdesc_set_pktlen(struct cppi5_host_desc_t *desc,
406 u32 pkt_len)
407{
408 WARN_ON(!desc);
409
410 desc->hdr.pkt_info0 |= (pkt_len & CPPI5_INFO0_HDESC_PKTLEN_MASK);
411}
412
413/**
414 * cppi5_hdesc_get_psflags - get Protocol Specific Flags from HDesc
415 * @desc: Host packet descriptor
416 *
417 * Returns Protocol Specific Flags from Host Packet Descriptor
418 */
419static inline u32 cppi5_hdesc_get_psflags(struct cppi5_host_desc_t *desc)
420{
421 WARN_ON(!desc);
422
423 return (desc->hdr.pkt_info1 & CPPI5_INFO1_HDESC_PSFLGS_MASK) >>
424 CPPI5_INFO1_HDESC_PSFLGS_SHIFT;
425}
426
427/**
428 * cppi5_hdesc_set_psflags - set Protocol Specific Flags in HDesc
429 * @desc: Host packet descriptor
430 */
431static inline void cppi5_hdesc_set_psflags(struct cppi5_host_desc_t *desc,
432 u32 ps_flags)
433{
434 WARN_ON(!desc);
435
436 desc->hdr.pkt_info1 |= (ps_flags <<
437 CPPI5_INFO1_HDESC_PSFLGS_SHIFT) &
438 CPPI5_INFO1_HDESC_PSFLGS_MASK;
439}
440
441/**
442 * cppi5_hdesc_get_errflags - get Packet Type from HDesc
443 * @desc: Host packet descriptor
444 */
445static inline u32 cppi5_hdesc_get_pkttype(struct cppi5_host_desc_t *desc)
446{
447 WARN_ON(!desc);
448
449 return (desc->hdr.pkt_info2 & CPPI5_INFO2_HDESC_PKTTYPE_MASK) >>
450 CPPI5_INFO2_HDESC_PKTTYPE_SHIFT;
451}
452
453/**
454 * cppi5_hdesc_get_errflags - set Packet Type in HDesc
455 * @desc: Host packet descriptor
456 * @pkt_type: Packet Type
457 */
458static inline void cppi5_hdesc_set_pkttype(struct cppi5_host_desc_t *desc,
459 u32 pkt_type)
460{
461 WARN_ON(!desc);
462 desc->hdr.pkt_info2 |=
463 (pkt_type << CPPI5_INFO2_HDESC_PKTTYPE_SHIFT) &
464 CPPI5_INFO2_HDESC_PKTTYPE_MASK;
465}
466
467/**
468 * cppi5_hdesc_attach_buf - attach buffer to HDesc
469 * @desc: Host packet descriptor
470 * @buf: Buffer physical address
471 * @buf_data_len: Buffer length
472 * @obuf: Original Buffer physical address
473 * @obuf_len: Original Buffer length
474 *
475 * Attaches buffer to Host Packet Descriptor
476 */
477static inline void cppi5_hdesc_attach_buf(struct cppi5_host_desc_t *desc,
478 dma_addr_t buf, u32 buf_data_len,
479 dma_addr_t obuf, u32 obuf_len)
480{
481 WARN_ON(!desc);
482 WARN_ON(!buf && !obuf);
483
484 desc->buf_ptr = buf;
485 desc->buf_info1 = buf_data_len & CPPI5_BUFINFO1_HDESC_DATA_LEN_MASK;
486 desc->org_buf_ptr = obuf;
487 desc->org_buf_len = obuf_len & CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK;
488}
489
490static inline void cppi5_hdesc_get_obuf(struct cppi5_host_desc_t *desc,
491 dma_addr_t *obuf, u32 *obuf_len)
492{
493 WARN_ON(!desc);
494 WARN_ON(!obuf);
495 WARN_ON(!obuf_len);
496
497 *obuf = desc->org_buf_ptr;
498 *obuf_len = desc->org_buf_len & CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK;
499}
500
501static inline void cppi5_hdesc_reset_to_original(struct cppi5_host_desc_t *desc)
502{
503 WARN_ON(!desc);
504
505 desc->buf_ptr = desc->org_buf_ptr;
506 desc->buf_info1 = desc->org_buf_len;
507}
508
509/**
510 * cppi5_hdesc_link_hbdesc - link Host Buffer Descriptor to HDesc
511 * @desc: Host Packet Descriptor
512 * @buf_desc: Host Buffer Descriptor physical address
513 *
514 * add and link Host Buffer Descriptor to HDesc
515 */
516static inline void cppi5_hdesc_link_hbdesc(struct cppi5_host_desc_t *desc,
517 dma_addr_t hbuf_desc)
518{
519 WARN_ON(!desc);
520 WARN_ON(!hbuf_desc);
521
522 desc->next_desc = hbuf_desc;
523}
524
525static inline dma_addr_t cppi5_hdesc_get_next_hbdesc(
526 struct cppi5_host_desc_t *desc)
527{
528 WARN_ON(!desc);
529
530 return (dma_addr_t)desc->next_desc;
531}
532
533static inline void cppi5_hdesc_reset_hbdesc(struct cppi5_host_desc_t *desc)
534{
535 WARN_ON(!desc);
536
537 desc->hdr = (struct cppi5_desc_hdr_t) { 0 };
538 desc->next_desc = 0;
539}
540
541/**
542 * cppi5_hdesc_epib_present - check if EPIB present
543 * @desc_hdr: packet descriptor/TR header
544 *
545 * Returns true if EPIB present in the packet
546 */
547static inline bool cppi5_hdesc_epib_present(struct cppi5_desc_hdr_t *desc_hdr)
548{
549 WARN_ON(!desc_hdr);
550 return !!(desc_hdr->pkt_info0 & CPPI5_INFO0_HDESC_EPIB_PRESENT);
551}
552
553/**
554 * cppi5_hdesc_get_psdata - Get pointer on PSDATA
555 * @desc: Host packet descriptor
556 *
557 * Returns pointer on PSDATA in HDesc.
558 * NULL - if ps_data placed at the start of data buffer.
559 */
560static inline void *cppi5_hdesc_get_psdata(struct cppi5_host_desc_t *desc)
561{
562 u32 psdata_size;
563 void *psdata;
564
565 WARN_ON(!desc);
566
567 if (desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION)
568 return NULL;
569
570 psdata_size = (desc->hdr.pkt_info0 &
571 CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >>
572 CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT;
573
574 if (!psdata_size)
575 return NULL;
576
577 psdata = &desc->epib;
578
579 if (cppi5_hdesc_epib_present(&desc->hdr))
580 psdata += CPPI5_INFO0_HDESC_EPIB_SIZE;
581
582 return psdata;
583}
584
585static inline u32 *cppi5_hdesc_get_psdata32(struct cppi5_host_desc_t *desc)
586{
587 return (u32 *)cppi5_hdesc_get_psdata(desc);
588}
589
590/**
591 * cppi5_hdesc_get_swdata - Get pointer on swdata
592 * @desc: Host packet descriptor
593 *
594 * Returns pointer on SWDATA in HDesc.
595 * NOTE. It's caller responsibility to be sure hdesc actually has swdata.
596 */
597static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
598{
599 u32 psdata_size = 0;
600 void *swdata;
601
602 WARN_ON(!desc);
603
604 if (!(desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION))
605 psdata_size = (desc->hdr.pkt_info0 &
606 CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >>
607 CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT;
608
609 swdata = &desc->epib;
610
611 if (cppi5_hdesc_epib_present(&desc->hdr))
612 swdata += CPPI5_INFO0_HDESC_EPIB_SIZE;
613
614 swdata += (psdata_size << 2);
615
616 return swdata;
617}
618
619/* ================================== TR ================================== */
620
621#define CPPI5_TR_TYPE_SHIFT (0U)
622#define CPPI5_TR_TYPE_MASK GENMASK(3, 0)
623#define CPPI5_TR_STATIC BIT(4)
624#define CPPI5_TR_WAIT BIT(5)
625#define CPPI5_TR_EVENT_SIZE_SHIFT (6U)
626#define CPPI5_TR_EVENT_SIZE_MASK GENMASK(7, 6)
627#define CPPI5_TR_TRIGGER0_SHIFT (8U)
628#define CPPI5_TR_TRIGGER0_MASK GENMASK(9, 8)
629#define CPPI5_TR_TRIGGER0_TYPE_SHIFT (10U)
630#define CPPI5_TR_TRIGGER0_TYPE_MASK GENMASK(11, 10)
631#define CPPI5_TR_TRIGGER1_SHIFT (12U)
632#define CPPI5_TR_TRIGGER1_MASK GENMASK(13, 12)
633#define CPPI5_TR_TRIGGER1_TYPE_SHIFT (14U)
634#define CPPI5_TR_TRIGGER1_TYPE_MASK GENMASK(15, 14)
635#define CPPI5_TR_CMD_ID_SHIFT (16U)
636#define CPPI5_TR_CMD_ID_MASK GENMASK(23, 16)
637#define CPPI5_TR_CSF_FLAGS_SHIFT (24U)
638#define CPPI5_TR_CSF_FLAGS_MASK GENMASK(31, 24)
639#define CPPI5_TR_CSF_SA_INDIRECT BIT(0)
640#define CPPI5_TR_CSF_DA_INDIRECT BIT(1)
641#define CPPI5_TR_CSF_SUPR_EVT BIT(2)
642#define CPPI5_TR_CSF_EOL_ADV_SHIFT (4U)
643#define CPPI5_TR_CSF_EOL_ADV_MASK GENMASK(6, 4)
644#define CPPI5_TR_CSF_EOP BIT(7)
645
646/* Udmap TR flags Type field specifies the type of TR. */
647enum cppi5_tr_types {
648 /* type0: One dimensional data move */
649 CPPI5_TR_TYPE0 = 0,
650 /* type1: Two dimensional data move */
651 CPPI5_TR_TYPE1,
652 /* type2: Three dimensional data move */
653 CPPI5_TR_TYPE2,
654 /* type3: Four dimensional data move */
655 CPPI5_TR_TYPE3,
656 /* type4: Four dimensional data move with data formatting */
657 CPPI5_TR_TYPE4,
658 /* type5: Four dimensional Cache Warm */
659 CPPI5_TR_TYPE5,
660 /* type6-7: Reserved */
661 /* type8: Four Dimensional Block Move */
662 CPPI5_TR_TYPE8 = 8,
663 /* type9: Four Dimensional Block Move with Repacking */
664 CPPI5_TR_TYPE9,
665 /* type10: Two Dimensional Block Move */
666 CPPI5_TR_TYPE10,
667 /* type11: Two Dimensional Block Move with Repacking */
668 CPPI5_TR_TYPE11,
669 /* type12-14: Reserved */
670 /* type15 Four Dimensional Block Move with Repacking and Indirection */
671 CPPI5_TR_TYPE15 = 15,
672 CPPI5_TR_TYPE_MAX
673};
674
675/*
676 * Udmap TR Flags EVENT_SIZE field specifies when an event is generated
677 * for each TR.
678 */
679enum cppi5_tr_event_size {
680 /* When TR is complete and all status for the TR has been received */
681 CPPI5_TR_EVENT_SIZE_COMPLETION,
682 /*
683 * Type 0: when the last data transaction is sent for the TR;
684 * Type 1-11: when ICNT1 is decremented
685 */
686 CPPI5_TR_EVENT_SIZE_ICNT1_DEC,
687 /*
688 * Type 0-1,10-11: when the last data transaction is sent for the TR;
689 * All other types: when ICNT2 is decremented
690 */
691 CPPI5_TR_EVENT_SIZE_ICNT2_DEC,
692 /*
693 * Type 0-2,10-11: when the last data transaction is sent for the TR;
694 * All other types: when ICNT3 is decremented
695 */
696 CPPI5_TR_EVENT_SIZE_ICNT3_DEC,
697 CPPI5_TR_EVENT_SIZE_MAX
698};
699
700/*
701 * Udmap TR Flags TRIGGERx field specifies the type of trigger used to
702 * enable the TR to transfer data as specified by TRIGGERx_TYPE field.
703 */
704enum cppi5_tr_trigger {
705 CPPI5_TR_TRIGGER_NONE, /* No Trigger */
706 CPPI5_TR_TRIGGER_GLOBAL0, /* Global Trigger 0 */
707 CPPI5_TR_TRIGGER_GLOBAL1, /* Global Trigger 1 */
708 CPPI5_TR_TRIGGER_LOCAL_EVENT, /* Local Event */
709 CPPI5_TR_TRIGGER_MAX
710};
711
712/*
713 * Udmap TR Flags TRIGGERx_TYPE field specifies the type of data transfer
714 * that will be enabled by receiving a trigger as specified by TRIGGERx.
715 */
716enum cppi5_tr_trigger_type {
717 /* The second inner most loop (ICNT1) will be decremented by 1 */
718 CPPI5_TR_TRIGGER_TYPE_ICNT1_DEC,
719 /* The third inner most loop (ICNT2) will be decremented by 1 */
720 CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
721 /* The outer most loop (ICNT3) will be decremented by 1 */
722 CPPI5_TR_TRIGGER_TYPE_ICNT3_DEC,
723 /* The entire TR will be allowed to complete */
724 CPPI5_TR_TRIGGER_TYPE_ALL,
725 CPPI5_TR_TRIGGER_TYPE_MAX
726};
727
728typedef u32 cppi5_tr_flags_t;
729
730/* Type 0 (One dimensional data move) TR (16 byte) */
731struct cppi5_tr_type0_t {
732 cppi5_tr_flags_t flags;
733 u16 icnt0;
734 u16 unused;
735 u64 addr;
736} __aligned(16) __packed;
737
738/* Type 1 (Two dimensional data move) TR (32 byte) */
739struct cppi5_tr_type1_t {
740 cppi5_tr_flags_t flags;
741 u16 icnt0;
742 u16 icnt1;
743 u64 addr;
744 s32 dim1;
745} __aligned(32) __packed;
746
747/* Type 2 (Three dimensional data move) TR (32 byte) */
748struct cppi5_tr_type2_t {
749 cppi5_tr_flags_t flags;
750 u16 icnt0;
751 u16 icnt1;
752 u64 addr;
753 s32 dim1;
754 u16 icnt2;
755 u16 unused;
756 s32 dim2;
757} __aligned(32) __packed;
758
759/* Type 3 (Four dimensional data move) TR (32 byte) */
760struct cppi5_tr_type3_t {
761 cppi5_tr_flags_t flags;
762 u16 icnt0;
763 u16 icnt1;
764 u64 addr;
765 s32 dim1;
766 u16 icnt2;
767 u16 icnt3;
768 s32 dim2;
769 s32 dim3;
770} __aligned(32) __packed;
771
772/*
773 * Type 15 (Four Dimensional Block Copy with Repacking and
774 * Indirection Support) TR (64 byte).
775 */
776struct cppi5_tr_type15_t {
777 cppi5_tr_flags_t flags;
778 u16 icnt0;
779 u16 icnt1;
780 u64 addr;
781 s32 dim1;
782 u16 icnt2;
783 u16 icnt3;
784 s32 dim2;
785 s32 dim3;
786 u32 _reserved;
787 s32 ddim1;
788 u64 daddr;
789 s32 ddim2;
790 s32 ddim3;
791 u16 dicnt0;
792 u16 dicnt1;
793 u16 dicnt2;
794 u16 dicnt3;
795} __aligned(64) __packed;
796
797struct cppi5_tr_resp_t {
798 u8 status;
799 u8 reserved;
800 u8 cmd_id;
801 u8 flags;
802} __packed;
803
804#define CPPI5_TR_RESPONSE_STATUS_TYPE_SHIFT (0U)
805#define CPPI5_TR_RESPONSE_STATUS_TYPE_MASK GENMASK(3, 0)
806#define CPPI5_TR_RESPONSE_STATUS_INFO_SHIFT (4U)
807#define CPPI5_TR_RESPONSE_STATUS_INFO_MASK GENMASK(7, 4)
808#define CPPI5_TR_RESPONSE_CMDID_SHIFT (16U)
809#define CPPI5_TR_RESPONSE_CMDID_MASK GENMASK(23, 16)
810#define CPPI5_TR_RESPONSE_CFG_SPECIFIC_SHIFT (24U)
811#define CPPI5_TR_RESPONSE_CFG_SPECIFIC_MASK GENMASK(31, 24)
812
813/*
814 * Udmap TR Response Status Type field is used to determine
815 * what type of status is being returned.
816 */
817enum cppi5_tr_resp_status_type {
818 CPPI5_TR_RESPONSE_STATUS_COMPLETE, /* None */
819 CPPI5_TR_RESPONSE_STATUS_TRANSFER_ERR, /* Transfer Error */
820 CPPI5_TR_RESPONSE_STATUS_ABORTED_ERR, /* Aborted Error */
821 CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ERR, /* Submission Error */
822 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ERR, /* Unsup. Feature */
823 CPPI5_TR_RESPONSE_STATUS_MAX
824};
825
826/*
827 * Udmap TR Response Status field values which corresponds
828 * CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ERR
829 */
830enum cppi5_tr_resp_status_submission {
831 /* ICNT0 was 0 */
832 CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ICNT0,
833 /* Channel FIFO was full when TR received */
834 CPPI5_TR_RESPONSE_STATUS_SUBMISSION_FIFO_FULL,
835 /* Channel is not owned by the submitter */
836 CPPI5_TR_RESPONSE_STATUS_SUBMISSION_OWN,
837 CPPI5_TR_RESPONSE_STATUS_SUBMISSION_MAX
838};
839
840/*
841 * Udmap TR Response Status field values which corresponds
842 * CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ERR
843 */
844enum cppi5_tr_resp_status_unsupported {
845 /* TR Type not supported */
846 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_TR_TYPE,
847 /* STATIC not supported */
848 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_STATIC,
849 /* EOL not supported */
850 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_EOL,
851 /* CONFIGURATION SPECIFIC not supported */
852 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_CFG_SPECIFIC,
853 /* AMODE not supported */
854 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_AMODE,
855 /* ELTYPE not supported */
856 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ELTYPE,
857 /* DFMT not supported */
858 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_DFMT,
859 /* SECTR not supported */
860 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_SECTR,
861 /* AMODE SPECIFIC field not supported */
862 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_AMODE_SPECIFIC,
863 CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_MAX
864};
865
866/**
867 * cppi5_trdesc_calc_size - Calculate TR Descriptor size
868 * @tr_count: number of TR records
869 * @tr_size: Nominal size of TR record (max) [16, 32, 64, 128]
870 *
871 * Returns required TR Descriptor size
872 */
873static inline size_t cppi5_trdesc_calc_size(u32 tr_count, u32 tr_size)
874{
875 /*
876 * The Size of a TR descriptor is:
877 * 1 x tr_size : the first 16 bytes is used by the packet info block +
878 * tr_count x tr_size : Transfer Request Records +
879 * tr_count x sizeof(struct cppi5_tr_resp_t) : Transfer Response Records
880 */
881 return tr_size * (tr_count + 1) +
882 sizeof(struct cppi5_tr_resp_t) * tr_count;
883}
884
885/**
886 * cppi5_trdesc_init - Init TR Descriptor
887 * @desc: TR Descriptor
888 * @tr_count: number of TR records
889 * @tr_size: Nominal size of TR record (max) [16, 32, 64, 128]
890 * @reload_idx: Absolute index to jump to on the 2nd and following passes
891 * through the TR packet.
892 * @reload_count: Number of times to jump from last entry to reload_idx. 0x1ff
893 * indicates infinite looping.
894 *
895 * Init TR Descriptor
896 */
897static inline void cppi5_trdesc_init(struct cppi5_desc_hdr_t *desc_hdr,
898 u32 tr_count, u32 tr_size, u32 reload_idx,
899 u32 reload_count)
900{
901 WARN_ON(!desc_hdr);
902 WARN_ON(tr_count & ~CPPI5_INFO0_TRDESC_LASTIDX_MASK);
903 WARN_ON(reload_idx > CPPI5_INFO0_TRDESC_RLDIDX_MAX);
904 WARN_ON(reload_count > CPPI5_INFO0_TRDESC_RLDCNT_MAX);
905
906 desc_hdr->pkt_info0 = CPPI5_INFO0_DESC_TYPE_VAL_TR <<
907 CPPI5_INFO0_HDESC_TYPE_SHIFT;
908 desc_hdr->pkt_info0 |= (reload_count << CPPI5_INFO0_TRDESC_RLDCNT_SHIFT) &
909 CPPI5_INFO0_TRDESC_RLDCNT_MASK;
910 desc_hdr->pkt_info0 |= (reload_idx << CPPI5_INFO0_TRDESC_RLDIDX_SHIFT) &
911 CPPI5_INFO0_TRDESC_RLDIDX_MASK;
912 desc_hdr->pkt_info0 |= (tr_count - 1) & CPPI5_INFO0_TRDESC_LASTIDX_MASK;
913
914 desc_hdr->pkt_info1 |= ((ffs(tr_size >> 4) - 1) <<
915 CPPI5_INFO1_TRDESC_RECSIZE_SHIFT) &
916 CPPI5_INFO1_TRDESC_RECSIZE_MASK;
917}
918
919/**
920 * cppi5_tr_init - Init TR record
921 * @flags: Pointer to the TR's flags
922 * @type: TR type
923 * @static_tr: TR is static
924 * @wait: Wait for TR completion before allow the next TR to start
925 * @event_size: output event generation cfg
926 * @cmd_id: TR identifier (application specifics)
927 *
928 * Init TR record
929 */
930static inline void cppi5_tr_init(cppi5_tr_flags_t *flags,
931 enum cppi5_tr_types type, bool static_tr,
932 bool wait, enum cppi5_tr_event_size event_size,
933 u32 cmd_id)
934{
935 WARN_ON(!flags);
936
937 *flags = type;
938 *flags |= (event_size << CPPI5_TR_EVENT_SIZE_SHIFT) &
939 CPPI5_TR_EVENT_SIZE_MASK;
940
941 *flags |= (cmd_id << CPPI5_TR_CMD_ID_SHIFT) &
942 CPPI5_TR_CMD_ID_MASK;
943
944 if (static_tr && (type == CPPI5_TR_TYPE8 || type == CPPI5_TR_TYPE9))
945 *flags |= CPPI5_TR_STATIC;
946
947 if (wait)
948 *flags |= CPPI5_TR_WAIT;
949}
950
951/**
952 * cppi5_tr_set_trigger - Configure trigger0/1 and trigger0/1_type
953 * @flags: Pointer to the TR's flags
954 * @trigger0: trigger0 selection
955 * @trigger0_type: type of data transfer that will be enabled by trigger0
956 * @trigger1: trigger1 selection
957 * @trigger1_type: type of data transfer that will be enabled by trigger1
958 *
959 * Configure the triggers for the TR
960 */
961static inline void cppi5_tr_set_trigger(cppi5_tr_flags_t *flags,
962 enum cppi5_tr_trigger trigger0,
963 enum cppi5_tr_trigger_type trigger0_type,
964 enum cppi5_tr_trigger trigger1,
965 enum cppi5_tr_trigger_type trigger1_type)
966{
967 WARN_ON(!flags);
968
969 *flags |= (trigger0 << CPPI5_TR_TRIGGER0_SHIFT) &
970 CPPI5_TR_TRIGGER0_MASK;
971 *flags |= (trigger0_type << CPPI5_TR_TRIGGER0_TYPE_SHIFT) &
972 CPPI5_TR_TRIGGER0_TYPE_MASK;
973
974 *flags |= (trigger1 << CPPI5_TR_TRIGGER1_SHIFT) &
975 CPPI5_TR_TRIGGER1_MASK;
976 *flags |= (trigger1_type << CPPI5_TR_TRIGGER1_TYPE_SHIFT) &
977 CPPI5_TR_TRIGGER1_TYPE_MASK;
978}
979
980/**
981 * cppi5_tr_cflag_set - Update the Configuration specific flags
982 * @flags: Pointer to the TR's flags
983 * @csf: Configuration specific flags
984 *
985 * Set a bit in Configuration Specific Flags section of the TR flags.
986 */
987static inline void cppi5_tr_csf_set(cppi5_tr_flags_t *flags, u32 csf)
988{
989 WARN_ON(!flags);
990
991 *flags |= (csf << CPPI5_TR_CSF_FLAGS_SHIFT) &
992 CPPI5_TR_CSF_FLAGS_MASK;
993}
994
995#endif /* __TI_CPPI5_H__ */