/* libhw_cr/rp2040_dma.c - Utilities for sharing the DMA IRQs * * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include /* for irq_set_exclusive_handler() */ #include "rp2040_dma.h" /* Borrowed from *********************************************/ dma_channel_hw_t *dma_channel_hw_addr(uint channel) { assert(channel < NUM_DMA_CHANNELS); return &dma_hw->ch[channel]; } enum dma_channel_transfer_size { DMA_SIZE_8 = 0, ///< Byte transfer (8 bits) DMA_SIZE_16 = 1, ///< Half word transfer (16 bits) DMA_SIZE_32 = 2 ///< Word transfer (32 bits) }; /* Our own code ***************************************************************/ struct dmairq_handler_entry { dmairq_handler_t fn; void *arg; }; struct dmairq_handler_entry dmairq_handlers[NUM_DMA_CHANNELS] = {}; bool dmairq_initialized[NUM_DMA_IRQS] = {}; static void dmairq_handler(void) { enum dmairq irq = __get_current_exception() - VTABLE_FIRST_IRQ; size_t irq_idx = irq - DMAIRQ_0; assert(irq_idx < NUM_DMA_IRQS); uint32_t regval = dma_hw->irq_ctrl[irq_idx].ints; for (uint channel = 0; channel < NUM_DMA_CHANNELS; channel++) { if (regval & 1u<fn) handler->fn(handler->arg, irq, channel); } } /* acknowledge irq */ dma_hw->intr = regval; } void dmairq_set_and_enable_exclusive_handler(enum dmairq irq, uint channel, dmairq_handler_t fn, void *arg) { assert(irq == DMAIRQ_0 || irq == DMAIRQ_1); assert(channel < NUM_DMA_CHANNELS); assert(fn); assert(dmairq_handlers[channel].fn == NULL); dmairq_handlers[channel].fn = fn; dmairq_handlers[channel].arg = arg; size_t irq_idx = irq - DMAIRQ_0; hw_set_bits(&dma_hw->irq_ctrl[irq_idx].inte, 1u<