Skip to content

Commit

Permalink
arm/raspberrypi: DMA API: ensure that channel is enabled when it is c…
Browse files Browse the repository at this point in the history
…onfigured.

I am not sure if channel has to be (power) enabled to access registers.
Consider that even for plain access enable is required to be on safe side.
  • Loading branch information
ppisa committed Aug 25, 2016
1 parent eb0e972 commit ec34b48
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions c/src/lib/libbsp/arm/raspberrypi/misc/dma.c
Expand Up @@ -61,6 +61,7 @@

#define BCM_PAGE_SIZE 4096
#define BCM_PAGE_MASK ( BCM_PAGE_SIZE - 1 )

/**
* @brief Table that indicates if a channel is currently occupied.
*/
Expand All @@ -70,6 +71,8 @@ static void rpi_dma_intr( void *arg );

rtems_status_code rpi_dma_reset( int ch );

RTEMS_INTERRUPT_LOCK_DEFINE( static, bcm_dma_lock, "bcm_dma_lock" );

int bus_dmamap_load_buffer(
bus_dma_segment_t segs[],
void *buf,
Expand Down Expand Up @@ -361,7 +364,9 @@ rtems_status_code rpi_dma_start(
int len
)
{
rtems_interrupt_lock_context lock_context;
struct bcm_dma_cb *cb;
uint32_t ch_mask = 1 << ch;

/* Check the channel number provided */
if ( ch < 0 || ch >= BCM_DMA_CH_MAX )
Expand Down Expand Up @@ -407,6 +412,12 @@ rtems_status_code rpi_dma_start(
/* Change the state of the channel */
BCM2835_REG( BCM_DMA_CS( ch ) ) = CS_ACTIVE;

if ( ! ( BCM2835_REG( BCM_DMA_ENABLE ) & ch_mask) ) {
rtems_interrupt_lock_acquire(&bcm_dma_lock, &lock_context);
BCM2835_REG( BCM_DMA_ENABLE ) |= ch_mask;
rtems_interrupt_lock_release(&bcm_dma_lock, &lock_context);
}

return RTEMS_SUCCESSFUL;
}

Expand Down Expand Up @@ -504,6 +515,7 @@ int bus_dmamap_load_buffer(

int rpi_dma_init( int channel )
{
rtems_interrupt_lock_context lock_context;
struct bcm_dma_ch *ch;
void *cb_virt;
vm_paddr_t cb_phys = 0;
Expand Down Expand Up @@ -581,6 +593,13 @@ int rpi_dma_init( int channel )
/* reset DMA */
BCM2835_REG( BCM_DMA_CS( channel ) ) = CS_RESET;

rtems_interrupt_lock_acquire(&bcm_dma_lock, &lock_context);
BCM2835_REG( BCM_DMA_ENABLE ) |= 1 << channel;
rtems_interrupt_lock_release(&bcm_dma_lock, &lock_context);

/* reset DMA */
BCM2835_REG( BCM_DMA_CS( channel ) ) = CS_RESET;

return 0;
}

Expand Down

0 comments on commit ec34b48

Please sign in to comment.