summaryrefslogtreecommitdiff
path: root/include/dma.h
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-04-02 12:55:58 -0700
committerChromeBot <chrome-bot@google.com>2013-04-03 11:49:07 -0700
commit4d1aadaf601f04be9f45a540284f9b1184681787 (patch)
treebb1611c290acab471e004c439377d44ac477b5da /include/dma.h
parent9137686ebec50f44300168d48617790edf67bece (diff)
downloadchrome-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.h229
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