1*ff4a7481SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 3f30c2269SUwe Zeisberger * arch/sh/drivers/dma/dma-pvr2.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * NEC PowerVR 2 (Dreamcast) DMA support 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Copyright (C) 2003, 2004 Paul Mundt 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds #include <linux/init.h> 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/module.h> 121da177e4SLinus Torvalds #include <linux/interrupt.h> 13f15cbe6fSPaul Mundt #include <mach/sysasic.h> 14f15cbe6fSPaul Mundt #include <mach/dma.h> 151da177e4SLinus Torvalds #include <asm/dma.h> 161da177e4SLinus Torvalds #include <asm/io.h> 171da177e4SLinus Torvalds 18e4c2cfeeSPaul Mundt static unsigned int xfer_complete; 19e4c2cfeeSPaul Mundt static int count; 201da177e4SLinus Torvalds 2135f3c518SPaul Mundt static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id) 221da177e4SLinus Torvalds { 231da177e4SLinus Torvalds if (get_dma_residue(PVR2_CASCADE_CHAN)) { 241da177e4SLinus Torvalds printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " 251da177e4SLinus Torvalds "on channel %d, waiting..\n", PVR2_CASCADE_CHAN); 261da177e4SLinus Torvalds dma_wait_for_completion(PVR2_CASCADE_CHAN); 271da177e4SLinus Torvalds } 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds if (count++ < 10) 301da177e4SLinus Torvalds pr_debug("Got a pvr2 dma interrupt for channel %d\n", 311da177e4SLinus Torvalds irq - HW_EVENT_PVR2_DMA); 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds xfer_complete = 1; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds return IRQ_HANDLED; 361da177e4SLinus Torvalds } 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds static int pvr2_request_dma(struct dma_channel *chan) 391da177e4SLinus Torvalds { 409d56dd3bSPaul Mundt if (__raw_readl(PVR2_DMA_MODE) != 0) 411da177e4SLinus Torvalds return -EBUSY; 421da177e4SLinus Torvalds 439d56dd3bSPaul Mundt __raw_writel(0, PVR2_DMA_LMMODE0); 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds return 0; 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static int pvr2_get_dma_residue(struct dma_channel *chan) 491da177e4SLinus Torvalds { 501da177e4SLinus Torvalds return xfer_complete == 0; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds static int pvr2_xfer_dma(struct dma_channel *chan) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds if (chan->sar || !chan->dar) 561da177e4SLinus Torvalds return -EINVAL; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds xfer_complete = 0; 591da177e4SLinus Torvalds 609d56dd3bSPaul Mundt __raw_writel(chan->dar, PVR2_DMA_ADDR); 619d56dd3bSPaul Mundt __raw_writel(chan->count, PVR2_DMA_COUNT); 629d56dd3bSPaul Mundt __raw_writel(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE); 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds return 0; 651da177e4SLinus Torvalds } 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds static struct irqaction pvr2_dma_irq = { 681da177e4SLinus Torvalds .name = "pvr2 DMA handler", 691da177e4SLinus Torvalds .handler = pvr2_dma_interrupt, 701da177e4SLinus Torvalds }; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds static struct dma_ops pvr2_dma_ops = { 731da177e4SLinus Torvalds .request = pvr2_request_dma, 741da177e4SLinus Torvalds .get_residue = pvr2_get_dma_residue, 751da177e4SLinus Torvalds .xfer = pvr2_xfer_dma, 761da177e4SLinus Torvalds }; 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds static struct dma_info pvr2_dma_info = { 790d831770SPaul Mundt .name = "pvr2_dmac", 801da177e4SLinus Torvalds .nr_channels = 1, 811da177e4SLinus Torvalds .ops = &pvr2_dma_ops, 821da177e4SLinus Torvalds .flags = DMAC_CHANNELS_TEI_CAPABLE, 831da177e4SLinus Torvalds }; 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds static int __init pvr2_dma_init(void) 861da177e4SLinus Torvalds { 871da177e4SLinus Torvalds setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); 881da177e4SLinus Torvalds request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds return register_dmac(&pvr2_dma_info); 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds static void __exit pvr2_dma_exit(void) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds free_dma(PVR2_CASCADE_CHAN); 961da177e4SLinus Torvalds free_irq(HW_EVENT_PVR2_DMA, 0); 970d831770SPaul Mundt unregister_dmac(&pvr2_dma_info); 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds subsys_initcall(pvr2_dma_init); 1011da177e4SLinus Torvalds module_exit(pvr2_dma_exit); 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); 1041da177e4SLinus Torvalds MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); 105*ff4a7481SKuninori Morimoto MODULE_LICENSE("GPL v2"); 106