/* * linux/include/asm-mips/mach-jz4730/dma.h * * JZ4730 DMA definition. * * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. * * Author: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef __ASM_JZ4730_DMA_H__ #define __ASM_JZ4730_DMA_H__ #include #include /* need byte IO */ #include /* And spinlocks */ #include #include #define DMA_UNIT_32 32 #define DMA_UNIT_16 16 /* block-mode EOP: high DREQ: high DACK: low*/ #define DMA_BLOCK_CONF \ DMAC_DCCSR_TM | \ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS /* single-mode EOP: high DREQ: high DACK: low */ #define DMA_SINGLE_CONF \ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN | \ DMAC_DCCSR_ERDM_HLEVEL | DMAC_DCCSR_EACKS #define DMA_8bit_RX_CONF \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN #define DMA_8bit_TX_CONF \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ DMAC_DCCSR_DS_8b | DMAC_DCCSR_RDIL_IGN #define DMA_16bit_RX_CONF \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN #define DMA_16bit_TX_CONF \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_16 | \ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN #define DMA_32bit_RX_CONF \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN #define DMA_32bit_TX_CONF \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_32b | DMAC_DCCSR_RDIL_IGN #define DMA_16BYTE_RX_CONF \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_8 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN #define DMA_16BYTE_TX_CONF \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_8 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_32_16BYTE_TX_CMD \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_32_16BYTE_RX_CMD \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_32 | DMAC_DCCSR_DWDH_32 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_16BIT_TX_CMD \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_16BIT_RX_CMD \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ DMAC_DCCSR_DS_16b | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_16BYTE_RX_CMD \ DMAC_DCCSR_DAM | \ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN #define DMA_AIC_16BYTE_TX_CMD \ DMAC_DCCSR_SAM | \ DMAC_DCCSR_SWDH_16 | DMAC_DCCSR_DWDH_16 | \ DMAC_DCCSR_DS_16B | DMAC_DCCSR_RDIL_IGN /* DMA Device ID's follow */ enum { DMA_ID_UART0_TX = 0, DMA_ID_UART0_RX, DMA_ID_UART1_TX, DMA_ID_UART1_RX, DMA_ID_UART2_TX, DMA_ID_UART2_RX, DMA_ID_UART3_TX, DMA_ID_UART3_RX, DMA_ID_SSI_TX, DMA_ID_SSI_RX, DMA_ID_MSC_TX, DMA_ID_MSC_RX, DMA_ID_AIC_TX, DMA_ID_AIC_RX, DMA_ID_BLOCK, /* DREQ */ DMA_ID_SINGLE, /* DREQ */ DMA_ID_PCMCIA0_TX, DMA_ID_PCMCIA0_RX, DMA_ID_PCMCIA1_TX, DMA_ID_PCMCIA2_RX, DMA_ID_AUTO, DMA_ID_RAW_SET, NUM_DMA_DEV }; /* dummy DCCSR bit, i386 style DMA macros compitable */ #define DMA_MODE_READ 0 /* I/O to memory, no autoinit, * increment, single mode */ #define DMA_MODE_WRITE 1 /* memory to I/O, no autoinit, * increment, single mode */ #define DMA_MODE_CASCADE 2 /* pass thru DREQ->HRQ, * DACK<-HLDA only */ #define DMA_AUTOINIT 3 #define DMA_MODE_MASK 3 struct jz_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; unsigned int source; }; extern struct jz_dma_chan jz_dma_table[]; extern int jz_request_dma(int dev_id, const char *dev_str, irqreturn_t (*irqhandler)(int, void *), unsigned long irqflags, void *irq_dev_id); extern void jz_free_dma(unsigned int dmanr); extern int jz_dma_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data); extern void dump_jz_dma_channel(unsigned int dmanr); extern void enable_dma(unsigned int dmanr); extern void disable_dma(unsigned int dmanr); extern void set_dma_addr(unsigned int dmanr, unsigned int a); extern void set_dma_count(unsigned int dmanr, unsigned int count); extern void set_dma_mode(unsigned int dmanr, unsigned int mode); extern void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); extern void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt); extern int get_dma_residue(unsigned int dmanr); extern spinlock_t dma_spin_lock; static __inline__ unsigned long claim_dma_lock(void) { unsigned long flags; spin_lock_irqsave(&dma_spin_lock, flags); return flags; } static __inline__ void release_dma_lock(unsigned long flags) { spin_unlock_irqrestore(&dma_spin_lock, flags); } /* Clear the 'DMA Pointer Flip Flop'. * Write 0 for LSB/MSB, 1 for MSB/LSB access. */ #define clear_dma_ff(channel) static __inline__ struct jz_dma_chan *get_dma_chan(unsigned int dmanr) { if (dmanr > NUM_DMA || jz_dma_table[dmanr].dev_id < 0) return NULL; return &jz_dma_table[dmanr]; } static __inline__ int dma_halted(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return 1; return __dmac_channel_transmit_halt_detected(dmanr) ? 1 : 0; } static __inline__ unsigned int get_dma_mode(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return 0; return chan->mode; } static __inline__ void clear_dma_done(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); } static __inline__ void clear_dma_halt(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT); REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR); } static __inline__ void clear_dma_flag(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return; REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); REG_DMAC_DMACR &= ~(DMAC_DMACR_HTR | DMAC_DMACR_AER); } static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) { } static __inline__ unsigned int get_dma_done_status(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); unsigned long dccsr; if (!chan) return 0; dccsr = REG_DMAC_DCCSR(chan->io); return dccsr & (DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR); } static __inline__ int get_dma_done_irq(unsigned int dmanr) { struct jz_dma_chan *chan = get_dma_chan(dmanr); if (!chan) return -1; return chan->irq; } #endif /* __ASM_JZ4730_DMA_H__ */