xref: /freebsd/sys/contrib/alpine-hal/al_hal_udma.h (revision d002f039aeb370370cd2cba63ad55cc4cf16c932)
149b49cdaSZbigniew Bodek /*-
249b49cdaSZbigniew Bodek *******************************************************************************
349b49cdaSZbigniew Bodek Copyright (C) 2015 Annapurna Labs Ltd.
449b49cdaSZbigniew Bodek 
549b49cdaSZbigniew Bodek This file may be licensed under the terms of the Annapurna Labs Commercial
649b49cdaSZbigniew Bodek License Agreement.
749b49cdaSZbigniew Bodek 
849b49cdaSZbigniew Bodek Alternatively, this file can be distributed under the terms of the GNU General
949b49cdaSZbigniew Bodek Public License V2 as published by the Free Software Foundation and can be
1049b49cdaSZbigniew Bodek found at http://www.gnu.org/licenses/gpl-2.0.html
1149b49cdaSZbigniew Bodek 
1249b49cdaSZbigniew Bodek Alternatively, redistribution and use in source and binary forms, with or
1349b49cdaSZbigniew Bodek without modification, are permitted provided that the following conditions are
1449b49cdaSZbigniew Bodek met:
1549b49cdaSZbigniew Bodek 
1649b49cdaSZbigniew Bodek     *     Redistributions of source code must retain the above copyright notice,
1749b49cdaSZbigniew Bodek this list of conditions and the following disclaimer.
1849b49cdaSZbigniew Bodek 
1949b49cdaSZbigniew Bodek     *     Redistributions in binary form must reproduce the above copyright
2049b49cdaSZbigniew Bodek notice, this list of conditions and the following disclaimer in
2149b49cdaSZbigniew Bodek the documentation and/or other materials provided with the
2249b49cdaSZbigniew Bodek distribution.
2349b49cdaSZbigniew Bodek 
2449b49cdaSZbigniew Bodek THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2549b49cdaSZbigniew Bodek ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2649b49cdaSZbigniew Bodek WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2749b49cdaSZbigniew Bodek DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
2849b49cdaSZbigniew Bodek ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2949b49cdaSZbigniew Bodek (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3049b49cdaSZbigniew Bodek LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3149b49cdaSZbigniew Bodek ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3249b49cdaSZbigniew Bodek (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3349b49cdaSZbigniew Bodek SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3449b49cdaSZbigniew Bodek 
3549b49cdaSZbigniew Bodek *******************************************************************************/
3649b49cdaSZbigniew Bodek 
3749b49cdaSZbigniew Bodek /**
3849b49cdaSZbigniew Bodek  * @defgroup group_udma_api API
3949b49cdaSZbigniew Bodek  * @ingroup group_udma
4049b49cdaSZbigniew Bodek  * UDMA API
4149b49cdaSZbigniew Bodek  * @{
4249b49cdaSZbigniew Bodek  * @}
4349b49cdaSZbigniew Bodek  *
4449b49cdaSZbigniew Bodek  * @defgroup group_udma_main UDMA Main
4549b49cdaSZbigniew Bodek  * @ingroup group_udma_api
4649b49cdaSZbigniew Bodek  * UDMA main API
4749b49cdaSZbigniew Bodek  * @{
4849b49cdaSZbigniew Bodek  * @file   al_hal_udma.h
4949b49cdaSZbigniew Bodek  *
5049b49cdaSZbigniew Bodek  * @brief C Header file for the Universal DMA HAL driver
5149b49cdaSZbigniew Bodek  *
5249b49cdaSZbigniew Bodek  */
5349b49cdaSZbigniew Bodek 
5449b49cdaSZbigniew Bodek #ifndef __AL_HAL_UDMA_H__
5549b49cdaSZbigniew Bodek #define __AL_HAL_UDMA_H__
5649b49cdaSZbigniew Bodek 
5749b49cdaSZbigniew Bodek #include "al_hal_common.h"
5849b49cdaSZbigniew Bodek #include "al_hal_udma_regs.h"
5949b49cdaSZbigniew Bodek 
6049b49cdaSZbigniew Bodek /* *INDENT-OFF* */
6149b49cdaSZbigniew Bodek #ifdef __cplusplus
6249b49cdaSZbigniew Bodek extern "C" {
6349b49cdaSZbigniew Bodek #endif
6449b49cdaSZbigniew Bodek /* *INDENT-ON* */
6549b49cdaSZbigniew Bodek 
6649b49cdaSZbigniew Bodek #define DMA_MAX_Q 	4
6749b49cdaSZbigniew Bodek #define AL_UDMA_MIN_Q_SIZE 	4
6849b49cdaSZbigniew Bodek #define AL_UDMA_MAX_Q_SIZE 	(1 << 16) /* hw can do more, but we limit it */
6949b49cdaSZbigniew Bodek 
7049b49cdaSZbigniew Bodek /* Default Max number of descriptors supported per action */
7149b49cdaSZbigniew Bodek #define AL_UDMA_DEFAULT_MAX_ACTN_DESCS	16
7249b49cdaSZbigniew Bodek 
7349b49cdaSZbigniew Bodek #define AL_UDMA_REV_ID_1	1
7449b49cdaSZbigniew Bodek #define AL_UDMA_REV_ID_2	2
7549b49cdaSZbigniew Bodek 
7649b49cdaSZbigniew Bodek #define DMA_RING_ID_MASK	0x3
7749b49cdaSZbigniew Bodek /* New registers ?? */
7849b49cdaSZbigniew Bodek /* Statistics - TBD */
7949b49cdaSZbigniew Bodek 
8049b49cdaSZbigniew Bodek /** UDMA submission descriptor */
8149b49cdaSZbigniew Bodek union al_udma_desc {
8249b49cdaSZbigniew Bodek 	/* TX */
8349b49cdaSZbigniew Bodek 	struct {
8449b49cdaSZbigniew Bodek 		uint32_t len_ctrl;
8549b49cdaSZbigniew Bodek 		uint32_t meta_ctrl;
8649b49cdaSZbigniew Bodek 		uint64_t buf_ptr;
8749b49cdaSZbigniew Bodek 	} tx;
8849b49cdaSZbigniew Bodek 	/* TX Meta, used by upper layer */
8949b49cdaSZbigniew Bodek 	struct {
9049b49cdaSZbigniew Bodek 		uint32_t len_ctrl;
9149b49cdaSZbigniew Bodek 		uint32_t meta_ctrl;
9249b49cdaSZbigniew Bodek 		uint32_t meta1;
9349b49cdaSZbigniew Bodek 		uint32_t meta2;
9449b49cdaSZbigniew Bodek 	} tx_meta;
9549b49cdaSZbigniew Bodek 	/* RX */
9649b49cdaSZbigniew Bodek 	struct {
9749b49cdaSZbigniew Bodek 		uint32_t len_ctrl;
9849b49cdaSZbigniew Bodek 		uint32_t buf2_ptr_lo;
9949b49cdaSZbigniew Bodek 		uint64_t buf1_ptr;
10049b49cdaSZbigniew Bodek 	} rx;
10149b49cdaSZbigniew Bodek } __packed_a16;
10249b49cdaSZbigniew Bodek 
10349b49cdaSZbigniew Bodek /* TX desc length and control fields */
10449b49cdaSZbigniew Bodek 
10549b49cdaSZbigniew Bodek #define AL_M2S_DESC_CONCAT			AL_BIT(31)	/* concatenate */
10649b49cdaSZbigniew Bodek #define AL_M2S_DESC_DMB				AL_BIT(30)
10749b49cdaSZbigniew Bodek 						/** Data Memory Barrier */
10849b49cdaSZbigniew Bodek #define AL_M2S_DESC_NO_SNOOP_H			AL_BIT(29)
10949b49cdaSZbigniew Bodek #define AL_M2S_DESC_INT_EN			AL_BIT(28)	/** enable interrupt */
11049b49cdaSZbigniew Bodek #define AL_M2S_DESC_LAST			AL_BIT(27)
11149b49cdaSZbigniew Bodek #define AL_M2S_DESC_FIRST			AL_BIT(26)
11249b49cdaSZbigniew Bodek #define AL_M2S_DESC_RING_ID_SHIFT		24
11349b49cdaSZbigniew Bodek #define AL_M2S_DESC_RING_ID_MASK		(0x3 << AL_M2S_DESC_RING_ID_SHIFT)
11449b49cdaSZbigniew Bodek #define AL_M2S_DESC_META_DATA			AL_BIT(23)
11549b49cdaSZbigniew Bodek #define AL_M2S_DESC_DUMMY			AL_BIT(22) /* for Metdata only */
11649b49cdaSZbigniew Bodek #define AL_M2S_DESC_LEN_ADJ_SHIFT		20
11749b49cdaSZbigniew Bodek #define AL_M2S_DESC_LEN_ADJ_MASK		(0x7 << AL_M2S_DESC_LEN_ADJ_SHIFT)
11849b49cdaSZbigniew Bodek #define AL_M2S_DESC_LEN_SHIFT			0
11949b49cdaSZbigniew Bodek #define AL_M2S_DESC_LEN_MASK			(0xfffff << AL_M2S_DESC_LEN_SHIFT)
12049b49cdaSZbigniew Bodek 
12149b49cdaSZbigniew Bodek #define AL_S2M_DESC_DUAL_BUF			AL_BIT(31)
12249b49cdaSZbigniew Bodek #define AL_S2M_DESC_NO_SNOOP_H			AL_BIT(29)
12349b49cdaSZbigniew Bodek #define AL_S2M_DESC_INT_EN			AL_BIT(28)	/** enable interrupt */
12449b49cdaSZbigniew Bodek #define AL_S2M_DESC_RING_ID_SHIFT		24
12549b49cdaSZbigniew Bodek #define AL_S2M_DESC_RING_ID_MASK		(0x3 << AL_S2M_DESC_RING_ID_SHIFT)
12649b49cdaSZbigniew Bodek #define AL_S2M_DESC_LEN_SHIFT			0
12749b49cdaSZbigniew Bodek #define AL_S2M_DESC_LEN_MASK			(0xffff << AL_S2M_DESC_LEN_SHIFT)
12849b49cdaSZbigniew Bodek #define AL_S2M_DESC_LEN2_SHIFT			16
12949b49cdaSZbigniew Bodek #define AL_S2M_DESC_LEN2_MASK			(0x3fff << AL_S2M_DESC_LEN2_SHIFT)
13049b49cdaSZbigniew Bodek #define AL_S2M_DESC_LEN2_GRANULARITY_SHIFT	6
13149b49cdaSZbigniew Bodek 
132*3fc36ee0SWojciech Macek /* TX/RX descriptor Target-ID field (in the buffer address 64 bit field) */
133*3fc36ee0SWojciech Macek #define AL_UDMA_DESC_TGTID_SHIFT		48
13449b49cdaSZbigniew Bodek 
13549b49cdaSZbigniew Bodek /** UDMA completion descriptor */
13649b49cdaSZbigniew Bodek union al_udma_cdesc {
13749b49cdaSZbigniew Bodek 	/* TX completion */
13849b49cdaSZbigniew Bodek 	struct {
13949b49cdaSZbigniew Bodek 		uint32_t ctrl_meta;
14049b49cdaSZbigniew Bodek 	} al_desc_comp_tx;
14149b49cdaSZbigniew Bodek 	/* RX completion */
14249b49cdaSZbigniew Bodek 	struct {
14349b49cdaSZbigniew Bodek 		/* TBD */
14449b49cdaSZbigniew Bodek 		uint32_t ctrl_meta;
14549b49cdaSZbigniew Bodek 	} al_desc_comp_rx;
14649b49cdaSZbigniew Bodek } __packed_a4;
14749b49cdaSZbigniew Bodek 
14849b49cdaSZbigniew Bodek /* TX/RX common completion desc ctrl_meta feilds */
14949b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_ERROR		AL_BIT(31)
15049b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_BUF1_USED		AL_BIT(30)
15149b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_DDP		AL_BIT(29)
15249b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_LAST		AL_BIT(27)
15349b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_FIRST		AL_BIT(26)
15449b49cdaSZbigniew Bodek /* word 2 */
15549b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_BUF2_USED			AL_BIT(31)
15649b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_BUF2_LEN_SHIFT	16
15749b49cdaSZbigniew Bodek #define AL_UDMA_CDESC_BUF2_LEN_MASK		AL_FIELD_MASK(29, 16)
15849b49cdaSZbigniew Bodek /** Basic Buffer structure */
15949b49cdaSZbigniew Bodek struct al_buf {
16049b49cdaSZbigniew Bodek 	al_phys_addr_t addr; /**< Buffer physical address */
16149b49cdaSZbigniew Bodek 	uint32_t len; /**< Buffer lenght in bytes */
16249b49cdaSZbigniew Bodek };
16349b49cdaSZbigniew Bodek 
16449b49cdaSZbigniew Bodek /** Block is a set of buffers that belong to same source or destination */
16549b49cdaSZbigniew Bodek struct al_block {
16649b49cdaSZbigniew Bodek 	struct al_buf *bufs; /**< The buffers of the block */
16749b49cdaSZbigniew Bodek 	uint32_t num; /**< Number of buffers of the block */
16849b49cdaSZbigniew Bodek 
16949b49cdaSZbigniew Bodek 	/**<
170*3fc36ee0SWojciech Macek 	 * Target-ID to be assigned to the block descriptors
171*3fc36ee0SWojciech Macek 	 * Requires Target-ID in descriptor to be enabled for the specific UDMA
17249b49cdaSZbigniew Bodek 	 * queue.
17349b49cdaSZbigniew Bodek 	 */
174*3fc36ee0SWojciech Macek 	uint16_t tgtid;
17549b49cdaSZbigniew Bodek };
17649b49cdaSZbigniew Bodek 
17749b49cdaSZbigniew Bodek /** UDMA type */
17849b49cdaSZbigniew Bodek enum al_udma_type {
17949b49cdaSZbigniew Bodek 	UDMA_TX,
18049b49cdaSZbigniew Bodek 	UDMA_RX
18149b49cdaSZbigniew Bodek };
18249b49cdaSZbigniew Bodek 
18349b49cdaSZbigniew Bodek /** UDMA state */
18449b49cdaSZbigniew Bodek enum al_udma_state {
18549b49cdaSZbigniew Bodek 	UDMA_DISABLE = 0,
18649b49cdaSZbigniew Bodek 	UDMA_IDLE,
18749b49cdaSZbigniew Bodek 	UDMA_NORMAL,
18849b49cdaSZbigniew Bodek 	UDMA_ABORT,
18949b49cdaSZbigniew Bodek 	UDMA_RESET
19049b49cdaSZbigniew Bodek };
19149b49cdaSZbigniew Bodek 
19249b49cdaSZbigniew Bodek extern const char *const al_udma_states_name[];
19349b49cdaSZbigniew Bodek 
19449b49cdaSZbigniew Bodek /** UDMA Q specific parameters from upper layer */
19549b49cdaSZbigniew Bodek struct al_udma_q_params {
19649b49cdaSZbigniew Bodek 	uint32_t size;		/**< ring size (in descriptors), submission and
19749b49cdaSZbigniew Bodek 				 * completion rings must have same size
19849b49cdaSZbigniew Bodek 				 */
19949b49cdaSZbigniew Bodek 	union al_udma_desc *desc_base; /**< cpu address for submission ring
20049b49cdaSZbigniew Bodek 					 * descriptors
20149b49cdaSZbigniew Bodek 					 */
20249b49cdaSZbigniew Bodek 	al_phys_addr_t desc_phy_base;	/**< submission ring descriptors
20349b49cdaSZbigniew Bodek 					 * physical base address
20449b49cdaSZbigniew Bodek 					 */
20549b49cdaSZbigniew Bodek #ifdef __FreeBSD__
20649b49cdaSZbigniew Bodek 	bus_dma_tag_t desc_phy_base_tag;
20749b49cdaSZbigniew Bodek 	bus_dmamap_t desc_phy_base_map;
20849b49cdaSZbigniew Bodek #endif
20949b49cdaSZbigniew Bodek 	uint8_t *cdesc_base;	/**< completion descriptors pointer, NULL */
21049b49cdaSZbigniew Bodek 				/* means no completion update */
21149b49cdaSZbigniew Bodek 	al_phys_addr_t cdesc_phy_base;	/**< completion descriptors ring
21249b49cdaSZbigniew Bodek 					 * physical base address
21349b49cdaSZbigniew Bodek 					 */
21449b49cdaSZbigniew Bodek #ifdef __FreeBSD__
21549b49cdaSZbigniew Bodek 	bus_dma_tag_t cdesc_phy_base_tag;
21649b49cdaSZbigniew Bodek 	bus_dmamap_t cdesc_phy_base_map;
21749b49cdaSZbigniew Bodek #endif
21849b49cdaSZbigniew Bodek 	uint32_t cdesc_size;	/**< size (in bytes) of a single dma completion
21949b49cdaSZbigniew Bodek 					* descriptor
22049b49cdaSZbigniew Bodek 					*/
22149b49cdaSZbigniew Bodek 
22249b49cdaSZbigniew Bodek 	uint8_t adapter_rev_id; /**<PCI adapter revision ID */
22349b49cdaSZbigniew Bodek };
22449b49cdaSZbigniew Bodek 
22549b49cdaSZbigniew Bodek /** UDMA parameters from upper layer */
22649b49cdaSZbigniew Bodek struct al_udma_params {
22749b49cdaSZbigniew Bodek 	struct unit_regs __iomem *udma_regs_base;
22849b49cdaSZbigniew Bodek 	enum al_udma_type type;	/**< Tx or Rx */
22949b49cdaSZbigniew Bodek 	uint8_t num_of_queues; /**< number of queues supported by the UDMA */
23049b49cdaSZbigniew Bodek 	const char *name; /**< the upper layer must keep the string area */
23149b49cdaSZbigniew Bodek };
23249b49cdaSZbigniew Bodek 
23349b49cdaSZbigniew Bodek /* Fordward decleration */
23449b49cdaSZbigniew Bodek struct al_udma;
23549b49cdaSZbigniew Bodek 
23649b49cdaSZbigniew Bodek /** SW status of a queue */
23749b49cdaSZbigniew Bodek enum al_udma_queue_status {
23849b49cdaSZbigniew Bodek 	AL_QUEUE_NOT_INITIALIZED = 0,
23949b49cdaSZbigniew Bodek 	AL_QUEUE_DISABLED,
24049b49cdaSZbigniew Bodek 	AL_QUEUE_ENABLED,
24149b49cdaSZbigniew Bodek 	AL_QUEUE_ABORTED
24249b49cdaSZbigniew Bodek };
24349b49cdaSZbigniew Bodek 
24449b49cdaSZbigniew Bodek /** UDMA Queue private data structure */
24549b49cdaSZbigniew Bodek struct __cache_aligned al_udma_q {
24649b49cdaSZbigniew Bodek 	uint16_t size_mask;		/**< mask used for pointers wrap around
24749b49cdaSZbigniew Bodek 					 * equals to size - 1
24849b49cdaSZbigniew Bodek 					 */
24949b49cdaSZbigniew Bodek 	union udma_q_regs __iomem *q_regs; /**< pointer to the per queue UDMA
25049b49cdaSZbigniew Bodek 					   * registers
25149b49cdaSZbigniew Bodek 					   */
25249b49cdaSZbigniew Bodek 	union al_udma_desc *desc_base_ptr; /**< base address submission ring
25349b49cdaSZbigniew Bodek 						* descriptors
25449b49cdaSZbigniew Bodek 						*/
25549b49cdaSZbigniew Bodek 	uint16_t next_desc_idx; /**< index to the next available submission
25649b49cdaSZbigniew Bodek 				      * descriptor
25749b49cdaSZbigniew Bodek 				      */
25849b49cdaSZbigniew Bodek 
25949b49cdaSZbigniew Bodek 	uint32_t desc_ring_id;	/**< current submission ring id */
26049b49cdaSZbigniew Bodek 
26149b49cdaSZbigniew Bodek 	uint8_t *cdesc_base_ptr;/**< completion descriptors pointer, NULL */
26249b49cdaSZbigniew Bodek 				/* means no completion */
26349b49cdaSZbigniew Bodek 	uint32_t cdesc_size;	/**< size (in bytes) of the udma completion ring
26449b49cdaSZbigniew Bodek 				 * descriptor
26549b49cdaSZbigniew Bodek 				 */
26649b49cdaSZbigniew Bodek 	uint16_t next_cdesc_idx; /**< index in descriptors for next completing
26749b49cdaSZbigniew Bodek 			      * ring descriptor
26849b49cdaSZbigniew Bodek 			      */
26949b49cdaSZbigniew Bodek 	uint8_t *end_cdesc_ptr;	/**< used for wrap around detection */
27049b49cdaSZbigniew Bodek 	uint16_t comp_head_idx; /**< completion ring head pointer register
27149b49cdaSZbigniew Bodek 				 *shadow
27249b49cdaSZbigniew Bodek 				 */
27349b49cdaSZbigniew Bodek 	volatile union al_udma_cdesc *comp_head_ptr; /**< when working in get_packet mode
27449b49cdaSZbigniew Bodek 				       * we maintain pointer instead of the
27549b49cdaSZbigniew Bodek 				       * above idx
27649b49cdaSZbigniew Bodek 				       */
27749b49cdaSZbigniew Bodek 
27849b49cdaSZbigniew Bodek 	uint32_t pkt_crnt_descs; /**< holds the number of processed descriptors
27949b49cdaSZbigniew Bodek 				  * of the current packet
28049b49cdaSZbigniew Bodek 				  */
28149b49cdaSZbigniew Bodek 	uint32_t comp_ring_id;	/**< current completion Ring Id */
28249b49cdaSZbigniew Bodek 
28349b49cdaSZbigniew Bodek 
28449b49cdaSZbigniew Bodek 	al_phys_addr_t desc_phy_base; /**< submission desc. physical base */
28549b49cdaSZbigniew Bodek 	al_phys_addr_t cdesc_phy_base; /**< completion desc. physical base */
28649b49cdaSZbigniew Bodek 
28749b49cdaSZbigniew Bodek 	uint32_t flags; /**< flags used for completion modes */
28849b49cdaSZbigniew Bodek 	uint32_t size;		/**< ring size in descriptors  */
28949b49cdaSZbigniew Bodek 	enum al_udma_queue_status status;
29049b49cdaSZbigniew Bodek 	struct al_udma *udma;	/**< pointer to parent UDMA */
29149b49cdaSZbigniew Bodek 	uint32_t qid;		/**< the index number of the queue */
29249b49cdaSZbigniew Bodek 
29349b49cdaSZbigniew Bodek 	/*
29449b49cdaSZbigniew Bodek 	 * The following fields are duplicated from the UDMA parent adapter
29549b49cdaSZbigniew Bodek 	 * due to performance considerations.
29649b49cdaSZbigniew Bodek 	 */
29749b49cdaSZbigniew Bodek 	uint8_t adapter_rev_id; /**<PCI adapter revision ID */
29849b49cdaSZbigniew Bodek };
29949b49cdaSZbigniew Bodek 
30049b49cdaSZbigniew Bodek /* UDMA */
30149b49cdaSZbigniew Bodek struct al_udma {
30249b49cdaSZbigniew Bodek 	const char *name;
30349b49cdaSZbigniew Bodek 	enum al_udma_type type;	/* Tx or Rx */
30449b49cdaSZbigniew Bodek 	enum al_udma_state state;
30549b49cdaSZbigniew Bodek 	uint8_t num_of_queues; /* number of queues supported by the UDMA */
30649b49cdaSZbigniew Bodek 	union udma_regs __iomem *udma_regs; /* pointer to the UDMA registers */
30749b49cdaSZbigniew Bodek 	struct udma_gen_regs *gen_regs;		/* pointer to the Gen registers*/
30849b49cdaSZbigniew Bodek 	struct al_udma_q udma_q[DMA_MAX_Q];	/* Array of UDMA Qs pointers */
30949b49cdaSZbigniew Bodek 	unsigned int rev_id; /* UDMA revision ID */
31049b49cdaSZbigniew Bodek };
31149b49cdaSZbigniew Bodek 
31249b49cdaSZbigniew Bodek 
31349b49cdaSZbigniew Bodek /*
31449b49cdaSZbigniew Bodek  * Configurations
31549b49cdaSZbigniew Bodek  */
31649b49cdaSZbigniew Bodek 
31749b49cdaSZbigniew Bodek /* Initializations functions */
31849b49cdaSZbigniew Bodek /**
31949b49cdaSZbigniew Bodek  * Initialize the udma engine
32049b49cdaSZbigniew Bodek  *
32149b49cdaSZbigniew Bodek  * @param udma udma data structure
32249b49cdaSZbigniew Bodek  * @param udma_params udma parameters from upper layer
32349b49cdaSZbigniew Bodek  *
32449b49cdaSZbigniew Bodek  * @return 0 on success. -EINVAL otherwise.
32549b49cdaSZbigniew Bodek  */
32649b49cdaSZbigniew Bodek int al_udma_init(struct al_udma *udma, struct al_udma_params *udma_params);
32749b49cdaSZbigniew Bodek 
32849b49cdaSZbigniew Bodek /**
32949b49cdaSZbigniew Bodek  * Initialize the udma queue data structure
33049b49cdaSZbigniew Bodek  *
33149b49cdaSZbigniew Bodek  * @param udma
33249b49cdaSZbigniew Bodek  * @param qid
33349b49cdaSZbigniew Bodek  * @param q_params
33449b49cdaSZbigniew Bodek  *
33549b49cdaSZbigniew Bodek  * @return 0 if no error found.
33649b49cdaSZbigniew Bodek  *	   -EINVAL if the qid is out of range
33749b49cdaSZbigniew Bodek  *	   -EIO if queue was already initialized
33849b49cdaSZbigniew Bodek  */
33949b49cdaSZbigniew Bodek 
34049b49cdaSZbigniew Bodek int al_udma_q_init(struct al_udma *udma, uint32_t qid,
34149b49cdaSZbigniew Bodek 		   struct al_udma_q_params *q_params);
34249b49cdaSZbigniew Bodek 
34349b49cdaSZbigniew Bodek /**
34449b49cdaSZbigniew Bodek  * Reset a udma queue
34549b49cdaSZbigniew Bodek  *
34649b49cdaSZbigniew Bodek  * Prior to calling this function make sure:
34749b49cdaSZbigniew Bodek  * 1. Queue interrupts are masked
34849b49cdaSZbigniew Bodek  * 2. No additional descriptors are written to the descriptor ring of the queue
34949b49cdaSZbigniew Bodek  * 3. No completed descriptors are being fetched
35049b49cdaSZbigniew Bodek  *
35149b49cdaSZbigniew Bodek  * The queue can be initialized again using 'al_udma_q_init'
35249b49cdaSZbigniew Bodek  *
35349b49cdaSZbigniew Bodek  * @param udma_q
35449b49cdaSZbigniew Bodek  *
35549b49cdaSZbigniew Bodek  * @return 0 if no error found.
35649b49cdaSZbigniew Bodek  */
35749b49cdaSZbigniew Bodek 
35849b49cdaSZbigniew Bodek int al_udma_q_reset(struct al_udma_q *udma_q);
35949b49cdaSZbigniew Bodek 
36049b49cdaSZbigniew Bodek /**
36149b49cdaSZbigniew Bodek  * return (by reference) a pointer to a specific queue date structure.
36249b49cdaSZbigniew Bodek  * this pointer needed for calling functions (i.e. al_udma_desc_action_add) that
36349b49cdaSZbigniew Bodek  * require this pointer as input argument.
36449b49cdaSZbigniew Bodek  *
36549b49cdaSZbigniew Bodek  * @param udma udma data structure
36649b49cdaSZbigniew Bodek  * @param qid queue index
36749b49cdaSZbigniew Bodek  * @param q_handle pointer to the location where the queue structure pointer
36849b49cdaSZbigniew Bodek  * written to.
36949b49cdaSZbigniew Bodek  *
37049b49cdaSZbigniew Bodek  * @return  0 on success. -EINVAL otherwise.
37149b49cdaSZbigniew Bodek  */
37249b49cdaSZbigniew Bodek int al_udma_q_handle_get(struct al_udma *udma, uint32_t qid,
37349b49cdaSZbigniew Bodek 		      struct al_udma_q **q_handle);
37449b49cdaSZbigniew Bodek 
37549b49cdaSZbigniew Bodek /**
37649b49cdaSZbigniew Bodek  * Change the UDMA's state
37749b49cdaSZbigniew Bodek  *
37849b49cdaSZbigniew Bodek  * @param udma udma data structure
37949b49cdaSZbigniew Bodek  * @param state the target state
38049b49cdaSZbigniew Bodek  *
38149b49cdaSZbigniew Bodek  * @return 0
38249b49cdaSZbigniew Bodek  */
38349b49cdaSZbigniew Bodek int al_udma_state_set(struct al_udma *udma, enum al_udma_state state);
38449b49cdaSZbigniew Bodek 
38549b49cdaSZbigniew Bodek /**
38649b49cdaSZbigniew Bodek  * return the current UDMA hardware state
38749b49cdaSZbigniew Bodek  *
38849b49cdaSZbigniew Bodek  * @param udma udma handle
38949b49cdaSZbigniew Bodek  *
39049b49cdaSZbigniew Bodek  * @return the UDMA state as reported by the hardware.
39149b49cdaSZbigniew Bodek  */
39249b49cdaSZbigniew Bodek enum al_udma_state al_udma_state_get(struct al_udma *udma);
39349b49cdaSZbigniew Bodek 
39449b49cdaSZbigniew Bodek /*
39549b49cdaSZbigniew Bodek  * Action handling
39649b49cdaSZbigniew Bodek  */
39749b49cdaSZbigniew Bodek 
39849b49cdaSZbigniew Bodek /**
39949b49cdaSZbigniew Bodek  * get number of descriptors that can be submitted to the udma.
40049b49cdaSZbigniew Bodek  * keep one free descriptor to simplify full/empty management
40149b49cdaSZbigniew Bodek  * @param udma_q queue handle
40249b49cdaSZbigniew Bodek  *
40349b49cdaSZbigniew Bodek  * @return num of free descriptors.
40449b49cdaSZbigniew Bodek  */
al_udma_available_get(struct al_udma_q * udma_q)40549b49cdaSZbigniew Bodek static INLINE uint32_t al_udma_available_get(struct al_udma_q *udma_q)
40649b49cdaSZbigniew Bodek {
40749b49cdaSZbigniew Bodek 	uint16_t tmp = udma_q->next_cdesc_idx - (udma_q->next_desc_idx + 1);
40849b49cdaSZbigniew Bodek 	tmp &= udma_q->size_mask;
40949b49cdaSZbigniew Bodek 
41049b49cdaSZbigniew Bodek 	return (uint32_t) tmp;
41149b49cdaSZbigniew Bodek }
41249b49cdaSZbigniew Bodek 
41349b49cdaSZbigniew Bodek /**
41449b49cdaSZbigniew Bodek  * check if queue has pending descriptors
41549b49cdaSZbigniew Bodek  *
41649b49cdaSZbigniew Bodek  * @param udma_q queue handle
41749b49cdaSZbigniew Bodek  *
41849b49cdaSZbigniew Bodek  * @return AL_TRUE if descriptors are submitted to completion ring and still
41949b49cdaSZbigniew Bodek  * not completed (with ack). AL_FALSE otherwise.
42049b49cdaSZbigniew Bodek  */
al_udma_is_empty(struct al_udma_q * udma_q)42149b49cdaSZbigniew Bodek static INLINE al_bool al_udma_is_empty(struct al_udma_q *udma_q)
42249b49cdaSZbigniew Bodek {
42349b49cdaSZbigniew Bodek 	if (((udma_q->next_cdesc_idx - udma_q->next_desc_idx) &
42449b49cdaSZbigniew Bodek 	     udma_q->size_mask) == 0)
42549b49cdaSZbigniew Bodek 		return AL_TRUE;
42649b49cdaSZbigniew Bodek 
42749b49cdaSZbigniew Bodek 	return AL_FALSE;
42849b49cdaSZbigniew Bodek }
42949b49cdaSZbigniew Bodek 
43049b49cdaSZbigniew Bodek /**
43149b49cdaSZbigniew Bodek  * get next available descriptor
43249b49cdaSZbigniew Bodek  * @param udma_q queue handle
43349b49cdaSZbigniew Bodek  *
43449b49cdaSZbigniew Bodek  * @return pointer to the next available descriptor
43549b49cdaSZbigniew Bodek  */
al_udma_desc_get(struct al_udma_q * udma_q)43649b49cdaSZbigniew Bodek static INLINE union al_udma_desc *al_udma_desc_get(struct al_udma_q *udma_q)
43749b49cdaSZbigniew Bodek {
43849b49cdaSZbigniew Bodek 	union al_udma_desc *desc;
43949b49cdaSZbigniew Bodek 	uint16_t next_desc_idx;
44049b49cdaSZbigniew Bodek 
44149b49cdaSZbigniew Bodek 	al_assert(udma_q);
44249b49cdaSZbigniew Bodek 
44349b49cdaSZbigniew Bodek 	next_desc_idx = udma_q->next_desc_idx;
44449b49cdaSZbigniew Bodek 	desc = udma_q->desc_base_ptr + next_desc_idx;
44549b49cdaSZbigniew Bodek 
44649b49cdaSZbigniew Bodek 	next_desc_idx++;
44749b49cdaSZbigniew Bodek 
44849b49cdaSZbigniew Bodek 	/* if reached end of queue, wrap around */
44949b49cdaSZbigniew Bodek 	udma_q->next_desc_idx = next_desc_idx & udma_q->size_mask;
45049b49cdaSZbigniew Bodek 
45149b49cdaSZbigniew Bodek 	return desc;
45249b49cdaSZbigniew Bodek }
45349b49cdaSZbigniew Bodek 
45449b49cdaSZbigniew Bodek /**
45549b49cdaSZbigniew Bodek  * get ring id for the last allocated descriptor
45649b49cdaSZbigniew Bodek  * @param udma_q
45749b49cdaSZbigniew Bodek  *
45849b49cdaSZbigniew Bodek  * @return ring id for the last allocated descriptor
45949b49cdaSZbigniew Bodek  * this function must be called each time a new descriptor is allocated
46049b49cdaSZbigniew Bodek  * by the al_udma_desc_get(), unless ring id is ignored.
46149b49cdaSZbigniew Bodek  */
al_udma_ring_id_get(struct al_udma_q * udma_q)46249b49cdaSZbigniew Bodek static INLINE uint32_t al_udma_ring_id_get(struct al_udma_q *udma_q)
46349b49cdaSZbigniew Bodek {
46449b49cdaSZbigniew Bodek 	uint32_t ring_id;
46549b49cdaSZbigniew Bodek 
46649b49cdaSZbigniew Bodek 	al_assert(udma_q);
46749b49cdaSZbigniew Bodek 
46849b49cdaSZbigniew Bodek 	ring_id = udma_q->desc_ring_id;
46949b49cdaSZbigniew Bodek 
47049b49cdaSZbigniew Bodek 	/* calculate the ring id of the next desc */
47149b49cdaSZbigniew Bodek 	/* if next_desc points to first desc, then queue wrapped around */
47249b49cdaSZbigniew Bodek 	if (unlikely(udma_q->next_desc_idx) == 0)
47349b49cdaSZbigniew Bodek 		udma_q->desc_ring_id = (udma_q->desc_ring_id + 1) &
47449b49cdaSZbigniew Bodek 			DMA_RING_ID_MASK;
47549b49cdaSZbigniew Bodek 	return ring_id;
47649b49cdaSZbigniew Bodek }
47749b49cdaSZbigniew Bodek 
47849b49cdaSZbigniew Bodek /* add DMA action - trigger the engine */
47949b49cdaSZbigniew Bodek /**
48049b49cdaSZbigniew Bodek  * add num descriptors to the submission queue.
48149b49cdaSZbigniew Bodek  *
48249b49cdaSZbigniew Bodek  * @param udma_q queue handle
48349b49cdaSZbigniew Bodek  * @param num number of descriptors to add to the queues ring.
48449b49cdaSZbigniew Bodek  *
48549b49cdaSZbigniew Bodek  * @return 0;
48649b49cdaSZbigniew Bodek  */
al_udma_desc_action_add(struct al_udma_q * udma_q,uint32_t num)48749b49cdaSZbigniew Bodek static INLINE int al_udma_desc_action_add(struct al_udma_q *udma_q,
48849b49cdaSZbigniew Bodek 					  uint32_t num)
48949b49cdaSZbigniew Bodek {
49049b49cdaSZbigniew Bodek 	uint32_t *addr;
49149b49cdaSZbigniew Bodek 
49249b49cdaSZbigniew Bodek 	al_assert(udma_q);
49349b49cdaSZbigniew Bodek 	al_assert((num > 0) && (num <= udma_q->size));
49449b49cdaSZbigniew Bodek 
49549b49cdaSZbigniew Bodek 	addr = &udma_q->q_regs->rings.drtp_inc;
49649b49cdaSZbigniew Bodek 	/* make sure data written to the descriptors will be visible by the */
49749b49cdaSZbigniew Bodek 	/* DMA */
49849b49cdaSZbigniew Bodek 	al_local_data_memory_barrier();
49949b49cdaSZbigniew Bodek 
50049b49cdaSZbigniew Bodek 	/*
50149b49cdaSZbigniew Bodek 	 * As we explicitly invoke the synchronization function
50249b49cdaSZbigniew Bodek 	 * (al_data_memory_barrier()), then we can use the relaxed version.
50349b49cdaSZbigniew Bodek 	 */
50449b49cdaSZbigniew Bodek 	al_reg_write32_relaxed(addr, num);
50549b49cdaSZbigniew Bodek 
50649b49cdaSZbigniew Bodek 	return 0;
50749b49cdaSZbigniew Bodek }
50849b49cdaSZbigniew Bodek 
50949b49cdaSZbigniew Bodek #define cdesc_is_first(flags) ((flags) & AL_UDMA_CDESC_FIRST)
51049b49cdaSZbigniew Bodek #define cdesc_is_last(flags) ((flags) & AL_UDMA_CDESC_LAST)
51149b49cdaSZbigniew Bodek 
51249b49cdaSZbigniew Bodek /**
51349b49cdaSZbigniew Bodek  * return pointer to the cdesc + offset desciptors. wrap around when needed.
51449b49cdaSZbigniew Bodek  *
51549b49cdaSZbigniew Bodek  * @param udma_q queue handle
51649b49cdaSZbigniew Bodek  * @param cdesc pointer that set by this function
51749b49cdaSZbigniew Bodek  * @param offset offset desciptors
51849b49cdaSZbigniew Bodek  *
51949b49cdaSZbigniew Bodek  */
al_cdesc_next(struct al_udma_q * udma_q,volatile union al_udma_cdesc * cdesc,uint32_t offset)52049b49cdaSZbigniew Bodek static INLINE volatile union al_udma_cdesc *al_cdesc_next(
52149b49cdaSZbigniew Bodek 	struct al_udma_q		*udma_q,
52249b49cdaSZbigniew Bodek 	volatile union al_udma_cdesc	*cdesc,
52349b49cdaSZbigniew Bodek 	uint32_t			offset)
52449b49cdaSZbigniew Bodek {
52549b49cdaSZbigniew Bodek 	volatile uint8_t *tmp = (volatile uint8_t *) cdesc + offset * udma_q->cdesc_size;
52649b49cdaSZbigniew Bodek 	al_assert(udma_q);
52749b49cdaSZbigniew Bodek 	al_assert(cdesc);
52849b49cdaSZbigniew Bodek 
52949b49cdaSZbigniew Bodek 	/* if wrap around */
53049b49cdaSZbigniew Bodek 	if (unlikely((tmp > udma_q->end_cdesc_ptr)))
53149b49cdaSZbigniew Bodek 		return (union al_udma_cdesc *)
53249b49cdaSZbigniew Bodek 			(udma_q->cdesc_base_ptr +
53349b49cdaSZbigniew Bodek 			(tmp - udma_q->end_cdesc_ptr - udma_q->cdesc_size));
53449b49cdaSZbigniew Bodek 
53549b49cdaSZbigniew Bodek 	return (volatile union al_udma_cdesc *) tmp;
53649b49cdaSZbigniew Bodek }
53749b49cdaSZbigniew Bodek 
53849b49cdaSZbigniew Bodek /**
53949b49cdaSZbigniew Bodek  * check if the flags of the descriptor indicates that is new one
54049b49cdaSZbigniew Bodek  * the function uses the ring id from the descriptor flags to know whether it
54149b49cdaSZbigniew Bodek  * new one by comparing it with the curring ring id of the queue
54249b49cdaSZbigniew Bodek  *
54349b49cdaSZbigniew Bodek  * @param udma_q queue handle
54449b49cdaSZbigniew Bodek  * @param flags the flags of the completion descriptor
54549b49cdaSZbigniew Bodek  *
54649b49cdaSZbigniew Bodek  * @return AL_TRUE if the completion descriptor is new one.
54749b49cdaSZbigniew Bodek  * 	AL_FALSE if it old one.
54849b49cdaSZbigniew Bodek  */
al_udma_new_cdesc(struct al_udma_q * udma_q,uint32_t flags)54949b49cdaSZbigniew Bodek static INLINE al_bool al_udma_new_cdesc(struct al_udma_q *udma_q,
55049b49cdaSZbigniew Bodek 								uint32_t flags)
55149b49cdaSZbigniew Bodek {
55249b49cdaSZbigniew Bodek 	if (((flags & AL_M2S_DESC_RING_ID_MASK) >> AL_M2S_DESC_RING_ID_SHIFT)
55349b49cdaSZbigniew Bodek 	    == udma_q->comp_ring_id)
55449b49cdaSZbigniew Bodek 		return AL_TRUE;
55549b49cdaSZbigniew Bodek 	return AL_FALSE;
55649b49cdaSZbigniew Bodek }
55749b49cdaSZbigniew Bodek 
55849b49cdaSZbigniew Bodek /**
55949b49cdaSZbigniew Bodek  * get next completion descriptor
56049b49cdaSZbigniew Bodek  * this function will also increment the completion ring id when the ring wraps
56149b49cdaSZbigniew Bodek  * around
56249b49cdaSZbigniew Bodek  *
56349b49cdaSZbigniew Bodek  * @param udma_q queue handle
56449b49cdaSZbigniew Bodek  * @param cdesc current completion descriptor
56549b49cdaSZbigniew Bodek  *
56649b49cdaSZbigniew Bodek  * @return pointer to the completion descriptor that follows the one pointed by
56749b49cdaSZbigniew Bodek  * cdesc
56849b49cdaSZbigniew Bodek  */
al_cdesc_next_update(struct al_udma_q * udma_q,volatile union al_udma_cdesc * cdesc)56949b49cdaSZbigniew Bodek static INLINE volatile union al_udma_cdesc *al_cdesc_next_update(
57049b49cdaSZbigniew Bodek 	struct al_udma_q		*udma_q,
57149b49cdaSZbigniew Bodek 	volatile union al_udma_cdesc	*cdesc)
57249b49cdaSZbigniew Bodek {
57349b49cdaSZbigniew Bodek 	/* if last desc, wrap around */
57449b49cdaSZbigniew Bodek 	if (unlikely(((volatile uint8_t *) cdesc == udma_q->end_cdesc_ptr))) {
57549b49cdaSZbigniew Bodek 		udma_q->comp_ring_id =
57649b49cdaSZbigniew Bodek 		    (udma_q->comp_ring_id + 1) & DMA_RING_ID_MASK;
57749b49cdaSZbigniew Bodek 		return (union al_udma_cdesc *) udma_q->cdesc_base_ptr;
57849b49cdaSZbigniew Bodek 	}
57949b49cdaSZbigniew Bodek 	return (volatile union al_udma_cdesc *) ((volatile uint8_t *) cdesc + udma_q->cdesc_size);
58049b49cdaSZbigniew Bodek }
58149b49cdaSZbigniew Bodek 
58249b49cdaSZbigniew Bodek /**
58349b49cdaSZbigniew Bodek  * get next completed packet from completion ring of the queue
58449b49cdaSZbigniew Bodek  *
58549b49cdaSZbigniew Bodek  * @param udma_q udma queue handle
58649b49cdaSZbigniew Bodek  * @param desc pointer that set by this function to the first descriptor
58749b49cdaSZbigniew Bodek  * note: desc is valid only when return value is not zero
58849b49cdaSZbigniew Bodek  * @return number of descriptors that belong to the packet. 0 means no completed
58949b49cdaSZbigniew Bodek  * full packet was found.
59049b49cdaSZbigniew Bodek  * If the descriptors found in the completion queue don't form full packet (no
59149b49cdaSZbigniew Bodek  * desc with LAST flag), then this function will do the following:
59249b49cdaSZbigniew Bodek  * (1) save the number of processed descriptors.
59349b49cdaSZbigniew Bodek  * (2) save last processed descriptor, so next time it called, it will resume
59449b49cdaSZbigniew Bodek  *     from there.
59549b49cdaSZbigniew Bodek  * (3) return 0.
59649b49cdaSZbigniew Bodek  * note: the descriptors that belong to the completed packet will still be
59749b49cdaSZbigniew Bodek  * considered as used, that means the upper layer is safe to access those
59849b49cdaSZbigniew Bodek  * descriptors when this function returns. the al_udma_cdesc_ack() should be
59949b49cdaSZbigniew Bodek  * called to inform the udma driver that those descriptors are freed.
60049b49cdaSZbigniew Bodek  */
60149b49cdaSZbigniew Bodek uint32_t al_udma_cdesc_packet_get(
60249b49cdaSZbigniew Bodek 	struct al_udma_q		*udma_q,
60349b49cdaSZbigniew Bodek 	volatile union al_udma_cdesc	**desc);
60449b49cdaSZbigniew Bodek 
60549b49cdaSZbigniew Bodek /** get completion descriptor pointer from its index */
60649b49cdaSZbigniew Bodek #define al_udma_cdesc_idx_to_ptr(udma_q, idx)				\
60749b49cdaSZbigniew Bodek 	((volatile union al_udma_cdesc *) ((udma_q)->cdesc_base_ptr +	\
60849b49cdaSZbigniew Bodek 				(idx) * (udma_q)->cdesc_size))
60949b49cdaSZbigniew Bodek 
61049b49cdaSZbigniew Bodek 
61149b49cdaSZbigniew Bodek /**
61249b49cdaSZbigniew Bodek  * return number of all completed descriptors in the completion ring
61349b49cdaSZbigniew Bodek  *
61449b49cdaSZbigniew Bodek  * @param udma_q udma queue handle
61549b49cdaSZbigniew Bodek  * @param cdesc pointer that set by this function to the first descriptor
61649b49cdaSZbigniew Bodek  * note: desc is valid only when return value is not zero
61749b49cdaSZbigniew Bodek  * note: pass NULL if not interested
61849b49cdaSZbigniew Bodek  * @return number of descriptors. 0 means no completed descriptors were found.
61949b49cdaSZbigniew Bodek  * note: the descriptors that belong to the completed packet will still be
62049b49cdaSZbigniew Bodek  * considered as used, that means the upper layer is safe to access those
62149b49cdaSZbigniew Bodek  * descriptors when this function returns. the al_udma_cdesc_ack() should be
62249b49cdaSZbigniew Bodek  * called to inform the udma driver that those descriptors are freed.
62349b49cdaSZbigniew Bodek  */
al_udma_cdesc_get_all(struct al_udma_q * udma_q,volatile union al_udma_cdesc ** cdesc)62449b49cdaSZbigniew Bodek static INLINE uint32_t al_udma_cdesc_get_all(
62549b49cdaSZbigniew Bodek 	struct al_udma_q		*udma_q,
62649b49cdaSZbigniew Bodek 	volatile union al_udma_cdesc	**cdesc)
62749b49cdaSZbigniew Bodek {
62849b49cdaSZbigniew Bodek 	uint16_t count = 0;
62949b49cdaSZbigniew Bodek 
63049b49cdaSZbigniew Bodek 	al_assert(udma_q);
63149b49cdaSZbigniew Bodek 
63249b49cdaSZbigniew Bodek 	udma_q->comp_head_idx = (uint16_t)
63349b49cdaSZbigniew Bodek 				(al_reg_read32(&udma_q->q_regs->rings.crhp) &
63449b49cdaSZbigniew Bodek 						0xFFFF);
63549b49cdaSZbigniew Bodek 
63649b49cdaSZbigniew Bodek 	count = (udma_q->comp_head_idx - udma_q->next_cdesc_idx) &
63749b49cdaSZbigniew Bodek 		udma_q->size_mask;
63849b49cdaSZbigniew Bodek 
63949b49cdaSZbigniew Bodek 	if (cdesc)
64049b49cdaSZbigniew Bodek 		*cdesc = al_udma_cdesc_idx_to_ptr(udma_q, udma_q->next_cdesc_idx);
64149b49cdaSZbigniew Bodek 
64249b49cdaSZbigniew Bodek 	return (uint32_t)count;
64349b49cdaSZbigniew Bodek }
64449b49cdaSZbigniew Bodek 
64549b49cdaSZbigniew Bodek /**
64649b49cdaSZbigniew Bodek  * acknowledge the driver that the upper layer completed processing completion
64749b49cdaSZbigniew Bodek  * descriptors
64849b49cdaSZbigniew Bodek  *
64949b49cdaSZbigniew Bodek  * @param udma_q udma queue handle
65049b49cdaSZbigniew Bodek  * @param num number of descriptors to acknowledge
65149b49cdaSZbigniew Bodek  *
65249b49cdaSZbigniew Bodek  * @return 0
65349b49cdaSZbigniew Bodek  */
al_udma_cdesc_ack(struct al_udma_q * udma_q,uint32_t num)65449b49cdaSZbigniew Bodek static INLINE int al_udma_cdesc_ack(struct al_udma_q *udma_q, uint32_t num)
65549b49cdaSZbigniew Bodek {
65649b49cdaSZbigniew Bodek 	al_assert(udma_q);
65749b49cdaSZbigniew Bodek 
65849b49cdaSZbigniew Bodek 	udma_q->next_cdesc_idx += num;
65949b49cdaSZbigniew Bodek 	udma_q->next_cdesc_idx &= udma_q->size_mask;
66049b49cdaSZbigniew Bodek 
66149b49cdaSZbigniew Bodek 	return 0;
66249b49cdaSZbigniew Bodek }
66349b49cdaSZbigniew Bodek 
66449b49cdaSZbigniew Bodek /* *INDENT-OFF* */
66549b49cdaSZbigniew Bodek #ifdef __cplusplus
66649b49cdaSZbigniew Bodek }
66749b49cdaSZbigniew Bodek #endif
66849b49cdaSZbigniew Bodek /* *INDENT-ON* */
66949b49cdaSZbigniew Bodek 
67049b49cdaSZbigniew Bodek #endif /* __AL_HAL_UDMA_H__ */
67149b49cdaSZbigniew Bodek /** @} end of UDMA group */
672