root/arch/sh/drivers/dma/dma-g2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. g2_dma_interrupt
  2. g2_enable_dma
  3. g2_disable_dma
  4. g2_xfer_dma
  5. g2_get_residue
  6. g2_dma_init
  7. g2_dma_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * arch/sh/drivers/dma/dma-g2.c
   4  *
   5  * G2 bus DMA support
   6  *
   7  * Copyright (C) 2003 - 2006  Paul Mundt
   8  */
   9 #include <linux/init.h>
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/interrupt.h>
  13 #include <asm/cacheflush.h>
  14 #include <mach/sysasic.h>
  15 #include <mach/dma.h>
  16 #include <asm/dma.h>
  17 
  18 struct g2_channel {
  19         unsigned long g2_addr;          /* G2 bus address */
  20         unsigned long root_addr;        /* Root bus (SH-4) address */
  21         unsigned long size;             /* Size (in bytes), 32-byte aligned */
  22         unsigned long direction;        /* Transfer direction */
  23         unsigned long ctrl;             /* Transfer control */
  24         unsigned long chan_enable;      /* Channel enable */
  25         unsigned long xfer_enable;      /* Transfer enable */
  26         unsigned long xfer_stat;        /* Transfer status */
  27 } __attribute__ ((aligned(32)));
  28 
  29 struct g2_status {
  30         unsigned long g2_addr;
  31         unsigned long root_addr;
  32         unsigned long size;
  33         unsigned long status;
  34 } __attribute__ ((aligned(16)));
  35 
  36 struct g2_dma_info {
  37         struct g2_channel channel[G2_NR_DMA_CHANNELS];
  38         unsigned long pad1[G2_NR_DMA_CHANNELS];
  39         unsigned long wait_state;
  40         unsigned long pad2[10];
  41         unsigned long magic;
  42         struct g2_status status[G2_NR_DMA_CHANNELS];
  43 } __attribute__ ((aligned(256)));
  44 
  45 static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
  46 
  47 #define g2_bytes_remaining(i) \
  48         ((g2_dma->channel[i].size - \
  49           g2_dma->status[i].size) & 0x0fffffff)
  50 
  51 static irqreturn_t g2_dma_interrupt(int irq, void *dev_id)
  52 {
  53         int i;
  54 
  55         for (i = 0; i < G2_NR_DMA_CHANNELS; i++) {
  56                 if (g2_dma->status[i].status & 0x20000000) {
  57                         unsigned int bytes = g2_bytes_remaining(i);
  58 
  59                         if (likely(bytes == 0)) {
  60                                 struct dma_info *info = dev_id;
  61                                 struct dma_channel *chan = info->channels + i;
  62 
  63                                 wake_up(&chan->wait_queue);
  64 
  65                                 return IRQ_HANDLED;
  66                         }
  67                 }
  68         }
  69 
  70         return IRQ_NONE;
  71 }
  72 
  73 static int g2_enable_dma(struct dma_channel *chan)
  74 {
  75         unsigned int chan_nr = chan->chan;
  76 
  77         g2_dma->channel[chan_nr].chan_enable = 1;
  78         g2_dma->channel[chan_nr].xfer_enable = 1;
  79 
  80         return 0;
  81 }
  82 
  83 static int g2_disable_dma(struct dma_channel *chan)
  84 {
  85         unsigned int chan_nr = chan->chan;
  86 
  87         g2_dma->channel[chan_nr].chan_enable = 0;
  88         g2_dma->channel[chan_nr].xfer_enable = 0;
  89 
  90         return 0;
  91 }
  92 
  93 static int g2_xfer_dma(struct dma_channel *chan)
  94 {
  95         unsigned int chan_nr = chan->chan;
  96 
  97         if (chan->sar & 31) {
  98                 printk("g2dma: unaligned source 0x%lx\n", chan->sar);
  99                 return -EINVAL;
 100         }
 101 
 102         if (chan->dar & 31) {
 103                 printk("g2dma: unaligned dest 0x%lx\n", chan->dar);
 104                 return -EINVAL;
 105         }
 106 
 107         /* Align the count */
 108         if (chan->count & 31)
 109                 chan->count = (chan->count + (32 - 1)) & ~(32 - 1);
 110 
 111         /* Fixup destination */
 112         chan->dar += 0xa0800000;
 113 
 114         /* Fixup direction */
 115         chan->mode = !chan->mode;
 116 
 117         flush_icache_range((unsigned long)chan->sar, chan->count);
 118 
 119         g2_disable_dma(chan);
 120 
 121         g2_dma->channel[chan_nr].g2_addr   = chan->dar & 0x1fffffe0;
 122         g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0;
 123         g2_dma->channel[chan_nr].size      = (chan->count & ~31) | 0x80000000;
 124         g2_dma->channel[chan_nr].direction = chan->mode;
 125 
 126         /*
 127          * bit 0 - ???
 128          * bit 1 - if set, generate a hardware event on transfer completion
 129          * bit 2 - ??? something to do with suspend?
 130          */
 131         g2_dma->channel[chan_nr].ctrl   = 5; /* ?? */
 132 
 133         g2_enable_dma(chan);
 134 
 135         /* debug cruft */
 136         pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, "
 137                  "0x%08lx, %ld, %ld, %ld, %ld\n",
 138                  g2_dma->channel[chan_nr].size,
 139                  g2_dma->channel[chan_nr].root_addr,
 140                  g2_dma->channel[chan_nr].g2_addr,
 141                  g2_dma->channel[chan_nr].direction,
 142                  g2_dma->channel[chan_nr].ctrl,
 143                  g2_dma->channel[chan_nr].chan_enable,
 144                  g2_dma->channel[chan_nr].xfer_enable);
 145 
 146         return 0;
 147 }
 148 
 149 static int g2_get_residue(struct dma_channel *chan)
 150 {
 151         return g2_bytes_remaining(chan->chan);
 152 }
 153 
 154 static struct dma_ops g2_dma_ops = {
 155         .xfer           = g2_xfer_dma,
 156         .get_residue    = g2_get_residue,
 157 };
 158 
 159 static struct dma_info g2_dma_info = {
 160         .name           = "g2_dmac",
 161         .nr_channels    = 4,
 162         .ops            = &g2_dma_ops,
 163         .flags          = DMAC_CHANNELS_TEI_CAPABLE,
 164 };
 165 
 166 static int __init g2_dma_init(void)
 167 {
 168         int ret;
 169 
 170         ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, 0,
 171                           "g2 DMA handler", &g2_dma_info);
 172         if (unlikely(ret))
 173                 return -EINVAL;
 174 
 175         /* Magic */
 176         g2_dma->wait_state      = 27;
 177         g2_dma->magic           = 0x4659404f;
 178 
 179         ret = register_dmac(&g2_dma_info);
 180         if (unlikely(ret != 0))
 181                 free_irq(HW_EVENT_G2_DMA, &g2_dma_info);
 182 
 183         return ret;
 184 }
 185 
 186 static void __exit g2_dma_exit(void)
 187 {
 188         free_irq(HW_EVENT_G2_DMA, &g2_dma_info);
 189         unregister_dmac(&g2_dma_info);
 190 }
 191 
 192 subsys_initcall(g2_dma_init);
 193 module_exit(g2_dma_exit);
 194 
 195 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 196 MODULE_DESCRIPTION("G2 bus DMA driver");
 197 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */