summaryrefslogtreecommitdiff
path: root/gxp-dma.h
blob: d3dd81e96a1e4109ae059bc7730d4324d7caca07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * GXP DMA interface.
 *
 * Copyright (C) 2021 Google LLC
 */
#ifndef __GXP_DMA_H__
#define __GXP_DMA_H__

#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/types.h>
#ifdef CONFIG_ANDROID
#include <soc/google/tpu-ext.h>
#endif

#include "gxp-internal.h"

struct gxp_dma_manager {
	struct rb_root mapping_tree;
};

/*
 * Error value to be returned in place of a dma_addr_t when a mapping fails.
 *
 * On newer kernels, this is defined in <linux/dma-mapping.h>. Redefined here
 * for older kernels, so clients can check for this value without worrying
 * which kernel version they're compiled for.
 */
#ifndef DMA_MAPPING_ERROR
#define DMA_MAPPING_ERROR (~(dma_addr_t)0)
#endif

/**
 * gxp_dma_init() - Initialize the GXP DMA subsystem
 * @gxp: The GXP device to initialize DMA for
 *
 * Return:
 * * 0       - DMA initialized successfully
 * * -EIO    - Failed to initialize underlying IOMMU hardware
 * * -ENODEV - The necessary hardware or device tree entries are missing
 * * -ENOMEM - Insufficient memory is available to initialize the interface
 */
int gxp_dma_init(struct gxp_dev *gxp);

/**
 * gxp_dma_exit() - Tear down the GXP DMA subsystem and release hardware
 * @gxp: The GXP device to tear down DMA for
 */
void gxp_dma_exit(struct gxp_dev *gxp);

/**
 * gxp_dma_map_resources() - Map the various buffers/registers with fixed IOVAs
 * @gxp: The GXP device to setup the mappings for
 *
 * GXP firmware expects several buffers and registers to be mapped to fixed
 * locations in their IOVA space. This function initializes all those mappings.
 *
 * This function must not be called until after all the `vaddr` and `size`
 * fields of every `struct gxp_mapped_resource` inside of @gxp have been
 * initialized.
 *
 * Return:
 * * 0    - Mappings created successfully
 * * -EIO - Failed to create one or more of the mappings
 */
int gxp_dma_map_resources(struct gxp_dev *gxp);

/**
 * gxp_dma_unmap_resources() - Unmap the IOVAs mapped by gxp_dma_map_resources
 * @gxp: The GXP device that was passed to gxp_dma_map_resources()
 *
 * GXP firmware expects several buffers and registers to be mapped to fixed
 * locations in their IOVA space. This function releases all those mappings.
 *
 * This function should be called after gxp_dma_map_resources().
 */
void gxp_dma_unmap_resources(struct gxp_dev *gxp);

#ifdef CONFIG_ANDROID
/**
 * gxp_dma_map_tpu_buffer() - Map the tpu mbx queue buffers with fixed IOVAs
 * @gxp: The GXP device to setup the mappings for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @mbx_info: Structure holding TPU-DSP mailbox queue buffer information
 *
 * Return:
 * * 0    - Mappings created successfully
 * * -EIO - Failed to create the mappings
 */
int gxp_dma_map_tpu_buffer(struct gxp_dev *gxp, uint core_list,
			   struct edgetpu_ext_mailbox_info *mbx_info);

/**
 * gxp_dma_unmap_tpu_buffer() - Unmap IOVAs mapped by gxp_dma_map_tpu_buffer()
 * @gxp: The GXP device that was passed to gxp_dma_map_tpu_buffer()
 * @mbx_desc: Structure holding info for already mapped TPU-DSP mailboxes.
 */
void gxp_dma_unmap_tpu_buffer(struct gxp_dev *gxp,
			      struct gxp_tpu_mbx_desc mbx_desc);
#endif  // CONFIG_ANDROID

/**
 * gxp_dma_alloc_coherent() - Allocate and map a coherent buffer for a GXP core
 * @gxp: The GXP device to map the allocated buffer for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @size: The size of the buffer to be allocated, in bytes
 * @dma_handle: Reference to a variable to be set to the allocated IOVA
 * @flag: The type of memory to allocate (see kmalloc)
 * @gxp_dma_flags: The type of mapping to create; Currently unused
 *
 * Return: Kernel virtual address of the allocated/mapped buffer
 */
