linux/arch/sh/drivers/dma/dma-pvr2.c
<<
>>
Prefs
   1/*
   2 * arch/sh/drivers/dma/dma-pvr2.c
   3 *
   4 * NEC PowerVR 2 (Dreamcast) DMA support
   5 *
   6 * Copyright (C) 2003, 2004  Paul Mundt
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/init.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/interrupt.h>
  16#include <mach/sysasic.h>
  17#include <mach/dma.h>
  18#include <asm/dma.h>
  19#include <asm/io.h>
  20
  21static unsigned int xfer_complete;
  22static int count;
  23
  24static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id)
  25{
  26        if (get_dma_residue(PVR2_CASCADE_CHAN)) {
  27                printk(KERN_WARNING "DMA: SH DMAC did not complete transfer "
  28                       "on channel %d, waiting..\n", PVR2_CASCADE_CHAN);
  29                dma_wait_for_completion(PVR2_CASCADE_CHAN);
  30        }
  31
  32        if (count++ < 10)
  33                pr_debug("Got a pvr2 dma interrupt for channel %d\n",
  34                         irq - HW_EVENT_PVR2_DMA);
  35
  36        xfer_complete = 1;
  37
  38        return IRQ_HANDLED;
  39}
  40
  41static int pvr2_request_dma(struct dma_channel *chan)
  42{
  43        if (ctrl_inl(PVR2_DMA_MODE) != 0)
  44                return -EBUSY;
  45
  46        ctrl_outl(0, PVR2_DMA_LMMODE0);
  47
  48        return 0;
  49}
  50
  51static int pvr2_get_dma_residue(struct dma_channel *chan)
  52{
  53        return xfer_complete == 0;
  54}
  55
  56static int pvr2_xfer_dma(struct dma_channel *chan)
  57{
  58        if (chan->sar || !chan->dar)
  59                return -EINVAL;
  60
  61        xfer_complete = 0;
  62
  63        ctrl_outl(chan->dar, PVR2_DMA_ADDR);
  64        ctrl_outl(chan->count, PVR2_DMA_COUNT);
  65        ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
  66
  67        return 0;
  68}
  69
  70static struct irqaction pvr2_dma_irq = {
  71        .name           = "pvr2 DMA handler",
  72        .handler        = pvr2_dma_interrupt,
  73        .flags          = IRQF_DISABLED,
  74};
  75
  76static struct dma_ops pvr2_dma_ops = {
  77        .request        = pvr2_request_dma,
  78        .get_residue    = pvr2_get_dma_residue,
  79        .xfer           = pvr2_xfer_dma,
  80};
  81
  82static struct dma_info pvr2_dma_info = {
  83        .name           = "pvr2_dmac",
  84        .nr_channels    = 1,
  85        .ops            = &pvr2_dma_ops,
  86        .flags          = DMAC_CHANNELS_TEI_CAPABLE,
  87};
  88
  89static int __init pvr2_dma_init(void)
  90{
  91        setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq);
  92        request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade");
  93
  94        return register_dmac(&pvr2_dma_info);
  95}
  96
  97static void __exit pvr2_dma_exit(void)
  98{
  99        free_dma(PVR2_CASCADE_CHAN);
 100        free_irq(HW_EVENT_PVR2_DMA, 0);
 101        unregister_dmac(&pvr2_dma_info);
 102}
 103
 104subsys_initcall(pvr2_dma_init);
 105module_exit(pvr2_dma_exit);
 106
 107MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 108MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
 109MODULE_LICENSE("GPL");
 110