xref: /linux/include/linux/dma/edma.h (revision 66498c75b4f8017f62d720d9b59675bdf3abce91)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
4  * Synopsys DesignWare eDMA core driver
5  *
6  * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
7  */
8 
9 #ifndef _DW_EDMA_H
10 #define _DW_EDMA_H
11 
12 #include <linux/device.h>
13 #include <linux/dmaengine.h>
14 
15 #define EDMA_MAX_WR_CH                                  8
16 #define EDMA_MAX_RD_CH                                  8
17 #define HDMA_MAX_WR_CH                                  64
18 #define HDMA_MAX_RD_CH                                  64
19 
20 struct dw_edma;
21 
22 struct dw_edma_region {
23 	u64		paddr;
24 	union {
25 		void		*mem;
26 		void __iomem	*io;
27 	} vaddr;
28 	size_t		sz;
29 };
30 
31 /**
32  * struct dw_edma_plat_ops - platform-specific eDMA methods
33  * @irq_vector:		Get IRQ number of the passed eDMA channel. Note the
34  *			method accepts the channel id in the end-to-end
35  *			numbering with the eDMA write channels being placed
36  *			first in the row.
37  * @pci_address:	Get PCIe bus address corresponding to the passed CPU
38  *			address. Note there is no need in specifying this
39  *			function if the address translation is performed by
40  *			the DW PCIe RP/EP controller with the DW eDMA device in
41  *			subject and DMA_BYPASS isn't set for all the outbound
42  *			iATU windows. That will be done by the controller
43  *			automatically.
44  */
45 struct dw_edma_plat_ops {
46 	int (*irq_vector)(struct device *dev, unsigned int nr);
47 	u64 (*pci_address)(struct device *dev, phys_addr_t cpu_addr);
48 };
49 
50 enum dw_edma_map_format {
51 	EDMA_MF_EDMA_LEGACY = 0x0,
52 	EDMA_MF_EDMA_UNROLL = 0x1,
53 	EDMA_MF_HDMA_COMPAT = 0x5,
54 	EDMA_MF_HDMA_NATIVE = 0x7,
55 };
56 
57 /**
58  * enum dw_edma_chip_flags - Flags specific to an eDMA chip
59  * @DW_EDMA_CHIP_LOCAL:		eDMA is used locally by an endpoint
60  * @DW_EDMA_CHIP_PARTIAL:	Only channels described by this instance are
61  *				owned by this driver. Controller-wide state
62  *				must be preserved, and layouts with shared
63  *				direction-wide registers must only be shared at
64  *				direction granularity. Layouts with per-channel
65  *				registers may be shared at channel granularity.
66  */
67 enum dw_edma_chip_flags {
68 	DW_EDMA_CHIP_LOCAL	= BIT(0),
69 	DW_EDMA_CHIP_PARTIAL	= BIT(1),
70 };
71 
72 /**
73  * enum dw_edma_ch_irq_mode - per-channel interrupt routing control
74  * @DW_EDMA_CH_IRQ_LOCAL:     local interrupt only (edma_int[])
75  * @DW_EDMA_CH_IRQ_REMOTE:    remote interrupt only (IMWr/MSI), without
76  *                            delivering local edma_int[].
77  *
78  * DesignWare EP eDMA can signal interrupts locally through the edma_int[]
79  * bus, and remotely using posted memory writes (IMWr) that may be
80  * interpreted as MSI/MSI-X by the RC.
81  *
82  * For the v0 eDMA linked-list programming path, DMA_*_INT_MASK gates the local
83  * edma_int[] assertion, while there is no dedicated per-channel mask for IMWr
84  * generation. To request a remote-only interrupt, Synopsys recommends setting
85  * both LIE and RIE, and masking the local interrupt in DMA_*_INT_MASK. See the
86  * DesignWare endpoint databook 6.30a, Linked List Mode interrupt handling
87  * ("Software Programming of an Endpoint's LIE and RIE Bits for Linked List
88  * Transfers", Attention).
89  *
90  * A local (DW_EDMA_CHIP_LOCAL) instance never issues transfers on a
91  * remote-routed channel: REMOTE routing on such an instance denotes a channel
92  * handed over to and driven by the remote side, and the recipe above is
93  * applied by the driving instance.
94  *
95  * HDMA linked-list watermark interrupts have the same LWIE/RWIE guidance. HDMA
96  * non-linked-list mode has dedicated local and remote stop/abort interrupt
97  * enables.
98  */
99 enum dw_edma_ch_irq_mode {
100 	DW_EDMA_CH_IRQ_LOCAL	= 0,
101 	DW_EDMA_CH_IRQ_REMOTE,
102 };
103 
104 /**
105  * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
106  * @dev:		 struct device of the eDMA controller
107  * @nr_irqs:		 total number of DMA IRQs
108  * @ops:		 DMA channel to IRQ number mapping
109  * @flags:		 dw_edma_chip_flags
110  * @reg_base:		 DMA register base address
111  * @ll_wr_cnt:		 DMA write link list count
112  * @ll_rd_cnt:		 DMA read link list count
113  * @ll_region_wr:	 DMA descriptor link list memory for write channel
114  * @ll_region_rd:	 DMA descriptor link list memory for read channel
115  * @dt_region_wr:	 DMA data memory for write channel
116  * @dt_region_rd:	 DMA data memory for read channel
117  * @db_irq:		 Virtual IRQ dedicated to interrupt emulation
118  * @db_offset:		 Offset from DMA register base
119  * @mf:			 DMA register map format
120  * @func_no:		 PCI endpoint function number used by DMA TLPs
121  * @dw:			 struct dw_edma that is filled by dw_edma_probe()
122  */
123 struct dw_edma_chip {
124 	struct device		*dev;
125 	int			nr_irqs;
126 	const struct dw_edma_plat_ops	*ops;
127 	u32			flags;
128 
129 	void __iomem		*reg_base;
130 
131 	u16			ll_wr_cnt;
132 	u16			ll_rd_cnt;
133 	/* link list address */
134 	struct dw_edma_region	ll_region_wr[HDMA_MAX_WR_CH];
135 	struct dw_edma_region	ll_region_rd[HDMA_MAX_RD_CH];
136 
137 	/* data region */
138 	struct dw_edma_region	dt_region_wr[HDMA_MAX_WR_CH];
139 	struct dw_edma_region	dt_region_rd[HDMA_MAX_RD_CH];
140 
141 	/* interrupt emulation */
142 	int			db_irq;
143 	resource_size_t		db_offset;
144 
145 	enum dw_edma_map_format	mf;
146 	u8			func_no;
147 
148 	struct dw_edma		*dw;
149 	bool			cfg_non_ll;
150 };
151 
152 /* Export to the platform drivers */
153 #if IS_REACHABLE(CONFIG_DW_EDMA)
154 int dw_edma_probe(struct dw_edma_chip *chip);
155 int dw_edma_remove(struct dw_edma_chip *chip);
156 #else
dw_edma_probe(struct dw_edma_chip * chip)157 static inline int dw_edma_probe(struct dw_edma_chip *chip)
158 {
159 	return -ENODEV;
160 }
161 
dw_edma_remove(struct dw_edma_chip * chip)162 static inline int dw_edma_remove(struct dw_edma_chip *chip)
163 {
164 	return 0;
165 }
166 #endif /* CONFIG_DW_EDMA */
167 
168 #endif /* _DW_EDMA_H */
169