blob: f142b5379ff8cd231a79fa9d46c84a8ad7cc68fc [file] [log] [blame]
Austin Schuh208337d2022-01-01 14:29:11 -08001/*
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)
12check_hw_size(dma_channel_hw_t, DMA_CHAN_STRIDE);
13check_hw_layout(dma_hw_t, abort, DMA_CHAN_ABORT_OFFSET);
14
15// sanity check
16static_assert(__builtin_offsetof(dma_hw_t, ch[0].ctrl_trig) == DMA_CH0_CTRL_TRIG_OFFSET, "hw mismatch");
17static_assert(__builtin_offsetof(dma_hw_t, ch[1].ctrl_trig) == DMA_CH1_CTRL_TRIG_OFFSET, "hw mismatch");
18
19static_assert(NUM_DMA_CHANNELS <= 16, "");
20static uint16_t _claimed;
21static uint8_t _timer_claimed;
22
23void dma_channel_claim(uint channel) {
24 check_dma_channel_param(channel);
25 hw_claim_or_assert((uint8_t *) &_claimed, channel, "DMA channel %d is already claimed");
26}
27
28void dma_claim_mask(uint32_t mask) {
29 for(uint i = 0; mask; i++, mask >>= 1u) {
30 if (mask & 1u) dma_channel_claim(i);
31 }
32}
33
34void dma_channel_unclaim(uint channel) {
35 check_dma_channel_param(channel);
36 hw_claim_clear((uint8_t *) &_claimed, channel);
37}
38
Ravago Jonesd208ae72023-02-13 02:24:07 -080039void dma_unclaim_mask(uint32_t mask) {
40 for(uint i = 0; mask; i++, mask >>= 1u) {
41 if (mask & 1u) dma_channel_unclaim(i);
42 }
43}
44
Austin Schuh208337d2022-01-01 14:29:11 -080045int dma_claim_unused_channel(bool required) {
46 return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
47}
48
49bool dma_channel_is_claimed(uint channel) {
50 check_dma_channel_param(channel);
51 return hw_is_claimed((uint8_t *) &_claimed, channel);
52}
53
54void dma_timer_claim(uint timer) {
55 check_dma_timer_param(timer);
56 hw_claim_or_assert(&_timer_claimed, timer, "DMA timer %d is already claimed");
57}
58
59void dma_timer_unclaim(uint timer) {
60 check_dma_timer_param(timer);
61 hw_claim_clear(&_timer_claimed, timer);
62}
63
64int dma_claim_unused_timer(bool required) {
65 return hw_claim_unused_from_range(&_timer_claimed, required, 0, NUM_DMA_TIMERS-1, "No DMA timers are available");
66}
67
68bool dma_timer_is_claimed(uint timer) {
69 check_dma_timer_param(timer);
70 return hw_is_claimed(&_timer_claimed, timer);
71}
72
73#ifndef NDEBUG
74
75void print_dma_ctrl(dma_channel_hw_t *channel) {
76 uint32_t ctrl = channel->ctrl_trig;
77 int rgsz = (ctrl & DMA_CH0_CTRL_TRIG_RING_SIZE_BITS) >> DMA_CH0_CTRL_TRIG_RING_SIZE_LSB;
78 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",
79 (uint) ctrl,
80 ctrl & DMA_CH0_CTRL_TRIG_AHB_ERROR_BITS ? 1 : 0,
81 ctrl & DMA_CH0_CTRL_TRIG_READ_ERROR_BITS ? 1 : 0,
82 ctrl & DMA_CH0_CTRL_TRIG_WRITE_ERROR_BITS ? 1 : 0,
83 ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS ? 1 : 0,
84 (int) ((ctrl & DMA_CH0_CTRL_TRIG_TREQ_SEL_BITS) >> DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB),
85 (int) ((ctrl & DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) >> DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB),
86 ctrl & DMA_CH0_CTRL_TRIG_RING_SEL_BITS ? 1 : 0,
87 rgsz ? (1 << rgsz) : 0,
88 ctrl & DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS ? 1 : 0,
89 ctrl & DMA_CH0_CTRL_TRIG_INCR_READ_BITS ? 1 : 0,
90 1 << ((ctrl & DMA_CH0_CTRL_TRIG_DATA_SIZE_BITS) >> DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB),
91 ctrl & DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS ? 1 : 0,
92 ctrl & DMA_CH0_CTRL_TRIG_EN_BITS ? 1 : 0);
93}
94#endif
95
96#if PARAM_ASSERTIONS_ENABLED(DMA)
97void check_dma_channel_param_impl(uint __unused channel) {
98 valid_params_if(DMA, channel < NUM_DMA_CHANNELS);
99}
100#endif