diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-04-02 12:55:58 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-04-03 11:49:07 -0700 |
commit | 4d1aadaf601f04be9f45a540284f9b1184681787 (patch) | |
tree | bb1611c290acab471e004c439377d44ac477b5da /include/dma.h | |
parent | 9137686ebec50f44300168d48617790edf67bece (diff) | |
download | chrome-ec-4d1aadaf601f04be9f45a540284f9b1184681787.tar.gz |
Trigger dma_init() via HOOK_INIT
There's no need for it to be initalized in board_init(); it just needs
to be done before ADC / I2C / SPI initialize.
BUG=chrome-os-partner:18343
BRANCH=none
TEST=boot spring; verify EC communication and 'adc' console command still work
Change-Id: I6039848fe031222d5ca59b459adfe18fc3e8ef08
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/47182
Reviewed-by: Vic Yang <victoryang@chromium.org>
Diffstat (limited to 'include/dma.h')
-rw-r--r-- | include/dma.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/include/dma.h b/include/dma.h new file mode 100644 index 0000000000..c784558612 --- /dev/null +++ b/include/dma.h @@ -0,0 +1,229 @@ +/* Copyright (c) 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. + * + * Register map and API for STM32 processor dma registers + */ + +#ifndef __STM32_DMA +#define __STM32_DMA + +#include "common.h" + +/* + * Available DMA channels, numbered from 0 + * + * Note: The STM datasheet tends to number things from 1. We should ask + * the European elevator engineers to talk to MCU engineer counterparts + * about this. This means that if the datasheet refers to channel n, + * you need to use n-1 in the code. + */ +enum { + DMAC_ADC, + DMAC_SPI1_RX, + DMAC_SPI1_TX, + DMAC_SPI2_RX, + DMAC_SPI2_TX, + + /* + * The same channels are used for i2c2 and spi, you can't use them at + * the same time or it will cause dma to not work + */ + DMAC_I2C2_TX = 3, + DMAC_I2C2_RX = 4, + DMAC_I2C1_TX = 5, + DMAC_I2C1_RX = 6, + + /* DMA1 has 7 channels, DMA2 has 5 */ + DMA1_NUM_CHANNELS = 7, + DMA2_NUM_CHANNELS = 5, + DMA_NUM_CHANNELS = DMA1_NUM_CHANNELS + DMA2_NUM_CHANNELS, +}; + +/* A single channel of the DMA controller */ +struct dma_channel { + uint32_t ccr; /* Control */ + uint32_t cndtr; /* Number of data to transfer */ + uint32_t cpar; /* Peripheral address */ + uint32_t cmar; /* Memory address */ + uint32_t reserved; +}; + +/* Registers for the DMA controller */ +struct dma_ctlr { + uint32_t isr; + uint32_t ifcr; + struct dma_channel chan[DMA_NUM_CHANNELS]; +}; + +/* DMA channel options */ +struct dma_option { + unsigned channel; /* DMA channel */ + void *periph; /* Pointer to peripheral data register */ + unsigned flags; /* DMA flags for the control register. Normally + used to select memory size. */ +}; + +/* Defines for accessing DMA ccr */ +#define DMA_PL_SHIFT 12 +#define DMA_PL_MASK (3 << DMA_PL_SHIFT) +enum { + DMA_PL_LOW, + DMA_PL_MEDIUM, + DMA_PL_HIGH, + DMA_PL_VERY_HIGH, +}; + +#define DMA_EN (1 << 0) +#define DMA_TCIE (1 << 1) +#define DMA_HTIE (1 << 2) +#define DMA_TEIE (1 << 3) +#define DMA_DIR_FROM_MEM_MASK (1 << 4) +#define DMA_MINC_MASK (1 << 7) +#define DMA_TCIF(channel) (1 << (1 + 4 * channel)) + +#define DMA_MSIZE_BYTE (0 << 10) +#define DMA_MSIZE_HALF_WORD (1 << 10) +#define DMA_MSIZE_WORD (2 << 10) + +#define DMA_PSIZE_BYTE (0 << 8) +#define DMA_PSIZE_HALF_WORD (1 << 8) +#define DMA_PSIZE_WORD (2 << 8) + +#define DMA_POLLING_INTERVAL_US 100 /* us */ +#define DMA_TRANSFER_TIMEOUT_US (100 * MSEC) /* us */ + +/* + * Certain DMA channels must be used for certain peripherals and transfer + * directions. We provide an easy way for drivers to select the correct + * channel. + */ + +/** + * @param spi SPI port to request: STM32_SPI1_PORT or STM32_SPI2_PORT + * @return DMA channel to use for rx / tx on that port + */ +#define DMA_CHANNEL_FOR_SPI_RX(spi) \ + ((spi) == STM32_SPI1_PORT ? DMAC_SPI1_RX : DMAC_SPI2_RX) +#define DMA_CHANNEL_FOR_SPI_TX(spi) \ + ((spi) == STM32_SPI1_PORT ? DMAC_SPI1_TX : DMAC_SPI2_TX) + +/** + * Get a pointer to a DMA channel. + * + * @param channel Channel number to read (DMAC_...) + * @return pointer to DMA channel registers + */ +struct dma_channel *dma_get_channel(int channel); + +/** + * Prepare a DMA transfer to transmit data from memory to a peripheral + * + * Call dma_go() afterwards to actually start the transfer. + * + * @param option DMA channel options + * @param count Number of bytes to transfer + * @param memory Pointer to memory address + * + * @return pointer to prepared channel + */ +void dma_prepare_tx(const struct dma_option *option, unsigned count, + const void *memory); + +/** + * Start a DMA transfer to receive data to memory from a peripheral + * + * @param option DMA channel options + * @param count Number of bytes to transfer + * @param memory Pointer to memory address + */ +int dma_start_rx(const struct dma_option *option, unsigned count, + const void *memory); + +/** + * Stop a DMA transfer on a channel + * + * Disable the DMA channel and immediate stop all transfers on it. + * + * @param channel Channel number to stop (DMAC_...) + */ +void dma_disable(unsigned channel); + +/** + * Get the number of bytes available to read, or number of bytes written + * + * Since the DMA controller counts downwards, if we know the starting value + * we can work out how many bytes have been completed so far. + * + * @param chan DMA channel to check (use dma_get_channel()) + * @param orig_count Original number of bytes requested on channel + * @return number of bytes completed on a channel, or 0 if this channel is + * not enabled + */ +int dma_bytes_done(struct dma_channel *chan, int orig_count); + +/** + * Start a previously-prepared dma channel + * + * @param chan Channel to start (returned from dma_prepare...()) + */ +void dma_go(struct dma_channel *chan); + +/** + * Testing: Print out the data transferred by a channel + * + * @param channel Channel number to read (DMAC_...) + * @param buff Start of DMA buffer + */ +void dma_check(int channel, char *buff); + +/** + * Dump out imformation about a dma channel + * + * @param channel Channel number to read (DMAC_...) + */ +void dma_dump(unsigned channel); + +/** + * Testing: Test that DMA works correctly for memory to memory transfers + */ +void dma_test(void); + +/** + * Clear the DMA interrupt/event flags for a given channel + * + * @param channel Which channel's isr to clear (DMAC_...) + */ +void dma_clear_isr(int channel); + +/** + * Enable "Transfer Complete" interrupt for a DMA channel + * + * @param channel Which channel's interrupts to change (DMAC_...) + */ +void dma_enable_tc_interrupt(int channel); + +/** + * Disable "Transfer Complete" interrupt for a DMA channel + * + * @param channel Which channel's interrupts to change (DMAC_...) + */ +void dma_disable_tc_interrupt(int channel); + +/** + * Get a pointer to the DMA peripheral controller that owns the channel + * + * @param channel Channel number to get the controller for (DMAC_...) + * @return pointer to DMA channel registers + */ +struct dma_ctlr *dma_get_ctlr(int channel); + +/** + * Wait for the DMA transfer to complete by polling the transfer complete flag + * + * @param channelĀ» Channel number to wait on (DMAC_...) + * @return -1 for timeout, 0 for sucess + */ +int dma_wait(int channel); + +#endif |