1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdio.h>
8 #include "hardware/dma.h"
9 #include "hardware/claim.h"
10 
11 #define DMA_CHAN_STRIDE (DMA_CH1_CTRL_TRIG_OFFSET - DMA_CH0_CTRL_TRIG_OFFSET)
12 check_hw_size(dma_channel_hw_t, DMA_CHAN_STRIDE);
13 check_hw_layout(dma_hw_t, abort, DMA_CHAN_ABORT_OFFSET);
14 
15 // sanity check
16 static_assert(__builtin_offsetof(dma_hw_t, ch[0].ctrl_trig) == DMA_CH0_CTRL_TRIG_OFFSET, "hw mismatch");
17 static_assert(__builtin_offsetof(dma_hw_t, ch[1].ctrl_trig) == DMA_CH1_CTRL_TRIG_OFFSET, "hw mismatch");
18 
19 static_assert(NUM_DMA_CHANNELS <= 16, "");
20 static uint16_t _claimed;
21 
dma_channel_claim(uint channel)22 void dma_channel_claim(uint channel) {
23     check_dma_channel_param(channel);
24     hw_claim_or_assert((uint8_t *) &_claimed, channel, "DMA channel %d is already claimed");
25 }
26 
dma_claim_mask(uint32_t mask)27 void dma_claim_mask(uint32_t mask) {
28     for(uint i = 0; mask; i++, mask >>= 1u) {
29         if (mask & 1u) dma_channel_claim(i);
30     }
31 }
32 
dma_channel_unclaim(uint channel)33 void dma_channel_unclaim(uint channel) {
34     check_dma_channel_param(channel);
35     hw_claim_clear((uint8_t *) &_claimed, channel);
36 }
37 
dma_claim_unused_channel(bool required)38 int dma_claim_unused_channel(bool required) {
39     return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
40 }
41 
42 #ifndef NDEBUG
43 
print_dma_ctrl(dma_channel_hw_t * channel)44 void print_dma_ctrl(dma_channel_hw_t *channel) {
45     uint32_t ctrl = channel->ctrl_trig;
46     int rgsz = (ctrl & DMA_CH0_CTRL_TRIG_RING_SIZE_BITS) >> DMA_CH0_CTRL_TRIG_RING_SIZE_LSB;
47     printf("(%08x) ber %d rer %d wer %d busy %d trq %d cto %d rgsl %d rgsz %d inw %d inr %d sz %d hip %d en %d",
48            (uint) ctrl,
49            ctrl & DMA_CH0_CTRL_TRIG_AHB_ERROR_BITS ? 1 : 0,
50            ctrl & DMA_CH0_CTRL_TRIG_READ_ERROR_BITS ? 1 : 0,
51            ctrl & DMA_CH0_CTRL_TRIG_WRITE_ERROR_BITS ? 1 : 0,
52            ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS ? 1 : 0,
53            (int) ((ctrl & DMA_CH0_CTRL_TRIG_TREQ_SEL_BITS) >> DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB),
54            (int) ((ctrl & DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) >> DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB),
55            ctrl & DMA_CH0_CTRL_TRIG_RING_SEL_BITS ? 1 : 0,
56            rgsz ? (1 << rgsz) : 0,
57            ctrl & DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS ? 1 : 0,
58            ctrl & DMA_CH0_CTRL_TRIG_INCR_READ_BITS ? 1 : 0,
59            1 << ((ctrl & DMA_CH0_CTRL_TRIG_DATA_SIZE_BITS) >> DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB),
60            ctrl & DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS ? 1 : 0,
61            ctrl & DMA_CH0_CTRL_TRIG_EN_BITS ? 1 : 0);
62 }
63 
check_dma_channel_param_impl(uint channel)64 void check_dma_channel_param_impl(uint channel) {
65     valid_params_if(DMA, channel < NUM_DMA_CHANNELS);
66 }
67 
68 #endif
69