sh: override DMA interrupt handler to dma-sh driver
RFC PATCH 1/1 sh: override DMA interrupt handler to dma-sh driver
Dma-sh has fixed interrupt handler and cannot register an interrupt for exclusive use of the device with dma.
I added a handler to sh_dmac_request_dma and reviced it to be able to appoint a handler.
Signed-off-by Nobuhiro Iwamatsu <[email protected]>
--- arch/sh/drivers/dma/Kconfig | 2 +- arch/sh/drivers/dma/dma-api.c | 63 +++++++++++++++++++++++++----------- arch/sh/drivers/dma/dma-pvr2.c | 2 +- arch/sh/drivers/dma/dma-sh.c | 38 ++++++++++++---------- arch/sh/drivers/dma/dma-sh.h | 46 +++++++++++++++++++-------- arch/sh/drivers/dma/dmabrg.c | 2 +- arch/sh/include/asm/dma.h | 36 +++++++++++++++++--- arch/sh/include/cpu-sh4/cpu/dma.h | 9 +++++- 8 files changed, 137 insertions(+), 61 deletions(-)
arch/sh/drivers/dma/Kconfig +1 -1
@@ -12,7 +12,7 @@ config SH_DMA config NR_ONCHIP_DMA_CHANNELS int depends on SH_DMA - default "6" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721 + default "6" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721 || CPU_SUBTYPE_SH7763 default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R default "12" if CPU_SUBTYPE_SH7780 default "4"
arch/sh/drivers/dma/dma-api.c +44 -19
128 lines not on this page · raw message
arch/sh/drivers/dma/dma-pvr2.c +1 -1
@@ -89,7 +89,7 @@ static struct dma_info pvr2_dma_info = {static int __init pvr2_dma_init (void ) {setup_irq (HW_EVENT_PVR2_DMA , &pvr2_dma_irq); -request_dma (PVR2_CASCADE_CHAN ,"pvr2 cascade" ); +request_dma (PVR2_CASCADE_CHAN ,"pvr2 cascade" ,NULL ,NULL );return register_dmac (&pvr2_dma_info); }
arch/sh/drivers/dma/dma-sh.c +20 -18
@@ -28,6 +28,7 @@ static int dmte_irq_map[] = {defined (CONFIG_CPU_SUBTYPE_SH7721 ) || \defined (CONFIG_CPU_SUBTYPE_SH7751R ) || \defined (CONFIG_CPU_SUBTYPE_SH7760 ) || \ +defined (CONFIG_CPU_SUBTYPE_SH7763 ) || \defined (CONFIG_CPU_SUBTYPE_SH7709 ) || \defined (CONFIG_CPU_SUBTYPE_SH7780 ) DMTE4_IRQ,
@@ -88,18 +89,25 @@ static irqreturn_t dma_tei(int irq, void *dev_id)return IRQ_HANDLED ; } -static int sh_dmac_request_dma (struct dma_channel *chan) +static int sh_dmac_request_dma (struct dma_channel *chan,irq_handler_t handler,void *data) {if (unlikely (!(chan->flags &DMA_TEI_CAPABLE )))return 0 ; +if (handler) +return request_irq (get_dmte_irq (chan->chan), handler, +IRQF_DISABLED , chan->dev_id, data); +return request_irq (get_dmte_irq (chan->chan), dma_tei, -IRQF_DISABLED , chan->dev_id, chan); +IRQF_DISABLED , chan->dev_id, chan); } -static void sh_dmac_free_dma (struct dma_channel *chan) +static void sh_dmac_free_dma (struct dma_channel *chan,void *data) { -free_irq (get_dmte_irq (chan->chan), chan); +if (data) +free_irq (get_dmte_irq (chan->chan), data); +else +free_irq (get_dmte_irq (chan->chan), chan); } static int
@@ -116,17 +124,14 @@ sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) }ctrl_outl (chcr,CHCR [chan->chan]); - chan->flags |=DMA_CONFIGURED ;return 0 ; }static void sh_dmac_enable_dma (struct dma_channel *chan) { -int irq; -u32 chcr; +u32 chcr=ctrl_inl (CHCR [chan->chan]); - chcr =ctrl_inl (CHCR [chan->chan]); chcr |=CHCR_DE ;if (chan->flags &DMA_TEI_CAPABLE )
@@ -134,21 +139,15 @@ static void sh_dmac_enable_dma(struct dma_channel *chan)ctrl_outl (chcr,CHCR [chan->chan]); -if (chan->flags &DMA_TEI_CAPABLE ) { - irq =get_dmte_irq (chan->chan); -enable_irq (irq); - } +if (chan->flags &DMA_TEI_CAPABLE ) +enable_irq (get_dmte_irq (chan->chan)); }static void sh_dmac_disable_dma (struct dma_channel *chan) { -int irq;u32 chcr; - -if (chan->flags &DMA_TEI_CAPABLE ) { - irq =get_dmte_irq (chan->chan); -disable_irq (irq); - } +if (chan->flags &DMA_TEI_CAPABLE ) +disable_irq (get_dmte_irq (chan->chan)); chcr =ctrl_inl (CHCR [chan->chan]); chcr &= ~(CHCR_DE |CHCR_TE |CHCR_IE );
@@ -205,6 +204,7 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan)#if defined(CONFIG_CPU_SUBTYPE_SH7720 ) || \ defined(CONFIG_CPU_SUBTYPE_SH7721 ) || \ + defined(CONFIG_CPU_SUBTYPE_SH7763 ) || \ defined(CONFIG_CPU_SUBTYPE_SH7780 )#define dmaor_read_reg () ctrl_inw(DMAOR)#define dmaor_write_reg (data) ctrl_outw(data, DMAOR)
@@ -249,6 +249,8 @@ static struct dma_ops sh_dmac_ops = { .get_residue = sh_dmac_get_dma_residue, .xfer = sh_dmac_xfer_dma, .configure = sh_dmac_configure_channel, + .start = sh_dmac_enable_dma, + .stop = sh_dmac_disable_dma, };static struct dma_info sh_dmac_info = {
arch/sh/drivers/dma/dma-sh.h +32 -14
69 lines not on this page · raw message
arch/sh/drivers/dma/dmabrg.c +1 -1
@@ -160,7 +160,7 @@ static int __init dmabrg_init(void)#ifdef CONFIG_SH_DMA /* request DMAC channel 0 before anyone else can get it */ - ret =request_dma (0 ,"DMAC 0 (DMABRG)" ); + ret =request_dma (0 ,"DMAC 0 (DMABRG)" ,NULL ,NULL );if (ret <0 )printk (KERN_INFO "DMABRG: DMAC ch0 not reserved!\n" );#endif
arch/sh/include/asm/dma.h +30 -6
@@ -1,5 +1,5 @@/* -* include/asm-sh/dma.h +* arch/sh/include/asm/dma.h * * Copyright (C) 2003, 2004 Paul Mundt *
@@ -13,6 +13,7 @@#include <linux/spinlock.h> #include <linux/wait.h> +#include <linux/interrupt.h> #include <linux/sched.h> #include <linux/sysdev.h> #include <cpu/dma.h>
@@ -67,13 +68,16 @@ extern spinlock_t dma_spin_lock;struct dma_channel ;struct dma_ops { -int (*request)(struct dma_channel *chan); -void (*free)(struct dma_channel *chan); +int (*request)(struct dma_channel *chan,irq_handler_t handler, +void *data); +void (*free)(struct dma_channel *chan,void *data);int (*get_residue)(struct dma_channel *chan);int (*xfer)(struct dma_channel *chan);int (*configure)(struct dma_channel *chan,unsigned long flags);int (*extend)(struct dma_channel *chan,unsigned long op,void *param); +void (*start)(struct dma_channel *chan); +void (*stop)(struct dma_channel *chan); };struct dma_channel {
@@ -124,6 +128,21 @@ struct dma_chan_caps {/* arch/sh/drivers/dma/dma-api.c */ extern int dma_xfer (unsigned int chan,unsigned long from,unsigned long to,size_t size,unsigned int mode); +/* SAR */ +#define dma_set_sar (val, chan) ctrl_outl(val, SAR[chan]) +#define dma_get_sar (chan) ctrl_inl(SAR[chan]) +/* DAR */ +#define dma_set_dar (val, chan) ctrl_outl(val, DAR[chan]) +#define dma_get_dar (chan) ctrl_inl(DAR[chan]) +/* DMATCR */ +#define dma_set_dmatcr (val, chan) ctrl_outl(val, DMATCR[chan]) +#define dma_get_dmatcr (chan) ctrl_inl(DMATCR[chan]) +/* CHCR */ +#define dma_set_chcr (val, chan) ctrl_outl(val, CHCR[chan]) +#define dma_get_chcr (chan) ctrl_inl(CHCR[chan]) +/* DMASR */ +#define dma_set_dmasr (val, chan) ctrl_outw(val, DMASR[chan]) +#define dma_get_dmasr (chan) ctrl_inw(DMASR[chan])#define dma_write (chan, from, to, size) \ dma_xfer(chan, from, to, size, DMA_MODE_WRITE)
@@ -135,10 +154,15 @@ extern int dma_xfer(unsigned int chan, unsigned long from,#define dma_read_page (chan, from, to) \ dma_read(chan, from, to, PAGE_SIZE) +extern int dma_start (unsigned int chan); +extern int dma_stop (unsigned int chan); +extern int request_dma_bycap (const char **dmac,const char **caps, -const char *dev_id); -extern int request_dma (unsigned int chan,const char *dev_id); -extern void free_dma (unsigned int chan); +const char *dev_id,irq_handler_t handler,void *data); +extern int dmac_search_free_channel (void ); +extern int request_dma (unsigned int chan,const char *dev_id, +irq_handler_t handler,void *data); +extern void free_dma (unsigned int chan,void *data);extern int get_dma_residue (unsigned int chan);extern struct dma_info *get_dma_info (unsigned int chan);extern struct dma_channel *get_dma_channel (unsigned int chan);
arch/sh/include/cpu-sh4/cpu/dma.h +8 -1
@@ -15,7 +15,14 @@#define DMAE_IRQ 38#ifdef CONFIG_CPU_SH4A -#define SH_DMAC_BASE 0xfc808020 + +#if defined(CONFIG_CPU_SUBTYPE_SH7763 ) ||\ + defined(CONFIG_CPU_SUBTYPE_SH7764 ) +# define SH_DMAC_BASE 0xff608020 +#else +/* SH7780/SH7785 */ +# define SH_DMAC_BASE 0xfc808020 +#endif #define CHCR_TS_MASK 0x18#define CHCR_TS_SHIFT 3
Signature · 1 line
1.5.6.3