18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
48c2ecf20Sopenharmony_ci * Synopsys DesignWare eDMA core driver
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _DW_EDMA_CORE_H
108c2ecf20Sopenharmony_ci#define _DW_EDMA_CORE_H
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/msi.h>
138c2ecf20Sopenharmony_ci#include <linux/dma/edma.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "../virt-dma.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define EDMA_LL_SZ					24
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cienum dw_edma_dir {
208c2ecf20Sopenharmony_ci	EDMA_DIR_WRITE = 0,
218c2ecf20Sopenharmony_ci	EDMA_DIR_READ
228c2ecf20Sopenharmony_ci};
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cienum dw_edma_mode {
258c2ecf20Sopenharmony_ci	EDMA_MODE_LEGACY = 0,
268c2ecf20Sopenharmony_ci	EDMA_MODE_UNROLL
278c2ecf20Sopenharmony_ci};
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cienum dw_edma_request {
308c2ecf20Sopenharmony_ci	EDMA_REQ_NONE = 0,
318c2ecf20Sopenharmony_ci	EDMA_REQ_STOP,
328c2ecf20Sopenharmony_ci	EDMA_REQ_PAUSE
338c2ecf20Sopenharmony_ci};
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cienum dw_edma_status {
368c2ecf20Sopenharmony_ci	EDMA_ST_IDLE = 0,
378c2ecf20Sopenharmony_ci	EDMA_ST_PAUSE,
388c2ecf20Sopenharmony_ci	EDMA_ST_BUSY
398c2ecf20Sopenharmony_ci};
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistruct dw_edma_chan;
428c2ecf20Sopenharmony_cistruct dw_edma_chunk;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistruct dw_edma_burst {
458c2ecf20Sopenharmony_ci	struct list_head		list;
468c2ecf20Sopenharmony_ci	u64				sar;
478c2ecf20Sopenharmony_ci	u64				dar;
488c2ecf20Sopenharmony_ci	u32				sz;
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistruct dw_edma_region {
528c2ecf20Sopenharmony_ci	phys_addr_t			paddr;
538c2ecf20Sopenharmony_ci	void				__iomem *vaddr;
548c2ecf20Sopenharmony_ci	size_t				sz;
558c2ecf20Sopenharmony_ci};
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistruct dw_edma_chunk {
588c2ecf20Sopenharmony_ci	struct list_head		list;
598c2ecf20Sopenharmony_ci	struct dw_edma_chan		*chan;
608c2ecf20Sopenharmony_ci	struct dw_edma_burst		*burst;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	u32				bursts_alloc;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	u8				cb;
658c2ecf20Sopenharmony_ci	struct dw_edma_region		ll_region;	/* Linked list */
668c2ecf20Sopenharmony_ci};
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistruct dw_edma_desc {
698c2ecf20Sopenharmony_ci	struct virt_dma_desc		vd;
708c2ecf20Sopenharmony_ci	struct dw_edma_chan		*chan;
718c2ecf20Sopenharmony_ci	struct dw_edma_chunk		*chunk;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	u32				chunks_alloc;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	u32				alloc_sz;
768c2ecf20Sopenharmony_ci	u32				xfer_sz;
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistruct dw_edma_chan {
808c2ecf20Sopenharmony_ci	struct virt_dma_chan		vc;
818c2ecf20Sopenharmony_ci	struct dw_edma_chip		*chip;
828c2ecf20Sopenharmony_ci	int				id;
838c2ecf20Sopenharmony_ci	enum dw_edma_dir		dir;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	off_t				ll_off;
868c2ecf20Sopenharmony_ci	u32				ll_max;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	off_t				dt_off;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	struct msi_msg			msi;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	enum dw_edma_request		request;
938c2ecf20Sopenharmony_ci	enum dw_edma_status		status;
948c2ecf20Sopenharmony_ci	u8				configured;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	struct dma_slave_config		config;
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct dw_edma_irq {
1008c2ecf20Sopenharmony_ci	struct msi_msg                  msi;
1018c2ecf20Sopenharmony_ci	u32				wr_mask;
1028c2ecf20Sopenharmony_ci	u32				rd_mask;
1038c2ecf20Sopenharmony_ci	struct dw_edma			*dw;
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistruct dw_edma_core_ops {
1078c2ecf20Sopenharmony_ci	int	(*irq_vector)(struct device *dev, unsigned int nr);
1088c2ecf20Sopenharmony_ci};
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistruct dw_edma {
1118c2ecf20Sopenharmony_ci	char				name[20];
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	struct dma_device		wr_edma;
1148c2ecf20Sopenharmony_ci	u16				wr_ch_cnt;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	struct dma_device		rd_edma;
1178c2ecf20Sopenharmony_ci	u16				rd_ch_cnt;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	struct dw_edma_region		rg_region;	/* Registers */
1208c2ecf20Sopenharmony_ci	struct dw_edma_region		ll_region;	/* Linked list */
1218c2ecf20Sopenharmony_ci	struct dw_edma_region		dt_region;	/* Data */
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	struct dw_edma_irq		*irq;
1248c2ecf20Sopenharmony_ci	int				nr_irqs;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	u32				version;
1278c2ecf20Sopenharmony_ci	enum dw_edma_mode		mode;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	struct dw_edma_chan		*chan;
1308c2ecf20Sopenharmony_ci	const struct dw_edma_core_ops	*ops;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	raw_spinlock_t			lock;		/* Only for legacy */
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistruct dw_edma_sg {
1368c2ecf20Sopenharmony_ci	struct scatterlist		*sgl;
1378c2ecf20Sopenharmony_ci	unsigned int			len;
1388c2ecf20Sopenharmony_ci};
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistruct dw_edma_cyclic {
1418c2ecf20Sopenharmony_ci	dma_addr_t			paddr;
1428c2ecf20Sopenharmony_ci	size_t				len;
1438c2ecf20Sopenharmony_ci	size_t				cnt;
1448c2ecf20Sopenharmony_ci};
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistruct dw_edma_transfer {
1478c2ecf20Sopenharmony_ci	struct dma_chan			*dchan;
1488c2ecf20Sopenharmony_ci	union dw_edma_xfer {
1498c2ecf20Sopenharmony_ci		struct dw_edma_sg	sg;
1508c2ecf20Sopenharmony_ci		struct dw_edma_cyclic	cyclic;
1518c2ecf20Sopenharmony_ci	} xfer;
1528c2ecf20Sopenharmony_ci	enum dma_transfer_direction	direction;
1538c2ecf20Sopenharmony_ci	unsigned long			flags;
1548c2ecf20Sopenharmony_ci	bool				cyclic;
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic inline
1588c2ecf20Sopenharmony_cistruct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	return container_of(vc, struct dw_edma_chan, vc);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic inline
1648c2ecf20Sopenharmony_cistruct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	return vc2dw_edma_chan(to_virt_chan(dchan));
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci#endif /* _DW_EDMA_CORE_H */
170