| /* Copyright (c) 2012 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); | 
 |  | 
 | /** | 
 |  * Init DMA peripheral ready for use | 
 |  */ | 
 | void dma_init(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 |