1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40 41 42 43 44 45 46/** 47 * @file 48 * 49 * Interface to the PCI / PCIe DMA engines. These are only avialable 50 * on chips with PCI / PCIe. 51 * 52 * <hr>$Revision: 70030 $<hr> 53 */ 54 55#ifndef __CVMX_DMA_ENGINES_H__ 56#define __CVMX_DMA_ENGINES_H__ 57 58#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 59#include <asm/octeon/cvmx-dpi-defs.h> 60#else 61#include "cvmx-dpi-defs.h" 62#endif 63 64#ifdef __cplusplus 65extern "C" { 66#endif 67 68typedef enum 69{ 70 CVMX_DMA_ENGINE_TRANSFER_OUTBOUND = 0, /**< OUTBOUND (read from L2/DRAM, write into PCI / PCIe memory space) */ 71 CVMX_DMA_ENGINE_TRANSFER_INBOUND = 1, /**< INBOUND (read from PCI / PCIe memory space, write into L2/DRAM) */ 72 CVMX_DMA_ENGINE_TRANSFER_INTERNAL = 2, /**< INTERNAL-ONLY (read from L2/DRAM, write into L2/DRAM). Only available on chips with PCIe */ 73 CVMX_DMA_ENGINE_TRANSFER_EXTERNAL = 3, /**< EXTERNAL-ONLY (read from PCIe memory space, write into PCIe memory space). Only available on chips with PCIe */ 74} cvmx_dma_engine_transfer_t; 75 76typedef union 77{ 78 uint64_t u64; 79 struct 80 { 81 uint64_t reserved_60_63 : 4; /**< Must be zero */ 82 uint64_t fport : 2; /**< First port. FPort indicates the physical PCIe port used for the 83 PCIe memory space pointers in the FIRST POINTERS block in the 84 EXTERNAL-ONLY case. Must be zero in the OUTBOUND, INBOUND and 85 INTERNAL-ONLY cases. Must be zero on chips with PCI */ 86 uint64_t lport : 2; /**< Last port. LPort indicates the physical PCIe port used for the 87 PCIe memory space pointers in the LAST POINTERS block in the 88 OUTBOUND, INBOUND, and EXTERNAL-ONLY cases. Must be zero in the 89 INTERNAL-ONLY case. Must be zero on chips with PCI */ 90 cvmx_dma_engine_transfer_t type : 2; /**< Type � A given PCI DMA transfer is either OUTBOUND (read from L2/DRAM, 91 write into PCI / PCIe memory space), INBOUND (read from PCI / PCIe memory space, write 92 into L2/DRAM), INTERNAL-ONLY (read from L2/DRAM, write into L2/DRAM), or 93 EXTERNAL-ONLY (read from PCIe memory space, write into PCIe memory space). */ 94 uint64_t wqp : 1; /**< Work-queue pointer. When WQP = 1, PTR (if non-zero) is a pointer to a 95 work-queue entry that is submitted by the hardware after completing the DMA; 96 when WQP = 0, PTR (if non-zero) is a pointer to a byte in local memory that 97 is written to 0 by the hardware after completing the DMA. */ 98 uint64_t c : 1; /**< C � Counter. 1 = use counter 1, 0 = use counter 0. 99 The C bit selects between the two counters (NPEI_DMA_CNTS[DMA0,DMA1]) 100 that can optionally be updated after an OUTBOUND or EXTERNAL-ONLY 101 transfer, and also selects between the two forced-interrupt bits 102 (NPEI_INT_SUMn[DMA0_FI, DMA1_FI]) that can optionally be set after an 103 OUTBOUND or EXTERNAL-ONLY transfer. C must be zero for INBOUND or 104 INTERNAL-ONLY transfers. */ 105 uint64_t ca : 1; /**< CA � Counter add. 106 When CA = 1, the hardware updates the selected counter after it completes the 107 PCI DMA OUTBOUND or EXTERNAL-ONLY Instruction. 108 - If C = 0, PCIE_DMA_CNT0 is updated 109 - If C = 1, PCIE_DMA_CNT1 is updated. 110 Note that this update may indirectly cause 111 NPEI_INT_SUM[DCNT0,DCNT1,DTIME0,DTIME1] to become set (depending 112 on the NPEI_DMA*_INT_LEVEL settings), so may cause interrupts to occur on a 113 remote PCI host. 114 - If NPEI_DMA_CONTROL[O_ADD1] = 1, the counter is updated by 1. 115 - If NPEI_DMA_CONTROL[O_ADD1] = 0, the counter is updated by the total 116 bytes in the transfer. 117 When CA = 0, the hardware does not update any counters. 118 For an INBOUND or INTERNAL-ONLY PCI DMA transfer, CA must never be 119 set, and the hardware never adds to the counters. */ 120 uint64_t fi : 1; /**< FI � Force interrupt. 121 When FI is set for an OUTBOUND or EXTERNAL-ONLY transfer, the hardware 122 sets a forced interrupt bit after it completes the PCI DMA Instruction. If C = 0, 123 NPEI_INT_SUMn[DMA0_FI] is set, else NPEI_INT_SUMn[DMA1_FI] is set. For 124 an INBOUND or INTERNAL-ONLY PCI DMA operation, FI must never be set, 125 and the hardware never generates interrupts. */ 126 uint64_t ii : 1; /**< II� Ignore the I bit (i.e. the I bit of the PCI DMA instruction local pointer). 127 For OUTBOUND transfers when II = 1, ignore the I bit and the FL bit in the 128 DMA HDR alone determines whether the hardware frees any/all of the local 129 buffers in the FIRST POINTERS area: 130 - when FL = 1, the hardware frees the local buffer when II=1. 131 - when FL = 0, the hardware does not free the local buffer when II=1. 132 For OUTBOUND transfers when II = 0, the I bit in the local pointer selects 133 whether local buffers are freed on a pointer-by-pointer basis: 134 - when (FL I) is true, the hardware frees the local buffer when II=0. 135 For INBOUND, INTERNAL-ONLY, and EXTERNAL-ONLY PCI DMA transfers, 136 II must never be set, and local buffers are never freed. */ 137 uint64_t fl : 1; /**< FL � Free local buffer. 138 When FL = 1, for an OUTBOUND operation, it indicates that the local buffers in 139 the FIRST BUFFERS area should be freed. 140 If II = 1, the FL bit alone indicates whether the local buffer should be freed: 141 - when FL = 1, the hardware frees the local buffer when II=1. 142 - when FL = 0, the hardware does not free the local buffer when II=1. 143 If II = 0, the I bit in the local pointer (refer to Section 9.5.2) determines whether 144 the local buffer is freed: 145 - when (FL I) is true, the hardware frees the local buffer when II=0. 146 For an INBOUND, INTERNAL-ONLY, or EXTERNAL-ONLY PCI DMA transfer, 147 FL must never be set, and local buffers are never freed. */ 148 uint64_t nlst : 4; /**< NLST � Number Last pointers. 149 The number of pointers in the LAST POINTERS area. 150 In the INBOUND, OUTBOUND, and EXTERNAL-ONLY cases, the LAST 151 POINTERS area contains PCI components, and the number of 64-bit words 152 required in the LAST POINTERS area is: 153 - HDR.NLST + ((HDR.NLST + 3)/4) where the division removes the fraction. 154 In the INTERNAL-ONLY case, the LAST POINTERS area contains local 155 pointers, and the number of 64-bit words required in the LAST POINTERS area is: 156 - HDR.NLST 157 Note that the sum of the number of 64-bit words in the LAST POINTERS and 158 FIRST POINTERS area must never exceed 31. */ 159 uint64_t nfst : 4; /**< NFST � Number First pointers. 160 The number of pointers in the FIRST POINTERS area. 161 In the INBOUND, OUTBOUND, and INTERNAL-ONLY cases, the FIRST 162 POINTERS area contains local pointers, and the number of 64-bit words required 163 in the FIRST POINTERS area is: 164 - HDR.NFST 165 In the EXTERNAL-ONLY case, the FIRST POINTERS area contains PCI 166 components, and the number of 64-bit words required in the FIRST POINTERS 167 area is: 168 - HDR.NFST + ((HDR.NFST + 3)/4) where the division removes the fraction. */ 169 uint64_t addr : 40; /**< PTR � Pointer, either a work-queue-entry pointer (when WQP = 1) or a local 170 memory pointer (WQP = 0). 171 When WQP = 1 and PTR 0x0, the hardware inserts the work-queue entry 172 indicated by PTR into a POW input queue after the PCI DMA operation is 173 complete. (Section 5.4 describes the work queue entry requirements in this 174 case.) When WQP = 1, PTR<2:0> must be 0x0. 175 When WQP = 0 and PTR 0x0, the hardware writes the single byte in local 176 memory indicated by PTR to 0x0 after the PCI DMA operation is complete. 177 NPEI_DMA_CONTROL[B0_LEND] selects the endian-ness of PTR in this 178 case. 179 When PTR = 0x0, the hardware performs no operation after the PCI DMA 180 operation is complete. */ 181 } s; 182} cvmx_dma_engine_header_t; 183 184typedef union 185{ 186 uint64_t u64; 187 struct 188 { 189 uint64_t i : 1; /**< I � Invert free. 190 This bit gives the software the ability to free buffers independently for an 191 OUTBOUND PCI DMA transfer. I is not used by the hardware when II is set. I 192 must not be set, and buffers are never freed, for INBOUND, INTERNAL-ONLY, 193 and EXTERNAL-ONLY PCI DMA transfers. */ 194 uint64_t back : 4; /**< Back � Backup amount. 195 Allows the start of a buffer that is to be freed during an OUTBOUND transfer to 196 be different from the ptr value. Back specifies the amount to subtract from the 197 pointer to reach the start when freeing a buffer. 198 The address that is the start of the buffer being freed is: 199 - Buffer start address = ((ptr >> 7) - Back) << 7. 200 Back is only used by the hardware when the buffer corresponding to ptr is freed. 201 Back must be 0x0, and buffers are never freed, for INBOUND, INTERNAL-ONLY, 202 and EXTERNAL-ONLY PCI DMA transfers. */ 203 uint64_t pool : 3; /**< Pool � Free pool. 204 Specifies which pool (of the eight hardware-managed FPA free pools) receives the 205 buffer associated with ptr when freed during an OUTBOUND transfer. 206 Pool is only used when the buffer corresponding to ptr is freed. Pool must be 0x0, 207 and buffers are never freed, for INBOUND, INTERNAL-ONLY, and EXTERNAL-ONLY 208 PCI DMA transfers. */ 209 uint64_t f : 1; /**< F � Full-block writes are allowed. 210 When set, the hardware is permitted to write all the bytes in the cache blocks 211 covered by ptr, ptr + Size - 1. This can improve memory system performance 212 when the write misses in the L2 cache. 213 F can only be set for local pointers that can be written to: 214 - The local pointers in the FIRST POINTERS area that are write pointers for 215 INBOUND transfers. 216 - The local pointers in the LAST POINTERS area that are always write 217 pointers (when present for INTERNAL-ONLY transfers). 218 F must not be set for local pointers that are not written to: 219 - The local pointers in the FIRST POINTERS area for OUTBOUND and 220 INTERNAL-ONLY transfers. */ 221 uint64_t a : 1; /**< A � Allocate L2. 222 This is a hint to the hardware that the cache blocks should be allocated in the L2 223 cache (if they were not already). */ 224 uint64_t l : 1; /**< L � Little-endian. 225 When L is set, the data at ptr is in little-endian format rather than big-endian. */ 226 uint64_t size : 13; /**< Size � Size in bytes of the contiguous space specified by ptr. A Size value of 0 is 227 illegal. Note that the sum of the sizes in the FIRST POINTERS area must always 228 exactly equal the sum of the sizes/lengths in the LAST POINTERS area: 229 - In the OUTBOUND and INBOUND cases, the HDR.NFST size fields in the 230 local pointers in the FIRST POINTERS area must exactly equal the lengths 231 of the HDR.NLST fragments in the PCI components in the LAST POINTERS 232 area. 233 - In the INTERNAL-ONLY case, the HDR.NFST size fields in the local 234 pointers in the FIRST POINTERS area must equal the HDR.NLST size 235 fields in the local pointers in the LAST POINTERS area. */ 236 uint64_t reserved_36_39 : 4; /**< Must be zero */ 237 uint64_t addr : 36; /**< L2/DRAM byte pointer. Points to where the packet data starts. 238 Ptr can be any byte alignment. Note that ptr is interpreted as a big-endian byte 239 pointer when L is clear, a little-endian byte pointer when L is set. */ 240 } internal; 241 struct 242 { 243 uint64_t len0 : 16; /**< Length of PCI / PCIe memory for address 0 */ 244 uint64_t len1 : 16; /**< Length of PCI / PCIe memory for address 1 */ 245 uint64_t len2 : 16; /**< Length of PCI / PCIe memory for address 2 */ 246 uint64_t len3 : 16; /**< Length of PCI / PCIe memory for address 3 */ 247 } pcie_length; 248} cvmx_dma_engine_buffer_t; 249 250/** 251 * Initialize the DMA engines for use 252 * 253 * @return Zero on success, negative on failure 254 */ 255int cvmx_dma_engine_initialize(void); 256 257/** 258 * Shutdown all DMA engines. The engeines must be idle when this 259 * function is called. 260 * 261 * @return Zero on success, negative on failure 262 */ 263int cvmx_dma_engine_shutdown(void); 264 265/** 266 * Return the number of DMA engimes supported by this chip 267 * 268 * @return Number of DMA engines 269 */ 270int cvmx_dma_engine_get_num(void); 271 272/** 273 * Submit a series of DMA command to the DMA engines. 274 * 275 * @param engine Engine to submit to (0 to cvmx_dma_engine_get_num()-1) 276 * @param header Command header 277 * @param num_buffers 278 * The number of data pointers 279 * @param buffers Command data pointers 280 * 281 * @return Zero on success, negative on failure 282 */ 283int cvmx_dma_engine_submit(int engine, cvmx_dma_engine_header_t header, int num_buffers, cvmx_dma_engine_buffer_t buffers[]); 284 285/** 286 * Build the first and last pointers based on a DMA engine header 287 * and submit them to the engine. The purpose of this function is 288 * to simplify the building of DMA engine commands by automatically 289 * converting a simple address and size into the apropriate internal 290 * or PCI / PCIe address list. This function does not support gather lists, 291 * so you will need to build your own lists in that case. 292 * 293 * @param engine Engine to submit to (0 to cvmx_dma_engine_get_num()-1) 294 * @param header DMA Command header. Note that the nfst and nlst fields do not 295 * need to be filled in. All other fields must be set properly. 296 * @param first_address 297 * Address to use for the first pointers. In the case of INTERNAL, 298 * INBOUND, and OUTBOUND this is an Octeon memory address. In the 299 * case of EXTERNAL, this is the source PCI / PCIe address. 300 * @param last_address 301 * Address to use for the last pointers. In the case of EXTERNAL, 302 * INBOUND, and OUTBOUND this is a PCI / PCIe address. In the 303 * case of INTERNAL, this is the Octeon memory destination address. 304 * @param size Size of the transfer to perform. 305 * 306 * @return Zero on success, negative on failure 307 */ 308int cvmx_dma_engine_transfer(int engine, cvmx_dma_engine_header_t header, 309 uint64_t first_address, uint64_t last_address, 310 int size); 311 312/** 313 * Simplified interface to the DMA engines to emulate memcpy() 314 * 315 * @param engine Engine to submit to (0 to cvmx_dma_engine_get_num()-1) 316 * @param dest Pointer to the destination memory. cvmx_ptr_to_phys() will be 317 * used to turn this into a physical address. It cannot be a local 318 * or CVMX_SHARED block. 319 * @param source Pointer to the source memory. 320 * cvmx_ptr_to_phys() will be used to turn this 321 * into a physical address. It cannot be a local 322 * or CVMX_SHARED block. 323 * @param length Number of bytes to copy 324 * 325 * @return Zero on success, negative on failure 326 */ 327static inline int cvmx_dma_engine_memcpy(int engine, void *dest, void *source, int length) 328{ 329 cvmx_dma_engine_header_t header; 330 header.u64 = 0; 331 header.s.type = CVMX_DMA_ENGINE_TRANSFER_INTERNAL; 332 return cvmx_dma_engine_transfer(engine, header, cvmx_ptr_to_phys(source), 333 cvmx_ptr_to_phys(dest), length); 334} 335 336/** 337 * Simplified interface to the DMA engines to emulate memcpy() 338 * When dici_mode is enabled, send zero byte. 339 * 340 * @param engine Engine to submit to (0 to cvmx_dma_engine_get_num()-1) 341 * @param dest Pointer to the destination memory. cvmx_ptr_to_phys() will be 342 * used to turn this into a physical address. It cannot be a local 343 * or CVMX_SHARED block. 344 * @param source Pointer to the source memory. 345 * cvmx_ptr_to_phys() will be used to turn this 346 * into a physical address. It cannot be a local 347 * or CVMX_SHARED block. 348 * @param length Number of bytes to copy 349 * @param core core number for zero byte write 350 * 351 * @return Zero on success, negative on failure 352 */ 353static inline int cvmx_dma_engine_memcpy_zero_byte(int engine, void *dest, void *source, int length, int core) 354{ 355 cvmx_dma_engine_header_t header; 356 header.u64 = 0; 357 header.s.type = CVMX_DMA_ENGINE_TRANSFER_INTERNAL; 358 /* If dici_mode is set, DPI increments the DPI_DMA_PPn_CNT[CNT], where the 359 value of core n is PTR<5:0>-1 when WQP=0 and PTR != 0 && PTR < 64. */ 360 if (octeon_has_feature(OCTEON_FEATURE_DICI_MODE)) 361 { 362 cvmx_dpi_dma_control_t dma_control; 363 dma_control.u64 = cvmx_read_csr(CVMX_DPI_DMA_CONTROL); 364 if (dma_control.s.dici_mode) 365 { 366 header.s.wqp = 0; // local memory pointer 367 header.s.addr = core + 1; 368 } 369 } 370 return cvmx_dma_engine_transfer(engine, header, cvmx_ptr_to_phys(source), 371 cvmx_ptr_to_phys(dest), length); 372} 373 374#ifdef __cplusplus 375} 376#endif 377 378#endif // __CVMX_CMD_QUEUE_H__ 379