Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
qm_dma.h
1 /*
2  * {% copyright %}
3  */
4 
5 #ifndef __QM_DMA_H_
6 #define __QM_DMA_H_
7 
8 #include "qm_common.h"
9 #include "qm_soc_regs.h"
10 
11 /**
12  * DMA Driver for Quark Microcontrollers.
13  *
14  * @defgroup groupDMA DMA
15  * @{
16  */
17 
18 /**
19  * DMA Handshake Polarity
20  */
21 typedef enum {
22  QM_DMA_HANDSHAKE_POLARITY_HIGH = 0x0, /**< Set HS polarity high. */
23  QM_DMA_HANDSHAKE_POLARITY_LOW = 0x1 /**< Set HS polarity low. */
25 
26 /**
27  * DMA Burst Transfer Length
28  */
29 typedef enum {
30  QM_DMA_BURST_TRANS_LENGTH_1 = 0x0, /**< Burst length 1 data item. */
31  QM_DMA_BURST_TRANS_LENGTH_4 = 0x1, /**< Burst length 4 data items. */
32  QM_DMA_BURST_TRANS_LENGTH_8 = 0x2, /**< Burst length 8 data items. */
33  QM_DMA_BURST_TRANS_LENGTH_16 = 0x3, /**< Burst length 16 data items. */
34  QM_DMA_BURST_TRANS_LENGTH_32 = 0x4, /**< Burst length 32 data items. */
35  QM_DMA_BURST_TRANS_LENGTH_64 = 0x5, /**< Burst length 64 data items. */
37  0x6, /**< Burst length 128 data items. */
38  QM_DMA_BURST_TRANS_LENGTH_256 = 0x7 /**< Burst length 256 data items. */
40 
41 /**
42  * DMA Transfer Width
43  */
44 typedef enum {
45  QM_DMA_TRANS_WIDTH_8 = 0x0, /**< Transfer width of 8 bits. */
46  QM_DMA_TRANS_WIDTH_16 = 0x1, /**< Transfer width of 16 bits. */
47  QM_DMA_TRANS_WIDTH_32 = 0x2, /**< Transfer width of 32 bits. */
48  QM_DMA_TRANS_WIDTH_64 = 0x3, /**< Transfer width of 64 bits. */
49  QM_DMA_TRANS_WIDTH_128 = 0x4, /**< Transfer width of 128 bits. */
50  QM_DMA_TRANS_WIDTH_256 = 0x5 /**< Transfer width of 256 bits. */
52 
53 /**
54  * DMA channel direction.
55  */
56 typedef enum {
57  QM_DMA_MEMORY_TO_MEMORY = 0x0, /**< Memory to memory transfer. */
59  0x1, /**< Memory to peripheral transfer. */
60  QM_DMA_PERIPHERAL_TO_MEMORY = 0x2 /**< Peripheral to memory transfer. */
62 
63 /*
64  * DMA Transfer Type
65  */
66 typedef enum {
67  QM_DMA_TYPE_SINGLE, /**< Single block mode. */
68  QM_DMA_TYPE_MULTI_CONT, /**< Contiguous multiblock mode. */
69  QM_DMA_TYPE_MULTI_LL, /**< Link list multiblock mode. */
70  QM_DMA_TYPE_MULTI_LL_CIRCULAR /**< Link list multiblock mode with cyclic
71  operation. */
73 
74 /**
75  * DMA channel configuration structure
76  */
77 typedef struct {
78  /** DMA channel handshake interface ID */
80 
81  /** DMA channel handshake polarity */
83 
84  /** DMA channel direction */
86 
87  /** DMA source transfer width */
89 
90  /** DMA destination transfer width */
92 
93  /** DMA source burst length */
95 
96  /** DMA destination burst length */
98 
99  /** DMA transfer type */
101 
102  /**
103  * Client callback for DMA transfer ISR
104  *
105  * @param[in] callback_context DMA client context.
106  * @param[in] len Data length transferred.
107  * @param[in] error Error code.
108  */
109  void (*client_callback)(void *callback_context, uint32_t len,
110  int error_code);
111 
112  /** DMA client context passed to the callbacks */
115 
116 /*
117  * Multiblock linked list node structure. The client does not need to know the
118  * internals of this struct but only its size, so that the correct memory for
119  * the linked list can be allocated (one node per DMA transfer block).
120  */
121 typedef struct {
122  uint32_t source_address; /**< Block source address. */
123  uint32_t destination_address; /**< Block destination address. */
124  uint32_t linked_list_address; /**< Pointer to next LLI. */
125  uint32_t ctrl_low; /**< Bottom half Ctrl register. */
126  uint32_t ctrl_high; /**< Top half Ctrl register. */
127  /**< Destination/source status writebacks are disabled. */
128 } qm_dma_linked_list_item_t;
129 
130 /**
131  * DMA single block transfer configuration structure
132  */
133 typedef struct {
134  uint32_t block_size; /**< DMA block size, Min = 1, Max = 4095. */
135  uint32_t *source_address; /**< DMA source transfer address. */
136  uint32_t *destination_address; /**< DMA destination transfer address. */
137 
139 
140 /**
141  * DMA multiblock transfer configuration structure
142  */
143 typedef struct {
144  uint32_t *source_address; /**< First block source address. */
145  uint32_t *destination_address; /**< First block destination address. */
146  uint16_t block_size; /**< DMA block size, Min = 1, Max = 4095. */
147  uint16_t
148  num_blocks; /**< Number of contiguous blocks to be transfered. */
149  qm_dma_linked_list_item_t *linked_list_first; /**< First block LLI
150  descriptor or NULL
151  (contiguous mode) */
153 
154 /**
155  * Initialise the DMA controller.
156  *
157  * The DMA controller and channels are first disabled.
158  * All DMA controller interrupts are masked
159  * using the controllers interrupt masking registers. The system
160  * DMA interrupts are then unmasked. Finally the DMA controller
161  * is enabled. This function must only be called once as it
162  * resets the DMA controller and interrupt masking.
163  *
164  * @param[in] dma DMA instance.
165  *
166  * @return Standard errno return type for QMSI.
167  * @retval 0 on success.
168  * @retval Negative @ref errno for possible error codes.
169  */
170 int qm_dma_init(const qm_dma_t dma);
171 
172 /**
173  * Setup a DMA channel configuration.
174  *
175  * Configures the channel source width, burst size, channel direction,
176  * handshaking interface, transfer type and registers the client callback and
177  * callback context. qm_dma_init() must first be called before configuring a
178  * channel. This function only needs to be called once unless a channel is being
179  * repurposed or its transfer type is changed.
180  *
181  * @param[in] dma DMA instance.
182  * @param[in] channel_id The channel to start.
183  * @param[in] channel_config The DMA channel configuration as
184  * defined by the DMA client. This must not be NULL.
185  *
186  * @return Standard errno return type for QMSI.
187  * @retval 0 on success.
188  * @retval Negative @ref errno for possible error codes.
189  */
190 int qm_dma_channel_set_config(const qm_dma_t dma,
191  const qm_dma_channel_id_t channel_id,
192  qm_dma_channel_config_t *const channel_config);
193 
194 /**
195  * Setup a DMA single block transfer.
196  *
197  * Configure the source address,destination addresses and block size.
198  * qm_dma_channel_set_config() must first be called before
199  * configuring a transfer. qm_dma_transfer_set_config() must
200  * be called before starting every transfer, even if the
201  * addresses and block size remain unchanged.
202  *
203  * @param[in] dma DMA instance.
204  * @param[in] channel_id The channel to start.
205  * @param[in] transfer_config The transfer DMA configuration
206  * as defined by the dma client.
207  * This must not be NULL.
208  *
209  * @return Standard errno return type for QMSI.
210  * @retval 0 on success.
211  * @retval Negative @ref errno for possible error codes.
212  */
214  const qm_dma_channel_id_t channel_id,
215  qm_dma_transfer_t *const transfer_config);
216 
217 /**
218  * Setup a DMA multiblock transfer.
219  *
220  * If the DMA channel has been configured for contiguous multiblock transfers,
221  * this function sets the source address, destination address, block size and
222  * number of block parameters needed to perform a continguous multiblock
223  * transfer. The linked_list_first parameter in the transfer struct is ignored.
224  *
225  * If the DMA channel has been configured for linked-list multiblock transfers,
226  * this function populates a linked list in the client memory area pointed at
227  * by the linked_list_first parameter in the transfer struct, using the provided
228  * parameters source address, destination address, block size and number of
229  * blocks (equal to the number of LLIs). This function may be called repeteadly
230  * in order to add different client buffers for transmission/reception that are
231  * not contiguous in memory (scatter-gather) in a buffer chain fashion. When
232  * calling qm_dma_transfer_start, the DMA core sees a single linked list built
233  * using consecutive calls to this function. Furthermore, if the transfer type
234  * is linked-list cyclic, the linked_list_address parameter of the last LLI
235  * points at the first LLI. The client needs to allocate enough memory starting
236  * at linked_list_first for the whole set of LLIs to fit, i.e. (num_blocks *
237  * sizeof(qm_dma_linked_list_item_t)).
238  *
239  * The DMA driver manages the block interrupts so that only when the last block
240  * of a buffer has been transfered, the client callback is invoked. Note that
241  * in linked-list mode, each buffer transfer results on a client callback, and
242  * all buffers need to contain the same number of blocks.
243  *
244  * qm_dma_multi_transfer_set_config() must be called before starting every
245  * transfer, even if the addresses, block size and other configuration
246  * information remain unchanged.
247  *
248  * @param[in] dma DMA instance.
249  * @param[in] channel_id The channel to start.
250  * @param[in] multi_transfer_config The transfer DMA configuration as defined by
251  * the dma client. This must not be NULL.
252  *
253  * @return Standard errno return type for QMSI.
254  * @retval 0 on success.
255  * @retval Negative @ref errno for possible error codes.
256  */
258  const qm_dma_t dma, const qm_dma_channel_id_t channel_id,
259  qm_dma_multi_transfer_t *const multi_transfer_config);
260 
261 /**
262  * Start a DMA transfer.
263  *
264  * qm_dma_transfer_set_config() mustfirst be called
265  * before starting a transfer.
266  *
267  * @param[in] dma DMA instance.
268  * @param[in] channel_id The channel to start.
269  *
270  * @return Standard errno return type for QMSI.
271  * @retval 0 on success.
272  * @retval Negative @ref errno for possible error codes.
273 */
274 int qm_dma_transfer_start(const qm_dma_t dma,
275  const qm_dma_channel_id_t channel_id);
276 
277 /**
278  * Terminate a DMA transfer.
279  *
280  * This function is only called if a transfer needs to be terminated manually.
281  * This may be require if an expected transfer complete callback
282  * has not been received. Terminating the transfer will
283  * trigger the transfer complete callback. The length
284  * returned by the callback is the transfer length at the
285  * time that the transfer was terminated.
286  *
287  * @param[in] dma DMA instance.
288  * @param[in] channel_id The channel to stop.
289  *
290  * @return Standard errno return type for QMSI.
291  * @retval 0 on success.
292  * @retval Negative @ref errno for possible error codes.
293 */
294 int qm_dma_transfer_terminate(const qm_dma_t dma,
295  const qm_dma_channel_id_t channel_id);
296 
297 /**
298  * Setup and start memory to memory transfer.
299  *
300  * This function will setup a memory to memory transfer by
301  * calling qm_dma_transfer_setup() and will then start the
302  * transfer by calling qm_dma_transfer_start(). This is
303  * done for consistency across user applications.
304  *
305  * @param[in] dma DMA instance.
306  * @param[in] channel_id The channel to start.
307  * @param[in] transfer_config The transfer DMA configuration
308  * as defined by the dma client.
309  * This must not be NULL.
310  *
311  * @return Standard errno return type for QMSI.
312  * @retval 0 on success.
313  * @retval Negative @ref errno for possible error codes.
314 */
316  const qm_dma_channel_id_t channel_id,
317  qm_dma_transfer_t *const transfer_config);
318 
319 /**
320  * Save DMA peripheral's context.
321  *
322  * Saves the configuration of the specified DMA peripheral
323  * before entering sleep.
324  *
325  * @param[in] dma DMA device.
326  * @param[out] ctx DMA context structure. This must not be NULL.
327  *
328  * @return Standard errno return type for QMSI.
329  * @retval 0 on success.
330  * @retval Negative @ref errno for possible error codes.
331  */
332 int qm_dma_save_context(const qm_dma_t dma, qm_dma_context_t *const ctx);
333 
334 /**
335  * Restore DMA peripheral's context.
336  *
337  * Restore the configuration of the specified DMA peripheral
338  * after exiting sleep.
339  *
340  * @param[in] dma DMA device.
341  * @param[in] ctx DMA context structure. This must not be NULL.
342  *
343  * @return Standard errno return type for QMSI.
344  * @retval 0 on success.
345  * @retval Negative @ref errno for possible error codes.
346  */
347 int qm_dma_restore_context(const qm_dma_t dma,
348  const qm_dma_context_t *const ctx);
349 
350 /**
351  * @}
352  */
353 
354 #endif /* __QM_DMA_H_ */
uint16_t num_blocks
Number of contiguous blocks to be transfered.
Definition: qm_dma.h:148
Burst length 256 data items.
Definition: qm_dma.h:38
DMA channel configuration structure.
Definition: qm_dma.h:77
qm_dma_transfer_type_t transfer_type
DMA transfer type.
Definition: qm_dma.h:100
uint32_t * destination_address
First block destination address.
Definition: qm_dma.h:145
Link list multiblock mode.
Definition: qm_dma.h:69
Burst length 8 data items.
Definition: qm_dma.h:32
uint32_t * destination_address
DMA destination transfer address.
Definition: qm_dma.h:136
qm_dma_t
DMA instances.
Definition: qm_soc_regs.h:1480
Burst length 64 data items.
Definition: qm_dma.h:35
Transfer width of 64 bits.
Definition: qm_dma.h:48
Burst length 16 data items.
Definition: qm_dma.h:33
DMA single block transfer configuration structure.
Definition: qm_dma.h:133
qm_dma_burst_length_t source_burst_length
DMA source burst length.
Definition: qm_dma.h:94
DMA context type.
Definition: qm_soc_regs.h:1911
qm_dma_linked_list_item_t * linked_list_first
First block LLI descriptor or NULL (contiguous mode)
Definition: qm_dma.h:149
uint32_t block_size
DMA block size, Min = 1, Max = 4095.
Definition: qm_dma.h:134
void * callback_context
DMA client context passed to the callbacks.
Definition: qm_dma.h:113
Link list multiblock mode with cyclic operation.
Definition: qm_dma.h:70
Transfer width of 8 bits.
Definition: qm_dma.h:45
qm_dma_transfer_type_t
Definition: qm_dma.h:66
qm_dma_handshake_polarity_t
DMA Handshake Polarity.
Definition: qm_dma.h:21
int qm_dma_restore_context(const qm_dma_t dma, const qm_dma_context_t *const ctx)
Restore DMA peripheral's context.
Definition: qm_dma.c:705
qm_dma_handshake_interface_t handshake_interface
DMA channel handshake interface ID.
Definition: qm_dma.h:79
int qm_dma_transfer_set_config(const qm_dma_t dma, const qm_dma_channel_id_t channel_id, qm_dma_transfer_t *const transfer_config)
Setup a DMA single block transfer.
Definition: qm_dma.c:345
Memory to memory transfer.
Definition: qm_dma.h:57
qm_dma_burst_length_t
DMA Burst Transfer Length.
Definition: qm_dma.h:29
qm_dma_handshake_polarity_t handshake_polarity
DMA channel handshake polarity.
Definition: qm_dma.h:82
Set HS polarity low.
Definition: qm_dma.h:23
int qm_dma_multi_transfer_set_config(const qm_dma_t dma, const qm_dma_channel_id_t channel_id, qm_dma_multi_transfer_t *const multi_transfer_config)
Setup a DMA multiblock transfer.
Definition: qm_dma.c:437
uint16_t block_size
DMA block size, Min = 1, Max = 4095.
Definition: qm_dma.h:146
Single block mode.
Definition: qm_dma.h:67
Burst length 128 data items.
Definition: qm_dma.h:36
Peripheral to memory transfer.
Definition: qm_dma.h:60
qm_dma_burst_length_t destination_burst_length
DMA destination burst length.
Definition: qm_dma.h:97
qm_dma_transfer_width_t destination_transfer_width
DMA destination transfer width.
Definition: qm_dma.h:91
int qm_dma_channel_set_config(const qm_dma_t dma, const qm_dma_channel_id_t channel_id, qm_dma_channel_config_t *const channel_config)
Setup a DMA channel configuration.
Definition: qm_dma.c:254
Burst length 4 data items.
Definition: qm_dma.h:31
Burst length 32 data items.
Definition: qm_dma.h:34
qm_dma_transfer_width_t source_transfer_width
DMA source transfer width.
Definition: qm_dma.h:88
int qm_dma_transfer_terminate(const qm_dma_t dma, const qm_dma_channel_id_t channel_id)
Terminate a DMA transfer.
Definition: qm_dma.c:618
qm_dma_channel_direction_t
DMA channel direction.
Definition: qm_dma.h:56
int qm_dma_transfer_start(const qm_dma_t dma, const qm_dma_channel_id_t channel_id)
Start a DMA transfer.
Definition: qm_dma.c:582
Set HS polarity high.
Definition: qm_dma.h:22
int qm_dma_init(const qm_dma_t dma)
Initialise the DMA controller.
Definition: qm_dma.c:208
Burst length 1 data item.
Definition: qm_dma.h:30
DMA multiblock transfer configuration structure.
Definition: qm_dma.h:143
Memory to peripheral transfer.
Definition: qm_dma.h:58
Transfer width of 16 bits.
Definition: qm_dma.h:46
uint32_t * source_address
DMA source transfer address.
Definition: qm_dma.h:135
qm_dma_transfer_width_t
DMA Transfer Width.
Definition: qm_dma.h:44
Transfer width of 32 bits.
Definition: qm_dma.h:47
Transfer width of 256 bits.
Definition: qm_dma.h:50
Contiguous multiblock mode.
Definition: qm_dma.h:68
int qm_dma_transfer_mem_to_mem(const qm_dma_t dma, const qm_dma_channel_id_t channel_id, qm_dma_transfer_t *const transfer_config)
Setup and start memory to memory transfer.
Definition: qm_dma.c:656
qm_dma_channel_id_t
DMA channel IDs.
Definition: qm_soc_regs.h:1486
uint32_t * source_address
First block source address.
Definition: qm_dma.h:144
qm_dma_handshake_interface_t
DMA hardware handshake interfaces.
Definition: qm_soc_regs.h:1493
Transfer width of 128 bits.
Definition: qm_dma.h:49
qm_dma_channel_direction_t channel_direction
DMA channel direction.
Definition: qm_dma.h:85
int qm_dma_save_context(const qm_dma_t dma, qm_dma_context_t *const ctx)
Save DMA peripheral's context.
Definition: qm_dma.c:681