void *gxp_dma_alloc_coherent(struct gxp_dev *gxp, uint core_list, size_t size,
			     dma_addr_t *dma_handle, gfp_t flag,
			     uint gxp_dma_flags);
/**
 * gxp_dma_free_coherent() - Unmap and free a coherent buffer
 * @gxp: The GXP device the buffer was allocated and mapped for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @size: The size of the buffer, in bytes, passed to `gxp_dma_alloc()`
 * @cpu_addr: The kernel virtual address returned by `gxp_dma_alloc()`
 * @dma_handle: The device IOVA, set by `gxp_dma_alloc()`
 *
 * If the buffer has been mirror-mapped via `gxp_dma_mirror_map()`, the buffer
 * will not be freed until all mappings have been unmapped.
 */
void gxp_dma_free_coherent(struct gxp_dev *gxp, uint core_list, size_t size,
			   void *cpu_addr, dma_addr_t dma_handle);

/**
 * gxp_dma_map_single() - Create a mapping for a kernel buffer
 * @gxp: The GXP device to map the buffer for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @cpu_addr: The kernel virtual address of the buffer to map
 * @size: The size of the buffer to map, in bytes
 * @direction: DMA direction
 * @attrs: The same set of flags used by the base DMA API
 * @gxp_dma_flags: The type of mapping to create; Currently unused
 *
 * Return: The IOVA the buffer was mapped to
 */
dma_addr_t gxp_dma_map_single(struct gxp_dev *gxp, uint core_list,
			      void *cpu_addr, size_t size,
			      enum dma_data_direction direction,
			      unsigned long attrs, uint gxp_dma_flags);
/**
 * gxp_dma_unmap_single() - Unmap a kernel buffer
 * @gxp: The GXP device the buffer was mapped for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @dma_addr: The device IOVA, returned by `gxp_dma_map_single()`
 * @size: The size of the mapping, which was passed to `gxp_dma_map_single()`
 * @direction: DMA direction; same as passed to `gxp_dma_map_single()`
 * @attrs: The same set of flags used by the base DMA API
 */
void gxp_dma_unmap_single(struct gxp_dev *gxp, uint core_list,
			  dma_addr_t dma_addr, size_t size,
			  enum dma_data_direction direction,
			  unsigned long attrs);

/**
 * gxp_dma_map_page() - Create a mapping for a physical page of memory
 * @gxp: The GXP device to map the page for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @page: The `struct page` of the physical page to create a mapping for
 * @offset: The offset into @page to begin the mapping at
 * @size: The number of bytes in @page to map
 * @direction: DMA direction
 * @attrs: The same set of flags used by the base DMA API
 * @gxp_dma_flags: The type of mapping to create; Currently unused
 *
 * Return: The IOVA the page was mapped to
 */
dma_addr_t gxp_dma_map_page(struct gxp_dev *gxp, uint core_list,
			    struct page *page, unsigned long offset,
			    size_t size, enum dma_data_direction direction,
			    unsigned long attrs, uint gxp_dma_flags);
/**
 * gxp_dma_unmap_page() - Unmap a physical page of memory
 * @gxp: The GXP device the page was mapped for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @dma_addr: The device IOVA, returned by `gxp_dma_map_page()`
 * @size: The size of the mapping, which was passed to `gxp_dma_map_page()`
 * @direction: DMA direction; Same as passed to `gxp_dma_map_page()`
 * @attrs: The same set of flags used by the base DMA API
 */
void gxp_dma_unmap_page(struct gxp_dev *gxp, uint core_list,
			dma_addr_t dma_addr, size_t size,
			enum dma_data_direction direction, unsigned long attrs);

/**
 * gxp_dma_map_resource() - Create a mapping for an MMIO resource
 * @gxp: The GXP device to map the resource for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @phys_addr: The physical address of the MMIO resource to map
 * @size: The size of the MMIO region to map, in bytes
 * @direction: DMA direction
 * @attrs: The same set of flags used by the base DMA API
 * @gxp_dma_flags: The type of mapping to create; Currently unused
 *
 * Return: The IOVA the MMIO resource was mapped to
 */
