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        dma_cookie_t            completed;
 176        struct list_head        active_list;
 177        struct list_head        queue;
 178        struct list_head        free_list;
 179
 180        unsigned int            descs_allocated;
 181};
 182
 183struct txx9dmac_dev {
 184        void __iomem            *regs;
 185        struct tasklet_struct   tasklet;
 186        int                     irq;
 187        struct txx9dmac_chan    *chan[TXX9_DMA_MAX_NR_CHANNELS];
 188        bool                    have_64bit_regs;
 189        unsigned int            descsize;
 190};
 191
 192static inline bool __is_dmac64(const struct txx9dmac_dev *ddev)
 193{
 194        return ddev->have_64bit_regs;
 195}
 196
 197static inline bool is_dmac64(const struct txx9dmac_chan *dc)
 198{
 199        return __is_dmac64(dc->ddev);
 200}
 201
 202#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
 203/* Hardware descriptor definition. (for simple-chain) */
 204struct txx9dmac_hwdesc {
 205#if defined(CONFIG_32BIT) && !defined(CONFIG_64BIT_PHYS_ADDR)
 206        TXX9_DMA_REG32(CHAR);
 207#else
 208        u64 CHAR;
 209#endif
 210        u64 SAR;
 211        u64 DAR;
 212        TXX9_DMA_REG32(CNTR);
 213};
 214struct txx9dmac_hwdesc32 {
 215        u32 CHAR;
 216        u32 SAR;
 217        u32 DAR;
 218        u32 CNTR;
 219};
 220#else
 221#define txx9dmac_hwdesc txx9dmac_cregs
 222#define txx9dmac_hwdesc32 txx9dmac_cregs32
 223#endif
 224
 225struct txx9dmac_desc {
 226        /* FIRST values the hardware uses */
 227        union {
 228                struct txx9dmac_hwdesc hwdesc;
 229                struct txx9dmac_hwdesc32 hwdesc32;
 230        };
 231
 232        /* THEN values for driver housekeeping */
 233        struct list_head                desc_node ____cacheline_aligned;
 234        struct list_head                tx_list;
 235        struct dma_async_tx_descriptor  txd;
 236        size_t                          len;
 237};
 238
 239#ifdef TXX9_DMA_USE_SIMPLE_CHAIN
 240
 241static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
 242{
 243        return (dc->ccr & TXX9_DMA_CCR_INTENT) != 0;
 244}
 245
 246static inline void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
 247{
 248        dc->ccr |= TXX9_DMA_CCR_INTENT;
 249}
 250
 251static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
 252                                            struct txx9dmac_desc *desc)
 253{
 254}
 255
 256static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
 257{
 258        dc->ccr |= TXX9_DMA_CCR_SMPCHN;
 259}
 260
 261static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
 262                                              struct txx9dmac_desc *desc,
 263                                              u32 sair, u32 dair, u32 ccr)
 264{
 265}
 266
 267#else /* TXX9_DMA_USE_SIMPLE_CHAIN */
 268
 269static inline bool txx9dmac_chan_INTENT(struct txx9dmac_chan *dc)
 270{
 271        return true;
 272}
 273
 274static void txx9dmac_chan_set_INTENT(struct txx9dmac_chan *dc)
 275{
 276}
 277
 278static inline void txx9dmac_desc_set_INTENT(struct txx9dmac_dev *ddev,
 279                                            struct txx9dmac_desc *desc)
 280{
 281        if (__is_dmac64(ddev))
 282                desc->hwdesc.CCR |= TXX9_DMA_CCR_INTENT;
 283        else
 284                desc->hwdesc32.CCR |= TXX9_DMA_CCR_INTENT;
 285}
 286
 287static inline void txx9dmac_chan_set_SMPCHN(struct txx9dmac_chan *dc)
 288{
 289}
 290
 291static inline void txx9dmac_desc_set_nosimple(struct txx9dmac_dev *ddev,
 292                                              struct txx9dmac_desc *desc,
 293                                              u32 sai, u32 dai, u32 ccr)
 294{
 295        if (__is_dmac64(ddev)) {
 296                desc->hwdesc.SAIR = sai;
 297                desc->hwdesc.DAIR = dai;
 298                desc->hwdesc.CCR = ccr;
 299        } else {
 300                desc->hwdesc32.SAIR = sai;
 301                desc->hwdesc32.DAIR = dai;
 302                desc->hwdesc32.CCR = ccr;
 303        }
 304}
 305
 306#endif /* TXX9_DMA_USE_SIMPLE_CHAIN */
 307
 308#endif /* TXX9DMAC_H */
 309