diff options
Diffstat (limited to 'chip/stm32/dma.c')
-rw-r--r-- | chip/stm32/dma.c | 410 |
1 files changed, 0 insertions, 410 deletions
diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c deleted file mode 100644 index 55317ba003..0000000000 --- a/chip/stm32/dma.c +++ /dev/null @@ -1,410 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "clock.h" -#include "common.h" -#include "console.h" -#include "dma.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_DMA, outstr) -#define CPRINTF(format, args...) cprintf(CC_DMA, format, ## args) - -/* Callback data to use when IRQ fires */ -static struct { - void (*cb)(void *); /* Callback function to call */ - void *cb_data; /* Callback data for callback function */ -} dma_irq[STM32_DMAC_COUNT]; - - -/** - * Return the IRQ for the DMA channel - * - * @param channel Channel number - * @return IRQ for the channel - */ -static int dma_get_irq(enum dma_channel channel) -{ -#ifdef CHIP_FAMILY_STM32F0 - if (channel == STM32_DMAC_CH1) - return STM32_IRQ_DMA_CHANNEL_1; - - return channel > STM32_DMAC_CH3 ? - STM32_IRQ_DMA_CHANNEL_4_7 : - STM32_IRQ_DMA_CHANNEL_2_3; -#elif defined(CHIP_FAMILY_STM32L4) - if (channel < STM32_DMAC_PER_CTLR) - return STM32_IRQ_DMA_CHANNEL_1 + channel; - else { - if (channel <= STM32_DMAC_CH13) - return STM32_IRQ_DMA2_CHANNEL1 + - (channel - STM32_DMAC_PER_CTLR); - else - return STM32_IRQ_DMA2_CHANNEL6 + - (channel - STM32_DMAC_PER_CTLR - 5); - } -#else - if (channel < STM32_DMAC_PER_CTLR) - return STM32_IRQ_DMA_CHANNEL_1 + channel; - else - return STM32_IRQ_DMA2_CHANNEL1 + - (channel - STM32_DMAC_PER_CTLR); -#endif -} - -/* - * Note, you must decrement the channel value by 1 from what is specified - * in the datasheets, as they index from 1 and this indexes from 0! - */ -stm32_dma_chan_t *dma_get_channel(enum dma_channel channel) -{ - stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); - - return &dma->chan[channel % STM32_DMAC_PER_CTLR]; -} - -#ifdef STM32_DMAMUX_CxCR -void dma_select_channel(enum dma_channel channel, uint8_t req) -{ - /* - * STM32G4 includes a DMAMUX block which is used to handle dma requests - * by peripherals. The correct 'req' number for a given peripheral is - * given in ST doc RM0440. - */ - STM32_DMAMUX_CxCR(channel) = req; -} -#elif defined(STM32_DMA_CSELR) -void dma_select_channel(enum dma_channel channel, unsigned char stream) -{ - /* Local channel # starting from 0 on each DMA controller */ - const unsigned char ch = channel % STM32_DMAC_PER_CTLR; - const unsigned char shift = STM32_DMA_PERIPHERALS_PER_CHANNEL; - const unsigned char mask = BIT(shift) - 1; - uint32_t val; - - ASSERT(ch < STM32_DMAC_PER_CTLR); - ASSERT(stream <= mask); - val = STM32_DMA_CSELR(channel) & ~(mask << ch * shift); - STM32_DMA_CSELR(channel) = val | (stream << ch * shift); -} -#endif /* STM32_DMAMUX_CxCR/STM32_DMA_CSELR */ - -void dma_disable(enum dma_channel channel) -{ - stm32_dma_chan_t *chan = dma_get_channel(channel); - - if (chan->ccr & STM32_DMA_CCR_EN) - chan->ccr &= ~STM32_DMA_CCR_EN; -} - -void dma_disable_all(void) -{ - int ch; - - for (ch = 0; ch < STM32_DMAC_COUNT; ch++) { - stm32_dma_chan_t *chan = dma_get_channel(ch); - - chan->ccr &= ~STM32_DMA_CCR_EN; - } -} - -/** - * Prepare a channel for use and start it - * - * @param chan Channel to read - * @param count Number of bytes to transfer - * @param periph Pointer to peripheral data register - * @param memory Pointer to memory address for receive/transmit - * @param flags DMA flags for the control register, normally: - * STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR for tx - * 0 for rx - */ -static void prepare_channel(enum dma_channel channel, unsigned int count, - void *periph, void *memory, unsigned int flags) -{ - stm32_dma_chan_t *chan = dma_get_channel(channel); - uint32_t ccr = STM32_DMA_CCR_PL_VERY_HIGH; - - dma_disable(channel); - dma_clear_isr(channel); - - /* Following the order in Doc ID 15965 Rev 5 p194 */ - chan->cpar = (uint32_t)periph; - chan->cmar = (uint32_t)memory; - chan->cndtr = count; - chan->ccr = ccr; - ccr |= flags; - chan->ccr = ccr; -} - -void dma_go(stm32_dma_chan_t *chan) -{ - /* Flush data in write buffer so that DMA can get the latest data */ - asm volatile("dsb;"); - - /* Fire it up */ - chan->ccr |= STM32_DMA_CCR_EN; -} - -void dma_prepare_tx(const struct dma_option *option, unsigned int count, - const void *memory) -{ - /* - * Cast away const for memory pointer; this is ok because we know - * we're preparing the channel for transmit. - */ - prepare_channel(option->channel, count, option->periph, (void *)memory, - STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR | - option->flags); -} - -void dma_start_rx(const struct dma_option *option, unsigned int count, - void *memory) -{ - stm32_dma_chan_t *chan = dma_get_channel(option->channel); - - prepare_channel(option->channel, count, option->periph, memory, - STM32_DMA_CCR_MINC | option->flags); - dma_go(chan); -} - -int dma_bytes_done(stm32_dma_chan_t *chan, int orig_count) -{ - return orig_count - chan->cndtr; -} - -bool dma_is_enabled(stm32_dma_chan_t *chan) -{ - return (chan->ccr & STM32_DMA_CCR_EN); -} - -#ifdef CONFIG_DMA_HELP -void dma_dump(enum dma_channel channel) -{ - stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); - stm32_dma_chan_t *chan = dma_get_channel(channel); - - CPRINTF("ccr=%x, cndtr=%x, cpar=%x, cmar=%x\n", chan->ccr, - chan->cndtr, chan->cpar, chan->cmar); - CPRINTF("chan %d, isr=%x, ifcr=%x\n", - channel, - (dma->isr >> ((channel % STM32_DMAC_PER_CTLR) * 4)) & 0xf, - (dma->ifcr >> ((channel % STM32_DMAC_PER_CTLR) * 4)) & 0xf); -} - -void dma_check(enum dma_channel channel, char *buf) -{ - stm32_dma_chan_t *chan; - int count; - int i; - - chan = dma_get_channel(channel); - count = chan->cndtr; - CPRINTF("c=%d\n", count); - udelay(100 * MSEC); - CPRINTF("c=%d\n", chan->cndtr); - for (i = 0; i < count; i++) - CPRINTF("%02x ", buf[i]); - udelay(100 * MSEC); - CPRINTF("c=%d\n", chan->cndtr); - for (i = 0; i < count; i++) - CPRINTF("%02x ", buf[i]); -} - -/* Run a check of memory-to-memory DMA */ -void dma_test(enum dma_channel channel) -{ - stm32_dma_chan_t *chan = dma_get_channel(channel); - uint32_t ctrl; - char periph[16], memory[16]; - unsigned int count = sizeof(periph); - int i; - - memset(memory, '\0', sizeof(memory)); - for (i = 0; i < count; i++) - periph[i] = 10 + i; - - /* Following the order in Doc ID 15965 Rev 5 p194 */ - chan->cpar = (uint32_t)periph; - chan->cmar = (uint32_t)memory; - chan->cndtr = count; - ctrl = STM32_DMA_CCR_PL_MEDIUM; - chan->ccr = ctrl; - - ctrl |= STM32_DMA_CCR_MINC; /* | STM32_DMA_CCR_DIR */; - ctrl |= STM32_DMA_CCR_MEM2MEM; - ctrl |= STM32_DMA_CCR_PINC; -/* ctrl |= STM32_DMA_CCR_MSIZE_32_BIT; */ -/* ctrl |= STM32_DMA_CCR_PSIZE_32_BIT; */ - chan->ccr = ctrl; - chan->ccr = ctrl | STM32_DMA_CCR_EN; - - for (i = 0; i < count; i++) - CPRINTF("%d/%d ", periph[i], memory[i]); - CPRINTF("\ncount=%d\n", chan->cndtr); -} -#endif /* CONFIG_DMA_HELP */ - -void dma_init(void) -{ -#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32L5) - STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN|STM32_RCC_AHB1ENR_DMA2EN; -#elif defined(CHIP_FAMILY_STM32G4) - STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN|STM32_RCC_AHB1ENR_DMA2EN | - STM32_RCC_AHB1ENR_DMAMUXEN; -#else - STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1; -#endif -#ifdef CHIP_FAMILY_STM32F3 - STM32_RCC_AHBENR |= STM32_RCC_HB_DMA2; -#endif - /* Delay 1 AHB clock cycle after the clock is enabled */ - clock_wait_bus_cycles(BUS_AHB, 1); -} - -int dma_wait(enum dma_channel channel) -{ - stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); - const uint32_t mask = STM32_DMA_ISR_TCIF(channel); - timestamp_t deadline; - - deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US; - while ((dma->isr & mask) != mask) { - if (deadline.val <= get_time().val) - return EC_ERROR_TIMEOUT; - - udelay(DMA_POLLING_INTERVAL_US); - } - return EC_SUCCESS; -} - -static inline void _dma_wake_callback(void *cb_data) -{ - task_id_t id = (task_id_t)(int)cb_data; - - if (id != TASK_ID_INVALID) - task_set_event(id, TASK_EVENT_DMA_TC); -} - -void dma_enable_tc_interrupt(enum dma_channel channel) -{ - dma_enable_tc_interrupt_callback(channel, _dma_wake_callback, - (void *)(int)task_get_current()); -} - -void dma_enable_tc_interrupt_callback(enum dma_channel channel, - void (*callback)(void *), - void *callback_data) -{ - stm32_dma_chan_t *chan = dma_get_channel(channel); - - dma_irq[channel].cb = callback; - dma_irq[channel].cb_data = callback_data; - - chan->ccr |= STM32_DMA_CCR_TCIE; - task_enable_irq(dma_get_irq(channel)); -} - -void dma_disable_tc_interrupt(enum dma_channel channel) -{ - stm32_dma_chan_t *chan = dma_get_channel(channel); - - chan->ccr &= ~STM32_DMA_CCR_TCIE; - task_disable_irq(dma_get_irq(channel)); - - dma_irq[channel].cb = NULL; - dma_irq[channel].cb_data = NULL; -} - -void dma_clear_isr(enum dma_channel channel) -{ - stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); - - dma->ifcr |= STM32_DMA_ISR_ALL(channel); -} - -#ifdef CONFIG_DMA_DEFAULT_HANDLERS -#ifdef CHIP_FAMILY_STM32F0 -void dma_event_interrupt_channel_1(void) -{ - if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(STM32_DMAC_CH1)) { - dma_clear_isr(STM32_DMAC_CH1); - if (dma_irq[STM32_DMAC_CH1].cb != NULL) - (*dma_irq[STM32_DMAC_CH1].cb) - (dma_irq[STM32_DMAC_CH1].cb_data); - } -} -DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_1, dma_event_interrupt_channel_1, 1); - -void dma_event_interrupt_channel_2_3(void) -{ - int i; - - for (i = STM32_DMAC_CH2; i <= STM32_DMAC_CH3; i++) { - if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(i)) { - dma_clear_isr(i); - if (dma_irq[i].cb != NULL) - (*dma_irq[i].cb)(dma_irq[i].cb_data); - } - } -} -DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_2_3, dma_event_interrupt_channel_2_3, 1); - -void dma_event_interrupt_channel_4_7(void) -{ - int i; - const unsigned int max_chan = MIN(STM32_DMAC_CH7, STM32_DMAC_COUNT); - - for (i = STM32_DMAC_CH4; i <= max_chan; i++) { - if (STM32_DMA1_REGS->isr & STM32_DMA_ISR_TCIF(i)) { - dma_clear_isr(i); - if (dma_irq[i].cb != NULL) - (*dma_irq[i].cb)(dma_irq[i].cb_data); - } - } -} -DECLARE_IRQ(STM32_IRQ_DMA_CHANNEL_4_7, dma_event_interrupt_channel_4_7, 1); - -#else /* !CHIP_FAMILY_STM32F0 */ - -#define DECLARE_DMA_IRQ(x) \ - void CONCAT2(dma_event_interrupt_channel_, x)(void) \ - { \ - dma_clear_isr(CONCAT2(STM32_DMAC_CH, x)); \ - if (dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb != NULL) \ - (*dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb) \ - (dma_irq[CONCAT2(STM32_DMAC_CH, x)].cb_data); \ - } \ - DECLARE_IRQ(CONCAT2(STM32_IRQ_DMA_CHANNEL_, x), \ - CONCAT2(dma_event_interrupt_channel_, x), 1) - -DECLARE_DMA_IRQ(1); -DECLARE_DMA_IRQ(2); -DECLARE_DMA_IRQ(3); -DECLARE_DMA_IRQ(4); -DECLARE_DMA_IRQ(5); -DECLARE_DMA_IRQ(6); -DECLARE_DMA_IRQ(7); -#ifdef CHIP_FAMILY_STM32F3 -DECLARE_DMA_IRQ(9); -DECLARE_DMA_IRQ(10); -#endif -#ifdef CHIP_FAMILY_STM32L4 -DECLARE_DMA_IRQ(9); -DECLARE_DMA_IRQ(10); -DECLARE_DMA_IRQ(11); -DECLARE_DMA_IRQ(12); -DECLARE_DMA_IRQ(13); -DECLARE_DMA_IRQ(14); -DECLARE_DMA_IRQ(15); -#endif - -#endif /* CHIP_FAMILY_STM32F0 */ -#endif /* CONFIG_DMA_DEFAULT_HANDLERS */ |