Migrate more OMAP DMA code to DMA engine
Subsystems (3)
cover Migrate more OMAP DMA code to DMA engine
The following patch series moves code to setup the DMA hardware and service interrupts from the hardware to the DMA engine driver. This reduces the dependency on the legacy DMA implementation.
This series does not remove the channel allocation/freeing hooks which are used to manage the allocation of physical channels - this is the next step in the evolution.
The patches which move the interrupt handling are currently less than perfect since they're writing to ENABLE_L0 under a different spinlock, and hence RFC only at the moment.
arch/arm/mach-omap1/dma.c | 183 +++++-------- arch/arm/mach-omap2/dma.c | 183 ++++++-------- arch/arm/plat-omap/dma.c | 17 +- drivers/dma/omap-dma.c | 653 ++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 25 ++- 5 files changed, 774 insertions(+), 287 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".
RFC 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 files changed, 1 insertions(+), 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.7.4.4
RFC 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(+), 0 deletions(-)
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.7.4.4
RFC 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 | 144 ++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 6 +- 2 files changed, 132 insertions(+), 18 deletions(-)
drivers/dma/omap-dma.c +128 -16
@@ -99,16 +99,96 @@ 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); + } + +if (dma_omap2plus () && 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 ); -omap_set_dma_transfer_params (c->dma_ch, d->es, sg->en, sg->fn, - d->sync_mode, c->dma_sig, d->sync_type); +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); + } + + 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 +197,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 +209,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 +560,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.7.4.4
RFC 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 files 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);
@@ -158,91 +193,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.7.4.4
Quoted 12 lines · Russell King - ARM Linux
The following patch series moves code to setup the DMA hardware and service interrupts from the hardware to the DMA engine driver. This reduces the dependency on the legacy DMA implementation.
This series does not remove the channel allocation/freeing hooks which are used to manage the allocation of physical channels - this is the next step in the evolution.
The patches which move the interrupt handling are currently less than perfect since they're writing to
ENABLE_L0under a different spinlock, and hence RFC only at the moment.
Quoted 7 lines
arch/arm/mach-omap1/dma.c | 183 +++++-------- arch/arm/mach-omap2/dma.c | 183 ++++++-------- arch/arm/plat-omap/dma.c | 17 +- drivers/dma/omap-dma.c | 653 ++++++++++++++++++++++++++++++++++++++++----- include/linux/omap-dma.h | 25 ++- 5 files changed, 774 insertions(+), 287 deletions(-)
I tested this series on DRA7 with mmc peripheral dma and it looked fine. Some how dmaengine test cases were not fine. But that may not have anything to do with this series. I will check more on that and will come back with that results as well.
Regards,
Sricharan
cover Migrate more OMAP DMA code to DMA engine
Quoted 4 lines · Sricharan R
I tested this series on DRA7 with mmc peripheral dma and it looked fine. Some how dmaengine test cases were not fine. But that may not have anything to do with this series. I will check more on that and will come back with that results as well.
Not fine in what sense?
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 Migrate more OMAP DMA code to DMA engine
Quoted 8 lines · Russell King - ARM Linux
Quoted 4 lines · Sricharan R
I tested this series on DRA7 with mmc peripheral dma and it looked fine. Some how dmaengine test cases were not fine. But that may not have anything to do with this series. I will check more on that and will come back with that results as well.
Not fine in what sense?
Sorry for delayed response.
So in the case of dmaengine test case, it looks for channels with DMA_MEMCPY, DMA_XOR, DMA_PQ capabilities. But the omap-dma
device is not registered with MEMCPY capabilities, hence the
testcase fails as no channels are available.
Regards,
Sricharan