OMAP dma engine rework
Subsystems (5)
cover OMAP dma engine rework
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
arch/arm/mach-omap1/dma.c | 191 ++++++-------- arch/arm/mach-omap2/dma.c | 183 ++++++------- arch/arm/plat-omap/dma.c | 17 +- drivers/dma/omap-dma.c | 659 +++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 25 +- 5 files changed, 784 insertions(+), 291 deletions(-)
Signature · 3 lines
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad. Estimate before purchase was "up to 13.2Mbit".
PATCH 1/26 dmaengine: omap-dma: use devm_kzalloc() to allocate omap_dmadev.
Use devm_kzalloc() to allocate omap_dmadev() so that we don't need complex error cleanup paths.
--- drivers/dma/omap-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/omap-dma.c +1 -2
@@ -594,7 +594,6 @@ static void omap_dma_free(struct omap_dmadev *od)tasklet_kill (&c->vc.task);kfree (c); } -kfree (od); }static int omap_dma_probe (struct platform_device *pdev)
@@ -602,7 +601,7 @@ static int omap_dma_probe(struct platform_device *pdev)struct omap_dmadev *od;int rc, i; - od =kzalloc (sizeof (*od),GFP_KERNEL ); + od =devm_kzalloc (&pdev->dev,sizeof (*od),GFP_KERNEL );if (!od)return -ENOMEM ;
Signature · 1 line
1.8.3.1
PATCH 2/26 dmaengine: omap-dma: provide a hook to get the underlying DMA platform ops
In reply to Russell King - ARM LinuxProvide and use a hook to obtain the underlying DMA platform operations so that omap-dma.c can access the hardware more directly without involving the legacy DMA driver.
--- arch/arm/plat-omap/dma.c | 6 ++++++ drivers/dma/omap-dma.c | 7 +++++++ include/linux/omap-dma.h | 2 ++ 3 files changed, 15 insertions(+)
arch/arm/plat-omap/dma.c +6 -0
@@ -2000,6 +2000,12 @@ void omap_dma_global_context_restore(void)omap_clear_dma (ch); } +struct omap_system_dma_plat_info *omap_get_plat_info (void ) +{ +return p; +} +EXPORT_SYMBOL_GPL (omap_get_plat_info); +static int omap_system_dma_probe (struct platform_device *pdev) {int ch, ret =0 ;
drivers/dma/omap-dma.c +7 -0
@@ -26,11 +26,13 @@ struct omap_dmadev {spinlock_t lock;struct tasklet_struct task;struct list_head pending; +struct omap_system_dma_plat_info *plat; };struct omap_chan {struct virt_dma_chan vc;struct list_head node; +struct omap_system_dma_plat_info *plat;struct dma_slave_config cfg;unsigned dma_sig;
@@ -573,6 +575,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig)if (!c)return -ENOMEM ; + c->plat = od->plat; c->dma_sig = dma_sig; c->vc.desc_free = omap_dma_desc_free;vchan_init (&c->vc, &od->ddev);
@@ -605,6 +608,10 @@ static int omap_dma_probe(struct platform_device *pdev)if (!od)return -ENOMEM ; + od->plat =omap_get_plat_info (); +if (!od->plat) +return -EPROBE_DEFER ; +dma_cap_set (DMA_SLAVE , od->ddev.cap_mask);dma_cap_set (DMA_CYCLIC , od->ddev.cap_mask); od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources;
include/linux/omap-dma.h +2 -0
@@ -292,6 +292,8 @@ struct omap_system_dma_plat_info {#define dma_omap15xx () ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE)))#define dma_omap16xx () ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +extern struct omap_system_dma_plat_info *omap_get_plat_info (void ); +extern void omap_set_dma_priority (int lch,int dst_port,int priority); extern int omap_request_dma(int dev_id, const char *dev_name, void (*callback)(int lch, u16 ch_status, void *data),
Signature · 1 line
1.8.3.1
PATCH 3/26 dmaengine: omap-dma: program hardware directly
In reply to Russell King - ARM LinuxProgram the transfer parameters directly into the hardware, rather than using the functions in arch/arm/plat-omap/dma.c.
--- drivers/dma/omap-dma.c | 142 +++++++++++++++++++++++++++++++++++++++++------ include/linux/omap-dma.h | 6 +- 2 files changed, 130 insertions(+), 18 deletions(-)
drivers/dma/omap-dma.c +126 -16
@@ -99,16 +99,94 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) {struct omap_sg *sg = d->sg + idx; +uint32_t val; + +if (d->dir ==DMA_DEV_TO_MEM ) { +if (dma_omap1 ()) { + val = c->plat->dma_read (CSDP , c->dma_ch); + val &= ~(0x1f <<9 ); + val |=OMAP_DMA_PORT_EMIFF <<9 ; + c->plat->dma_write (val,CSDP , c->dma_ch); + } -if (d->dir ==DMA_DEV_TO_MEM ) -omap_set_dma_dest_params (c->dma_ch,OMAP_DMA_PORT_EMIFF , -OMAP_DMA_AMODE_POST_INC , sg->addr,0 ,0 ); -else -omap_set_dma_src_params (c->dma_ch,OMAP_DMA_PORT_EMIFF , -OMAP_DMA_AMODE_POST_INC , sg->addr,0 ,0 ); + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(0x03 <<14 ); + val |=OMAP_DMA_AMODE_POST_INC <<14 ; + c->plat->dma_write (val,CCR , c->dma_ch); + + c->plat->dma_write (sg->addr,CDSA , c->dma_ch); + c->plat->dma_write (0 ,CDEI , c->dma_ch); + c->plat->dma_write (0 ,CDFI , c->dma_ch); + }else { +if (dma_omap1 ()) { + val = c->plat->dma_read (CSDP , c->dma_ch); + val &= ~(0x1f <<2 ); + val |=OMAP_DMA_PORT_EMIFF <<2 ; + c->plat->dma_write (val,CSDP , c->dma_ch); + } + + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(0x03 <<12 ); + val |=OMAP_DMA_AMODE_POST_INC <<12 ; + c->plat->dma_write (val,CCR , c->dma_ch); + + c->plat->dma_write (sg->addr,CSSA , c->dma_ch); + c->plat->dma_write (0 ,CSEI , c->dma_ch); + c->plat->dma_write (0 ,CSFI , c->dma_ch); + } + + val = c->plat->dma_read (CSDP , c->dma_ch); + val &= ~0x03 ; + val |= d->es; + c->plat->dma_write (val,CSDP , c->dma_ch); + +if (dma_omap1 ()) { + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(1 <<5 ); +if (d->sync_mode ==OMAP_DMA_SYNC_FRAME ) + val |=1 <<5 ; + c->plat->dma_write (val,CCR , c->dma_ch); + + val = c->plat->dma_read (CCR2 , c->dma_ch); + val &= ~(1 <<2 ); +if (d->sync_mode ==OMAP_DMA_SYNC_BLOCK ) + val |=1 <<2 ; + c->plat->dma_write (val,CCR2 , c->dma_ch); + }else if (c->dma_sig) { + val = c->plat->dma_read (CCR , c->dma_ch); + +/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ + val &= ~((1 <<23 ) | (3 <<19 ) |0x1f ); + val |= (c->dma_sig & ~0x1f ) <<14 ; + val |= c->dma_sig &0x1f ; + +if (d->sync_mode &OMAP_DMA_SYNC_FRAME ) + val |=1 <<5 ; +else + val &= ~(1 <<5 ); + +if (d->sync_mode &OMAP_DMA_SYNC_BLOCK ) + val |=1 <<18 ; +else + val &= ~(1 <<18 ); + +switch (d->sync_type) { +case OMAP_DMA_DST_SYNC_PREFETCH : + val &= ~(1 <<24 );/* dest synch */ + val |=1 <<23 ;/* Prefetch */ +break ; +case 0 : + val &= ~(1 <<24 );/* dest synch */ +break ; +default : + val |=1 <<24 ;/* source synch */ +break ; + } + c->plat->dma_write (val,CCR , c->dma_ch); + } -omap_set_dma_transfer_params (c->dma_ch, d->es, sg->en, sg->fn, - d->sync_mode, c->dma_sig, d->sync_type); + c->plat->dma_write (sg->en,CEN , c->dma_ch); + c->plat->dma_write (sg->fn,CFN , c->dma_ch);omap_start_dma (c->dma_ch); }
@@ -117,6 +195,7 @@ static void omap_dma_start_desc(struct omap_chan *c) {struct virt_dma_desc *vd =vchan_next_desc (&c->vc);struct omap_desc *d; +uint32_t val;if (!vd) { c->desc =NULL ;
@@ -128,12 +207,39 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d =to_omap_dma_desc (&vd->tx); c->sgidx =0 ; -if (d->dir ==DMA_DEV_TO_MEM ) -omap_set_dma_src_params (c->dma_ch, d->periph_port, -OMAP_DMA_AMODE_CONSTANT , d->dev_addr,0 , d->fi); -else -omap_set_dma_dest_params (c->dma_ch, d->periph_port, -OMAP_DMA_AMODE_CONSTANT , d->dev_addr,0 , d->fi); +if (d->dir ==DMA_DEV_TO_MEM ) { +if (dma_omap1 ()) { + val = c->plat->dma_read (CSDP , c->dma_ch); + val &= ~(0x1f <<2 ); + val |= d->periph_port <<2 ; + c->plat->dma_write (val,CSDP , c->dma_ch); + } + + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(0x03 <<12 ); + val |=OMAP_DMA_AMODE_CONSTANT <<12 ; + c->plat->dma_write (val,CCR , c->dma_ch); + + c->plat->dma_write (d->dev_addr,CSSA , c->dma_ch); + c->plat->dma_write (0 ,CSEI , c->dma_ch); + c->plat->dma_write (d->fi,CSFI , c->dma_ch); + }else { +if (dma_omap1 ()) { + val = c->plat->dma_read (CSDP , c->dma_ch); + val &= ~(0x1f <<9 ); + val |= d->periph_port <<9 ; + c->plat->dma_write (val,CSDP , c->dma_ch); + } + + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(0x03 <<14 ); + val |=OMAP_DMA_AMODE_CONSTANT <<14 ; + c->plat->dma_write (val,CCR , c->dma_ch); + + c->plat->dma_write (d->dev_addr,CDSA , c->dma_ch); + c->plat->dma_write (0 ,CDEI , c->dma_ch); + c->plat->dma_write (d->fi,CDFI , c->dma_ch); + }omap_dma_start_sg (c, d,0 ); }
@@ -452,8 +558,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( }if (dma_omap2plus ()) { -omap_set_dma_src_burst_mode (c->dma_ch,OMAP_DMA_DATA_BURST_16 ); -omap_set_dma_dest_burst_mode (c->dma_ch,OMAP_DMA_DATA_BURST_16 ); +uint32_t val; + + val = c->plat->dma_read (CSDP , c->dma_ch); + val |=0x03 <<7 ;/* src burst mode 16 */ + val |=0x03 <<14 ;/* dst burst mode 16 */ + c->plat->dma_write (val,CSDP , c->dma_ch); }return vchan_tx_prep (&c->vc, &d->vd, flags);
include/linux/omap-dma.h +4 -2
@@ -289,8 +289,10 @@ struct omap_system_dma_plat_info {#define dma_omap2plus () 0#endif #define dma_omap1 () (!dma_omap2plus()) -#define dma_omap15xx () ((dma_omap1() && (d->dev_caps & ENABLE_1510_MODE))) -#define dma_omap16xx () ((dma_omap1() && (d->dev_caps & ENABLE_16XX_MODE))) +#define __dma_omap15xx (d) (dma_omap1() && (d)->dev_caps & ENABLE_1510_MODE) +#define __dma_omap16xx (d) (dma_omap1() && (d)->dev_caps & ENABLE_16XX_MODE) +#define dma_omap15xx () __dma_omap15xx(d) +#define dma_omap16xx () __dma_omap16xx(d)extern struct omap_system_dma_plat_info *omap_get_plat_info (void );
Signature · 1 line
1.8.3.1
PATCH 4/26 dmaengine: omap-dma: consolidate writes to DMA registers
In reply to Russell King - ARM LinuxThere's no need to keep writing registers which don't change value in omap_dma_start_sg(). Move this into omap_dma_start_desc() and merge the register updates together.
--- drivers/dma/omap-dma.c | 123 +++++++++++++++++++------------------------------ 1 file changed, 48 insertions(+), 75 deletions(-)
drivers/dma/omap-dma.c +48 -75
@@ -99,40 +99,75 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) {struct omap_sg *sg = d->sg + idx; + +if (d->dir ==DMA_DEV_TO_MEM ) { + c->plat->dma_write (sg->addr,CDSA , c->dma_ch); + c->plat->dma_write (0 ,CDEI , c->dma_ch); + c->plat->dma_write (0 ,CDFI , c->dma_ch); + }else { + c->plat->dma_write (sg->addr,CSSA , c->dma_ch); + c->plat->dma_write (0 ,CSEI , c->dma_ch); + c->plat->dma_write (0 ,CSFI , c->dma_ch); + } + + c->plat->dma_write (sg->en,CEN , c->dma_ch); + c->plat->dma_write (sg->fn,CFN , c->dma_ch); + +omap_start_dma (c->dma_ch); +} + +static void omap_dma_start_desc (struct omap_chan *c) +{ +struct virt_dma_desc *vd =vchan_next_desc (&c->vc); +struct omap_desc *d;uint32_t val; +if (!vd) { + c->desc =NULL ; +return ; + } + +list_del (&vd->node); + + c->desc = d =to_omap_dma_desc (&vd->tx); + c->sgidx =0 ; +if (d->dir ==DMA_DEV_TO_MEM ) {if (dma_omap1 ()) { val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<9 ); + val &= ~(0x1f <<9 |0x1f <<2 ); val |=OMAP_DMA_PORT_EMIFF <<9 ; + val |= d->periph_port <<2 ; c->plat->dma_write (val,CSDP , c->dma_ch); } val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<14 ); + val &= ~(0x03 <<14 |0x03 <<12 ); val |=OMAP_DMA_AMODE_POST_INC <<14 ; + val |=OMAP_DMA_AMODE_CONSTANT <<12 ; c->plat->dma_write (val,CCR , c->dma_ch); - c->plat->dma_write (sg->addr,CDSA , c->dma_ch); - c->plat->dma_write (0 ,CDEI , c->dma_ch); - c->plat->dma_write (0 ,CDFI , c->dma_ch); + c->plat->dma_write (d->dev_addr,CSSA , c->dma_ch); + c->plat->dma_write (0 ,CSEI , c->dma_ch); + c->plat->dma_write (d->fi,CSFI , c->dma_ch); }else {if (dma_omap1 ()) { val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<2 ); + val &= ~(0x1f <<9 |0x1f <<2 ); + val |= d->periph_port <<9 ; val |=OMAP_DMA_PORT_EMIFF <<2 ; c->plat->dma_write (val,CSDP , c->dma_ch); } val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<12 ); + val &= ~(0x03 <<12 |0x03 <<14 ); + val |=OMAP_DMA_AMODE_CONSTANT <<14 ; val |=OMAP_DMA_AMODE_POST_INC <<12 ; c->plat->dma_write (val,CCR , c->dma_ch); - c->plat->dma_write (sg->addr,CSSA , c->dma_ch); - c->plat->dma_write (0 ,CSEI , c->dma_ch); - c->plat->dma_write (0 ,CSFI , c->dma_ch); + c->plat->dma_write (d->dev_addr,CDSA , c->dma_ch); + c->plat->dma_write (0 ,CDEI , c->dma_ch); + c->plat->dma_write (d->fi,CDFI , c->dma_ch); } val = c->plat->dma_read (CSDP , c->dma_ch);
@@ -156,91 +191,29 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, val = c->plat->dma_read (CCR , c->dma_ch);/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~((1 <<23 ) | (3 <<19 ) |0x1f ); + val &= ~(1 <<24 |1 <<23 |3 <<19 |1 <<18 |1 <<5 |0x1f ); val |= (c->dma_sig & ~0x1f ) <<14 ; val |= c->dma_sig &0x1f ;if (d->sync_mode &OMAP_DMA_SYNC_FRAME ) val |=1 <<5 ; -else - val &= ~(1 <<5 );if (d->sync_mode &OMAP_DMA_SYNC_BLOCK ) val |=1 <<18 ; -else - val &= ~(1 <<18 );switch (d->sync_type) { -case OMAP_DMA_DST_SYNC_PREFETCH : - val &= ~(1 <<24 );/* dest synch */ +case OMAP_DMA_DST_SYNC_PREFETCH :/* dest synch */ val |=1 <<23 ;/* Prefetch */ break ;case 0 : - val &= ~(1 <<24 );/* dest synch */ break ;default : - val |=1 <<24 ;/* source synch */ + val |=1 <<24 ;/* source synch */ break ; } c->plat->dma_write (val,CCR , c->dma_ch); } - c->plat->dma_write (sg->en,CEN , c->dma_ch); - c->plat->dma_write (sg->fn,CFN , c->dma_ch); - -omap_start_dma (c->dma_ch); -} - -static void omap_dma_start_desc (struct omap_chan *c) -{ -struct virt_dma_desc *vd =vchan_next_desc (&c->vc); -struct omap_desc *d; -uint32_t val; - -if (!vd) { - c->desc =NULL ; -return ; - } - -list_del (&vd->node); - - c->desc = d =to_omap_dma_desc (&vd->tx); - c->sgidx =0 ; - -if (d->dir ==DMA_DEV_TO_MEM ) { -if (dma_omap1 ()) { - val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<2 ); - val |= d->periph_port <<2 ; - c->plat->dma_write (val,CSDP , c->dma_ch); - } - - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<12 ); - val |=OMAP_DMA_AMODE_CONSTANT <<12 ; - c->plat->dma_write (val,CCR , c->dma_ch); - - c->plat->dma_write (d->dev_addr,CSSA , c->dma_ch); - c->plat->dma_write (0 ,CSEI , c->dma_ch); - c->plat->dma_write (d->fi,CSFI , c->dma_ch); - }else { -if (dma_omap1 ()) { - val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<9 ); - val |= d->periph_port <<9 ; - c->plat->dma_write (val,CSDP , c->dma_ch); - } - - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<14 ); - val |=OMAP_DMA_AMODE_CONSTANT <<14 ; - c->plat->dma_write (val,CCR , c->dma_ch); - - c->plat->dma_write (d->dev_addr,CDSA , c->dma_ch); - c->plat->dma_write (0 ,CDEI , c->dma_ch); - c->plat->dma_write (d->fi,CDFI , c->dma_ch); - } -omap_dma_start_sg (c, d,0 ); }
Signature · 1 line
1.8.3.1
PATCH 5/26 dmaengine: omap-dma: control start/stop directly
In reply to Russell King - ARM LinuxProgram the non-cyclic mode DMA start/stop directly, rather than via arch/arm/plat-omap/dma.c.
--- drivers/dma/omap-dma.c | 151 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 10 deletions(-)
drivers/dma/omap-dma.c +141 -10
@@ -5,6 +5,7 @@* it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/delay.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/err.h>
@@ -60,6 +61,7 @@ struct omap_desc {uint8_t sync_mode;/* OMAP_DMA_SYNC_xxx */ uint8_t sync_type;/* OMAP_DMA_xxx_SYNC* */ uint8_t periph_port;/* Peripheral port */ +uint16_t cicr;/* CICR value */ unsigned sglen;struct omap_sg sg[0 ];
@@ -95,6 +97,111 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)kfree (container_of(vd ,struct omap_desc ,vd )); } +static void omap_dma_start (struct omap_chan *c,struct omap_desc *d) +{ +struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); +uint32_t val; + +if (__dma_omap15xx (od->plat->dma_attr)) + c->plat->dma_write (0 ,CPC , c->dma_ch); +else + c->plat->dma_write (0 ,CDAC , c->dma_ch); + +if (!__dma_omap15xx (od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read (CLNK_CTRL , c->dma_ch); + +if (dma_omap1 ()) + val &= ~(1 <<14 ); + + val |= c->dma_ch |1 <<15 ; + + c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); + }else if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS ) + c->plat->dma_write (c->dma_ch,CLNK_CTRL , c->dma_ch); + +/* Clear CSR */ +if (dma_omap1 ()) + c->plat->dma_read (CSR , c->dma_ch); +else + c->plat->dma_write (~0 ,CSR , c->dma_ch); + +/* Enable interrupts */ + c->plat->dma_write (d->cicr,CICR , c->dma_ch); + + val = c->plat->dma_read (CCR , c->dma_ch); +if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) + val |=OMAP_DMA_CCR_BUFFERING_DISABLE ; + val |=OMAP_DMA_CCR_EN ; +mb (); + c->plat->dma_write (val,CCR , c->dma_ch); +} + +static void omap_dma_stop (struct omap_chan *c) +{ +struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); +uint32_t val; + +/* disable irq */ + c->plat->dma_write (0 ,CICR , c->dma_ch); + +/* Clear CSR */ +if (dma_omap1 ()) + c->plat->dma_read (CSR , c->dma_ch); +else + c->plat->dma_write (~0 ,CSR , c->dma_ch); + + val = c->plat->dma_read (CCR , c->dma_ch); +if (od->plat->errata & DMA_ERRATA_i541 && + val &OMAP_DMA_CCR_SEL_SRC_DST_SYNC ) { +uint32_t sysconfig; +unsigned i; + + sysconfig = c->plat->dma_read (OCP_SYSCONFIG , c->dma_ch); + val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK ; + val |=DMA_SYSCONFIG_MIDLEMODE (DMA_IDLEMODE_NO_IDLE ); + c->plat->dma_write (val,OCP_SYSCONFIG , c->dma_ch); + + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~OMAP_DMA_CCR_EN ; + c->plat->dma_write (val,CCR , c->dma_ch); + +/* Wait for sDMA FIFO to drain */ +for (i =0 ; ; i++) { + val = c->plat->dma_read (CCR , c->dma_ch); +if (!(val & (OMAP_DMA_CCR_RD_ACTIVE |OMAP_DMA_CCR_WR_ACTIVE ))) +break ; + +if (i >100 ) +break ; + +udelay (5 ); + } + +if (val & (OMAP_DMA_CCR_RD_ACTIVE |OMAP_DMA_CCR_WR_ACTIVE )) +dev_err (c->vc.chan.device->dev, +"DMA drain did not complete on lch %d\n" , + c->dma_ch); + + c->plat->dma_write (sysconfig,OCP_SYSCONFIG , c->dma_ch); + }else { + val &= ~OMAP_DMA_CCR_EN ; + c->plat->dma_write (val,CCR , c->dma_ch); + } + +mb (); + +if (!__dma_omap15xx (od->plat->dma_attr) && c->cyclic) { + val = c->plat->dma_read (CLNK_CTRL , c->dma_ch); + +if (dma_omap1 ()) + val |=1 <<14 ;/* set the STOP_LNK bit */ +else + val &= ~(1 <<15 );/* Clear the ENABLE_LNK bit */ + + c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); + } +} +static void omap_dma_start_sg (struct omap_chan *c,struct omap_desc *d,unsigned idx) {
@@ -113,7 +220,7 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, c->plat->dma_write (sg->en,CEN , c->dma_ch); c->plat->dma_write (sg->fn,CFN , c->dma_ch); -omap_start_dma (c->dma_ch); +omap_dma_start (c, d); }static void omap_dma_start_desc (struct omap_chan *c)
@@ -434,6 +541,12 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->sync_mode =OMAP_DMA_SYNC_FRAME ; d->sync_type = sync_type; d->periph_port =OMAP_DMA_PORT_TIPB ; + d->cicr =OMAP_DMA_DROP_IRQ |OMAP_DMA_BLOCK_IRQ ; + +if (dma_omap1 ()) + d->cicr |=OMAP1_DMA_TOUT_IRQ ; +else + d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ;/* * Build our scatterlist entries: each contains the address,
@@ -463,6 +576,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( size_t period_len, enum dma_transfer_direction dir, unsigned long flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device);struct omap_chan *c =to_omap_dma_chan (chan);enum dma_slave_buswidth dev_width;struct omap_desc *d;
@@ -519,15 +633,25 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0 ].en = period_len / es_bytes[es]; d->sg[0 ].fn = buf_len / period_len; d->sglen =1 ; + d->cicr =OMAP_DMA_DROP_IRQ ; +if (flags &DMA_PREP_INTERRUPT ) + d->cicr |=OMAP_DMA_FRAME_IRQ ; + +if (dma_omap1 ()) + d->cicr |=OMAP1_DMA_TOUT_IRQ ; +else + d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ;if (!c->cyclic) { c->cyclic = true; -omap_dma_link_lch (c->dma_ch, c->dma_ch); -if (flags &DMA_PREP_INTERRUPT ) -omap_enable_dma_irq (c->dma_ch,OMAP_DMA_FRAME_IRQ ); +if (__dma_omap15xx (od->plat->dma_attr)) { +uint32_t val; -omap_disable_dma_irq (c->dma_ch,OMAP_DMA_BLOCK_IRQ ); + val = c->plat->dma_read (CCR , c->dma_ch); + val |=3 <<8 ; + c->plat->dma_write (val,CCR , c->dma_ch); + } }if (dma_omap2plus ()) {
@@ -568,20 +692,27 @@ static int omap_dma_terminate_all(struct omap_chan *c)/* * Stop DMA activity: we assume the callback will not be called -* after omap_stop_dma() returns (even if it does, it will see +* after omap_dma_stop() returns (even if it does, it will see * c->desc is NULL and exit.) */ if (c->desc) { c->desc =NULL ;/* Avoid stopping the dma twice */ if (!c->paused) -omap_stop_dma (c->dma_ch); +omap_dma_stop (c); }if (c->cyclic) { c->cyclic = false; c->paused = false; -omap_dma_unlink_lch (c->dma_ch, c->dma_ch); + +if (__dma_omap15xx (od->plat->dma_attr)) { +uint32_t val; + + val = c->plat->dma_read (CCR , c->dma_ch); + val &= ~(3 <<8 ); + c->plat->dma_write (val,CCR , c->dma_ch); + } }vchan_get_all_descriptors (&c->vc, &head);
@@ -598,7 +729,7 @@ static int omap_dma_pause(struct omap_chan *c)return -EINVAL ;if (!c->paused) { -omap_stop_dma (c->dma_ch); +omap_dma_stop (c); c->paused = true; }
@@ -612,7 +743,7 @@ static int omap_dma_resume(struct omap_chan *c)return -EINVAL ;if (c->paused) { -omap_start_dma (c->dma_ch); +omap_dma_start (c, c->desc); c->paused = false; }
Signature · 1 line
1.8.3.1
PATCH 6/26 dmaengine: omap-dma: move reading of dma position to omap-dma.c
In reply to Russell King - ARM LinuxRead the current DMA position from the hardware directly rather than via arch/arm/plat-omap/dma.c.
--- drivers/dma/omap-dma.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-)
drivers/dma/omap-dma.c +64 -2
@@ -427,6 +427,68 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)return size; } +static dma_addr_t omap_dma_get_src_pos (struct omap_chan *c) +{ +struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); +dma_addr_t addr; + +if (__dma_omap15xx (od->plat->dma_attr)) + addr = c->plat->dma_read (CPC , c->dma_ch); +else + addr = c->plat->dma_read (CSAC , c->dma_ch); + +if (od->plat->errata &DMA_ERRATA_3_3 && addr ==0 ) + addr = c->plat->dma_read (CSAC , c->dma_ch); + +if (!__dma_omap15xx (od->plat->dma_attr)) { +/* +* CDAC == 0 indicates that the DMA transfer on the channel has +* not been started (no data has been transferred so far). +* Return the programmed source start address in this case. +*/ +if (c->plat->dma_read (CDAC , c->dma_ch)) + addr = c->plat->dma_read (CSAC , c->dma_ch); +else + addr = c->plat->dma_read (CSSA , c->dma_ch); + } + +if (dma_omap1 ()) + addr |= c->plat->dma_read (CSSA , c->dma_ch) &0xffff0000 ; + +return addr; +} + +static dma_addr_t omap_dma_get_dst_pos (struct omap_chan *c) +{ +struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); +dma_addr_t addr; + +if (__dma_omap15xx (od->plat->dma_attr)) + addr = c->plat->dma_read (CPC , c->dma_ch); +else + addr = c->plat->dma_read (CDAC , c->dma_ch); + +/* +* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is +* read before the DMA controller finished disabling the channel. +*/ +if (!__dma_omap15xx (od->plat->dma_attr) && addr ==0 ) { + addr = c->plat->dma_read (CDAC , c->dma_ch); +/* +* CDAC == 0 indicates that the DMA transfer on the channel has +* not been started (no data has been transferred so far). +* Return the programmed destination start address in this case. +*/ +if (addr ==0 ) + addr = c->plat->dma_read (CDSA , c->dma_ch); + } + +if (dma_omap1 ()) + addr |= c->plat->dma_read (CDSA , c->dma_ch) &0xffff0000 ; + +return addr; +} +static enum dma_status omap_dma_tx_status (struct dma_chan *chan,dma_cookie_t cookie,struct dma_tx_state *txstate) {
@@ -448,9 +510,9 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,dma_addr_t pos;if (d->dir ==DMA_MEM_TO_DEV ) - pos =omap_get_dma_src_pos (c->dma_ch); + pos =omap_dma_get_src_pos (c);else if (d->dir ==DMA_DEV_TO_MEM ) - pos =omap_get_dma_dst_pos (c->dma_ch); + pos =omap_dma_get_dst_pos (c);else pos =0 ;
Signature · 1 line
1.8.3.1
PATCH 7/26 dmaengine: omap-dma: consolidate setup of CSDP
In reply to Russell King - ARM LinuxConsolidate the setup of the channel source destination parameters register. This way, we calculate the required CSDP value when we setup a transfer descriptor, and only write it to the device registers once when we start the descriptor.
--- drivers/dma/omap-dma.c | 64 ++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 36 deletions(-)
drivers/dma/omap-dma.c +28 -36
@@ -60,8 +60,8 @@ struct omap_desc {uint8_t es;/* OMAP_DMA_DATA_TYPE_xxx */ uint8_t sync_mode;/* OMAP_DMA_SYNC_xxx */ uint8_t sync_type;/* OMAP_DMA_xxx_SYNC* */ -uint8_t periph_port;/* Peripheral port */ uint16_t cicr;/* CICR value */ +uint32_t csdp;/* CSDP value */ unsigned sglen;struct omap_sg sg[0 ];
@@ -240,14 +240,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->sgidx =0 ;if (d->dir ==DMA_DEV_TO_MEM ) { -if (dma_omap1 ()) { - val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<9 |0x1f <<2 ); - val |=OMAP_DMA_PORT_EMIFF <<9 ; - val |= d->periph_port <<2 ; - c->plat->dma_write (val,CSDP , c->dma_ch); - } - val = c->plat->dma_read (CCR , c->dma_ch); val &= ~(0x03 <<14 |0x03 <<12 ); val |=OMAP_DMA_AMODE_POST_INC <<14 ;
@@ -258,14 +250,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write (0 ,CSEI , c->dma_ch); c->plat->dma_write (d->fi,CSFI , c->dma_ch); }else { -if (dma_omap1 ()) { - val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~(0x1f <<9 |0x1f <<2 ); - val |= d->periph_port <<9 ; - val |=OMAP_DMA_PORT_EMIFF <<2 ; - c->plat->dma_write (val,CSDP , c->dma_ch); - } - val = c->plat->dma_read (CCR , c->dma_ch); val &= ~(0x03 <<12 |0x03 <<14 ); val |=OMAP_DMA_AMODE_CONSTANT <<14 ;
@@ -277,10 +261,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write (d->fi,CDFI , c->dma_ch); } - val = c->plat->dma_read (CSDP , c->dma_ch); - val &= ~0x03 ; - val |= d->es; - c->plat->dma_write (val,CSDP , c->dma_ch); + c->plat->dma_write (d->csdp,CSDP , c->dma_ch);if (dma_omap1 ()) { val = c->plat->dma_read (CCR , c->dma_ch);
@@ -602,13 +583,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->es = es; d->sync_mode =OMAP_DMA_SYNC_FRAME ; d->sync_type = sync_type; - d->periph_port =OMAP_DMA_PORT_TIPB ; d->cicr =OMAP_DMA_DROP_IRQ |OMAP_DMA_BLOCK_IRQ ; + d->csdp = es; -if (dma_omap1 ()) +if (dma_omap1 ()) { d->cicr |=OMAP1_DMA_TOUT_IRQ ; -else + +if (dir ==DMA_DEV_TO_MEM ) + d->csdp |=OMAP_DMA_PORT_EMIFF <<9 | +OMAP_DMA_PORT_TIPB <<2 ; +else + d->csdp |=OMAP_DMA_PORT_TIPB <<9 | +OMAP_DMA_PORT_EMIFF <<2 ; + }else { d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ; + }/* * Build our scatterlist entries: each contains the address,
@@ -690,7 +679,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(else d->sync_mode =OMAP_DMA_SYNC_ELEMENT ; d->sync_type = sync_type; - d->periph_port =OMAP_DMA_PORT_MPUI ; d->sg[0 ].addr = buf_addr; d->sg[0 ].en = period_len / es_bytes[es]; d->sg[0 ].fn = buf_len / period_len;
@@ -699,11 +687,24 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(if (flags &DMA_PREP_INTERRUPT ) d->cicr |=OMAP_DMA_FRAME_IRQ ; -if (dma_omap1 ()) + d->csdp = es; + +if (dma_omap1 ()) { d->cicr |=OMAP1_DMA_TOUT_IRQ ; -else + +if (dir ==DMA_DEV_TO_MEM ) + d->csdp |=OMAP_DMA_PORT_EMIFF <<9 | +OMAP_DMA_PORT_MPUI <<2 ; +else + d->csdp |=OMAP_DMA_PORT_MPUI <<9 | +OMAP_DMA_PORT_EMIFF <<2 ; + }else { d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ; +/* src and dst burst mode 16 */ + d->csdp |=3 <<14 |3 <<7 ; + } +if (!c->cyclic) { c->cyclic = true;
@@ -716,15 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( } } -if (dma_omap2plus ()) { -uint32_t val; - - val = c->plat->dma_read (CSDP , c->dma_ch); - val |=0x03 <<7 ;/* src burst mode 16 */ - val |=0x03 <<14 ;/* dst burst mode 16 */ - c->plat->dma_write (val,CSDP , c->dma_ch); - } -return vchan_tx_prep (&c->vc, &d->vd, flags); }
Signature · 1 line
1.8.3.1
PATCH 8/26 dmaengine: omap-dma: consolidate setup of CCR
In reply to Russell King - ARM LinuxConsolidate the setup of the channel control register. Prepare the basic value in the preparation of the DMA descriptor, and write it into the register upon descriptor execution.
--- drivers/dma/omap-dma.c | 147 ++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 86 deletions(-)
drivers/dma/omap-dma.c +61 -86
@@ -58,8 +58,7 @@ struct omap_desc {int16_t fi;/* for OMAP_DMA_SYNC_PACKET */ uint8_t es;/* OMAP_DMA_DATA_TYPE_xxx */ -uint8_t sync_mode;/* OMAP_DMA_SYNC_xxx */ -uint8_t sync_type;/* OMAP_DMA_xxx_SYNC* */ +uint32_t ccr;/* CCR value */ uint16_t cicr;/* CICR value */ uint32_t csdp;/* CSDP value */
@@ -227,7 +226,6 @@ static void omap_dma_start_desc(struct omap_chan *c) {struct virt_dma_desc *vd =vchan_next_desc (&c->vc);struct omap_desc *d; -uint32_t val;if (!vd) { c->desc =NULL ;
@@ -239,23 +237,15 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d =to_omap_dma_desc (&vd->tx); c->sgidx =0 ; -if (d->dir ==DMA_DEV_TO_MEM ) { - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<14 |0x03 <<12 ); - val |=OMAP_DMA_AMODE_POST_INC <<14 ; - val |=OMAP_DMA_AMODE_CONSTANT <<12 ; - c->plat->dma_write (val,CCR , c->dma_ch); + c->plat->dma_write (d->ccr,CCR , c->dma_ch); +if (dma_omap1 ()) + c->plat->dma_write (d->ccr >>16 ,CCR2 , c->dma_ch); +if (d->dir ==DMA_DEV_TO_MEM ) { c->plat->dma_write (d->dev_addr,CSSA , c->dma_ch); c->plat->dma_write (0 ,CSEI , c->dma_ch); c->plat->dma_write (d->fi,CSFI , c->dma_ch); }else { - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(0x03 <<12 |0x03 <<14 ); - val |=OMAP_DMA_AMODE_CONSTANT <<14 ; - val |=OMAP_DMA_AMODE_POST_INC <<12 ; - c->plat->dma_write (val,CCR , c->dma_ch); - c->plat->dma_write (d->dev_addr,CDSA , c->dma_ch); c->plat->dma_write (0 ,CDEI , c->dma_ch); c->plat->dma_write (d->fi,CDFI , c->dma_ch);
@@ -263,45 +253,6 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write (d->csdp,CSDP , c->dma_ch); -if (dma_omap1 ()) { - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(1 <<5 ); -if (d->sync_mode ==OMAP_DMA_SYNC_FRAME ) - val |=1 <<5 ; - c->plat->dma_write (val,CCR , c->dma_ch); - - val = c->plat->dma_read (CCR2 , c->dma_ch); - val &= ~(1 <<2 ); -if (d->sync_mode ==OMAP_DMA_SYNC_BLOCK ) - val |=1 <<2 ; - c->plat->dma_write (val,CCR2 , c->dma_ch); - }else if (c->dma_sig) { - val = c->plat->dma_read (CCR , c->dma_ch); - -/* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~(1 <<24 |1 <<23 |3 <<19 |1 <<18 |1 <<5 |0x1f ); - val |= (c->dma_sig & ~0x1f ) <<14 ; - val |= c->dma_sig &0x1f ; - -if (d->sync_mode &OMAP_DMA_SYNC_FRAME ) - val |=1 <<5 ; - -if (d->sync_mode &OMAP_DMA_SYNC_BLOCK ) - val |=1 <<18 ; - -switch (d->sync_type) { -case OMAP_DMA_DST_SYNC_PREFETCH :/* dest synch */ - val |=1 <<23 ;/* Prefetch */ -break ; -case 0 : -break ; -default : - val |=1 <<24 ;/* source synch */ -break ; - } - c->plat->dma_write (val,CCR , c->dma_ch); - } -omap_dma_start_sg (c, d,0 ); }
@@ -540,19 +491,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(struct scatterlist *sgent;struct omap_desc *d;dma_addr_t dev_addr; -unsigned i, j =0 , es, en, frame_bytes, sync_type; +unsigned i, j =0 , es, en, frame_bytes;u32 burst;if (dir ==DMA_DEV_TO_MEM ) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type =OMAP_DMA_SRC_SYNC ; }else if (dir ==DMA_MEM_TO_DEV ) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type =OMAP_DMA_DST_SYNC ; }else {dev_err (chan->device->dev,"%s: bad direction?\n" , __func__);return NULL ;
@@ -581,12 +530,28 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dir = dir; d->dev_addr = dev_addr; d->es = es; - d->sync_mode =OMAP_DMA_SYNC_FRAME ; - d->sync_type = sync_type; + + d->ccr =0 ; +if (dir ==DMA_DEV_TO_MEM ) + d->ccr |=OMAP_DMA_AMODE_POST_INC <<14 | +OMAP_DMA_AMODE_CONSTANT <<12 ; +else + d->ccr |=OMAP_DMA_AMODE_CONSTANT <<14 | +OMAP_DMA_AMODE_POST_INC <<12 ; + d->cicr =OMAP_DMA_DROP_IRQ |OMAP_DMA_BLOCK_IRQ ; d->csdp = es;if (dma_omap1 ()) { + d->ccr |=1 <<5 ;/* frame sync */ +if (__dma_omap16xx (od->plat->dma_attr)) { + d->ccr |=1 <<10 ;/* disable 3.0/3.1 compatibility mode */ +/* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch +1 ; + }else { + d->ccr |= c->dma_sig &0x1f ; + } + d->cicr |=OMAP1_DMA_TOUT_IRQ ;if (dir ==DMA_DEV_TO_MEM )
@@ -596,6 +561,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp |=OMAP_DMA_PORT_TIPB <<9 |OMAP_DMA_PORT_EMIFF <<2 ; }else { + d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; + d->ccr |= c->dma_sig &0x1f ; + d->ccr |=1 <<5 ;/* frame sync */ + +if (dir ==DMA_DEV_TO_MEM ) + d->ccr |=1 <<24 ;/* source synch */ + d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ; }
@@ -632,19 +604,17 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(enum dma_slave_buswidth dev_width;struct omap_desc *d;dma_addr_t dev_addr; -unsigned es, sync_type; +unsigned es;u32 burst;if (dir ==DMA_DEV_TO_MEM ) { dev_addr = c->cfg.src_addr; dev_width = c->cfg.src_addr_width; burst = c->cfg.src_maxburst; - sync_type =OMAP_DMA_SRC_SYNC ; }else if (dir ==DMA_MEM_TO_DEV ) { dev_addr = c->cfg.dst_addr; dev_width = c->cfg.dst_addr_width; burst = c->cfg.dst_maxburst; - sync_type =OMAP_DMA_DST_SYNC ; }else {dev_err (chan->device->dev,"%s: bad direction?\n" , __func__);return NULL ;
@@ -674,15 +644,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->dev_addr = dev_addr; d->fi = burst; d->es = es; -if (burst) - d->sync_mode =OMAP_DMA_SYNC_PACKET ; -else - d->sync_mode =OMAP_DMA_SYNC_ELEMENT ; - d->sync_type = sync_type; d->sg[0 ].addr = buf_addr; d->sg[0 ].en = period_len / es_bytes[es]; d->sg[0 ].fn = buf_len / period_len; d->sglen =1 ; + + d->ccr =0 ; +if (__dma_omap15xx (od->plat->dma_attr)) + d->ccr =3 <<8 ; +if (dir ==DMA_DEV_TO_MEM ) + d->ccr |=OMAP_DMA_AMODE_POST_INC <<14 | +OMAP_DMA_AMODE_CONSTANT <<12 ; +else + d->ccr |=OMAP_DMA_AMODE_CONSTANT <<14 | +OMAP_DMA_AMODE_POST_INC <<12 ; + d->cicr =OMAP_DMA_DROP_IRQ ;if (flags &DMA_PREP_INTERRUPT ) d->cicr |=OMAP_DMA_FRAME_IRQ ;
@@ -690,6 +666,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es;if (dma_omap1 ()) { +if (__dma_omap16xx (od->plat->dma_attr)) { + d->ccr |=1 <<10 ;/* disable 3.0/3.1 compatibility mode */ +/* Duplicate what plat-omap/dma.c does */ + d->ccr |= c->dma_ch +1 ; + }else { + d->ccr |= c->dma_sig &0x1f ; + } + d->cicr |=OMAP1_DMA_TOUT_IRQ ;if (dir ==DMA_DEV_TO_MEM )
@@ -699,23 +683,22 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |=OMAP_DMA_PORT_MPUI <<9 |OMAP_DMA_PORT_EMIFF <<2 ; }else { + d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; + d->ccr |= c->dma_sig &0x1f ; + +if (burst) + d->ccr |=1 <<18 |1 <<5 ;/* packet */ + +if (dir ==DMA_DEV_TO_MEM ) + d->ccr |=1 <<24 ;/* source synch */ + d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ;/* src and dst burst mode 16 */ d->csdp |=3 <<14 |3 <<7 ; } -if (!c->cyclic) { - c->cyclic = true; - -if (__dma_omap15xx (od->plat->dma_attr)) { -uint32_t val; - - val = c->plat->dma_read (CCR , c->dma_ch); - val |=3 <<8 ; - c->plat->dma_write (val,CCR , c->dma_ch); - } - } + c->cyclic = true;return vchan_tx_prep (&c->vc, &d->vd, flags); }
@@ -759,14 +742,6 @@ static int omap_dma_terminate_all(struct omap_chan *c)if (c->cyclic) { c->cyclic = false; c->paused = false; - -if (__dma_omap15xx (od->plat->dma_attr)) { -uint32_t val; - - val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~(3 <<8 ); - c->plat->dma_write (val,CCR , c->dma_ch); - } }vchan_get_all_descriptors (&c->vc, &head);
Signature · 1 line
1.8.3.1
PATCH 9/26 dmaengine: omap-dma: provide register definitions
In reply to Russell King - ARM LinuxProvide our own set of more complete register definitions; this allows us to get rid of the meaningless 1 << n constants scattered throughout this code.
--- drivers/dma/omap-dma.c | 171 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 54 deletions(-)
drivers/dma/omap-dma.c +117 -54
@@ -57,7 +57,7 @@ struct omap_desc {dma_addr_t dev_addr;int16_t fi;/* for OMAP_DMA_SYNC_PACKET */ -uint8_t es;/* OMAP_DMA_DATA_TYPE_xxx */ +uint8_t es;/* CSDP_DATA_TYPE_xxx */ uint32_t ccr;/* CCR value */ uint16_t cicr;/* CICR value */ uint32_t csdp;/* CSDP value */
@@ -66,10 +66,83 @@ struct omap_desc {struct omap_sg sg[0 ]; }; +enum { +CCR_FS =BIT (5 ), +CCR_READ_PRIORITY =BIT (6 ), +CCR_ENABLE =BIT (7 ), +CCR_AUTO_INIT =BIT (8 ),/* OMAP1 only */ +CCR_REPEAT =BIT (9 ),/* OMAP1 only */ +CCR_OMAP31_DISABLE =BIT (10 ),/* OMAP1 only */ +CCR_SUSPEND_SENSITIVE =BIT (8 ),/* OMAP2+ only */ +CCR_RD_ACTIVE =BIT (9 ),/* OMAP2+ only */ +CCR_WR_ACTIVE =BIT (10 ),/* OMAP2+ only */ +CCR_SRC_AMODE_CONSTANT =0 <<12 , +CCR_SRC_AMODE_POSTINC =1 <<12 , +CCR_SRC_AMODE_SGLIDX =2 <<12 , +CCR_SRC_AMODE_DBLIDX =3 <<12 , +CCR_DST_AMODE_CONSTANT =0 <<14 , +CCR_DST_AMODE_POSTINC =1 <<14 , +CCR_DST_AMODE_SGLIDX =2 <<14 , +CCR_DST_AMODE_DBLIDX =3 <<14 , +CCR_CONSTANT_FILL =BIT (16 ), +CCR_TRANSPARENT_COPY =BIT (17 ), +CCR_BS =BIT (18 ), +CCR_SUPERVISOR =BIT (22 ), +CCR_PREFETCH =BIT (23 ), +CCR_TRIGGER_SRC =BIT (24 ), +CCR_BUFFERING_DISABLE =BIT (25 ), +CCR_WRITE_PRIORITY =BIT (26 ), +CCR_SYNC_ELEMENT =0 , +CCR_SYNC_FRAME =CCR_FS , +CCR_SYNC_BLOCK =CCR_BS , +CCR_SYNC_PACKET =CCR_BS |CCR_FS , + +CSDP_DATA_TYPE_8 =0 , +CSDP_DATA_TYPE_16 =1 , +CSDP_DATA_TYPE_32 =2 , +CSDP_SRC_PORT_EMIFF =0 <<2 ,/* OMAP1 only */ +CSDP_SRC_PORT_EMIFS =1 <<2 ,/* OMAP1 only */ +CSDP_SRC_PORT_OCP_T1 =2 <<2 ,/* OMAP1 only */ +CSDP_SRC_PORT_TIPB =3 <<2 ,/* OMAP1 only */ +CSDP_SRC_PORT_OCP_T2 =4 <<2 ,/* OMAP1 only */ +CSDP_SRC_PORT_MPUI =5 <<2 ,/* OMAP1 only */ +CSDP_SRC_PACKED =BIT (6 ), +CSDP_SRC_BURST_1 =0 <<7 , +CSDP_SRC_BURST_16 =1 <<7 , +CSDP_SRC_BURST_32 =2 <<7 , +CSDP_SRC_BURST_64 =3 <<7 , +CSDP_DST_PORT_EMIFF =0 <<9 ,/* OMAP1 only */ +CSDP_DST_PORT_EMIFS =1 <<9 ,/* OMAP1 only */ +CSDP_DST_PORT_OCP_T1 =2 <<9 ,/* OMAP1 only */ +CSDP_DST_PORT_TIPB =3 <<9 ,/* OMAP1 only */ +CSDP_DST_PORT_OCP_T2 =4 <<9 ,/* OMAP1 only */ +CSDP_DST_PORT_MPUI =5 <<9 ,/* OMAP1 only */ +CSDP_DST_PACKED =BIT (13 ), +CSDP_DST_BURST_1 =0 <<14 , +CSDP_DST_BURST_16 =1 <<14 , +CSDP_DST_BURST_32 =2 <<14 , +CSDP_DST_BURST_64 =3 <<14 , + +CICR_TOUT_IE =BIT (0 ),/* OMAP1 only */ +CICR_DROP_IE =BIT (1 ), +CICR_HALF_IE =BIT (2 ), +CICR_FRAME_IE =BIT (3 ), +CICR_LAST_IE =BIT (4 ), +CICR_BLOCK_IE =BIT (5 ), +CICR_PKT_IE =BIT (7 ),/* OMAP2+ only */ +CICR_TRANS_ERR_IE =BIT (8 ),/* OMAP2+ only */ +CICR_SUPERVISOR_ERR_IE =BIT (10 ),/* OMAP2+ only */ +CICR_MISALIGNED_ERR_IE =BIT (11 ),/* OMAP2+ only */ +CICR_DRAIN_IE =BIT (12 ),/* OMAP2+ only */ +CICR_SUPER_BLOCK_IE =BIT (14 ),/* OMAP2+ only */ + +CLNK_CTRL_ENABLE_LNK =BIT (15 ), +}; +static const unsigned es_bytes[] = { - [OMAP_DMA_DATA_TYPE_S8 ] =1 , - [OMAP_DMA_DATA_TYPE_S16 ] =2 , - [OMAP_DMA_DATA_TYPE_S32 ] =4 , + [CSDP_DATA_TYPE_8 ] =1 , + [CSDP_DATA_TYPE_16 ] =2 , + [CSDP_DATA_TYPE_32 ] =4 , };static struct of_dma_filter_info omap_dma_info = {
@@ -112,7 +185,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)if (dma_omap1 ()) val &= ~(1 <<14 ); - val |= c->dma_ch |1 <<15 ; + val |= c->dma_ch |CLNK_CTRL_ENABLE_LNK ; c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); }else if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS )
@@ -129,8 +202,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read (CCR , c->dma_ch);if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) - val |=OMAP_DMA_CCR_BUFFERING_DISABLE ; - val |=OMAP_DMA_CCR_EN ; + val |=CCR_BUFFERING_DISABLE ; + val |=CCR_ENABLE ;mb (); c->plat->dma_write (val,CCR , c->dma_ch); }
@@ -150,8 +223,7 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write (~0 ,CSR , c->dma_ch); val = c->plat->dma_read (CCR , c->dma_ch); -if (od->plat->errata & DMA_ERRATA_i541 && - val &OMAP_DMA_CCR_SEL_SRC_DST_SYNC ) { +if (od->plat->errata & DMA_ERRATA_i541 && val &CCR_TRIGGER_SRC ) {uint32_t sysconfig;unsigned i;
@@ -161,13 +233,13 @@ static void omap_dma_stop(struct omap_chan *c) c->plat->dma_write (val,OCP_SYSCONFIG , c->dma_ch); val = c->plat->dma_read (CCR , c->dma_ch); - val &= ~OMAP_DMA_CCR_EN ; + val &= ~CCR_ENABLE ; c->plat->dma_write (val,CCR , c->dma_ch);/* Wait for sDMA FIFO to drain */ for (i =0 ; ; i++) { val = c->plat->dma_read (CCR , c->dma_ch); -if (!(val & (OMAP_DMA_CCR_RD_ACTIVE |OMAP_DMA_CCR_WR_ACTIVE ))) +if (!(val & (CCR_RD_ACTIVE |CCR_WR_ACTIVE )))break ;if (i >100 )
@@ -176,14 +248,14 @@ static void omap_dma_stop(struct omap_chan *c)udelay (5 ); } -if (val & (OMAP_DMA_CCR_RD_ACTIVE |OMAP_DMA_CCR_WR_ACTIVE )) +if (val & (CCR_RD_ACTIVE |CCR_WR_ACTIVE ))dev_err (c->vc.chan.device->dev,"DMA drain did not complete on lch %d\n" , c->dma_ch); c->plat->dma_write (sysconfig,OCP_SYSCONFIG , c->dma_ch); }else { - val &= ~OMAP_DMA_CCR_EN ; + val &= ~CCR_ENABLE ; c->plat->dma_write (val,CCR , c->dma_ch); }
@@ -195,7 +267,7 @@ static void omap_dma_stop(struct omap_chan *c)if (dma_omap1 ()) val |=1 <<14 ;/* set the STOP_LNK bit */ else - val &= ~(1 <<15 );/* Clear the ENABLE_LNK bit */ + val &= ~CLNK_CTRL_ENABLE_LNK ; c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); }
@@ -510,13 +582,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(/* Bus width translates to the element size (ES) */ switch (dev_width) {case DMA_SLAVE_BUSWIDTH_1_BYTE : - es =OMAP_DMA_DATA_TYPE_S8 ; + es =CSDP_DATA_TYPE_8 ;break ;case DMA_SLAVE_BUSWIDTH_2_BYTES : - es =OMAP_DMA_DATA_TYPE_S16 ; + es =CSDP_DATA_TYPE_16 ;break ;case DMA_SLAVE_BUSWIDTH_4_BYTES : - es =OMAP_DMA_DATA_TYPE_S32 ; + es =CSDP_DATA_TYPE_32 ;break ;default :/* not reached */ return NULL ;
@@ -531,44 +603,38 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr =0 ; + d->ccr =CCR_SYNC_FRAME ;if (dir ==DMA_DEV_TO_MEM ) - d->ccr |=OMAP_DMA_AMODE_POST_INC <<14 | -OMAP_DMA_AMODE_CONSTANT <<12 ; + d->ccr |=CCR_DST_AMODE_POSTINC |CCR_SRC_AMODE_CONSTANT ;else - d->ccr |=OMAP_DMA_AMODE_CONSTANT <<14 | -OMAP_DMA_AMODE_POST_INC <<12 ; + d->ccr |=CCR_DST_AMODE_CONSTANT |CCR_SRC_AMODE_POSTINC ; - d->cicr =OMAP_DMA_DROP_IRQ |OMAP_DMA_BLOCK_IRQ ; + d->cicr =CICR_DROP_IE |CICR_BLOCK_IE ; d->csdp = es;if (dma_omap1 ()) { - d->ccr |=1 <<5 ;/* frame sync */ if (__dma_omap16xx (od->plat->dma_attr)) { - d->ccr |=1 <<10 ;/* disable 3.0/3.1 compatibility mode */ + d->ccr |=CCR_OMAP31_DISABLE ;/* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch +1 ; }else { d->ccr |= c->dma_sig &0x1f ; } - d->cicr |=OMAP1_DMA_TOUT_IRQ ; + d->cicr |=CICR_TOUT_IE ;if (dir ==DMA_DEV_TO_MEM ) - d->csdp |=OMAP_DMA_PORT_EMIFF <<9 | -OMAP_DMA_PORT_TIPB <<2 ; + d->csdp |=CSDP_DST_PORT_EMIFF |CSDP_SRC_PORT_TIPB ;else - d->csdp |=OMAP_DMA_PORT_TIPB <<9 | -OMAP_DMA_PORT_EMIFF <<2 ; + d->csdp |=CSDP_DST_PORT_TIPB |CSDP_SRC_PORT_EMIFF ; }else { d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; d->ccr |= c->dma_sig &0x1f ; - d->ccr |=1 <<5 ;/* frame sync */ if (dir ==DMA_DEV_TO_MEM ) - d->ccr |=1 <<24 ;/* source synch */ + d->ccr |=CCR_TRIGGER_SRC ; - d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ; + d->cicr |=CICR_MISALIGNED_ERR_IE |CICR_TRANS_ERR_IE ; }/*
@@ -623,13 +689,13 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(/* Bus width translates to the element size (ES) */ switch (dev_width) {case DMA_SLAVE_BUSWIDTH_1_BYTE : - es =OMAP_DMA_DATA_TYPE_S8 ; + es =CSDP_DATA_TYPE_8 ;break ;case DMA_SLAVE_BUSWIDTH_2_BYTES : - es =OMAP_DMA_DATA_TYPE_S16 ; + es =CSDP_DATA_TYPE_16 ;break ;case DMA_SLAVE_BUSWIDTH_4_BYTES : - es =OMAP_DMA_DATA_TYPE_S32 ; + es =CSDP_DATA_TYPE_32 ;break ;default :/* not reached */ return NULL ;
@@ -651,51 +717,48 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->ccr =0 ;if (__dma_omap15xx (od->plat->dma_attr)) - d->ccr =3 <<8 ; + d->ccr =CCR_AUTO_INIT |CCR_REPEAT ;if (dir ==DMA_DEV_TO_MEM ) - d->ccr |=OMAP_DMA_AMODE_POST_INC <<14 | -OMAP_DMA_AMODE_CONSTANT <<12 ; + d->ccr |=CCR_DST_AMODE_POSTINC |CCR_SRC_AMODE_CONSTANT ;else - d->ccr |=OMAP_DMA_AMODE_CONSTANT <<14 | -OMAP_DMA_AMODE_POST_INC <<12 ; + d->ccr |=CCR_DST_AMODE_CONSTANT |CCR_SRC_AMODE_POSTINC ; - d->cicr =OMAP_DMA_DROP_IRQ ; + d->cicr =CICR_DROP_IE ;if (flags &DMA_PREP_INTERRUPT ) - d->cicr |=OMAP_DMA_FRAME_IRQ ; + d->cicr |=CICR_FRAME_IE ; d->csdp = es;if (dma_omap1 ()) {if (__dma_omap16xx (od->plat->dma_attr)) { - d->ccr |=1 <<10 ;/* disable 3.0/3.1 compatibility mode */ + d->ccr |=CCR_OMAP31_DISABLE ;/* Duplicate what plat-omap/dma.c does */ d->ccr |= c->dma_ch +1 ; }else { d->ccr |= c->dma_sig &0x1f ; } - d->cicr |=OMAP1_DMA_TOUT_IRQ ; + d->cicr |=CICR_TOUT_IE ;if (dir ==DMA_DEV_TO_MEM ) - d->csdp |=OMAP_DMA_PORT_EMIFF <<9 | -OMAP_DMA_PORT_MPUI <<2 ; + d->csdp |=CSDP_DST_PORT_EMIFF |CSDP_SRC_PORT_MPUI ;else - d->csdp |=OMAP_DMA_PORT_MPUI <<9 | -OMAP_DMA_PORT_EMIFF <<2 ; + d->csdp |=CSDP_DST_PORT_MPUI |CSDP_SRC_PORT_EMIFF ; }else { d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; d->ccr |= c->dma_sig &0x1f ;if (burst) - d->ccr |=1 <<18 |1 <<5 ;/* packet */ + d->ccr |=CCR_SYNC_PACKET ; +else + d->ccr |=CCR_SYNC_ELEMENT ;if (dir ==DMA_DEV_TO_MEM ) - d->ccr |=1 <<24 ;/* source synch */ + d->ccr |=CCR_TRIGGER_SRC ; - d->cicr |=OMAP2_DMA_MISALIGNED_ERR_IRQ |OMAP2_DMA_TRANS_ERR_IRQ ; + d->cicr |=CICR_MISALIGNED_ERR_IE |CICR_TRANS_ERR_IE ; -/* src and dst burst mode 16 */ - d->csdp |=3 <<14 |3 <<7 ; + d->csdp |=CSDP_DST_BURST_64 |CSDP_SRC_BURST_64 ; } c->cyclic = true;
Signature · 1 line
1.8.3.1
PATCH 10/26 dmaengine: omap-dma: move CCR buffering disable errata out of the fast path
In reply to Russell King - ARM LinuxSince we record the CCR register in the dma transaction, we can move the processing of the iframe buffering errata out of the omap_dma_start(). Move it to the preparation functions.
--- drivers/dma/omap-dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/dma/omap-dma.c +5 -2
@@ -201,8 +201,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) c->plat->dma_write (d->cicr,CICR , c->dma_ch); val = c->plat->dma_read (CCR , c->dma_ch); -if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) - val |=CCR_BUFFERING_DISABLE ; val |=CCR_ENABLE ;mb (); c->plat->dma_write (val,CCR , c->dma_ch);
@@ -558,6 +556,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen, enum dma_transfer_direction dir, unsigned long tx_flags, void *context) { + struct omap_dmadev *od = to_omap_dma_dev(chan->device);struct omap_chan *c =to_omap_dma_chan (chan);enum dma_slave_buswidth dev_width;struct scatterlist *sgent;
@@ -636,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->cicr |=CICR_MISALIGNED_ERR_IE |CICR_TRANS_ERR_IE ; } +if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) + d->ccr |=CCR_BUFFERING_DISABLE ;/* * Build our scatterlist entries: each contains the address,
@@ -760,6 +761,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |=CSDP_DST_BURST_64 |CSDP_SRC_BURST_64 ; } +if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) + d->ccr |=CCR_BUFFERING_DISABLE ; c->cyclic = true;
Signature · 1 line
1.8.3.1
PATCH 11/26 dmaengine: omap-dma: consolidate clearing channel status register
In reply to Russell King - ARM Linux--- drivers/dma/omap-dma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/dma/omap-dma.c +10 -10
@@ -169,6 +169,14 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)kfree (container_of(vd ,struct omap_desc ,vd )); } +static void omap_dma_clear_csr (struct omap_chan *c) +{ +if (dma_omap1 ()) + c->plat->dma_read (CSR , c->dma_ch); +else + c->plat->dma_write (~0 ,CSR , c->dma_ch); +} +static void omap_dma_start (struct omap_chan *c,struct omap_desc *d) {struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device);
@@ -191,11 +199,7 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) }else if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS ) c->plat->dma_write (c->dma_ch,CLNK_CTRL , c->dma_ch); -/* Clear CSR */ -if (dma_omap1 ()) - c->plat->dma_read (CSR , c->dma_ch); -else - c->plat->dma_write (~0 ,CSR , c->dma_ch); +omap_dma_clear_csr (c);/* Enable interrupts */ c->plat->dma_write (d->cicr,CICR , c->dma_ch);
@@ -214,11 +218,7 @@ static void omap_dma_stop(struct omap_chan *c)/* disable irq */ c->plat->dma_write (0 ,CICR , c->dma_ch); -/* Clear CSR */ -if (dma_omap1 ()) - c->plat->dma_read (CSR , c->dma_ch); -else - c->plat->dma_write (~0 ,CSR , c->dma_ch); +omap_dma_clear_csr (c); val = c->plat->dma_read (CCR , c->dma_ch);if (od->plat->errata & DMA_ERRATA_i541 && val &CCR_TRIGGER_SRC ) {
Signature · 1 line
1.8.3.1
PATCH 12/26 dmaengine: omap-dma: improve efficiency loading C.SA/C.EI/C.FI registers
In reply to Russell King - ARM Linux--- drivers/dma/omap-dma.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/dma/omap-dma.c +20 -12
@@ -275,17 +275,21 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, unsigned idx) {struct omap_sg *sg = d->sg + idx; +unsigned cxsa, cxei, cxfi;if (d->dir ==DMA_DEV_TO_MEM ) { - c->plat->dma_write (sg->addr,CDSA , c->dma_ch); - c->plat->dma_write (0 ,CDEI , c->dma_ch); - c->plat->dma_write (0 ,CDFI , c->dma_ch); + cxsa =CDSA ; + cxei =CDEI ; + cxfi =CDFI ; }else { - c->plat->dma_write (sg->addr,CSSA , c->dma_ch); - c->plat->dma_write (0 ,CSEI , c->dma_ch); - c->plat->dma_write (0 ,CSFI , c->dma_ch); + cxsa =CSSA ; + cxei =CSEI ; + cxfi =CSFI ; } + c->plat->dma_write (sg->addr, cxsa, c->dma_ch); + c->plat->dma_write (0 , cxei, c->dma_ch); + c->plat->dma_write (0 , cxfi, c->dma_ch); c->plat->dma_write (sg->en,CEN , c->dma_ch); c->plat->dma_write (sg->fn,CFN , c->dma_ch);
@@ -296,6 +300,7 @@ static void omap_dma_start_desc(struct omap_chan *c) {struct virt_dma_desc *vd =vchan_next_desc (&c->vc);struct omap_desc *d; +unsigned cxsa, cxei, cxfi;if (!vd) { c->desc =NULL ;
@@ -312,15 +317,18 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write (d->ccr >>16 ,CCR2 , c->dma_ch);if (d->dir ==DMA_DEV_TO_MEM ) { - c->plat->dma_write (d->dev_addr,CSSA , c->dma_ch); - c->plat->dma_write (0 ,CSEI , c->dma_ch); - c->plat->dma_write (d->fi,CSFI , c->dma_ch); + cxsa =CSSA ; + cxei =CSEI ; + cxfi =CSFI ; }else { - c->plat->dma_write (d->dev_addr,CDSA , c->dma_ch); - c->plat->dma_write (0 ,CDEI , c->dma_ch); - c->plat->dma_write (d->fi,CDFI , c->dma_ch); + cxsa =CDSA ; + cxei =CDEI ; + cxfi =CDFI ; } + c->plat->dma_write (d->dev_addr, cxsa, c->dma_ch); + c->plat->dma_write (0 , cxei, c->dma_ch); + c->plat->dma_write (d->fi, cxfi, c->dma_ch); c->plat->dma_write (d->csdp,CSDP , c->dma_ch);omap_dma_start_sg (c, d,0 );
Signature · 1 line
1.8.3.1
PATCH 13/26 dmaengine: omap-dma: move clnk_ctrl setting to preparation functions
In reply to Russell King - ARM LinuxMove the clnk_ctrl setup to the preparation functions, saving its value in the omap_desc. This only needs to be set once per descriptor, not for each segment, so set it in omap_dma_start_desc() rather than omap_dma_start().
--- drivers/dma/omap-dma.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-)
drivers/dma/omap-dma.c +9 -14
@@ -59,6 +59,7 @@ struct omap_desc {int16_t fi;/* for OMAP_DMA_SYNC_PACKET */ uint8_t es;/* CSDP_DATA_TYPE_xxx */ uint32_t ccr;/* CCR value */ +uint16_t clnk_ctrl;/* CLNK_CTRL value */ uint16_t cicr;/* CICR value */ uint32_t csdp;/* CSDP value */
@@ -187,18 +188,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)else c->plat->dma_write (0 ,CDAC , c->dma_ch); -if (!__dma_omap15xx (od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read (CLNK_CTRL , c->dma_ch); - -if (dma_omap1 ()) - val &= ~(1 <<14 ); - - val |= c->dma_ch |CLNK_CTRL_ENABLE_LNK ; - - c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); - }else if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS ) - c->plat->dma_write (c->dma_ch,CLNK_CTRL , c->dma_ch); -omap_dma_clear_csr (c);/* Enable interrupts */
@@ -330,6 +319,7 @@ static void omap_dma_start_desc(struct omap_chan *c) c->plat->dma_write (0 , cxei, c->dma_ch); c->plat->dma_write (d->fi, cxfi, c->dma_ch); c->plat->dma_write (d->csdp,CSDP , c->dma_ch); + c->plat->dma_write (d->clnk_ctrl,CLNK_CTRL , c->dma_ch);omap_dma_start_sg (c, d,0 ); }
@@ -645,6 +635,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( }if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) d->ccr |=CCR_BUFFERING_DISABLE ; +if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS ) + d->clnk_ctrl = c->dma_ch;/* * Build our scatterlist entries: each contains the address,
@@ -725,8 +717,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sglen =1 ; d->ccr =0 ; -if (__dma_omap15xx (od->plat->dma_attr)) - d->ccr =CCR_AUTO_INIT |CCR_REPEAT ;if (dir ==DMA_DEV_TO_MEM ) d->ccr |=CCR_DST_AMODE_POSTINC |CCR_SRC_AMODE_CONSTANT ;else
@@ -772,6 +762,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) d->ccr |=CCR_BUFFERING_DISABLE ; +if (__dma_omap15xx (od->plat->dma_attr)) + d->ccr |=CCR_AUTO_INIT |CCR_REPEAT ; +else + d->clnk_ctrl = c->dma_ch |CLNK_CTRL_ENABLE_LNK ; + c->cyclic = true;return vchan_tx_prep (&c->vc, &d->vd, flags);
Signature · 1 line
1.8.3.1
PATCH 14/26 dmaengine: omap-dma: move barrier to omap_dma_start_desc()
In reply to Russell King - ARM LinuxWe don't need to issue a barrier for every segment of a DMA transfer; doing this just once per descriptor will do.
--- drivers/dma/omap-dma.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/dma/omap-dma.c +7 -1
@@ -195,7 +195,6 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) val = c->plat->dma_read (CCR , c->dma_ch); val |=CCR_ENABLE ; -mb (); c->plat->dma_write (val,CCR , c->dma_ch); }
@@ -301,6 +300,13 @@ static void omap_dma_start_desc(struct omap_chan *c) c->desc = d =to_omap_dma_desc (&vd->tx); c->sgidx =0 ; +/* +* This provides the necessary barrier to ensure data held in +* DMA coherent memory is visible to the DMA engine prior to +* the transfer starting. +*/ +mb (); + c->plat->dma_write (d->ccr,CCR , c->dma_ch);if (dma_omap1 ()) c->plat->dma_write (d->ccr >>16 ,CCR2 , c->dma_ch);
Signature · 1 line
1.8.3.1
PATCH 15/26 dmaengine: omap-dma: use cached CCR value when enabling DMA
In reply to Russell King - ARM LinuxWe don't need to read-modify-write the CCR register; we already know what value it should contain at this point. Use the cached CCR value when setting the enable bit.
--- drivers/dma/omap-dma.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/dma/omap-dma.c +2 -4
@@ -181,7 +181,6 @@ static void omap_dma_clear_csr(struct omap_chan *c)static void omap_dma_start (struct omap_chan *c,struct omap_desc *d) {struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); -uint32_t val;if (__dma_omap15xx (od->plat->dma_attr)) c->plat->dma_write (0 ,CPC , c->dma_ch);
@@ -193,9 +192,8 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)/* Enable interrupts */ c->plat->dma_write (d->cicr,CICR , c->dma_ch); - val = c->plat->dma_read (CCR , c->dma_ch); - val |=CCR_ENABLE ; - c->plat->dma_write (val,CCR , c->dma_ch); +/* Enable channel */ + c->plat->dma_write (d->ccr |CCR_ENABLE ,CCR , c->dma_ch); }static void omap_dma_stop (struct omap_chan *c)
Signature · 1 line
1.8.3.1
PATCH 16/26 dmaengine: omap-dma: provide register read/write functions
In reply to Russell King - ARM LinuxProvide a pair of channel register accessors, and a pair of global accessors for non-channel specific registers.
--- drivers/dma/omap-dma.c | 102 +++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 41 deletions(-)
drivers/dma/omap-dma.c +61 -41
@@ -170,12 +170,32 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)kfree (container_of(vd ,struct omap_desc ,vd )); } +static void omap_dma_glbl_write (struct omap_dmadev *od,unsigned reg,unsigned val) +{ + od->plat->dma_write (val, reg,0 ); +} + +static unsigned omap_dma_glbl_read (struct omap_dmadev *od,unsigned reg) +{ +return od->plat->dma_read (reg,0 ); +} + +static void omap_dma_chan_write (struct omap_chan *c,unsigned reg,unsigned val) +{ + c->plat->dma_write (val, reg, c->dma_ch); +} + +static unsigned omap_dma_chan_read (struct omap_chan *c,unsigned reg) +{ +return c->plat->dma_read (reg, c->dma_ch); +} +static void omap_dma_clear_csr (struct omap_chan *c) {if (dma_omap1 ()) - c->plat->dma_read (CSR , c->dma_ch); +omap_dma_chan_read (c,CSR );else - c->plat->dma_write (~0 ,CSR , c->dma_ch); +omap_dma_chan_write (c,CSR , ~0 ); }static void omap_dma_start (struct omap_chan *c,struct omap_desc *d)
@@ -183,17 +203,17 @@ static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device);if (__dma_omap15xx (od->plat->dma_attr)) - c->plat->dma_write (0 ,CPC , c->dma_ch); +omap_dma_chan_write (c,CPC ,0 );else - c->plat->dma_write (0 ,CDAC , c->dma_ch); +omap_dma_chan_write (c,CDAC ,0 );omap_dma_clear_csr (c);/* Enable interrupts */ - c->plat->dma_write (d->cicr,CICR , c->dma_ch); +omap_dma_chan_write (c,CICR , d->cicr);/* Enable channel */ - c->plat->dma_write (d->ccr |CCR_ENABLE ,CCR , c->dma_ch); +omap_dma_chan_write (c,CCR , d->ccr |CCR_ENABLE ); }static void omap_dma_stop (struct omap_chan *c)
@@ -202,27 +222,27 @@ static void omap_dma_stop(struct omap_chan *c)uint32_t val;/* disable irq */ - c->plat->dma_write (0 ,CICR , c->dma_ch); +omap_dma_chan_write (c,CICR ,0 );omap_dma_clear_csr (c); - val = c->plat->dma_read (CCR , c->dma_ch); + val =omap_dma_chan_read (c,CCR );if (od->plat->errata & DMA_ERRATA_i541 && val &CCR_TRIGGER_SRC ) {uint32_t sysconfig;unsigned i; - sysconfig = c->plat->dma_read (OCP_SYSCONFIG , c->dma_ch); + sysconfig =omap_dma_glbl_read (od,OCP_SYSCONFIG ); val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK ; val |=DMA_SYSCONFIG_MIDLEMODE (DMA_IDLEMODE_NO_IDLE ); - c->plat->dma_write (val,OCP_SYSCONFIG , c->dma_ch); +omap_dma_glbl_write (od,OCP_SYSCONFIG , val); - val = c->plat->dma_read (CCR , c->dma_ch); + val =omap_dma_chan_read (c,CCR ); val &= ~CCR_ENABLE ; - c->plat->dma_write (val,CCR , c->dma_ch); +omap_dma_chan_write (c,CCR , val);/* Wait for sDMA FIFO to drain */ for (i =0 ; ; i++) { - val = c->plat->dma_read (CCR , c->dma_ch); + val =omap_dma_chan_read (c,CCR );if (!(val & (CCR_RD_ACTIVE |CCR_WR_ACTIVE )))break ;
@@ -237,23 +257,23 @@ static void omap_dma_stop(struct omap_chan *c)"DMA drain did not complete on lch %d\n" , c->dma_ch); - c->plat->dma_write (sysconfig,OCP_SYSCONFIG , c->dma_ch); +omap_dma_glbl_write (od,OCP_SYSCONFIG , sysconfig); }else { val &= ~CCR_ENABLE ; - c->plat->dma_write (val,CCR , c->dma_ch); +omap_dma_chan_write (c,CCR , val); }mb ();if (!__dma_omap15xx (od->plat->dma_attr) && c->cyclic) { - val = c->plat->dma_read (CLNK_CTRL , c->dma_ch); + val =omap_dma_chan_read (c,CLNK_CTRL );if (dma_omap1 ()) val |=1 <<14 ;/* set the STOP_LNK bit */ else val &= ~CLNK_CTRL_ENABLE_LNK ; - c->plat->dma_write (val,CLNK_CTRL , c->dma_ch); +omap_dma_chan_write (c,CLNK_CTRL , val); } }
@@ -273,11 +293,11 @@ static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, cxfi =CSFI ; } - c->plat->dma_write (sg->addr, cxsa, c->dma_ch); - c->plat->dma_write (0 , cxei, c->dma_ch); - c->plat->dma_write (0 , cxfi, c->dma_ch); - c->plat->dma_write (sg->en,CEN , c->dma_ch); - c->plat->dma_write (sg->fn,CFN , c->dma_ch); +omap_dma_chan_write (c, cxsa, sg->addr); +omap_dma_chan_write (c, cxei,0 ); +omap_dma_chan_write (c, cxfi,0 ); +omap_dma_chan_write (c,CEN , sg->en); +omap_dma_chan_write (c,CFN , sg->fn);omap_dma_start (c, d); }
@@ -305,9 +325,9 @@ static void omap_dma_start_desc(struct omap_chan *c)*/ mb (); - c->plat->dma_write (d->ccr,CCR , c->dma_ch); +omap_dma_chan_write (c,CCR , d->ccr);if (dma_omap1 ()) - c->plat->dma_write (d->ccr >>16 ,CCR2 , c->dma_ch); +omap_dma_chan_write (c,CCR2 , d->ccr >>16 );if (d->dir ==DMA_DEV_TO_MEM ) { cxsa =CSSA ;
@@ -319,11 +339,11 @@ static void omap_dma_start_desc(struct omap_chan *c) cxfi =CDFI ; } - c->plat->dma_write (d->dev_addr, cxsa, c->dma_ch); - c->plat->dma_write (0 , cxei, c->dma_ch); - c->plat->dma_write (d->fi, cxfi, c->dma_ch); - c->plat->dma_write (d->csdp,CSDP , c->dma_ch); - c->plat->dma_write (d->clnk_ctrl,CLNK_CTRL , c->dma_ch); +omap_dma_chan_write (c, cxsa, d->dev_addr); +omap_dma_chan_write (c, cxei,0 ); +omap_dma_chan_write (c, cxfi, d->fi); +omap_dma_chan_write (c,CSDP , d->csdp); +omap_dma_chan_write (c,CLNK_CTRL , d->clnk_ctrl);omap_dma_start_sg (c, d,0 ); }
@@ -437,12 +457,12 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)dma_addr_t addr;if (__dma_omap15xx (od->plat->dma_attr)) - addr = c->plat->dma_read (CPC , c->dma_ch); + addr =omap_dma_chan_read (c,CPC );else - addr = c->plat->dma_read (CSAC , c->dma_ch); + addr =omap_dma_chan_read (c,CSAC );if (od->plat->errata &DMA_ERRATA_3_3 && addr ==0 ) - addr = c->plat->dma_read (CSAC , c->dma_ch); + addr =omap_dma_chan_read (c,CSAC );if (!__dma_omap15xx (od->plat->dma_attr)) {/*
@@ -450,14 +470,14 @@ static dma_addr_t omap_dma_get_src_pos(struct omap_chan *c)* not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ -if (c->plat->dma_read (CDAC , c->dma_ch)) - addr = c->plat->dma_read (CSAC , c->dma_ch); +if (omap_dma_chan_read (c,CDAC )) + addr =omap_dma_chan_read (c,CSAC );else - addr = c->plat->dma_read (CSSA , c->dma_ch); + addr =omap_dma_chan_read (c,CSSA ); }if (dma_omap1 ()) - addr |= c->plat->dma_read (CSSA , c->dma_ch) &0xffff0000 ; + addr |=omap_dma_chan_read (c,CSSA ) &0xffff0000 ;return addr; }
@@ -468,27 +488,27 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)dma_addr_t addr;if (__dma_omap15xx (od->plat->dma_attr)) - addr = c->plat->dma_read (CPC , c->dma_ch); + addr =omap_dma_chan_read (c,CPC );else - addr = c->plat->dma_read (CDAC , c->dma_ch); + addr =omap_dma_chan_read (c,CDAC );/* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!__dma_omap15xx (od->plat->dma_attr) && addr ==0 ) { - addr = c->plat->dma_read (CDAC , c->dma_ch); + addr =omap_dma_chan_read (c,CDAC );/* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed destination start address in this case. */ if (addr ==0 ) - addr = c->plat->dma_read (CDSA , c->dma_ch); + addr =omap_dma_chan_read (c,CDSA ); }if (dma_omap1 ()) - addr |= c->plat->dma_read (CDSA , c->dma_ch) &0xffff0000 ; + addr |=omap_dma_chan_read (c,CDSA ) &0xffff0000 ;return addr; }
Signature · 1 line
1.8.3.1
PATCH 17/26 dmaengine: omap-dma: cleanup errata 3.3 handling
In reply to Russell King - ARM Linux--- drivers/dma/omap-dma.c | 52 ++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 23 deletions(-)
drivers/dma/omap-dma.c +29 -23
@@ -451,28 +451,39 @@ static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)return size; } +/* +* OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is +* read before the DMA controller finished disabling the channel. +*/ +static uint32_t omap_dma_chan_read_3_3 (struct omap_chan *c,unsigned reg) +{ +struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); +uint32_t val; + + val =omap_dma_chan_read (c, reg); +if (val ==0 && od->plat->errata &DMA_ERRATA_3_3 ) + val =omap_dma_chan_read (c, reg); + +return val; +} +static dma_addr_t omap_dma_get_src_pos (struct omap_chan *c) {struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device); -dma_addr_t addr; +dma_addr_t addr, cdac; -if (__dma_omap15xx (od->plat->dma_attr)) +if (__dma_omap15xx (od->plat->dma_attr)) { addr =omap_dma_chan_read (c,CPC ); -else - addr =omap_dma_chan_read (c,CSAC ); - -if (od->plat->errata &DMA_ERRATA_3_3 && addr ==0 ) - addr =omap_dma_chan_read (c,CSAC ); + }else { + addr =omap_dma_chan_read_3_3 (c,CSAC ); + cdac =omap_dma_chan_read_3_3 (c,CDAC ); -if (!__dma_omap15xx (od->plat->dma_attr)) {/* * CDAC == 0 indicates that the DMA transfer on the channel has * not been started (no data has been transferred so far). * Return the programmed source start address in this case. */ -if (omap_dma_chan_read (c,CDAC )) - addr =omap_dma_chan_read (c,CSAC ); -else +if (cdac ==0 ) addr =omap_dma_chan_read (c,CSSA ); }
@@ -487,21 +498,16 @@ static dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c)struct omap_dmadev *od =to_omap_dma_dev (c->vc.chan.device);dma_addr_t addr; -if (__dma_omap15xx (od->plat->dma_attr)) +if (__dma_omap15xx (od->plat->dma_attr)) { addr =omap_dma_chan_read (c,CPC ); -else - addr =omap_dma_chan_read (c,CDAC ); + }else { + addr =omap_dma_chan_read_3_3 (c,CDAC ); -/* -* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is -* read before the DMA controller finished disabling the channel. -*/ -if (!__dma_omap15xx (od->plat->dma_attr) && addr ==0 ) { - addr =omap_dma_chan_read (c,CDAC );/* -* CDAC == 0 indicates that the DMA transfer on the channel has -* not been started (no data has been transferred so far). -* Return the programmed destination start address in this case. +* CDAC == 0 indicates that the DMA transfer on the channel +* has not been started (no data has been transferred so +* far). Return the programmed destination start address in +* this case. */ if (addr ==0 ) addr =omap_dma_chan_read (c,CDSA );
Signature · 1 line
1.8.3.1
PATCH 18/26 ARM: omap: remove references to disable_irq_lch
In reply to Russell King - ARM LinuxThe disable_irq_lch method is never actually used, so there's not much point it existing; remove it.
--- arch/arm/mach-omap1/dma.c | 1 - arch/arm/mach-omap2/dma.c | 10 ---------- include/linux/omap-dma.h | 1 - 3 files changed, 12 deletions(-)
arch/arm/mach-omap1/dma.c +0 -1
@@ -363,7 +363,6 @@ static int __init omap1_system_dma_init(void) p->clear_dma = omap1_clear_dma; p->dma_write = dma_write; p->dma_read = dma_read; - p->disable_irq_lch =NULL ; p->errata =configure_dma_errata ();
arch/arm/mach-omap2/dma.c +0 -10
@@ -112,15 +112,6 @@ static inline u32 dma_read(int reg, int lch)return val; } -static inline void omap2_disable_irq_lch (int lch) -{ -u32 val; - - val =dma_read (IRQENABLE_L0 , lch); - val &= ~(1 << lch); -dma_write (val,IRQENABLE_L0 , lch); -} -static void omap2_clear_dma (int lch) {int i = dma_common_ch_start;
@@ -239,7 +230,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) } p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; - p->disable_irq_lch = omap2_disable_irq_lch; p->show_dma_caps = omap2_show_dma_caps; p->clear_dma = omap2_clear_dma; p->dma_write = dma_write;
include/linux/omap-dma.h +0 -1
@@ -275,7 +275,6 @@ struct omap_dma_dev_attr {struct omap_system_dma_plat_info {struct omap_dma_dev_attr *dma_attr;u32 errata; -void (*disable_irq_lch)(int lch);void (*show_dma_caps)(void );void (*clear_lch_regs)(int lch);void (*clear_dma)(int lch);
Signature · 1 line
1.8.3.1
PATCH 19/26 ARM: omap: remove almost-const variables
In reply to Russell King - ARM Linuxdma_stride and dma_common_ch_start are only ever initialised to one known value at initialisation, and are private to each of these files. There's no point these being variables at all.
--- arch/arm/mach-omap1/dma.c | 14 ++++---------- arch/arm/mach-omap2/dma.c | 14 +++++--------- 2 files changed, 9 insertions(+), 19 deletions(-)
arch/arm/mach-omap1/dma.c +4 -10
@@ -36,8 +36,6 @@static u32 errata;static u32 enable_1510_mode; -static u8 dma_stride; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;static u16 reg_map[] = { [GCR ] =0x400 ,
@@ -184,7 +182,7 @@ static inline void dma_write(u32 val, int reg, int lch)u8 stride;u32 offset; - stride = (reg >= dma_common_ch_start) ? dma_stride :0 ; + stride = (reg >=CPC ) ?OMAP1_DMA_STRIDE :0 ; offset = reg_map[reg] + (stride * lch);__raw_writew (val, dma_base + offset);
@@ -200,7 +198,7 @@ static inline u32 dma_read(int reg, int lch)u8 stride;u32 offset, val; - stride = (reg >= dma_common_ch_start) ? dma_stride :0 ; + stride = (reg >=CPC ) ?OMAP1_DMA_STRIDE :0 ; offset = reg_map[reg] + (stride * lch); val =__raw_readw (dma_base + offset);
@@ -216,9 +214,9 @@ static inline u32 dma_read(int reg, int lch)static void omap1_clear_lch_regs (int lch) { -int i = dma_common_ch_start; +int i; -for (; i <= dma_common_ch_end; i +=1 ) +for (i =CPC ; i <=COLOR ; i +=1 )dma_write (0 , i, lch); }
@@ -380,10 +378,6 @@ static int __init omap1_system_dma_init(void) goto exit_release_chan; } - dma_stride =OMAP1_DMA_STRIDE ; - dma_common_ch_start =CPC ; - dma_common_ch_end =COLOR ; - dma_pdev =platform_device_register_full (&omap_dma_dev_info);if (IS_ERR (dma_pdev)) { ret =PTR_ERR (dma_pdev);
arch/arm/mach-omap2/dma.c +5 -9
@@ -38,11 +38,10 @@#define OMAP2_DMA_STRIDE 0x60static u32 errata; -static u8 dma_stride;static struct omap_dma_dev_attr *d; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; +static enum omap_reg_offsets dma_common_ch_end;static u16 reg_map[] = { [REVISION ] =0x00 ,
@@ -96,7 +95,7 @@ static inline void dma_write(u32 val, int reg, int lch)u8 stride;u32 offset; - stride = (reg >= dma_common_ch_start) ? dma_stride :0 ; + stride = (reg >=CSDP ) ?OMAP2_DMA_STRIDE :0 ; offset = reg_map[reg] + (stride * lch);__raw_writel (val, dma_base + offset); }
@@ -106,7 +105,7 @@ static inline u32 dma_read(int reg, int lch)u8 stride;u32 offset, val; - stride = (reg >= dma_common_ch_start) ? dma_stride :0 ; + stride = (reg >=CSDP ) ?OMAP2_DMA_STRIDE :0 ; offset = reg_map[reg] + (stride * lch); val =__raw_readl (dma_base + offset);return val;
@@ -114,9 +113,9 @@ static inline u32 dma_read(int reg, int lch)static void omap2_clear_dma (int lch) { -int i = dma_common_ch_start; +int i; -for (; i <= dma_common_ch_end; i +=1 ) +for (i =CSDP ; i <= dma_common_ch_end; i +=1 )dma_write (0 , i, lch); }
@@ -219,9 +218,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)struct resource *mem;char *name ="omap_dma_system" ; - dma_stride =OMAP2_DMA_STRIDE ; - dma_common_ch_start =CSDP ; - p =kzalloc (sizeof (struct omap_system_dma_plat_info ),GFP_KERNEL );if (!p) { pr_err("%s: Unable to allocate pdata for %s:%s\n",
Signature · 1 line
1.8.3.1
PATCH 20/26 ARM: omap: clean up DMA register accesses
In reply to Russell King - ARM LinuxWe can do much better with this by using a structure to describe each register, rather than code.
--- arch/arm/mach-omap1/dma.c | 117 +++++++++++++++++++++------------------------- arch/arm/mach-omap2/dma.c | 99 +++++++++++++++++++-------------------- include/linux/omap-dma.h | 13 ++++++ 3 files changed, 115 insertions(+), 114 deletions(-)
arch/arm/mach-omap1/dma.c +54 -63
@@ -32,53 +32,52 @@#define OMAP1_DMA_BASE (0xfffed800)#define OMAP1_LOGICAL_DMA_CH_COUNT 17 -#define OMAP1_DMA_STRIDE 0x40static u32 errata;static u32 enable_1510_mode; -static u16 reg_map[] = { - [GCR ] =0x400 , - [GSCR ] =0x404 , - [GRST1 ] =0x408 , - [HW_ID ] =0x442 , - [PCH2_ID ] =0x444 , - [PCH0_ID ] =0x446 , - [PCH1_ID ] =0x448 , - [PCHG_ID ] =0x44a , - [PCHD_ID ] =0x44c , - [CAPS_0 ] =0x44e , - [CAPS_1 ] =0x452 , - [CAPS_2 ] =0x456 , - [CAPS_3 ] =0x458 , - [CAPS_4 ] =0x45a , - [PCH2_SR ] =0x460 , - [PCH0_SR ] =0x480 , - [PCH1_SR ] =0x482 , - [PCHD_SR ] =0x4c0 , +static const struct omap_dma_reg reg_map[] = { + [GCR ] = {0x0400 ,0x00 ,OMAP_DMA_REG_16BIT }, + [GSCR ] = {0x0404 ,0x00 ,OMAP_DMA_REG_16BIT }, + [GRST1 ] = {0x0408 ,0x00 ,OMAP_DMA_REG_16BIT }, + [HW_ID ] = {0x0442 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH2_ID ] = {0x0444 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH0_ID ] = {0x0446 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH1_ID ] = {0x0448 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCHG_ID ] = {0x044a ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCHD_ID ] = {0x044c ,0x00 ,OMAP_DMA_REG_16BIT }, + [CAPS_0 ] = {0x044e ,0x00 ,OMAP_DMA_REG_2X16BIT }, + [CAPS_1 ] = {0x0452 ,0x00 ,OMAP_DMA_REG_2X16BIT }, + [CAPS_2 ] = {0x0456 ,0x00 ,OMAP_DMA_REG_16BIT }, + [CAPS_3 ] = {0x0458 ,0x00 ,OMAP_DMA_REG_16BIT }, + [CAPS_4 ] = {0x045a ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH2_SR ] = {0x0460 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH0_SR ] = {0x0480 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCH1_SR ] = {0x0482 ,0x00 ,OMAP_DMA_REG_16BIT }, + [PCHD_SR ] = {0x04c0 ,0x00 ,OMAP_DMA_REG_16BIT },/* Common Registers */ - [CSDP ] =0x00 , - [CCR ] =0x02 , - [CICR ] =0x04 , - [CSR ] =0x06 , - [CEN ] =0x10 , - [CFN ] =0x12 , - [CSFI ] =0x14 , - [CSEI ] =0x16 , - [CPC ] =0x18 ,/* 15xx only */ - [CSAC ] =0x18 , - [CDAC ] =0x1a , - [CDEI ] =0x1c , - [CDFI ] =0x1e , - [CLNK_CTRL ] =0x28 , + [CSDP ] = {0x0000 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CCR ] = {0x0002 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CICR ] = {0x0004 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CSR ] = {0x0006 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CEN ] = {0x0010 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CFN ] = {0x0012 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CSFI ] = {0x0014 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CSEI ] = {0x0016 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CPC ] = {0x0018 ,0x40 ,OMAP_DMA_REG_16BIT },/* 15xx only */ + [CSAC ] = {0x0018 ,0x40 ,OMAP_DMA_REG_16BIT }, + [CDAC ] = {0x001a ,0x40 ,OMAP_DMA_REG_16BIT }, + [CDEI ] = {0x001c ,0x40 ,OMAP_DMA_REG_16BIT }, + [CDFI ] = {0x001e ,0x40 ,OMAP_DMA_REG_16BIT }, + [CLNK_CTRL ] = {0x0028 ,0x40 ,OMAP_DMA_REG_16BIT },/* Channel specific register offsets */ - [CSSA ] =0x08 , - [CDSA ] =0x0c , - [COLOR ] =0x20 , - [CCR2 ] =0x24 , - [LCH_CTRL ] =0x2a , + [CSSA ] = {0x0008 ,0x40 ,OMAP_DMA_REG_2X16BIT }, + [CDSA ] = {0x000c ,0x40 ,OMAP_DMA_REG_2X16BIT }, + [COLOR ] = {0x0020 ,0x40 ,OMAP_DMA_REG_2X16BIT }, + [CCR2 ] = {0x0024 ,0x40 ,OMAP_DMA_REG_16BIT }, + [LCH_CTRL ] = {0x002a ,0x40 ,OMAP_DMA_REG_16BIT }, };static struct resource res[]__initdata = {
@@ -179,36 +178,28 @@ static struct resource res[] __initdata = {static void __iomem *dma_base;static inline void dma_write (u32 val,int reg,int lch) { -u8 stride; -u32 offset; +void __iomem *addr = dma_base; - stride = (reg >=CPC ) ?OMAP1_DMA_STRIDE :0 ; - offset = reg_map[reg] + (stride * lch); + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; -__raw_writew (val, dma_base + offset); -if ((reg >CLNK_CTRL && reg <CCEN ) || - (reg >PCHD_ID && reg <CAPS_2 )) { -u32 offset2 = reg_map[reg] +2 + (stride * lch); -__raw_writew (val >>16 , dma_base + offset2); - } +__raw_writew (val, addr); +if (reg_map[reg].type ==OMAP_DMA_REG_2X16BIT ) +__raw_writew (val >>16 , addr +2 ); }static inline u32 dma_read (int reg,int lch) { -u8 stride; -u32 offset, val; - - stride = (reg >=CPC ) ?OMAP1_DMA_STRIDE :0 ; - offset = reg_map[reg] + (stride * lch); - - val =__raw_readw (dma_base + offset); -if ((reg >CLNK_CTRL && reg <CCEN ) || - (reg >PCHD_ID && reg <CAPS_2 )) { -u16 upper; -u32 offset2 = reg_map[reg] +2 + (stride * lch); - upper =__raw_readw (dma_base + offset2); - val |= (upper <<16 ); - } +void __iomem *addr = dma_base; +uint32_t val; + + addr += reg_map[reg].offset; + addr += reg_map[reg].stride * lch; + + val =__raw_readw (addr); +if (reg_map[reg].type ==OMAP_DMA_REG_2X16BIT ) + val |=__raw_readw (addr +2 ) <<16 ; +return val; }
arch/arm/mach-omap2/dma.c +48 -51
128 lines not on this page · raw message
include/linux/omap-dma.h +13 -0
@@ -271,6 +271,19 @@ struct omap_dma_dev_attr {struct omap_dma_lch *chan; }; +enum { +OMAP_DMA_REG_NONE , +OMAP_DMA_REG_16BIT , +OMAP_DMA_REG_2X16BIT , +OMAP_DMA_REG_32BIT , +}; + +struct omap_dma_reg { +u16 offset; +u8 stride; +u8 type; +}; +/* System DMA platform data structure */ struct omap_system_dma_plat_info {struct omap_dma_dev_attr *dma_attr;
Signature · 1 line
1.8.3.1
PATCH 21/26 ARM: omap: dma: get rid of errata global
In reply to Russell King - ARM LinuxThere's no need for this to be a global variable; move it into the errata configuration function instead.
--- arch/arm/mach-omap1/dma.c | 4 ++-- arch/arm/mach-omap2/dma.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-)
arch/arm/mach-omap1/dma.c +2 -2
@@ -33,7 +33,6 @@#define OMAP1_DMA_BASE (0xfffed800)#define OMAP1_LOGICAL_DMA_CH_COUNT 17 -static u32 errata;static u32 enable_1510_mode;static const struct omap_dma_reg reg_map[] = {
@@ -244,8 +243,9 @@ static void omap1_show_dma_caps(void)return ; } -static u32 configure_dma_errata (void ) +static unsigned configure_dma_errata (void ) { +unsigned errata =0 ;/* * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
arch/arm/mach-omap2/dma.c +2 -3
@@ -35,8 +35,6 @@#include "omap_hwmod.h" #include "omap_device.h" -static u32 errata; -static struct omap_dma_dev_attr *d;static enum omap_reg_offsets dma_common_ch_end;
@@ -124,8 +122,9 @@ static void omap2_show_dma_caps(void)return ; } -static u32 configure_dma_errata (void ) +static unsigned configure_dma_errata (void ) { +unsigned errata =0 ;/* * Errata applicable for OMAP2430ES1.0 and all omap2420
Signature · 1 line
1.8.3.1
PATCH 22/26 ARM: omap: move dma channel allocation into plat-omap code
In reply to Russell King - ARM LinuxThis really needs to be there, because otherwise the plat-omap code can kfree() this data structure, and then re-use the pointer later.
--- arch/arm/mach-omap1/dma.c | 17 ++--------------- arch/arm/mach-omap2/dma.c | 7 ------- arch/arm/plat-omap/dma.c | 11 ++++++++--- include/linux/omap-dma.h | 1 - 4 files changed, 10 insertions(+), 26 deletions(-)
arch/arm/mach-omap1/dma.c +2 -15
@@ -325,17 +325,6 @@ static int __init omap1_system_dma_init(void) d->dev_caps |=CLEAR_CSR_ON_READ ; d->dev_caps |=IS_WORD_16 ; - - d->chan =kzalloc (sizeof (struct omap_dma_lch ) * - (d->lch_count),GFP_KERNEL ); -if (!d->chan) { -dev_err (&pdev->dev, -"%s: Memory allocation failed for d->chan!\n" , - __func__); - ret = -ENOMEM ; - goto exit_release_d; - } -if (cpu_is_omap15xx ()) d->chan_count =9 ;else if (cpu_is_omap16xx () ||cpu_is_omap7xx ()) {
@@ -359,14 +348,14 @@ static int __init omap1_system_dma_init(void)if (ret) {dev_err (&pdev->dev,"%s: Unable to add resources for %s%d\n" , __func__, pdev->name, pdev->id); - goto exit_release_chan; + goto exit_release_d; } ret =platform_device_add (pdev);if (ret) {dev_err (&pdev->dev,"%s: Unable to add resources for %s%d\n" , __func__, pdev->name, pdev->id); - goto exit_release_chan; + goto exit_release_d; } dma_pdev =platform_device_register_full (&omap_dma_dev_info);
@@ -379,8 +368,6 @@ static int __init omap1_system_dma_init(void) exit_release_pdev:platform_device_del (pdev); -exit_release_chan: -kfree (d->chan); exit_release_d:kfree (d); exit_release_p:
arch/arm/mach-omap2/dma.c +0 -7
@@ -251,13 +251,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) } d = oh->dev_attr; - d->chan =kzalloc (sizeof (struct omap_dma_lch ) * - (d->lch_count),GFP_KERNEL ); - -if (!d->chan) { -dev_err (&pdev->dev,"%s: kzalloc fail\n" , __func__); -return -ENOMEM ; - }if (cpu_is_omap34xx () && (omap_type () !=OMAP2_DEVICE_TYPE_GP )) d->dev_caps |=HS_CHANNELS_RESERVED ;
arch/arm/plat-omap/dma.c +8 -3
@@ -2030,9 +2030,16 @@ static int omap_system_dma_probe(struct platform_device *pdev) dma_lch_count = d->lch_count; dma_chan_count = dma_lch_count; - dma_chan = d->chan; enable_1510_mode = d->dev_caps &ENABLE_1510_MODE ; + dma_chan =devm_kcalloc (&pdev->dev, dma_lch_count, +sizeof (struct omap_dma_lch ),GFP_KERNEL ); +if (!dma_chan) { +dev_err (&pdev->dev,"%s: kzalloc fail\n" , __func__); +return -ENOMEM ; + } + +if (dma_omap2plus ()) { dma_linked_lch =kzalloc (sizeof (struct dma_link_info ) * dma_lch_count,GFP_KERNEL );
@@ -2117,7 +2124,6 @@ static int omap_system_dma_probe(struct platform_device *pdev) } exit_dma_lch_fail: -kfree (dma_chan);return ret; }
@@ -2137,7 +2143,6 @@ static int omap_system_dma_remove(struct platform_device *pdev)free_irq (dma_irq, (void *)(irq_rel +1 )); } } -kfree (dma_chan);return 0 ; }
include/linux/omap-dma.h +0 -1
@@ -268,7 +268,6 @@ struct omap_dma_dev_attr {u32 dev_caps;u16 lch_count;u16 chan_count; -struct omap_dma_lch *chan; };enum {
Signature · 1 line
1.8.3.1
PATCH 23/26 ARM: omap: dma: get rid of 'p' allocation and clean up
In reply to Russell King - ARM LinuxThe omap_system_dma_plat_info structure is only seven words, it's not worth the expense of kmalloc()'ing backing store for this only to release it later. Note that platform_device_add_data() copies the data anyway. Clean up the initialisation of this structure - we don't even need code to initialise most of this structure.
--- arch/arm/mach-omap1/dma.c | 36 ++++++++++++++---------------------- arch/arm/mach-omap2/dma.c | 34 +++++++++++++--------------------- 2 files changed, 27 insertions(+), 43 deletions(-)
arch/arm/mach-omap1/dma.c +14 -22
@@ -263,9 +263,17 @@ static const struct platform_device_info omap_dma_dev_info = { .dma_mask = DMA_BIT_MASK(32), }; +static struct omap_system_dma_plat_info dma_plat_info__initdata = { + .show_dma_caps = omap1_show_dma_caps, + .clear_lch_regs = omap1_clear_lch_regs, + .clear_dma = omap1_clear_dma, + .dma_write = dma_write, + .dma_read = dma_read, +}; +static int __init omap1_system_dma_init (void ) { -struct omap_system_dma_plat_info *p; +struct omap_system_dma_plat_info p;struct omap_dma_dev_attr *d;struct platform_device *pdev, *dma_pdev;int ret;
@@ -291,20 +299,12 @@ static int __init omap1_system_dma_init(void) goto exit_iounmap; } - p =kzalloc (sizeof (struct omap_system_dma_plat_info ),GFP_KERNEL ); -if (!p) { -dev_err (&pdev->dev,"%s: Unable to allocate 'p' for %s\n" , - __func__, pdev->name); - ret = -ENOMEM ; - goto exit_iounmap; - } - d =kzalloc (sizeof (struct omap_dma_dev_attr ),GFP_KERNEL );if (!d) {dev_err (&pdev->dev,"%s: Unable to allocate 'd' for %s\n" , __func__, pdev->name); ret = -ENOMEM ; - goto exit_release_p; + goto exit_iounmap; } d->lch_count =OMAP1_LOGICAL_DMA_CH_COUNT ;
@@ -334,17 +334,11 @@ static int __init omap1_system_dma_init(void) d->chan_count =9 ; } - p->dma_attr = d; - - p->show_dma_caps = omap1_show_dma_caps; - p->clear_lch_regs = omap1_clear_lch_regs; - p->clear_dma = omap1_clear_dma; - p->dma_write = dma_write; - p->dma_read = dma_read; - - p->errata =configure_dma_errata (); + p = dma_plat_info; + p.dma_attr = d; + p.errata =configure_dma_errata (); - ret =platform_device_add_data (pdev, p,sizeof (*p)); + ret =platform_device_add_data (pdev, &p,sizeof (p));if (ret) {dev_err (&pdev->dev,"%s: Unable to add resources for %s%d\n" , __func__, pdev->name, pdev->id);
@@ -370,8 +364,6 @@ static int __init omap1_system_dma_init(void)platform_device_del (pdev); exit_release_d:kfree (d); -exit_release_p: -kfree (p); exit_iounmap:iounmap (dma_base); exit_device_put:
arch/arm/mach-omap2/dma.c +13 -21
@@ -35,8 +35,6 @@#include "omap_hwmod.h" #include "omap_device.h" -static struct omap_dma_dev_attr *d; -static enum omap_reg_offsets dma_common_ch_end;static const struct omap_dma_reg reg_map[] = {
@@ -206,33 +204,27 @@ static unsigned configure_dma_errata(void)return errata; } +static struct omap_system_dma_plat_info dma_plat_info__initdata = { + .show_dma_caps = omap2_show_dma_caps, + .clear_dma = omap2_clear_dma, + .dma_write = dma_write, + .dma_read = dma_read, +}; +/* One time initializations */ static int __init omap2_system_dma_init_dev (struct omap_hwmod *oh,void *unused) {struct platform_device *pdev; -struct omap_system_dma_plat_info *p; +struct omap_system_dma_plat_info p; +struct omap_dma_dev_attr *d;struct resource *mem;char *name ="omap_dma_system" ; - p =kzalloc (sizeof (struct omap_system_dma_plat_info ),GFP_KERNEL ); -if (!p) { -pr_err ("%s: Unable to allocate pdata for %s:%s\n" , - __func__, name, oh->name); -return -ENOMEM ; - } - - p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; - p->show_dma_caps = omap2_show_dma_caps; - p->clear_dma = omap2_clear_dma; - p->dma_write = dma_write; - p->dma_read = dma_read; - - p->clear_lch_regs =NULL ; - - p->errata =configure_dma_errata (); + p = dma_plat_info; + p.dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; + p.errata =configure_dma_errata (); - pdev =omap_device_build (name,0 , oh, p,sizeof (*p)); -kfree (p); + pdev =omap_device_build (name,0 , oh, &p,sizeof (p));if (IS_ERR (pdev)) {pr_err ("%s: Can't build omap_device for %s:%s.\n" , __func__, name, oh->name);
Signature · 1 line
1.8.3.1
PATCH 24/26 dmaengine: omap-dma: move register read/writes into omap-dma.c
In reply to Russell King - ARM LinuxExport the DMA register information from the SoC specific data, such that we can access the registers directly in omap-dma.c, mapping the register region ourselves as well.
Rather than calculating the DMA channel register in its entirety for each access, we pre-calculate an offset base address for the allocated DMA channel and then just use the appropriate register offset.
--- arch/arm/mach-omap1/dma.c | 4 ++ arch/arm/mach-omap2/dma.c | 18 ++++++--- drivers/dma/omap-dma.c | 96 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 2 + 4 files changed, 105 insertions(+), 15 deletions(-)
arch/arm/mach-omap1/dma.c +4 -0
@@ -261,9 +261,13 @@ static const struct platform_device_info omap_dma_dev_info = { .name = "omap-dma-engine", .id = -1, .dma_mask = DMA_BIT_MASK(32), + .res = res, + .num_res = 1, };static struct omap_system_dma_plat_info dma_plat_info__initdata = { + .reg_map = reg_map, + .channel_stride =0x40 , .show_dma_caps = omap1_show_dma_caps, .clear_lch_regs = omap1_clear_lch_regs, .clear_dma = omap1_clear_dma,
arch/arm/mach-omap2/dma.c +12 -6
@@ -205,12 +205,20 @@ static unsigned configure_dma_errata(void) }static struct omap_system_dma_plat_info dma_plat_info__initdata = { + .reg_map = reg_map, + .channel_stride =0x60 , .show_dma_caps = omap2_show_dma_caps, .clear_dma = omap2_clear_dma, .dma_write = dma_write, .dma_read = dma_read, }; +static struct platform_device_info omap_dma_dev_info = { + .name ="omap-dma-engine" , + .id =-1 , + .dma_mask =DMA_BIT_MASK (32 ), +}; +/* One time initializations */ static int __init omap2_system_dma_init_dev (struct omap_hwmod *oh,void *unused) {
@@ -231,11 +239,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)return PTR_ERR (pdev); } + omap_dma_dev_info.res = pdev->resource; + omap_dma_dev_info.num_res = pdev->num_resources; + mem =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (!mem) {dev_err (&pdev->dev,"%s: no mem resource\n" , __func__);return -EINVAL ; } + dma_base =ioremap (mem->start,resource_size (mem));if (!dma_base) {dev_err (&pdev->dev,"%s: ioremap fail\n" , __func__);
@@ -256,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)return 0 ; } -static const struct platform_device_info omap_dma_dev_info = { - .name ="omap-dma-engine" , - .id =-1 , - .dma_mask =DMA_BIT_MASK (32 ), -}; -static int __init omap2_system_dma_init (void ) {struct platform_device *pdev;
drivers/dma/omap-dma.c +87 -9
171 lines not on this page · raw message
include/linux/omap-dma.h +2 -0
@@ -285,6 +285,8 @@ struct omap_dma_reg {/* System DMA platform data structure */ struct omap_system_dma_plat_info { +const struct omap_dma_reg *reg_map; +unsigned channel_stride;struct omap_dma_dev_attr *dma_attr;u32 errata;void (*show_dma_caps)(void );
Signature · 1 line
1.8.3.1
PATCH 25/26 dmaengine: omap-dma: move IRQ handling to omap-dma
In reply to Russell King - ARM Linux--- drivers/dma/omap-dma.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 6 deletions(-)
drivers/dma/omap-dma.c +115 -6
@@ -30,6 +30,10 @@ struct omap_dmadev {void __iomem *base;const struct omap_dma_reg *reg_map;struct omap_system_dma_plat_info *plat; +bool legacy; +spinlock_t irq_lock; +uint32_t irq_enable_mask; +struct omap_chan *lch_map[32 ]; };struct omap_chan {
@@ -254,10 +258,22 @@ static void omap_dma_clear_csr(struct omap_chan *c)omap_dma_chan_write (c,CSR , ~0 ); } +static unsigned omap_dma_get_csr (struct omap_chan *c) +{ +unsigned val =omap_dma_chan_read (c,CSR ); + +if (!dma_omap1 ()) +omap_dma_chan_write (c,CSR , val); + +return val; +} +static void omap_dma_assign (struct omap_dmadev *od,struct omap_chan *c,unsigned lch) { c->channel_base = od->base + od->plat->channel_stride * lch; + + od->lch_map[lch] = c; }static void omap_dma_start (struct omap_chan *c,struct omap_desc *d)
@@ -460,32 +476,103 @@ static void omap_dma_sched(unsigned long data) } } +static irqreturn_t omap_dma_irq (int irq,void *devid) +{ +struct omap_dmadev *od = devid; +unsigned status, channel; + +spin_lock (&od->irq_lock); + + status =omap_dma_glbl_read (od,IRQSTATUS_L1 ); + status &= od->irq_enable_mask; +if (status ==0 ) { +spin_unlock (&od->irq_lock); +return IRQ_NONE ; + } + +while ((channel =ffs (status)) !=0 ) { +unsigned mask, csr; +struct omap_chan *c; + + channel -=1 ; + mask =BIT (channel); + status &= ~mask; + + c = od->lch_map[channel]; +if (c ==NULL ) { +/* This should never happen */ +dev_err (od->ddev.dev,"invalid channel %u\n" , channel); +continue ; + } + + csr =omap_dma_get_csr (c); +omap_dma_glbl_write (od,IRQSTATUS_L1 , mask); + +omap_dma_callback (channel, csr, c); + } + +spin_unlock (&od->irq_lock); + +return IRQ_HANDLED ; +} +static int omap_dma_alloc_chan_resources (struct dma_chan *chan) {struct omap_dmadev *od =to_omap_dma_dev (chan->device);struct omap_chan *c =to_omap_dma_chan (chan);int ret; -dev_dbg (od->ddev.dev,"allocating channel for %u\n" , c->dma_sig); +if (od->legacy) { + ret =omap_request_dma (c->dma_sig,"DMA engine" , + omap_dma_callback, c, &c->dma_ch); + }else { + ret =omap_request_dma (c->dma_sig,"DMA engine" ,NULL ,NULL , + &c->dma_ch); + } - ret =omap_request_dma (c->dma_sig,"DMA engine" , omap_dma_callback, - c, &c->dma_ch); +dev_dbg (od->ddev.dev,"allocating channel %u for %u\n" , + c->dma_ch, c->dma_sig); -if (ret >=0 ) +if (ret >=0 ) {omap_dma_assign (od, c, c->dma_ch); +if (!od->legacy) { +unsigned val; + +spin_lock_irq (&od->irq_lock); + val =BIT (c->dma_ch); +omap_dma_glbl_write (od,IRQSTATUS_L1 , val); + od->irq_enable_mask |= val; +omap_dma_glbl_write (od,IRQENABLE_L1 , od->irq_enable_mask); + + val =omap_dma_glbl_read (od,IRQENABLE_L0 ); + val &= ~BIT (c->dma_ch); +omap_dma_glbl_write (od,IRQENABLE_L0 , val); +spin_unlock_irq (&od->irq_lock); + } + } +return ret; }static void omap_dma_free_chan_resources (struct dma_chan *chan) { +struct omap_dmadev *od =to_omap_dma_dev (chan->device);struct omap_chan *c =to_omap_dma_chan (chan); +if (!od->legacy) { +spin_lock_irq (&od->irq_lock); + od->irq_enable_mask &= ~BIT (c->dma_ch); +omap_dma_glbl_write (od,IRQENABLE_L1 , od->irq_enable_mask); +spin_unlock_irq (&od->irq_lock); + } + c->channel_base =NULL ; + od->lch_map[c->dma_ch] =NULL ;vchan_free_chan_resources (&c->vc);omap_free_dma (c->dma_ch); -dev_dbg (c->vc.chan.device->dev,"freeing channel for %u\n" , c->dma_sig); +dev_dbg (od->ddev.dev,"freeing channel for %u\n" , c->dma_sig); }static size_t omap_dma_sg_size (struct omap_sg *sg)
@@ -1015,7 +1102,7 @@ static int omap_dma_probe(struct platform_device *pdev) {struct omap_dmadev *od;struct resource *res; -int rc, i; +int rc, i, irq; od =devm_kzalloc (&pdev->dev,sizeof (*od),GFP_KERNEL );if (!od)
@@ -1045,6 +1132,7 @@ static int omap_dma_probe(struct platform_device *pdev)INIT_LIST_HEAD (&od->ddev.channels);INIT_LIST_HEAD (&od->pending);spin_lock_init (&od->lock); +spin_lock_init (&od->irq_lock);tasklet_init (&od->task, omap_dma_sched, (unsigned long )od);
@@ -1056,6 +1144,21 @@ static int omap_dma_probe(struct platform_device *pdev) } } + irq =platform_get_irq (pdev,1 ); +if (irq <=0 ) { +dev_info (&pdev->dev,"failed to get L1 IRQ: %d\n" , irq); + od->legacy = true; + }else { +/* Disable all interrupts */ + od->irq_enable_mask =0 ; +omap_dma_glbl_write (od,IRQENABLE_L1 ,0 ); + + rc =devm_request_irq (&pdev->dev, irq, omap_dma_irq, +IRQF_SHARED ,"omap-dma-engine" , od); +if (rc) +return rc; + } + rc =dma_async_device_register (&od->ddev);if (rc) { pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n",
@@ -1092,6 +1195,12 @@ static int omap_dma_remove(struct platform_device *pdev)of_dma_controller_free (pdev->dev.of_node);dma_async_device_unregister (&od->ddev); + +if (!od->legacy) { +/* Disable all interrupts */ +omap_dma_glbl_write (od,IRQENABLE_L0 ,0 ); + } +omap_dma_free (od);return 0 ;
Signature · 1 line
1.8.3.1
PATCH 26/26 dmaengine: omap-dma: more consolidation of CCR register setup
In reply to Russell King - ARM LinuxWe can move the handling of the DMA synchronisation control out of the prepare functions; this can be pre-calculated when the DMA channel has been allocated, so we don't need to duplicate this in both prepare functions.
--- drivers/dma/omap-dma.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-)
drivers/dma/omap-dma.c +18 -28
@@ -41,6 +41,7 @@ struct omap_chan {struct list_head node;void __iomem *channel_base;const struct omap_dma_reg *reg_map; +uint32_t ccr;struct dma_slave_config cfg;unsigned dma_sig;
@@ -552,6 +553,21 @@ static int omap_dma_alloc_chan_resources(struct dma_chan *chan) } } +if (dma_omap1 ()) { +if (__dma_omap16xx (od->plat->dma_attr)) { + c->ccr =CCR_OMAP31_DISABLE ; +/* Duplicate what plat-omap/dma.c does */ + c->ccr |= c->dma_ch +1 ; + }else { + c->ccr = c->dma_sig &0x1f ; + } + }else { + c->ccr = c->dma_sig &0x1f ; + c->ccr |= (c->dma_sig & ~0x1f ) <<14 ; + } +if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) + c->ccr |=CCR_BUFFERING_DISABLE ; +return ret; }
@@ -787,7 +803,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->dev_addr = dev_addr; d->es = es; - d->ccr =CCR_SYNC_FRAME ; + d->ccr = c->ccr |CCR_SYNC_FRAME ;if (dir ==DMA_DEV_TO_MEM ) d->ccr |=CCR_DST_AMODE_POSTINC |CCR_SRC_AMODE_CONSTANT ;else
@@ -797,14 +813,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( d->csdp = es;if (dma_omap1 ()) { -if (__dma_omap16xx (od->plat->dma_attr)) { - d->ccr |=CCR_OMAP31_DISABLE ; -/* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch +1 ; - }else { - d->ccr |= c->dma_sig &0x1f ; - } - d->cicr |=CICR_TOUT_IE ;if (dir ==DMA_DEV_TO_MEM )
@@ -812,16 +820,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(else d->csdp |=CSDP_DST_PORT_TIPB |CSDP_SRC_PORT_EMIFF ; }else { - d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; - d->ccr |= c->dma_sig &0x1f ; -if (dir ==DMA_DEV_TO_MEM ) d->ccr |=CCR_TRIGGER_SRC ; d->cicr |=CICR_MISALIGNED_ERR_IE |CICR_TRANS_ERR_IE ; } -if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) - d->ccr |=CCR_BUFFERING_DISABLE ;if (od->plat->errata &DMA_ERRATA_PARALLEL_CHANNELS ) d->clnk_ctrl = c->dma_ch;
@@ -903,7 +906,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->sg[0 ].fn = buf_len / period_len; d->sglen =1 ; - d->ccr =0 ; + d->ccr = c->ccr;if (dir ==DMA_DEV_TO_MEM ) d->ccr |=CCR_DST_AMODE_POSTINC |CCR_SRC_AMODE_CONSTANT ;else
@@ -916,14 +919,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp = es;if (dma_omap1 ()) { -if (__dma_omap16xx (od->plat->dma_attr)) { - d->ccr |=CCR_OMAP31_DISABLE ; -/* Duplicate what plat-omap/dma.c does */ - d->ccr |= c->dma_ch +1 ; - }else { - d->ccr |= c->dma_sig &0x1f ; - } - d->cicr |=CICR_TOUT_IE ;if (dir ==DMA_DEV_TO_MEM )
@@ -931,9 +926,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(else d->csdp |=CSDP_DST_PORT_MPUI |CSDP_SRC_PORT_EMIFF ; }else { - d->ccr |= (c->dma_sig & ~0x1f ) <<14 ; - d->ccr |= c->dma_sig &0x1f ; -if (burst) d->ccr |=CCR_SYNC_PACKET ;else
@@ -946,8 +938,6 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( d->csdp |=CSDP_DST_BURST_64 |CSDP_SRC_BURST_64 ; } -if (od->plat->errata &DMA_ERRATA_IFRAME_BUFFERING ) - d->ccr |=CCR_BUFFERING_DISABLE ;if (__dma_omap15xx (od->plat->dma_attr)) d->ccr |=CCR_AUTO_INIT |CCR_REPEAT ;
Signature · 1 line
1.8.3.1
Tony Lindgren
maintainercover OMAP dma engine rework
In reply to Russell King - ARM LinuxQuoted 10 lines · Russell King - ARM Linux
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
Looks good to me and should not conflict with other patches that I'm aware of. Please feel free to add:
cover OMAP dma engine rework
In reply to Russell King - ARM LinuxQuoted 11 lines · Russell King - ARM Linux
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
Quoted 7 lines
arch/arm/mach-omap1/dma.c | 191 ++++++-------- arch/arm/mach-omap2/dma.c | 183 ++++++------- arch/arm/plat-omap/dma.c | 17 +- drivers/dma/omap-dma.c | 659 +++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 25 +- 5 files changed, 784 insertions(+), 291 deletions(-)
Tested this on DRA7XX with MMC peripheral DMA
Regards,
Sricharan
cover OMAP dma engine rework
In reply to Russell King - ARM LinuxQuoted 10 lines · Russell King - ARM Linux
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
So is this series finalized. I havent seen the pull request for this or did i miss it!
Signature · 1 line
~Vinod
Quoted 12 lines
arch/arm/mach-omap1/dma.c | 191 ++++++-------- arch/arm/mach-omap2/dma.c | 183 ++++++------- arch/arm/plat-omap/dma.c | 17 +- drivers/dma/omap-dma.c | 659 +++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 25 +- 5 files changed, 784 insertions(+), 291 deletions(-)Signature · 3 lines
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad. Estimate before purchase was "up to 13.2Mbit".
cover OMAP dma engine rework
Quoted 5 lines · Vinod Koul
Quoted 4 lines · Russell King - ARM Linux
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
Quoted 8 lines
Quoted 6 lines
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
So is this series finalized. I havent seen the pull request for this or did i miss it!
Gah, missed this.
As nothing has changed with it since 18th February, which was to add Tony's ack to the set. I think it's as good as it's going to get for the time being. It's also been in linux-next all this time, and no one has reported any problems. I'll need to sort out a proper pull request for it ASAP... or something. An alternate solution would be your blessing for this set.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover OMAP dma engine rework
Quoted 15 lines · Russell King - ARM Linux
Quoted 5 lines · Vinod Koul
Quoted 4 lines · Russell King - ARM Linux
This is the current set of patches for the OMAP DMA engine rework, which should now work correctly on OMAP1 platforms thanks to Tony's testing.
Quoted 8 lines
Quoted 6 lines
It would be good to get this validated by others across a range of OMAP platforms, and queued up for the next merge window, so it can be built upon.
Acks appreciated, and once sufficient have been added, I'll send a pull request for this to Vinod.
So is this series finalized. I havent seen the pull request for this or did i miss it!
Quoted 8 lines
Gah, missed this.
As nothing has changed with it since 18th February, which was to add Tony's ack to the set. I think it's as good as it's going to get for the time being. It's also been in linux-next all this time, and no one has reported any problems. I'll need to sort out a proper pull request for it ASAP... or something. An alternate solution would be your blessing for this set.
Okay in that case pls send with my ACK.
Thanks
Signature · 1 line
~Vinod