⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 au1000_dma.h

📁 linux-2.6.15.6
💻 H
字号:
/* * BRIEF MODULE DESCRIPTION *	Defines for using and allocating dma channels on the Alchemy *      Au1000 mips processor. * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. *         	stevel@mvista.com or source@mvista.com * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  You should have received a copy of the  GNU General Public License along *  with this program; if not, write  to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. * */#ifndef __ASM_AU1000_DMA_H#define __ASM_AU1000_DMA_H#include <asm/io.h>		/* need byte IO */#include <linux/spinlock.h>	/* And spinlocks */#include <linux/delay.h>#include <asm/system.h>#define NUM_AU1000_DMA_CHANNELS	8/* DMA Channel Base Addresses */#define DMA_CHANNEL_BASE	0xB4002000#define DMA_CHANNEL_LEN		0x00000100/* DMA Channel Register Offsets */#define DMA_MODE_SET		0x00000000#define DMA_MODE_READ		DMA_MODE_SET#define DMA_MODE_CLEAR		0x00000004/* DMA Mode register bits follow */#define DMA_DAH_MASK		(0x0f << 20)#define DMA_DID_BIT		16#define DMA_DID_MASK		(0x0f << DMA_DID_BIT)#define DMA_DS			(1<<15)#define DMA_BE			(1<<13)#define DMA_DR			(1<<12)#define DMA_TS8			(1<<11)#define DMA_DW_BIT		9#define DMA_DW_MASK		(0x03 << DMA_DW_BIT)#define DMA_DW8			(0 << DMA_DW_BIT)#define DMA_DW16		(1 << DMA_DW_BIT)#define DMA_DW32		(2 << DMA_DW_BIT)#define DMA_NC			(1<<8)#define DMA_IE			(1<<7)#define DMA_HALT		(1<<6)#define DMA_GO			(1<<5)#define DMA_AB			(1<<4)#define DMA_D1			(1<<3)#define DMA_BE1			(1<<2)#define DMA_D0			(1<<1)#define DMA_BE0			(1<<0)#define DMA_PERIPHERAL_ADDR       0x00000008#define DMA_BUFFER0_START         0x0000000C#define DMA_BUFFER1_START         0x00000014#define DMA_BUFFER0_COUNT         0x00000010#define DMA_BUFFER1_COUNT         0x00000018#define DMA_BAH_BIT 16#define DMA_BAH_MASK (0x0f << DMA_BAH_BIT)#define DMA_COUNT_BIT 0#define DMA_COUNT_MASK (0xffff << DMA_COUNT_BIT)/* DMA Device ID's follow */enum {	DMA_ID_UART0_TX = 0,	DMA_ID_UART0_RX,	DMA_ID_GP04,	DMA_ID_GP05,	DMA_ID_AC97C_TX,	DMA_ID_AC97C_RX,	DMA_ID_UART3_TX,	DMA_ID_UART3_RX,	DMA_ID_USBDEV_EP0_RX,	DMA_ID_USBDEV_EP0_TX,	DMA_ID_USBDEV_EP2_TX,	DMA_ID_USBDEV_EP3_TX,	DMA_ID_USBDEV_EP4_RX,	DMA_ID_USBDEV_EP5_RX,	DMA_ID_I2S_TX,	DMA_ID_I2S_RX,	DMA_NUM_DEV};/* DMA Device ID's for 2nd bank (AU1100) follow */enum {	DMA_ID_SD0_TX = 0,	DMA_ID_SD0_RX,	DMA_ID_SD1_TX,	DMA_ID_SD1_RX,	DMA_NUM_DEV_BANK2};struct dma_chan {	int dev_id;		// this channel is allocated if >=0, free otherwise	unsigned int io;	const char *dev_str;	int irq;	void *irq_dev;	unsigned int fifo_addr;	unsigned int mode;};/* These are in arch/mips/au1000/common/dma.c */extern struct dma_chan au1000_dma_table[];extern int request_au1000_dma(int dev_id,			      const char *dev_str,			      irqreturn_t (*irqhandler)(int, void *,						 struct pt_regs *),			      unsigned long irqflags,			      void *irq_dev_id);extern void free_au1000_dma(unsigned int dmanr);extern int au1000_dma_read_proc(char *buf, char **start, off_t fpos,				int length, int *eof, void *data);extern void dump_au1000_dma_channel(unsigned int dmanr);extern spinlock_t au1000_dma_spin_lock;static __inline__ struct dma_chan *get_dma_chan(unsigned int dmanr){	if (dmanr >= NUM_AU1000_DMA_CHANNELS	    || au1000_dma_table[dmanr].dev_id < 0)		return NULL;	return &au1000_dma_table[dmanr];}static __inline__ unsigned long claim_dma_lock(void){	unsigned long flags;	spin_lock_irqsave(&au1000_dma_spin_lock, flags);	return flags;}static __inline__ void release_dma_lock(unsigned long flags){	spin_unlock_irqrestore(&au1000_dma_spin_lock, flags);}/* * Set the DMA buffer enable bits in the mode register. */static __inline__ void enable_dma_buffer0(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_BE0, chan->io + DMA_MODE_SET);}static __inline__ void enable_dma_buffer1(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_BE1, chan->io + DMA_MODE_SET);}static __inline__ void enable_dma_buffers(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);}static __inline__ void start_dma(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_GO, chan->io + DMA_MODE_SET);}#define DMA_HALT_POLL 0x5000static __inline__ void halt_dma(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	int i;	if (!chan)		return;	au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);	// poll the halt bit	for (i = 0; i < DMA_HALT_POLL; i++)		if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)			break;	if (i == DMA_HALT_POLL)		printk(KERN_INFO "halt_dma: HALT poll expired!\n");}static __inline__ void disable_dma(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	halt_dma(dmanr);	// now we can disable the buffers	au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);}static __inline__ int dma_halted(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return 1;	return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;}/* initialize a DMA channel */static __inline__ void init_dma(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	u32 mode;	if (!chan)		return;	disable_dma(dmanr);	// set device FIFO address	au_writel(CPHYSADDR(chan->fifo_addr),		  chan->io + DMA_PERIPHERAL_ADDR);	mode = chan->mode | (chan->dev_id << DMA_DID_BIT);	if (chan->irq)		mode |= DMA_IE;	au_writel(~mode, chan->io + DMA_MODE_CLEAR);	au_writel(mode, chan->io + DMA_MODE_SET);}/* * set mode for a specific DMA channel */static __inline__ void set_dma_mode(unsigned int dmanr, unsigned int mode){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	/*	 * set_dma_mode is only allowed to change endianess, direction,	 * transfer size, device FIFO width, and coherency settings.	 * Make sure anything else is masked off.	 */	mode &= (DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);	chan->mode &= ~(DMA_BE | DMA_DR | DMA_TS8 | DMA_DW_MASK | DMA_NC);	chan->mode |= mode;}static __inline__ unsigned int get_dma_mode(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return 0;	return chan->mode;}static __inline__ int get_dma_active_buffer(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return -1;	return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;}/* * set the device FIFO address for a specific DMA channel - only * applicable to GPO4 and GPO5. All the other devices have fixed * FIFO addresses. */static __inline__ void set_dma_fifo_addr(unsigned int dmanr,					 unsigned int a){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	if (chan->mode & DMA_DS)	/* second bank of device ids */		return;	if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)		return;	au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);}/* * Clear the DMA buffer done bits in the mode register. */static __inline__ void clear_dma_done0(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);}static __inline__ void clear_dma_done1(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);}/* * This does nothing - not applicable to Au1000 DMA. */static __inline__ void set_dma_page(unsigned int dmanr, char pagenr){}/* * Set Buffer 0 transfer address for specific DMA channel. */static __inline__ void set_dma_addr0(unsigned int dmanr, unsigned int a){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(a, chan->io + DMA_BUFFER0_START);}/* * Set Buffer 1 transfer address for specific DMA channel. */static __inline__ void set_dma_addr1(unsigned int dmanr, unsigned int a){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	au_writel(a, chan->io + DMA_BUFFER1_START);}/* * Set Buffer 0 transfer size (max 64k) for a specific DMA channel. */static __inline__ void set_dma_count0(unsigned int dmanr,				      unsigned int count){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	count &= DMA_COUNT_MASK;	au_writel(count, chan->io + DMA_BUFFER0_COUNT);}/* * Set Buffer 1 transfer size (max 64k) for a specific DMA channel. */static __inline__ void set_dma_count1(unsigned int dmanr,				      unsigned int count){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	count &= DMA_COUNT_MASK;	au_writel(count, chan->io + DMA_BUFFER1_COUNT);}/* * Set both buffer transfer sizes (max 64k) for a specific DMA channel. */static __inline__ void set_dma_count(unsigned int dmanr,				     unsigned int count){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return;	count &= DMA_COUNT_MASK;	au_writel(count, chan->io + DMA_BUFFER0_COUNT);	au_writel(count, chan->io + DMA_BUFFER1_COUNT);}/* * Returns which buffer has its done bit set in the mode register. * Returns -1 if neither or both done bits set. */static __inline__ unsigned int get_dma_buffer_done(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return 0;    return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);}/* * Returns the DMA channel's Buffer Done IRQ number. */static __inline__ int get_dma_done_irq(unsigned int dmanr){	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return -1;	return chan->irq;}/* * Get DMA residue count. Returns the number of _bytes_ left to transfer. */static __inline__ int get_dma_residue(unsigned int dmanr){	int curBufCntReg, count;	struct dma_chan *chan = get_dma_chan(dmanr);	if (!chan)		return 0;	curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?	    DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;	count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;	if ((chan->mode & DMA_DW_MASK) == DMA_DW16)		count <<= 1;	else if ((chan->mode & DMA_DW_MASK) == DMA_DW32)		count <<= 2;	return count;}#endif /* __ASM_AU1000_DMA_H */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -