From 324a2716d4da7efbe014c8dceb6df0a16c792eea Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 24 Jul 2015 16:55:42 -0700 Subject: [PATCH] stm32: Define second DMA controller present on STM32F3 Define second DMA controller, to be used by SPI3 on STM32F373. BRANCH=smaug TEST=Check with dmahelp the DMA engine is activated. BUG=chrome-os-partner:42304 Change-Id: Id2490ab91092b1ed738f5318bdeebfbe93f09171 Signed-off-by: Gwendal Grignou Reviewed-on: https://chromium-review.googlesource.com/288511 Reviewed-by: Vincent Palatin --- chip/stm32/dma.c | 29 ++++++++++++++++++++--------- chip/stm32/registers.h | 31 +++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c index f6f7be0871..56723e1be1 100644 --- a/chip/stm32/dma.c +++ b/chip/stm32/dma.c @@ -23,6 +23,7 @@ static struct { void *cb_data; /* Callback data for callback function */ } dma_irq[STM32_DMAC_COUNT]; + /** * Return the IRQ for the DMA channel * @@ -39,7 +40,11 @@ static int dma_get_irq(enum dma_channel channel) STM32_IRQ_DMA_CHANNEL_4_7 : STM32_IRQ_DMA_CHANNEL_2_3; #else - return STM32_IRQ_DMA_CHANNEL_1 + channel; + 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 } @@ -49,9 +54,9 @@ static int dma_get_irq(enum dma_channel channel) */ stm32_dma_chan_t *dma_get_channel(enum dma_channel channel) { - stm32_dma_regs_t *dma = STM32_DMA1_REGS; + stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); - return &dma->chan[channel]; + return &dma->chan[channel % STM32_DMAC_PER_CTLR]; } void dma_disable(enum dma_channel channel) @@ -143,15 +148,15 @@ int dma_bytes_done(stm32_dma_chan_t *chan, int orig_count) #ifdef CONFIG_DMA_HELP void dma_dump(enum dma_channel channel) { - stm32_dma_regs_t *dma = STM32_DMA1_REGS; + 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 * 4)) & 0xf, - (dma->ifcr >> (channel * 4)) & 0xf); + (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) @@ -209,15 +214,17 @@ void dma_test(enum dma_channel channel) void dma_init(void) { - /* Enable DMA1; current chips don't have DMA2 */ STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1; +#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_DMA1_REGS; + stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); const uint32_t mask = STM32_DMA_ISR_TCIF(channel); timestamp_t deadline; @@ -270,7 +277,7 @@ void dma_disable_tc_interrupt(enum dma_channel channel) void dma_clear_isr(enum dma_channel channel) { - stm32_dma_regs_t *dma = STM32_DMA1_REGS; + stm32_dma_regs_t *dma = STM32_DMA_REGS(channel); dma->ifcr |= STM32_DMA_ISR_ALL(channel); } @@ -336,6 +343,10 @@ 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 #endif /* CHIP_FAMILY_STM32F0 */ #endif /* CONFIG_DMA_DEFAULT_HANDLERS */ diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index f4416d9fc6..4970ea5f4b 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -144,6 +144,10 @@ #define STM32_IRQ_TIM19 78 /* STM32F373 only */ #define STM32_IRQ_FPU 81 /* STM32F373 only */ +/* To simplify code generation, define DMA channel 9..10 */ +#define STM32_IRQ_DMA_CHANNEL_9 STM32_IRQ_DMA2_CHANNEL1 +#define STM32_IRQ_DMA_CHANNEL_10 STM32_IRQ_DMA2_CHANNEL2 + /* aliases for easier code sharing */ #define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV #define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV @@ -565,6 +569,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_CR2 REG32(STM32_RCC_BASE + 0x34) /* STM32F0XX */ #define STM32_RCC_HB_DMA1 (1 << 0) +/* STM32F373 */ +#define STM32_RCC_HB_DMA2 (1 << 1) #define STM32_RCC_PB2_TIM1 (1 << 11) /* Except STM32F373 */ #define STM32_RCC_PB2_TIM15 (1 << 16) /* STM32F0XX and STM32F373 */ #define STM32_RCC_PB2_TIM16 (1 << 17) /* STM32F0XX and STM32F373 */ @@ -1102,6 +1108,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_DMA1_BASE 0x40026000 #elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) #define STM32_DMA1_BASE 0x40020000 +#define STM32_DMA2_BASE 0x40020400 #else #error Unsupported chip variant #endif @@ -1126,6 +1133,12 @@ enum dma_channel { STM32_DMAC_CH5 = 4, STM32_DMAC_CH6 = 5, STM32_DMAC_CH7 = 6, + /* + * Skip CH8, it should belong to DMA engine 1. + * Sharing code with STM32s that have 16 engines will be easier. + */ + STM32_DMAC_CH9 = 8, + STM32_DMAC_CH10 = 9, /* Channel functions */ STM32_DMAC_ADC = STM32_DMAC_CH1, @@ -1147,19 +1160,23 @@ enum dma_channel { #ifdef CHIP_VARIANT_STM32F373 STM32_DMAC_SPI2_RX = STM32_DMAC_CH4, STM32_DMAC_SPI2_TX = STM32_DMAC_CH5, + + STM32_DMAC_COUNT = 10, #else STM32_DMAC_SPI2_RX = STM32_DMAC_CH6, STM32_DMAC_SPI2_TX = STM32_DMAC_CH7, -#endif /* Only DMA1 (with 7 channels) is present on STM32L151x */ STM32_DMAC_COUNT = 7, +#endif #else /* stm32f03x and stm32f05x have only 5 channels */ STM32_DMAC_COUNT = 5, #endif }; +#define STM32_DMAC_PER_CTLR 8 + /* Registers for a single channel of the DMA controller */ struct stm32_dma_chan { uint32_t ccr; /* Control */ @@ -1187,8 +1204,18 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE) +#ifdef CHIP_FAMILY_STM32F3 +#define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE) + +#define STM32_DMA_REGS(channel) \ + ((channel) < STM32_DMAC_PER_CTLR ? STM32_DMA1_REGS : STM32_DMA2_REGS) +#else +#define STM32_DMA_REGS(channel) STM32_DMA1_REGS +#endif + /* Bits for DMA controller regs (isr and ifcr) */ -#define STM32_DMA_ISR_MASK(channel, mask) ((mask) << (4 * (channel))) +#define STM32_DMA_ISR_MASK(channel, mask) \ + ((mask) << (4 * ((channel) % STM32_DMAC_PER_CTLR))) #define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 0) #define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 1) #define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 2)