162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci// Copyright 2014-2015 Freescale
362306a36Sopenharmony_ci// Copyright 2018 NXP
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * Driver for NXP Layerscape Queue Direct Memory Access Controller
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Author:
962306a36Sopenharmony_ci *  Wen He <wen.he_1@nxp.com>
1062306a36Sopenharmony_ci *  Jiaheng Fan <jiaheng.fan@nxp.com>
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci#include <linux/of_dma.h>
1862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1962306a36Sopenharmony_ci#include <linux/platform_device.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "virt-dma.h"
2262306a36Sopenharmony_ci#include "fsldma.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Register related definition */
2562306a36Sopenharmony_ci#define FSL_QDMA_DMR			0x0
2662306a36Sopenharmony_ci#define FSL_QDMA_DSR			0x4
2762306a36Sopenharmony_ci#define FSL_QDMA_DEIER			0xe00
2862306a36Sopenharmony_ci#define FSL_QDMA_DEDR			0xe04
2962306a36Sopenharmony_ci#define FSL_QDMA_DECFDW0R		0xe10
3062306a36Sopenharmony_ci#define FSL_QDMA_DECFDW1R		0xe14
3162306a36Sopenharmony_ci#define FSL_QDMA_DECFDW2R		0xe18
3262306a36Sopenharmony_ci#define FSL_QDMA_DECFDW3R		0xe1c
3362306a36Sopenharmony_ci#define FSL_QDMA_DECFQIDR		0xe30
3462306a36Sopenharmony_ci#define FSL_QDMA_DECBR			0xe34
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define FSL_QDMA_BCQMR(x)		(0xc0 + 0x100 * (x))
3762306a36Sopenharmony_ci#define FSL_QDMA_BCQSR(x)		(0xc4 + 0x100 * (x))
3862306a36Sopenharmony_ci#define FSL_QDMA_BCQEDPA_SADDR(x)	(0xc8 + 0x100 * (x))
3962306a36Sopenharmony_ci#define FSL_QDMA_BCQDPA_SADDR(x)	(0xcc + 0x100 * (x))
4062306a36Sopenharmony_ci#define FSL_QDMA_BCQEEPA_SADDR(x)	(0xd0 + 0x100 * (x))
4162306a36Sopenharmony_ci#define FSL_QDMA_BCQEPA_SADDR(x)	(0xd4 + 0x100 * (x))
4262306a36Sopenharmony_ci#define FSL_QDMA_BCQIER(x)		(0xe0 + 0x100 * (x))
4362306a36Sopenharmony_ci#define FSL_QDMA_BCQIDR(x)		(0xe4 + 0x100 * (x))
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define FSL_QDMA_SQDPAR			0x80c
4662306a36Sopenharmony_ci#define FSL_QDMA_SQEPAR			0x814
4762306a36Sopenharmony_ci#define FSL_QDMA_BSQMR			0x800
4862306a36Sopenharmony_ci#define FSL_QDMA_BSQSR			0x804
4962306a36Sopenharmony_ci#define FSL_QDMA_BSQICR			0x828
5062306a36Sopenharmony_ci#define FSL_QDMA_CQMR			0xa00
5162306a36Sopenharmony_ci#define FSL_QDMA_CQDSCR1		0xa08
5262306a36Sopenharmony_ci#define FSL_QDMA_CQDSCR2                0xa0c
5362306a36Sopenharmony_ci#define FSL_QDMA_CQIER			0xa10
5462306a36Sopenharmony_ci#define FSL_QDMA_CQEDR			0xa14
5562306a36Sopenharmony_ci#define FSL_QDMA_SQCCMR			0xa20
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* Registers for bit and genmask */
5862306a36Sopenharmony_ci#define FSL_QDMA_CQIDR_SQT		BIT(15)
5962306a36Sopenharmony_ci#define QDMA_CCDF_FORMAT		BIT(29)
6062306a36Sopenharmony_ci#define QDMA_CCDF_SER			BIT(30)
6162306a36Sopenharmony_ci#define QDMA_SG_FIN			BIT(30)
6262306a36Sopenharmony_ci#define QDMA_SG_LEN_MASK		GENMASK(29, 0)
6362306a36Sopenharmony_ci#define QDMA_CCDF_MASK			GENMASK(28, 20)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define FSL_QDMA_DEDR_CLEAR		GENMASK(31, 0)
6662306a36Sopenharmony_ci#define FSL_QDMA_BCQIDR_CLEAR		GENMASK(31, 0)
6762306a36Sopenharmony_ci#define FSL_QDMA_DEIER_CLEAR		GENMASK(31, 0)
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define FSL_QDMA_BCQIER_CQTIE		BIT(15)
7062306a36Sopenharmony_ci#define FSL_QDMA_BCQIER_CQPEIE		BIT(23)
7162306a36Sopenharmony_ci#define FSL_QDMA_BSQICR_ICEN		BIT(31)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define FSL_QDMA_BSQICR_ICST(x)		((x) << 16)
7462306a36Sopenharmony_ci#define FSL_QDMA_CQIER_MEIE		BIT(31)
7562306a36Sopenharmony_ci#define FSL_QDMA_CQIER_TEIE		BIT(0)
7662306a36Sopenharmony_ci#define FSL_QDMA_SQCCMR_ENTER_WM	BIT(21)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define FSL_QDMA_BCQMR_EN		BIT(31)
7962306a36Sopenharmony_ci#define FSL_QDMA_BCQMR_EI		BIT(30)
8062306a36Sopenharmony_ci#define FSL_QDMA_BCQMR_CD_THLD(x)	((x) << 20)
8162306a36Sopenharmony_ci#define FSL_QDMA_BCQMR_CQ_SIZE(x)	((x) << 16)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define FSL_QDMA_BCQSR_QF		BIT(16)
8462306a36Sopenharmony_ci#define FSL_QDMA_BCQSR_XOFF		BIT(0)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define FSL_QDMA_BSQMR_EN		BIT(31)
8762306a36Sopenharmony_ci#define FSL_QDMA_BSQMR_DI		BIT(30)
8862306a36Sopenharmony_ci#define FSL_QDMA_BSQMR_CQ_SIZE(x)	((x) << 16)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define FSL_QDMA_BSQSR_QE		BIT(17)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define FSL_QDMA_DMR_DQD		BIT(30)
9362306a36Sopenharmony_ci#define FSL_QDMA_DSR_DB		BIT(31)
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* Size related definition */
9662306a36Sopenharmony_ci#define FSL_QDMA_QUEUE_MAX		8
9762306a36Sopenharmony_ci#define FSL_QDMA_COMMAND_BUFFER_SIZE	64
9862306a36Sopenharmony_ci#define FSL_QDMA_DESCRIPTOR_BUFFER_SIZE 32
9962306a36Sopenharmony_ci#define FSL_QDMA_CIRCULAR_DESC_SIZE_MIN	64
10062306a36Sopenharmony_ci#define FSL_QDMA_CIRCULAR_DESC_SIZE_MAX	16384
10162306a36Sopenharmony_ci#define FSL_QDMA_QUEUE_NUM_MAX		8
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/* Field definition for CMD */
10462306a36Sopenharmony_ci#define FSL_QDMA_CMD_RWTTYPE		0x4
10562306a36Sopenharmony_ci#define FSL_QDMA_CMD_LWC                0x2
10662306a36Sopenharmony_ci#define FSL_QDMA_CMD_RWTTYPE_OFFSET	28
10762306a36Sopenharmony_ci#define FSL_QDMA_CMD_NS_OFFSET		27
10862306a36Sopenharmony_ci#define FSL_QDMA_CMD_DQOS_OFFSET	24
10962306a36Sopenharmony_ci#define FSL_QDMA_CMD_WTHROTL_OFFSET	20
11062306a36Sopenharmony_ci#define FSL_QDMA_CMD_DSEN_OFFSET	19
11162306a36Sopenharmony_ci#define FSL_QDMA_CMD_LWC_OFFSET		16
11262306a36Sopenharmony_ci#define FSL_QDMA_CMD_PF			BIT(17)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/* Field definition for Descriptor status */
11562306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_RTE		BIT(5)
11662306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_WTE		BIT(4)
11762306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_CDE		BIT(2)
11862306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_SDE		BIT(1)
11962306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_DDE		BIT(0)
12062306a36Sopenharmony_ci#define QDMA_CCDF_STATUS_MASK		(QDMA_CCDF_STATUS_RTE | \
12162306a36Sopenharmony_ci					QDMA_CCDF_STATUS_WTE | \
12262306a36Sopenharmony_ci					QDMA_CCDF_STATUS_CDE | \
12362306a36Sopenharmony_ci					QDMA_CCDF_STATUS_SDE | \
12462306a36Sopenharmony_ci					QDMA_CCDF_STATUS_DDE)
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/* Field definition for Descriptor offset */
12762306a36Sopenharmony_ci#define QDMA_CCDF_OFFSET		20
12862306a36Sopenharmony_ci#define QDMA_SDDF_CMD(x)		(((u64)(x)) << 32)
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/* Field definition for safe loop count*/
13162306a36Sopenharmony_ci#define FSL_QDMA_HALT_COUNT		1500
13262306a36Sopenharmony_ci#define FSL_QDMA_MAX_SIZE		16385
13362306a36Sopenharmony_ci#define	FSL_QDMA_COMP_TIMEOUT		1000
13462306a36Sopenharmony_ci#define FSL_COMMAND_QUEUE_OVERFLLOW	10
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci#define FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma_engine, x)			\
13762306a36Sopenharmony_ci	(((fsl_qdma_engine)->block_offset) * (x))
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/**
14062306a36Sopenharmony_ci * struct fsl_qdma_format - This is the struct holding describing compound
14162306a36Sopenharmony_ci *			    descriptor format with qDMA.
14262306a36Sopenharmony_ci * @status:		    Command status and enqueue status notification.
14362306a36Sopenharmony_ci * @cfg:		    Frame offset and frame format.
14462306a36Sopenharmony_ci * @addr_lo:		    Holding the compound descriptor of the lower
14562306a36Sopenharmony_ci *			    32-bits address in memory 40-bit address.
14662306a36Sopenharmony_ci * @addr_hi:		    Same as above member, but point high 8-bits in
14762306a36Sopenharmony_ci *			    memory 40-bit address.
14862306a36Sopenharmony_ci * @__reserved1:	    Reserved field.
14962306a36Sopenharmony_ci * @cfg8b_w1:		    Compound descriptor command queue origin produced
15062306a36Sopenharmony_ci *			    by qDMA and dynamic debug field.
15162306a36Sopenharmony_ci * @data:		    Pointer to the memory 40-bit address, describes DMA
15262306a36Sopenharmony_ci *			    source information and DMA destination information.
15362306a36Sopenharmony_ci */
15462306a36Sopenharmony_cistruct fsl_qdma_format {
15562306a36Sopenharmony_ci	__le32 status;
15662306a36Sopenharmony_ci	__le32 cfg;
15762306a36Sopenharmony_ci	union {
15862306a36Sopenharmony_ci		struct {
15962306a36Sopenharmony_ci			__le32 addr_lo;
16062306a36Sopenharmony_ci			u8 addr_hi;
16162306a36Sopenharmony_ci			u8 __reserved1[2];
16262306a36Sopenharmony_ci			u8 cfg8b_w1;
16362306a36Sopenharmony_ci		} __packed;
16462306a36Sopenharmony_ci		__le64 data;
16562306a36Sopenharmony_ci	};
16662306a36Sopenharmony_ci} __packed;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci/* qDMA status notification pre information */
16962306a36Sopenharmony_cistruct fsl_pre_status {
17062306a36Sopenharmony_ci	u64 addr;
17162306a36Sopenharmony_ci	u8 queue;
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct fsl_pre_status, pre);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistruct fsl_qdma_chan {
17762306a36Sopenharmony_ci	struct virt_dma_chan		vchan;
17862306a36Sopenharmony_ci	struct virt_dma_desc		vdesc;
17962306a36Sopenharmony_ci	enum dma_status			status;
18062306a36Sopenharmony_ci	struct fsl_qdma_engine		*qdma;
18162306a36Sopenharmony_ci	struct fsl_qdma_queue		*queue;
18262306a36Sopenharmony_ci};
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistruct fsl_qdma_queue {
18562306a36Sopenharmony_ci	struct fsl_qdma_format	*virt_head;
18662306a36Sopenharmony_ci	struct fsl_qdma_format	*virt_tail;
18762306a36Sopenharmony_ci	struct list_head	comp_used;
18862306a36Sopenharmony_ci	struct list_head	comp_free;
18962306a36Sopenharmony_ci	struct dma_pool		*comp_pool;
19062306a36Sopenharmony_ci	struct dma_pool		*desc_pool;
19162306a36Sopenharmony_ci	spinlock_t		queue_lock;
19262306a36Sopenharmony_ci	dma_addr_t		bus_addr;
19362306a36Sopenharmony_ci	u32                     n_cq;
19462306a36Sopenharmony_ci	u32			id;
19562306a36Sopenharmony_ci	struct fsl_qdma_format	*cq;
19662306a36Sopenharmony_ci	void __iomem		*block_base;
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistruct fsl_qdma_comp {
20062306a36Sopenharmony_ci	dma_addr_t              bus_addr;
20162306a36Sopenharmony_ci	dma_addr_t              desc_bus_addr;
20262306a36Sopenharmony_ci	struct fsl_qdma_format	*virt_addr;
20362306a36Sopenharmony_ci	struct fsl_qdma_format	*desc_virt_addr;
20462306a36Sopenharmony_ci	struct fsl_qdma_chan	*qchan;
20562306a36Sopenharmony_ci	struct virt_dma_desc    vdesc;
20662306a36Sopenharmony_ci	struct list_head	list;
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistruct fsl_qdma_engine {
21062306a36Sopenharmony_ci	struct dma_device	dma_dev;
21162306a36Sopenharmony_ci	void __iomem		*ctrl_base;
21262306a36Sopenharmony_ci	void __iomem            *status_base;
21362306a36Sopenharmony_ci	void __iomem		*block_base;
21462306a36Sopenharmony_ci	u32			n_chans;
21562306a36Sopenharmony_ci	u32			n_queues;
21662306a36Sopenharmony_ci	struct mutex            fsl_qdma_mutex;
21762306a36Sopenharmony_ci	int			error_irq;
21862306a36Sopenharmony_ci	int			*queue_irq;
21962306a36Sopenharmony_ci	u32			feature;
22062306a36Sopenharmony_ci	struct fsl_qdma_queue	*queue;
22162306a36Sopenharmony_ci	struct fsl_qdma_queue	**status;
22262306a36Sopenharmony_ci	struct fsl_qdma_chan	*chans;
22362306a36Sopenharmony_ci	int			block_number;
22462306a36Sopenharmony_ci	int			block_offset;
22562306a36Sopenharmony_ci	int			irq_base;
22662306a36Sopenharmony_ci	int			desc_allocated;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci};
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic inline u64
23162306a36Sopenharmony_ciqdma_ccdf_addr_get64(const struct fsl_qdma_format *ccdf)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	return le64_to_cpu(ccdf->data) & (U64_MAX >> 24);
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic inline void
23762306a36Sopenharmony_ciqdma_desc_addr_set64(struct fsl_qdma_format *ccdf, u64 addr)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	ccdf->addr_hi = upper_32_bits(addr);
24062306a36Sopenharmony_ci	ccdf->addr_lo = cpu_to_le32(lower_32_bits(addr));
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic inline u8
24462306a36Sopenharmony_ciqdma_ccdf_get_queue(const struct fsl_qdma_format *ccdf)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	return ccdf->cfg8b_w1 & U8_MAX;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic inline int
25062306a36Sopenharmony_ciqdma_ccdf_get_offset(const struct fsl_qdma_format *ccdf)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	return (le32_to_cpu(ccdf->cfg) & QDMA_CCDF_MASK) >> QDMA_CCDF_OFFSET;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic inline void
25662306a36Sopenharmony_ciqdma_ccdf_set_format(struct fsl_qdma_format *ccdf, int offset)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	ccdf->cfg = cpu_to_le32(QDMA_CCDF_FORMAT |
25962306a36Sopenharmony_ci				(offset << QDMA_CCDF_OFFSET));
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic inline int
26362306a36Sopenharmony_ciqdma_ccdf_get_status(const struct fsl_qdma_format *ccdf)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	return (le32_to_cpu(ccdf->status) & QDMA_CCDF_STATUS_MASK);
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic inline void
26962306a36Sopenharmony_ciqdma_ccdf_set_ser(struct fsl_qdma_format *ccdf, int status)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	ccdf->status = cpu_to_le32(QDMA_CCDF_SER | status);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic inline void qdma_csgf_set_len(struct fsl_qdma_format *csgf, int len)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	csgf->cfg = cpu_to_le32(len & QDMA_SG_LEN_MASK);
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic inline void qdma_csgf_set_f(struct fsl_qdma_format *csgf, int len)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	csgf->cfg = cpu_to_le32(QDMA_SG_FIN | (len & QDMA_SG_LEN_MASK));
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic u32 qdma_readl(struct fsl_qdma_engine *qdma, void __iomem *addr)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	return FSL_DMA_IN(qdma, addr, 32);
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic void qdma_writel(struct fsl_qdma_engine *qdma, u32 val,
29062306a36Sopenharmony_ci			void __iomem *addr)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	FSL_DMA_OUT(qdma, addr, val, 32);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic struct fsl_qdma_chan *to_fsl_qdma_chan(struct dma_chan *chan)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	return container_of(chan, struct fsl_qdma_chan, vchan.chan);
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic struct fsl_qdma_comp *to_fsl_qdma_comp(struct virt_dma_desc *vd)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	return container_of(vd, struct fsl_qdma_comp, vdesc);
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic void fsl_qdma_free_chan_resources(struct dma_chan *chan)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
30862306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_chan->queue;
30962306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma = fsl_chan->qdma;
31062306a36Sopenharmony_ci	struct fsl_qdma_comp *comp_temp, *_comp_temp;
31162306a36Sopenharmony_ci	unsigned long flags;
31262306a36Sopenharmony_ci	LIST_HEAD(head);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
31562306a36Sopenharmony_ci	vchan_get_all_descriptors(&fsl_chan->vchan, &head);
31662306a36Sopenharmony_ci	spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	if (!fsl_queue->comp_pool && !fsl_queue->desc_pool)
32162306a36Sopenharmony_ci		return;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	list_for_each_entry_safe(comp_temp, _comp_temp,
32462306a36Sopenharmony_ci				 &fsl_queue->comp_used,	list) {
32562306a36Sopenharmony_ci		dma_pool_free(fsl_queue->comp_pool,
32662306a36Sopenharmony_ci			      comp_temp->virt_addr,
32762306a36Sopenharmony_ci			      comp_temp->bus_addr);
32862306a36Sopenharmony_ci		dma_pool_free(fsl_queue->desc_pool,
32962306a36Sopenharmony_ci			      comp_temp->desc_virt_addr,
33062306a36Sopenharmony_ci			      comp_temp->desc_bus_addr);
33162306a36Sopenharmony_ci		list_del(&comp_temp->list);
33262306a36Sopenharmony_ci		kfree(comp_temp);
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	list_for_each_entry_safe(comp_temp, _comp_temp,
33662306a36Sopenharmony_ci				 &fsl_queue->comp_free, list) {
33762306a36Sopenharmony_ci		dma_pool_free(fsl_queue->comp_pool,
33862306a36Sopenharmony_ci			      comp_temp->virt_addr,
33962306a36Sopenharmony_ci			      comp_temp->bus_addr);
34062306a36Sopenharmony_ci		dma_pool_free(fsl_queue->desc_pool,
34162306a36Sopenharmony_ci			      comp_temp->desc_virt_addr,
34262306a36Sopenharmony_ci			      comp_temp->desc_bus_addr);
34362306a36Sopenharmony_ci		list_del(&comp_temp->list);
34462306a36Sopenharmony_ci		kfree(comp_temp);
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	dma_pool_destroy(fsl_queue->comp_pool);
34862306a36Sopenharmony_ci	dma_pool_destroy(fsl_queue->desc_pool);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	fsl_qdma->desc_allocated--;
35162306a36Sopenharmony_ci	fsl_queue->comp_pool = NULL;
35262306a36Sopenharmony_ci	fsl_queue->desc_pool = NULL;
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cistatic void fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp,
35662306a36Sopenharmony_ci				      dma_addr_t dst, dma_addr_t src, u32 len)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	u32 cmd;
35962306a36Sopenharmony_ci	struct fsl_qdma_format *sdf, *ddf;
36062306a36Sopenharmony_ci	struct fsl_qdma_format *ccdf, *csgf_desc, *csgf_src, *csgf_dest;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	ccdf = fsl_comp->virt_addr;
36362306a36Sopenharmony_ci	csgf_desc = fsl_comp->virt_addr + 1;
36462306a36Sopenharmony_ci	csgf_src = fsl_comp->virt_addr + 2;
36562306a36Sopenharmony_ci	csgf_dest = fsl_comp->virt_addr + 3;
36662306a36Sopenharmony_ci	sdf = fsl_comp->desc_virt_addr;
36762306a36Sopenharmony_ci	ddf = fsl_comp->desc_virt_addr + 1;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	memset(fsl_comp->virt_addr, 0, FSL_QDMA_COMMAND_BUFFER_SIZE);
37062306a36Sopenharmony_ci	memset(fsl_comp->desc_virt_addr, 0, FSL_QDMA_DESCRIPTOR_BUFFER_SIZE);
37162306a36Sopenharmony_ci	/* Head Command Descriptor(Frame Descriptor) */
37262306a36Sopenharmony_ci	qdma_desc_addr_set64(ccdf, fsl_comp->bus_addr + 16);
37362306a36Sopenharmony_ci	qdma_ccdf_set_format(ccdf, qdma_ccdf_get_offset(ccdf));
37462306a36Sopenharmony_ci	qdma_ccdf_set_ser(ccdf, qdma_ccdf_get_status(ccdf));
37562306a36Sopenharmony_ci	/* Status notification is enqueued to status queue. */
37662306a36Sopenharmony_ci	/* Compound Command Descriptor(Frame List Table) */
37762306a36Sopenharmony_ci	qdma_desc_addr_set64(csgf_desc, fsl_comp->desc_bus_addr);
37862306a36Sopenharmony_ci	/* It must be 32 as Compound S/G Descriptor */
37962306a36Sopenharmony_ci	qdma_csgf_set_len(csgf_desc, 32);
38062306a36Sopenharmony_ci	qdma_desc_addr_set64(csgf_src, src);
38162306a36Sopenharmony_ci	qdma_csgf_set_len(csgf_src, len);
38262306a36Sopenharmony_ci	qdma_desc_addr_set64(csgf_dest, dst);
38362306a36Sopenharmony_ci	qdma_csgf_set_len(csgf_dest, len);
38462306a36Sopenharmony_ci	/* This entry is the last entry. */
38562306a36Sopenharmony_ci	qdma_csgf_set_f(csgf_dest, len);
38662306a36Sopenharmony_ci	/* Descriptor Buffer */
38762306a36Sopenharmony_ci	cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
38862306a36Sopenharmony_ci			  FSL_QDMA_CMD_RWTTYPE_OFFSET) |
38962306a36Sopenharmony_ci			  FSL_QDMA_CMD_PF;
39062306a36Sopenharmony_ci	sdf->data = QDMA_SDDF_CMD(cmd);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
39362306a36Sopenharmony_ci			  FSL_QDMA_CMD_RWTTYPE_OFFSET);
39462306a36Sopenharmony_ci	cmd |= cpu_to_le32(FSL_QDMA_CMD_LWC << FSL_QDMA_CMD_LWC_OFFSET);
39562306a36Sopenharmony_ci	ddf->data = QDMA_SDDF_CMD(cmd);
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci/*
39962306a36Sopenharmony_ci * Pre-request full command descriptor for enqueue.
40062306a36Sopenharmony_ci */
40162306a36Sopenharmony_cistatic int fsl_qdma_pre_request_enqueue_desc(struct fsl_qdma_queue *queue)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	int i;
40462306a36Sopenharmony_ci	struct fsl_qdma_comp *comp_temp, *_comp_temp;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	for (i = 0; i < queue->n_cq + FSL_COMMAND_QUEUE_OVERFLLOW; i++) {
40762306a36Sopenharmony_ci		comp_temp = kzalloc(sizeof(*comp_temp), GFP_KERNEL);
40862306a36Sopenharmony_ci		if (!comp_temp)
40962306a36Sopenharmony_ci			goto err_alloc;
41062306a36Sopenharmony_ci		comp_temp->virt_addr =
41162306a36Sopenharmony_ci			dma_pool_alloc(queue->comp_pool, GFP_KERNEL,
41262306a36Sopenharmony_ci				       &comp_temp->bus_addr);
41362306a36Sopenharmony_ci		if (!comp_temp->virt_addr)
41462306a36Sopenharmony_ci			goto err_dma_alloc;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci		comp_temp->desc_virt_addr =
41762306a36Sopenharmony_ci			dma_pool_alloc(queue->desc_pool, GFP_KERNEL,
41862306a36Sopenharmony_ci				       &comp_temp->desc_bus_addr);
41962306a36Sopenharmony_ci		if (!comp_temp->desc_virt_addr)
42062306a36Sopenharmony_ci			goto err_desc_dma_alloc;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		list_add_tail(&comp_temp->list, &queue->comp_free);
42362306a36Sopenharmony_ci	}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	return 0;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cierr_desc_dma_alloc:
42862306a36Sopenharmony_ci	dma_pool_free(queue->comp_pool, comp_temp->virt_addr,
42962306a36Sopenharmony_ci		      comp_temp->bus_addr);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cierr_dma_alloc:
43262306a36Sopenharmony_ci	kfree(comp_temp);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cierr_alloc:
43562306a36Sopenharmony_ci	list_for_each_entry_safe(comp_temp, _comp_temp,
43662306a36Sopenharmony_ci				 &queue->comp_free, list) {
43762306a36Sopenharmony_ci		if (comp_temp->virt_addr)
43862306a36Sopenharmony_ci			dma_pool_free(queue->comp_pool,
43962306a36Sopenharmony_ci				      comp_temp->virt_addr,
44062306a36Sopenharmony_ci				      comp_temp->bus_addr);
44162306a36Sopenharmony_ci		if (comp_temp->desc_virt_addr)
44262306a36Sopenharmony_ci			dma_pool_free(queue->desc_pool,
44362306a36Sopenharmony_ci				      comp_temp->desc_virt_addr,
44462306a36Sopenharmony_ci				      comp_temp->desc_bus_addr);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		list_del(&comp_temp->list);
44762306a36Sopenharmony_ci		kfree(comp_temp);
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	return -ENOMEM;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/*
45462306a36Sopenharmony_ci * Request a command descriptor for enqueue.
45562306a36Sopenharmony_ci */
45662306a36Sopenharmony_cistatic struct fsl_qdma_comp
45762306a36Sopenharmony_ci*fsl_qdma_request_enqueue_desc(struct fsl_qdma_chan *fsl_chan)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	unsigned long flags;
46062306a36Sopenharmony_ci	struct fsl_qdma_comp *comp_temp;
46162306a36Sopenharmony_ci	int timeout = FSL_QDMA_COMP_TIMEOUT;
46262306a36Sopenharmony_ci	struct fsl_qdma_queue *queue = fsl_chan->queue;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	while (timeout--) {
46562306a36Sopenharmony_ci		spin_lock_irqsave(&queue->queue_lock, flags);
46662306a36Sopenharmony_ci		if (!list_empty(&queue->comp_free)) {
46762306a36Sopenharmony_ci			comp_temp = list_first_entry(&queue->comp_free,
46862306a36Sopenharmony_ci						     struct fsl_qdma_comp,
46962306a36Sopenharmony_ci						     list);
47062306a36Sopenharmony_ci			list_del(&comp_temp->list);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci			spin_unlock_irqrestore(&queue->queue_lock, flags);
47362306a36Sopenharmony_ci			comp_temp->qchan = fsl_chan;
47462306a36Sopenharmony_ci			return comp_temp;
47562306a36Sopenharmony_ci		}
47662306a36Sopenharmony_ci		spin_unlock_irqrestore(&queue->queue_lock, flags);
47762306a36Sopenharmony_ci		udelay(1);
47862306a36Sopenharmony_ci	}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	return NULL;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic struct fsl_qdma_queue
48462306a36Sopenharmony_ci*fsl_qdma_alloc_queue_resources(struct platform_device *pdev,
48562306a36Sopenharmony_ci				struct fsl_qdma_engine *fsl_qdma)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	int ret, len, i, j;
48862306a36Sopenharmony_ci	int queue_num, block_number;
48962306a36Sopenharmony_ci	unsigned int queue_size[FSL_QDMA_QUEUE_MAX];
49062306a36Sopenharmony_ci	struct fsl_qdma_queue *queue_head, *queue_temp;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	queue_num = fsl_qdma->n_queues;
49362306a36Sopenharmony_ci	block_number = fsl_qdma->block_number;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (queue_num > FSL_QDMA_QUEUE_MAX)
49662306a36Sopenharmony_ci		queue_num = FSL_QDMA_QUEUE_MAX;
49762306a36Sopenharmony_ci	len = sizeof(*queue_head) * queue_num * block_number;
49862306a36Sopenharmony_ci	queue_head = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
49962306a36Sopenharmony_ci	if (!queue_head)
50062306a36Sopenharmony_ci		return NULL;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	ret = device_property_read_u32_array(&pdev->dev, "queue-sizes",
50362306a36Sopenharmony_ci					     queue_size, queue_num);
50462306a36Sopenharmony_ci	if (ret) {
50562306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get queue-sizes.\n");
50662306a36Sopenharmony_ci		return NULL;
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci	for (j = 0; j < block_number; j++) {
50962306a36Sopenharmony_ci		for (i = 0; i < queue_num; i++) {
51062306a36Sopenharmony_ci			if (queue_size[i] > FSL_QDMA_CIRCULAR_DESC_SIZE_MAX ||
51162306a36Sopenharmony_ci			    queue_size[i] < FSL_QDMA_CIRCULAR_DESC_SIZE_MIN) {
51262306a36Sopenharmony_ci				dev_err(&pdev->dev,
51362306a36Sopenharmony_ci					"Get wrong queue-sizes.\n");
51462306a36Sopenharmony_ci				return NULL;
51562306a36Sopenharmony_ci			}
51662306a36Sopenharmony_ci			queue_temp = queue_head + i + (j * queue_num);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci			queue_temp->cq =
51962306a36Sopenharmony_ci			dmam_alloc_coherent(&pdev->dev,
52062306a36Sopenharmony_ci					    sizeof(struct fsl_qdma_format) *
52162306a36Sopenharmony_ci					    queue_size[i],
52262306a36Sopenharmony_ci					    &queue_temp->bus_addr,
52362306a36Sopenharmony_ci					    GFP_KERNEL);
52462306a36Sopenharmony_ci			if (!queue_temp->cq)
52562306a36Sopenharmony_ci				return NULL;
52662306a36Sopenharmony_ci			queue_temp->block_base = fsl_qdma->block_base +
52762306a36Sopenharmony_ci				FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
52862306a36Sopenharmony_ci			queue_temp->n_cq = queue_size[i];
52962306a36Sopenharmony_ci			queue_temp->id = i;
53062306a36Sopenharmony_ci			queue_temp->virt_head = queue_temp->cq;
53162306a36Sopenharmony_ci			queue_temp->virt_tail = queue_temp->cq;
53262306a36Sopenharmony_ci			/*
53362306a36Sopenharmony_ci			 * List for queue command buffer
53462306a36Sopenharmony_ci			 */
53562306a36Sopenharmony_ci			INIT_LIST_HEAD(&queue_temp->comp_used);
53662306a36Sopenharmony_ci			spin_lock_init(&queue_temp->queue_lock);
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci	return queue_head;
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_cistatic struct fsl_qdma_queue
54362306a36Sopenharmony_ci*fsl_qdma_prep_status_queue(struct platform_device *pdev)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	int ret;
54662306a36Sopenharmony_ci	unsigned int status_size;
54762306a36Sopenharmony_ci	struct fsl_qdma_queue *status_head;
54862306a36Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	ret = of_property_read_u32(np, "status-sizes", &status_size);
55162306a36Sopenharmony_ci	if (ret) {
55262306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get status-sizes.\n");
55362306a36Sopenharmony_ci		return NULL;
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci	if (status_size > FSL_QDMA_CIRCULAR_DESC_SIZE_MAX ||
55662306a36Sopenharmony_ci	    status_size < FSL_QDMA_CIRCULAR_DESC_SIZE_MIN) {
55762306a36Sopenharmony_ci		dev_err(&pdev->dev, "Get wrong status_size.\n");
55862306a36Sopenharmony_ci		return NULL;
55962306a36Sopenharmony_ci	}
56062306a36Sopenharmony_ci	status_head = devm_kzalloc(&pdev->dev,
56162306a36Sopenharmony_ci				   sizeof(*status_head), GFP_KERNEL);
56262306a36Sopenharmony_ci	if (!status_head)
56362306a36Sopenharmony_ci		return NULL;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	/*
56662306a36Sopenharmony_ci	 * Buffer for queue command
56762306a36Sopenharmony_ci	 */
56862306a36Sopenharmony_ci	status_head->cq = dmam_alloc_coherent(&pdev->dev,
56962306a36Sopenharmony_ci					      sizeof(struct fsl_qdma_format) *
57062306a36Sopenharmony_ci					      status_size,
57162306a36Sopenharmony_ci					      &status_head->bus_addr,
57262306a36Sopenharmony_ci					      GFP_KERNEL);
57362306a36Sopenharmony_ci	if (!status_head->cq) {
57462306a36Sopenharmony_ci		devm_kfree(&pdev->dev, status_head);
57562306a36Sopenharmony_ci		return NULL;
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci	status_head->n_cq = status_size;
57862306a36Sopenharmony_ci	status_head->virt_head = status_head->cq;
57962306a36Sopenharmony_ci	status_head->virt_tail = status_head->cq;
58062306a36Sopenharmony_ci	status_head->comp_pool = NULL;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	return status_head;
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_cistatic int fsl_qdma_halt(struct fsl_qdma_engine *fsl_qdma)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	u32 reg;
58862306a36Sopenharmony_ci	int i, j, count = FSL_QDMA_HALT_COUNT;
58962306a36Sopenharmony_ci	void __iomem *block, *ctrl = fsl_qdma->ctrl_base;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	/* Disable the command queue and wait for idle state. */
59262306a36Sopenharmony_ci	reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR);
59362306a36Sopenharmony_ci	reg |= FSL_QDMA_DMR_DQD;
59462306a36Sopenharmony_ci	qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR);
59562306a36Sopenharmony_ci	for (j = 0; j < fsl_qdma->block_number; j++) {
59662306a36Sopenharmony_ci		block = fsl_qdma->block_base +
59762306a36Sopenharmony_ci			FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
59862306a36Sopenharmony_ci		for (i = 0; i < FSL_QDMA_QUEUE_NUM_MAX; i++)
59962306a36Sopenharmony_ci			qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BCQMR(i));
60062306a36Sopenharmony_ci	}
60162306a36Sopenharmony_ci	while (1) {
60262306a36Sopenharmony_ci		reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DSR);
60362306a36Sopenharmony_ci		if (!(reg & FSL_QDMA_DSR_DB))
60462306a36Sopenharmony_ci			break;
60562306a36Sopenharmony_ci		if (count-- < 0)
60662306a36Sopenharmony_ci			return -EBUSY;
60762306a36Sopenharmony_ci		udelay(100);
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	for (j = 0; j < fsl_qdma->block_number; j++) {
61162306a36Sopenharmony_ci		block = fsl_qdma->block_base +
61262306a36Sopenharmony_ci			FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		/* Disable status queue. */
61562306a36Sopenharmony_ci		qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BSQMR);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		/*
61862306a36Sopenharmony_ci		 * clear the command queue interrupt detect register for
61962306a36Sopenharmony_ci		 * all queues.
62062306a36Sopenharmony_ci		 */
62162306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR,
62262306a36Sopenharmony_ci			    block + FSL_QDMA_BCQIDR(0));
62362306a36Sopenharmony_ci	}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	return 0;
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cistatic int
62962306a36Sopenharmony_cifsl_qdma_queue_transfer_complete(struct fsl_qdma_engine *fsl_qdma,
63062306a36Sopenharmony_ci				 void *block,
63162306a36Sopenharmony_ci				 int id)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	bool duplicate;
63462306a36Sopenharmony_ci	u32 reg, i, count;
63562306a36Sopenharmony_ci	u8 completion_status;
63662306a36Sopenharmony_ci	struct fsl_qdma_queue *temp_queue;
63762306a36Sopenharmony_ci	struct fsl_qdma_format *status_addr;
63862306a36Sopenharmony_ci	struct fsl_qdma_comp *fsl_comp = NULL;
63962306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_qdma->queue;
64062306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_status = fsl_qdma->status[id];
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	count = FSL_QDMA_MAX_SIZE;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	while (count--) {
64562306a36Sopenharmony_ci		duplicate = 0;
64662306a36Sopenharmony_ci		reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQSR);
64762306a36Sopenharmony_ci		if (reg & FSL_QDMA_BSQSR_QE)
64862306a36Sopenharmony_ci			return 0;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci		status_addr = fsl_status->virt_head;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci		if (qdma_ccdf_get_queue(status_addr) ==
65362306a36Sopenharmony_ci		   __this_cpu_read(pre.queue) &&
65462306a36Sopenharmony_ci			qdma_ccdf_addr_get64(status_addr) ==
65562306a36Sopenharmony_ci			__this_cpu_read(pre.addr))
65662306a36Sopenharmony_ci			duplicate = 1;
65762306a36Sopenharmony_ci		i = qdma_ccdf_get_queue(status_addr) +
65862306a36Sopenharmony_ci			id * fsl_qdma->n_queues;
65962306a36Sopenharmony_ci		__this_cpu_write(pre.addr, qdma_ccdf_addr_get64(status_addr));
66062306a36Sopenharmony_ci		__this_cpu_write(pre.queue, qdma_ccdf_get_queue(status_addr));
66162306a36Sopenharmony_ci		temp_queue = fsl_queue + i;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci		spin_lock(&temp_queue->queue_lock);
66462306a36Sopenharmony_ci		if (list_empty(&temp_queue->comp_used)) {
66562306a36Sopenharmony_ci			if (!duplicate) {
66662306a36Sopenharmony_ci				spin_unlock(&temp_queue->queue_lock);
66762306a36Sopenharmony_ci				return -EAGAIN;
66862306a36Sopenharmony_ci			}
66962306a36Sopenharmony_ci		} else {
67062306a36Sopenharmony_ci			fsl_comp = list_first_entry(&temp_queue->comp_used,
67162306a36Sopenharmony_ci						    struct fsl_qdma_comp, list);
67262306a36Sopenharmony_ci			if (fsl_comp->bus_addr + 16 !=
67362306a36Sopenharmony_ci				__this_cpu_read(pre.addr)) {
67462306a36Sopenharmony_ci				if (!duplicate) {
67562306a36Sopenharmony_ci					spin_unlock(&temp_queue->queue_lock);
67662306a36Sopenharmony_ci					return -EAGAIN;
67762306a36Sopenharmony_ci				}
67862306a36Sopenharmony_ci			}
67962306a36Sopenharmony_ci		}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci		if (duplicate) {
68262306a36Sopenharmony_ci			reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQMR);
68362306a36Sopenharmony_ci			reg |= FSL_QDMA_BSQMR_DI;
68462306a36Sopenharmony_ci			qdma_desc_addr_set64(status_addr, 0x0);
68562306a36Sopenharmony_ci			fsl_status->virt_head++;
68662306a36Sopenharmony_ci			if (fsl_status->virt_head == fsl_status->cq
68762306a36Sopenharmony_ci						   + fsl_status->n_cq)
68862306a36Sopenharmony_ci				fsl_status->virt_head = fsl_status->cq;
68962306a36Sopenharmony_ci			qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR);
69062306a36Sopenharmony_ci			spin_unlock(&temp_queue->queue_lock);
69162306a36Sopenharmony_ci			continue;
69262306a36Sopenharmony_ci		}
69362306a36Sopenharmony_ci		list_del(&fsl_comp->list);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci		completion_status = qdma_ccdf_get_status(status_addr);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci		reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQMR);
69862306a36Sopenharmony_ci		reg |= FSL_QDMA_BSQMR_DI;
69962306a36Sopenharmony_ci		qdma_desc_addr_set64(status_addr, 0x0);
70062306a36Sopenharmony_ci		fsl_status->virt_head++;
70162306a36Sopenharmony_ci		if (fsl_status->virt_head == fsl_status->cq + fsl_status->n_cq)
70262306a36Sopenharmony_ci			fsl_status->virt_head = fsl_status->cq;
70362306a36Sopenharmony_ci		qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR);
70462306a36Sopenharmony_ci		spin_unlock(&temp_queue->queue_lock);
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci		/* The completion_status is evaluated here
70762306a36Sopenharmony_ci		 * (outside of spin lock)
70862306a36Sopenharmony_ci		 */
70962306a36Sopenharmony_ci		if (completion_status) {
71062306a36Sopenharmony_ci			/* A completion error occurred! */
71162306a36Sopenharmony_ci			if (completion_status & QDMA_CCDF_STATUS_WTE) {
71262306a36Sopenharmony_ci				/* Write transaction error */
71362306a36Sopenharmony_ci				fsl_comp->vdesc.tx_result.result =
71462306a36Sopenharmony_ci					DMA_TRANS_WRITE_FAILED;
71562306a36Sopenharmony_ci			} else if (completion_status & QDMA_CCDF_STATUS_RTE) {
71662306a36Sopenharmony_ci				/* Read transaction error */
71762306a36Sopenharmony_ci				fsl_comp->vdesc.tx_result.result =
71862306a36Sopenharmony_ci					DMA_TRANS_READ_FAILED;
71962306a36Sopenharmony_ci			} else {
72062306a36Sopenharmony_ci				/* Command/source/destination
72162306a36Sopenharmony_ci				 * description error
72262306a36Sopenharmony_ci				 */
72362306a36Sopenharmony_ci				fsl_comp->vdesc.tx_result.result =
72462306a36Sopenharmony_ci					DMA_TRANS_ABORTED;
72562306a36Sopenharmony_ci				dev_err(fsl_qdma->dma_dev.dev,
72662306a36Sopenharmony_ci					"DMA status descriptor error %x\n",
72762306a36Sopenharmony_ci					completion_status);
72862306a36Sopenharmony_ci			}
72962306a36Sopenharmony_ci		}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci		spin_lock(&fsl_comp->qchan->vchan.lock);
73262306a36Sopenharmony_ci		vchan_cookie_complete(&fsl_comp->vdesc);
73362306a36Sopenharmony_ci		fsl_comp->qchan->status = DMA_COMPLETE;
73462306a36Sopenharmony_ci		spin_unlock(&fsl_comp->qchan->vchan.lock);
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	return 0;
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic irqreturn_t fsl_qdma_error_handler(int irq, void *dev_id)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	unsigned int intr;
74362306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma = dev_id;
74462306a36Sopenharmony_ci	void __iomem *status = fsl_qdma->status_base;
74562306a36Sopenharmony_ci	unsigned int decfdw0r;
74662306a36Sopenharmony_ci	unsigned int decfdw1r;
74762306a36Sopenharmony_ci	unsigned int decfdw2r;
74862306a36Sopenharmony_ci	unsigned int decfdw3r;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	intr = qdma_readl(fsl_qdma, status + FSL_QDMA_DEDR);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	if (intr) {
75362306a36Sopenharmony_ci		decfdw0r = qdma_readl(fsl_qdma, status + FSL_QDMA_DECFDW0R);
75462306a36Sopenharmony_ci		decfdw1r = qdma_readl(fsl_qdma, status + FSL_QDMA_DECFDW1R);
75562306a36Sopenharmony_ci		decfdw2r = qdma_readl(fsl_qdma, status + FSL_QDMA_DECFDW2R);
75662306a36Sopenharmony_ci		decfdw3r = qdma_readl(fsl_qdma, status + FSL_QDMA_DECFDW3R);
75762306a36Sopenharmony_ci		dev_err(fsl_qdma->dma_dev.dev,
75862306a36Sopenharmony_ci			"DMA transaction error! (%x: %x-%x-%x-%x)\n",
75962306a36Sopenharmony_ci			intr, decfdw0r, decfdw1r, decfdw2r, decfdw3r);
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	qdma_writel(fsl_qdma, FSL_QDMA_DEDR_CLEAR, status + FSL_QDMA_DEDR);
76362306a36Sopenharmony_ci	return IRQ_HANDLED;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_cistatic irqreturn_t fsl_qdma_queue_handler(int irq, void *dev_id)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	int id;
76962306a36Sopenharmony_ci	unsigned int intr, reg;
77062306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma = dev_id;
77162306a36Sopenharmony_ci	void __iomem *block, *ctrl = fsl_qdma->ctrl_base;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	id = irq - fsl_qdma->irq_base;
77462306a36Sopenharmony_ci	if (id < 0 && id > fsl_qdma->block_number) {
77562306a36Sopenharmony_ci		dev_err(fsl_qdma->dma_dev.dev,
77662306a36Sopenharmony_ci			"irq %d is wrong irq_base is %d\n",
77762306a36Sopenharmony_ci			irq, fsl_qdma->irq_base);
77862306a36Sopenharmony_ci	}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	block = fsl_qdma->block_base +
78162306a36Sopenharmony_ci		FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, id);
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	intr = qdma_readl(fsl_qdma, block + FSL_QDMA_BCQIDR(0));
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	if ((intr & FSL_QDMA_CQIDR_SQT) != 0)
78662306a36Sopenharmony_ci		intr = fsl_qdma_queue_transfer_complete(fsl_qdma, block, id);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	if (intr != 0) {
78962306a36Sopenharmony_ci		reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR);
79062306a36Sopenharmony_ci		reg |= FSL_QDMA_DMR_DQD;
79162306a36Sopenharmony_ci		qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR);
79262306a36Sopenharmony_ci		qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BCQIER(0));
79362306a36Sopenharmony_ci		dev_err(fsl_qdma->dma_dev.dev, "QDMA: status err!\n");
79462306a36Sopenharmony_ci	}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	/* Clear all detected events and interrupts. */
79762306a36Sopenharmony_ci	qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR,
79862306a36Sopenharmony_ci		    block + FSL_QDMA_BCQIDR(0));
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	return IRQ_HANDLED;
80162306a36Sopenharmony_ci}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cistatic int
80462306a36Sopenharmony_cifsl_qdma_irq_init(struct platform_device *pdev,
80562306a36Sopenharmony_ci		  struct fsl_qdma_engine *fsl_qdma)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	int i;
80862306a36Sopenharmony_ci	int cpu;
80962306a36Sopenharmony_ci	int ret;
81062306a36Sopenharmony_ci	char irq_name[32];
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	fsl_qdma->error_irq =
81362306a36Sopenharmony_ci		platform_get_irq_byname(pdev, "qdma-error");
81462306a36Sopenharmony_ci	if (fsl_qdma->error_irq < 0)
81562306a36Sopenharmony_ci		return fsl_qdma->error_irq;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, fsl_qdma->error_irq,
81862306a36Sopenharmony_ci			       fsl_qdma_error_handler, 0,
81962306a36Sopenharmony_ci			       "qDMA error", fsl_qdma);
82062306a36Sopenharmony_ci	if (ret) {
82162306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't register qDMA controller IRQ.\n");
82262306a36Sopenharmony_ci		return  ret;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	for (i = 0; i < fsl_qdma->block_number; i++) {
82662306a36Sopenharmony_ci		sprintf(irq_name, "qdma-queue%d", i);
82762306a36Sopenharmony_ci		fsl_qdma->queue_irq[i] =
82862306a36Sopenharmony_ci				platform_get_irq_byname(pdev, irq_name);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci		if (fsl_qdma->queue_irq[i] < 0)
83162306a36Sopenharmony_ci			return fsl_qdma->queue_irq[i];
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci		ret = devm_request_irq(&pdev->dev,
83462306a36Sopenharmony_ci				       fsl_qdma->queue_irq[i],
83562306a36Sopenharmony_ci				       fsl_qdma_queue_handler,
83662306a36Sopenharmony_ci				       0,
83762306a36Sopenharmony_ci				       "qDMA queue",
83862306a36Sopenharmony_ci				       fsl_qdma);
83962306a36Sopenharmony_ci		if (ret) {
84062306a36Sopenharmony_ci			dev_err(&pdev->dev,
84162306a36Sopenharmony_ci				"Can't register qDMA queue IRQ.\n");
84262306a36Sopenharmony_ci			return  ret;
84362306a36Sopenharmony_ci		}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci		cpu = i % num_online_cpus();
84662306a36Sopenharmony_ci		ret = irq_set_affinity_hint(fsl_qdma->queue_irq[i],
84762306a36Sopenharmony_ci					    get_cpu_mask(cpu));
84862306a36Sopenharmony_ci		if (ret) {
84962306a36Sopenharmony_ci			dev_err(&pdev->dev,
85062306a36Sopenharmony_ci				"Can't set cpu %d affinity to IRQ %d.\n",
85162306a36Sopenharmony_ci				cpu,
85262306a36Sopenharmony_ci				fsl_qdma->queue_irq[i]);
85362306a36Sopenharmony_ci			return  ret;
85462306a36Sopenharmony_ci		}
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	return 0;
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_cistatic void fsl_qdma_irq_exit(struct platform_device *pdev,
86162306a36Sopenharmony_ci			      struct fsl_qdma_engine *fsl_qdma)
86262306a36Sopenharmony_ci{
86362306a36Sopenharmony_ci	int i;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	devm_free_irq(&pdev->dev, fsl_qdma->error_irq, fsl_qdma);
86662306a36Sopenharmony_ci	for (i = 0; i < fsl_qdma->block_number; i++)
86762306a36Sopenharmony_ci		devm_free_irq(&pdev->dev, fsl_qdma->queue_irq[i], fsl_qdma);
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic int fsl_qdma_reg_init(struct fsl_qdma_engine *fsl_qdma)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	u32 reg;
87362306a36Sopenharmony_ci	int i, j, ret;
87462306a36Sopenharmony_ci	struct fsl_qdma_queue *temp;
87562306a36Sopenharmony_ci	void __iomem *status = fsl_qdma->status_base;
87662306a36Sopenharmony_ci	void __iomem *block, *ctrl = fsl_qdma->ctrl_base;
87762306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_qdma->queue;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* Try to halt the qDMA engine first. */
88062306a36Sopenharmony_ci	ret = fsl_qdma_halt(fsl_qdma);
88162306a36Sopenharmony_ci	if (ret) {
88262306a36Sopenharmony_ci		dev_err(fsl_qdma->dma_dev.dev, "DMA halt failed!");
88362306a36Sopenharmony_ci		return ret;
88462306a36Sopenharmony_ci	}
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	for (i = 0; i < fsl_qdma->block_number; i++) {
88762306a36Sopenharmony_ci		/*
88862306a36Sopenharmony_ci		 * Clear the command queue interrupt detect register for
88962306a36Sopenharmony_ci		 * all queues.
89062306a36Sopenharmony_ci		 */
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci		block = fsl_qdma->block_base +
89362306a36Sopenharmony_ci			FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, i);
89462306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR,
89562306a36Sopenharmony_ci			    block + FSL_QDMA_BCQIDR(0));
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	for (j = 0; j < fsl_qdma->block_number; j++) {
89962306a36Sopenharmony_ci		block = fsl_qdma->block_base +
90062306a36Sopenharmony_ci			FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
90162306a36Sopenharmony_ci		for (i = 0; i < fsl_qdma->n_queues; i++) {
90262306a36Sopenharmony_ci			temp = fsl_queue + i + (j * fsl_qdma->n_queues);
90362306a36Sopenharmony_ci			/*
90462306a36Sopenharmony_ci			 * Initialize Command Queue registers to
90562306a36Sopenharmony_ci			 * point to the first
90662306a36Sopenharmony_ci			 * command descriptor in memory.
90762306a36Sopenharmony_ci			 * Dequeue Pointer Address Registers
90862306a36Sopenharmony_ci			 * Enqueue Pointer Address Registers
90962306a36Sopenharmony_ci			 */
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci			qdma_writel(fsl_qdma, temp->bus_addr,
91262306a36Sopenharmony_ci				    block + FSL_QDMA_BCQDPA_SADDR(i));
91362306a36Sopenharmony_ci			qdma_writel(fsl_qdma, temp->bus_addr,
91462306a36Sopenharmony_ci				    block + FSL_QDMA_BCQEPA_SADDR(i));
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci			/* Initialize the queue mode. */
91762306a36Sopenharmony_ci			reg = FSL_QDMA_BCQMR_EN;
91862306a36Sopenharmony_ci			reg |= FSL_QDMA_BCQMR_CD_THLD(ilog2(temp->n_cq) - 4);
91962306a36Sopenharmony_ci			reg |= FSL_QDMA_BCQMR_CQ_SIZE(ilog2(temp->n_cq) - 6);
92062306a36Sopenharmony_ci			qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BCQMR(i));
92162306a36Sopenharmony_ci		}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci		/*
92462306a36Sopenharmony_ci		 * Workaround for erratum: ERR010812.
92562306a36Sopenharmony_ci		 * We must enable XOFF to avoid the enqueue rejection occurs.
92662306a36Sopenharmony_ci		 * Setting SQCCMR ENTER_WM to 0x20.
92762306a36Sopenharmony_ci		 */
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_SQCCMR_ENTER_WM,
93062306a36Sopenharmony_ci			    block + FSL_QDMA_SQCCMR);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci		/*
93362306a36Sopenharmony_ci		 * Initialize status queue registers to point to the first
93462306a36Sopenharmony_ci		 * command descriptor in memory.
93562306a36Sopenharmony_ci		 * Dequeue Pointer Address Registers
93662306a36Sopenharmony_ci		 * Enqueue Pointer Address Registers
93762306a36Sopenharmony_ci		 */
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci		qdma_writel(fsl_qdma, fsl_qdma->status[j]->bus_addr,
94062306a36Sopenharmony_ci			    block + FSL_QDMA_SQEPAR);
94162306a36Sopenharmony_ci		qdma_writel(fsl_qdma, fsl_qdma->status[j]->bus_addr,
94262306a36Sopenharmony_ci			    block + FSL_QDMA_SQDPAR);
94362306a36Sopenharmony_ci		/* Initialize status queue interrupt. */
94462306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_BCQIER_CQTIE,
94562306a36Sopenharmony_ci			    block + FSL_QDMA_BCQIER(0));
94662306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_BSQICR_ICEN |
94762306a36Sopenharmony_ci				   FSL_QDMA_BSQICR_ICST(5) | 0x8000,
94862306a36Sopenharmony_ci				   block + FSL_QDMA_BSQICR);
94962306a36Sopenharmony_ci		qdma_writel(fsl_qdma, FSL_QDMA_CQIER_MEIE |
95062306a36Sopenharmony_ci				   FSL_QDMA_CQIER_TEIE,
95162306a36Sopenharmony_ci				   block + FSL_QDMA_CQIER);
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci		/* Initialize the status queue mode. */
95462306a36Sopenharmony_ci		reg = FSL_QDMA_BSQMR_EN;
95562306a36Sopenharmony_ci		reg |= FSL_QDMA_BSQMR_CQ_SIZE(ilog2
95662306a36Sopenharmony_ci			(fsl_qdma->status[j]->n_cq) - 6);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci		qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR);
95962306a36Sopenharmony_ci		reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQMR);
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	/* Initialize controller interrupt register. */
96362306a36Sopenharmony_ci	qdma_writel(fsl_qdma, FSL_QDMA_DEDR_CLEAR, status + FSL_QDMA_DEDR);
96462306a36Sopenharmony_ci	qdma_writel(fsl_qdma, FSL_QDMA_DEIER_CLEAR, status + FSL_QDMA_DEIER);
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR);
96762306a36Sopenharmony_ci	reg &= ~FSL_QDMA_DMR_DQD;
96862306a36Sopenharmony_ci	qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	return 0;
97162306a36Sopenharmony_ci}
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_cistatic struct dma_async_tx_descriptor *
97462306a36Sopenharmony_cifsl_qdma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst,
97562306a36Sopenharmony_ci		     dma_addr_t src, size_t len, unsigned long flags)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	struct fsl_qdma_comp *fsl_comp;
97862306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	fsl_comp = fsl_qdma_request_enqueue_desc(fsl_chan);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	if (!fsl_comp)
98362306a36Sopenharmony_ci		return NULL;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	fsl_qdma_comp_fill_memcpy(fsl_comp, dst, src, len);
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	return vchan_tx_prep(&fsl_chan->vchan, &fsl_comp->vdesc, flags);
98862306a36Sopenharmony_ci}
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_cistatic void fsl_qdma_enqueue_desc(struct fsl_qdma_chan *fsl_chan)
99162306a36Sopenharmony_ci{
99262306a36Sopenharmony_ci	u32 reg;
99362306a36Sopenharmony_ci	struct virt_dma_desc *vdesc;
99462306a36Sopenharmony_ci	struct fsl_qdma_comp *fsl_comp;
99562306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_chan->queue;
99662306a36Sopenharmony_ci	void __iomem *block = fsl_queue->block_base;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	reg = qdma_readl(fsl_chan->qdma, block + FSL_QDMA_BCQSR(fsl_queue->id));
99962306a36Sopenharmony_ci	if (reg & (FSL_QDMA_BCQSR_QF | FSL_QDMA_BCQSR_XOFF))
100062306a36Sopenharmony_ci		return;
100162306a36Sopenharmony_ci	vdesc = vchan_next_desc(&fsl_chan->vchan);
100262306a36Sopenharmony_ci	if (!vdesc)
100362306a36Sopenharmony_ci		return;
100462306a36Sopenharmony_ci	list_del(&vdesc->node);
100562306a36Sopenharmony_ci	fsl_comp = to_fsl_qdma_comp(vdesc);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	memcpy(fsl_queue->virt_head++,
100862306a36Sopenharmony_ci	       fsl_comp->virt_addr, sizeof(struct fsl_qdma_format));
100962306a36Sopenharmony_ci	if (fsl_queue->virt_head == fsl_queue->cq + fsl_queue->n_cq)
101062306a36Sopenharmony_ci		fsl_queue->virt_head = fsl_queue->cq;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	list_add_tail(&fsl_comp->list, &fsl_queue->comp_used);
101362306a36Sopenharmony_ci	barrier();
101462306a36Sopenharmony_ci	reg = qdma_readl(fsl_chan->qdma, block + FSL_QDMA_BCQMR(fsl_queue->id));
101562306a36Sopenharmony_ci	reg |= FSL_QDMA_BCQMR_EI;
101662306a36Sopenharmony_ci	qdma_writel(fsl_chan->qdma, reg, block + FSL_QDMA_BCQMR(fsl_queue->id));
101762306a36Sopenharmony_ci	fsl_chan->status = DMA_IN_PROGRESS;
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_cistatic void fsl_qdma_free_desc(struct virt_dma_desc *vdesc)
102162306a36Sopenharmony_ci{
102262306a36Sopenharmony_ci	unsigned long flags;
102362306a36Sopenharmony_ci	struct fsl_qdma_comp *fsl_comp;
102462306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	fsl_comp = to_fsl_qdma_comp(vdesc);
102762306a36Sopenharmony_ci	fsl_queue = fsl_comp->qchan->queue;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	spin_lock_irqsave(&fsl_queue->queue_lock, flags);
103062306a36Sopenharmony_ci	list_add_tail(&fsl_comp->list, &fsl_queue->comp_free);
103162306a36Sopenharmony_ci	spin_unlock_irqrestore(&fsl_queue->queue_lock, flags);
103262306a36Sopenharmony_ci}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_cistatic void fsl_qdma_issue_pending(struct dma_chan *chan)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	unsigned long flags;
103762306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
103862306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_chan->queue;
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	spin_lock_irqsave(&fsl_queue->queue_lock, flags);
104162306a36Sopenharmony_ci	spin_lock(&fsl_chan->vchan.lock);
104262306a36Sopenharmony_ci	if (vchan_issue_pending(&fsl_chan->vchan))
104362306a36Sopenharmony_ci		fsl_qdma_enqueue_desc(fsl_chan);
104462306a36Sopenharmony_ci	spin_unlock(&fsl_chan->vchan.lock);
104562306a36Sopenharmony_ci	spin_unlock_irqrestore(&fsl_queue->queue_lock, flags);
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_cistatic void fsl_qdma_synchronize(struct dma_chan *chan)
104962306a36Sopenharmony_ci{
105062306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	vchan_synchronize(&fsl_chan->vchan);
105362306a36Sopenharmony_ci}
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_cistatic int fsl_qdma_terminate_all(struct dma_chan *chan)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	LIST_HEAD(head);
105862306a36Sopenharmony_ci	unsigned long flags;
105962306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
106262306a36Sopenharmony_ci	vchan_get_all_descriptors(&fsl_chan->vchan, &head);
106362306a36Sopenharmony_ci	spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
106462306a36Sopenharmony_ci	vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
106562306a36Sopenharmony_ci	return 0;
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic int fsl_qdma_alloc_chan_resources(struct dma_chan *chan)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	int ret;
107162306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan);
107262306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma = fsl_chan->qdma;
107362306a36Sopenharmony_ci	struct fsl_qdma_queue *fsl_queue = fsl_chan->queue;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	if (fsl_queue->comp_pool && fsl_queue->desc_pool)
107662306a36Sopenharmony_ci		return fsl_qdma->desc_allocated;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	INIT_LIST_HEAD(&fsl_queue->comp_free);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	/*
108162306a36Sopenharmony_ci	 * The dma pool for queue command buffer
108262306a36Sopenharmony_ci	 */
108362306a36Sopenharmony_ci	fsl_queue->comp_pool =
108462306a36Sopenharmony_ci	dma_pool_create("comp_pool",
108562306a36Sopenharmony_ci			chan->device->dev,
108662306a36Sopenharmony_ci			FSL_QDMA_COMMAND_BUFFER_SIZE,
108762306a36Sopenharmony_ci			64, 0);
108862306a36Sopenharmony_ci	if (!fsl_queue->comp_pool)
108962306a36Sopenharmony_ci		return -ENOMEM;
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	/*
109262306a36Sopenharmony_ci	 * The dma pool for Descriptor(SD/DD) buffer
109362306a36Sopenharmony_ci	 */
109462306a36Sopenharmony_ci	fsl_queue->desc_pool =
109562306a36Sopenharmony_ci	dma_pool_create("desc_pool",
109662306a36Sopenharmony_ci			chan->device->dev,
109762306a36Sopenharmony_ci			FSL_QDMA_DESCRIPTOR_BUFFER_SIZE,
109862306a36Sopenharmony_ci			32, 0);
109962306a36Sopenharmony_ci	if (!fsl_queue->desc_pool)
110062306a36Sopenharmony_ci		goto err_desc_pool;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	ret = fsl_qdma_pre_request_enqueue_desc(fsl_queue);
110362306a36Sopenharmony_ci	if (ret) {
110462306a36Sopenharmony_ci		dev_err(chan->device->dev,
110562306a36Sopenharmony_ci			"failed to alloc dma buffer for S/G descriptor\n");
110662306a36Sopenharmony_ci		goto err_mem;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	fsl_qdma->desc_allocated++;
111062306a36Sopenharmony_ci	return fsl_qdma->desc_allocated;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_cierr_mem:
111362306a36Sopenharmony_ci	dma_pool_destroy(fsl_queue->desc_pool);
111462306a36Sopenharmony_cierr_desc_pool:
111562306a36Sopenharmony_ci	dma_pool_destroy(fsl_queue->comp_pool);
111662306a36Sopenharmony_ci	return -ENOMEM;
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic int fsl_qdma_probe(struct platform_device *pdev)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	int ret, i;
112262306a36Sopenharmony_ci	int blk_num, blk_off;
112362306a36Sopenharmony_ci	u32 len, chans, queues;
112462306a36Sopenharmony_ci	struct fsl_qdma_chan *fsl_chan;
112562306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma;
112662306a36Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	ret = of_property_read_u32(np, "dma-channels", &chans);
112962306a36Sopenharmony_ci	if (ret) {
113062306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get dma-channels.\n");
113162306a36Sopenharmony_ci		return ret;
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	ret = of_property_read_u32(np, "block-offset", &blk_off);
113562306a36Sopenharmony_ci	if (ret) {
113662306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get block-offset.\n");
113762306a36Sopenharmony_ci		return ret;
113862306a36Sopenharmony_ci	}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	ret = of_property_read_u32(np, "block-number", &blk_num);
114162306a36Sopenharmony_ci	if (ret) {
114262306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get block-number.\n");
114362306a36Sopenharmony_ci		return ret;
114462306a36Sopenharmony_ci	}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	blk_num = min_t(int, blk_num, num_online_cpus());
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	len = sizeof(*fsl_qdma);
114962306a36Sopenharmony_ci	fsl_qdma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
115062306a36Sopenharmony_ci	if (!fsl_qdma)
115162306a36Sopenharmony_ci		return -ENOMEM;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	len = sizeof(*fsl_chan) * chans;
115462306a36Sopenharmony_ci	fsl_qdma->chans = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
115562306a36Sopenharmony_ci	if (!fsl_qdma->chans)
115662306a36Sopenharmony_ci		return -ENOMEM;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	len = sizeof(struct fsl_qdma_queue *) * blk_num;
115962306a36Sopenharmony_ci	fsl_qdma->status = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
116062306a36Sopenharmony_ci	if (!fsl_qdma->status)
116162306a36Sopenharmony_ci		return -ENOMEM;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	len = sizeof(int) * blk_num;
116462306a36Sopenharmony_ci	fsl_qdma->queue_irq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
116562306a36Sopenharmony_ci	if (!fsl_qdma->queue_irq)
116662306a36Sopenharmony_ci		return -ENOMEM;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	ret = of_property_read_u32(np, "fsl,dma-queues", &queues);
116962306a36Sopenharmony_ci	if (ret) {
117062306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't get queues.\n");
117162306a36Sopenharmony_ci		return ret;
117262306a36Sopenharmony_ci	}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	fsl_qdma->desc_allocated = 0;
117562306a36Sopenharmony_ci	fsl_qdma->n_chans = chans;
117662306a36Sopenharmony_ci	fsl_qdma->n_queues = queues;
117762306a36Sopenharmony_ci	fsl_qdma->block_number = blk_num;
117862306a36Sopenharmony_ci	fsl_qdma->block_offset = blk_off;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	mutex_init(&fsl_qdma->fsl_qdma_mutex);
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	for (i = 0; i < fsl_qdma->block_number; i++) {
118362306a36Sopenharmony_ci		fsl_qdma->status[i] = fsl_qdma_prep_status_queue(pdev);
118462306a36Sopenharmony_ci		if (!fsl_qdma->status[i])
118562306a36Sopenharmony_ci			return -ENOMEM;
118662306a36Sopenharmony_ci	}
118762306a36Sopenharmony_ci	fsl_qdma->ctrl_base = devm_platform_ioremap_resource(pdev, 0);
118862306a36Sopenharmony_ci	if (IS_ERR(fsl_qdma->ctrl_base))
118962306a36Sopenharmony_ci		return PTR_ERR(fsl_qdma->ctrl_base);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	fsl_qdma->status_base = devm_platform_ioremap_resource(pdev, 1);
119262306a36Sopenharmony_ci	if (IS_ERR(fsl_qdma->status_base))
119362306a36Sopenharmony_ci		return PTR_ERR(fsl_qdma->status_base);
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	fsl_qdma->block_base = devm_platform_ioremap_resource(pdev, 2);
119662306a36Sopenharmony_ci	if (IS_ERR(fsl_qdma->block_base))
119762306a36Sopenharmony_ci		return PTR_ERR(fsl_qdma->block_base);
119862306a36Sopenharmony_ci	fsl_qdma->queue = fsl_qdma_alloc_queue_resources(pdev, fsl_qdma);
119962306a36Sopenharmony_ci	if (!fsl_qdma->queue)
120062306a36Sopenharmony_ci		return -ENOMEM;
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	fsl_qdma->irq_base = platform_get_irq_byname(pdev, "qdma-queue0");
120362306a36Sopenharmony_ci	if (fsl_qdma->irq_base < 0)
120462306a36Sopenharmony_ci		return fsl_qdma->irq_base;
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	fsl_qdma->feature = of_property_read_bool(np, "big-endian");
120762306a36Sopenharmony_ci	INIT_LIST_HEAD(&fsl_qdma->dma_dev.channels);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	for (i = 0; i < fsl_qdma->n_chans; i++) {
121062306a36Sopenharmony_ci		struct fsl_qdma_chan *fsl_chan = &fsl_qdma->chans[i];
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci		fsl_chan->qdma = fsl_qdma;
121362306a36Sopenharmony_ci		fsl_chan->queue = fsl_qdma->queue + i % (fsl_qdma->n_queues *
121462306a36Sopenharmony_ci							fsl_qdma->block_number);
121562306a36Sopenharmony_ci		fsl_chan->vchan.desc_free = fsl_qdma_free_desc;
121662306a36Sopenharmony_ci		vchan_init(&fsl_chan->vchan, &fsl_qdma->dma_dev);
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	dma_cap_set(DMA_MEMCPY, fsl_qdma->dma_dev.cap_mask);
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	fsl_qdma->dma_dev.dev = &pdev->dev;
122262306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_free_chan_resources =
122362306a36Sopenharmony_ci		fsl_qdma_free_chan_resources;
122462306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_alloc_chan_resources =
122562306a36Sopenharmony_ci		fsl_qdma_alloc_chan_resources;
122662306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_tx_status = dma_cookie_status;
122762306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_prep_dma_memcpy = fsl_qdma_prep_memcpy;
122862306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_issue_pending = fsl_qdma_issue_pending;
122962306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_synchronize = fsl_qdma_synchronize;
123062306a36Sopenharmony_ci	fsl_qdma->dma_dev.device_terminate_all = fsl_qdma_terminate_all;
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
123362306a36Sopenharmony_ci	if (ret) {
123462306a36Sopenharmony_ci		dev_err(&pdev->dev, "dma_set_mask failure.\n");
123562306a36Sopenharmony_ci		return ret;
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	platform_set_drvdata(pdev, fsl_qdma);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	ret = fsl_qdma_reg_init(fsl_qdma);
124162306a36Sopenharmony_ci	if (ret) {
124262306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n");
124362306a36Sopenharmony_ci		return ret;
124462306a36Sopenharmony_ci	}
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	ret = fsl_qdma_irq_init(pdev, fsl_qdma);
124762306a36Sopenharmony_ci	if (ret)
124862306a36Sopenharmony_ci		return ret;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	ret = dma_async_device_register(&fsl_qdma->dma_dev);
125162306a36Sopenharmony_ci	if (ret) {
125262306a36Sopenharmony_ci		dev_err(&pdev->dev, "Can't register NXP Layerscape qDMA engine.\n");
125362306a36Sopenharmony_ci		return ret;
125462306a36Sopenharmony_ci	}
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	return 0;
125762306a36Sopenharmony_ci}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_cistatic void fsl_qdma_cleanup_vchan(struct dma_device *dmadev)
126062306a36Sopenharmony_ci{
126162306a36Sopenharmony_ci	struct fsl_qdma_chan *chan, *_chan;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	list_for_each_entry_safe(chan, _chan,
126462306a36Sopenharmony_ci				 &dmadev->channels, vchan.chan.device_node) {
126562306a36Sopenharmony_ci		list_del(&chan->vchan.chan.device_node);
126662306a36Sopenharmony_ci		tasklet_kill(&chan->vchan.task);
126762306a36Sopenharmony_ci	}
126862306a36Sopenharmony_ci}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_cistatic int fsl_qdma_remove(struct platform_device *pdev)
127162306a36Sopenharmony_ci{
127262306a36Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
127362306a36Sopenharmony_ci	struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev);
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci	fsl_qdma_irq_exit(pdev, fsl_qdma);
127662306a36Sopenharmony_ci	fsl_qdma_cleanup_vchan(&fsl_qdma->dma_dev);
127762306a36Sopenharmony_ci	of_dma_controller_free(np);
127862306a36Sopenharmony_ci	dma_async_device_unregister(&fsl_qdma->dma_dev);
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	return 0;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic const struct of_device_id fsl_qdma_dt_ids[] = {
128462306a36Sopenharmony_ci	{ .compatible = "fsl,ls1021a-qdma", },
128562306a36Sopenharmony_ci	{ /* sentinel */ }
128662306a36Sopenharmony_ci};
128762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, fsl_qdma_dt_ids);
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_cistatic struct platform_driver fsl_qdma_driver = {
129062306a36Sopenharmony_ci	.driver		= {
129162306a36Sopenharmony_ci		.name	= "fsl-qdma",
129262306a36Sopenharmony_ci		.of_match_table = fsl_qdma_dt_ids,
129362306a36Sopenharmony_ci	},
129462306a36Sopenharmony_ci	.probe          = fsl_qdma_probe,
129562306a36Sopenharmony_ci	.remove		= fsl_qdma_remove,
129662306a36Sopenharmony_ci};
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cimodule_platform_driver(fsl_qdma_driver);
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ciMODULE_ALIAS("platform:fsl-qdma");
130162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
130262306a36Sopenharmony_ciMODULE_DESCRIPTION("NXP Layerscape qDMA engine driver");
1303