dma_addr_t gxp_dma_map_resource(struct gxp_dev *gxp, uint core_list,
				phys_addr_t phys_addr, size_t size,
				enum dma_data_direction direction,
				unsigned long attrs, uint gxp_dma_flags);
/**
 * gxp_dma_unmap_resource() - Unmap an MMIO resource
 * @gxp: The GXP device the MMIO resource was mapped for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @dma_addr: The device IOVA, returned by `gxp_dma_map_resource()`
 * @size: The size of the mapping, which was passed to `gxp_dma_map_resource()`
 * @direction: DMA direction; Same as passed to `gxp_dma_map_resource()`
 * @attrs: The same set of flags used by the base DMA API
 */
void gxp_dma_unmap_resource(struct gxp_dev *gxp, uint core_list,
			    dma_addr_t dma_addr, size_t size,
			    enum dma_data_direction direction,
			    unsigned long attrs);

/**
 * gxp_dma_map_sg() - Create a mapping for a scatter-gather list
 * @gxp: The GXP device to map the scatter-gather list for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @sg: The scatter-gather list of the buffer to be mapped
 * @nents: The number of entries in @sg
 * @direction: DMA direction
 * @attrs: The same set of flags used by the base DMA API
 * @gxp_dma_flags: The type of mapping to create; Currently unused
 *
 * Return: The number of scatter-gather entries mapped to
 */
int gxp_dma_map_sg(struct gxp_dev *gxp, uint core_list, struct scatterlist *sg,
		   int nents, enum dma_data_direction direction,
		   unsigned long attrs, uint gxp_dma_flags);
/**
 * gxp_dma_unmap_sg() - Unmap a scatter-gather list
 * @gxp: The GXP device the scatter-gather list was mapped for
 * @core_list: A bitfield enumerating the physical cores the mapping is for
 * @sg: The scatter-gather list to unmap; The same one passed to
 *      `gxp_dma_map_sg()`
 * @nents: The number of entries in @sg; Same value passed to `gxp_dma_map_sg()`
 * @direction: DMA direction; Same as passed to `gxp_dma_map_sg()`
 * @attrs: The same set of flags used by the base DMA API
 */
void gxp_dma_unmap_sg(struct gxp_dev *gxp, uint core_list,
		      struct scatterlist *sg, int nents,
		      enum dma_data_direction direction, unsigned long attrs);

/**
 * gxp_dma_sync_single_for_cpu() - Sync buffer for reading by the CPU
 * @gxp: The GXP device the mapping was created for
 * @dma_handle: The device IOVA, obtained from one of the `gxp_dma_map_*` APIs
 * @size: The size of the mapped region to sync
 * @direction: DMA direction
 */
void gxp_dma_sync_single_for_cpu(struct gxp_dev *gxp, dma_addr_t dma_handle,
				 size_t size,
				 enum dma_data_direction direction);
/**
 * gxp_dma_sync_single_for_device() - Sync buffer for reading by the device
 * @gxp: The GXP device the mapping was created for
 * @dma_handle: The device IOVA, obtained from one of the `gxp_dma_map_*` APIs
 * @size: The size of the mapped region to sync
 * @direction: DMA direction
 */
void gxp_dma_sync_single_for_device(struct gxp_dev *gxp, dma_addr_t dma_handle,
				    size_t size,
				    enum dma_data_direction direction);

/**
 * gxp_dma_sync_sg_for_cpu() - Sync sg list for reading by the  CPU
 * @gxp: The GXP device the mapping was created for
 * @sg: The mapped scatter-gather list to be synced
 * @nents: The number of entries in @sg
 * @direction: DMA direction
 */
void gxp_dma_sync_sg_for_cpu(struct gxp_dev *gxp, struct scatterlist *sg,
			     int nents, enum dma_data_direction direction);
/**
 * gxp_dma_sync_sg_for_device() - Sync sg list for reading by the device
 * @gxp: The GXP device the mapping was created for
 * @sg: The mapped scatter-gather list to be synced
 * @nents: The number of entries in @sg
 * @direction: DMA direction
 */
void gxp_dma_sync_sg_for_device(struct gxp_dev *gxp, struct scatterlist *sg,
				int nents, enum dma_data_direction direction);

#endif /* __GXP_DMA_H__ */