1/* 2 * dma.h - Blackfin DMA defines/structures/etc... 3 * 4 * Copyright 2004-2008 Analog Devices Inc. 5 * Licensed under the GPL-2 or later. 6 */ 7 8#ifndef _BLACKFIN_DMA_H_ 9#define _BLACKFIN_DMA_H_ 10 11#include <linux/interrupt.h> 12#include <mach/dma.h> 13#include <linux/atomic.h> 14#include <asm/blackfin.h> 15#include <asm/page.h> 16#include <asm-generic/dma.h> 17#include <asm/bfin_dma.h> 18 19/*------------------------- 20 * config reg bits value 21 *-------------------------*/ 22#define DATA_SIZE_8 0 23#define DATA_SIZE_16 1 24#define DATA_SIZE_32 2 25#ifdef CONFIG_BF60x 26#define DATA_SIZE_64 3 27#endif 28 29#define DMA_FLOW_STOP 0 30#define DMA_FLOW_AUTO 1 31#ifdef CONFIG_BF60x 32#define DMA_FLOW_LIST 4 33#define DMA_FLOW_ARRAY 5 34#define DMA_FLOW_LIST_DEMAND 6 35#define DMA_FLOW_ARRAY_DEMAND 7 36#else 37#define DMA_FLOW_ARRAY 4 38#define DMA_FLOW_SMALL 6 39#define DMA_FLOW_LARGE 7 40#endif 41 42#define DIMENSION_LINEAR 0 43#define DIMENSION_2D 1 44 45#define DIR_READ 0 46#define DIR_WRITE 1 47 48#define INTR_DISABLE 0 49#ifdef CONFIG_BF60x 50#define INTR_ON_PERI 1 51#endif 52#define INTR_ON_BUF 2 53#define INTR_ON_ROW 3 54 55#define DMA_NOSYNC_KEEP_DMA_BUF 0 56#define DMA_SYNC_RESTART 1 57 58#ifdef DMA_MMR_SIZE_32 59#define DMA_MMR_SIZE_TYPE long 60#define DMA_MMR_READ bfin_read32 61#define DMA_MMR_WRITE bfin_write32 62#else 63#define DMA_MMR_SIZE_TYPE short 64#define DMA_MMR_READ bfin_read16 65#define DMA_MMR_WRITE bfin_write16 66#endif 67 68struct dma_desc_array { 69 unsigned long start_addr; 70 unsigned DMA_MMR_SIZE_TYPE cfg; 71 unsigned DMA_MMR_SIZE_TYPE x_count; 72 DMA_MMR_SIZE_TYPE x_modify; 73} __attribute__((packed)); 74 75struct dmasg { 76 void *next_desc_addr; 77 unsigned long start_addr; 78 unsigned DMA_MMR_SIZE_TYPE cfg; 79 unsigned DMA_MMR_SIZE_TYPE x_count; 80 DMA_MMR_SIZE_TYPE x_modify; 81 unsigned DMA_MMR_SIZE_TYPE y_count; 82 DMA_MMR_SIZE_TYPE y_modify; 83} __attribute__((packed)); 84 85struct dma_register { 86 void *next_desc_ptr; /* DMA Next Descriptor Pointer register */ 87 unsigned long start_addr; /* DMA Start address register */ 88#ifdef CONFIG_BF60x 89 unsigned long cfg; /* DMA Configuration register */ 90 91 unsigned long x_count; /* DMA x_count register */ 92 93 long x_modify; /* DMA x_modify register */ 94 95 unsigned long y_count; /* DMA y_count register */ 96 97 long y_modify; /* DMA y_modify register */ 98 99 unsigned long reserved; 100 unsigned long reserved2; 101 102 void *curr_desc_ptr; /* DMA Current Descriptor Pointer 103 register */ 104 void *prev_desc_ptr; /* DMA previous initial Descriptor Pointer 105 register */ 106 unsigned long curr_addr_ptr; /* DMA Current Address Pointer 107 register */ 108 unsigned long irq_status; /* DMA irq status register */ 109 110 unsigned long curr_x_count; /* DMA Current x-count register */ 111 112 unsigned long curr_y_count; /* DMA Current y-count register */ 113 114 unsigned long reserved3; 115 116 unsigned long bw_limit_count; /* DMA band width limit count register */ 117 unsigned long curr_bw_limit_count; /* DMA Current band width limit 118 count register */ 119 unsigned long bw_monitor_count; /* DMA band width limit count register */ 120 unsigned long curr_bw_monitor_count; /* DMA Current band width limit 121 count register */ 122#else 123 unsigned short cfg; /* DMA Configuration register */ 124 unsigned short dummy1; /* DMA Configuration register */ 125 126 unsigned long reserved; 127 128 unsigned short x_count; /* DMA x_count register */ 129 unsigned short dummy2; 130 131 short x_modify; /* DMA x_modify register */ 132 unsigned short dummy3; 133 134 unsigned short y_count; /* DMA y_count register */ 135 unsigned short dummy4; 136 137 short y_modify; /* DMA y_modify register */ 138 unsigned short dummy5; 139 140 void *curr_desc_ptr; /* DMA Current Descriptor Pointer 141 register */ 142 unsigned long curr_addr_ptr; /* DMA Current Address Pointer 143 register */ 144 unsigned short irq_status; /* DMA irq status register */ 145 unsigned short dummy6; 146 147 unsigned short peripheral_map; /* DMA peripheral map register */ 148 unsigned short dummy7; 149 150 unsigned short curr_x_count; /* DMA Current x-count register */ 151 unsigned short dummy8; 152 153 unsigned long reserved2; 154 155 unsigned short curr_y_count; /* DMA Current y-count register */ 156 unsigned short dummy9; 157 158 unsigned long reserved3; 159#endif 160 161}; 162 163struct dma_channel { 164 const char *device_id; 165 atomic_t chan_status; 166 volatile struct dma_register *regs; 167 struct dmasg *sg; /* large mode descriptor */ 168 unsigned int irq; 169 void *data; 170#ifdef CONFIG_PM 171 unsigned short saved_peripheral_map; 172#endif 173}; 174 175#ifdef CONFIG_PM 176int blackfin_dma_suspend(void); 177void blackfin_dma_resume(void); 178#endif 179 180/******************************************************************************* 181* DMA API's 182*******************************************************************************/ 183extern struct dma_channel dma_ch[MAX_DMA_CHANNELS]; 184extern struct dma_register * const dma_io_base_addr[MAX_DMA_CHANNELS]; 185extern int channel2irq(unsigned int channel); 186 187static inline void set_dma_start_addr(unsigned int channel, unsigned long addr) 188{ 189 dma_ch[channel].regs->start_addr = addr; 190} 191static inline void set_dma_next_desc_addr(unsigned int channel, void *addr) 192{ 193 dma_ch[channel].regs->next_desc_ptr = addr; 194} 195static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr) 196{ 197 dma_ch[channel].regs->curr_desc_ptr = addr; 198} 199static inline void set_dma_x_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE x_count) 200{ 201 dma_ch[channel].regs->x_count = x_count; 202} 203static inline void set_dma_y_count(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE y_count) 204{ 205 dma_ch[channel].regs->y_count = y_count; 206} 207static inline void set_dma_x_modify(unsigned int channel, DMA_MMR_SIZE_TYPE x_modify) 208{ 209 dma_ch[channel].regs->x_modify = x_modify; 210} 211static inline void set_dma_y_modify(unsigned int channel, DMA_MMR_SIZE_TYPE y_modify) 212{ 213 dma_ch[channel].regs->y_modify = y_modify; 214} 215static inline void set_dma_config(unsigned int channel, unsigned DMA_MMR_SIZE_TYPE config) 216{ 217 dma_ch[channel].regs->cfg = config; 218} 219static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr) 220{ 221 dma_ch[channel].regs->curr_addr_ptr = addr; 222} 223 224#ifdef CONFIG_BF60x 225static inline unsigned long 226set_bfin_dma_config2(char direction, char flow_mode, char intr_mode, 227 char dma_mode, char mem_width, char syncmode, char peri_width) 228{ 229 unsigned long config = 0; 230 231 switch (intr_mode) { 232 case INTR_ON_BUF: 233 if (dma_mode == DIMENSION_2D) 234 config = DI_EN_Y; 235 else 236 config = DI_EN_X; 237 break; 238 case INTR_ON_ROW: 239 config = DI_EN_X; 240 break; 241 case INTR_ON_PERI: 242 config = DI_EN_P; 243 break; 244 }; 245 246 return config | (direction << 1) | (mem_width << 8) | (dma_mode << 26) | 247 (flow_mode << 12) | (syncmode << 2) | (peri_width << 4); 248} 249#endif 250 251static inline unsigned DMA_MMR_SIZE_TYPE 252set_bfin_dma_config(char direction, char flow_mode, 253 char intr_mode, char dma_mode, char mem_width, char syncmode) 254{ 255#ifdef CONFIG_BF60x 256 return set_bfin_dma_config2(direction, flow_mode, intr_mode, dma_mode, 257 mem_width, syncmode, mem_width); 258#else 259 return (direction << 1) | (mem_width << 2) | (dma_mode << 4) | 260 (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5); 261#endif 262} 263 264static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_irqstat(unsigned int channel) 265{ 266 return dma_ch[channel].regs->irq_status; 267} 268static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_xcount(unsigned int channel) 269{ 270 return dma_ch[channel].regs->curr_x_count; 271} 272static inline unsigned DMA_MMR_SIZE_TYPE get_dma_curr_ycount(unsigned int channel) 273{ 274 return dma_ch[channel].regs->curr_y_count; 275} 276static inline void *get_dma_next_desc_ptr(unsigned int channel) 277{ 278 return dma_ch[channel].regs->next_desc_ptr; 279} 280static inline void *get_dma_curr_desc_ptr(unsigned int channel) 281{ 282 return dma_ch[channel].regs->curr_desc_ptr; 283} 284static inline unsigned DMA_MMR_SIZE_TYPE get_dma_config(unsigned int channel) 285{ 286 return dma_ch[channel].regs->cfg; 287} 288static inline unsigned long get_dma_curr_addr(unsigned int channel) 289{ 290 return dma_ch[channel].regs->curr_addr_ptr; 291} 292 293static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize) 294{ 295 /* Make sure the internal data buffers in the core are drained 296 * so that the DMA descriptors are completely written when the 297 * DMA engine goes to fetch them below. 298 */ 299 SSYNC(); 300 301 dma_ch[channel].regs->next_desc_ptr = sg; 302 dma_ch[channel].regs->cfg = 303 (dma_ch[channel].regs->cfg & ~NDSIZE) | 304 ((ndsize << NDSIZE_OFFSET) & NDSIZE); 305} 306 307static inline int dma_channel_active(unsigned int channel) 308{ 309 return atomic_read(&dma_ch[channel].chan_status); 310} 311 312static inline void disable_dma(unsigned int channel) 313{ 314 dma_ch[channel].regs->cfg &= ~DMAEN; 315 SSYNC(); 316} 317static inline void enable_dma(unsigned int channel) 318{ 319 dma_ch[channel].regs->curr_x_count = 0; 320 dma_ch[channel].regs->curr_y_count = 0; 321 dma_ch[channel].regs->cfg |= DMAEN; 322} 323int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data); 324 325static inline void dma_disable_irq(unsigned int channel) 326{ 327 disable_irq(dma_ch[channel].irq); 328} 329static inline void dma_disable_irq_nosync(unsigned int channel) 330{ 331 disable_irq_nosync(dma_ch[channel].irq); 332} 333static inline void dma_enable_irq(unsigned int channel) 334{ 335 enable_irq(dma_ch[channel].irq); 336} 337static inline void clear_dma_irqstat(unsigned int channel) 338{ 339 dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR | DMA_PIRQ; 340} 341 342void *dma_memcpy(void *dest, const void *src, size_t count); 343void *dma_memcpy_nocache(void *dest, const void *src, size_t count); 344void *safe_dma_memcpy(void *dest, const void *src, size_t count); 345void blackfin_dma_early_init(void); 346void early_dma_memcpy(void *dest, const void *src, size_t count); 347void early_dma_memcpy_done(void); 348 349#endif 350