11da177e4SLinus Torvalds /* 2f30c2269SUwe Zeisberger * arch/sh/drivers/dma/dma-pvr2.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * NEC PowerVR 2 (Dreamcast) DMA support 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 2003, 2004 Paul Mundt 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 91da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 101da177e4SLinus Torvalds * for more details. 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds #include <linux/init.h> 131da177e4SLinus Torvalds #include <linux/kernel.h> 141da177e4SLinus Torvalds #include <linux/module.h> 151da177e4SLinus Torvalds #include <linux/interrupt.h> 161da177e4SLinus Torvalds #include <asm/mach/sysasic.h> 171da177e4SLinus Torvalds #include <asm/mach/dma.h> 181da177e4SLinus Torvalds #include <asm/dma.h> 191da177e4SLinus Torvalds #include <asm/io.h> 201da177e4SLinus Torvalds 21e4c2cfeeSPaul Mundt static unsigned int xfer_complete; 22e4c2cfeeSPaul Mundt static int count; 231da177e4SLinus Torvalds 24*35f3c518SPaul Mundt static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id) 251da177e4SLinus Torvalds { 261da177e4SLinus Torvalds if (get_dma_residue(PVR2_CASCADE_CHAN)) { 271da177e4SLinus Torvalds printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " 281da177e4SLinus Torvalds "on channel %d, waiting..\n", PVR2_CASCADE_CHAN); 291da177e4SLinus Torvalds dma_wait_for_completion(PVR2_CASCADE_CHAN); 301da177e4SLinus Torvalds } 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds if (count++ < 10) 331da177e4SLinus Torvalds pr_debug("Got a pvr2 dma interrupt for channel %d\n", 341da177e4SLinus Torvalds irq - HW_EVENT_PVR2_DMA); 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds xfer_complete = 1; 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds return IRQ_HANDLED; 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds static int pvr2_request_dma(struct dma_channel *chan) 421da177e4SLinus Torvalds { 431da177e4SLinus Torvalds if (ctrl_inl(PVR2_DMA_MODE) != 0) 441da177e4SLinus Torvalds return -EBUSY; 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds ctrl_outl(0, PVR2_DMA_LMMODE0); 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds return 0; 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds static int pvr2_get_dma_residue(struct dma_channel *chan) 521da177e4SLinus Torvalds { 531da177e4SLinus Torvalds return xfer_complete == 0; 541da177e4SLinus Torvalds } 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds static int pvr2_xfer_dma(struct dma_channel *chan) 571da177e4SLinus Torvalds { 581da177e4SLinus Torvalds if (chan->sar || !chan->dar) 591da177e4SLinus Torvalds return -EINVAL; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds xfer_complete = 0; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds ctrl_outl(chan->dar, PVR2_DMA_ADDR); 641da177e4SLinus Torvalds ctrl_outl(chan->count, PVR2_DMA_COUNT); 651da177e4SLinus Torvalds ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds return 0; 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds static struct irqaction pvr2_dma_irq = { 711da177e4SLinus Torvalds .name = "pvr2 DMA handler", 721da177e4SLinus Torvalds .handler = pvr2_dma_interrupt, 736d20819fSThomas Gleixner .flags = IRQF_DISABLED, 741da177e4SLinus Torvalds }; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds static struct dma_ops pvr2_dma_ops = { 771da177e4SLinus Torvalds .request = pvr2_request_dma, 781da177e4SLinus Torvalds .get_residue = pvr2_get_dma_residue, 791da177e4SLinus Torvalds .xfer = pvr2_xfer_dma, 801da177e4SLinus Torvalds }; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds static struct dma_info pvr2_dma_info = { 830d831770SPaul Mundt .name = "pvr2_dmac", 841da177e4SLinus Torvalds .nr_channels = 1, 851da177e4SLinus Torvalds .ops = &pvr2_dma_ops, 861da177e4SLinus Torvalds .flags = DMAC_CHANNELS_TEI_CAPABLE, 871da177e4SLinus Torvalds }; 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds static int __init pvr2_dma_init(void) 901da177e4SLinus Torvalds { 911da177e4SLinus Torvalds setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); 921da177e4SLinus Torvalds request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds return register_dmac(&pvr2_dma_info); 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds static void __exit pvr2_dma_exit(void) 981da177e4SLinus Torvalds { 991da177e4SLinus Torvalds free_dma(PVR2_CASCADE_CHAN); 1001da177e4SLinus Torvalds free_irq(HW_EVENT_PVR2_DMA, 0); 1010d831770SPaul Mundt unregister_dmac(&pvr2_dma_info); 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds subsys_initcall(pvr2_dma_init); 1051da177e4SLinus Torvalds module_exit(pvr2_dma_exit); 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); 1081da177e4SLinus Torvalds MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); 1091da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 110