1 /* 2 * Copyright (c) 2023 Intel Corporation 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef _SEDI_DRIVER_DMA_H_ 8 #define _SEDI_DRIVER_DMA_H_ 9 10 #ifdef __cplusplus 11 extern "C" { 12 #endif 13 14 #include "sedi_driver_common.h" 15 16 /*! 17 * \defgroup sedi_driver_dma DMA 18 * \ingroup sedi_driver 19 */ 20 21 #define SEDI_DMA_API_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(0, 1) 22 23 #define DMA_CHANNEL_NUM 8 24 25 /****** DMA Control Codes *****/ 26 27 /*! 28 * \defgroup dma_control_codes DMA Control Codes 29 * \ingroup sedi_driver_dma 30 * \{ 31 */ 32 33 typedef enum { 34 SEDI_CONFIG_DMA_DIRECTION = 0, 35 SEDI_CONFIG_DMA_SR_MEM_TYPE, 36 SEDI_CONFIG_DMA_DT_MEM_TYPE, 37 SEDI_CONFIG_DMA_LL_SR_MSB, /* MSB bits of source addr in LL mode*/ 38 SEDI_CONFIG_DMA_LL_DT_MSB, /* MSB bits of destination addr in LL mode*/ 39 SEDI_CONFIG_DMA_BURST_LENGTH, 40 SEDI_CONFIG_DMA_SR_TRANS_WIDTH, 41 SEDI_CONFIG_DMA_DT_TRANS_WIDTH, 42 SEDI_CONFIG_DMA_HS_DEVICE_ID, 43 SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, 44 SEDI_CONFIG_DMA_HS_POLARITY, 45 SEDI_CONFIG_DMA_CONTROL_ID_MAX 46 } dma_control_code; 47 48 /*! 49 * DMA Burst Transfer Length 50 */ 51 typedef enum { 52 DMA_BURST_TRANS_LENGTH_1 = 0x0, /**< Burst length 1 data item. */ 53 DMA_BURST_TRANS_LENGTH_4 = 0x1, /**< Burst length 4 data items. */ 54 DMA_BURST_TRANS_LENGTH_8 = 0x2, /**< Burst length 8 data items. */ 55 DMA_BURST_TRANS_LENGTH_16 = 0x3, /**< Burst length 16 data items. */ 56 DMA_BURST_TRANS_LENGTH_32 = 0x4, /**< Burst length 32 data items. */ 57 DMA_BURST_TRANS_LENGTH_64 = 0x5, /**< Burst length 64 data items. */ 58 DMA_BURST_TRANS_LENGTH_128 = 0x6, /**< Burst length 128 data items. */ 59 DMA_BURST_TRANS_LENGTH_256 = 0x7, /**< Burst length 256 data items. */ 60 DMA_BURST_TRANS_LENGTH_MAX 61 } dma_burst_length_t; 62 63 /*! 64 * DMA Transfer Width 65 */ 66 typedef enum { 67 DMA_TRANS_WIDTH_8 = 0x0, /**< Transfer width of 8 bits. */ 68 DMA_TRANS_WIDTH_16 = 0x1, /**< Transfer width of 16 bits. */ 69 DMA_TRANS_WIDTH_32 = 0x2, /**< Transfer width of 32 bits. */ 70 DMA_TRANS_WIDTH_64 = 0x3, /**< Transfer width of 64 bits. */ 71 DMA_TRANS_WIDTH_128 = 0x4, /**< Transfer width of 128 bits. */ 72 DMA_TRANS_WIDTH_256 = 0x5, /**< Transfer width of 256 bits. */ 73 DMA_TRANS_WIDTH_MAX 74 } dma_transfer_width_t; 75 76 /*! 77 * DMA channel direction. 78 */ 79 typedef enum { 80 DMA_MEMORY_TO_MEMORY = 0x0, /**< Memory to memory transfer. */ 81 DMA_MEMORY_TO_PERIPHERAL = 0x1, /**< Memory to peripheral transfer.*/ 82 DMA_PERIPHERAL_TO_MEMORY = 0x2, /**< Peripheral to memory transfer. */ 83 DMA_PERIPHERAL_TO_PERIPHERAL = 0x3, /**< Peripheral to peripheral. */ 84 DMA_DIRECTION_MAX 85 } dma_channel_direction_t; 86 87 typedef enum { 88 DMA_SRAM_MEM = 0x0, 89 DMA_DRAM_MEM = 0x1, 90 DMA_UMA_MEM = 0x2, 91 DMA_MEM_TYPE_MAX 92 } dma_memory_type_t; 93 /*! 94 * handshake polarity 95 */ 96 typedef enum { 97 DMA_HS_POLARITY_HIGH = 0x0, /* handshake polarity high */ 98 DMA_HS_POLARITY_LOW = 0x1, /* handshake polarity low*/ 99 DMA_HS_POLARITY_MAX 100 } dma_hs_polarity_t; 101 102 /*! 103 * dma handshake rx/tx 104 */ 105 typedef enum { 106 DMA_HS_PER_RX = 0x0, /* handshake peripheral rx */ 107 DMA_HS_PER_TX = 0x1, /* handshake peripheral tx */ 108 DMA_HS_PER_RTX_MAX 109 } dma_hs_per_rtx_t; 110 111 typedef enum { DMA_INCREMENT_INC, DMA_INCREMENT_NO_CHANGE } dma_increment_t; 112 113 /* dma channel control register bit map details*/ 114 #define LLP_SRC_EN_LOC 28 115 #define LLP_DST_EN_LOC 27 116 #define TT_FC_LOC 20 117 #define SRC_MSIZE_LOC 14 118 #define DEST_MSIZE_LOC 11 119 #define SINC_LOC 10 120 #define DINC_LOC 8 121 #define SRC_TR_WIDTH_LOC 4 122 #define DST_TR_WIDTH_LOC 1 123 #define INT_EN_LOC 0 124 125 #define BUILD_LL_CTRL_REG(direction, src_burst, dst_burst, src_width, \ 126 dst_width, sinc, dinc) \ 127 ((direction << TT_FC_LOC) | (sinc << SINC_LOC) | (dinc << DINC_LOC) | \ 128 (src_burst << SRC_MSIZE_LOC) | (dst_burst << DEST_MSIZE_LOC) | \ 129 (src_width << SRC_TR_WIDTH_LOC) | (dst_width << DST_TR_WIDTH_LOC) | \ 130 (1 << LLP_DST_EN_LOC) | (1 << LLP_SRC_EN_LOC) | (1 << INT_EN_LOC)) 131 132 #define BUILD_LL_M2M_CTRL_REG(src_burst, dst_burst, src_width, dst_width) \ 133 BUILD_LL_CTRL_REG(DMA_MEMORY_TO_MEMORY, src_burst, dst_burst, \ 134 src_width, dst_width, DMA_INCREMENT_INC, \ 135 DMA_INCREMENT_INC) 136 137 #define BUILD_LL_M2P_CTRL_REG(src_burst, dst_burst, src_width, dst_width) \ 138 BUILD_LL_CTRL_REG(DMA_MEMORY_TO_PERIPHERAL, src_burst, dst_burst, \ 139 src_width, dst_width, DMA_INCREMENT_INC, \ 140 DMA_INCREMENT_NO_CHANGE) 141 142 #define BUILD_LL_P2M_CTRL_REG(src_burst, dst_burst, src_width, dst_width) \ 143 BUILD_LL_CTRL_REG(DMA_PERIPHERAL_TO_MEMORY, src_burst, dst_burst, \ 144 src_width, dst_width, DMA_INCREMENT_NO_CHANGE, \ 145 DMA_INCREMENT_INC) 146 /*! 147 * list item for DMA linker list mode. 148 */ 149 typedef struct dma_linked_list_item { 150 uint32_t src_addr; /**< Block source address. */ 151 uint32_t dst_addr; /**< Block destination address. */ 152 /**< Pointer to next LLI. */ 153 const struct dma_linked_list_item *next_ll_p; 154 /**< Bottom half Ctrl register. */ 155 union { 156 uint32_t raw; 157 struct { 158 uint32_t int_en : 1; 159 uint32_t dst_tr_width : 3; 160 uint32_t src_tr_width : 3; 161 uint32_t resvd0 : 1; 162 uint32_t dinc : 1; 163 uint32_t rsevd1 : 1; 164 uint32_t sinc : 1; 165 uint32_t dest_burst_len : 3; 166 uint32_t src_burst_len : 3; 167 uint32_t resvd2 : 1; 168 uint32_t resvd3 : 1; 169 uint32_t resvd4 : 1; 170 uint32_t direction : 2; 171 uint32_t resvd5 : 5; 172 uint32_t llp_dst_en : 1; 173 uint32_t llp_src_en : 1; 174 uint32_t resvd6 : 3; 175 } bits; 176 } ctrl_low; 177 /**< Top half Ctrl register. */ 178 union { 179 uint32_t raw; 180 struct { 181 uint32_t resvd0 : 15; 182 uint32_t block_size : 17; 183 }; 184 } ctrl_high; 185 /* write backs for D/S STAT*/ 186 uint32_t dstat; 187 uint32_t sstat; 188 } dma_linked_list_item_t; 189 190 /*! 191 * \} 192 */ 193 194 /****** DMA Event *****/ 195 196 /*! 197 * \defgroup dma_event DMA Event Types 198 * \ingroup sedi_driver_dma 199 * \{ 200 */ 201 202 /*! 203 * \def SEDI_DMA_EVENT_TRANSFER_DONE 204 * \brief DMA transfer finished 205 */ 206 #define SEDI_DMA_EVENT_TRANSFER_DONE (1UL << 0) 207 208 /*! 209 * \def SEDI_DMA_EVENT_TRANSFER_INCOMPLETE 210 * \brief DMA incomplete transfer 211 */ 212 #define SEDI_DMA_EVENT_TRANSFER_INCOMPLETE (1UL << 1) 213 214 /*! 215 * \def SEDI_DMA_EVENT_BUSY 216 * \brief DMA is busy 217 */ 218 #define SEDI_DMA_EVENT_BUSY (1UL << 2) 219 220 /*! 221 * \def SEDI_DMA_EVENT_BUS_ERROR 222 * \brief Bus error detected 223 */ 224 #define SEDI_DMA_EVENT_BUS_ERROR (1UL << 3) 225 226 /*! 227 * \} 228 */ 229 230 /*! 231 * \struct sedi_dma_status_t 232 * \brief DMA Status 233 * \ingroup sedi_driver_dma 234 */ 235 typedef struct { 236 /**< Busy flag */ 237 uint32_t busy : 1; 238 uint32_t bus_error : 1; 239 uint32_t reserved : 30; 240 } sedi_dma_status_t; 241 242 /*! 243 * \struct sedi_dma_capabilities_t 244 * \brief DMA Driver Capabilities. 245 * \ingroup sedi_driver_dma 246 */ 247 typedef struct { 248 uint32_t is_available : 1; /** 1:available 0:used by host **/ 249 uint32_t reserved : 31; /**< Reserved (must be zero) */ 250 } sedi_dma_capabilities_t; 251 252 /*! 253 * \struct dma_sc_attr_t 254 * \brief DMA scatter gather attributions 255 * \ingroup sedi_driver_dma 256 */ 257 typedef struct { 258 uint32_t src_addr; 259 uint32_t dst_addr; 260 uint32_t block_size; 261 uint32_t interval; 262 uint8_t is_scatter; 263 uint8_t need_reload; 264 } sc_attr_t; 265 266 /*! 267 * \defgroup dma_event_handler DMA Event Handler Callback 268 * \ingroup sedi_driver_dma 269 * \{ 270 */ 271 272 /*! 273 * \typedef sedi_dma_event_cb_t 274 * \brief Callback function type for signal dma event. 275 * \param[in] event: event type. see \ref dma_event 276 * \param[in] dma_device: dma device id 277 * \param[in] channel_id: dma channel id 278 * \param[inout] param: other params 279 * \return void 280 */ 281 typedef void (*sedi_dma_event_cb_t)(IN sedi_dma_t dma_device, IN int channel_id, 282 IN int event, INOUT void *param); 283 284 /*! 285 * \} 286 */ 287 288 /*! 289 * \defgroup dma_function_calls DMA Driver Function Calls 290 * \ingroup sedi_driver_dma 291 * \{ 292 */ 293 294 /*! 295 * \brief Get the dma driver's API version. 296 * \return the version of current dma driver's API 297 */ 298 sedi_driver_version_t sedi_dma_get_version(void); 299 300 /*! 301 * \brief Get the device's capabilities. 302 * \param[in] dma_device: dma device id 303 * \param[inout] cap: the capabilities of specific dma device 304 * \return \ref return_status 305 */ 306 int sedi_dma_get_capabilities(IN sedi_dma_t dma_device, 307 INOUT sedi_dma_capabilities_t *cap); 308 309 /*! 310 * \brief Initialize the device 311 * \param[in] dma_device: dma device id 312 * \param[in] channel_id: dma channel id 313 * \param[in] cb: the callback function which can receive device's events. 314 * \param[inout] param: the user defined callback param, like controller point. 315 * \return \ref return_status 316 */ 317 int32_t sedi_dma_init(IN sedi_dma_t dma_device, IN int channel_id, 318 IN sedi_dma_event_cb_t cb, INOUT void *param); 319 320 /*! 321 * \brief Uninitialize the device 322 * \param[in] dma_device: dma device id 323 * \return \ref return_status 324 */ 325 int32_t sedi_dma_uninit(IN sedi_dma_t dma_device, IN int channel_id); 326 327 /*! 328 * \brief Set the device's power 329 * \param[in] dma_device: dma device id 330 * \param[in] channel_id: dma channel id 331 * \param[in] state: the power state to be set to the device 332 * \return \ref return_status 333 */ 334 int32_t sedi_dma_set_power(IN sedi_dma_t dma_device, IN int channel_id, 335 IN sedi_power_state_t state); 336 337 /*! 338 * \brief Control the dma device 339 * \param[in] dma_device: dma device id 340 * \param[in] channel_id: dma channel id 341 * \param[in] control: control operation code. see \ref dma_control_codes 342 * \param[in] arg: argument of operation (optional) 343 * \return \ref return_status 344 */ 345 int32_t sedi_dma_control(IN sedi_dma_t dma_device, IN int channel_id, 346 IN uint32_t control_id, IN uint32_t arg); 347 348 /*! 349 * \brief Get device's status 350 * \param[in] dma_device: dma device id 351 * \param[in] channel_id: dma channel id 352 * \param[out] status: the memory pointer for dma status 353 * \return \ref return_status 354 */ 355 int sedi_dma_get_status(IN sedi_dma_t dma_device, IN int channel_id, 356 OUT sedi_dma_status_t *status); 357 358 /*! 359 * \brief fill up linked-list node with given configuration 360 * \param[inout] ll_p: linked list pointer to fill up 361 * \param[in] src_addr: source addr 362 * \param[in] dst_addr: destination addr 363 * \param[in] block_size: transfer data length 364 * \param[in] ctrl_reg_low: control register lower 32-bitcontent 365 * \param[in] ll_p_next: the pointer to next node, set NULL for the last one 366 * \return \ref return_status 367 */ 368 int dma_fill_linkedlist(INOUT dma_linked_list_item_t *ll_p, 369 IN uint32_t src_addr, IN uint32_t dst_addr, 370 IN uint32_t block_size, IN uint32_t ctrl_reg_low, 371 IN dma_linked_list_item_t *ll_p_next); 372 373 /*! 374 * \brief fill up linked-list node with given scatter gather configuration 375 * \param[inout] ll_p: linked list pointer to fill up 376 * \param[in] count: linked-list node count 377 * \param[in] ctrl_reg_low: control register lower 32-bitcontent 378 * \param[in] attr: scatter gather attributions 379 * \return \ref return_status 380 */ 381 int dma_fill_sc_linkedlist(INOUT dma_linked_list_item_t *llp, 382 IN uint8_t count, IN uint32_t ctrl_reg_low, 383 IN sc_attr_t *attr); 384 385 /*! 386 * \brief transfer data with dma in linked-list mode 387 * \param[in] dma_device: dma device id 388 * \param[in] channel_id: dma channel id 389 * \param[in] linkedlist_header: linked list header indicating the transferring 390 * \return \ref return_status 391 */ 392 int32_t 393 sedi_dma_start_ll_transfer(IN sedi_dma_t dma_device, IN int channel_id, 394 IN dma_linked_list_item_t *linkedlist_header); 395 396 /*! 397 * \brief transfer data with dma 398 * \param[in] dma_device: dma device id 399 * \param[in] channel_id: dma channel id 400 * \param[in] sr_addr: source addr 401 * \param[in] dest_addr: destination addr 402 * \param[in] length: transfer data length 403 * \return \ref return_status 404 */ 405 int32_t sedi_dma_start_transfer(IN sedi_dma_t dma_device, IN int channel_id, 406 IN uint64_t sr_addr, IN uint64_t dest_addr, 407 IN uint32_t length); 408 409 /*! 410 * \brief transfer data with dma in pulling mode 411 * \param[in] dma_device: dma device id 412 * \param[in] channel_id: dma channel id 413 * \param[in] sr_addr: source addr 414 * \param[in] dest_addr: destination addr 415 * \param[in] length: transfer data length 416 * \return \ref return_status 417 */ 418 int32_t sedi_dma_start_transfer_polling(IN sedi_dma_t dma_device, 419 IN int channel_id, IN uint64_t sr_addr, 420 IN uint64_t dest_addr, 421 IN uint32_t length); 422 /*! 423 * \brief abort dma transfer in process 424 * \param[in] dma_device: dma device id 425 * \param[in] channel_id: dma channel id 426 * \return \ref return_status 427 */ 428 int32_t sedi_dma_abort_transfer(IN sedi_dma_t dma_device, IN int channel_id); 429 430 int32_t sedi_dma_get_done_status(IN sedi_dma_t dma_device, IN int channel_id, 431 OUT uint32_t *done_bytes, OUT dma_linked_list_item_t **next_llp); 432 /*! 433 * \} 434 */ 435 436 #ifdef __cplusplus 437 } 438 #endif 439 440 #endif /* _SEDI_DRIVER_DMA_H_*/ 441