source: rtems/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c @ 76386c1

4.115
Last change on this file since 76386c1 was 76386c1, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 26, 2014 at 2:00:44 PM

bsp/altera-cyclone-v: Add DMA support hwlib files

  • Property mode set to 100644
File size: 131.5 KB
Line 
1/******************************************************************************
2 *
3 * Copyright 2013 Altera Corporation. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * OF SUCH DAMAGE.
28 *
29 ******************************************************************************/
30
31#include <stdio.h>
32#include "alt_dma.h"
33#include "socal/socal.h"
34#include "socal/hps.h"
35#include "socal/alt_rstmgr.h"
36#include "socal/alt_sysmgr.h"
37
38#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
39#include "alt_16550_uart.h"
40#include "socal/alt_uart.h"
41#endif
42
43#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
44#include "socal/alt_qspi.h"
45#endif
46
47/////
48
49#ifndef MIN
50#define MIN(a, b) ((a) > (b) ? (b) : (a))
51#endif // MIN
52
53#ifndef ARRAY_COUNT
54#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
55#endif
56
57// NOTE: To enable debugging output, delete the next line and uncomment the
58//   line after.
59#define dprintf(...)
60// #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
61
62/////
63
64//
65// SoCAL stand in for DMA Controller registers
66//
67// The base can be one of the following:
68//  - ALT_DMANONSECURE_ADDR
69//  - ALT_DMASECURE_ADDR
70//
71// Macros which have a channel parameter does no validation.
72//
73
74// DMA Manager Status Register
75#define ALT_DMA_DSR_OFST 0x0
76#define ALT_DMA_DSR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DSR_OFST))
77#define ALT_DMA_DSR_DMASTATUS_SET_MSK 0x0000000f
78#define ALT_DMA_DSR_DMASTATUS_GET(value) ((value) & 0x0000000f)
79
80// DMA Program Counter Register
81#define ALT_DMA_DPC_OFST 0x4
82#define ALT_DMA_DPC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DPC_OFST))
83
84// Interrupt Enable Register
85#define ALT_DMA_INTEN_OFST 0x20
86#define ALT_DMA_INTEN_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTEN_OFST))
87
88// Event-Interrupt Raw Status Register
89#define ALT_DMA_INT_EVENT_RIS_OFST 0x24
90#define ALT_DMA_INT_EVENT_RIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INT_EVENT_RIS_OFST))
91
92// Interrupt Status Register
93#define ALT_DMA_INTMIS_OFST 0x28
94#define ALT_DMA_INTMIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTMIS_OFST))
95
96// Interrupt Clear Register
97#define ALT_DMA_INTCLR_OFST 0x2c
98#define ALT_DMA_INTCLR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTCLR_OFST))
99
100// Fault Status DMA Manager Register
101#define ALT_DMA_FSRD_OFST 0x30
102#define ALT_DMA_FSRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST))
103
104// Fault Status DMA Channel Register
105#define ALT_DMA_FSRC_OFST 0x34
106#define ALT_DMA_FSRC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRC_OFST))
107
108// Fault Type DMA Manager Register
109#define ALT_DMA_FTRD_OFST 0x38
110#define ALT_DMA_FTRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST))
111
112// Fault Type DMA Channel Registers
113#define ALT_DMA_FTRx_OFST(channel) (0x40 + 0x4 * (channel))
114#define ALT_DMA_FTRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FTRx_OFST(channel)))
115
116// Channel Status Registers
117#define ALT_DMA_CSRx_OFST(channel) (0x100 + 0x8 * (channel))
118#define ALT_DMA_CSRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CSRx_OFST(channel)))
119#define ALT_DMA_CSRx_CHANNELSTATUS_SET_MSK 0x0000000f
120#define ALT_DMA_CSRx_CHANNELSTATUS_GET(value) ((value) & 0x0000000f)
121
122// Channel Program Counter Registers
123#define ALT_DMA_CPCx_OFST(channel) (0x104 + 0x8 * (channel))
124#define ALT_DMA_CPCx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CPCx_OFST(channel)))
125
126// Source Address Registers
127#define ALT_DMA_SARx_OFST(channel) (0x400 + 0x20 * (channel))
128#define ALT_DMA_SARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_SARx_OFST(channel)))
129
130// Destination Address Registers
131#define ALT_DMA_DARx_OFST(channel) (0x404 + 0x20 * (channel))
132#define ALT_DMA_DARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DARx_OFST(channel)))
133
134// Channel Control Registers
135#define ALT_DMA_CCRx_OFST(channel) (0x408 + 0x20 * (channel))
136#define ALT_DMA_CCRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CCRx_OFST(channel)))
137
138// Loop Counter 0 Registers
139#define ALT_DMA_LC0_x_OFST(channel) (0x40c + 0x20 * (channel))
140#define ALT_DMA_LC0_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC0_x_OFST(channel)))
141
142// Loop Counter 1 Registers
143#define ALT_DMA_LC1_x_OFST(channel) (0x410 + 0x20 * (channel))
144#define ALT_DMA_LC1_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC1_x_OFST(channel)))
145
146// Debug Status Register
147#define ALT_DMA_DBGSTATUS_OFST 0xd00
148#define ALT_DMA_DBGSTATUS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGSTATUS_OFST))
149
150// Debug Command Register
151#define ALT_DMA_DBGCMD_OFST 0xd04
152#define ALT_DMA_DBGCMD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGCMD_OFST))
153
154// Debug Instruction-0 Register
155#define ALT_DMA_DBGINST0_OFST 0xd08
156#define ALT_DMA_DBGINST0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST0_OFST))
157#define ALT_DMA_DBGINST0_CHANNELNUMBER_SET(value) (((value) & 0x7) << 8)
158#define ALT_DMA_DBGINST0_DEBUGTHREAD_SET(value) ((value) & 0x1)
159#define ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER 0
160#define ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL 1
161#define ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(value) (((value) & 0xff) << 16)
162#define ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(value) (((value) & 0xff) << 24)
163
164// Debug Instruction-1 Register
165#define ALT_DMA_DBGINST1_OFST 0xd0c
166#define ALT_DMA_DBGINST1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST1_OFST))
167
168// Configuration Registers 0 - 4
169#define ALT_DMA_CR0_OFST 0xe00
170#define ALT_DMA_CR1_OFST 0xe04
171#define ALT_DMA_CR2_OFST 0xe08
172#define ALT_DMA_CR3_OFST 0xe0c
173#define ALT_DMA_CR4_OFST 0xe10
174#define ALT_DMA_CR0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR0_OFST))
175#define ALT_DMA_CR1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR1_OFST))
176#define ALT_DMA_CR2_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR2_OFST))
177#define ALT_DMA_CR3_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR3_OFST))
178#define ALT_DMA_CR4_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR4_OFST))
179
180// DMA Configuration Register
181#define ALT_DMA_CRD_OFST 0xe14
182#define ALT_DMA_CRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CRD_OFST))
183
184// Watchdog Register
185#define ALT_DMA_WD_OFST 0xe80
186#define ALT_DMA_WD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_WD_OFST))
187
188/////
189
190//
191// Internal Data structures
192//
193
194// This flag marks the channel as being allocated.
195#define ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED (1 << 0)
196
197typedef struct ALT_DMA_CHANNEL_INFO_s
198{
199    uint8_t flag;
200}
201ALT_DMA_CHANNEL_INFO_t;
202
203static ALT_DMA_CHANNEL_INFO_t channel_info_array[8];
204
205/////
206
207ALT_STATUS_CODE alt_dma_init(const ALT_DMA_CFG_t * dma_cfg)
208{
209    // Initialize the channel information array
210    for (int i = 0; i < 8; ++i)
211    {
212        channel_info_array[i].flag = 0;
213    }
214
215    // Update the System Manager DMA configuration items
216   
217    uint32_t dmactrl = 0;
218
219    // Handle FPGA / CAN muxing
220    for (int i = 0; i < 4; ++i)
221    {
222        // The default is FPGA.
223        switch (dma_cfg->periph_mux[i])
224        {
225        case ALT_DMA_PERIPH_MUX_DEFAULT:
226        case ALT_DMA_PERIPH_MUX_FPGA:
227            break;
228        case ALT_DMA_PERIPH_MUX_CAN:
229            dmactrl |= (ALT_SYSMGR_DMA_CTL_CHANSEL_0_SET_MSK << i);
230            break;
231        default:
232            return ALT_E_ERROR;
233        }
234    }
235
236    // Handle Manager security
237    // Default is Secure state.
238    switch (dma_cfg->manager_sec)
239    {
240    case ALT_DMA_SECURITY_DEFAULT:
241    case ALT_DMA_SECURITY_SECURE:
242        break;
243    case ALT_DMA_SECURITY_NONSECURE:
244        dmactrl |= ALT_SYSMGR_DMA_CTL_MGRNONSECURE_SET_MSK;
245        break;
246    default:
247        return ALT_E_ERROR;
248    }
249
250    // Handle IRQ security
251    for (int i = 0; i < ALT_SYSMGR_DMA_CTL_IRQNONSECURE_WIDTH; ++i)
252    {
253        // Default is Secure state.
254        switch (dma_cfg->irq_sec[i])
255        {
256        case ALT_DMA_SECURITY_DEFAULT:
257        case ALT_DMA_SECURITY_SECURE:
258            break;
259        case ALT_DMA_SECURITY_NONSECURE:
260            dmactrl |= (1 << (i + ALT_SYSMGR_DMA_CTL_IRQNONSECURE_LSB));
261            break;
262        default:
263            return ALT_E_ERROR;
264        }
265    }
266
267    alt_write_word(ALT_SYSMGR_DMA_CTL_ADDR, dmactrl);
268
269    // Update the System Manager DMA peripheral security items
270
271    uint32_t dmapersecurity = 0;
272
273    for (int i = 0; i < 32; ++i)
274    {
275        // Default is Secure state.
276        switch (dma_cfg->periph_sec[i])
277        {
278        case ALT_DMA_SECURITY_DEFAULT:
279        case ALT_DMA_SECURITY_SECURE:
280            break;
281        case ALT_DMA_SECURITY_NONSECURE:
282            dmapersecurity |= (1 << i);
283            break;
284        default:
285            return ALT_E_ERROR;
286        }
287    }
288
289    alt_write_word(ALT_SYSMGR_DMA_PERSECURITY_ADDR, dmapersecurity);
290
291    // Take DMA out of reset.
292
293    alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK);
294
295    return ALT_E_SUCCESS;
296}
297
298ALT_STATUS_CODE alt_dma_uninit(void)
299{
300    // DMAKILL all channel and free all allocated channels.
301    for (int i = 0; i < 8; ++i)
302    {
303        if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
304        {
305            alt_dma_channel_kill((ALT_DMA_CHANNEL_t)i);
306            alt_dma_channel_free((ALT_DMA_CHANNEL_t)i);
307        }
308    }
309
310    // Put DMA into reset.
311
312    alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK);
313
314    return ALT_E_SUCCESS;
315}
316
317ALT_STATUS_CODE alt_dma_channel_alloc(ALT_DMA_CHANNEL_t channel)
318{
319    // Validate channel
320    switch (channel)
321    {
322    case ALT_DMA_CHANNEL_0:
323    case ALT_DMA_CHANNEL_1:
324    case ALT_DMA_CHANNEL_2:
325    case ALT_DMA_CHANNEL_3:
326    case ALT_DMA_CHANNEL_4:
327    case ALT_DMA_CHANNEL_5:
328    case ALT_DMA_CHANNEL_6:
329    case ALT_DMA_CHANNEL_7:
330        break;
331    default:
332        return ALT_E_BAD_ARG;
333    }
334
335    // Verify channel is unallocated
336
337    if (channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
338    {
339        return ALT_E_ERROR;
340    }
341
342    // Mark channel as allocated
343
344    channel_info_array[channel].flag |= ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED;
345
346    return ALT_E_SUCCESS;
347}
348
349ALT_STATUS_CODE alt_dma_channel_alloc_any(ALT_DMA_CHANNEL_t * allocated)
350{
351    // Sweep channel array for unallocated channel
352
353    for (int i = 0; i < 8; ++i)
354    {
355        if (!(channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
356        {
357            // Allocate that free channel.
358
359            ALT_STATUS_CODE status = alt_dma_channel_alloc((ALT_DMA_CHANNEL_t)i);
360            if (status == ALT_E_SUCCESS)
361            {
362                *allocated = (ALT_DMA_CHANNEL_t)i;
363            }
364            return status;
365        }
366    }
367
368    // No free channels found.
369
370    return ALT_E_ERROR;
371}
372
373ALT_STATUS_CODE alt_dma_channel_free(ALT_DMA_CHANNEL_t channel)
374{
375    // Validate channel
376    switch (channel)
377    {
378    case ALT_DMA_CHANNEL_0:
379    case ALT_DMA_CHANNEL_1:
380    case ALT_DMA_CHANNEL_2:
381    case ALT_DMA_CHANNEL_3:
382    case ALT_DMA_CHANNEL_4:
383    case ALT_DMA_CHANNEL_5:
384    case ALT_DMA_CHANNEL_6:
385    case ALT_DMA_CHANNEL_7:
386        break;
387    default:
388        return ALT_E_BAD_ARG;
389    }
390
391    // Verify channel is allocated
392
393    if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
394    {
395        return ALT_E_ERROR;
396    }
397
398    // Verify channel is stopped
399
400    ALT_DMA_CHANNEL_STATE_t state;
401    ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state);
402    if (status != ALT_E_SUCCESS)
403    {
404        return status;
405    }
406    if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
407    {
408        return ALT_E_ERROR;
409    }
410
411    // Mark channel as unallocated.
412
413    channel_info_array[channel].flag &= ~ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED;
414
415    return ALT_E_SUCCESS;
416}
417
418ALT_STATUS_CODE alt_dma_channel_exec(ALT_DMA_CHANNEL_t channel, ALT_DMA_PROGRAM_t * pgm)
419{
420    // Validate channel
421    switch (channel)
422    {
423    case ALT_DMA_CHANNEL_0:
424    case ALT_DMA_CHANNEL_1:
425    case ALT_DMA_CHANNEL_2:
426    case ALT_DMA_CHANNEL_3:
427    case ALT_DMA_CHANNEL_4:
428    case ALT_DMA_CHANNEL_5:
429    case ALT_DMA_CHANNEL_6:
430    case ALT_DMA_CHANNEL_7:
431        break;
432    default:
433        return ALT_E_BAD_ARG;
434    }
435
436    // Verify channel is allocated
437
438    if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
439    {
440        return ALT_E_ERROR;
441    }
442
443    // Verify channel is stopped
444
445    ALT_DMA_CHANNEL_STATE_t state;
446    ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state);
447    if (status != ALT_E_SUCCESS)
448    {
449        return status;
450    }
451    if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
452    {
453        return ALT_E_ERROR;
454    }
455
456    // Validate the program
457
458    if (alt_dma_program_validate(pgm) != ALT_E_SUCCESS)
459    {
460        return ALT_E_ERROR;
461    }
462
463    //
464    // Execute the program
465    //
466
467    // Get the start address
468
469    uint32_t start = (uint32_t) &pgm->program[pgm->buffer_start];
470
471    dprintf("DMA[exec]: pgm->program = %p.\n", pgm->program);
472    dprintf("DMA[exec]: start        = %p.\n", (void *)start);
473
474    // Configure DBGINST0 and DBGINST1 to execute DMAGO targetting the requested channel.
475
476    // For information on APB Interface, see PL330, section 2.5.1.
477    // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
478    // For information on DMAGO, see PL330, section 4.3.5.
479
480    alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
481                   ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0xa0) | 
482                   ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(channel));
483
484    alt_write_word(ALT_DMA_DBGINST1_ADDR(ALT_DMASECURE_ADDR), start);
485
486    // Execute the instruction held in DBGINST{0,1}
487
488    // For information on DBGCMD, see PL330, section 3.3.19.
489
490    alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
491
492    return ALT_E_SUCCESS;
493}
494
495ALT_STATUS_CODE alt_dma_channel_kill(ALT_DMA_CHANNEL_t channel)
496{
497    // Validate channel
498    switch (channel)
499    {
500    case ALT_DMA_CHANNEL_0:
501    case ALT_DMA_CHANNEL_1:
502    case ALT_DMA_CHANNEL_2:
503    case ALT_DMA_CHANNEL_3:
504    case ALT_DMA_CHANNEL_4:
505    case ALT_DMA_CHANNEL_5:
506    case ALT_DMA_CHANNEL_6:
507    case ALT_DMA_CHANNEL_7:
508        break;
509    default:
510        return ALT_E_BAD_ARG;
511    }
512
513    // Verify channel is allocated
514
515    if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
516    {
517        return ALT_E_ERROR;
518    }
519
520    // NOTE: Don't worry about the current channel state. Just issue DMAKILL
521    //   instruction. The channel state cannot move from from Stopped back to
522    //   Killing.
523
524    // Configure DBGINST0 to execute DMAKILL on the requested channel thread.
525    // DMAKILL is short enough not to use DBGINST1 register.
526
527    // For information on APB Interface, see PL330, section 2.5.1.
528    // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
529    // For information on DMAKILL, see PL330, section 4.3.6.
530
531    alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
532                   ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x1) |
533                   ALT_DMA_DBGINST0_CHANNELNUMBER_SET(channel) |
534                   ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL));
535
536    // Execute the instruction held in DBGINST0
537
538    // For information on DBGCMD, see PL330, section 3.3.19.
539
540    alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
541
542    // Wait for channel to move to KILLING or STOPPED state. Do not wait for
543    // the STOPPED only. If the AXI transaction hangs permanently, it can be
544    // waiting indefinately.
545
546    ALT_STATUS_CODE status = ALT_E_SUCCESS;
547    ALT_DMA_CHANNEL_STATE_t current;
548    uint32_t i = 20000;
549
550    while (--i)
551    {
552        status = alt_dma_channel_state_get(channel, &current);
553        if (status != ALT_E_SUCCESS)
554        {
555            break;
556        }
557        if (   (current == ALT_DMA_CHANNEL_STATE_KILLING)
558            || (current == ALT_DMA_CHANNEL_STATE_STOPPED))
559        {
560            break;
561        }
562    }
563
564    if (i == 0)
565    {
566        status = ALT_E_TMO;
567    }
568
569    return status;
570}
571
572ALT_STATUS_CODE alt_dma_channel_reg_get(ALT_DMA_CHANNEL_t channel,
573                                        ALT_DMA_PROGRAM_REG_t reg, uint32_t * val)
574{
575    // Validate channel
576    switch (channel)
577    {
578    case ALT_DMA_CHANNEL_0:
579    case ALT_DMA_CHANNEL_1:
580    case ALT_DMA_CHANNEL_2:
581    case ALT_DMA_CHANNEL_3:
582    case ALT_DMA_CHANNEL_4:
583    case ALT_DMA_CHANNEL_5:
584    case ALT_DMA_CHANNEL_6:
585    case ALT_DMA_CHANNEL_7:
586        break;
587    default:
588        return ALT_E_BAD_ARG;
589    }
590
591    // For information on SAR, see PL330, section 3.3.13.
592    // For information on DAR, see PL330, section 3.3.14.
593    // For information on CCR, see PL330, section 3.3.15.
594
595    switch (reg)
596    {
597    case ALT_DMA_PROGRAM_REG_SAR:
598        *val = alt_read_word(ALT_DMA_SARx_ADDR(ALT_DMASECURE_ADDR, channel));
599        break;
600    case ALT_DMA_PROGRAM_REG_DAR:
601        *val = alt_read_word(ALT_DMA_DARx_ADDR(ALT_DMASECURE_ADDR, channel));
602        break;
603    case ALT_DMA_PROGRAM_REG_CCR:
604        *val = alt_read_word(ALT_DMA_CCRx_ADDR(ALT_DMASECURE_ADDR, channel));
605        break;
606    default:
607        return ALT_E_BAD_ARG;
608    }
609
610    return ALT_E_SUCCESS;
611}
612
613ALT_STATUS_CODE alt_dma_send_event(ALT_DMA_EVENT_t evt_num)
614{
615    // Validate evt_num
616
617    switch (evt_num)
618    {
619    case ALT_DMA_EVENT_0:
620    case ALT_DMA_EVENT_1:
621    case ALT_DMA_EVENT_2:
622    case ALT_DMA_EVENT_3:
623    case ALT_DMA_EVENT_4:
624    case ALT_DMA_EVENT_5:
625    case ALT_DMA_EVENT_6:
626    case ALT_DMA_EVENT_7:
627    case ALT_DMA_EVENT_ABORT:
628        break;
629    default:
630        return ALT_E_BAD_ARG;
631    }
632
633    // Issue the DMASEV on the DMA manager thread.
634    // DMASEV is short enough not to use DBGINST1 register.
635
636    // For information on APB Interface, see PL330, section 2.5.1.
637    // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
638    // For information on DMASEV, see PL330, section 4.3.15.
639
640    alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
641                   ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x34) | // opcode for DMASEV
642                   ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(evt_num << 3) |
643                   ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER)
644        );
645
646    // Execute the instruction held in DBGINST0
647
648    // For information on DBGCMD, see PL330, section 3.3.19.
649
650    alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
651
652    return ALT_E_SUCCESS;
653}
654
655ALT_STATUS_CODE alt_dma_manager_state_get(ALT_DMA_MANAGER_STATE_t * state)
656{
657    // For information on DSR, see PL330, section 3.3.1.
658
659    uint32_t raw_state = alt_read_word(ALT_DMA_DSR_ADDR(ALT_DMASECURE_ADDR));
660
661    *state = (ALT_DMA_MANAGER_STATE_t)ALT_DMA_DSR_DMASTATUS_GET(raw_state);
662
663    return ALT_E_SUCCESS;
664}
665
666ALT_STATUS_CODE alt_dma_channel_state_get(ALT_DMA_CHANNEL_t channel,
667                                          ALT_DMA_CHANNEL_STATE_t * state)
668{
669    // Validate channel
670    switch (channel)
671    {
672    case ALT_DMA_CHANNEL_0:
673    case ALT_DMA_CHANNEL_1:
674    case ALT_DMA_CHANNEL_2:
675    case ALT_DMA_CHANNEL_3:
676    case ALT_DMA_CHANNEL_4:
677    case ALT_DMA_CHANNEL_5:
678    case ALT_DMA_CHANNEL_6:
679    case ALT_DMA_CHANNEL_7:
680        break;
681    default:
682        return ALT_E_BAD_ARG;
683    }
684
685    // For information on CSR, see PL330, section 3.3.11.
686
687    uint32_t raw_state = alt_read_word(ALT_DMA_CSRx_ADDR(ALT_DMASECURE_ADDR, channel));
688
689    *state = (ALT_DMA_CHANNEL_STATE_t)ALT_DMA_CSRx_CHANNELSTATUS_GET(raw_state);
690
691    return ALT_E_SUCCESS;
692}
693
694ALT_STATUS_CODE alt_dma_manager_fault_status_get(ALT_DMA_MANAGER_FAULT_t * fault)
695{
696    // For information on FTRD, see PL330, section 3.3.9.
697
698    *fault = (ALT_DMA_MANAGER_FAULT_t)alt_read_word(ALT_DMA_FTRD_ADDR(ALT_DMASECURE_ADDR));
699
700    return ALT_E_SUCCESS;
701}
702
703ALT_STATUS_CODE alt_dma_channel_fault_status_get(ALT_DMA_CHANNEL_t channel,
704                                                 ALT_DMA_CHANNEL_FAULT_t * fault)
705{
706    // Validate channel
707    switch (channel)
708    {
709    case ALT_DMA_CHANNEL_0:
710    case ALT_DMA_CHANNEL_1:
711    case ALT_DMA_CHANNEL_2:
712    case ALT_DMA_CHANNEL_3:
713    case ALT_DMA_CHANNEL_4:
714    case ALT_DMA_CHANNEL_5:
715    case ALT_DMA_CHANNEL_6:
716    case ALT_DMA_CHANNEL_7:
717        break;
718    default:
719        return ALT_E_BAD_ARG;
720    }
721
722    // For information on FTR, see PL330, section 3.3.10.
723
724    *fault = (ALT_DMA_CHANNEL_FAULT_t)alt_read_word(ALT_DMA_FTRx_ADDR(ALT_DMASECURE_ADDR, channel));
725
726    return ALT_E_SUCCESS;
727}
728
729ALT_STATUS_CODE alt_dma_event_int_select(ALT_DMA_EVENT_t evt_num,
730                                         ALT_DMA_EVENT_SELECT_t opt)
731{
732    // Validate evt_num
733    switch (evt_num)
734    {
735    case ALT_DMA_EVENT_0:
736    case ALT_DMA_EVENT_1:
737    case ALT_DMA_EVENT_2:
738    case ALT_DMA_EVENT_3:
739    case ALT_DMA_EVENT_4:
740    case ALT_DMA_EVENT_5:
741    case ALT_DMA_EVENT_6:
742    case ALT_DMA_EVENT_7:
743    case ALT_DMA_EVENT_ABORT:
744        break;
745    default:
746        return ALT_E_BAD_ARG;
747    }
748
749    // For information on INTEN, see PL330, section 3.3.3.
750
751    switch (opt)
752    {
753    case ALT_DMA_EVENT_SELECT_SEND_EVT:
754        alt_clrbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num);
755        break;
756    case ALT_DMA_EVENT_SELECT_SIG_IRQ:
757        alt_setbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num);
758        break;
759    default:
760        return ALT_E_BAD_ARG;
761    }
762
763    return ALT_E_SUCCESS;
764}
765
766ALT_STATUS_CODE alt_dma_event_int_status_get_raw(ALT_DMA_EVENT_t evt_num)
767{
768    // Validate evt_num
769    switch (evt_num)
770    {
771    case ALT_DMA_EVENT_0:
772    case ALT_DMA_EVENT_1:
773    case ALT_DMA_EVENT_2:
774    case ALT_DMA_EVENT_3:
775    case ALT_DMA_EVENT_4:
776    case ALT_DMA_EVENT_5:
777    case ALT_DMA_EVENT_6:
778    case ALT_DMA_EVENT_7:
779    case ALT_DMA_EVENT_ABORT:
780        break;
781    default:
782        return ALT_E_BAD_ARG;
783    }
784
785    // For information on INT_EVENT_RIS, see PL330, section 3.3.4.
786
787    uint32_t status_raw = alt_read_word(ALT_DMA_INT_EVENT_RIS_ADDR(ALT_DMASECURE_ADDR));
788
789    if (status_raw & (1 << evt_num))
790    {
791        return ALT_E_TRUE;
792    }
793    else
794    {
795        return ALT_E_FALSE;
796    }
797}
798
799ALT_STATUS_CODE alt_dma_int_status_get(ALT_DMA_EVENT_t irq_num)
800{
801    // Validate evt_num
802    switch (irq_num)
803    {
804    case ALT_DMA_EVENT_0:
805    case ALT_DMA_EVENT_1:
806    case ALT_DMA_EVENT_2:
807    case ALT_DMA_EVENT_3:
808    case ALT_DMA_EVENT_4:
809    case ALT_DMA_EVENT_5:
810    case ALT_DMA_EVENT_6:
811    case ALT_DMA_EVENT_7:
812    case ALT_DMA_EVENT_ABORT:
813        break;
814    default:
815        return ALT_E_BAD_ARG;
816    }
817
818    // For information on INTMIS, see PL330, section 3.3.5.
819
820    uint32_t int_status = alt_read_word(ALT_DMA_INTMIS_ADDR(ALT_DMASECURE_ADDR));
821
822    if (int_status & (1 << irq_num))
823    {
824        return ALT_E_TRUE;
825    }
826    else
827    {
828        return ALT_E_FALSE;
829    }
830}
831
832ALT_STATUS_CODE alt_dma_int_clear(ALT_DMA_EVENT_t irq_num)
833{
834    // Validate evt_num
835    switch (irq_num)
836    {
837    case ALT_DMA_EVENT_0:
838    case ALT_DMA_EVENT_1:
839    case ALT_DMA_EVENT_2:
840    case ALT_DMA_EVENT_3:
841    case ALT_DMA_EVENT_4:
842    case ALT_DMA_EVENT_5:
843    case ALT_DMA_EVENT_6:
844    case ALT_DMA_EVENT_7:
845    case ALT_DMA_EVENT_ABORT:
846        break;
847    default:
848        return ALT_E_BAD_ARG;
849    }
850
851    // For information on INTCLR, see PL330, section 3.3.6.
852
853    alt_write_word(ALT_DMA_INTCLR_ADDR(ALT_DMASECURE_ADDR), 1 << irq_num);
854
855    return ALT_E_SUCCESS;
856}
857
858/////
859
860ALT_STATUS_CODE alt_dma_memory_to_memory(ALT_DMA_CHANNEL_t channel,
861                                         ALT_DMA_PROGRAM_t * program,
862                                         void * dst,
863                                         const void * src,
864                                         size_t size,
865                                         bool send_evt,
866                                         ALT_DMA_EVENT_t evt)
867{
868    ALT_STATUS_CODE status = ALT_E_SUCCESS;
869
870    // If the size is zero, and no event is requested, just return success.
871    if ((size == 0) && (send_evt == false))
872    {
873        return status;
874    }
875
876    if (status == ALT_E_SUCCESS)
877    {
878        status = alt_dma_program_init(program);
879    }
880
881    if (size != 0)
882    {
883        uintptr_t udst = (uintptr_t)dst;
884        uintptr_t usrc = (uintptr_t)src;
885
886        dprintf("DMA[M->M]: dst  = %p.\n", dst);
887        dprintf("DMA[M->M]: src  = %p.\n", src);
888        dprintf("DMA[M->M]: size = 0x%x.\n", size);
889       
890        // Detect if memory regions overshoots the address space.
891
892        if (udst + size - 1 < udst)
893        {
894            return ALT_E_BAD_ARG;
895        }
896        if (usrc + size - 1 < usrc)
897        {
898            return ALT_E_BAD_ARG;
899        }
900
901        // Detect if memory regions overlaps.
902
903        if (udst > usrc)
904        {
905            if (usrc + size - 1 > udst)
906            {
907                return ALT_E_BAD_ARG;
908            }
909        }
910        else
911        {
912            if (udst + size - 1 > usrc)
913            {
914                return ALT_E_BAD_ARG;
915            }
916        }
917
918        if (status == ALT_E_SUCCESS)
919        {
920            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, usrc);
921        }
922        if (status == ALT_E_SUCCESS)
923        {
924            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, udst);
925        }
926
927        size_t sizeleft = size;
928
929        //
930        // The algorithm uses the strategy described in PL330 B.3.1.
931        // It is extended for 2-byte and 1-byte unaligned cases.
932        //
933
934        // First see how many byte(s) we need to transfer to get src to be 8 byte aligned
935        if (usrc & 0x7)
936        {
937            uint32_t aligncount = MIN(8 - (usrc & 0x7), sizeleft);
938            sizeleft -= aligncount;
939
940            dprintf("DMA[M->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount);
941
942            // Program in the following parameters:
943            //  - SS8 (Source      burst size of 1-byte)
944            //  - DS8 (Destination burst size of 1-byte)
945            //  - SBx (Source      burst length of [aligncount] transfers)
946            //  - DBx (Destination burst length of [aligncount] transfers)
947            //  - All other options default.
948
949            if (status == ALT_E_SUCCESS)
950            {
951                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
952                                                (   ((aligncount - 1) << 4) // SB
953                                                  | ALT_DMA_CCR_OPT_SS8
954                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
955                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
956                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
957                                                  | ((aligncount - 1) << 18) // DB
958                                                  | ALT_DMA_CCR_OPT_DS8
959                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
960                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
961                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
962                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
963                                                )
964                    );
965            }
966            if (status == ALT_E_SUCCESS)
967            {
968                status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
969            }
970            if (status == ALT_E_SUCCESS)
971            {
972                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
973            }
974        }
975
976        // This is the number of 8-byte bursts
977        uint32_t burstcount = sizeleft >> 3;
978
979        bool correction = (burstcount != 0);
980
981        // Update the size left to transfer
982        sizeleft &= 0x7;
983
984        dprintf("DMA[M->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount);
985        dprintf("DMA[M->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft);
986
987        // Determine how many 16 length bursts can be done
988
989        if (burstcount >> 4)
990        {
991            uint32_t length16burstcount = burstcount >> 4;
992            burstcount &= 0xf;
993
994            dprintf("DMA[M->M]:   Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount);
995            dprintf("DMA[M->M]:   Number of remaining 8-byte transfer(s):       %lu.\n", burstcount);
996
997            // Program in the following parameters:
998            //  - SS64 (Source      burst size of 8-byte)
999            //  - DS64 (Destination burst size of 8-byte)
1000            //  - SB16 (Source      burst length of 16 transfers)
1001            //  - DB16 (Destination burst length of 16 transfers)
1002            //  - All other options default.
1003
1004            if (status == ALT_E_SUCCESS)
1005            {
1006                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1007                                                (   ALT_DMA_CCR_OPT_SB16
1008                                                  | ALT_DMA_CCR_OPT_SS64
1009                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1010                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1011                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1012                                                  | ALT_DMA_CCR_OPT_DB16
1013                                                  | ALT_DMA_CCR_OPT_DS64
1014                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1015                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1016                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1017                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1018                                                )
1019                    );
1020            }
1021
1022            while (length16burstcount > 0)
1023            {
1024                if (status != ALT_E_SUCCESS)
1025                {
1026                    break;
1027                }
1028
1029                uint32_t loopcount = MIN(length16burstcount, 256);
1030                length16burstcount -= loopcount;
1031
1032                dprintf("DMA[M->M]:   Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount);
1033
1034                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1035                {
1036                    status = alt_dma_program_DMALP(program, loopcount);
1037                }
1038                if (status == ALT_E_SUCCESS)
1039                {
1040                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1041                }
1042                if (status == ALT_E_SUCCESS)
1043                {
1044                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1045                }
1046                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1047                {
1048                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1049                }
1050            }
1051        }
1052
1053        // At this point, we should have [burstcount] 8-byte transfer(s)
1054        // remaining. [burstcount] should be less than 16.
1055
1056        // Do one more burst with a SB / DB of length [burstcount].
1057
1058        if (burstcount)
1059        {
1060            // Program in the following parameters:
1061            //  - SS64 (Source      burst size of 8-byte)
1062            //  - DS64 (Destination burst size of 8-byte)
1063            //  - SBx  (Source      burst length of [burstlength] transfers)
1064            //  - DBx  (Destination burst length of [burstlength] transfers)
1065            //  - All other options default.
1066
1067            if (status == ALT_E_SUCCESS)
1068            {
1069                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1070                                                (   ((burstcount - 1) << 4) // SB
1071                                                  | ALT_DMA_CCR_OPT_SS64
1072                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1073                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1074                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1075                                                  | ((burstcount - 1) << 18) // DB
1076                                                  | ALT_DMA_CCR_OPT_DS64
1077                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1078                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1079                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1080                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1081                                                )
1082                    );
1083            }
1084            if (status == ALT_E_SUCCESS)
1085            {
1086                status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1087            }
1088            if (status == ALT_E_SUCCESS)
1089            {
1090                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1091            }
1092        }
1093
1094        // This is where the last DMAMOV CCR and DMAST is done if an
1095        // alignment correction required.
1096
1097        if (   (correction == true)
1098            && ((usrc & 0x7) != (udst & 0x7)) // If src and dst are mod-8 congruent, no correction is needed.
1099           )
1100        {
1101            if (status == ALT_E_SUCCESS)
1102            {
1103                // Determine what type of correction.
1104
1105                // Set the source parameters to match that of the destination
1106                // parameters. This way the SAR is increment in the same fashion as
1107                // DAR. This will allow the non 8-byte transfers to copy correctly.
1108
1109                uint32_t ccr;
1110
1111                if ((usrc & 0x3) == (udst & 0x3))
1112                {
1113                    dprintf("DMA[M->M]: Single correction 4-byte burst size tranfer.\n");
1114
1115                    // Program in the following parameters:
1116                    //  - SS32 (Source      burst size of 4-byte)
1117                    //  - DS32 (Destination burst size of 4-byte)
1118                    //  - SB1  (Source      burst length of 1 transfer)
1119                    //  - DB1  (Destination burst length of 1 transfer)
1120                    //  - All other options default.
1121
1122                    ccr = (   ALT_DMA_CCR_OPT_SB1
1123                            | ALT_DMA_CCR_OPT_SS32
1124                            | ALT_DMA_CCR_OPT_SA_DEFAULT
1125                            | ALT_DMA_CCR_OPT_SP_DEFAULT
1126                            | ALT_DMA_CCR_OPT_SC_DEFAULT
1127                            | ALT_DMA_CCR_OPT_DB1
1128                            | ALT_DMA_CCR_OPT_DS32
1129                            | ALT_DMA_CCR_OPT_DA_DEFAULT
1130                            | ALT_DMA_CCR_OPT_DP_DEFAULT
1131                            | ALT_DMA_CCR_OPT_DC_DEFAULT
1132                            | ALT_DMA_CCR_OPT_ES_DEFAULT
1133                          );
1134                }
1135                else if ((usrc & 0x1) == (udst & 0x1))
1136                {
1137                    dprintf("DMA[M->M]: Single correction 2-byte burst size tranfer.\n");
1138
1139                    // Program in the following parameters:
1140                    //  - SS16 (Source      burst size of 2-byte)
1141                    //  - DS16 (Destination burst size of 2-byte)
1142                    //  - SB1  (Source      burst length of 1 transfer)
1143                    //  - DB1  (Destination burst length of 1 transfer)
1144                    //  - All other options default.
1145
1146                    ccr = (   ALT_DMA_CCR_OPT_SB1
1147                            | ALT_DMA_CCR_OPT_SS16
1148                            | ALT_DMA_CCR_OPT_SA_DEFAULT
1149                            | ALT_DMA_CCR_OPT_SP_DEFAULT
1150                            | ALT_DMA_CCR_OPT_SC_DEFAULT
1151                            | ALT_DMA_CCR_OPT_DB1
1152                            | ALT_DMA_CCR_OPT_DS16
1153                            | ALT_DMA_CCR_OPT_DA_DEFAULT
1154                            | ALT_DMA_CCR_OPT_DP_DEFAULT
1155                            | ALT_DMA_CCR_OPT_DC_DEFAULT
1156                            | ALT_DMA_CCR_OPT_ES_DEFAULT
1157                          );
1158                }
1159                else
1160                {
1161                    dprintf("DMA[M->M]: Single correction 1-byte burst size tranfer.\n");
1162
1163                    // Program in the following parameters:
1164                    //  - SS8 (Source      burst size of 1-byte)
1165                    //  - DS8 (Destination burst size of 1-byte)
1166                    //  - SB1 (Source      burst length of 1 transfer)
1167                    //  - DB1 (Destination burst length of 1 transfer)
1168                    //  - All other options default.
1169
1170                    ccr = (   ALT_DMA_CCR_OPT_SB1
1171                            | ALT_DMA_CCR_OPT_SS8
1172                            | ALT_DMA_CCR_OPT_SA_DEFAULT
1173                            | ALT_DMA_CCR_OPT_SP_DEFAULT
1174                            | ALT_DMA_CCR_OPT_SC_DEFAULT
1175                            | ALT_DMA_CCR_OPT_DB1
1176                            | ALT_DMA_CCR_OPT_DS8
1177                            | ALT_DMA_CCR_OPT_DA_DEFAULT
1178                            | ALT_DMA_CCR_OPT_DP_DEFAULT
1179                            | ALT_DMA_CCR_OPT_DC_DEFAULT
1180                            | ALT_DMA_CCR_OPT_ES_DEFAULT
1181                          );
1182                }
1183
1184                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1185                                                ccr);
1186            }
1187            if (status == ALT_E_SUCCESS)
1188            {
1189                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1190            }
1191        }
1192
1193        // At this point, there should be 0 - 7 1-byte transfers remaining.
1194
1195        if (sizeleft)
1196        {
1197            dprintf("DMA[M->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft);
1198
1199            // Program in the following parameters:
1200            //  - SS8 (Source      burst size of 1-byte)
1201            //  - DS8 (Destination burst size of 1-byte)
1202            //  - SBx (Source      burst length of [sizeleft] transfers)
1203            //  - DBx (Destination burst length of [sizeleft] transfers)
1204            //  - All other options default.
1205
1206            if (status == ALT_E_SUCCESS)
1207            {
1208                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1209                                                (   ((sizeleft - 1) << 4) // SB
1210                                                  | ALT_DMA_CCR_OPT_SS8
1211                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1212                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1213                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1214                                                  | ((sizeleft - 1) << 18) // DB
1215                                                  | ALT_DMA_CCR_OPT_DS8
1216                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1217                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1218                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1219                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1220                                                )
1221                    );
1222            }
1223            if (status == ALT_E_SUCCESS)
1224            {
1225                status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1226            }
1227            if (status == ALT_E_SUCCESS)
1228            {
1229                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1230            }
1231        }
1232    } // if (size != 0)
1233
1234    // Send event if requested.
1235    if (send_evt)
1236    {
1237        if (status == ALT_E_SUCCESS)
1238        {
1239            dprintf("DMA[M->M]: Adding event ...\n");
1240            status = alt_dma_program_DMASEV(program, evt);
1241        }
1242    }
1243
1244    // Now that everything is done, end the program.
1245    if (status == ALT_E_SUCCESS)
1246    {
1247        status = alt_dma_program_DMAEND(program);
1248    }
1249
1250    // If there was a problem assembling the program, clean up the buffer and exit.
1251    if (status != ALT_E_SUCCESS)
1252    {
1253        // Do not report the status for the clear operation. A failure should be
1254        // reported regardless of if the clear is successful.
1255        alt_dma_program_clear(program);
1256        return status;
1257    }
1258
1259    // Execute the program on the given channel.
1260    return alt_dma_channel_exec(channel, program);
1261}
1262
1263ALT_STATUS_CODE alt_dma_zero_to_memory(ALT_DMA_CHANNEL_t channel,
1264                                       ALT_DMA_PROGRAM_t * program,
1265                                       void * buf,
1266                                       size_t size,
1267                                       bool send_evt,
1268                                       ALT_DMA_EVENT_t evt)
1269{
1270    ALT_STATUS_CODE status = ALT_E_SUCCESS;
1271
1272    // If the size is zero, and no event is requested, just return success.
1273    if ((size == 0) && (send_evt == false))
1274    {
1275        return status;
1276    }
1277
1278    if (status == ALT_E_SUCCESS)
1279    {
1280        status = alt_dma_program_init(program);
1281    }
1282
1283    if (size != 0)
1284    {
1285        if (status == ALT_E_SUCCESS)
1286        {
1287            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)buf);
1288        }
1289
1290        dprintf("DMA[Z->M]: buf  = %p.\n", buf);
1291        dprintf("DMA[Z->M]: size = 0x%x.\n", size);
1292
1293        size_t sizeleft = size;
1294
1295        // First see how many byte(s) we need to transfer to get dst to be 8 byte aligned.
1296        if ((uint32_t)buf & 0x7)
1297        {
1298            uint32_t aligncount = MIN(8 - ((uint32_t)buf & 0x7), sizeleft);
1299            sizeleft -= aligncount;
1300
1301            dprintf("DMA[Z->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount);
1302
1303            // Program in the following parameters:
1304            //  - DS8 (Destination burst size of 1-byte)
1305            //  - DBx (Destination burst length of [aligncount] transfers)
1306            //  - All other options default.
1307
1308            if (status == ALT_E_SUCCESS)
1309            {
1310                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1311                                                (   ALT_DMA_CCR_OPT_SB_DEFAULT
1312                                                  | ALT_DMA_CCR_OPT_SS_DEFAULT
1313                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1314                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1315                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1316                                                  | ((aligncount - 1) << 18) // DB
1317                                                  | ALT_DMA_CCR_OPT_DS8
1318                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1319                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1320                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1321                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1322                                                )
1323                    );
1324            }
1325            if (status == ALT_E_SUCCESS)
1326            {
1327                status = alt_dma_program_DMASTZ(program);
1328            }
1329        }
1330
1331        // This is the number of 8-byte bursts left
1332        uint32_t burstcount = sizeleft >> 3;
1333
1334        // Update the size left to transfer
1335        sizeleft &= 0x7;
1336
1337        dprintf("DMA[Z->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount);
1338        dprintf("DMA[Z->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft);
1339
1340        // Determine how many 16 length bursts can be done
1341        if (burstcount >> 4)
1342        {
1343            uint32_t length16burstcount = burstcount >> 4;
1344            burstcount &= 0xf;
1345
1346            dprintf("DMA[Z->M]:   Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount);
1347            dprintf("DMA[Z->M]:   Number of remaining 8-byte transfer(s):       %lu.\n", burstcount);
1348
1349            // Program in the following parameters:
1350            //  - DS64 (Destination burst size of 8-byte)
1351            //  - DB16 (Destination burst length of 16 transfers)
1352            //  - All other options default.
1353
1354            if (status == ALT_E_SUCCESS)
1355            {
1356                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1357                                                (   ALT_DMA_CCR_OPT_SB_DEFAULT
1358                                                  | ALT_DMA_CCR_OPT_SS_DEFAULT
1359                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1360                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1361                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1362                                                  | ALT_DMA_CCR_OPT_DB16
1363                                                  | ALT_DMA_CCR_OPT_DS64
1364                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1365                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1366                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1367                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1368                                                )
1369                    );
1370            }
1371
1372            while (length16burstcount > 0)
1373            {
1374                if (status != ALT_E_SUCCESS)
1375                {
1376                    break;
1377                }
1378
1379                uint32_t loopcount = MIN(length16burstcount, 256);
1380                length16burstcount -= loopcount;
1381
1382                dprintf("DMA[Z->M]:   Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount);
1383
1384                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1385                {
1386                    status = alt_dma_program_DMALP(program, loopcount);
1387                }
1388                if (status == ALT_E_SUCCESS)
1389                {
1390                    status = alt_dma_program_DMASTZ(program);
1391                }
1392                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1393                {
1394                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1395                }
1396            }
1397        }
1398
1399        // At this point, we should have [burstcount] 8-byte transfer(s)
1400        // remaining. [burstcount] should be less than 16.
1401
1402        // Do one more burst with a SB / DB of length [burstcount].
1403
1404        if (burstcount)
1405        {
1406            // Program in the following parameters:
1407            //  - DS64 (Destination burst size of 8-byte)
1408            //  - DBx  (Destination burst length of [burstlength] transfers)
1409            //  - All other options default.
1410
1411            if (status == ALT_E_SUCCESS)
1412            {
1413                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1414                                                (   ALT_DMA_CCR_OPT_SB_DEFAULT
1415                                                  | ALT_DMA_CCR_OPT_SS_DEFAULT
1416                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1417                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1418                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1419                                                  | ((burstcount - 1) << 18) // DB
1420                                                  | ALT_DMA_CCR_OPT_DS64
1421                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1422                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1423                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1424                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1425                                                )
1426                    );
1427            }
1428            if (status == ALT_E_SUCCESS)
1429            {
1430                status = alt_dma_program_DMASTZ(program);
1431            }
1432        }
1433
1434        // At this point, there should be 0 - 7 1-byte transfers remaining.
1435
1436        if (sizeleft)
1437        {
1438            dprintf("DMA[Z->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft);
1439
1440            // Program in the following parameters:
1441            //  - DS8 (Destination burst size of 1-byte)
1442            //  - DBx (Destination burst length of [sizeleft] transfers)
1443            //  - All other options default.
1444
1445            if (status == ALT_E_SUCCESS)
1446            {
1447                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1448                                                (   ALT_DMA_CCR_OPT_SB_DEFAULT
1449                                                  | ALT_DMA_CCR_OPT_SS_DEFAULT
1450                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1451                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1452                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1453                                                  | ((sizeleft - 1) << 18) // DB
1454                                                  | ALT_DMA_CCR_OPT_DS8
1455                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1456                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1457                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1458                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1459                                                )
1460                    );
1461            }
1462            if (status == ALT_E_SUCCESS)
1463            {
1464                status = alt_dma_program_DMASTZ(program);
1465            }
1466        }
1467    } // if (size != 0)
1468
1469    // Send event if requested.
1470    if (send_evt)
1471    {
1472        if (status == ALT_E_SUCCESS)
1473        {
1474            dprintf("DMA[Z->M]: Adding event ...\n");
1475            status = alt_dma_program_DMASEV(program, evt);
1476        }
1477    }
1478
1479    // Now that everything is done, end the program.
1480    if (status == ALT_E_SUCCESS)
1481    {
1482        status = alt_dma_program_DMAEND(program);
1483    }
1484
1485    // If there was a problem assembling the program, clean up the buffer and exit.
1486    if (status != ALT_E_SUCCESS)
1487    {
1488        // Do not report the status for the clear operation. A failure should be
1489        // reported regardless of if the clear is successful.
1490        alt_dma_program_clear(program);
1491        return status;
1492    }
1493
1494    // Execute the program on the given channel.
1495    return alt_dma_channel_exec(channel, program);
1496}
1497
1498ALT_STATUS_CODE alt_dma_memory_to_register(ALT_DMA_CHANNEL_t channel,
1499                                           ALT_DMA_PROGRAM_t * program,
1500                                           void * dst_reg,
1501                                           const void * src_buf,
1502                                           size_t count,
1503                                           uint32_t register_width_bits,
1504                                           bool send_evt,
1505                                           ALT_DMA_EVENT_t evt)
1506{
1507    ALT_STATUS_CODE status = ALT_E_SUCCESS;
1508
1509    // If the count is zero, and no event is requested, just return success.
1510    if ((count == 0) && (send_evt == false))
1511    {
1512        return status;
1513    }
1514
1515    if (status == ALT_E_SUCCESS)
1516    {
1517        status = alt_dma_program_init(program);
1518    }
1519
1520    if (count != 0)
1521    {
1522        // Verify valid register_width_bits and construct the CCR SS and DS parameters.
1523        uint32_t ccr_ss_ds_mask = 0;
1524
1525        if (status == ALT_E_SUCCESS)
1526        {
1527            switch (register_width_bits)
1528            {
1529            case 8:
1530                // Program in the following parameters:
1531                //  - SS8 (Source      burst size of 8 bits)
1532                //  - DS8 (Destination burst size of 8 bits)
1533                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8;
1534                break;
1535            case 16:
1536                // Program in the following parameters:
1537                //  - SS16 (Source      burst size of 16 bits)
1538                //  - DS16 (Destination burst size of 16 bits)
1539                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16;
1540                break;
1541            case 32:
1542                // Program in the following parameters:
1543                //  - SS32 (Source      burst size of 32 bits)
1544                //  - DS32 (Destination burst size of 32 bits)
1545                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32;
1546                break;
1547            case 64:
1548                // Program in the following parameters:
1549                //  - SS64 (Source      burst size of 64 bits)
1550                //  - DS64 (Destination burst size of 64 bits)
1551                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64;
1552                break;
1553            default:
1554                status = ALT_E_BAD_ARG;
1555                break;
1556            }
1557        }
1558
1559        // Verify that the dst_reg and src_buf are aligned to the register width
1560        if (status == ALT_E_SUCCESS)
1561        {
1562            if      (((uintptr_t)dst_reg & ((register_width_bits >> 3) - 1)) != 0)
1563            {
1564                status = ALT_E_BAD_ARG;
1565            }
1566            else if (((uintptr_t)src_buf & ((register_width_bits >> 3) - 1)) != 0)
1567            {
1568                status = ALT_E_BAD_ARG;
1569            }
1570            else
1571            {
1572                dprintf("DMA[M->R]: dst_reg = %p.\n",   dst_reg);
1573                dprintf("DMA[M->R]: src_buf = %p.\n",   src_buf);
1574                dprintf("DMA[M->R]: count   = 0x%x.\n", count);
1575            }
1576        }
1577
1578        if (status == ALT_E_SUCCESS)
1579        {
1580            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_buf);
1581        }
1582        if (status == ALT_E_SUCCESS)
1583        {
1584            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_reg);
1585        }
1586
1587        // This is the remaining count left to process.
1588        uint32_t countleft = count;
1589
1590        // See how many 16-length bursts we can use
1591        if (countleft >> 4)
1592        {
1593            // Program in the following parameters:
1594            //  - SSx  (Source      burst size of [ccr_ss_ds_mask])
1595            //  - DSx  (Destination burst size of [ccr_ss_ds_mask])
1596            //  - DAF  (Destination address fixed)
1597            //  - SB16 (Source      burst length of 16 transfers)
1598            //  - DB16 (Destination burst length of 16 transfers)
1599            //  - All other options default.
1600
1601            if (status == ALT_E_SUCCESS)
1602            {
1603                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1604                                                (   ccr_ss_ds_mask
1605                                                  | ALT_DMA_CCR_OPT_SB16
1606                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1607                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1608                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1609                                                  | ALT_DMA_CCR_OPT_DB16
1610                                                  | ALT_DMA_CCR_OPT_DAF
1611                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1612                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1613                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1614                                                )
1615                    );
1616            }
1617
1618            uint32_t length16burst = countleft >> 4;
1619            countleft &= 0xf;
1620
1621            dprintf("DMA[M->R]:   Number of 16 burst length transfer(s): %lu.\n", length16burst);
1622            dprintf("DMA[M->R]:   Number of remaining transfer(s):       %lu.\n", countleft);
1623
1624            // See how many 256x 16-length bursts we can use
1625            if (length16burst >> 8)
1626            {
1627                uint32_t loop256length16burst = length16burst >> 8;
1628                length16burst &= ((1 << 8) - 1);
1629
1630                dprintf("DMA[M->R]:     Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst);
1631                dprintf("DMA[M->R]:     Number of remaining 16 burst length transfer(s):  %lu.\n", length16burst);
1632
1633                while (loop256length16burst > 0)
1634                {
1635                    if (status != ALT_E_SUCCESS)
1636                    {
1637                        break;
1638                    }
1639
1640                    uint32_t loopcount = MIN(loop256length16burst, 256);
1641                    loop256length16burst -= loopcount;
1642
1643                    dprintf("DMA[M->R]:     Looping %lux super loop transfer(s).\n", loopcount);
1644
1645                    if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1646                    {
1647                        status = alt_dma_program_DMALP(program, loopcount);
1648                    }
1649
1650                    if (status == ALT_E_SUCCESS)
1651                    {
1652                        status = alt_dma_program_DMALP(program, 256);
1653                    }
1654                    if (status == ALT_E_SUCCESS)
1655                    {
1656                        status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1657                    }
1658                    if (status == ALT_E_SUCCESS)
1659                    {
1660                        status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1661                    }
1662                    if (status == ALT_E_SUCCESS)
1663                    {
1664                        status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1665                    }
1666
1667                    if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1668                    {
1669                        status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1670                    }
1671                }
1672            }
1673
1674            // The super loop above ensures that the length16burst is below 256.
1675            if (length16burst > 0)
1676            {
1677                uint32_t loopcount = length16burst;
1678                length16burst = 0;
1679
1680                dprintf("DMA[M->R]:   Looping %lux 16 burst length transfer(s).\n", loopcount);
1681
1682                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1683                {
1684                    status = alt_dma_program_DMALP(program, loopcount);
1685                }
1686                if (status == ALT_E_SUCCESS)
1687                {
1688                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1689                }
1690                if (status == ALT_E_SUCCESS)
1691                {
1692                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1693                }
1694                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1695                {
1696                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1697                }
1698            }
1699        }
1700
1701        // At this point, we should have [countleft] transfer(s) remaining.
1702        // [countleft] should be less than 16.
1703
1704        if (countleft)
1705        {
1706            // Program in the following parameters:
1707            //  - SSx (Source      burst size of [ccr_ss_ds_mask])
1708            //  - DSx (Destination burst size of [ccr_ss_ds_mask])
1709            //  - DAF (Destination address fixed)
1710            //  - SBx (Source      burst length of [countleft] transfer(s))
1711            //  - DBx (Destination burst length of [countleft] transfer(s))
1712            //  - All other options default.
1713
1714            if (status == ALT_E_SUCCESS)
1715            {
1716                dprintf("DMA[M->R]:   Tail end %lux transfer(s).\n", countleft);
1717
1718                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1719                                                (   ccr_ss_ds_mask
1720                                                  | ((countleft - 1) << 4) // SB
1721                                                  | ALT_DMA_CCR_OPT_SA_DEFAULT
1722                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1723                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1724                                                  | ((countleft - 1) << 18) // DB
1725                                                  | ALT_DMA_CCR_OPT_DAF
1726                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1727                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1728                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1729                                                )
1730                    );
1731            }
1732            if (status == ALT_E_SUCCESS)
1733            {
1734                status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1735            }
1736            if (status == ALT_E_SUCCESS)
1737            {
1738                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1739            }
1740        }
1741
1742    } // if (count != 0)
1743
1744    // Send event if requested.
1745    if (send_evt)
1746    {
1747        if (status == ALT_E_SUCCESS)
1748        {
1749            dprintf("DMA[M->R]: Adding event ...\n");
1750            status = alt_dma_program_DMASEV(program, evt);
1751        }
1752    }
1753
1754    // Now that everything is done, end the program.
1755    if (status == ALT_E_SUCCESS)
1756    {
1757        dprintf("DMA[M->R]: DMAEND program.\n");
1758        status = alt_dma_program_DMAEND(program);
1759    }
1760
1761    // If there was a problem assembling the program, clean up the buffer and exit.
1762    if (status != ALT_E_SUCCESS)
1763    {
1764        // Do not report the status for the clear operation. A failure should be
1765        // reported regardless of if the clear is successful.
1766        alt_dma_program_clear(program);
1767        return status;
1768    }
1769
1770    // Execute the program on the given channel.
1771    return alt_dma_channel_exec(channel, program);
1772}
1773
1774ALT_STATUS_CODE alt_dma_register_to_memory(ALT_DMA_CHANNEL_t channel,
1775                                           ALT_DMA_PROGRAM_t * program,
1776                                           void * dst_buf,
1777                                           const void * src_reg,
1778                                           size_t count,
1779                                           uint32_t register_width_bits,
1780                                           bool send_evt,
1781                                           ALT_DMA_EVENT_t evt)
1782{
1783    ALT_STATUS_CODE status = ALT_E_SUCCESS;
1784
1785    // If the count is zero, and no event is requested, just return success.
1786    if ((count == 0) && (send_evt == false))
1787    {
1788        return status;
1789    }
1790
1791    if (status == ALT_E_SUCCESS)
1792    {
1793        status = alt_dma_program_init(program);
1794    }
1795
1796    if (count != 0)
1797    {
1798        // Verify valid register_width_bits and construct the CCR SS and DS parameters.
1799        uint32_t ccr_ss_ds_mask = 0;
1800
1801        if (status == ALT_E_SUCCESS)
1802        {
1803            switch (register_width_bits)
1804            {
1805            case 8:
1806                // Program in the following parameters:
1807                //  - SS8 (Source      burst size of 8 bits)
1808                //  - DS8 (Destination burst size of 8 bits)
1809                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8;
1810                break;
1811            case 16:
1812                // Program in the following parameters:
1813                //  - SS16 (Source      burst size of 16 bits)
1814                //  - DS16 (Destination burst size of 16 bits)
1815                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16;
1816                break;
1817            case 32:
1818                // Program in the following parameters:
1819                //  - SS32 (Source      burst size of 32 bits)
1820                //  - DS32 (Destination burst size of 32 bits)
1821                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32;
1822                break;
1823            case 64:
1824                // Program in the following parameters:
1825                //  - SS64 (Source      burst size of 64 bits)
1826                //  - DS64 (Destination burst size of 64 bits)
1827                ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64;
1828                break;
1829            default:
1830                dprintf("DMA[R->M]: Invalid register width.\n");
1831                status = ALT_E_BAD_ARG;
1832                break;
1833            }
1834        }
1835
1836        // Verify that the dst_buf and src_reg are aligned to the register width
1837        if (status == ALT_E_SUCCESS)
1838        {
1839            if      (((uintptr_t)dst_buf & ((register_width_bits >> 3) - 1)) != 0)
1840            {
1841                status = ALT_E_BAD_ARG;
1842            }
1843            else if (((uintptr_t)src_reg & ((register_width_bits >> 3) - 1)) != 0)
1844            {
1845                status = ALT_E_BAD_ARG;
1846            }
1847            else
1848            {
1849                dprintf("DMA[R->M]: dst_reg = %p.\n",   dst_buf);
1850                dprintf("DMA[R->M]: src_buf = %p.\n",   src_reg);
1851                dprintf("DMA[R->M]: count   = 0x%x.\n", count);
1852            }
1853        }
1854
1855        if (status == ALT_E_SUCCESS)
1856        {
1857            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_reg);
1858        }
1859        if (status == ALT_E_SUCCESS)
1860        {
1861            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_buf);
1862        }
1863
1864        // This is the remaining count left to process.
1865        uint32_t countleft = count;
1866
1867        // See how many 16-length bursts we can use
1868        if (countleft >> 4)
1869        {
1870            uint32_t length16burst = countleft >> 4;
1871            countleft &= 0xf;
1872
1873            dprintf("DMA[R->M]:   Number of 16 burst length transfer(s): %lu.\n", length16burst);
1874            dprintf("DMA[R->M]:   Number of remaining transfer(s):       %lu.\n", countleft);
1875
1876            //
1877            // The algorithm uses the strategy described in PL330 B.2.3.
1878            // Not sure if registers will accept burst transfers so read the register in its own transfer.
1879            //
1880
1881            // Program in the following parameters:
1882            //  - SAF  (Source      address fixed)
1883            //  - SSx  (Source      burst size of [ccr_ss_ds_mask])
1884            //  - DSx  (Destination burst size of [ccr_ss_ds_mask])
1885            //  - SB16 (Source      burst length of 16 transfers)
1886            //  - DB16 (Destination burst length of 16 transfers)
1887            //  - All other options default.
1888
1889            if (status == ALT_E_SUCCESS)
1890            {
1891                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1892                                                (   ccr_ss_ds_mask
1893                                                  | ALT_DMA_CCR_OPT_SB16
1894                                                  | ALT_DMA_CCR_OPT_SAF
1895                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
1896                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
1897                                                  | ALT_DMA_CCR_OPT_DB16
1898                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
1899                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
1900                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
1901                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
1902                                                )
1903                    );
1904            }
1905
1906            // See how many 256x 16-length bursts we can do
1907            if (length16burst >> 8)
1908            {
1909                uint32_t loop256length16burst = length16burst >> 8;
1910                length16burst &= ((1 << 8) - 1);
1911
1912                dprintf("DMA[R->M]:     Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst);
1913                dprintf("DMA[R->M]:     Number of remaining 16 burst length transfer(s):  %lu.\n", length16burst);
1914
1915                while (loop256length16burst > 0)
1916                {
1917                    if (status != ALT_E_SUCCESS)
1918                    {
1919                        break;
1920                    }
1921
1922                    uint32_t loopcount = MIN(loop256length16burst, 256);
1923                    loop256length16burst -= loopcount;
1924
1925                    dprintf("DMA[R->M]:     Looping %lux super loop transfer(s).\n", loopcount);
1926
1927                    if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1928                    {
1929                        status = alt_dma_program_DMALP(program, loopcount);
1930                    }
1931
1932                    if (status == ALT_E_SUCCESS)
1933                    {
1934                        status = alt_dma_program_DMALP(program, 256);
1935                    }
1936                    if (status == ALT_E_SUCCESS)
1937                    {
1938                        status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1939                    }
1940                    if (status == ALT_E_SUCCESS)
1941                    {
1942                        status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1943                    }
1944                    if (status == ALT_E_SUCCESS)
1945                    {
1946                        status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1947                    }
1948
1949                    if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1950                    {
1951                        status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1952                    }
1953                }
1954            }
1955
1956            // The super loop above ensures that the length16burst is below 256.
1957            if (length16burst > 0)
1958            {
1959                uint32_t loopcount = length16burst;
1960                length16burst = 0;
1961
1962                dprintf("DMA[R->M]:   Looping %lux 16 burst length transfer(s).\n", loopcount);
1963
1964                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1965                {
1966                    status = alt_dma_program_DMALP(program, loopcount);
1967                }
1968                if (status == ALT_E_SUCCESS)
1969                {
1970                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1971                }
1972                if (status == ALT_E_SUCCESS)
1973                {
1974                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1975                }
1976                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1977                {
1978                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1979                }
1980            }
1981        }
1982
1983        // At this point, we should have [countleft] transfer(s) remaining.
1984        // [countleft] should be less than 16.
1985
1986        if (countleft)
1987        {
1988            dprintf("DMA[R->M]:   Tail end %lux transfer(s).\n", countleft);
1989
1990            // Program in the following parameters:
1991            //  - SAF (Source      address fixed)
1992            //  - SSx (Source      burst size of [ccr_ss_ds_mask])
1993            //  - DSx (Destination burst size of [ccr_ss_ds_mask])
1994            //  - SBx (Source      burst length of [countleft] transfer(s))
1995            //  - DBx (Destination burst length of [countleft] transfer(s))
1996            //  - All other options default.
1997
1998            if (status == ALT_E_SUCCESS)
1999            {
2000                status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2001                                                (   ccr_ss_ds_mask
2002                                                  | ((countleft - 1) << 4) // SB
2003                                                  | ALT_DMA_CCR_OPT_SAF
2004                                                  | ALT_DMA_CCR_OPT_SP_DEFAULT
2005                                                  | ALT_DMA_CCR_OPT_SC_DEFAULT
2006                                                  | ((countleft - 1) << 18) // DB
2007                                                  | ALT_DMA_CCR_OPT_DA_DEFAULT
2008                                                  | ALT_DMA_CCR_OPT_DP_DEFAULT
2009                                                  | ALT_DMA_CCR_OPT_DC_DEFAULT
2010                                                  | ALT_DMA_CCR_OPT_ES_DEFAULT
2011                                                )
2012                    );
2013            }
2014
2015            if (status == ALT_E_SUCCESS)
2016            {
2017                status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2018            }
2019            if (status == ALT_E_SUCCESS)
2020            {
2021                status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2022            }
2023        }
2024
2025    } // if (count != 0)
2026
2027    // Send event if requested.
2028    if (send_evt)
2029    {
2030        if (status == ALT_E_SUCCESS)
2031        {
2032            dprintf("DMA[R->M]: Adding event ...\n");
2033            status = alt_dma_program_DMASEV(program, evt);
2034        }
2035    }
2036
2037    // Now that everything is done, end the program.
2038    if (status == ALT_E_SUCCESS)
2039    {
2040        status = alt_dma_program_DMAEND(program);
2041    }
2042
2043    // If there was a problem assembling the program, clean up the buffer and exit.
2044    if (status != ALT_E_SUCCESS)
2045    {
2046        // Do not report the status for the clear operation. A failure should be
2047        // reported regardless of if the clear is successful.
2048        alt_dma_program_clear(program);
2049        return status;
2050    }
2051
2052    // Execute the program on the given channel.
2053    return alt_dma_channel_exec(channel, program);
2054}
2055
2056#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
2057static ALT_STATUS_CODE alt_dma_memory_to_qspi(ALT_DMA_PROGRAM_t * program,
2058                                              const char * src,
2059                                              size_t size)
2060{
2061    if ((uintptr_t)src & 0x3)
2062    {
2063        return ALT_E_ERROR;
2064    }
2065
2066    if (size & 0x3)
2067    {
2068        return ALT_E_ERROR;
2069    }
2070
2071    /////
2072
2073    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2074
2075    if (status == ALT_E_SUCCESS)
2076    {
2077        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
2078                                        (uint32_t)ALT_QSPIDATA_ADDR);
2079    }
2080    if (status == ALT_E_SUCCESS)
2081    {
2082        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
2083                                        (uint32_t)src);
2084    }
2085
2086    /////
2087
2088    uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2089    uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper);
2090    uint32_t qspi_burst_size_log2  = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper);
2091    uint32_t qspi_single_size      = 1 << qspi_single_size_log2;
2092    uint32_t qspi_burst_size       = 1 << qspi_burst_size_log2;
2093
2094    dprintf("DMA[M->P][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size);
2095
2096    // Because single transfers are equal or smaller than burst (and in the
2097    // smaller case, it is always a clean multiple), only the single size
2098    // check is needed for transfer composability.
2099    if (size & (qspi_single_size - 1))
2100    {
2101        dprintf("DMA[M->P][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n");
2102        return ALT_E_ERROR;
2103    }
2104
2105    /////
2106
2107    if ((uintptr_t)src & 0x7)
2108    {
2109        // Source address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned.
2110
2111        dprintf("DMA[M->P][QSPI]: Creating 1x 4-byte aligning transfer.\n");
2112
2113        if (status == ALT_E_SUCCESS)
2114        {
2115            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2116                                            (   ALT_DMA_CCR_OPT_SAI
2117                                              | ALT_DMA_CCR_OPT_SS32
2118                                              | ALT_DMA_CCR_OPT_SB1
2119                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2120                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2121                                              | ALT_DMA_CCR_OPT_DAF
2122                                              | ALT_DMA_CCR_OPT_DS32
2123                                              | ALT_DMA_CCR_OPT_DB1
2124                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2125                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2126                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2127                                            )
2128                );
2129        }
2130
2131        if (status == ALT_E_SUCCESS)
2132        {
2133            status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2134        }
2135
2136        if (status == ALT_E_SUCCESS)
2137        {
2138            status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2139        }
2140
2141        if (status == ALT_E_SUCCESS)
2142        {
2143            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2144        }
2145
2146        if (status == ALT_E_SUCCESS)
2147        {
2148            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2149        }
2150
2151        size -= sizeof(uint32_t);
2152    }
2153
2154    uint32_t qspi_single_count = 0;
2155    uint32_t qspi_burst_count  = size >> qspi_burst_size_log2;
2156
2157    // Use QSPI burst transfers if:
2158    //  - QSPI bursts are larger than QSPI singles [AND]
2159    //  - Size is large enough that at least 1 burst will be used.
2160
2161    if (   (qspi_burst_size_log2 > qspi_single_size_log2)
2162        && (qspi_burst_count != 0)
2163       )
2164    {
2165        // qspi_burst_count = size >> qspi_burst_size_log2;
2166        qspi_single_count   = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2;
2167
2168        dprintf("DMA[M->P][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count);
2169
2170        // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2171        uint32_t src_size_log2 = MIN(3, qspi_burst_size_log2);
2172
2173        uint32_t src_length   = 0;
2174        uint32_t src_multiple = 0;
2175
2176        if ((qspi_burst_size >> src_size_log2) <= 16)
2177        {
2178            src_length   = qspi_burst_size >> src_size_log2;
2179            src_multiple = 1;
2180        }
2181        else
2182        {
2183            src_length   = 16;
2184            src_multiple = (qspi_burst_size >> src_size_log2) >> 4; // divide by 16
2185
2186            if (src_multiple == 0)
2187            {
2188                dprintf("DEBUG[QSPI][B]: src_multiple is 0.\n");
2189                status = ALT_E_ERROR;
2190            }
2191        }
2192
2193        // uint32_t dst_length = 1; // dst_length is always 1 because the address is fixed.
2194        uint32_t dst_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t)
2195
2196        dprintf("DMA[M->P][QSPI][B]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n",
2197                32,                       1,          dst_multiple);
2198        dprintf("DMA[M->P][QSPI][B]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n",
2199                (1 << src_size_log2) * 8, src_length, src_multiple);
2200
2201        /////
2202
2203        // Program in the following parameters:
2204        //  - SAI  (Source      address increment)
2205        //  - SSx  (Source      burst size of [1 << src_size_log2]-bytes)
2206        //  - SBx  (Source      burst length of [src_length] transfer(s))
2207        //  - DAF  (Destination address fixed)
2208        //  - DS32 (Destination burst size of 4-bytes)
2209        //  - DB1  (Destination burst length of 1 transfer)
2210        //  - All other parameters default
2211
2212        if (status == ALT_E_SUCCESS)
2213        {
2214            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2215                                            (   ALT_DMA_CCR_OPT_SAI
2216                                              | (src_size_log2 << 1) // SS
2217                                              | ((src_length - 1) << 4) // SB
2218                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2219                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2220                                              | ALT_DMA_CCR_OPT_DAF
2221                                              | ALT_DMA_CCR_OPT_DS32
2222                                              | ALT_DMA_CCR_OPT_DB1
2223                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2224                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2225                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2226                                            )
2227                );
2228        }
2229
2230        // NOTE: We do not do the 256x bursts for M->P case because we only
2231        //   write up to 256 B at a time.
2232
2233        while (qspi_burst_count > 0)
2234        {
2235            if (status != ALT_E_SUCCESS)
2236            {
2237                break;
2238            }
2239
2240            uint32_t loopcount = MIN(qspi_burst_count, 256);
2241            qspi_burst_count -= loopcount;
2242
2243            dprintf("DMA[M->P][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount);
2244
2245            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2246            {
2247                status = alt_dma_program_DMALP(program, loopcount);
2248            }
2249
2250            if (status == ALT_E_SUCCESS)
2251            {
2252                status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2253            }
2254            if (status == ALT_E_SUCCESS)
2255            {
2256                status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2257            }
2258            for (uint32_t j = 0; j < src_multiple; ++j)
2259            {
2260                if (status == ALT_E_SUCCESS)
2261                {
2262                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2263                }
2264            }
2265            for (uint32_t k = 0; k < dst_multiple; ++k)
2266            {
2267                if (status == ALT_E_SUCCESS)
2268                {
2269                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2270                }
2271            }
2272
2273            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2274            {
2275                status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2276            }
2277        }
2278    }
2279    else
2280    {
2281        qspi_single_count = size >> qspi_single_size_log2;
2282    }
2283
2284    // Assemble the single portion of the DMA program.
2285    if (qspi_single_count)
2286    {
2287        dprintf("DMA[M->P][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count);
2288
2289        // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2290        uint32_t src_size_log2 = MIN(3, qspi_single_size_log2);
2291
2292        uint32_t src_length   = 0;
2293        uint32_t src_multiple = 0;
2294
2295        if ((qspi_single_size >> src_size_log2) <= 16)
2296        {
2297            src_length   = qspi_single_size >> src_size_log2;
2298            src_multiple = 1;
2299        }
2300        else
2301        {
2302            src_length   = 16;
2303            src_multiple = (qspi_single_size >> src_size_log2) >> 4; // divide by 16
2304
2305            if (src_multiple == 0)
2306            {
2307                dprintf("DEBUG[QSPI][S]: src_multiple is 0.\n");
2308                status = ALT_E_ERROR;
2309            }
2310        }
2311
2312        // uint32_t dst_length = 1; // dst_length is always 1 becaus the address is fixed.
2313        uint32_t dst_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t)
2314
2315        dprintf("DMA[M->P][QSPI][S]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n",
2316                32,                      1,          dst_multiple);
2317        dprintf("DMA[M->P][QSPI][S]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n",
2318                (1 <<src_size_log2) * 8, src_length, src_multiple);
2319
2320        /////
2321
2322        // Program in the following parameters:
2323        //  - SAI  (Source      address increment)
2324        //  - SSx  (Source      burst size of [1 << src_size_log2]-bytes)
2325        //  - SBx  (Source      burst length of [src_length] transfer(s))
2326        //  - DAF  (Destination address fixed)
2327        //  - DS32 (Destination burst size of 4-bytes)
2328        //  - DB1  (Destination burst length of 1 transfer)
2329        //  - All other parameters default
2330
2331        if (status == ALT_E_SUCCESS)
2332        {
2333            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2334                                            (   ALT_DMA_CCR_OPT_SAI
2335                                              | (src_size_log2 << 1) // SS
2336                                              | ((src_length - 1) << 4) // SB
2337                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2338                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2339                                              | ALT_DMA_CCR_OPT_DAF
2340                                              | ALT_DMA_CCR_OPT_DS32
2341                                              | ALT_DMA_CCR_OPT_DB1
2342                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2343                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2344                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2345                                            )
2346                );
2347        }
2348
2349        // NOTE: We do not do the 256x bursts for M->P case because we only
2350        //   write up to 256 B at a time.
2351
2352        while (qspi_single_count > 0)
2353        {
2354            if (status != ALT_E_SUCCESS)
2355            {
2356                break;
2357            }
2358
2359            uint32_t loopcount = MIN(qspi_single_count, 256);
2360            qspi_single_count -= loopcount;
2361
2362            dprintf("DMA[M->P][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount);
2363
2364            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2365            {
2366                status = alt_dma_program_DMALP(program, loopcount);
2367            }
2368
2369            if (status == ALT_E_SUCCESS)
2370            {
2371                status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2372            }
2373            if (status == ALT_E_SUCCESS)
2374            {
2375                status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2376            }
2377            for (uint32_t j = 0; j < src_multiple; ++j)
2378            {
2379                if (status == ALT_E_SUCCESS)
2380                {
2381                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2382                }
2383            }
2384            for (uint32_t k = 0; k < dst_multiple; ++k)
2385            {
2386                if (status == ALT_E_SUCCESS)
2387                {
2388                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2389                }
2390            }
2391
2392            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2393            {
2394                status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2395            }
2396        }
2397
2398    } // if (qspi_single_count != 0)
2399
2400    return status;
2401}
2402
2403static ALT_STATUS_CODE alt_dma_qspi_to_memory(ALT_DMA_PROGRAM_t * program,
2404                                              char * dst,
2405                                              size_t size)
2406{
2407    if ((uintptr_t)dst & 0x3)
2408    {
2409        return ALT_E_ERROR;
2410    }
2411
2412    if (size & 0x3)
2413    {
2414        return ALT_E_ERROR;
2415    }
2416
2417    /////
2418
2419    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2420
2421    if (status == ALT_E_SUCCESS)
2422    {
2423        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
2424                                        (uint32_t)dst);
2425    }
2426    if (status == ALT_E_SUCCESS)
2427    {
2428        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
2429                                        (uint32_t)ALT_QSPIDATA_ADDR);
2430    }
2431
2432    /////
2433
2434    uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2435    uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper);
2436    uint32_t qspi_burst_size_log2  = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper);
2437    uint32_t qspi_single_size      = 1 << qspi_single_size_log2;
2438    uint32_t qspi_burst_size       = 1 << qspi_burst_size_log2;
2439
2440    dprintf("DMA[P->M][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size);
2441
2442    // Because single transfers are equal or smaller than burst (and in the
2443    // smaller case, it is always a clean multiple), only the single size
2444    // check is needed for transfer composability.
2445    if (size & (qspi_single_size - 1))
2446    {
2447        dprintf("DMA[P->M][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n");
2448        return ALT_E_ERROR;
2449    }
2450
2451    /////
2452
2453    if ((uintptr_t)dst & 0x7)
2454    {
2455        // Destination address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned.
2456
2457        dprintf("DMA[P->M][QSPI]: Creating 1x 4-byte aligning transfer.\n");
2458
2459        if (status == ALT_E_SUCCESS)
2460        {
2461            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2462                                            (   ALT_DMA_CCR_OPT_SAF
2463                                              | ALT_DMA_CCR_OPT_SS32
2464                                              | ALT_DMA_CCR_OPT_SB1
2465                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2466                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2467                                              | ALT_DMA_CCR_OPT_DAI
2468                                              | ALT_DMA_CCR_OPT_DS32
2469                                              | ALT_DMA_CCR_OPT_DB1
2470                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2471                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2472                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2473                                            )
2474                );
2475        }
2476
2477        if (status == ALT_E_SUCCESS)
2478        {
2479            status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2480        }
2481
2482        if (status == ALT_E_SUCCESS)
2483        {
2484            status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2485        }
2486
2487        if (status == ALT_E_SUCCESS)
2488        {
2489            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2490        }
2491
2492        if (status == ALT_E_SUCCESS)
2493        {
2494            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2495        }
2496
2497        size -= sizeof(uint32_t);
2498    }
2499
2500    uint32_t qspi_single_count = 0;
2501    uint32_t qspi_burst_count  = size >> qspi_burst_size_log2;
2502
2503    // Use QSPI burst transfers if:
2504    //  - QSPI bursts are larger than QSPI singles [AND]
2505    //  - Size is large enough that at least 1 burst will be used.
2506
2507    if (   (qspi_burst_size_log2 > qspi_single_size_log2)
2508        && (qspi_burst_count != 0)
2509       )
2510    {
2511        // qspi_burst_count = size >> qspi_burst_size_log2;
2512        qspi_single_count   = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2;
2513
2514        dprintf("DMA[P->M][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count);
2515
2516        // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2517        uint32_t dst_size_log2 = MIN(3, qspi_burst_size_log2);
2518
2519        uint32_t dst_length   = 0;
2520        uint32_t dst_multiple = 0;
2521
2522        if ((qspi_burst_size >> dst_size_log2) <= 16)
2523        {
2524            dst_length   = qspi_burst_size >> dst_size_log2;
2525            dst_multiple = 1;
2526        }
2527        else
2528        {
2529            dst_length   = 16;
2530            dst_multiple = (qspi_burst_size >> dst_size_log2) >> 4; // divide by 16
2531
2532            if (dst_multiple == 0)
2533            {
2534                dprintf("DEBUG[QSPI][B]: dst_multiple is 0.\n");
2535                status = ALT_E_ERROR;
2536            }
2537        }
2538
2539        // uint32_t src_length = 1; // src_length is always 1 because the address is fixed.
2540        uint32_t src_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t)
2541
2542        dprintf("DMA[P->M][QSPI][B]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n", 
2543                (1 << dst_size_log2) * 8, dst_length, dst_multiple);
2544        dprintf("DMA[P->M][QSPI][B]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n",
2545                32,                       1,          src_multiple);
2546
2547        /////
2548
2549        // Program in the following parameters:
2550        //  - SAF  (Source      address fixed)
2551        //  - SS32 (Source      burst size of 4-bytes)
2552        //  - SB1  (Source      burst length of 1 transfer)
2553        //  - DAI  (Destination address increment)
2554        //  - DSx  (Destination burst size of [1 << dst_size_log2]-bytes])
2555        //  - DBx  (Destination burst length of [dst_length] transfer(s))
2556        //  - All other parameters default
2557
2558        if (status == ALT_E_SUCCESS)
2559        {
2560            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2561                                            (   ALT_DMA_CCR_OPT_SAF
2562                                              | ALT_DMA_CCR_OPT_SS32
2563                                              | ALT_DMA_CCR_OPT_SB1
2564                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2565                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2566                                              | ALT_DMA_CCR_OPT_DAI
2567                                              | (dst_size_log2 << 15) // DS
2568                                              | ((dst_length - 1) << 18) // DB
2569                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2570                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2571                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2572                                            )
2573                );
2574        }
2575
2576        // See how many 256x bursts we can construct. This will allow for extremely large requests.
2577
2578        if (qspi_burst_count >> 8)
2579        {
2580            uint32_t qspi_burst256_count = qspi_burst_count >> 8;
2581            qspi_burst_count &= (1 << 8) - 1;
2582
2583            while (qspi_burst256_count > 0)
2584            {
2585                if (status != ALT_E_SUCCESS)
2586                {
2587                    break;
2588                }
2589
2590                uint32_t loopcount = MIN(qspi_burst256_count, 256);
2591                qspi_burst256_count -= loopcount;
2592
2593                dprintf("DMA[P->M][QSPI][B]: Creating %lu 256x burst-type transfer(s).\n", loopcount);
2594
2595                // Outer loop {
2596
2597                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2598                {
2599                    status = alt_dma_program_DMALP(program, loopcount);
2600                }
2601
2602                // Inner loop {
2603
2604                if (status == ALT_E_SUCCESS)
2605                {
2606                    status = alt_dma_program_DMALP(program, 256);
2607                }
2608
2609                if (status == ALT_E_SUCCESS)
2610                {
2611                    status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2612                }
2613                if (status == ALT_E_SUCCESS)
2614                {
2615                    status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2616                }
2617                for (uint32_t j = 0; j < src_multiple; ++j)
2618                {
2619                    if (status == ALT_E_SUCCESS)
2620                    {
2621                        status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2622                    }
2623                }
2624                for (uint32_t k = 0; k < dst_multiple; ++k)
2625                {
2626                    if (status == ALT_E_SUCCESS)
2627                    {
2628                        status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2629                    }
2630                }
2631
2632                if (status == ALT_E_SUCCESS)
2633                {
2634                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2635                }
2636
2637                // } Inner loop
2638
2639                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2640                {
2641                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2642                }
2643
2644                // } Outer loop
2645            }
2646        }
2647
2648        while (qspi_burst_count > 0)
2649        {
2650            if (status != ALT_E_SUCCESS)
2651            {
2652                break;
2653            }
2654
2655            uint32_t loopcount = MIN(qspi_burst_count, 256);
2656            qspi_burst_count -= loopcount;
2657
2658            dprintf("DMA[P->M][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount);
2659
2660            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2661            {
2662                status = alt_dma_program_DMALP(program, loopcount);
2663            }
2664
2665            if (status == ALT_E_SUCCESS)
2666            {
2667                status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2668            }
2669            if (status == ALT_E_SUCCESS)
2670            {
2671                status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2672            }
2673            for (uint32_t j = 0; j < src_multiple; ++j)
2674            {
2675                if (status == ALT_E_SUCCESS)
2676                {
2677                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2678                }
2679            }
2680            for (uint32_t k = 0; k < dst_multiple; ++k)
2681            {
2682                if (status == ALT_E_SUCCESS)
2683                {
2684                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2685                }
2686            }
2687
2688            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2689            {
2690                status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2691            }
2692        }
2693    }
2694    else
2695    {
2696        qspi_single_count = size >> qspi_single_size_log2;
2697    }
2698
2699    // Assemble the single portion of the DMA program.
2700    if (qspi_single_count)
2701    {
2702        dprintf("DMA[P->M][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count);
2703
2704        // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2705        uint32_t dst_size_log2 = MIN(3, qspi_single_size_log2);
2706
2707        uint32_t dst_length   = 0;
2708        uint32_t dst_multiple = 0;
2709
2710        if ((qspi_single_size >> dst_size_log2) <= 16)
2711        {
2712            dst_length   = qspi_single_size >> dst_size_log2;
2713            dst_multiple = 1;
2714        }
2715        else
2716        {
2717            dst_length   = 16;
2718            dst_multiple = (qspi_single_size >> dst_size_log2) >> 4; // divide by 16
2719
2720            if (dst_multiple == 0)
2721            {
2722                dprintf("DEBUG[QSPI][S]: dst_multiple is 0.\n");
2723                status = ALT_E_ERROR;
2724            }
2725        }
2726
2727        // uint32_t src_length = 1; // src_length is always 1 because the address is fixed.
2728        uint32_t src_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t)
2729
2730        dprintf("DMA[P->M][QSPI][S]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n",
2731                (1 << dst_size_log2) * 8, dst_length, dst_multiple);
2732        dprintf("DMA[P->M][QSPI][S]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n",
2733                32,                       1,          src_multiple);
2734
2735        /////
2736
2737        // Program in the following parameters:
2738        //  - SAF  (Source      address fixed)
2739        //  - SS32 (Source      burst size of 4-bytes)
2740        //  - SB1  (Source      burst length of 1 transfer)
2741        //  - DAI  (Destination address increment)
2742        //  - DSx  (Destination burst size of [1 << dst_size_log2]-bytes])
2743        //  - DBx  (Destination burst length of [dst_length] transfer(s))
2744        //  - All other parameters default
2745
2746        if (status == ALT_E_SUCCESS)
2747        {
2748            status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2749                                            (   ALT_DMA_CCR_OPT_SAF
2750                                              | ALT_DMA_CCR_OPT_SS32
2751                                              | ALT_DMA_CCR_OPT_SB1
2752                                              | ALT_DMA_CCR_OPT_SP_DEFAULT
2753                                              | ALT_DMA_CCR_OPT_SC_DEFAULT
2754                                              | ALT_DMA_CCR_OPT_DAI
2755                                              | (dst_size_log2 << 15) // DS
2756                                              | ((dst_length - 1) << 18) // DB
2757                                              | ALT_DMA_CCR_OPT_DP_DEFAULT
2758                                              | ALT_DMA_CCR_OPT_DC_DEFAULT
2759                                              | ALT_DMA_CCR_OPT_ES_DEFAULT
2760                                            )
2761                );
2762        }
2763
2764        // See how many 256x bursts we can construct. This will allow for extremely large requests.
2765
2766        if (qspi_single_count >> 8)
2767        {
2768            uint32_t qspi_single256_count = qspi_single_count >> 8;
2769            qspi_single_count &= (1 << 8) - 1;
2770
2771            while (qspi_single256_count > 0)
2772            {
2773                if (status != ALT_E_SUCCESS)
2774                {
2775                    break;
2776                }
2777
2778                uint32_t loopcount = MIN(qspi_single256_count, 256);
2779                qspi_single256_count -= loopcount;
2780
2781                dprintf("DMA[P->M][QSPI][S]: Creating %lu 256x single-type transfer(s).\n", loopcount);
2782
2783                // Outer loop {
2784
2785                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2786                {
2787                    status = alt_dma_program_DMALP(program, loopcount);
2788                }
2789
2790                // Inner loop {
2791
2792                if (status == ALT_E_SUCCESS)
2793                {
2794                    status = alt_dma_program_DMALP(program, 256);
2795                }
2796
2797                if (status == ALT_E_SUCCESS)
2798                {
2799                    status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2800                }
2801                if (status == ALT_E_SUCCESS)
2802                {
2803                    status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2804                }
2805                for (uint32_t j = 0; j < src_multiple; ++j)
2806                {
2807                    if (status == ALT_E_SUCCESS)
2808                    {
2809                        status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2810                    }
2811                }
2812                for (uint32_t k = 0; k < dst_multiple; ++k)
2813                {
2814                    if (status == ALT_E_SUCCESS)
2815                    {
2816                        status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2817                    }
2818                }
2819
2820                if (status == ALT_E_SUCCESS)
2821                {
2822                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2823                }
2824
2825                // } Inner loop
2826
2827                if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2828                {
2829                    status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2830                }
2831
2832                // } Outer loop
2833            }
2834        }
2835
2836        while (qspi_single_count > 0)
2837        {
2838            if (status != ALT_E_SUCCESS)
2839            {
2840                break;
2841            }
2842
2843            uint32_t loopcount = MIN(qspi_single_count, 256);
2844            qspi_single_count -= loopcount;
2845
2846            dprintf("DMA[P->M][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount);
2847
2848            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2849            {
2850                status = alt_dma_program_DMALP(program, loopcount);
2851            }
2852
2853            if (status == ALT_E_SUCCESS)
2854            {
2855                status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2856            }
2857            if (status == ALT_E_SUCCESS)
2858            {
2859                status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2860            }
2861            for (uint32_t j = 0; j < src_multiple; ++j)
2862            {
2863                if (status == ALT_E_SUCCESS)
2864                {
2865                    status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2866                }
2867            }
2868            for (uint32_t k = 0; k < dst_multiple; ++k)
2869            {
2870                if (status == ALT_E_SUCCESS)
2871                {
2872                    status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2873                }
2874            }
2875
2876            if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2877            {
2878                status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2879            }
2880        }
2881
2882    } // if (qspi_single_count != 0)
2883
2884    return status;
2885}
2886#endif // ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
2887
2888#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
2889static ALT_STATUS_CODE alt_dma_memory_to_16550_single(ALT_DMA_PROGRAM_t * program,
2890                                                      ALT_DMA_PERIPH_t periph,
2891                                                      size_t size)
2892{
2893    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2894
2895    // Program in the following parameters:
2896    //  - SS8 (Source      burst size of 1-byte)
2897    //  - DS8 (Destination burst size of 1-byte)
2898    //  - SB1 (Source      burst length of 1 transfer)
2899    //  - DB1 (Destination burst length of 1 transfer)
2900    //  - DAF (Destination address fixed)
2901    //  - All other options default.
2902
2903    if (status == ALT_E_SUCCESS)
2904    {
2905        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2906                                        (   ALT_DMA_CCR_OPT_SB1
2907                                          | ALT_DMA_CCR_OPT_SS8
2908                                          | ALT_DMA_CCR_OPT_SA_DEFAULT
2909                                          | ALT_DMA_CCR_OPT_SP_DEFAULT
2910                                          | ALT_DMA_CCR_OPT_SC_DEFAULT
2911                                          | ALT_DMA_CCR_OPT_DB1
2912                                          | ALT_DMA_CCR_OPT_DS8
2913                                          | ALT_DMA_CCR_OPT_DAF
2914                                          | ALT_DMA_CCR_OPT_DP_DEFAULT
2915                                          | ALT_DMA_CCR_OPT_DC_DEFAULT
2916                                          | ALT_DMA_CCR_OPT_ES_DEFAULT
2917                                        )
2918            );
2919    }
2920
2921    uint32_t sizeleft = size;
2922
2923    while (sizeleft > 0)
2924    {
2925        if (status != ALT_E_SUCCESS)
2926        {
2927            break;
2928        }
2929
2930        uint32_t loopcount = MIN(sizeleft, 256);
2931        sizeleft -= loopcount;
2932
2933        dprintf("DMA[M->P][16550][S]: Creating %lu transfer(s).\n", loopcount);
2934
2935        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2936        {
2937            status = alt_dma_program_DMALP(program, loopcount);
2938        }
2939
2940        if (status == ALT_E_SUCCESS)
2941        {
2942            status = alt_dma_program_DMAFLUSHP(program, periph);
2943        }
2944        if (status == ALT_E_SUCCESS)
2945        {
2946            status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2947        }
2948        if (status == ALT_E_SUCCESS)
2949        {
2950            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2951        }
2952        if (status == ALT_E_SUCCESS)
2953        {
2954            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2955        }
2956
2957        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2958        {
2959            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2960        }
2961    }
2962
2963    return status;
2964}
2965
2966static ALT_STATUS_CODE alt_dma_memory_to_16550_burst(ALT_DMA_PROGRAM_t * program,
2967                                                     ALT_DMA_PERIPH_t periph,
2968                                                     size_t burst_size,
2969                                                     size_t burst_count)
2970{
2971    ALT_STATUS_CODE status = ALT_E_SUCCESS;
2972
2973    // Program in the following parameters:
2974    //  - SS8  (Source      burst size of 1-byte)
2975    //  - DS8  (Destination burst size of 1-byte)
2976    //  - SB16 (Source      burst length of 16 transfers)
2977    //  - DB16 (Destination burst length of 16 transfers)
2978    //  - DAF  (Source      address fixed)
2979    //  - All other options default.
2980
2981    if (status == ALT_E_SUCCESS)
2982    {
2983        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2984                                        (   ALT_DMA_CCR_OPT_SB16
2985                                          | ALT_DMA_CCR_OPT_SS8
2986                                          | ALT_DMA_CCR_OPT_SA_DEFAULT
2987                                          | ALT_DMA_CCR_OPT_SP_DEFAULT
2988                                          | ALT_DMA_CCR_OPT_SC_DEFAULT
2989                                          | ALT_DMA_CCR_OPT_DB16
2990                                          | ALT_DMA_CCR_OPT_DS8
2991                                          | ALT_DMA_CCR_OPT_DAF
2992                                          | ALT_DMA_CCR_OPT_DP_DEFAULT
2993                                          | ALT_DMA_CCR_OPT_DC_DEFAULT
2994                                          | ALT_DMA_CCR_OPT_ES_DEFAULT
2995                                        )
2996            );
2997    }
2998
2999    while (burst_count > 0)
3000    {
3001        if (status != ALT_E_SUCCESS)
3002        {
3003            break;
3004        }
3005
3006        uint32_t loopcount = MIN(burst_count, 256);
3007        burst_count -= loopcount;
3008
3009        dprintf("DMA[M->P][16550][B]: Creating outer %lu inner loop(s).\n", loopcount);
3010
3011        // Outer loop {
3012
3013        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3014        {
3015            status = alt_dma_program_DMALP(program, loopcount);
3016        }
3017        if (status == ALT_E_SUCCESS)
3018        {
3019            status = alt_dma_program_DMAFLUSHP(program, periph);
3020        }
3021        if (status == ALT_E_SUCCESS)
3022        {
3023            status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST);
3024        }
3025
3026        // Inner loop {
3027
3028        // Loop [burst_size / 16] times. The burst_size was trimmed to the
3029        // nearest multiple of 16 by the caller. Each burst does 16 transfers
3030        // hence the need for the divide.
3031
3032        dprintf("DMA[M->P][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4);
3033
3034        if (status == ALT_E_SUCCESS)
3035        {
3036            status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16.
3037        }
3038        if (status == ALT_E_SUCCESS)
3039        {
3040            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3041        }
3042        if (status == ALT_E_SUCCESS)
3043        {
3044            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3045        }
3046        if (status == ALT_E_SUCCESS)
3047        {
3048            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3049        }
3050
3051        // } Inner loop
3052
3053        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3054        {
3055            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3056        }
3057
3058        // } Outer loop
3059    }
3060
3061    return status;
3062}
3063
3064static ALT_STATUS_CODE alt_dma_memory_to_16550(ALT_DMA_PROGRAM_t * program,
3065                                               ALT_DMA_PERIPH_t periph,
3066                                               ALT_16550_HANDLE_t * handle,
3067                                               const void * src,
3068                                               size_t size)
3069{
3070    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3071
3072    if (status == ALT_E_SUCCESS)
3073    {
3074        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
3075                                        (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location));
3076    }
3077    if (status == ALT_E_SUCCESS)
3078    {
3079        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
3080                                        (uint32_t)src);
3081    }
3082
3083    // Determine if FIFOs are enabled from the FCR cache
3084
3085    if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0)
3086    {
3087        dprintf("DMA[M->P][16550]: FIFOs enabled.\n");
3088
3089        //
3090        // FIFOs are enabled.
3091        //
3092
3093        uint32_t tx_size;
3094        uint32_t burst_size;
3095        ALT_16550_FIFO_TRIGGER_TX_t trig_tx;
3096
3097        // Get the TX FIFO Size
3098        // Use the register interface to avoid coupling the 16550 and DMA.
3099        tx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
3100
3101        // Get the TX FIFO Trigger Level from the FCR cache
3102        trig_tx = (ALT_16550_FIFO_TRIGGER_TX_t)ALT_UART_FCR_TET_GET(handle->fcr);
3103
3104        switch (trig_tx)
3105        {
3106        case ALT_16550_FIFO_TRIGGER_TX_EMPTY:
3107            burst_size = tx_size;
3108            break;
3109        case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY:
3110            burst_size = tx_size - 2;
3111            break;
3112        case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL:
3113            burst_size = 3 * (tx_size >> 2);
3114            break;
3115        case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL:
3116            burst_size = tx_size >> 1;
3117            break;
3118        default:
3119            // This case should never happen.
3120            return ALT_E_ERROR;
3121        }
3122
3123        if (burst_size < 16)
3124        {
3125            // There's no point bursting 1 byte at a time per notify, so just do single transfers.
3126            if (status == ALT_E_SUCCESS)
3127            {
3128                status = alt_dma_memory_to_16550_single(program,
3129                                                        periph,
3130                                                        size);
3131            }
3132        }
3133        else
3134        {
3135            uint32_t sizeleft = size;
3136
3137            // Now trip the burst size to a multiple of 16.
3138            // This will optimize the bursting in the fewest possible commands.
3139            dprintf("DMA[M->P][16550]: Untrimmed burst size = %lu.\n", burst_size);
3140            burst_size &= ~0xf;
3141            dprintf("DMA[M->P][16550]: Trimmed burst size   = %lu.\n", burst_size);
3142
3143            // Determine how many burst transfers can be done
3144            uint32_t burst_count = 0;
3145
3146            burst_count = sizeleft / burst_size;
3147            sizeleft -= burst_count * burst_size;
3148
3149            if (burst_count == 0)
3150            {
3151                // Do the transfer
3152                if (status == ALT_E_SUCCESS)
3153                {
3154                    status = alt_dma_memory_to_16550_single(program,
3155                                                            periph,
3156                                                            sizeleft);
3157                }
3158            }
3159            else
3160            {
3161                // Do the burst transfers
3162                if (status == ALT_E_SUCCESS)
3163                {
3164                    status = alt_dma_memory_to_16550_burst(program,
3165                                                           periph,
3166                                                           burst_size,
3167                                                           burst_count);
3168                }
3169
3170                // Program the DMA engine to transfer the non-burstable items in single tranfers
3171                if (status == ALT_E_SUCCESS)
3172                {
3173                    status = alt_dma_memory_to_16550_single(program,
3174                                                            periph,
3175                                                            sizeleft);
3176                }
3177
3178            } // else if (burst_count == 0)
3179        }
3180    }
3181    else
3182    {
3183        dprintf("DMA[M->P][16550]: FIFOs disabled.\n");
3184
3185        //
3186        // FIFOs are disabled.
3187        //
3188
3189        status = alt_dma_memory_to_16550_single(program,
3190                                                periph,
3191                                                size);
3192    }
3193
3194    return status;
3195}
3196
3197static ALT_STATUS_CODE alt_dma_16550_to_memory_single(ALT_DMA_PROGRAM_t * program,
3198                                                      ALT_DMA_PERIPH_t periph,
3199                                                      size_t size)
3200{
3201    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3202
3203    // Program in the following parameters:
3204    //  - SS8 (Source      burst size of 1-byte)
3205    //  - DS8 (Destination burst size of 1-byte)
3206    //  - SB1 (Source      burst length of 1 transfer)
3207    //  - DB1 (Destination burst length of 1 transfer)
3208    //  - SAF (Source      address fixed)
3209    //  - All other options default.
3210
3211    if (status == ALT_E_SUCCESS)
3212    {
3213        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
3214                                        (   ALT_DMA_CCR_OPT_SB1
3215                                          | ALT_DMA_CCR_OPT_SS8
3216                                          | ALT_DMA_CCR_OPT_SAF
3217                                          | ALT_DMA_CCR_OPT_SP_DEFAULT
3218                                          | ALT_DMA_CCR_OPT_SC_DEFAULT
3219                                          | ALT_DMA_CCR_OPT_DB1
3220                                          | ALT_DMA_CCR_OPT_DS8
3221                                          | ALT_DMA_CCR_OPT_DA_DEFAULT
3222                                          | ALT_DMA_CCR_OPT_DP_DEFAULT
3223                                          | ALT_DMA_CCR_OPT_DC_DEFAULT
3224                                          | ALT_DMA_CCR_OPT_ES_DEFAULT
3225                                        )
3226            );
3227    }
3228
3229    uint32_t sizeleft = size;
3230
3231    while (sizeleft > 0)
3232    {
3233        if (status != ALT_E_SUCCESS)
3234        {
3235            break;
3236        }
3237
3238        uint32_t loopcount = MIN(sizeleft, 256);
3239        sizeleft -= loopcount;
3240
3241        dprintf("DMA[P->M][16550][S]: Creating %lu transfer(s).\n", loopcount);
3242
3243        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3244        {
3245            status = alt_dma_program_DMALP(program, loopcount);
3246        }
3247        if (status == ALT_E_SUCCESS)
3248        {
3249            status = alt_dma_program_DMAFLUSHP(program, periph);
3250        }
3251        if (status == ALT_E_SUCCESS)
3252        {
3253            status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3254        }
3255        if (status == ALT_E_SUCCESS)
3256        {
3257            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3258        }
3259        if (status == ALT_E_SUCCESS)
3260        {
3261            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3262        }
3263        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3264        {
3265            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3266        }
3267    }
3268
3269    return status;
3270}                                             
3271
3272static ALT_STATUS_CODE alt_dma_16550_to_memory_burst(ALT_DMA_PROGRAM_t * program,
3273                                                     ALT_DMA_PERIPH_t periph,
3274                                                     size_t burst_size,
3275                                                     size_t burst_count)
3276{
3277    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3278
3279    // Program in the following parameters:
3280    //  - SS8  (Source      burst size of 1-byte)
3281    //  - DS8  (Destination burst size of 1-byte)
3282    //  - SB16 (Source      burst length of 16 transfers)
3283    //  - DB16 (Destination burst length of 16 transfers)
3284    //  - SAF  (Source      address fixed)
3285    //  - All other options default.
3286
3287    if (status == ALT_E_SUCCESS)
3288    {
3289        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
3290                                        (   ALT_DMA_CCR_OPT_SB16
3291                                          | ALT_DMA_CCR_OPT_SS8
3292                                          | ALT_DMA_CCR_OPT_SAF
3293                                          | ALT_DMA_CCR_OPT_SP_DEFAULT
3294                                          | ALT_DMA_CCR_OPT_SC_DEFAULT
3295                                          | ALT_DMA_CCR_OPT_DB16
3296                                          | ALT_DMA_CCR_OPT_DS8
3297                                          | ALT_DMA_CCR_OPT_DA_DEFAULT
3298                                          | ALT_DMA_CCR_OPT_DP_DEFAULT
3299                                          | ALT_DMA_CCR_OPT_DC_DEFAULT
3300                                          | ALT_DMA_CCR_OPT_ES_DEFAULT
3301                                        )
3302            );
3303    }
3304
3305    while (burst_count > 0)
3306    {
3307        if (status != ALT_E_SUCCESS)
3308        {
3309            break;
3310        }
3311
3312        uint32_t loopcount = MIN(burst_count, 256);
3313        burst_count -= loopcount;
3314
3315        dprintf("DMA[P->M][16550][B]: Creating outer %lu inner loop(s).\n", loopcount);
3316
3317        // Outer loop {
3318
3319        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3320        {
3321            status = alt_dma_program_DMALP(program, loopcount);
3322        }
3323        if (status == ALT_E_SUCCESS)
3324        {
3325            status = alt_dma_program_DMAFLUSHP(program, periph);
3326        }
3327        if (status == ALT_E_SUCCESS)
3328        {
3329            status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST);
3330        }
3331
3332        // Inner loop {
3333
3334        // Loop [burst_size / 16] times. The burst_size was trimmed to the
3335        // nearest multiple of 16 by the caller. Each burst does 16 transfers
3336        // hence the need for the divide.
3337
3338        dprintf("DMA[P->M][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4);
3339
3340        if (status == ALT_E_SUCCESS)
3341        {
3342            status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16.
3343        }
3344        if (status == ALT_E_SUCCESS)
3345        {
3346            status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3347        }
3348        if (status == ALT_E_SUCCESS)
3349        {
3350            status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3351        }
3352        if (status == ALT_E_SUCCESS)
3353        {
3354            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3355        }
3356
3357        // } Inner loop
3358
3359        if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3360        {
3361            status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3362        }
3363
3364        // } Outer loop
3365    }
3366
3367    return status;
3368}
3369
3370static ALT_STATUS_CODE alt_dma_16550_to_memory(ALT_DMA_PROGRAM_t * program,
3371                                               ALT_DMA_PERIPH_t periph,
3372                                               ALT_16550_HANDLE_t * handle,
3373                                               void * dst,
3374                                               size_t size)
3375{
3376    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3377
3378    if (status == ALT_E_SUCCESS)
3379    {
3380        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst);
3381    }
3382    if (status == ALT_E_SUCCESS)
3383    {
3384        status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location));
3385    }
3386
3387    // Determine if FIFOs are enabled from the FCR cache
3388
3389    if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0)
3390    {
3391        dprintf("DMA[P->M][16550]: FIFOs enabled.\n");
3392
3393        //
3394        // FIFOs are enabled.
3395        //
3396
3397        uint32_t rx_size;
3398        uint32_t burst_size;
3399        ALT_16550_FIFO_TRIGGER_RX_t trig_rx;
3400
3401        // Get the RX FIFO Size
3402        // Use the register interface to avoid coupling the 16550 and DMA.
3403        rx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
3404
3405        // Get the RX FIFO Trigger Level from the FCR cache
3406        trig_rx = (ALT_16550_FIFO_TRIGGER_RX_t)ALT_UART_FCR_RT_GET(handle->fcr);
3407
3408        switch (trig_rx)
3409        {
3410        case ALT_16550_FIFO_TRIGGER_RX_ANY:
3411            burst_size = 1;
3412            break;
3413        case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL:
3414            burst_size = rx_size >> 2; // divide by 4
3415            break;
3416        case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL:
3417            burst_size = rx_size >> 1; // divide by 2
3418            break;
3419        case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL:
3420            burst_size = rx_size - 2;
3421            break;
3422        default:
3423            // This case should never happen.
3424            return ALT_E_ERROR;
3425        }
3426
3427        if (burst_size < 16)
3428        {
3429            // There's no point bursting 1 byte at a time per notify, so just do single transfers.
3430            if (status == ALT_E_SUCCESS)
3431            {
3432                status = alt_dma_16550_to_memory_single(program,
3433                                                        periph,
3434                                                        size);
3435            }
3436        }
3437        else
3438        {
3439            uint32_t sizeleft = size;
3440
3441            // Now trim the burst size to a multiple of 16.
3442            // This will optimize the bursting in the fewest possible commands.
3443            dprintf("DMA[P->M][16550]: Untrimmed burst size = %lu.\n", burst_size);
3444            burst_size &= ~0xf;
3445            dprintf("DMA[P->M][16550]: Trimmed burst size   = %lu.\n", burst_size);
3446
3447            // Determine how many burst transfers can be done
3448            uint32_t burst_count = 0;
3449
3450            burst_count = sizeleft / burst_size;
3451            sizeleft -= burst_count * burst_size;
3452
3453            if (burst_count == 0)
3454            {
3455                // Do the transfer.
3456                if (status == ALT_E_SUCCESS)
3457                {
3458                    status = alt_dma_16550_to_memory_single(program,
3459                                                            periph,
3460                                                            sizeleft);
3461                }
3462            }
3463            else
3464            {
3465                // Do the burst transfers
3466                if (status == ALT_E_SUCCESS)
3467                {
3468                    status = alt_dma_16550_to_memory_burst(program,
3469                                                           periph,
3470                                                           burst_size,
3471                                                           burst_count);
3472                }
3473
3474                // Program the DMA engine to transfer the non-burstable items in single transfers.
3475                if (status == ALT_E_SUCCESS)
3476                {
3477                    status = alt_dma_16550_to_memory_single(program,
3478                                                            periph,
3479                                                            sizeleft);
3480                }
3481
3482            } // if (burst_count == 0)
3483        }
3484    }
3485    else
3486    {
3487        dprintf("DMA[P->M][16550]: FIFOs disabled.\n");
3488
3489        //
3490        // FIFOs are disabled.
3491        //
3492
3493        status = alt_dma_16550_to_memory_single(program,
3494                                                periph,
3495                                                size);
3496    }
3497
3498    return status;
3499}
3500#endif // ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3501
3502ALT_STATUS_CODE alt_dma_memory_to_periph(ALT_DMA_CHANNEL_t channel,
3503                                         ALT_DMA_PROGRAM_t * program,
3504                                         ALT_DMA_PERIPH_t dstp,
3505                                         const void * src,
3506                                         size_t size,
3507                                         void * periph_info,
3508                                         bool send_evt,
3509                                         ALT_DMA_EVENT_t evt)
3510{
3511    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3512
3513    if ((size == 0) && (send_evt == false))
3514    {
3515        return status;
3516    }
3517
3518    if (status == ALT_E_SUCCESS)
3519    {
3520        dprintf("DMA[M->P]: Init Program.\n");
3521        status = alt_dma_program_init(program);
3522    }
3523
3524    if ((status == ALT_E_SUCCESS) && (size != 0))
3525    {
3526        switch (dstp)
3527        {
3528#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
3529        case ALT_DMA_PERIPH_QSPI_FLASH_TX:
3530            status = alt_dma_memory_to_qspi(program, src, size);
3531            break;
3532#endif
3533
3534#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3535        case ALT_DMA_PERIPH_UART0_TX:
3536        case ALT_DMA_PERIPH_UART1_TX:
3537            status = alt_dma_memory_to_16550(program, dstp,
3538                                             (ALT_16550_HANDLE_t *)periph_info, src, size);
3539            break;
3540#endif
3541
3542        case ALT_DMA_PERIPH_FPGA_0:
3543        case ALT_DMA_PERIPH_FPGA_1:
3544        case ALT_DMA_PERIPH_FPGA_2:
3545        case ALT_DMA_PERIPH_FPGA_3:
3546        case ALT_DMA_PERIPH_FPGA_4:
3547        case ALT_DMA_PERIPH_FPGA_5:
3548        case ALT_DMA_PERIPH_FPGA_6:
3549        case ALT_DMA_PERIPH_FPGA_7:
3550        case ALT_DMA_PERIPH_I2C0_TX:
3551        case ALT_DMA_PERIPH_I2C1_TX:
3552        case ALT_DMA_PERIPH_I2C2_TX:
3553        case ALT_DMA_PERIPH_I2C3_TX:
3554        case ALT_DMA_PERIPH_SPI0_MASTER_TX:
3555        case ALT_DMA_PERIPH_SPI0_SLAVE_TX:
3556        case ALT_DMA_PERIPH_SPI1_MASTER_TX:
3557        case ALT_DMA_PERIPH_SPI1_SLAVE_TX:
3558
3559        default:
3560            status = ALT_E_BAD_ARG;
3561            break;
3562        }
3563    }
3564
3565    // Send event if requested.
3566    if (send_evt)
3567    {
3568        if (status == ALT_E_SUCCESS)
3569        {
3570            dprintf("DMA[M->P]: Adding event.\n");
3571            status = alt_dma_program_DMASEV(program, evt);
3572        }
3573    }
3574
3575    // Now that everything is done, end the program.
3576    if (status == ALT_E_SUCCESS)
3577    {
3578        status = alt_dma_program_DMAEND(program);
3579    }
3580
3581    // If there was a problem assembling the program, clean up the buffer and exit.
3582    if (status != ALT_E_SUCCESS)
3583    {
3584        // Do not report the status for the clear operation. A failure should be
3585        // reported regardless of if the clear is successful.
3586        alt_dma_program_clear(program);
3587        return status;
3588    }
3589
3590    // Execute the program on the given channel.
3591
3592    return alt_dma_channel_exec(channel, program);
3593}
3594
3595ALT_STATUS_CODE alt_dma_periph_to_memory(ALT_DMA_CHANNEL_t channel,
3596                                         ALT_DMA_PROGRAM_t * program,
3597                                         void * dst,
3598                                         ALT_DMA_PERIPH_t srcp,
3599                                         size_t size,
3600                                         void * periph_info,
3601                                         bool send_evt,
3602                                         ALT_DMA_EVENT_t evt)
3603{
3604    ALT_STATUS_CODE status = ALT_E_SUCCESS;
3605
3606    if ((size == 0) && (send_evt == false))
3607    {
3608        return ALT_E_SUCCESS;
3609    }
3610
3611    if (status == ALT_E_SUCCESS)
3612    {
3613        dprintf("DMA[P->M]: Init Program.\n");
3614        status = alt_dma_program_init(program);
3615    }
3616
3617    if ((status == ALT_E_SUCCESS) && (size != 0))
3618    {
3619        switch (srcp)
3620        {
3621#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
3622        case ALT_DMA_PERIPH_QSPI_FLASH_RX:
3623            status = alt_dma_qspi_to_memory(program, dst, size);
3624            break;
3625#endif
3626
3627#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3628        case ALT_DMA_PERIPH_UART0_RX:
3629        case ALT_DMA_PERIPH_UART1_RX:
3630            status = alt_dma_16550_to_memory(program, srcp,
3631                                             (ALT_16550_HANDLE_t *)periph_info, dst, size);
3632            break;
3633#endif
3634
3635        case ALT_DMA_PERIPH_FPGA_0:
3636        case ALT_DMA_PERIPH_FPGA_1:
3637        case ALT_DMA_PERIPH_FPGA_2:
3638        case ALT_DMA_PERIPH_FPGA_3:
3639        case ALT_DMA_PERIPH_FPGA_4:
3640        case ALT_DMA_PERIPH_FPGA_5:
3641        case ALT_DMA_PERIPH_FPGA_6:
3642        case ALT_DMA_PERIPH_FPGA_7:
3643        case ALT_DMA_PERIPH_I2C0_RX:
3644        case ALT_DMA_PERIPH_I2C1_RX:
3645        case ALT_DMA_PERIPH_I2C2_RX:
3646        case ALT_DMA_PERIPH_I2C3_RX:
3647        case ALT_DMA_PERIPH_SPI0_MASTER_RX:
3648        case ALT_DMA_PERIPH_SPI0_SLAVE_RX:
3649        case ALT_DMA_PERIPH_SPI1_MASTER_RX:
3650        case ALT_DMA_PERIPH_SPI1_SLAVE_RX:
3651
3652        default:
3653            status = ALT_E_BAD_ARG;
3654            break;
3655        }
3656    }
3657
3658    // Send event if requested.
3659    if (send_evt)
3660    {
3661        if (status == ALT_E_SUCCESS)
3662        {
3663            dprintf("DMA[P->M]: Adding event.\n");
3664            status = alt_dma_program_DMASEV(program, evt);
3665        }
3666    }
3667
3668    // Now that everything is done, end the program.
3669    if (status == ALT_E_SUCCESS)
3670    {
3671        status = alt_dma_program_DMAEND(program);
3672    }
3673
3674    // If there was a problem assembling the program, clean up the buffer and exit.
3675    if (status != ALT_E_SUCCESS)
3676    {
3677        // Do not report the status for the clear operation. A failure should be
3678        // reported regardless of if the clear is successful.
3679        alt_dma_program_clear(program);
3680        return status;
3681    }
3682
3683    // Execute the program on the given channel.
3684
3685    return alt_dma_channel_exec(channel, program);
3686}
3687
3688/////
3689
3690static bool alt_dma_is_init(void)
3691{
3692    uint32_t permodrst = alt_read_word(ALT_RSTMGR_PERMODRST_ADDR);
3693
3694    if (permodrst & ALT_RSTMGR_PERMODRST_DMA_SET_MSK)
3695    {
3696        return false;
3697    }
3698    else
3699    {
3700        return true;
3701    }
3702}
3703
3704ALT_STATUS_CODE alt_dma_ecc_start(void * block, size_t size)
3705{
3706    if (alt_dma_is_init() == false)
3707    {
3708        return ALT_E_ERROR;
3709    }
3710
3711    if ((uintptr_t)block & (sizeof(uint64_t) - 1))
3712    {
3713        return ALT_E_ERROR;
3714    }
3715
3716    // Verify that all channels are either unallocated or allocated and idle.
3717
3718    for (int i = 0; i < ARRAY_COUNT(channel_info_array); ++i)
3719    {
3720        if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
3721        {
3722            ALT_DMA_CHANNEL_STATE_t state;
3723            alt_dma_channel_state_get((ALT_DMA_CHANNEL_t)i, &state);
3724
3725            if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
3726            {
3727                dprintf("DMA[ECC]: Error: Channel %d state is non-stopped (%d).\n", i, (int)state);
3728                return ALT_E_ERROR;
3729            }
3730        }
3731    }
3732
3733    /////
3734
3735    // Enable ECC for DMA RAM
3736
3737    dprintf("DEBUG[DMA][ECC]: Enable ECC in SysMgr.\n");
3738    alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR, ALT_SYSMGR_ECC_DMA_EN_SET_MSK);
3739
3740    // Clear any pending spurious DMA ECC interrupts.
3741
3742    dprintf("DEBUG[DMA][ECC]: Clear any pending spurious ECC status in SysMgr.\n");
3743    alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR,
3744                     ALT_SYSMGR_ECC_DMA_EN_SET_MSK
3745                   | ALT_SYSMGR_ECC_DMA_SERR_SET_MSK
3746                   | ALT_SYSMGR_ECC_DMA_DERR_SET_MSK);
3747
3748    return ALT_E_SUCCESS;
3749}
Note: See TracBrowser for help on using the repository browser.