Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:03

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsARMLPC176X_dma
0007  *
0008  * @brief Direct memory access (DMA) support.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2008, 2009 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * 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)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <bsp/lpc176x.h>
0037 #include <bsp/dma.h>
0038 #include <bsp/irq.h>
0039 
0040 static rtems_id lpc176x_dma_sema_table[ GPDMA_CH_NUMBER ];
0041 static bool     lpc176x_dma_status_table[ GPDMA_CH_NUMBER ];
0042 
0043 static void lpc176x_dma_copy_handler( void *arg )
0044 {
0045   /* Get interrupt status */
0046   uint32_t tc = GPDMA_INT_TCSTAT;
0047   uint32_t err = GPDMA_INT_ERR_STAT;
0048 
0049   /* Clear interrupt status */
0050   GPDMA_INT_TCCLR = tc;
0051   GPDMA_INT_ERR_CLR = err;
0052 
0053   if ( ( tc & GPDMA_STATUS_CH_0 ) != 0 ) {
0054     rtems_semaphore_release( lpc176x_dma_sema_table[ 0 ] );
0055   }
0056 
0057   /* else implies that the channel is not the 0. Also,
0058      there is nothing to do. */
0059 
0060   lpc176x_dma_status_table[ 0 ] = ( err & GPDMA_STATUS_CH_0 ) == 0;
0061 
0062   if ( ( tc & GPDMA_STATUS_CH_1 ) != 0 ) {
0063     rtems_semaphore_release( lpc176x_dma_sema_table[ 1 ] );
0064   }
0065 
0066   /* else implies that the channel is not the 1. Also,
0067      there is nothing to do. */
0068 
0069   lpc176x_dma_status_table[ 1 ] = ( err & GPDMA_STATUS_CH_1 ) == 0;
0070 }
0071 
0072 rtems_status_code lpc176x_dma_copy_initialize( void )
0073 {
0074   rtems_status_code status_code = RTEMS_SUCCESSFUL;
0075   rtems_id          id0 = RTEMS_ID_NONE;
0076   rtems_id          id1 = RTEMS_ID_NONE;
0077 
0078   /* Create semaphore for channel 0 */
0079   status_code = rtems_semaphore_create( rtems_build_name( 'D', 'M', 'A', '0' ),
0080     0,
0081     RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0082     0,
0083     &id0 );
0084 
0085   if ( status_code != RTEMS_SUCCESSFUL ) {
0086     return status_code;
0087   }
0088 
0089   /* else implies that the semaphore to the channel 0 was created succefully.
0090      Also, there is nothing to do. */
0091 
0092   /* Create semaphore for channel 1 */
0093   status_code = rtems_semaphore_create( rtems_build_name( 'D', 'M', 'A', '1' ),
0094     0,
0095     RTEMS_LOCAL | RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0096     0,
0097     &id1 );
0098 
0099   if ( status_code != RTEMS_SUCCESSFUL ) {
0100     rtems_semaphore_delete( id0 );
0101 
0102     return status_code;
0103   }
0104 
0105   /* else implies that the semaphore to the channel 1 was created succefully.
0106      Also, there is nothing to do. */
0107 
0108   /* Install DMA interrupt handler */
0109   status_code = rtems_interrupt_handler_install( LPC176X_IRQ_DMA,
0110     "DMA copy",
0111     RTEMS_INTERRUPT_UNIQUE,
0112     lpc176x_dma_copy_handler,
0113     NULL );
0114 
0115   if ( status_code != RTEMS_SUCCESSFUL ) {
0116     rtems_semaphore_delete( id0 );
0117     rtems_semaphore_delete( id1 );
0118 
0119     return status_code;
0120   }
0121 
0122   /* else implies that the interrupt handler was installed succefully. Also,
0123      there is nothing to do. */
0124 
0125   /* Initialize global data */
0126   lpc176x_dma_sema_table[ 0 ] = id0;
0127   lpc176x_dma_sema_table[ 1 ] = id1;
0128 
0129   return RTEMS_SUCCESSFUL;
0130 }
0131 
0132 rtems_status_code lpc176x_dma_copy_release( void )
0133 {
0134   rtems_status_code status_code = RTEMS_SUCCESSFUL;
0135   rtems_status_code status_code_aux = RTEMS_SUCCESSFUL;
0136 
0137   status_code = rtems_interrupt_handler_remove( LPC176X_IRQ_DMA,
0138     lpc176x_dma_copy_handler,
0139     NULL );
0140 
0141   if ( status_code != RTEMS_SUCCESSFUL ) {
0142     status_code_aux = status_code;
0143   }
0144 
0145   /* else implies that the interrupt handler was removed succefully. Also,
0146      there is nothing to do. */
0147 
0148   status_code = rtems_semaphore_delete( lpc176x_dma_sema_table[ 0 ] );
0149 
0150   if ( status_code != RTEMS_SUCCESSFUL ) {
0151     status_code_aux = status_code;
0152   }
0153 
0154   /* else implies that the semaphore to the channel 0 was deleted succefully.
0155      Also, there is nothing to do. */
0156 
0157   status_code = rtems_semaphore_delete( lpc176x_dma_sema_table[ 1 ] );
0158 
0159   if ( status_code != RTEMS_SUCCESSFUL ) {
0160     status_code_aux = status_code;
0161   }
0162 
0163   /* else implies that the semaphore to the channel 1 was deleted succefully.
0164      Also, there is nothing to do. */
0165 
0166   return status_code_aux;
0167 }
0168 
0169 rtems_status_code lpc176x_dma_copy(
0170   unsigned          channel,
0171   const void *const dest,
0172   const void *const src,
0173   size_t            n,
0174   const size_t      width
0175 )
0176 {
0177   rtems_status_code             status_code = RTEMS_SUCCESSFUL;
0178   volatile lpc176x_dma_channel *e = GPDMA_CH_BASE_ADDR( channel );
0179   uint32_t                      w = GPDMA_CH_CTRL_W_8;
0180 
0181   switch ( width ) {
0182     case 4:
0183       w = GPDMA_CH_CTRL_W_32;
0184       break;
0185     case 2:
0186       w = GPDMA_CH_CTRL_W_16;
0187       break;
0188   }
0189 
0190   n = n >> w;
0191 
0192   if ( n > 0 && n < 4096 ) {
0193     e->desc.src = (uint32_t) src;
0194     e->desc.dest = (uint32_t) dest;
0195     e->desc.lli = 0;
0196     e->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ( 0, n ) |
0197                    SET_GPDMA_CH_CTRL_SBSZ( 0, GPDMA_CH_CTRL_BSZ_1 ) |
0198                    SET_GPDMA_CH_CTRL_DBSZ( 0, GPDMA_CH_CTRL_BSZ_1 ) |
0199                    SET_GPDMA_CH_CTRL_SW( 0, w ) |
0200                    SET_GPDMA_CH_CTRL_DW( 0, w ) |
0201                    GPDMA_CH_CTRL_ITC |
0202                    GPDMA_CH_CTRL_SI |
0203                    GPDMA_CH_CTRL_DI;
0204     e->cfg = SET_GPDMA_CH_CFG_FLOW( 0, GPDMA_CH_CFG_FLOW_MEM_TO_MEM_DMA ) |
0205              GPDMA_CH_CFG_IE |
0206              GPDMA_CH_CFG_ITC |
0207              GPDMA_CH_CFG_EN;
0208   } else {
0209     status_code = RTEMS_INVALID_SIZE;
0210   }
0211 
0212   return status_code;
0213 }
0214 
0215 rtems_status_code lpc176x_dma_copy_wait( const unsigned channel )
0216 {
0217   rtems_status_code status_code = RTEMS_SUCCESSFUL;
0218 
0219   status_code = rtems_semaphore_obtain( lpc176x_dma_sema_table[ channel ],
0220     RTEMS_WAIT,
0221     RTEMS_NO_TIMEOUT );
0222 
0223   if ( status_code != RTEMS_SUCCESSFUL ) {
0224     return status_code;
0225   }
0226 
0227   /* else implies that the semaphore was obtained succefully. Also,
0228      there is nothing to do. */
0229 
0230   status_code = lpc176x_dma_status_table[ channel ]
0231                 ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
0232 
0233   return status_code;
0234 }