linux/arch/blackfin/include/asm/dma.h
<<
>>
Prefs
   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