linux/drivers/dma/txx9dmac.h
<<
>>
Prefs
   1/*
   2 * Driver for the TXx9 SoC DMA Controller
   3 *
   4 * Copyright (C) 2009 Atsushi Nemoto
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10#ifndef TXX9DMAC_H
  11#define TXX9DMAC_H
  12
  13#include <linux/dmaengine.h>
  14#include <asm/txx9/dmac.h>
  15
  16/*
  17 * Design Notes:
  18 *
  19 * This DMAC have four channels and one FIFO buffer.  Each channel can
  20 * be configured for memory-memory or device-memory transfer, but only
  21 * one channel can do alignment-free memory-memory transfer at a time
  22 * while the channel should occupy the FIFO buffer for effective
  23 * transfers.
  24 *
  25 * Instead of dynamically assign the FIFO buffer to channels, I chose
  26 * make one dedicated channel for memory-memory transfer.  The
  27 * dedicated channel is public.  Other channels are private and used
  28 * for slave transfer.  Some devices in the SoC are wired to certain
  29 * DMA channel.
  30 */
  31
  32#ifdef CONFIG_MACH_TX49XX
  33static inline bool txx9_dma_have_SMPCHN(void)
  34{
  35        return true;
  36}
  37#define TXX9_DMA_USE_SIMPLE_CHAIN
  38#else
  39static inline bool txx9_dma_have_SMPCHN(void)
  40{
  41        return false;
  42}
  43#endif
  44
  45#ifdef __LITTLE_ENDIAN
  46#ifdef CONFIG_MACH_TX49XX
  47#define CCR_LE  TXX9_DMA_CCR_LE
  48#define MCR_LE  0
  49#else
  50#define CCR_LE  0
  51#define MCR_LE  TXX9_DMA_MCR_LE
  52#endif
  53#else
  54#define CCR_LE  0
  55#define MCR_LE  0
  56#endif
  57
  58/*
  59 * Redefine this macro to handle differences between 32- and 64-bit
  60 * addressing, big vs. little endian, etc.
  61 */
  62#ifdef __BIG_ENDIAN
  63#define TXX9_DMA_REG32(name)            u32 __pad_##name; u32 name
  64#else
  65#define TXX9_DMA_REG32(name)            u32 name; u32 __pad_##name
  66#endif
  67
  68/* Hardware register definitions. */
  69struct txx9dmac_cregs {
  70#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
  71        TXX9_DMA_REG32(CHAR);   /* Chain Address Register */
  72#else
  73        u64 CHAR;               /* Chain Address Register */
  74#endif
  75        u64 SAR;                /* Source Address Register */
  76        u64 DAR;                /* Destination Address Register */
  77        TXX9_DMA_REG32(CNTR);   /* Count Register */
  78        TXX9_DMA_REG32(SAIR);   /* Source Address Increment Register */
  79        TXX9_DMA_REG32(DAIR);   /* Destination Address Increment Register */
  80        TXX9_DMA_REG32(CCR);    /* Channel Control Register */
  81        TXX9_DMA_REG32(CSR);    /* Channel Status Register */
  82};
  83struct txx9dmac_cregs32 {
  84        u32 CHAR;
  85        u32 SAR;
  86        u32 DAR;
  87        u32 CNTR;
  88        u32 SAIR;
  89        u32 DAIR;
  90        u32 CCR;
  91        u32 CSR;
  92};
  93
  94struct txx9dmac_regs {
  95        /* per-channel registers */
  96        struct txx9dmac_cregs   CHAN[TXX9_DMA_MAX_NR_CHANNELS];
  97        u64     __pad[9];
  98        u64     MFDR;           /* Memory Fill Data Register */
  99        TXX9_DMA_REG32(MCR);    /* Master Control Register */
 100};
 101struct txx9dmac_regs32 {
 102        struct txx9dmac_cregs32 CHAN[TXX9_DMA_MAX_NR_CHANNELS];
 103        u32     __pad[9];
 104        u32     MFDR;
 105        u32     MCR;
 106};
 107
 108/* bits for MCR */
 109#define TXX9_DMA_MCR_EIS(ch)    (0x10000000<<(ch))
 110#define TXX9_DMA_MCR_DIS(ch)    (0x01000000<<(ch))
 111#define TXX9_DMA_MCR_RSFIF      0x00000080
 112#define TXX9_DMA_MCR_FIFUM(ch)  (0x00000008<<(ch))
 113#define TXX9_DMA_MCR_LE         0x00000004
 114#define TXX9_DMA_MCR_RPRT       0x00000002
 115#define TXX9_DMA_MCR_MSTEN      0x00000001
 116
 117/* bits for CCRn */
 118#define TXX9_DMA_CCR_IMMCHN     0x20000000
 119#define TXX9_DMA_CCR_USEXFSZ    0x10000000
 120#define TXX9_DMA_CCR_LE         0x08000000
 121#define TXX9_DMA_CCR_DBINH      0x04000000
 122#define TXX9_DMA_CCR_SBINH      0x02000000
 123#define TXX9_DMA_CCR_CHRST      0x01000000
 124#define TXX9_DMA_CCR_RVBYTE     0x00800000
 125#define TXX9_DMA_CCR_ACKPOL     0x00400000
 126#define TXX9_DMA_CCR_REQPL      0x00200000
 127#define TXX9_DMA_CCR_EGREQ      0x00100000
 128#define TXX9_DMA_CCR_CHDN       0x00080000
 129#define TXX9_DMA_CCR_DNCTL      0x00060000
 130#define TXX9_DMA_CCR_EXTRQ      0x00010000
 131#define TXX9_DMA_CCR_INTRQD     0x0000e000
 132#define TXX9_DMA_CCR_INTENE     0x00001000
 133#define TXX9_DMA_CCR_INTENC     0x00000800
 134#define TXX9_DMA_CCR_INTENT     0x00000400
 135#define TXX9_DMA_CCR_CHNEN      0x00000200
 136#define TXX9_DMA_CCR_XFACT      0x00000100
 137#define TXX9_DMA_CCR_SMPCHN     0x00000020
 138#define TXX9_DMA_CCR_XFSZ(order)        (((order) << 2) & 0x0000001c)
 139#define TXX9_DMA_CCR_XFSZ_1     TXX9_DMA_CCR_XFSZ(0)
 140#define TXX9_DMA_CCR_XFSZ_2     TXX9_DMA_CCR_XFSZ(1)
 141#define TXX9_DMA_CCR_XFSZ_4     TXX9_DMA_CCR_XFSZ(2)
 142#define TXX9_DMA_CCR_XFSZ_8     TXX9_DMA_CCR_XFSZ(3)
 143#define TXX9_DMA_CCR_XFSZ_X4    TXX9_DMA_CCR_XFSZ(4)
 144#define TXX9_DMA_CCR_XFSZ_X8    TXX9_DMA_CCR_XFSZ(5)
 145#define TXX9_DMA_CCR_XFSZ_X16   TXX9_DMA_CCR_XFSZ(6)
 146#define TXX9_DMA_CCR_XFSZ_X32   TXX9_DMA_CCR_XFSZ(7)
 147#define TXX9_DMA_CCR_MEMIO      0x00000002
 148#define TXX9_DMA_CCR_SNGAD      0x00000001
 149
 150/* bits for CSRn */
 151#define TXX9_DMA_CSR_CHNEN      0x00000400
 152#define TXX9_DMA_CSR_STLXFER    0x00000200
 153#define TXX9_DMA_CSR_XFACT      0x00000100
 154#define TXX9_DMA_CSR_ABCHC      0x00000080
 155#define TXX9_DMA_CSR_NCHNC      0x00000040
 156#define TXX9_DMA_CSR_NTRNFC     0x00000020
 157#define TXX9_DMA_CSR_EXTDN      0x00000010
 158#define TXX9_DMA_CSR_CFERR      0x00000008
 159#define TXX9_DMA_CSR_CHERR      0x00000004
 160#define TXX9_DMA_CSR_DESERR     0x00000002
 161#define TXX9_DMA_CSR_SORERR     0x00000001
 162
 163struct txx9dmac_chan {
 164        struct dma_chan         chan;
 165        struct dma_device       dma;
 166        struct txx9dmac_dev     *ddev;
 167        void __iomem            *ch_regs;
 168        struct tasklet_struct   tasklet;
 169        int                     irq;
 170        u32                     ccr;
 171
 172        spinlock_t              lock;
 173
 174        /* these other elements are all protected by lock */
 175        struct list_head        active_list;
 176        struct list_head        queue;
 177        struct list_head        free_list;
 178
 179        unsigned int            descs_allocated;
 180};
 181
 182struct txx9dmac_dev {
 183        void __iomem            *regs;
 184        struct tasklet_struct   tasklet;
 185        int                     irq;
 186        struct txx9dmac_chan    *chan[TXX9_DMA_MAX_NR_CHANNELS];
 187        bool                    have_64bit_regs;
 188        unsigned int            descsize;
 189};
 190
 191static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)
 192{
 193        return ddev->have_64bit_regs;
 194}
 195
 196static inline bool is_dmac64(const struct txx9dmac_chan *dc)
 197{
 198        return __is_dmac64(dc->ddev);
 199}
 200
 201#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
 202/* Hardware descriptor definition. (for simple-chain) */
 203struct txx9dmac_hwdesc {
 204#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
 205        TXX9_DMA_REG32(CHAR);
 206#else
 207        u64 CHAR;
 208#endif
 209        u64 SAR;
 210        u64 DAR;
 211        TXX9_DMA_REG32(CNTR);
 212};
 213struct txx9dmac_hwdesc32 {
 214        u32 CHAR;
 215        u32 SAR;
 216        u32 DAR;
 217        u32 CNTR;
 218};
 219#else
 220#define txx9dmac_hwdesc txx9dmac_cregs
 221#define txx9dmac_hwdesc32 txx9dmac_cregs32
 222#endif
 223
 224struct txx9dmac_desc {
 225        /* FIRST values the hardware uses */
 226        union {
 227                struct txx9dmac_hwdesc hwdesc;
 228                struct txx9dmac_hwdesc32 hwdesc32;
 229        };
 230
 231        /* THEN values for driver housekeeping */
 232        struct list_head                desc_node ____cacheline_aligned;
 233        struct list_head                tx_list;
 234        struct dma_async_tx_descriptor  txd;
 235        size_t                          len;
 236};
 237
 238#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
 239
 240static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
 241{
 242        return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;
 243}
 244
 245static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
 246{
 247        dc->ccr |= TXX9_DMA_CCR_INTENT;
 248}
 249
 250static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
 251                                            struct txx9dmac_desc *desc)
 252{
 253}
 254
 255static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
 256{
 257        dc->ccr |= TXX9_DMA_CCR_SMPCHN;
 258}
 259
 260static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
 261                                              struct txx9dmac_desc *desc,
 262                                              u32 sair, u32 dair, u32 ccr)
 263{
 264}
 265
 266#else /* TXX9_DMA_USE_SIMPLE_CHAIN */
 267
 268static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
 269{
 270        return true;
 271}
 272
 273static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
 274{
 275}
 276
 277static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
 278                                            struct txx9dmac_desc *desc)
 279{
 280        if (__is_dmac64(ddev))
 281                desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;
 282        else
 283                desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;
 284}
 285
 286static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
 287{
 288}
 289
 290static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
 291                                              struct txx9dmac_desc *desc,
 292                                              u32 sai, u32 dai, u32 ccr)
 293{
 294        if (__is_dmac64(ddev)) {
 295                desc->hwdesc.SAIR = sai;
 296                desc->hwdesc.DAIR = dai;
 297                desc->hwdesc.CCR = ccr;
 298        } else {
 299                desc->hwdesc32.SAIR = sai;
 300                desc->hwdesc32.DAIR = dai;
 301                desc->hwdesc32.CCR = ccr;
 302        }
 303}
 304
 305#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */
 306
 307#endif /* TXX9DMAC_H */
 308