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