Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:42

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsARMCycVContrib
0005  */
0006 
0007 /******************************************************************************
0008  *
0009  * Copyright 2013 Altera Corporation. All Rights Reserved.
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions are met:
0013  *
0014  * 1. Redistributions of source code must retain the above copyright notice,
0015  * this list of conditions and the following disclaimer.
0016  *
0017  * 2. Redistributions in binary form must reproduce the above copyright notice,
0018  * this list of conditions and the following disclaimer in the documentation
0019  * and/or other materials provided with the distribution.
0020  *
0021  * 3. The name of the author may not be used to endorse or promote products
0022  * derived from this software without specific prior written permission.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
0025  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
0027  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0028  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0029  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0032  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
0033  * OF SUCH DAMAGE.
0034  *
0035  ******************************************************************************/
0036 
0037 #include <stdio.h>
0038 #include <bsp/alt_dma.h>
0039 #include <bsp/socal/socal.h>
0040 #include <bsp/socal/hps.h>
0041 #include <bsp/socal/alt_rstmgr.h>
0042 #include <bsp/socal/alt_sysmgr.h>
0043 
0044 #if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
0045 #include <bsp/alt_16550_uart.h>
0046 #include <bsp/socal/alt_uart.h>
0047 #endif
0048 
0049 #if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
0050 #include <bsp/socal/alt_qspi.h>
0051 #endif
0052 
0053 /////
0054 
0055 #ifndef MIN
0056 #define MIN(a, b) ((a) > (b) ? (b) : (a))
0057 #endif // MIN
0058 
0059 #ifndef ARRAY_COUNT
0060 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
0061 #endif
0062 
0063 // NOTE: To enable debugging output, delete the next line and uncomment the
0064 //   line after.
0065 #define dprintf(...)
0066 // #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
0067 
0068 /////
0069 
0070 //
0071 // SoCAL stand in for DMA Controller registers
0072 //
0073 // The base can be one of the following: 
0074 //  - ALT_DMANONSECURE_ADDR
0075 //  - ALT_DMASECURE_ADDR
0076 //
0077 // Macros which have a channel parameter does no validation.
0078 //
0079 
0080 // DMA Manager Status Register
0081 #define ALT_DMA_DSR_OFST 0x0
0082 #define ALT_DMA_DSR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DSR_OFST))
0083 #define ALT_DMA_DSR_DMASTATUS_SET_MSK 0x0000000f
0084 #define ALT_DMA_DSR_DMASTATUS_GET(value) ((value) & 0x0000000f)
0085 
0086 // DMA Program Counter Register
0087 #define ALT_DMA_DPC_OFST 0x4
0088 #define ALT_DMA_DPC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DPC_OFST))
0089 
0090 // Interrupt Enable Register
0091 #define ALT_DMA_INTEN_OFST 0x20
0092 #define ALT_DMA_INTEN_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTEN_OFST))
0093 
0094 // Event-Interrupt Raw Status Register
0095 #define ALT_DMA_INT_EVENT_RIS_OFST 0x24
0096 #define ALT_DMA_INT_EVENT_RIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INT_EVENT_RIS_OFST))
0097 
0098 // Interrupt Status Register
0099 #define ALT_DMA_INTMIS_OFST 0x28
0100 #define ALT_DMA_INTMIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTMIS_OFST))
0101 
0102 // Interrupt Clear Register
0103 #define ALT_DMA_INTCLR_OFST 0x2c
0104 #define ALT_DMA_INTCLR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTCLR_OFST))
0105 
0106 // Fault Status DMA Manager Register
0107 #define ALT_DMA_FSRD_OFST 0x30
0108 #define ALT_DMA_FSRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST))
0109 
0110 // Fault Status DMA Channel Register
0111 #define ALT_DMA_FSRC_OFST 0x34
0112 #define ALT_DMA_FSRC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRC_OFST))
0113 
0114 // Fault Type DMA Manager Register
0115 #define ALT_DMA_FTRD_OFST 0x38
0116 #define ALT_DMA_FTRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST))
0117 
0118 // Fault Type DMA Channel Registers
0119 #define ALT_DMA_FTRx_OFST(channel) (0x40 + 0x4 * (channel))
0120 #define ALT_DMA_FTRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FTRx_OFST(channel)))
0121 
0122 // Channel Status Registers
0123 #define ALT_DMA_CSRx_OFST(channel) (0x100 + 0x8 * (channel))
0124 #define ALT_DMA_CSRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CSRx_OFST(channel)))
0125 #define ALT_DMA_CSRx_CHANNELSTATUS_SET_MSK 0x0000000f
0126 #define ALT_DMA_CSRx_CHANNELSTATUS_GET(value) ((value) & 0x0000000f)
0127 
0128 // Channel Program Counter Registers
0129 #define ALT_DMA_CPCx_OFST(channel) (0x104 + 0x8 * (channel))
0130 #define ALT_DMA_CPCx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CPCx_OFST(channel)))
0131 
0132 // Source Address Registers
0133 #define ALT_DMA_SARx_OFST(channel) (0x400 + 0x20 * (channel))
0134 #define ALT_DMA_SARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_SARx_OFST(channel)))
0135 
0136 // Destination Address Registers
0137 #define ALT_DMA_DARx_OFST(channel) (0x404 + 0x20 * (channel))
0138 #define ALT_DMA_DARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DARx_OFST(channel)))
0139 
0140 // Channel Control Registers
0141 #define ALT_DMA_CCRx_OFST(channel) (0x408 + 0x20 * (channel))
0142 #define ALT_DMA_CCRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CCRx_OFST(channel)))
0143 
0144 // Loop Counter 0 Registers
0145 #define ALT_DMA_LC0_x_OFST(channel) (0x40c + 0x20 * (channel))
0146 #define ALT_DMA_LC0_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC0_x_OFST(channel)))
0147 
0148 // Loop Counter 1 Registers
0149 #define ALT_DMA_LC1_x_OFST(channel) (0x410 + 0x20 * (channel))
0150 #define ALT_DMA_LC1_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC1_x_OFST(channel)))
0151 
0152 // Debug Status Register
0153 #define ALT_DMA_DBGSTATUS_OFST 0xd00
0154 #define ALT_DMA_DBGSTATUS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGSTATUS_OFST))
0155 
0156 // Debug Command Register
0157 #define ALT_DMA_DBGCMD_OFST 0xd04
0158 #define ALT_DMA_DBGCMD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGCMD_OFST))
0159 
0160 // Debug Instruction-0 Register
0161 #define ALT_DMA_DBGINST0_OFST 0xd08
0162 #define ALT_DMA_DBGINST0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST0_OFST))
0163 #define ALT_DMA_DBGINST0_CHANNELNUMBER_SET(value) (((value) & 0x7) << 8)
0164 #define ALT_DMA_DBGINST0_DEBUGTHREAD_SET(value) ((value) & 0x1)
0165 #define ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER 0
0166 #define ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL 1
0167 #define ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(value) (((value) & 0xff) << 16)
0168 #define ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(value) (((value) & 0xff) << 24)
0169 
0170 // Debug Instruction-1 Register
0171 #define ALT_DMA_DBGINST1_OFST 0xd0c
0172 #define ALT_DMA_DBGINST1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST1_OFST))
0173 
0174 // Configuration Registers 0 - 4
0175 #define ALT_DMA_CR0_OFST 0xe00
0176 #define ALT_DMA_CR1_OFST 0xe04
0177 #define ALT_DMA_CR2_OFST 0xe08
0178 #define ALT_DMA_CR3_OFST 0xe0c
0179 #define ALT_DMA_CR4_OFST 0xe10
0180 #define ALT_DMA_CR0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR0_OFST))
0181 #define ALT_DMA_CR1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR1_OFST))
0182 #define ALT_DMA_CR2_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR2_OFST))
0183 #define ALT_DMA_CR3_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR3_OFST))
0184 #define ALT_DMA_CR4_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR4_OFST))
0185 
0186 // DMA Configuration Register
0187 #define ALT_DMA_CRD_OFST 0xe14
0188 #define ALT_DMA_CRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CRD_OFST))
0189 
0190 // Watchdog Register
0191 #define ALT_DMA_WD_OFST 0xe80
0192 #define ALT_DMA_WD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_WD_OFST))
0193 
0194 /////
0195 
0196 //
0197 // Internal Data structures
0198 //
0199 
0200 // This flag marks the channel as being allocated.
0201 #define ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED (1 << 0)
0202 
0203 typedef struct ALT_DMA_CHANNEL_INFO_s
0204 {
0205     uint8_t flag;
0206 }
0207 ALT_DMA_CHANNEL_INFO_t;
0208 
0209 static ALT_DMA_CHANNEL_INFO_t channel_info_array[8];
0210 
0211 /////
0212 
0213 ALT_STATUS_CODE alt_dma_init(const ALT_DMA_CFG_t * dma_cfg)
0214 {
0215     // Initialize the channel information array
0216     for (int i = 0; i < 8; ++i)
0217     {
0218         channel_info_array[i].flag = 0;
0219     }
0220 
0221     // Update the System Manager DMA configuration items
0222     
0223     uint32_t dmactrl = 0;
0224 
0225     // Handle FPGA / CAN muxing
0226     for (int i = 0; i < 4; ++i)
0227     {
0228         // The default is FPGA.
0229         switch (dma_cfg->periph_mux[i])
0230         {
0231         case ALT_DMA_PERIPH_MUX_DEFAULT:
0232         case ALT_DMA_PERIPH_MUX_FPGA:
0233             break;
0234         case ALT_DMA_PERIPH_MUX_CAN:
0235             dmactrl |= (ALT_SYSMGR_DMA_CTL_CHANSEL_0_SET_MSK << i);
0236             break;
0237         default:
0238             return ALT_E_ERROR;
0239         }
0240     }
0241 
0242     // Handle Manager security
0243     // Default is Secure state.
0244     switch (dma_cfg->manager_sec)
0245     {
0246     case ALT_DMA_SECURITY_DEFAULT:
0247     case ALT_DMA_SECURITY_SECURE:
0248         break;
0249     case ALT_DMA_SECURITY_NONSECURE:
0250         dmactrl |= ALT_SYSMGR_DMA_CTL_MGRNONSECURE_SET_MSK;
0251         break;
0252     default:
0253         return ALT_E_ERROR;
0254     }
0255 
0256     // Handle IRQ security
0257     for (int i = 0; i < ALT_SYSMGR_DMA_CTL_IRQNONSECURE_WIDTH; ++i)
0258     {
0259         // Default is Secure state.
0260         switch (dma_cfg->irq_sec[i])
0261         {
0262         case ALT_DMA_SECURITY_DEFAULT:
0263         case ALT_DMA_SECURITY_SECURE:
0264             break;
0265         case ALT_DMA_SECURITY_NONSECURE:
0266             dmactrl |= (1 << (i + ALT_SYSMGR_DMA_CTL_IRQNONSECURE_LSB));
0267             break;
0268         default:
0269             return ALT_E_ERROR;
0270         }
0271     }
0272 
0273     alt_write_word(ALT_SYSMGR_DMA_CTL_ADDR, dmactrl);
0274 
0275     // Update the System Manager DMA peripheral security items
0276 
0277     uint32_t dmapersecurity = 0;
0278 
0279     for (int i = 0; i < 32; ++i)
0280     {
0281         // Default is Secure state.
0282         switch (dma_cfg->periph_sec[i])
0283         {
0284         case ALT_DMA_SECURITY_DEFAULT:
0285         case ALT_DMA_SECURITY_SECURE:
0286             break;
0287         case ALT_DMA_SECURITY_NONSECURE:
0288             dmapersecurity |= (1 << i);
0289             break;
0290         default:
0291             return ALT_E_ERROR;
0292         }
0293     }
0294 
0295     alt_write_word(ALT_SYSMGR_DMA_PERSECURITY_ADDR, dmapersecurity);
0296 
0297     // Take DMA out of reset.
0298 
0299     alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK);
0300 
0301     return ALT_E_SUCCESS;
0302 }
0303 
0304 ALT_STATUS_CODE alt_dma_uninit(void)
0305 {
0306     // DMAKILL all channel and free all allocated channels.
0307     for (int i = 0; i < 8; ++i)
0308     {
0309         if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
0310         {
0311             alt_dma_channel_kill((ALT_DMA_CHANNEL_t)i);
0312             alt_dma_channel_free((ALT_DMA_CHANNEL_t)i);
0313         }
0314     }
0315 
0316     // Put DMA into reset.
0317 
0318     alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK);
0319 
0320     return ALT_E_SUCCESS;
0321 }
0322 
0323 ALT_STATUS_CODE alt_dma_channel_alloc(ALT_DMA_CHANNEL_t channel)
0324 {
0325     // Validate channel
0326     switch (channel)
0327     {
0328     case ALT_DMA_CHANNEL_0:
0329     case ALT_DMA_CHANNEL_1:
0330     case ALT_DMA_CHANNEL_2:
0331     case ALT_DMA_CHANNEL_3:
0332     case ALT_DMA_CHANNEL_4:
0333     case ALT_DMA_CHANNEL_5:
0334     case ALT_DMA_CHANNEL_6:
0335     case ALT_DMA_CHANNEL_7:
0336         break;
0337     default:
0338         return ALT_E_BAD_ARG;
0339     }
0340 
0341     // Verify channel is unallocated
0342 
0343     if (channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
0344     {
0345         return ALT_E_ERROR;
0346     }
0347 
0348     // Mark channel as allocated
0349 
0350     channel_info_array[channel].flag |= ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED;
0351 
0352     return ALT_E_SUCCESS;
0353 }
0354 
0355 ALT_STATUS_CODE alt_dma_channel_alloc_any(ALT_DMA_CHANNEL_t * allocated)
0356 {
0357     // Sweep channel array for unallocated channel
0358 
0359     for (int i = 0; i < 8; ++i)
0360     {
0361         if (!(channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
0362         {
0363             // Allocate that free channel.
0364 
0365             ALT_STATUS_CODE status = alt_dma_channel_alloc((ALT_DMA_CHANNEL_t)i);
0366             if (status == ALT_E_SUCCESS)
0367             {
0368                 *allocated = (ALT_DMA_CHANNEL_t)i;
0369             }
0370             return status;
0371         }
0372     }
0373 
0374     // No free channels found.
0375 
0376     return ALT_E_ERROR;
0377 }
0378 
0379 ALT_STATUS_CODE alt_dma_channel_free(ALT_DMA_CHANNEL_t channel)
0380 {
0381     // Validate channel
0382     switch (channel)
0383     {
0384     case ALT_DMA_CHANNEL_0:
0385     case ALT_DMA_CHANNEL_1:
0386     case ALT_DMA_CHANNEL_2:
0387     case ALT_DMA_CHANNEL_3:
0388     case ALT_DMA_CHANNEL_4:
0389     case ALT_DMA_CHANNEL_5:
0390     case ALT_DMA_CHANNEL_6:
0391     case ALT_DMA_CHANNEL_7:
0392         break;
0393     default:
0394         return ALT_E_BAD_ARG;
0395     }
0396 
0397     // Verify channel is allocated
0398 
0399     if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
0400     {
0401         return ALT_E_ERROR;
0402     }
0403 
0404     // Verify channel is stopped
0405 
0406     ALT_DMA_CHANNEL_STATE_t state;
0407     ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state);
0408     if (status != ALT_E_SUCCESS)
0409     {
0410         return status;
0411     }
0412     if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
0413     {
0414         return ALT_E_ERROR;
0415     }
0416 
0417     // Mark channel as unallocated.
0418 
0419     channel_info_array[channel].flag &= ~ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED;
0420 
0421     return ALT_E_SUCCESS;
0422 }
0423 
0424 ALT_STATUS_CODE alt_dma_channel_exec(ALT_DMA_CHANNEL_t channel, ALT_DMA_PROGRAM_t * pgm)
0425 {
0426     // Validate channel
0427     switch (channel)
0428     {
0429     case ALT_DMA_CHANNEL_0:
0430     case ALT_DMA_CHANNEL_1:
0431     case ALT_DMA_CHANNEL_2:
0432     case ALT_DMA_CHANNEL_3:
0433     case ALT_DMA_CHANNEL_4:
0434     case ALT_DMA_CHANNEL_5:
0435     case ALT_DMA_CHANNEL_6:
0436     case ALT_DMA_CHANNEL_7:
0437         break;
0438     default:
0439         return ALT_E_BAD_ARG;
0440     }
0441 
0442     // Verify channel is allocated
0443 
0444     if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
0445     {
0446         return ALT_E_ERROR;
0447     }
0448 
0449     // Verify channel is stopped
0450 
0451     ALT_DMA_CHANNEL_STATE_t state;
0452     ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state);
0453     if (status != ALT_E_SUCCESS)
0454     {
0455         return status;
0456     }
0457     if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
0458     {
0459         return ALT_E_ERROR;
0460     }
0461 
0462     // Validate the program
0463 
0464     if (alt_dma_program_validate(pgm) != ALT_E_SUCCESS)
0465     {
0466         return ALT_E_ERROR;
0467     }
0468 
0469     //
0470     // Execute the program
0471     //
0472 
0473     // Get the start address
0474 
0475     uint32_t start = (uint32_t) &pgm->program[pgm->buffer_start];
0476 
0477     dprintf("DMA[exec]: pgm->program = %p.\n", pgm->program);
0478     dprintf("DMA[exec]: start        = %p.\n", (void *)start);
0479 
0480     // Configure DBGINST0 and DBGINST1 to execute DMAGO targetting the requested channel.
0481 
0482     // For information on APB Interface, see PL330, section 2.5.1.
0483     // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
0484     // For information on DMAGO, see PL330, section 4.3.5.
0485 
0486     alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
0487                    ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0xa0) | 
0488                    ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(channel));
0489 
0490     alt_write_word(ALT_DMA_DBGINST1_ADDR(ALT_DMASECURE_ADDR), start);
0491 
0492     // Execute the instruction held in DBGINST{0,1}
0493 
0494     // For information on DBGCMD, see PL330, section 3.3.19.
0495 
0496     alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
0497 
0498     return ALT_E_SUCCESS;
0499 }
0500 
0501 ALT_STATUS_CODE alt_dma_channel_kill(ALT_DMA_CHANNEL_t channel)
0502 {
0503     // Validate channel
0504     switch (channel)
0505     {
0506     case ALT_DMA_CHANNEL_0:
0507     case ALT_DMA_CHANNEL_1:
0508     case ALT_DMA_CHANNEL_2:
0509     case ALT_DMA_CHANNEL_3:
0510     case ALT_DMA_CHANNEL_4:
0511     case ALT_DMA_CHANNEL_5:
0512     case ALT_DMA_CHANNEL_6:
0513     case ALT_DMA_CHANNEL_7:
0514         break;
0515     default:
0516         return ALT_E_BAD_ARG;
0517     }
0518 
0519     // Verify channel is allocated
0520 
0521     if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED))
0522     {
0523         return ALT_E_ERROR;
0524     }
0525 
0526     // NOTE: Don't worry about the current channel state. Just issue DMAKILL
0527     //   instruction. The channel state cannot move from from Stopped back to
0528     //   Killing.
0529 
0530     // Configure DBGINST0 to execute DMAKILL on the requested channel thread.
0531     // DMAKILL is short enough not to use DBGINST1 register.
0532 
0533     // For information on APB Interface, see PL330, section 2.5.1.
0534     // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
0535     // For information on DMAKILL, see PL330, section 4.3.6.
0536 
0537     alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
0538                    ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x1) |
0539                    ALT_DMA_DBGINST0_CHANNELNUMBER_SET(channel) |
0540                    ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL));
0541 
0542     // Execute the instruction held in DBGINST0
0543 
0544     // For information on DBGCMD, see PL330, section 3.3.19.
0545 
0546     alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
0547 
0548     // Wait for channel to move to KILLING or STOPPED state. Do not wait for
0549     // the STOPPED only. If the AXI transaction hangs permanently, it can be
0550     // waiting indefinately.
0551 
0552     ALT_STATUS_CODE status = ALT_E_SUCCESS;
0553     ALT_DMA_CHANNEL_STATE_t current;
0554     uint32_t i = 20000;
0555 
0556     while (--i)
0557     {
0558         status = alt_dma_channel_state_get(channel, &current);
0559         if (status != ALT_E_SUCCESS)
0560         {
0561             break;
0562         }
0563         if (   (current == ALT_DMA_CHANNEL_STATE_KILLING)
0564             || (current == ALT_DMA_CHANNEL_STATE_STOPPED))
0565         {
0566             break;
0567         }
0568     }
0569 
0570     if (i == 0)
0571     {
0572         status = ALT_E_TMO;
0573     }
0574 
0575     return status;
0576 }
0577 
0578 ALT_STATUS_CODE alt_dma_channel_reg_get(ALT_DMA_CHANNEL_t channel,
0579                                         ALT_DMA_PROGRAM_REG_t reg, uint32_t * val)
0580 {
0581     // Validate channel
0582     switch (channel)
0583     {
0584     case ALT_DMA_CHANNEL_0:
0585     case ALT_DMA_CHANNEL_1:
0586     case ALT_DMA_CHANNEL_2:
0587     case ALT_DMA_CHANNEL_3:
0588     case ALT_DMA_CHANNEL_4:
0589     case ALT_DMA_CHANNEL_5:
0590     case ALT_DMA_CHANNEL_6:
0591     case ALT_DMA_CHANNEL_7:
0592         break;
0593     default:
0594         return ALT_E_BAD_ARG;
0595     }
0596 
0597     // For information on SAR, see PL330, section 3.3.13.
0598     // For information on DAR, see PL330, section 3.3.14.
0599     // For information on CCR, see PL330, section 3.3.15.
0600 
0601     switch (reg)
0602     {
0603     case ALT_DMA_PROGRAM_REG_SAR:
0604         *val = alt_read_word(ALT_DMA_SARx_ADDR(ALT_DMASECURE_ADDR, channel));
0605         break;
0606     case ALT_DMA_PROGRAM_REG_DAR:
0607         *val = alt_read_word(ALT_DMA_DARx_ADDR(ALT_DMASECURE_ADDR, channel));
0608         break;
0609     case ALT_DMA_PROGRAM_REG_CCR:
0610         *val = alt_read_word(ALT_DMA_CCRx_ADDR(ALT_DMASECURE_ADDR, channel));
0611         break;
0612     default:
0613         return ALT_E_BAD_ARG;
0614     }
0615 
0616     return ALT_E_SUCCESS;
0617 }
0618 
0619 ALT_STATUS_CODE alt_dma_send_event(ALT_DMA_EVENT_t evt_num)
0620 {
0621     // Validate evt_num
0622 
0623     switch (evt_num)
0624     {
0625     case ALT_DMA_EVENT_0:
0626     case ALT_DMA_EVENT_1:
0627     case ALT_DMA_EVENT_2:
0628     case ALT_DMA_EVENT_3:
0629     case ALT_DMA_EVENT_4:
0630     case ALT_DMA_EVENT_5:
0631     case ALT_DMA_EVENT_6:
0632     case ALT_DMA_EVENT_7:
0633     case ALT_DMA_EVENT_ABORT:
0634         break;
0635     default:
0636         return ALT_E_BAD_ARG;
0637     }
0638 
0639     // Issue the DMASEV on the DMA manager thread.
0640     // DMASEV is short enough not to use DBGINST1 register.
0641 
0642     // For information on APB Interface, see PL330, section 2.5.1.
0643     // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21.
0644     // For information on DMASEV, see PL330, section 4.3.15.
0645 
0646     alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR),
0647                    ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x34) | // opcode for DMASEV
0648                    ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(evt_num << 3) |
0649                    ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER)
0650         );
0651 
0652     // Execute the instruction held in DBGINST0
0653 
0654     // For information on DBGCMD, see PL330, section 3.3.19.
0655 
0656     alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0);
0657 
0658     return ALT_E_SUCCESS;
0659 }
0660 
0661 ALT_STATUS_CODE alt_dma_manager_state_get(ALT_DMA_MANAGER_STATE_t * state)
0662 {
0663     // For information on DSR, see PL330, section 3.3.1.
0664 
0665     uint32_t raw_state = alt_read_word(ALT_DMA_DSR_ADDR(ALT_DMASECURE_ADDR));
0666 
0667     *state = (ALT_DMA_MANAGER_STATE_t)ALT_DMA_DSR_DMASTATUS_GET(raw_state);
0668 
0669     return ALT_E_SUCCESS;
0670 }
0671 
0672 ALT_STATUS_CODE alt_dma_channel_state_get(ALT_DMA_CHANNEL_t channel,
0673                                           ALT_DMA_CHANNEL_STATE_t * state)
0674 {
0675     // Validate channel
0676     switch (channel)
0677     {
0678     case ALT_DMA_CHANNEL_0:
0679     case ALT_DMA_CHANNEL_1:
0680     case ALT_DMA_CHANNEL_2:
0681     case ALT_DMA_CHANNEL_3:
0682     case ALT_DMA_CHANNEL_4:
0683     case ALT_DMA_CHANNEL_5:
0684     case ALT_DMA_CHANNEL_6:
0685     case ALT_DMA_CHANNEL_7:
0686         break;
0687     default:
0688         return ALT_E_BAD_ARG;
0689     }
0690 
0691     // For information on CSR, see PL330, section 3.3.11.
0692 
0693     uint32_t raw_state = alt_read_word(ALT_DMA_CSRx_ADDR(ALT_DMASECURE_ADDR, channel));
0694 
0695     *state = (ALT_DMA_CHANNEL_STATE_t)ALT_DMA_CSRx_CHANNELSTATUS_GET(raw_state);
0696 
0697     return ALT_E_SUCCESS;
0698 }
0699 
0700 ALT_STATUS_CODE alt_dma_manager_fault_status_get(ALT_DMA_MANAGER_FAULT_t * fault)
0701 {
0702     // For information on FTRD, see PL330, section 3.3.9.
0703 
0704     *fault = (ALT_DMA_MANAGER_FAULT_t)alt_read_word(ALT_DMA_FTRD_ADDR(ALT_DMASECURE_ADDR));
0705 
0706     return ALT_E_SUCCESS;
0707 }
0708 
0709 ALT_STATUS_CODE alt_dma_channel_fault_status_get(ALT_DMA_CHANNEL_t channel,
0710                                                  ALT_DMA_CHANNEL_FAULT_t * fault)
0711 {
0712     // Validate channel
0713     switch (channel)
0714     {
0715     case ALT_DMA_CHANNEL_0:
0716     case ALT_DMA_CHANNEL_1:
0717     case ALT_DMA_CHANNEL_2:
0718     case ALT_DMA_CHANNEL_3:
0719     case ALT_DMA_CHANNEL_4:
0720     case ALT_DMA_CHANNEL_5:
0721     case ALT_DMA_CHANNEL_6:
0722     case ALT_DMA_CHANNEL_7:
0723         break;
0724     default:
0725         return ALT_E_BAD_ARG;
0726     }
0727 
0728     // For information on FTR, see PL330, section 3.3.10.
0729 
0730     *fault = (ALT_DMA_CHANNEL_FAULT_t)alt_read_word(ALT_DMA_FTRx_ADDR(ALT_DMASECURE_ADDR, channel));
0731 
0732     return ALT_E_SUCCESS;
0733 }
0734 
0735 ALT_STATUS_CODE alt_dma_event_int_select(ALT_DMA_EVENT_t evt_num,
0736                                          ALT_DMA_EVENT_SELECT_t opt)
0737 {
0738     // Validate evt_num
0739     switch (evt_num)
0740     {
0741     case ALT_DMA_EVENT_0:
0742     case ALT_DMA_EVENT_1:
0743     case ALT_DMA_EVENT_2:
0744     case ALT_DMA_EVENT_3:
0745     case ALT_DMA_EVENT_4:
0746     case ALT_DMA_EVENT_5:
0747     case ALT_DMA_EVENT_6:
0748     case ALT_DMA_EVENT_7:
0749     case ALT_DMA_EVENT_ABORT:
0750         break;
0751     default:
0752         return ALT_E_BAD_ARG;
0753     }
0754 
0755     // For information on INTEN, see PL330, section 3.3.3.
0756 
0757     switch (opt)
0758     {
0759     case ALT_DMA_EVENT_SELECT_SEND_EVT:
0760         alt_clrbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num);
0761         break;
0762     case ALT_DMA_EVENT_SELECT_SIG_IRQ:
0763         alt_setbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num);
0764         break;
0765     default:
0766         return ALT_E_BAD_ARG;
0767     }
0768 
0769     return ALT_E_SUCCESS;
0770 }
0771 
0772 ALT_STATUS_CODE alt_dma_event_int_status_get_raw(ALT_DMA_EVENT_t evt_num)
0773 {
0774     // Validate evt_num
0775     switch (evt_num)
0776     {
0777     case ALT_DMA_EVENT_0:
0778     case ALT_DMA_EVENT_1:
0779     case ALT_DMA_EVENT_2:
0780     case ALT_DMA_EVENT_3:
0781     case ALT_DMA_EVENT_4:
0782     case ALT_DMA_EVENT_5:
0783     case ALT_DMA_EVENT_6:
0784     case ALT_DMA_EVENT_7:
0785     case ALT_DMA_EVENT_ABORT:
0786         break;
0787     default:
0788         return ALT_E_BAD_ARG;
0789     }
0790 
0791     // For information on INT_EVENT_RIS, see PL330, section 3.3.4.
0792 
0793     uint32_t status_raw = alt_read_word(ALT_DMA_INT_EVENT_RIS_ADDR(ALT_DMASECURE_ADDR));
0794 
0795     if (status_raw & (1 << evt_num))
0796     {
0797         return ALT_E_TRUE;
0798     }
0799     else
0800     {
0801         return ALT_E_FALSE;
0802     }
0803 }
0804 
0805 ALT_STATUS_CODE alt_dma_int_status_get(ALT_DMA_EVENT_t irq_num)
0806 {
0807     // Validate evt_num
0808     switch (irq_num)
0809     {
0810     case ALT_DMA_EVENT_0:
0811     case ALT_DMA_EVENT_1:
0812     case ALT_DMA_EVENT_2:
0813     case ALT_DMA_EVENT_3:
0814     case ALT_DMA_EVENT_4:
0815     case ALT_DMA_EVENT_5:
0816     case ALT_DMA_EVENT_6:
0817     case ALT_DMA_EVENT_7:
0818     case ALT_DMA_EVENT_ABORT:
0819         break;
0820     default:
0821         return ALT_E_BAD_ARG;
0822     }
0823 
0824     // For information on INTMIS, see PL330, section 3.3.5.
0825 
0826     uint32_t int_status = alt_read_word(ALT_DMA_INTMIS_ADDR(ALT_DMASECURE_ADDR));
0827 
0828     if (int_status & (1 << irq_num))
0829     {
0830         return ALT_E_TRUE;
0831     }
0832     else
0833     {
0834         return ALT_E_FALSE;
0835     }
0836 }
0837 
0838 ALT_STATUS_CODE alt_dma_int_clear(ALT_DMA_EVENT_t irq_num)
0839 {
0840     // Validate evt_num
0841     switch (irq_num)
0842     {
0843     case ALT_DMA_EVENT_0:
0844     case ALT_DMA_EVENT_1:
0845     case ALT_DMA_EVENT_2:
0846     case ALT_DMA_EVENT_3:
0847     case ALT_DMA_EVENT_4:
0848     case ALT_DMA_EVENT_5:
0849     case ALT_DMA_EVENT_6:
0850     case ALT_DMA_EVENT_7:
0851     case ALT_DMA_EVENT_ABORT:
0852         break;
0853     default:
0854         return ALT_E_BAD_ARG;
0855     }
0856 
0857     // For information on INTCLR, see PL330, section 3.3.6.
0858 
0859     alt_write_word(ALT_DMA_INTCLR_ADDR(ALT_DMASECURE_ADDR), 1 << irq_num);
0860 
0861     return ALT_E_SUCCESS;
0862 }
0863 
0864 /////
0865 
0866 ALT_STATUS_CODE alt_dma_memory_to_memory(ALT_DMA_CHANNEL_t channel,
0867                                          ALT_DMA_PROGRAM_t * program,
0868                                          void * dst,
0869                                          const void * src,
0870                                          size_t size,
0871                                          bool send_evt,
0872                                          ALT_DMA_EVENT_t evt)
0873 {
0874     ALT_STATUS_CODE status = ALT_E_SUCCESS;
0875 
0876     // If the size is zero, and no event is requested, just return success.
0877     if ((size == 0) && (send_evt == false))
0878     {
0879         return status;
0880     }
0881 
0882     if (status == ALT_E_SUCCESS)
0883     {
0884         status = alt_dma_program_init(program);
0885     }
0886 
0887     if (size != 0)
0888     {
0889         uintptr_t udst = (uintptr_t)dst;
0890         uintptr_t usrc = (uintptr_t)src;
0891 
0892         dprintf("DMA[M->M]: dst  = %p.\n", dst);
0893         dprintf("DMA[M->M]: src  = %p.\n", src);
0894         dprintf("DMA[M->M]: size = 0x%x.\n", size);
0895         
0896         // Detect if memory regions overshoots the address space.
0897 
0898         if (udst + size - 1 < udst)
0899         {
0900             return ALT_E_BAD_ARG;
0901         }
0902         if (usrc + size - 1 < usrc)
0903         {
0904             return ALT_E_BAD_ARG;
0905         }
0906 
0907         // Detect if memory regions overlaps.
0908 
0909         if (udst > usrc)
0910         {
0911             if (usrc + size - 1 > udst)
0912             {
0913                 return ALT_E_BAD_ARG;
0914             }
0915         }
0916         else
0917         {
0918             if (udst + size - 1 > usrc)
0919             {
0920                 return ALT_E_BAD_ARG;
0921             }
0922         }
0923 
0924         if (status == ALT_E_SUCCESS)
0925         {
0926             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, usrc);
0927         }
0928         if (status == ALT_E_SUCCESS)
0929         {
0930             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, udst);
0931         }
0932 
0933         size_t sizeleft = size;
0934 
0935         //
0936         // The algorithm uses the strategy described in PL330 B.3.1.
0937         // It is extended for 2-byte and 1-byte unaligned cases.
0938         //
0939 
0940         // First see how many byte(s) we need to transfer to get src to be 8 byte aligned
0941         if (usrc & 0x7)
0942         {
0943             uint32_t aligncount = MIN(8 - (usrc & 0x7), sizeleft);
0944             sizeleft -= aligncount;
0945 
0946             dprintf("DMA[M->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount);
0947 
0948             // Program in the following parameters:
0949             //  - SS8 (Source      burst size of 1-byte)
0950             //  - DS8 (Destination burst size of 1-byte)
0951             //  - SBx (Source      burst length of [aligncount] transfers)
0952             //  - DBx (Destination burst length of [aligncount] transfers)
0953             //  - All other options default.
0954 
0955             if (status == ALT_E_SUCCESS)
0956             {
0957                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
0958                                                 (   ((aligncount - 1) << 4) // SB
0959                                                   | ALT_DMA_CCR_OPT_SS8
0960                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
0961                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
0962                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
0963                                                   | ((aligncount - 1) << 18) // DB
0964                                                   | ALT_DMA_CCR_OPT_DS8
0965                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
0966                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
0967                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
0968                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
0969                                                 )
0970                     );
0971             }
0972             if (status == ALT_E_SUCCESS)
0973             {
0974                 status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
0975             }
0976             if (status == ALT_E_SUCCESS)
0977             {
0978                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
0979             }
0980         }
0981 
0982         // This is the number of 8-byte bursts
0983         uint32_t burstcount = sizeleft >> 3;
0984 
0985         bool correction = (burstcount != 0);
0986 
0987         // Update the size left to transfer
0988         sizeleft &= 0x7;
0989 
0990         dprintf("DMA[M->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount);
0991         dprintf("DMA[M->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft);
0992 
0993         // Determine how many 16 length bursts can be done
0994 
0995         if (burstcount >> 4)
0996         {
0997             uint32_t length16burstcount = burstcount >> 4;
0998             burstcount &= 0xf;
0999 
1000             dprintf("DMA[M->M]:   Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount);
1001             dprintf("DMA[M->M]:   Number of remaining 8-byte transfer(s):       %lu.\n", burstcount);
1002 
1003             // Program in the following parameters:
1004             //  - SS64 (Source      burst size of 8-byte)
1005             //  - DS64 (Destination burst size of 8-byte)
1006             //  - SB16 (Source      burst length of 16 transfers)
1007             //  - DB16 (Destination burst length of 16 transfers)
1008             //  - All other options default.
1009 
1010             if (status == ALT_E_SUCCESS)
1011             {
1012                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1013                                                 (   ALT_DMA_CCR_OPT_SB16
1014                                                   | ALT_DMA_CCR_OPT_SS64
1015                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1016                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1017                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1018                                                   | ALT_DMA_CCR_OPT_DB16
1019                                                   | ALT_DMA_CCR_OPT_DS64
1020                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1021                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1022                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1023                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1024                                                 )
1025                     );
1026             }
1027 
1028             while (length16burstcount > 0)
1029             {
1030                 if (status != ALT_E_SUCCESS)
1031                 {
1032                     break;
1033                 }
1034 
1035                 uint32_t loopcount = MIN(length16burstcount, 256);
1036                 length16burstcount -= loopcount;
1037 
1038                 dprintf("DMA[M->M]:   Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount);
1039 
1040                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1041                 {
1042                     status = alt_dma_program_DMALP(program, loopcount);
1043                 }
1044                 if (status == ALT_E_SUCCESS)
1045                 {
1046                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1047                 }
1048                 if (status == ALT_E_SUCCESS)
1049                 {
1050                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1051                 }
1052                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1053                 {
1054                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1055                 }
1056             }
1057         }
1058 
1059         // At this point, we should have [burstcount] 8-byte transfer(s)
1060         // remaining. [burstcount] should be less than 16.
1061 
1062         // Do one more burst with a SB / DB of length [burstcount].
1063 
1064         if (burstcount)
1065         {
1066             // Program in the following parameters:
1067             //  - SS64 (Source      burst size of 8-byte)
1068             //  - DS64 (Destination burst size of 8-byte)
1069             //  - SBx  (Source      burst length of [burstlength] transfers)
1070             //  - DBx  (Destination burst length of [burstlength] transfers)
1071             //  - All other options default.
1072 
1073             if (status == ALT_E_SUCCESS)
1074             {
1075                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1076                                                 (   ((burstcount - 1) << 4) // SB
1077                                                   | ALT_DMA_CCR_OPT_SS64
1078                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1079                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1080                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1081                                                   | ((burstcount - 1) << 18) // DB
1082                                                   | ALT_DMA_CCR_OPT_DS64
1083                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1084                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1085                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1086                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1087                                                 )
1088                     );
1089             }
1090             if (status == ALT_E_SUCCESS)
1091             {
1092                 status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1093             }
1094             if (status == ALT_E_SUCCESS)
1095             {
1096                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1097             }
1098         }
1099 
1100         // This is where the last DMAMOV CCR and DMAST is done if an
1101         // alignment correction required.
1102 
1103         if (   (correction == true)
1104             && ((usrc & 0x7) != (udst & 0x7)) // If src and dst are mod-8 congruent, no correction is needed.
1105            )
1106         {
1107             if (status == ALT_E_SUCCESS)
1108             {
1109                 // Determine what type of correction.
1110 
1111                 // Set the source parameters to match that of the destination
1112                 // parameters. This way the SAR is increment in the same fashion as
1113                 // DAR. This will allow the non 8-byte transfers to copy correctly.
1114 
1115                 uint32_t ccr;
1116 
1117                 if ((usrc & 0x3) == (udst & 0x3))
1118                 {
1119                     dprintf("DMA[M->M]: Single correction 4-byte burst size tranfer.\n");
1120 
1121                     // Program in the following parameters:
1122                     //  - SS32 (Source      burst size of 4-byte)
1123                     //  - DS32 (Destination burst size of 4-byte)
1124                     //  - SB1  (Source      burst length of 1 transfer)
1125                     //  - DB1  (Destination burst length of 1 transfer)
1126                     //  - All other options default.
1127 
1128                     ccr = (   ALT_DMA_CCR_OPT_SB1
1129                             | ALT_DMA_CCR_OPT_SS32
1130                             | ALT_DMA_CCR_OPT_SA_DEFAULT
1131                             | ALT_DMA_CCR_OPT_SP_DEFAULT
1132                             | ALT_DMA_CCR_OPT_SC_DEFAULT
1133                             | ALT_DMA_CCR_OPT_DB1
1134                             | ALT_DMA_CCR_OPT_DS32
1135                             | ALT_DMA_CCR_OPT_DA_DEFAULT
1136                             | ALT_DMA_CCR_OPT_DP_DEFAULT
1137                             | ALT_DMA_CCR_OPT_DC_DEFAULT
1138                             | ALT_DMA_CCR_OPT_ES_DEFAULT
1139                           );
1140                 }
1141                 else if ((usrc & 0x1) == (udst & 0x1))
1142                 {
1143                     dprintf("DMA[M->M]: Single correction 2-byte burst size tranfer.\n");
1144 
1145                     // Program in the following parameters:
1146                     //  - SS16 (Source      burst size of 2-byte)
1147                     //  - DS16 (Destination burst size of 2-byte)
1148                     //  - SB1  (Source      burst length of 1 transfer)
1149                     //  - DB1  (Destination burst length of 1 transfer)
1150                     //  - All other options default.
1151 
1152                     ccr = (   ALT_DMA_CCR_OPT_SB1
1153                             | ALT_DMA_CCR_OPT_SS16
1154                             | ALT_DMA_CCR_OPT_SA_DEFAULT
1155                             | ALT_DMA_CCR_OPT_SP_DEFAULT
1156                             | ALT_DMA_CCR_OPT_SC_DEFAULT
1157                             | ALT_DMA_CCR_OPT_DB1
1158                             | ALT_DMA_CCR_OPT_DS16
1159                             | ALT_DMA_CCR_OPT_DA_DEFAULT
1160                             | ALT_DMA_CCR_OPT_DP_DEFAULT
1161                             | ALT_DMA_CCR_OPT_DC_DEFAULT
1162                             | ALT_DMA_CCR_OPT_ES_DEFAULT
1163                           );
1164                 }
1165                 else
1166                 {
1167                     dprintf("DMA[M->M]: Single correction 1-byte burst size tranfer.\n");
1168 
1169                     // Program in the following parameters:
1170                     //  - SS8 (Source      burst size of 1-byte)
1171                     //  - DS8 (Destination burst size of 1-byte)
1172                     //  - SB1 (Source      burst length of 1 transfer)
1173                     //  - DB1 (Destination burst length of 1 transfer)
1174                     //  - All other options default.
1175 
1176                     ccr = (   ALT_DMA_CCR_OPT_SB1
1177                             | ALT_DMA_CCR_OPT_SS8
1178                             | ALT_DMA_CCR_OPT_SA_DEFAULT
1179                             | ALT_DMA_CCR_OPT_SP_DEFAULT
1180                             | ALT_DMA_CCR_OPT_SC_DEFAULT
1181                             | ALT_DMA_CCR_OPT_DB1
1182                             | ALT_DMA_CCR_OPT_DS8
1183                             | ALT_DMA_CCR_OPT_DA_DEFAULT
1184                             | ALT_DMA_CCR_OPT_DP_DEFAULT
1185                             | ALT_DMA_CCR_OPT_DC_DEFAULT
1186                             | ALT_DMA_CCR_OPT_ES_DEFAULT
1187                           );
1188                 }
1189 
1190                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1191                                                 ccr);
1192             }
1193             if (status == ALT_E_SUCCESS)
1194             {
1195                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1196             }
1197         }
1198 
1199         // At this point, there should be 0 - 7 1-byte transfers remaining.
1200 
1201         if (sizeleft)
1202         {
1203             dprintf("DMA[M->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft);
1204 
1205             // Program in the following parameters:
1206             //  - SS8 (Source      burst size of 1-byte)
1207             //  - DS8 (Destination burst size of 1-byte)
1208             //  - SBx (Source      burst length of [sizeleft] transfers)
1209             //  - DBx (Destination burst length of [sizeleft] transfers)
1210             //  - All other options default.
1211 
1212             if (status == ALT_E_SUCCESS)
1213             {
1214                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1215                                                 (   ((sizeleft - 1) << 4) // SB
1216                                                   | ALT_DMA_CCR_OPT_SS8
1217                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1218                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1219                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1220                                                   | ((sizeleft - 1) << 18) // DB
1221                                                   | ALT_DMA_CCR_OPT_DS8
1222                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1223                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1224                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1225                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1226                                                 )
1227                     );
1228             }
1229             if (status == ALT_E_SUCCESS)
1230             {
1231                 status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1232             }
1233             if (status == ALT_E_SUCCESS)
1234             {
1235                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1236             }
1237         }
1238     } // if (size != 0)
1239 
1240     // Send event if requested.
1241     if (send_evt)
1242     {
1243         if (status == ALT_E_SUCCESS)
1244         {
1245             dprintf("DMA[M->M]: Adding event ...\n");
1246             status = alt_dma_program_DMASEV(program, evt);
1247         }
1248     }
1249 
1250     // Now that everything is done, end the program.
1251     if (status == ALT_E_SUCCESS)
1252     {
1253         status = alt_dma_program_DMAEND(program);
1254     }
1255 
1256     // If there was a problem assembling the program, clean up the buffer and exit.
1257     if (status != ALT_E_SUCCESS)
1258     {
1259         // Do not report the status for the clear operation. A failure should be
1260         // reported regardless of if the clear is successful.
1261         alt_dma_program_clear(program);
1262         return status;
1263     }
1264 
1265     // Execute the program on the given channel.
1266     return alt_dma_channel_exec(channel, program);
1267 }
1268 
1269 ALT_STATUS_CODE alt_dma_zero_to_memory(ALT_DMA_CHANNEL_t channel,
1270                                        ALT_DMA_PROGRAM_t * program,
1271                                        void * buf,
1272                                        size_t size,
1273                                        bool send_evt,
1274                                        ALT_DMA_EVENT_t evt)
1275 {
1276     ALT_STATUS_CODE status = ALT_E_SUCCESS;
1277 
1278     // If the size is zero, and no event is requested, just return success.
1279     if ((size == 0) && (send_evt == false))
1280     {
1281         return status;
1282     }
1283 
1284     if (status == ALT_E_SUCCESS)
1285     {
1286         status = alt_dma_program_init(program);
1287     }
1288 
1289     if (size != 0)
1290     {
1291         if (status == ALT_E_SUCCESS)
1292         {
1293             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)buf);
1294         }
1295 
1296         dprintf("DMA[Z->M]: buf  = %p.\n", buf);
1297         dprintf("DMA[Z->M]: size = 0x%x.\n", size);
1298 
1299         size_t sizeleft = size;
1300 
1301         // First see how many byte(s) we need to transfer to get dst to be 8 byte aligned.
1302         if ((uint32_t)buf & 0x7)
1303         {
1304             uint32_t aligncount = MIN(8 - ((uint32_t)buf & 0x7), sizeleft);
1305             sizeleft -= aligncount;
1306 
1307             dprintf("DMA[Z->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount);
1308 
1309             // Program in the following parameters:
1310             //  - DS8 (Destination burst size of 1-byte)
1311             //  - DBx (Destination burst length of [aligncount] transfers)
1312             //  - All other options default.
1313 
1314             if (status == ALT_E_SUCCESS)
1315             {
1316                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1317                                                 (   ALT_DMA_CCR_OPT_SB_DEFAULT
1318                                                   | ALT_DMA_CCR_OPT_SS_DEFAULT
1319                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1320                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1321                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1322                                                   | ((aligncount - 1) << 18) // DB
1323                                                   | ALT_DMA_CCR_OPT_DS8
1324                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1325                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1326                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1327                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1328                                                 )
1329                     );
1330             }
1331             if (status == ALT_E_SUCCESS)
1332             {
1333                 status = alt_dma_program_DMASTZ(program);
1334             }
1335         }
1336 
1337         // This is the number of 8-byte bursts left
1338         uint32_t burstcount = sizeleft >> 3;
1339 
1340         // Update the size left to transfer
1341         sizeleft &= 0x7;
1342 
1343         dprintf("DMA[Z->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount);
1344         dprintf("DMA[Z->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft);
1345 
1346         // Determine how many 16 length bursts can be done
1347         if (burstcount >> 4)
1348         {
1349             uint32_t length16burstcount = burstcount >> 4;
1350             burstcount &= 0xf;
1351 
1352             dprintf("DMA[Z->M]:   Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount);
1353             dprintf("DMA[Z->M]:   Number of remaining 8-byte transfer(s):       %lu.\n", burstcount);
1354 
1355             // Program in the following parameters:
1356             //  - DS64 (Destination burst size of 8-byte)
1357             //  - DB16 (Destination burst length of 16 transfers)
1358             //  - All other options default.
1359 
1360             if (status == ALT_E_SUCCESS)
1361             {
1362                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1363                                                 (   ALT_DMA_CCR_OPT_SB_DEFAULT
1364                                                   | ALT_DMA_CCR_OPT_SS_DEFAULT
1365                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1366                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1367                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1368                                                   | ALT_DMA_CCR_OPT_DB16
1369                                                   | ALT_DMA_CCR_OPT_DS64
1370                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1371                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1372                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1373                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1374                                                 )
1375                     );
1376             }
1377 
1378             while (length16burstcount > 0)
1379             {
1380                 if (status != ALT_E_SUCCESS)
1381                 {
1382                     break;
1383                 }
1384 
1385                 uint32_t loopcount = MIN(length16burstcount, 256);
1386                 length16burstcount -= loopcount;
1387 
1388                 dprintf("DMA[Z->M]:   Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount);
1389 
1390                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1391                 {
1392                     status = alt_dma_program_DMALP(program, loopcount);
1393                 }
1394                 if (status == ALT_E_SUCCESS)
1395                 {
1396                     status = alt_dma_program_DMASTZ(program);
1397                 }
1398                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1399                 {
1400                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1401                 }
1402             }
1403         }
1404 
1405         // At this point, we should have [burstcount] 8-byte transfer(s)
1406         // remaining. [burstcount] should be less than 16.
1407 
1408         // Do one more burst with a SB / DB of length [burstcount].
1409 
1410         if (burstcount)
1411         {
1412             // Program in the following parameters:
1413             //  - DS64 (Destination burst size of 8-byte)
1414             //  - DBx  (Destination burst length of [burstlength] transfers)
1415             //  - All other options default.
1416 
1417             if (status == ALT_E_SUCCESS)
1418             {
1419                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1420                                                 (   ALT_DMA_CCR_OPT_SB_DEFAULT
1421                                                   | ALT_DMA_CCR_OPT_SS_DEFAULT
1422                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1423                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1424                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1425                                                   | ((burstcount - 1) << 18) // DB
1426                                                   | ALT_DMA_CCR_OPT_DS64
1427                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1428                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1429                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1430                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1431                                                 )
1432                     );
1433             }
1434             if (status == ALT_E_SUCCESS)
1435             {
1436                 status = alt_dma_program_DMASTZ(program);
1437             }
1438         }
1439 
1440         // At this point, there should be 0 - 7 1-byte transfers remaining.
1441 
1442         if (sizeleft)
1443         {
1444             dprintf("DMA[Z->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft);
1445 
1446             // Program in the following parameters:
1447             //  - DS8 (Destination burst size of 1-byte)
1448             //  - DBx (Destination burst length of [sizeleft] transfers)
1449             //  - All other options default.
1450 
1451             if (status == ALT_E_SUCCESS)
1452             {
1453                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1454                                                 (   ALT_DMA_CCR_OPT_SB_DEFAULT
1455                                                   | ALT_DMA_CCR_OPT_SS_DEFAULT
1456                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1457                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1458                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1459                                                   | ((sizeleft - 1) << 18) // DB
1460                                                   | ALT_DMA_CCR_OPT_DS8
1461                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1462                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1463                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1464                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1465                                                 )
1466                     );
1467             }
1468             if (status == ALT_E_SUCCESS)
1469             {
1470                 status = alt_dma_program_DMASTZ(program);
1471             }
1472         }
1473     } // if (size != 0)
1474 
1475     // Send event if requested.
1476     if (send_evt)
1477     {
1478         if (status == ALT_E_SUCCESS)
1479         {
1480             dprintf("DMA[Z->M]: Adding event ...\n");
1481             status = alt_dma_program_DMASEV(program, evt);
1482         }
1483     }
1484 
1485     // Now that everything is done, end the program.
1486     if (status == ALT_E_SUCCESS)
1487     {
1488         status = alt_dma_program_DMAEND(program);
1489     }
1490 
1491     // If there was a problem assembling the program, clean up the buffer and exit.
1492     if (status != ALT_E_SUCCESS)
1493     {
1494         // Do not report the status for the clear operation. A failure should be
1495         // reported regardless of if the clear is successful.
1496         alt_dma_program_clear(program);
1497         return status;
1498     }
1499 
1500     // Execute the program on the given channel.
1501     return alt_dma_channel_exec(channel, program);
1502 }
1503 
1504 ALT_STATUS_CODE alt_dma_memory_to_register(ALT_DMA_CHANNEL_t channel,
1505                                            ALT_DMA_PROGRAM_t * program,
1506                                            void * dst_reg,
1507                                            const void * src_buf,
1508                                            size_t count,
1509                                            uint32_t register_width_bits,
1510                                            bool send_evt,
1511                                            ALT_DMA_EVENT_t evt)
1512 {
1513     ALT_STATUS_CODE status = ALT_E_SUCCESS;
1514 
1515     // If the count is zero, and no event is requested, just return success.
1516     if ((count == 0) && (send_evt == false))
1517     {
1518         return status;
1519     }
1520 
1521     if (status == ALT_E_SUCCESS)
1522     {
1523         status = alt_dma_program_init(program);
1524     }
1525 
1526     if (count != 0)
1527     {
1528         // Verify valid register_width_bits and construct the CCR SS and DS parameters.
1529         uint32_t ccr_ss_ds_mask = 0;
1530 
1531         if (status == ALT_E_SUCCESS)
1532         {
1533             switch (register_width_bits)
1534             {
1535             case 8:
1536                 // Program in the following parameters:
1537                 //  - SS8 (Source      burst size of 8 bits)
1538                 //  - DS8 (Destination burst size of 8 bits)
1539                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8;
1540                 break;
1541             case 16:
1542                 // Program in the following parameters:
1543                 //  - SS16 (Source      burst size of 16 bits)
1544                 //  - DS16 (Destination burst size of 16 bits)
1545                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16;
1546                 break;
1547             case 32:
1548                 // Program in the following parameters:
1549                 //  - SS32 (Source      burst size of 32 bits)
1550                 //  - DS32 (Destination burst size of 32 bits)
1551                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32;
1552                 break;
1553             case 64:
1554                 // Program in the following parameters:
1555                 //  - SS64 (Source      burst size of 64 bits)
1556                 //  - DS64 (Destination burst size of 64 bits)
1557                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64;
1558                 break;
1559             default:
1560                 status = ALT_E_BAD_ARG;
1561                 break;
1562             }
1563         }
1564 
1565         // Verify that the dst_reg and src_buf are aligned to the register width
1566         if (status == ALT_E_SUCCESS)
1567         {
1568             if      (((uintptr_t)dst_reg & ((register_width_bits >> 3) - 1)) != 0)
1569             {
1570                 status = ALT_E_BAD_ARG;
1571             }
1572             else if (((uintptr_t)src_buf & ((register_width_bits >> 3) - 1)) != 0)
1573             {
1574                 status = ALT_E_BAD_ARG;
1575             }
1576             else
1577             {
1578                 dprintf("DMA[M->R]: dst_reg = %p.\n",   dst_reg);
1579                 dprintf("DMA[M->R]: src_buf = %p.\n",   src_buf);
1580                 dprintf("DMA[M->R]: count   = 0x%x.\n", count);
1581             }
1582         }
1583 
1584         if (status == ALT_E_SUCCESS)
1585         {
1586             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_buf);
1587         }
1588         if (status == ALT_E_SUCCESS)
1589         {
1590             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_reg);
1591         }
1592 
1593         // This is the remaining count left to process.
1594         uint32_t countleft = count;
1595 
1596         // See how many 16-length bursts we can use
1597         if (countleft >> 4)
1598         {
1599             // Program in the following parameters:
1600             //  - SSx  (Source      burst size of [ccr_ss_ds_mask])
1601             //  - DSx  (Destination burst size of [ccr_ss_ds_mask])
1602             //  - DAF  (Destination address fixed)
1603             //  - SB16 (Source      burst length of 16 transfers)
1604             //  - DB16 (Destination burst length of 16 transfers)
1605             //  - All other options default.
1606 
1607             if (status == ALT_E_SUCCESS)
1608             {
1609                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1610                                                 (   ccr_ss_ds_mask
1611                                                   | ALT_DMA_CCR_OPT_SB16
1612                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1613                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1614                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1615                                                   | ALT_DMA_CCR_OPT_DB16
1616                                                   | ALT_DMA_CCR_OPT_DAF
1617                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1618                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1619                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1620                                                 )
1621                     );
1622             }
1623 
1624             uint32_t length16burst = countleft >> 4;
1625             countleft &= 0xf;
1626 
1627             dprintf("DMA[M->R]:   Number of 16 burst length transfer(s): %lu.\n", length16burst);
1628             dprintf("DMA[M->R]:   Number of remaining transfer(s):       %lu.\n", countleft);
1629 
1630             // See how many 256x 16-length bursts we can use
1631             if (length16burst >> 8)
1632             {
1633                 uint32_t loop256length16burst = length16burst >> 8;
1634                 length16burst &= ((1 << 8) - 1);
1635 
1636                 dprintf("DMA[M->R]:     Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst);
1637                 dprintf("DMA[M->R]:     Number of remaining 16 burst length transfer(s):  %lu.\n", length16burst);
1638 
1639                 while (loop256length16burst > 0)
1640                 {
1641                     if (status != ALT_E_SUCCESS)
1642                     {
1643                         break;
1644                     }
1645 
1646                     uint32_t loopcount = MIN(loop256length16burst, 256);
1647                     loop256length16burst -= loopcount;
1648 
1649                     dprintf("DMA[M->R]:     Looping %lux super loop transfer(s).\n", loopcount);
1650 
1651                     if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1652                     {
1653                         status = alt_dma_program_DMALP(program, loopcount);
1654                     }
1655 
1656                     if (status == ALT_E_SUCCESS)
1657                     {
1658                         status = alt_dma_program_DMALP(program, 256);
1659                     }
1660                     if (status == ALT_E_SUCCESS)
1661                     {
1662                         status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1663                     }
1664                     if (status == ALT_E_SUCCESS)
1665                     {
1666                         status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1667                     }
1668                     if (status == ALT_E_SUCCESS)
1669                     {
1670                         status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1671                     }
1672 
1673                     if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1674                     {
1675                         status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1676                     }
1677                 }
1678             }
1679 
1680             // The super loop above ensures that the length16burst is below 256.
1681             if (length16burst > 0)
1682             {
1683                 uint32_t loopcount = length16burst;
1684                 length16burst = 0;
1685 
1686                 dprintf("DMA[M->R]:   Looping %lux 16 burst length transfer(s).\n", loopcount);
1687 
1688                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1689                 {
1690                     status = alt_dma_program_DMALP(program, loopcount);
1691                 }
1692                 if (status == ALT_E_SUCCESS)
1693                 {
1694                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1695                 }
1696                 if (status == ALT_E_SUCCESS)
1697                 {
1698                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1699                 }
1700                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1701                 {
1702                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1703                 }
1704             }
1705         }
1706 
1707         // At this point, we should have [countleft] transfer(s) remaining.
1708         // [countleft] should be less than 16.
1709 
1710         if (countleft)
1711         {
1712             // Program in the following parameters:
1713             //  - SSx (Source      burst size of [ccr_ss_ds_mask])
1714             //  - DSx (Destination burst size of [ccr_ss_ds_mask])
1715             //  - DAF (Destination address fixed)
1716             //  - SBx (Source      burst length of [countleft] transfer(s))
1717             //  - DBx (Destination burst length of [countleft] transfer(s))
1718             //  - All other options default.
1719 
1720             if (status == ALT_E_SUCCESS)
1721             {
1722                 dprintf("DMA[M->R]:   Tail end %lux transfer(s).\n", countleft);
1723 
1724                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1725                                                 (   ccr_ss_ds_mask
1726                                                   | ((countleft - 1) << 4) // SB
1727                                                   | ALT_DMA_CCR_OPT_SA_DEFAULT
1728                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1729                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1730                                                   | ((countleft - 1) << 18) // DB
1731                                                   | ALT_DMA_CCR_OPT_DAF
1732                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1733                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1734                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1735                                                 )
1736                     );
1737             }
1738             if (status == ALT_E_SUCCESS)
1739             {
1740                 status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1741             }
1742             if (status == ALT_E_SUCCESS)
1743             {
1744                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1745             }
1746         }
1747 
1748     } // if (count != 0)
1749 
1750     // Send event if requested.
1751     if (send_evt)
1752     {
1753         if (status == ALT_E_SUCCESS)
1754         {
1755             dprintf("DMA[M->R]: Adding event ...\n");
1756             status = alt_dma_program_DMASEV(program, evt);
1757         }
1758     }
1759 
1760     // Now that everything is done, end the program.
1761     if (status == ALT_E_SUCCESS)
1762     {
1763         dprintf("DMA[M->R]: DMAEND program.\n");
1764         status = alt_dma_program_DMAEND(program);
1765     }
1766 
1767     // If there was a problem assembling the program, clean up the buffer and exit.
1768     if (status != ALT_E_SUCCESS)
1769     {
1770         // Do not report the status for the clear operation. A failure should be
1771         // reported regardless of if the clear is successful.
1772         alt_dma_program_clear(program);
1773         return status;
1774     }
1775 
1776     // Execute the program on the given channel.
1777     return alt_dma_channel_exec(channel, program);
1778 }
1779 
1780 ALT_STATUS_CODE alt_dma_register_to_memory(ALT_DMA_CHANNEL_t channel,
1781                                            ALT_DMA_PROGRAM_t * program,
1782                                            void * dst_buf,
1783                                            const void * src_reg,
1784                                            size_t count,
1785                                            uint32_t register_width_bits,
1786                                            bool send_evt,
1787                                            ALT_DMA_EVENT_t evt)
1788 {
1789     ALT_STATUS_CODE status = ALT_E_SUCCESS;
1790 
1791     // If the count is zero, and no event is requested, just return success.
1792     if ((count == 0) && (send_evt == false))
1793     {
1794         return status;
1795     }
1796 
1797     if (status == ALT_E_SUCCESS)
1798     {
1799         status = alt_dma_program_init(program);
1800     }
1801 
1802     if (count != 0)
1803     {
1804         // Verify valid register_width_bits and construct the CCR SS and DS parameters.
1805         uint32_t ccr_ss_ds_mask = 0;
1806 
1807         if (status == ALT_E_SUCCESS)
1808         {
1809             switch (register_width_bits)
1810             {
1811             case 8:
1812                 // Program in the following parameters:
1813                 //  - SS8 (Source      burst size of 8 bits)
1814                 //  - DS8 (Destination burst size of 8 bits)
1815                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8;
1816                 break;
1817             case 16:
1818                 // Program in the following parameters:
1819                 //  - SS16 (Source      burst size of 16 bits)
1820                 //  - DS16 (Destination burst size of 16 bits)
1821                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16;
1822                 break;
1823             case 32:
1824                 // Program in the following parameters:
1825                 //  - SS32 (Source      burst size of 32 bits)
1826                 //  - DS32 (Destination burst size of 32 bits)
1827                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32;
1828                 break;
1829             case 64:
1830                 // Program in the following parameters:
1831                 //  - SS64 (Source      burst size of 64 bits)
1832                 //  - DS64 (Destination burst size of 64 bits)
1833                 ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64;
1834                 break;
1835             default:
1836                 dprintf("DMA[R->M]: Invalid register width.\n");
1837                 status = ALT_E_BAD_ARG;
1838                 break;
1839             }
1840         }
1841 
1842         // Verify that the dst_buf and src_reg are aligned to the register width
1843         if (status == ALT_E_SUCCESS)
1844         {
1845             if      (((uintptr_t)dst_buf & ((register_width_bits >> 3) - 1)) != 0)
1846             {
1847                 status = ALT_E_BAD_ARG;
1848             }
1849             else if (((uintptr_t)src_reg & ((register_width_bits >> 3) - 1)) != 0)
1850             {
1851                 status = ALT_E_BAD_ARG;
1852             }
1853             else
1854             {
1855                 dprintf("DMA[R->M]: dst_reg = %p.\n",   dst_buf);
1856                 dprintf("DMA[R->M]: src_buf = %p.\n",   src_reg);
1857                 dprintf("DMA[R->M]: count   = 0x%x.\n", count);
1858             }
1859         }
1860 
1861         if (status == ALT_E_SUCCESS)
1862         {
1863             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_reg);
1864         }
1865         if (status == ALT_E_SUCCESS)
1866         {
1867             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_buf);
1868         }
1869 
1870         // This is the remaining count left to process.
1871         uint32_t countleft = count;
1872 
1873         // See how many 16-length bursts we can use
1874         if (countleft >> 4)
1875         {
1876             uint32_t length16burst = countleft >> 4;
1877             countleft &= 0xf;
1878 
1879             dprintf("DMA[R->M]:   Number of 16 burst length transfer(s): %lu.\n", length16burst);
1880             dprintf("DMA[R->M]:   Number of remaining transfer(s):       %lu.\n", countleft);
1881 
1882             //
1883             // The algorithm uses the strategy described in PL330 B.2.3.
1884             // Not sure if registers will accept burst transfers so read the register in its own transfer.
1885             //
1886 
1887             // Program in the following parameters:
1888             //  - SAF  (Source      address fixed)
1889             //  - SSx  (Source      burst size of [ccr_ss_ds_mask])
1890             //  - DSx  (Destination burst size of [ccr_ss_ds_mask])
1891             //  - SB16 (Source      burst length of 16 transfers)
1892             //  - DB16 (Destination burst length of 16 transfers)
1893             //  - All other options default.
1894 
1895             if (status == ALT_E_SUCCESS)
1896             {
1897                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
1898                                                 (   ccr_ss_ds_mask
1899                                                   | ALT_DMA_CCR_OPT_SB16
1900                                                   | ALT_DMA_CCR_OPT_SAF
1901                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
1902                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
1903                                                   | ALT_DMA_CCR_OPT_DB16
1904                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
1905                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
1906                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
1907                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
1908                                                 )
1909                     );
1910             }
1911 
1912             // See how many 256x 16-length bursts we can do
1913             if (length16burst >> 8)
1914             {
1915                 uint32_t loop256length16burst = length16burst >> 8;
1916                 length16burst &= ((1 << 8) - 1);
1917 
1918                 dprintf("DMA[R->M]:     Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst);
1919                 dprintf("DMA[R->M]:     Number of remaining 16 burst length transfer(s):  %lu.\n", length16burst);
1920 
1921                 while (loop256length16burst > 0)
1922                 {
1923                     if (status != ALT_E_SUCCESS)
1924                     {
1925                         break;
1926                     }
1927 
1928                     uint32_t loopcount = MIN(loop256length16burst, 256);
1929                     loop256length16burst -= loopcount;
1930 
1931                     dprintf("DMA[R->M]:     Looping %lux super loop transfer(s).\n", loopcount);
1932 
1933                     if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1934                     {
1935                         status = alt_dma_program_DMALP(program, loopcount);
1936                     }
1937 
1938                     if (status == ALT_E_SUCCESS)
1939                     {
1940                         status = alt_dma_program_DMALP(program, 256);
1941                     }
1942                     if (status == ALT_E_SUCCESS)
1943                     {
1944                         status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1945                     }
1946                     if (status == ALT_E_SUCCESS)
1947                     {
1948                         status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1949                     }
1950                     if (status == ALT_E_SUCCESS)
1951                     {
1952                         status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1953                     }
1954 
1955                     if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1956                     {
1957                         status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1958                     }
1959                 }
1960             }
1961 
1962             // The super loop above ensures that the length16burst is below 256.
1963             if (length16burst > 0)
1964             {
1965                 uint32_t loopcount = length16burst;
1966                 length16burst = 0;
1967 
1968                 dprintf("DMA[R->M]:   Looping %lux 16 burst length transfer(s).\n", loopcount);
1969 
1970                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1971                 {
1972                     status = alt_dma_program_DMALP(program, loopcount);
1973                 }
1974                 if (status == ALT_E_SUCCESS)
1975                 {
1976                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1977                 }
1978                 if (status == ALT_E_SUCCESS)
1979                 {
1980                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1981                 }
1982                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
1983                 {
1984                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
1985                 }
1986             }
1987         }
1988 
1989         // At this point, we should have [countleft] transfer(s) remaining.
1990         // [countleft] should be less than 16.
1991 
1992         if (countleft)
1993         {
1994             dprintf("DMA[R->M]:   Tail end %lux transfer(s).\n", countleft);
1995 
1996             // Program in the following parameters:
1997             //  - SAF (Source      address fixed)
1998             //  - SSx (Source      burst size of [ccr_ss_ds_mask])
1999             //  - DSx (Destination burst size of [ccr_ss_ds_mask])
2000             //  - SBx (Source      burst length of [countleft] transfer(s))
2001             //  - DBx (Destination burst length of [countleft] transfer(s))
2002             //  - All other options default.
2003 
2004             if (status == ALT_E_SUCCESS)
2005             {
2006                 status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2007                                                 (   ccr_ss_ds_mask
2008                                                   | ((countleft - 1) << 4) // SB
2009                                                   | ALT_DMA_CCR_OPT_SAF
2010                                                   | ALT_DMA_CCR_OPT_SP_DEFAULT
2011                                                   | ALT_DMA_CCR_OPT_SC_DEFAULT
2012                                                   | ((countleft - 1) << 18) // DB
2013                                                   | ALT_DMA_CCR_OPT_DA_DEFAULT
2014                                                   | ALT_DMA_CCR_OPT_DP_DEFAULT
2015                                                   | ALT_DMA_CCR_OPT_DC_DEFAULT
2016                                                   | ALT_DMA_CCR_OPT_ES_DEFAULT
2017                                                 )
2018                     );
2019             }
2020 
2021             if (status == ALT_E_SUCCESS)
2022             {
2023                 status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2024             }
2025             if (status == ALT_E_SUCCESS)
2026             {
2027                 status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2028             }
2029         }
2030 
2031     } // if (count != 0)
2032 
2033     // Send event if requested.
2034     if (send_evt)
2035     {
2036         if (status == ALT_E_SUCCESS)
2037         {
2038             dprintf("DMA[R->M]: Adding event ...\n");
2039             status = alt_dma_program_DMASEV(program, evt);
2040         }
2041     }
2042 
2043     // Now that everything is done, end the program.
2044     if (status == ALT_E_SUCCESS)
2045     {
2046         status = alt_dma_program_DMAEND(program);
2047     }
2048 
2049     // If there was a problem assembling the program, clean up the buffer and exit.
2050     if (status != ALT_E_SUCCESS)
2051     {
2052         // Do not report the status for the clear operation. A failure should be
2053         // reported regardless of if the clear is successful.
2054         alt_dma_program_clear(program);
2055         return status;
2056     }
2057 
2058     // Execute the program on the given channel.
2059     return alt_dma_channel_exec(channel, program);
2060 }
2061 
2062 #if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
2063 static ALT_STATUS_CODE alt_dma_memory_to_qspi(ALT_DMA_PROGRAM_t * program,
2064                                               const char * src,
2065                                               size_t size)
2066 {
2067     if ((uintptr_t)src & 0x3)
2068     {
2069         return ALT_E_ERROR;
2070     }
2071 
2072     if (size & 0x3)
2073     {
2074         return ALT_E_ERROR;
2075     }
2076 
2077     /////
2078 
2079     ALT_STATUS_CODE status = ALT_E_SUCCESS;
2080 
2081     if (status == ALT_E_SUCCESS)
2082     {
2083         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
2084                                         (uint32_t)ALT_QSPIDATA_ADDR);
2085     }
2086     if (status == ALT_E_SUCCESS)
2087     {
2088         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
2089                                         (uint32_t)src);
2090     }
2091 
2092     /////
2093 
2094     uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2095     uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper);
2096     uint32_t qspi_burst_size_log2  = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper);
2097     uint32_t qspi_single_size      = 1 << qspi_single_size_log2;
2098     uint32_t qspi_burst_size       = 1 << qspi_burst_size_log2;
2099 
2100     dprintf("DMA[M->P][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size);
2101 
2102     // Because single transfers are equal or smaller than burst (and in the
2103     // smaller case, it is always a clean multiple), only the single size
2104     // check is needed for transfer composability.
2105     if (size & (qspi_single_size - 1))
2106     {
2107         dprintf("DMA[M->P][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n");
2108         return ALT_E_ERROR;
2109     }
2110 
2111     /////
2112 
2113     if ((uintptr_t)src & 0x7)
2114     {
2115         // Source address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned.
2116 
2117         dprintf("DMA[M->P][QSPI]: Creating 1x 4-byte aligning transfer.\n");
2118 
2119         if (status == ALT_E_SUCCESS)
2120         {
2121             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2122                                             (   ALT_DMA_CCR_OPT_SAI
2123                                               | ALT_DMA_CCR_OPT_SS32
2124                                               | ALT_DMA_CCR_OPT_SB1
2125                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2126                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2127                                               | ALT_DMA_CCR_OPT_DAF
2128                                               | ALT_DMA_CCR_OPT_DS32
2129                                               | ALT_DMA_CCR_OPT_DB1
2130                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2131                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2132                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2133                                             )
2134                 );
2135         }
2136 
2137         if (status == ALT_E_SUCCESS)
2138         {
2139             status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2140         }
2141 
2142         if (status == ALT_E_SUCCESS)
2143         {
2144             status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2145         }
2146 
2147         if (status == ALT_E_SUCCESS)
2148         {
2149             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2150         }
2151 
2152         if (status == ALT_E_SUCCESS)
2153         {
2154             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2155         }
2156 
2157         size -= sizeof(uint32_t);
2158     }
2159 
2160     uint32_t qspi_single_count = 0;
2161     uint32_t qspi_burst_count  = size >> qspi_burst_size_log2;
2162 
2163     // Use QSPI burst transfers if:
2164     //  - QSPI bursts are larger than QSPI singles [AND]
2165     //  - Size is large enough that at least 1 burst will be used.
2166 
2167     if (   (qspi_burst_size_log2 > qspi_single_size_log2)
2168         && (qspi_burst_count != 0)
2169        )
2170     {
2171         // qspi_burst_count = size >> qspi_burst_size_log2;
2172         qspi_single_count   = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2;
2173 
2174         dprintf("DMA[M->P][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count);
2175 
2176         // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2177         uint32_t src_size_log2 = MIN(3, qspi_burst_size_log2);
2178 
2179         uint32_t src_length   = 0;
2180         uint32_t src_multiple = 0;
2181 
2182         if ((qspi_burst_size >> src_size_log2) <= 16)
2183         {
2184             src_length   = qspi_burst_size >> src_size_log2;
2185             src_multiple = 1;
2186         }
2187         else
2188         {
2189             src_length   = 16;
2190             src_multiple = (qspi_burst_size >> src_size_log2) >> 4; // divide by 16
2191 
2192             if (src_multiple == 0)
2193             {
2194                 dprintf("DEBUG[QSPI][B]: src_multiple is 0.\n");
2195                 status = ALT_E_ERROR;
2196             }
2197         }
2198 
2199         // uint32_t dst_length = 1; // dst_length is always 1 because the address is fixed.
2200         uint32_t dst_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t)
2201 
2202         dprintf("DMA[M->P][QSPI][B]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n",
2203                 32,                       1,          dst_multiple);
2204         dprintf("DMA[M->P][QSPI][B]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n",
2205                 (1 << src_size_log2) * 8, src_length, src_multiple);
2206 
2207         /////
2208 
2209         // Program in the following parameters:
2210         //  - SAI  (Source      address increment)
2211         //  - SSx  (Source      burst size of [1 << src_size_log2]-bytes)
2212         //  - SBx  (Source      burst length of [src_length] transfer(s))
2213         //  - DAF  (Destination address fixed)
2214         //  - DS32 (Destination burst size of 4-bytes)
2215         //  - DB1  (Destination burst length of 1 transfer)
2216         //  - All other parameters default
2217 
2218         if (status == ALT_E_SUCCESS)
2219         {
2220             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2221                                             (   ALT_DMA_CCR_OPT_SAI
2222                                               | (src_size_log2 << 1) // SS
2223                                               | ((src_length - 1) << 4) // SB
2224                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2225                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2226                                               | ALT_DMA_CCR_OPT_DAF
2227                                               | ALT_DMA_CCR_OPT_DS32
2228                                               | ALT_DMA_CCR_OPT_DB1
2229                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2230                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2231                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2232                                             )
2233                 );
2234         }
2235 
2236         // NOTE: We do not do the 256x bursts for M->P case because we only
2237         //   write up to 256 B at a time.
2238 
2239         while (qspi_burst_count > 0)
2240         {
2241             if (status != ALT_E_SUCCESS)
2242             {
2243                 break;
2244             }
2245 
2246             uint32_t loopcount = MIN(qspi_burst_count, 256);
2247             qspi_burst_count -= loopcount;
2248 
2249             dprintf("DMA[M->P][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount);
2250 
2251             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2252             {
2253                 status = alt_dma_program_DMALP(program, loopcount);
2254             }
2255 
2256             if (status == ALT_E_SUCCESS)
2257             {
2258                 status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2259             }
2260             if (status == ALT_E_SUCCESS)
2261             {
2262                 status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2263             }
2264             for (uint32_t j = 0; j < src_multiple; ++j)
2265             {
2266                 if (status == ALT_E_SUCCESS)
2267                 {
2268                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2269                 }
2270             }
2271             for (uint32_t k = 0; k < dst_multiple; ++k)
2272             {
2273                 if (status == ALT_E_SUCCESS)
2274                 {
2275                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2276                 }
2277             }
2278 
2279             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2280             {
2281                 status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2282             }
2283         }
2284     }
2285     else
2286     {
2287         qspi_single_count = size >> qspi_single_size_log2;
2288     }
2289 
2290     // Assemble the single portion of the DMA program.
2291     if (qspi_single_count)
2292     {
2293         dprintf("DMA[M->P][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count);
2294 
2295         // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2296         uint32_t src_size_log2 = MIN(3, qspi_single_size_log2);
2297 
2298         uint32_t src_length   = 0;
2299         uint32_t src_multiple = 0;
2300 
2301         if ((qspi_single_size >> src_size_log2) <= 16)
2302         {
2303             src_length   = qspi_single_size >> src_size_log2;
2304             src_multiple = 1;
2305         }
2306         else
2307         {
2308             src_length   = 16;
2309             src_multiple = (qspi_single_size >> src_size_log2) >> 4; // divide by 16
2310 
2311             if (src_multiple == 0)
2312             {
2313                 dprintf("DEBUG[QSPI][S]: src_multiple is 0.\n");
2314                 status = ALT_E_ERROR;
2315             }
2316         }
2317 
2318         // uint32_t dst_length = 1; // dst_length is always 1 becaus the address is fixed.
2319         uint32_t dst_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t)
2320 
2321         dprintf("DMA[M->P][QSPI][S]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n",
2322                 32,                      1,          dst_multiple);
2323         dprintf("DMA[M->P][QSPI][S]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n",
2324                 (1 <<src_size_log2) * 8, src_length, src_multiple);
2325 
2326         /////
2327 
2328         // Program in the following parameters:
2329         //  - SAI  (Source      address increment)
2330         //  - SSx  (Source      burst size of [1 << src_size_log2]-bytes)
2331         //  - SBx  (Source      burst length of [src_length] transfer(s))
2332         //  - DAF  (Destination address fixed)
2333         //  - DS32 (Destination burst size of 4-bytes)
2334         //  - DB1  (Destination burst length of 1 transfer)
2335         //  - All other parameters default
2336 
2337         if (status == ALT_E_SUCCESS)
2338         {
2339             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2340                                             (   ALT_DMA_CCR_OPT_SAI
2341                                               | (src_size_log2 << 1) // SS
2342                                               | ((src_length - 1) << 4) // SB
2343                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2344                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2345                                               | ALT_DMA_CCR_OPT_DAF
2346                                               | ALT_DMA_CCR_OPT_DS32
2347                                               | ALT_DMA_CCR_OPT_DB1
2348                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2349                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2350                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2351                                             )
2352                 );
2353         }
2354 
2355         // NOTE: We do not do the 256x bursts for M->P case because we only
2356         //   write up to 256 B at a time.
2357 
2358         while (qspi_single_count > 0)
2359         {
2360             if (status != ALT_E_SUCCESS)
2361             {
2362                 break;
2363             }
2364 
2365             uint32_t loopcount = MIN(qspi_single_count, 256);
2366             qspi_single_count -= loopcount;
2367 
2368             dprintf("DMA[M->P][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount);
2369 
2370             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2371             {
2372                 status = alt_dma_program_DMALP(program, loopcount);
2373             }
2374 
2375             if (status == ALT_E_SUCCESS)
2376             {
2377                 status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX);
2378             }
2379             if (status == ALT_E_SUCCESS)
2380             {
2381                 status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2382             }
2383             for (uint32_t j = 0; j < src_multiple; ++j)
2384             {
2385                 if (status == ALT_E_SUCCESS)
2386                 {
2387                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2388                 }
2389             }
2390             for (uint32_t k = 0; k < dst_multiple; ++k)
2391             {
2392                 if (status == ALT_E_SUCCESS)
2393                 {
2394                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2395                 }
2396             }
2397 
2398             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2399             {
2400                 status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2401             }
2402         }
2403 
2404     } // if (qspi_single_count != 0)
2405 
2406     return status;
2407 }
2408 
2409 static ALT_STATUS_CODE alt_dma_qspi_to_memory(ALT_DMA_PROGRAM_t * program,
2410                                               char * dst,
2411                                               size_t size)
2412 {
2413     if ((uintptr_t)dst & 0x3)
2414     {
2415         return ALT_E_ERROR;
2416     }
2417 
2418     if (size & 0x3)
2419     {
2420         return ALT_E_ERROR;
2421     }
2422 
2423     /////
2424 
2425     ALT_STATUS_CODE status = ALT_E_SUCCESS;
2426 
2427     if (status == ALT_E_SUCCESS)
2428     {
2429         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
2430                                         (uint32_t)dst);
2431     }
2432     if (status == ALT_E_SUCCESS)
2433     {
2434         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
2435                                         (uint32_t)ALT_QSPIDATA_ADDR);
2436     }
2437 
2438     /////
2439 
2440     uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2441     uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper);
2442     uint32_t qspi_burst_size_log2  = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper);
2443     uint32_t qspi_single_size      = 1 << qspi_single_size_log2;
2444     uint32_t qspi_burst_size       = 1 << qspi_burst_size_log2;
2445 
2446     dprintf("DMA[P->M][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size);
2447 
2448     // Because single transfers are equal or smaller than burst (and in the
2449     // smaller case, it is always a clean multiple), only the single size
2450     // check is needed for transfer composability.
2451     if (size & (qspi_single_size - 1))
2452     {
2453         dprintf("DMA[P->M][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n");
2454         return ALT_E_ERROR;
2455     }
2456 
2457     /////
2458 
2459     if ((uintptr_t)dst & 0x7)
2460     {
2461         // Destination address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned.
2462 
2463         dprintf("DMA[P->M][QSPI]: Creating 1x 4-byte aligning transfer.\n");
2464 
2465         if (status == ALT_E_SUCCESS)
2466         {
2467             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2468                                             (   ALT_DMA_CCR_OPT_SAF
2469                                               | ALT_DMA_CCR_OPT_SS32
2470                                               | ALT_DMA_CCR_OPT_SB1
2471                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2472                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2473                                               | ALT_DMA_CCR_OPT_DAI
2474                                               | ALT_DMA_CCR_OPT_DS32
2475                                               | ALT_DMA_CCR_OPT_DB1
2476                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2477                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2478                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2479                                             )
2480                 );
2481         }
2482 
2483         if (status == ALT_E_SUCCESS)
2484         {
2485             status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2486         }
2487 
2488         if (status == ALT_E_SUCCESS)
2489         {
2490             status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2491         }
2492 
2493         if (status == ALT_E_SUCCESS)
2494         {
2495             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2496         }
2497 
2498         if (status == ALT_E_SUCCESS)
2499         {
2500             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2501         }
2502 
2503         size -= sizeof(uint32_t);
2504     }
2505 
2506     uint32_t qspi_single_count = 0;
2507     uint32_t qspi_burst_count  = size >> qspi_burst_size_log2;
2508 
2509     // Use QSPI burst transfers if:
2510     //  - QSPI bursts are larger than QSPI singles [AND]
2511     //  - Size is large enough that at least 1 burst will be used.
2512 
2513     if (   (qspi_burst_size_log2 > qspi_single_size_log2)
2514         && (qspi_burst_count != 0)
2515        )
2516     {
2517         // qspi_burst_count = size >> qspi_burst_size_log2;
2518         qspi_single_count   = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2;
2519 
2520         dprintf("DMA[P->M][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count);
2521 
2522         // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2523         uint32_t dst_size_log2 = MIN(3, qspi_burst_size_log2);
2524 
2525         uint32_t dst_length   = 0;
2526         uint32_t dst_multiple = 0;
2527 
2528         if ((qspi_burst_size >> dst_size_log2) <= 16)
2529         {
2530             dst_length   = qspi_burst_size >> dst_size_log2;
2531             dst_multiple = 1;
2532         }
2533         else
2534         {
2535             dst_length   = 16;
2536             dst_multiple = (qspi_burst_size >> dst_size_log2) >> 4; // divide by 16
2537 
2538             if (dst_multiple == 0)
2539             {
2540                 dprintf("DEBUG[QSPI][B]: dst_multiple is 0.\n");
2541                 status = ALT_E_ERROR;
2542             }
2543         }
2544 
2545         // uint32_t src_length = 1; // src_length is always 1 because the address is fixed.
2546         uint32_t src_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t)
2547 
2548         dprintf("DMA[P->M][QSPI][B]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n", 
2549                 (1 << dst_size_log2) * 8, dst_length, dst_multiple);
2550         dprintf("DMA[P->M][QSPI][B]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n",
2551                 32,                       1,          src_multiple);
2552 
2553         /////
2554 
2555         // Program in the following parameters:
2556         //  - SAF  (Source      address fixed)
2557         //  - SS32 (Source      burst size of 4-bytes)
2558         //  - SB1  (Source      burst length of 1 transfer)
2559         //  - DAI  (Destination address increment)
2560         //  - DSx  (Destination burst size of [1 << dst_size_log2]-bytes])
2561         //  - DBx  (Destination burst length of [dst_length] transfer(s))
2562         //  - All other parameters default
2563 
2564         if (status == ALT_E_SUCCESS)
2565         {
2566             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2567                                             (   ALT_DMA_CCR_OPT_SAF
2568                                               | ALT_DMA_CCR_OPT_SS32
2569                                               | ALT_DMA_CCR_OPT_SB1
2570                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2571                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2572                                               | ALT_DMA_CCR_OPT_DAI
2573                                               | (dst_size_log2 << 15) // DS
2574                                               | ((dst_length - 1) << 18) // DB
2575                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2576                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2577                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2578                                             )
2579                 );
2580         }
2581 
2582         // See how many 256x bursts we can construct. This will allow for extremely large requests.
2583 
2584         if (qspi_burst_count >> 8)
2585         {
2586             uint32_t qspi_burst256_count = qspi_burst_count >> 8;
2587             qspi_burst_count &= (1 << 8) - 1;
2588 
2589             while (qspi_burst256_count > 0)
2590             {
2591                 if (status != ALT_E_SUCCESS)
2592                 {
2593                     break;
2594                 }
2595 
2596                 uint32_t loopcount = MIN(qspi_burst256_count, 256);
2597                 qspi_burst256_count -= loopcount;
2598 
2599                 dprintf("DMA[P->M][QSPI][B]: Creating %lu 256x burst-type transfer(s).\n", loopcount);
2600 
2601                 // Outer loop {
2602 
2603                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2604                 {
2605                     status = alt_dma_program_DMALP(program, loopcount);
2606                 }
2607 
2608                 // Inner loop {
2609 
2610                 if (status == ALT_E_SUCCESS)
2611                 {
2612                     status = alt_dma_program_DMALP(program, 256);
2613                 }
2614 
2615                 if (status == ALT_E_SUCCESS)
2616                 {
2617                     status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2618                 }
2619                 if (status == ALT_E_SUCCESS)
2620                 {
2621                     status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2622                 }
2623                 for (uint32_t j = 0; j < src_multiple; ++j)
2624                 {
2625                     if (status == ALT_E_SUCCESS)
2626                     {
2627                         status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2628                     }
2629                 }
2630                 for (uint32_t k = 0; k < dst_multiple; ++k)
2631                 {
2632                     if (status == ALT_E_SUCCESS)
2633                     {
2634                         status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2635                     }
2636                 }
2637 
2638                 if (status == ALT_E_SUCCESS)
2639                 {
2640                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2641                 }
2642 
2643                 // } Inner loop
2644 
2645                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2646                 {
2647                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2648                 }
2649 
2650                 // } Outer loop
2651             }
2652         }
2653 
2654         while (qspi_burst_count > 0)
2655         {
2656             if (status != ALT_E_SUCCESS)
2657             {
2658                 break;
2659             }
2660 
2661             uint32_t loopcount = MIN(qspi_burst_count, 256);
2662             qspi_burst_count -= loopcount;
2663 
2664             dprintf("DMA[P->M][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount);
2665 
2666             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2667             {
2668                 status = alt_dma_program_DMALP(program, loopcount);
2669             }
2670 
2671             if (status == ALT_E_SUCCESS)
2672             {
2673                 status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2674             }
2675             if (status == ALT_E_SUCCESS)
2676             {
2677                 status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST);
2678             }
2679             for (uint32_t j = 0; j < src_multiple; ++j)
2680             {
2681                 if (status == ALT_E_SUCCESS)
2682                 {
2683                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2684                 }
2685             }
2686             for (uint32_t k = 0; k < dst_multiple; ++k)
2687             {
2688                 if (status == ALT_E_SUCCESS)
2689                 {
2690                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
2691                 }
2692             }
2693 
2694             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2695             {
2696                 status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2697             }
2698         }
2699     }
2700     else
2701     {
2702         qspi_single_count = size >> qspi_single_size_log2;
2703     }
2704 
2705     // Assemble the single portion of the DMA program.
2706     if (qspi_single_count)
2707     {
2708         dprintf("DMA[P->M][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count);
2709 
2710         // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus.
2711         uint32_t dst_size_log2 = MIN(3, qspi_single_size_log2);
2712 
2713         uint32_t dst_length   = 0;
2714         uint32_t dst_multiple = 0;
2715 
2716         if ((qspi_single_size >> dst_size_log2) <= 16)
2717         {
2718             dst_length   = qspi_single_size >> dst_size_log2;
2719             dst_multiple = 1;
2720         }
2721         else
2722         {
2723             dst_length   = 16;
2724             dst_multiple = (qspi_single_size >> dst_size_log2) >> 4; // divide by 16
2725 
2726             if (dst_multiple == 0)
2727             {
2728                 dprintf("DEBUG[QSPI][S]: dst_multiple is 0.\n");
2729                 status = ALT_E_ERROR;
2730             }
2731         }
2732 
2733         // uint32_t src_length = 1; // src_length is always 1 because the address is fixed.
2734         uint32_t src_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t)
2735 
2736         dprintf("DMA[P->M][QSPI][S]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n",
2737                 (1 << dst_size_log2) * 8, dst_length, dst_multiple);
2738         dprintf("DMA[P->M][QSPI][S]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n",
2739                 32,                       1,          src_multiple);
2740 
2741         /////
2742 
2743         // Program in the following parameters:
2744         //  - SAF  (Source      address fixed)
2745         //  - SS32 (Source      burst size of 4-bytes)
2746         //  - SB1  (Source      burst length of 1 transfer)
2747         //  - DAI  (Destination address increment)
2748         //  - DSx  (Destination burst size of [1 << dst_size_log2]-bytes])
2749         //  - DBx  (Destination burst length of [dst_length] transfer(s))
2750         //  - All other parameters default
2751 
2752         if (status == ALT_E_SUCCESS)
2753         {
2754             status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2755                                             (   ALT_DMA_CCR_OPT_SAF
2756                                               | ALT_DMA_CCR_OPT_SS32
2757                                               | ALT_DMA_CCR_OPT_SB1
2758                                               | ALT_DMA_CCR_OPT_SP_DEFAULT
2759                                               | ALT_DMA_CCR_OPT_SC_DEFAULT
2760                                               | ALT_DMA_CCR_OPT_DAI
2761                                               | (dst_size_log2 << 15) // DS
2762                                               | ((dst_length - 1) << 18) // DB
2763                                               | ALT_DMA_CCR_OPT_DP_DEFAULT
2764                                               | ALT_DMA_CCR_OPT_DC_DEFAULT
2765                                               | ALT_DMA_CCR_OPT_ES_DEFAULT
2766                                             )
2767                 );
2768         }
2769 
2770         // See how many 256x bursts we can construct. This will allow for extremely large requests.
2771 
2772         if (qspi_single_count >> 8)
2773         {
2774             uint32_t qspi_single256_count = qspi_single_count >> 8;
2775             qspi_single_count &= (1 << 8) - 1;
2776 
2777             while (qspi_single256_count > 0)
2778             {
2779                 if (status != ALT_E_SUCCESS)
2780                 {
2781                     break;
2782                 }
2783 
2784                 uint32_t loopcount = MIN(qspi_single256_count, 256);
2785                 qspi_single256_count -= loopcount;
2786 
2787                 dprintf("DMA[P->M][QSPI][S]: Creating %lu 256x single-type transfer(s).\n", loopcount);
2788 
2789                 // Outer loop {
2790 
2791                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2792                 {
2793                     status = alt_dma_program_DMALP(program, loopcount);
2794                 }
2795 
2796                 // Inner loop {
2797 
2798                 if (status == ALT_E_SUCCESS)
2799                 {
2800                     status = alt_dma_program_DMALP(program, 256);
2801                 }
2802 
2803                 if (status == ALT_E_SUCCESS)
2804                 {
2805                     status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2806                 }
2807                 if (status == ALT_E_SUCCESS)
2808                 {
2809                     status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2810                 }
2811                 for (uint32_t j = 0; j < src_multiple; ++j)
2812                 {
2813                     if (status == ALT_E_SUCCESS)
2814                     {
2815                         status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2816                     }
2817                 }
2818                 for (uint32_t k = 0; k < dst_multiple; ++k)
2819                 {
2820                     if (status == ALT_E_SUCCESS)
2821                     {
2822                         status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2823                     }
2824                 }
2825 
2826                 if (status == ALT_E_SUCCESS)
2827                 {
2828                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2829                 }
2830 
2831                 // } Inner loop
2832 
2833                 if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2834                 {
2835                     status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2836                 }
2837 
2838                 // } Outer loop
2839             }
2840         }
2841 
2842         while (qspi_single_count > 0)
2843         {
2844             if (status != ALT_E_SUCCESS)
2845             {
2846                 break;
2847             }
2848 
2849             uint32_t loopcount = MIN(qspi_single_count, 256);
2850             qspi_single_count -= loopcount;
2851 
2852             dprintf("DMA[P->M][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount);
2853 
2854             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2855             {
2856                 status = alt_dma_program_DMALP(program, loopcount);
2857             }
2858 
2859             if (status == ALT_E_SUCCESS)
2860             {
2861                 status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX);
2862             }
2863             if (status == ALT_E_SUCCESS)
2864             {
2865                 status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2866             }
2867             for (uint32_t j = 0; j < src_multiple; ++j)
2868             {
2869                 if (status == ALT_E_SUCCESS)
2870                 {
2871                     status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2872                 }
2873             }
2874             for (uint32_t k = 0; k < dst_multiple; ++k)
2875             {
2876                 if (status == ALT_E_SUCCESS)
2877                 {
2878                     status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2879                 }
2880             }
2881 
2882             if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2883             {
2884                 status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE);
2885             }
2886         }
2887 
2888     } // if (qspi_single_count != 0)
2889 
2890     return status;
2891 }
2892 #endif // ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
2893 
2894 #if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
2895 static ALT_STATUS_CODE alt_dma_memory_to_16550_single(ALT_DMA_PROGRAM_t * program,
2896                                                       ALT_DMA_PERIPH_t periph,
2897                                                       size_t size)
2898 {
2899     ALT_STATUS_CODE status = ALT_E_SUCCESS;
2900 
2901     // Program in the following parameters:
2902     //  - SS8 (Source      burst size of 1-byte)
2903     //  - DS8 (Destination burst size of 1-byte)
2904     //  - SB1 (Source      burst length of 1 transfer)
2905     //  - DB1 (Destination burst length of 1 transfer)
2906     //  - DAF (Destination address fixed)
2907     //  - All other options default.
2908 
2909     if (status == ALT_E_SUCCESS)
2910     {
2911         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2912                                         (   ALT_DMA_CCR_OPT_SB1
2913                                           | ALT_DMA_CCR_OPT_SS8
2914                                           | ALT_DMA_CCR_OPT_SA_DEFAULT
2915                                           | ALT_DMA_CCR_OPT_SP_DEFAULT
2916                                           | ALT_DMA_CCR_OPT_SC_DEFAULT
2917                                           | ALT_DMA_CCR_OPT_DB1
2918                                           | ALT_DMA_CCR_OPT_DS8
2919                                           | ALT_DMA_CCR_OPT_DAF
2920                                           | ALT_DMA_CCR_OPT_DP_DEFAULT
2921                                           | ALT_DMA_CCR_OPT_DC_DEFAULT
2922                                           | ALT_DMA_CCR_OPT_ES_DEFAULT
2923                                         )
2924             );
2925     }
2926 
2927     uint32_t sizeleft = size;
2928 
2929     while (sizeleft > 0)
2930     {
2931         if (status != ALT_E_SUCCESS)
2932         {
2933             break;
2934         }
2935 
2936         uint32_t loopcount = MIN(sizeleft, 256);
2937         sizeleft -= loopcount;
2938 
2939         dprintf("DMA[M->P][16550][S]: Creating %lu transfer(s).\n", loopcount);
2940 
2941         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2942         {
2943             status = alt_dma_program_DMALP(program, loopcount);
2944         }
2945 
2946         if (status == ALT_E_SUCCESS)
2947         {
2948             status = alt_dma_program_DMAFLUSHP(program, periph);
2949         }
2950         if (status == ALT_E_SUCCESS)
2951         {
2952             status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2953         }
2954         if (status == ALT_E_SUCCESS)
2955         {
2956             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2957         }
2958         if (status == ALT_E_SUCCESS)
2959         {
2960             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2961         }
2962 
2963         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
2964         {
2965             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
2966         }
2967     }
2968 
2969     return status;
2970 }
2971 
2972 static ALT_STATUS_CODE alt_dma_memory_to_16550_burst(ALT_DMA_PROGRAM_t * program,
2973                                                      ALT_DMA_PERIPH_t periph,
2974                                                      size_t burst_size,
2975                                                      size_t burst_count)
2976 {
2977     ALT_STATUS_CODE status = ALT_E_SUCCESS;
2978 
2979     // Program in the following parameters:
2980     //  - SS8  (Source      burst size of 1-byte)
2981     //  - DS8  (Destination burst size of 1-byte)
2982     //  - SB16 (Source      burst length of 16 transfers)
2983     //  - DB16 (Destination burst length of 16 transfers)
2984     //  - DAF  (Source      address fixed)
2985     //  - All other options default.
2986 
2987     if (status == ALT_E_SUCCESS)
2988     {
2989         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
2990                                         (   ALT_DMA_CCR_OPT_SB16
2991                                           | ALT_DMA_CCR_OPT_SS8
2992                                           | ALT_DMA_CCR_OPT_SA_DEFAULT
2993                                           | ALT_DMA_CCR_OPT_SP_DEFAULT
2994                                           | ALT_DMA_CCR_OPT_SC_DEFAULT
2995                                           | ALT_DMA_CCR_OPT_DB16
2996                                           | ALT_DMA_CCR_OPT_DS8
2997                                           | ALT_DMA_CCR_OPT_DAF
2998                                           | ALT_DMA_CCR_OPT_DP_DEFAULT
2999                                           | ALT_DMA_CCR_OPT_DC_DEFAULT
3000                                           | ALT_DMA_CCR_OPT_ES_DEFAULT
3001                                         )
3002             );
3003     }
3004 
3005     while (burst_count > 0)
3006     {
3007         if (status != ALT_E_SUCCESS)
3008         {
3009             break;
3010         }
3011 
3012         uint32_t loopcount = MIN(burst_count, 256);
3013         burst_count -= loopcount;
3014 
3015         dprintf("DMA[M->P][16550][B]: Creating outer %lu inner loop(s).\n", loopcount);
3016 
3017         // Outer loop {
3018 
3019         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3020         {
3021             status = alt_dma_program_DMALP(program, loopcount);
3022         }
3023         if (status == ALT_E_SUCCESS)
3024         {
3025             status = alt_dma_program_DMAFLUSHP(program, periph);
3026         }
3027         if (status == ALT_E_SUCCESS)
3028         {
3029             status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST);
3030         }
3031 
3032         // Inner loop {
3033 
3034         // Loop [burst_size / 16] times. The burst_size was trimmed to the
3035         // nearest multiple of 16 by the caller. Each burst does 16 transfers
3036         // hence the need for the divide.
3037 
3038         dprintf("DMA[M->P][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4);
3039 
3040         if (status == ALT_E_SUCCESS)
3041         {
3042             status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16.
3043         }
3044         if (status == ALT_E_SUCCESS)
3045         {
3046             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3047         }
3048         if (status == ALT_E_SUCCESS)
3049         {
3050             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3051         }
3052         if (status == ALT_E_SUCCESS)
3053         {
3054             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3055         }
3056 
3057         // } Inner loop
3058 
3059         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3060         {
3061             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3062         }
3063 
3064         // } Outer loop
3065     }
3066 
3067     return status;
3068 }
3069 
3070 static ALT_STATUS_CODE alt_dma_memory_to_16550(ALT_DMA_PROGRAM_t * program,
3071                                                ALT_DMA_PERIPH_t periph,
3072                                                ALT_16550_HANDLE_t * handle,
3073                                                const void * src,
3074                                                size_t size)
3075 {
3076     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3077 
3078     if (status == ALT_E_SUCCESS)
3079     {
3080         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR,
3081                                         (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location));
3082     }
3083     if (status == ALT_E_SUCCESS)
3084     {
3085         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR,
3086                                         (uint32_t)src);
3087     }
3088 
3089     // Determine if FIFOs are enabled from the FCR cache
3090 
3091     if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0)
3092     {
3093         dprintf("DMA[M->P][16550]: FIFOs enabled.\n");
3094 
3095         //
3096         // FIFOs are enabled.
3097         //
3098 
3099         uint32_t tx_size;
3100         uint32_t burst_size;
3101         ALT_16550_FIFO_TRIGGER_TX_t trig_tx;
3102 
3103         // Get the TX FIFO Size
3104         // Use the register interface to avoid coupling the 16550 and DMA.
3105         tx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
3106 
3107         // Get the TX FIFO Trigger Level from the FCR cache
3108         trig_tx = (ALT_16550_FIFO_TRIGGER_TX_t)ALT_UART_FCR_TET_GET(handle->fcr);
3109 
3110         switch (trig_tx)
3111         {
3112         case ALT_16550_FIFO_TRIGGER_TX_EMPTY:
3113             burst_size = tx_size;
3114             break;
3115         case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY:
3116             burst_size = tx_size - 2;
3117             break;
3118         case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL:
3119             burst_size = 3 * (tx_size >> 2);
3120             break;
3121         case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL:
3122             burst_size = tx_size >> 1;
3123             break;
3124         default:
3125             // This case should never happen.
3126             return ALT_E_ERROR;
3127         }
3128 
3129         if (burst_size < 16)
3130         {
3131             // There's no point bursting 1 byte at a time per notify, so just do single transfers.
3132             if (status == ALT_E_SUCCESS)
3133             {
3134                 status = alt_dma_memory_to_16550_single(program,
3135                                                         periph,
3136                                                         size);
3137             }
3138         }
3139         else
3140         {
3141             uint32_t sizeleft = size;
3142 
3143             // Now trip the burst size to a multiple of 16.
3144             // This will optimize the bursting in the fewest possible commands.
3145             dprintf("DMA[M->P][16550]: Untrimmed burst size = %lu.\n", burst_size);
3146             burst_size &= ~0xf;
3147             dprintf("DMA[M->P][16550]: Trimmed burst size   = %lu.\n", burst_size);
3148 
3149             // Determine how many burst transfers can be done
3150             uint32_t burst_count = 0;
3151 
3152             burst_count = sizeleft / burst_size;
3153             sizeleft -= burst_count * burst_size;
3154 
3155             if (burst_count == 0)
3156             {
3157                 // Do the transfer
3158                 if (status == ALT_E_SUCCESS)
3159                 {
3160                     status = alt_dma_memory_to_16550_single(program,
3161                                                             periph,
3162                                                             sizeleft);
3163                 }
3164             }
3165             else
3166             {
3167                 // Do the burst transfers
3168                 if (status == ALT_E_SUCCESS)
3169                 {
3170                     status = alt_dma_memory_to_16550_burst(program,
3171                                                            periph,
3172                                                            burst_size,
3173                                                            burst_count);
3174                 }
3175 
3176                 // Program the DMA engine to transfer the non-burstable items in single tranfers
3177                 if (status == ALT_E_SUCCESS)
3178                 {
3179                     status = alt_dma_memory_to_16550_single(program,
3180                                                             periph,
3181                                                             sizeleft);
3182                 }
3183 
3184             } // else if (burst_count == 0)
3185         }
3186     }
3187     else
3188     {
3189         dprintf("DMA[M->P][16550]: FIFOs disabled.\n");
3190 
3191         //
3192         // FIFOs are disabled.
3193         //
3194 
3195         status = alt_dma_memory_to_16550_single(program,
3196                                                 periph,
3197                                                 size);
3198     }
3199 
3200     return status;
3201 }
3202 
3203 static ALT_STATUS_CODE alt_dma_16550_to_memory_single(ALT_DMA_PROGRAM_t * program,
3204                                                       ALT_DMA_PERIPH_t periph,
3205                                                       size_t size)
3206 {
3207     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3208 
3209     // Program in the following parameters:
3210     //  - SS8 (Source      burst size of 1-byte)
3211     //  - DS8 (Destination burst size of 1-byte)
3212     //  - SB1 (Source      burst length of 1 transfer)
3213     //  - DB1 (Destination burst length of 1 transfer)
3214     //  - SAF (Source      address fixed)
3215     //  - All other options default.
3216 
3217     if (status == ALT_E_SUCCESS)
3218     {
3219         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
3220                                         (   ALT_DMA_CCR_OPT_SB1
3221                                           | ALT_DMA_CCR_OPT_SS8
3222                                           | ALT_DMA_CCR_OPT_SAF
3223                                           | ALT_DMA_CCR_OPT_SP_DEFAULT
3224                                           | ALT_DMA_CCR_OPT_SC_DEFAULT
3225                                           | ALT_DMA_CCR_OPT_DB1
3226                                           | ALT_DMA_CCR_OPT_DS8
3227                                           | ALT_DMA_CCR_OPT_DA_DEFAULT
3228                                           | ALT_DMA_CCR_OPT_DP_DEFAULT
3229                                           | ALT_DMA_CCR_OPT_DC_DEFAULT
3230                                           | ALT_DMA_CCR_OPT_ES_DEFAULT
3231                                         )
3232             );
3233     }
3234 
3235     uint32_t sizeleft = size;
3236 
3237     while (sizeleft > 0)
3238     {
3239         if (status != ALT_E_SUCCESS)
3240         {
3241             break;
3242         }
3243 
3244         uint32_t loopcount = MIN(sizeleft, 256);
3245         sizeleft -= loopcount;
3246 
3247         dprintf("DMA[P->M][16550][S]: Creating %lu transfer(s).\n", loopcount);
3248 
3249         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3250         {
3251             status = alt_dma_program_DMALP(program, loopcount);
3252         }
3253         if (status == ALT_E_SUCCESS)
3254         {
3255             status = alt_dma_program_DMAFLUSHP(program, periph);
3256         }
3257         if (status == ALT_E_SUCCESS)
3258         {
3259             status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3260         }
3261         if (status == ALT_E_SUCCESS)
3262         {
3263             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3264         }
3265         if (status == ALT_E_SUCCESS)
3266         {
3267             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3268         }
3269         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3270         {
3271             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE);
3272         }
3273     }
3274 
3275     return status;
3276 }                                              
3277 
3278 static ALT_STATUS_CODE alt_dma_16550_to_memory_burst(ALT_DMA_PROGRAM_t * program,
3279                                                      ALT_DMA_PERIPH_t periph,
3280                                                      size_t burst_size,
3281                                                      size_t burst_count)
3282 {
3283     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3284 
3285     // Program in the following parameters:
3286     //  - SS8  (Source      burst size of 1-byte)
3287     //  - DS8  (Destination burst size of 1-byte)
3288     //  - SB16 (Source      burst length of 16 transfers)
3289     //  - DB16 (Destination burst length of 16 transfers)
3290     //  - SAF  (Source      address fixed)
3291     //  - All other options default.
3292 
3293     if (status == ALT_E_SUCCESS)
3294     {
3295         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR,
3296                                         (   ALT_DMA_CCR_OPT_SB16
3297                                           | ALT_DMA_CCR_OPT_SS8
3298                                           | ALT_DMA_CCR_OPT_SAF
3299                                           | ALT_DMA_CCR_OPT_SP_DEFAULT
3300                                           | ALT_DMA_CCR_OPT_SC_DEFAULT
3301                                           | ALT_DMA_CCR_OPT_DB16
3302                                           | ALT_DMA_CCR_OPT_DS8
3303                                           | ALT_DMA_CCR_OPT_DA_DEFAULT
3304                                           | ALT_DMA_CCR_OPT_DP_DEFAULT
3305                                           | ALT_DMA_CCR_OPT_DC_DEFAULT
3306                                           | ALT_DMA_CCR_OPT_ES_DEFAULT
3307                                         )
3308             );
3309     }
3310 
3311     while (burst_count > 0)
3312     {
3313         if (status != ALT_E_SUCCESS)
3314         {
3315             break;
3316         }
3317 
3318         uint32_t loopcount = MIN(burst_count, 256);
3319         burst_count -= loopcount;
3320 
3321         dprintf("DMA[P->M][16550][B]: Creating outer %lu inner loop(s).\n", loopcount);
3322 
3323         // Outer loop {
3324 
3325         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3326         {
3327             status = alt_dma_program_DMALP(program, loopcount);
3328         }
3329         if (status == ALT_E_SUCCESS)
3330         {
3331             status = alt_dma_program_DMAFLUSHP(program, periph);
3332         }
3333         if (status == ALT_E_SUCCESS)
3334         {
3335             status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST);
3336         }
3337 
3338         // Inner loop {
3339 
3340         // Loop [burst_size / 16] times. The burst_size was trimmed to the
3341         // nearest multiple of 16 by the caller. Each burst does 16 transfers
3342         // hence the need for the divide.
3343 
3344         dprintf("DMA[P->M][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4);
3345 
3346         if (status == ALT_E_SUCCESS)
3347         {
3348             status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16.
3349         }
3350         if (status == ALT_E_SUCCESS)
3351         {
3352             status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3353         }
3354         if (status == ALT_E_SUCCESS)
3355         {
3356             status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3357         }
3358         if (status == ALT_E_SUCCESS)
3359         {
3360             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3361         }
3362 
3363         // } Inner loop
3364 
3365         if ((status == ALT_E_SUCCESS) && (loopcount > 1))
3366         {
3367             status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST);
3368         }
3369 
3370         // } Outer loop
3371     }
3372 
3373     return status;
3374 }
3375 
3376 static ALT_STATUS_CODE alt_dma_16550_to_memory(ALT_DMA_PROGRAM_t * program,
3377                                                ALT_DMA_PERIPH_t periph,
3378                                                ALT_16550_HANDLE_t * handle,
3379                                                void * dst,
3380                                                size_t size)
3381 {
3382     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3383 
3384     if (status == ALT_E_SUCCESS)
3385     {
3386         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst);
3387     }
3388     if (status == ALT_E_SUCCESS)
3389     {
3390         status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location));
3391     }
3392 
3393     // Determine if FIFOs are enabled from the FCR cache
3394 
3395     if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0)
3396     {
3397         dprintf("DMA[P->M][16550]: FIFOs enabled.\n");
3398 
3399         //
3400         // FIFOs are enabled.
3401         //
3402 
3403         uint32_t rx_size;
3404         uint32_t burst_size;
3405         ALT_16550_FIFO_TRIGGER_RX_t trig_rx;
3406 
3407         // Get the RX FIFO Size
3408         // Use the register interface to avoid coupling the 16550 and DMA.
3409         rx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
3410 
3411         // Get the RX FIFO Trigger Level from the FCR cache
3412         trig_rx = (ALT_16550_FIFO_TRIGGER_RX_t)ALT_UART_FCR_RT_GET(handle->fcr);
3413 
3414         switch (trig_rx)
3415         {
3416         case ALT_16550_FIFO_TRIGGER_RX_ANY:
3417             burst_size = 1;
3418             break;
3419         case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL:
3420             burst_size = rx_size >> 2; // divide by 4
3421             break;
3422         case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL:
3423             burst_size = rx_size >> 1; // divide by 2
3424             break;
3425         case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL:
3426             burst_size = rx_size - 2;
3427             break;
3428         default:
3429             // This case should never happen.
3430             return ALT_E_ERROR;
3431         }
3432 
3433         if (burst_size < 16)
3434         {
3435             // There's no point bursting 1 byte at a time per notify, so just do single transfers.
3436             if (status == ALT_E_SUCCESS)
3437             {
3438                 status = alt_dma_16550_to_memory_single(program,
3439                                                         periph,
3440                                                         size);
3441             }
3442         }
3443         else
3444         {
3445             uint32_t sizeleft = size;
3446 
3447             // Now trim the burst size to a multiple of 16.
3448             // This will optimize the bursting in the fewest possible commands.
3449             dprintf("DMA[P->M][16550]: Untrimmed burst size = %lu.\n", burst_size);
3450             burst_size &= ~0xf;
3451             dprintf("DMA[P->M][16550]: Trimmed burst size   = %lu.\n", burst_size);
3452 
3453             // Determine how many burst transfers can be done
3454             uint32_t burst_count = 0;
3455 
3456             burst_count = sizeleft / burst_size;
3457             sizeleft -= burst_count * burst_size;
3458 
3459             if (burst_count == 0)
3460             {
3461                 // Do the transfer.
3462                 if (status == ALT_E_SUCCESS)
3463                 {
3464                     status = alt_dma_16550_to_memory_single(program,
3465                                                             periph,
3466                                                             sizeleft);
3467                 }
3468             }
3469             else
3470             {
3471                 // Do the burst transfers
3472                 if (status == ALT_E_SUCCESS)
3473                 {
3474                     status = alt_dma_16550_to_memory_burst(program,
3475                                                            periph,
3476                                                            burst_size,
3477                                                            burst_count);
3478                 }
3479 
3480                 // Program the DMA engine to transfer the non-burstable items in single transfers.
3481                 if (status == ALT_E_SUCCESS)
3482                 {
3483                     status = alt_dma_16550_to_memory_single(program,
3484                                                             periph,
3485                                                             sizeleft);
3486                 }
3487 
3488             } // if (burst_count == 0)
3489         }
3490     }
3491     else
3492     {
3493         dprintf("DMA[P->M][16550]: FIFOs disabled.\n");
3494 
3495         //
3496         // FIFOs are disabled.
3497         //
3498 
3499         status = alt_dma_16550_to_memory_single(program,
3500                                                 periph,
3501                                                 size);
3502     }
3503 
3504     return status;
3505 }
3506 #endif // ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3507 
3508 ALT_STATUS_CODE alt_dma_memory_to_periph(ALT_DMA_CHANNEL_t channel,
3509                                          ALT_DMA_PROGRAM_t * program,
3510                                          ALT_DMA_PERIPH_t dstp,
3511                                          const void * src,
3512                                          size_t size,
3513                                          void * periph_info,
3514                                          bool send_evt,
3515                                          ALT_DMA_EVENT_t evt)
3516 {
3517     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3518 
3519     if ((size == 0) && (send_evt == false))
3520     {
3521         return status;
3522     }
3523 
3524     if (status == ALT_E_SUCCESS)
3525     {
3526         dprintf("DMA[M->P]: Init Program.\n");
3527         status = alt_dma_program_init(program);
3528     }
3529 
3530     if ((status == ALT_E_SUCCESS) && (size != 0))
3531     {
3532         switch (dstp)
3533         {
3534 #if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
3535         case ALT_DMA_PERIPH_QSPI_FLASH_TX:
3536             status = alt_dma_memory_to_qspi(program, src, size);
3537             break;
3538 #endif
3539 
3540 #if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3541         case ALT_DMA_PERIPH_UART0_TX:
3542         case ALT_DMA_PERIPH_UART1_TX:
3543             status = alt_dma_memory_to_16550(program, dstp,
3544                                              (ALT_16550_HANDLE_t *)periph_info, src, size);
3545             break;
3546 #endif
3547 
3548         case ALT_DMA_PERIPH_FPGA_0:
3549         case ALT_DMA_PERIPH_FPGA_1:
3550         case ALT_DMA_PERIPH_FPGA_2:
3551         case ALT_DMA_PERIPH_FPGA_3:
3552         case ALT_DMA_PERIPH_FPGA_4:
3553         case ALT_DMA_PERIPH_FPGA_5:
3554         case ALT_DMA_PERIPH_FPGA_6:
3555         case ALT_DMA_PERIPH_FPGA_7:
3556         case ALT_DMA_PERIPH_I2C0_TX:
3557         case ALT_DMA_PERIPH_I2C1_TX:
3558         case ALT_DMA_PERIPH_I2C2_TX:
3559         case ALT_DMA_PERIPH_I2C3_TX:
3560         case ALT_DMA_PERIPH_SPI0_MASTER_TX:
3561         case ALT_DMA_PERIPH_SPI0_SLAVE_TX:
3562         case ALT_DMA_PERIPH_SPI1_MASTER_TX:
3563         case ALT_DMA_PERIPH_SPI1_SLAVE_TX:
3564 
3565         default:
3566             status = ALT_E_BAD_ARG;
3567             break;
3568         }
3569     }
3570 
3571     // Send event if requested.
3572     if (send_evt)
3573     {
3574         if (status == ALT_E_SUCCESS)
3575         {
3576             dprintf("DMA[M->P]: Adding event.\n");
3577             status = alt_dma_program_DMASEV(program, evt);
3578         }
3579     }
3580 
3581     // Now that everything is done, end the program.
3582     if (status == ALT_E_SUCCESS)
3583     {
3584         status = alt_dma_program_DMAEND(program);
3585     }
3586 
3587     // If there was a problem assembling the program, clean up the buffer and exit.
3588     if (status != ALT_E_SUCCESS)
3589     {
3590         // Do not report the status for the clear operation. A failure should be
3591         // reported regardless of if the clear is successful.
3592         alt_dma_program_clear(program);
3593         return status;
3594     }
3595 
3596     // Execute the program on the given channel.
3597 
3598     return alt_dma_channel_exec(channel, program);
3599 }
3600 
3601 ALT_STATUS_CODE alt_dma_periph_to_memory(ALT_DMA_CHANNEL_t channel,
3602                                          ALT_DMA_PROGRAM_t * program,
3603                                          void * dst,
3604                                          ALT_DMA_PERIPH_t srcp,
3605                                          size_t size,
3606                                          void * periph_info,
3607                                          bool send_evt,
3608                                          ALT_DMA_EVENT_t evt)
3609 {
3610     ALT_STATUS_CODE status = ALT_E_SUCCESS;
3611 
3612     if ((size == 0) && (send_evt == false))
3613     {
3614         return ALT_E_SUCCESS;
3615     }
3616 
3617     if (status == ALT_E_SUCCESS)
3618     {
3619         dprintf("DMA[P->M]: Init Program.\n");
3620         status = alt_dma_program_init(program);
3621     }
3622 
3623     if ((status == ALT_E_SUCCESS) && (size != 0))
3624     {
3625         switch (srcp)
3626         {
3627 #if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT
3628         case ALT_DMA_PERIPH_QSPI_FLASH_RX:
3629             status = alt_dma_qspi_to_memory(program, dst, size);
3630             break;
3631 #endif
3632 
3633 #if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT
3634         case ALT_DMA_PERIPH_UART0_RX:
3635         case ALT_DMA_PERIPH_UART1_RX:
3636             status = alt_dma_16550_to_memory(program, srcp,
3637                                              (ALT_16550_HANDLE_t *)periph_info, dst, size);
3638             break;
3639 #endif
3640 
3641         case ALT_DMA_PERIPH_FPGA_0:
3642         case ALT_DMA_PERIPH_FPGA_1:
3643         case ALT_DMA_PERIPH_FPGA_2:
3644         case ALT_DMA_PERIPH_FPGA_3:
3645         case ALT_DMA_PERIPH_FPGA_4:
3646         case ALT_DMA_PERIPH_FPGA_5:
3647         case ALT_DMA_PERIPH_FPGA_6:
3648         case ALT_DMA_PERIPH_FPGA_7:
3649         case ALT_DMA_PERIPH_I2C0_RX:
3650         case ALT_DMA_PERIPH_I2C1_RX:
3651         case ALT_DMA_PERIPH_I2C2_RX:
3652         case ALT_DMA_PERIPH_I2C3_RX:
3653         case ALT_DMA_PERIPH_SPI0_MASTER_RX:
3654         case ALT_DMA_PERIPH_SPI0_SLAVE_RX:
3655         case ALT_DMA_PERIPH_SPI1_MASTER_RX:
3656         case ALT_DMA_PERIPH_SPI1_SLAVE_RX:
3657 
3658         default:
3659             status = ALT_E_BAD_ARG;
3660             break;
3661         }
3662     }
3663 
3664     // Send event if requested.
3665     if (send_evt)
3666     {
3667         if (status == ALT_E_SUCCESS)
3668         {
3669             dprintf("DMA[P->M]: Adding event.\n");
3670             status = alt_dma_program_DMASEV(program, evt);
3671         }
3672     }
3673 
3674     // Now that everything is done, end the program.
3675     if (status == ALT_E_SUCCESS)
3676     {
3677         status = alt_dma_program_DMAEND(program);
3678     }
3679 
3680     // If there was a problem assembling the program, clean up the buffer and exit.
3681     if (status != ALT_E_SUCCESS)
3682     {
3683         // Do not report the status for the clear operation. A failure should be
3684         // reported regardless of if the clear is successful.
3685         alt_dma_program_clear(program);
3686         return status;
3687     }
3688 
3689     // Execute the program on the given channel.
3690 
3691     return alt_dma_channel_exec(channel, program);
3692 }
3693 
3694 /////
3695 
3696 static bool alt_dma_is_init(void)
3697 {
3698     uint32_t permodrst = alt_read_word(ALT_RSTMGR_PERMODRST_ADDR);
3699 
3700     if (permodrst & ALT_RSTMGR_PERMODRST_DMA_SET_MSK)
3701     {
3702         return false;
3703     }
3704     else
3705     {
3706         return true;
3707     }
3708 }
3709 
3710 ALT_STATUS_CODE alt_dma_ecc_start(void * block, size_t size)
3711 {
3712     if (alt_dma_is_init() == false)
3713     {
3714         return ALT_E_ERROR;
3715     }
3716 
3717     if ((uintptr_t)block & (sizeof(uint64_t) - 1))
3718     {
3719         return ALT_E_ERROR;
3720     }
3721 
3722     // Verify that all channels are either unallocated or allocated and idle.
3723 
3724     for (int i = 0; i < ARRAY_COUNT(channel_info_array); ++i)
3725     {
3726         if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)
3727         {
3728             ALT_DMA_CHANNEL_STATE_t state;
3729             alt_dma_channel_state_get((ALT_DMA_CHANNEL_t)i, &state);
3730 
3731             if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
3732             {
3733                 dprintf("DMA[ECC]: Error: Channel %d state is non-stopped (%d).\n", i, (int)state);
3734                 return ALT_E_ERROR;
3735             }
3736         }
3737     }
3738 
3739     /////
3740 
3741     // Enable ECC for DMA RAM
3742 
3743     dprintf("DEBUG[DMA][ECC]: Enable ECC in SysMgr.\n");
3744     alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR, ALT_SYSMGR_ECC_DMA_EN_SET_MSK);
3745 
3746     // Clear any pending spurious DMA ECC interrupts.
3747 
3748     dprintf("DEBUG[DMA][ECC]: Clear any pending spurious ECC status in SysMgr.\n");
3749     alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR,
3750                      ALT_SYSMGR_ECC_DMA_EN_SET_MSK
3751                    | ALT_SYSMGR_ECC_DMA_SERR_SET_MSK
3752                    | ALT_SYSMGR_ECC_DMA_DERR_SET_MSK);
3753 
3754     return ALT_E_SUCCESS;
3755 }