mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
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>
230 lines
5.9 KiB
C
230 lines
5.9 KiB
C
/* 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
|