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