2018-12-28 00:31:49 -08:00
// SPDX-License-Identifier: GPL-2.0
2005-04-16 15:20:36 -07:00
/*
2006-10-03 23:01:26 +02:00
* arch / sh / drivers / dma / dma - pvr2 . c
2005-04-16 15:20:36 -07:00
*
* NEC PowerVR 2 ( Dreamcast ) DMA support
*
* Copyright ( C ) 2003 , 2004 Paul Mundt
*/
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/interrupt.h>
2008-07-29 08:09:44 +09:00
# include <mach/sysasic.h>
# include <mach/dma.h>
2005-04-16 15:20:36 -07:00
# include <asm/dma.h>
# include <asm/io.h>
2006-09-27 12:31:01 +09:00
static unsigned int xfer_complete ;
static int count ;
2005-04-16 15:20:36 -07:00
2006-10-06 15:31:16 +09:00
static irqreturn_t pvr2_dma_interrupt ( int irq , void * dev_id )
2005-04-16 15:20:36 -07:00
{
if ( get_dma_residue ( PVR2_CASCADE_CHAN ) ) {
printk ( KERN_WARNING " DMA: SH DMAC did not complete transfer "
" on channel %d, waiting.. \n " , PVR2_CASCADE_CHAN ) ;
dma_wait_for_completion ( PVR2_CASCADE_CHAN ) ;
}
if ( count + + < 10 )
pr_debug ( " Got a pvr2 dma interrupt for channel %d \n " ,
irq - HW_EVENT_PVR2_DMA ) ;
xfer_complete = 1 ;
return IRQ_HANDLED ;
}
static int pvr2_request_dma ( struct dma_channel * chan )
{
2010-01-26 12:58:40 +09:00
if ( __raw_readl ( PVR2_DMA_MODE ) ! = 0 )
2005-04-16 15:20:36 -07:00
return - EBUSY ;
2010-01-26 12:58:40 +09:00
__raw_writel ( 0 , PVR2_DMA_LMMODE0 ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static int pvr2_get_dma_residue ( struct dma_channel * chan )
{
return xfer_complete = = 0 ;
}
static int pvr2_xfer_dma ( struct dma_channel * chan )
{
if ( chan - > sar | | ! chan - > dar )
return - EINVAL ;
xfer_complete = 0 ;
2010-01-26 12:58:40 +09:00
__raw_writel ( chan - > dar , PVR2_DMA_ADDR ) ;
__raw_writel ( chan - > count , PVR2_DMA_COUNT ) ;
__raw_writel ( chan - > mode & DMA_MODE_MASK , PVR2_DMA_MODE ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static struct irqaction pvr2_dma_irq = {
. name = " pvr2 DMA handler " ,
. handler = pvr2_dma_interrupt ,
} ;
static struct dma_ops pvr2_dma_ops = {
. request = pvr2_request_dma ,
. get_residue = pvr2_get_dma_residue ,
. xfer = pvr2_xfer_dma ,
} ;
static struct dma_info pvr2_dma_info = {
2006-01-16 22:14:09 -08:00
. name = " pvr2_dmac " ,
2005-04-16 15:20:36 -07:00
. nr_channels = 1 ,
. ops = & pvr2_dma_ops ,
. flags = DMAC_CHANNELS_TEI_CAPABLE ,
} ;
static int __init pvr2_dma_init ( void )
{
setup_irq ( HW_EVENT_PVR2_DMA , & pvr2_dma_irq ) ;
request_dma ( PVR2_CASCADE_CHAN , " pvr2 cascade " ) ;
return register_dmac ( & pvr2_dma_info ) ;
}
static void __exit pvr2_dma_exit ( void )
{
free_dma ( PVR2_CASCADE_CHAN ) ;
free_irq ( HW_EVENT_PVR2_DMA , 0 ) ;
2006-01-16 22:14:09 -08:00
unregister_dmac ( & pvr2_dma_info ) ;
2005-04-16 15:20:36 -07:00
}
subsys_initcall ( pvr2_dma_init ) ;
module_exit ( pvr2_dma_exit ) ;
MODULE_AUTHOR ( " Paul Mundt <lethal@linux-sh.org> " ) ;
MODULE_DESCRIPTION ( " NEC PowerVR 2 DMA driver " ) ;
2018-12-28 00:31:49 -08:00
MODULE_LICENSE ( " GPL v2 " ) ;